diff -rc glib2.0-2.18.2-orig/glib/goption.c glib2.0-2.18.2/glib/goption.c
*** glib2.0-2.18.2-orig/glib/goption.c	2008-10-16 16:31:58.000000000 +0200
--- glib2.0-2.18.2/glib/goption.c	2008-12-13 22:29:13.000000000 +0100
***************
*** 33,38 ****
--- 33,44 ----
  #include <stdio.h>
  #include <errno.h>
  
+ #ifdef G_OS_WIN32
+ #define STRICT
+ #include <windows.h>
+ #undef STRICT
+ #endif
+ 
  #define TRANSLATE(group, str) (((group)->translate_func ? (* (group)->translate_func) ((str), (group)->translate_data) : (str)))
  
  #define NO_ARG(entry) ((entry)->arg == G_OPTION_ARG_NONE ||       \
***************
*** 119,124 ****
--- 125,134 ----
    GOptionErrorFunc error_func;
  };
  
+ /* Set to true by g_option_prepare_argv; tells GOption to treat
+  * argv as UTF-8 strings on Windows */
+ static gboolean prepare_argv_called = FALSE;
+ 
  static void free_changes_list (GOptionContext *context,
  			       gboolean        revert);
  static void free_pending_nulls (GOptionContext *context,
***************
*** 183,188 ****
--- 193,250 ----
  }
  
  /**
+  * g_option_prepare_argv:
+  * @argc: a pointer to the number of command line arguments
+  * @argv: a pointer to the array of command line arguments
+  * @error: a return location for errors, or NULL
+  *
+  * Prepares the argument vector for parsing with GOption. On Windows,
+  * it replaces @argv with UTF-8 encoded Unicode command line retrieved
+  * from the operating system, and tells GOption to assume that its
+  * arguments are in UTF-8. On other systems, it does nothing.
+  *
+  * This function must be called before any processing is done on @argc
+  * and @argv.
+  *
+  * Return value: %TRUE if the argument vector was successfully converted,
+  *               %FALSE if an error occurred
+  *
+  * Since: 2.20
+  */
+ gboolean
+ g_option_prepare_argv (gint *argc, gchar ***argv, GError **error)
+ {
+   if (prepare_argv_called)
+     g_error("g_option_prepare_argv called more than once");
+ 
+ #ifdef G_OS_WIN32
+   LPWSTR windows_cmdline = GetCommandLineW();
+   gchar *cmdline = g_convert ((gchar*) windows_cmdline, wcslen (windows_cmdline) * 2,
+                               "UTF-8", "UTF-16", NULL, NULL, NULL);
+ 
+   /* This may theoretically happen when the command line is invalid UTF-16,
+    * e.g. when it has lone surrogate characters. */
+   if (!cmdline)
+     {
+       g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
+ 		   _("Failed to convert the command line to UTF-8"), option_name);
+       return FALSE;
+     }
+ 
+   /* This may happen when the command line is incorrectly quoted. */
+   if (!g_shell_parse_argv (cmdline, argc, argv, NULL))
+     {
+       g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_FAILED,
+ 		   _("Failed to parse the command line"), option_name);
+       return FALSE;
+     }
+ #endif
+ 
+   prepare_argv_called = TRUE;
+   return TRUE;
+ }
+ 
+ /**
   * g_option_context_new:
   * @parameter_string: a string which is displayed in
   *    the first line of <option>--help</option> output, after the
***************
*** 1002,1009 ****
      case G_OPTION_ARG_STRING:
        {
  	gchar *data;
! 	
! 	data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
  
  	if (!data)
  	  return FALSE;
--- 1064,1075 ----
      case G_OPTION_ARG_STRING:
        {
  	gchar *data;
! #ifdef G_OS_WIN32
! 	if (prepare_argv_called)
! 	  data = g_strdup (value);
! 	else
! #endif
! 	  data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
  
  	if (!data)
  	  return FALSE;
***************
*** 1021,1031 ****
      case G_OPTION_ARG_STRING_ARRAY:
        {
  	gchar *data;
  
! 	data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
! 
! 	if (!data)
! 	  return FALSE;
  
  	change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
  			     entry->arg_data);
--- 1087,1103 ----
      case G_OPTION_ARG_STRING_ARRAY:
        {
  	gchar *data;
+ #ifdef G_OS_WIN32
+ 	if (prepare_argv_called)
+ 	  data = g_strdup (value);
+ 	else
+ #endif
+ 	  {
+ 	    data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
  
! 	    if (!data)
! 	      return FALSE;
! 	  }
  
  	change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
  			     entry->arg_data);
***************
*** 1055,1067 ****
  	gchar *data;
  
  #ifdef G_OS_WIN32
! 	data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
  	
! 	if (!data)
! 	  return FALSE;
! #else
! 	data = g_strdup (value);
  #endif
  	change = get_change (context, G_OPTION_ARG_FILENAME,
  			     entry->arg_data);
  	g_free (change->allocated.str);
--- 1127,1143 ----
  	gchar *data;
  
  #ifdef G_OS_WIN32
! 	if (!prepare_argv_called)
! 	  {
! 	    data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
  	
! 	    if (!data)
! 	      return FALSE;
! 	  }
! 	else
  #endif
+ 	data = g_strdup (value);
+ 
  	change = get_change (context, G_OPTION_ARG_FILENAME,
  			     entry->arg_data);
  	g_free (change->allocated.str);
***************
*** 1078,1090 ****
  	gchar *data;
  	
  #ifdef G_OS_WIN32
! 	data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
  	
! 	if (!data)
! 	  return FALSE;
! #else
! 	data = g_strdup (value);
  #endif
  	change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
  			     entry->arg_data);
  
--- 1154,1170 ----
  	gchar *data;
  	
  #ifdef G_OS_WIN32
! 	if (!prepare_argv_called)
! 	  {
! 	    data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
  	
! 	    if (!data)
! 	      return FALSE;
! 	  }
! 	else
  #endif
+ 	data = g_strdup (value);
+ 
  	change = get_change (context, G_OPTION_ARG_STRING_ARRAY,
  			     entry->arg_data);
  
***************
*** 1135,1147 ****
  	else if (entry->flags & G_OPTION_FLAG_FILENAME)
  	  {
  #ifdef G_OS_WIN32
!   	    data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
! #else
! 	    data = g_strdup (value);
  #endif
  	  }
  	else
! 	  data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
  
  	if (!(entry->flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG)) && 
  	    !data)
--- 1215,1235 ----
  	else if (entry->flags & G_OPTION_FLAG_FILENAME)
  	  {
  #ifdef G_OS_WIN32
!             if (!prepare_argv_called)
!   	      data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
!   	    else
  #endif
+ 	    data = g_strdup (value);
  	  }
  	else
! 	  {
! #ifdef G_OS_WIN32
! 	    if (prepare_argv_called)
! 	      data = g_strdup (value);
! 	    else
! #endif
! 	    data = g_locale_to_utf8 (value, -1, NULL, NULL, error);
! 	  }
  
  	if (!(entry->flags & (G_OPTION_FLAG_NO_ARG|G_OPTION_FLAG_OPTIONAL_ARG)) && 
  	    !data)
***************
*** 1512,1518 ****
   * Parses the command line arguments, recognizing options
   * which have been added to @context. A side-effect of 
   * calling this function is that g_set_prgname() will be
!  * called.
   *
   * If the parsing is successful, any parsed arguments are
   * removed from the array and @argc and @argv are updated 
--- 1600,1607 ----
   * Parses the command line arguments, recognizing options
   * which have been added to @context. A side-effect of 
   * calling this function is that g_set_prgname() will be
!  * called. To ensure portability, the function
!  * g_option_prepare_argv() must be called before this one.
   *
   * If the parsing is successful, any parsed arguments are
   * removed from the array and @argc and @argv are updated 
***************
*** 1527,1536 ****
--- 1616,1631 ----
   * this function will produce help output to stdout and
   * call <literal>exit (0)</literal>.
   *
+  * On Windows, the arguments of main() can contain file names
+  * not representable in the locale encoding. Trying to open
+  * those files will fail. To fix this, call
+  * g_option_prepare_argv() before g_option_context_parse().
+  *
   * Note that function depends on the 
   * <link linkend="setlocale">current locale</link> for 
   * automatic character set conversion of string and filename
   * arguments.
+  *
   * 
   * Return value: %TRUE if the parsing was successful, 
   *               %FALSE if an error occurred
***************
*** 1546,1551 ****
--- 1641,1650 ----
    gint i, j, k;
    GList *list;
  
+   if (!prepare_argv_called)
+     g_warning ("g_option_prepare_argv must be called before "
+                "g_option_context_parse to ensure Windows portability");
+ 
    /* Set program name */
    if (!g_get_prgname())
      {
diff -rc glib2.0-2.18.2-orig/glib/goption.h glib2.0-2.18.2/glib/goption.h
*** glib2.0-2.18.2-orig/glib/goption.h	2008-10-16 16:31:58.000000000 +0200
--- glib2.0-2.18.2/glib/goption.h	2008-12-13 21:26:48.000000000 +0100
***************
*** 100,105 ****
--- 100,109 ----
  
  #define G_OPTION_REMAINING ""
  
+ gboolean        g_option_prepare_argv             (gint                *argc,
+                                                    gchar             ***argv,
+                                                    GError             **error);
+ 
  GOptionContext *g_option_context_new              (const gchar         *parameter_string);
  void            g_option_context_set_summary      (GOptionContext      *context,
                                                     const gchar         *summary);
