diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2019-04-16 08:40:55 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2019-04-16 08:40:55 +0000 |
commit | 422e5fb188f5164d0d4d871a195b65a51ed515ef (patch) | |
tree | 9e1d75c9af897a4e104b2b6f0748315b7fdbd98c | |
parent | c95e2ae9c9f6642ca26b2bdba43c3c05b7113428 (diff) | |
parent | cf39fbd08d063954f801aef23145dbf00290d9bb (diff) | |
download | glib-422e5fb188f5164d0d4d871a195b65a51ed515ef.tar.gz |
Merge branch 'w32-argv0' into 'master'
W32: swap special g_get_prgname() for platform_get_argv0()
See merge request GNOME/glib!766
-rw-r--r-- | glib/goption.c | 49 | ||||
-rw-r--r-- | glib/gutils.c | 23 | ||||
-rw-r--r-- | glib/tests/option-argv0.c | 8 |
3 files changed, 55 insertions, 25 deletions
diff --git a/glib/goption.c b/glib/goption.c index 8494ca739..183e9d9d3 100644 --- a/glib/goption.c +++ b/glib/goption.c @@ -194,6 +194,10 @@ #include "gprintf.h" #include "glibintl.h" +#if defined G_OS_WIN32 +#include <windows.h> +#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 || \ @@ -1860,6 +1864,51 @@ platform_get_argv0 (void) base_arg0 = g_path_get_basename (*cmdline); g_free (cmdline); return base_arg0; +#elif defined G_OS_WIN32 + const wchar_t *cmdline; + wchar_t **wargv; + int wargc; + gchar *utf8_buf = NULL; + char *base_arg0 = NULL; + + /* Pretend it's const, since we're not allowed to free it */ + cmdline = (const wchar_t *) GetCommandLineW (); + if (G_UNLIKELY (cmdline == NULL)) + return NULL; + + /* Skip leading whitespace. CommandLineToArgvW() is documented + * to behave weirdly with that. The character codes below + * correspond to the *only* unicode characters that are + * considered to be spaces by CommandLineToArgvW(). The rest + * (such as 0xa0 - NO-BREAK SPACE) are treated as + * normal characters. + */ + while (cmdline[0] == 0x09 || + cmdline[0] == 0x0a || + cmdline[0] == 0x0c || + cmdline[0] == 0x0d || + cmdline[0] == 0x20) + cmdline++; + + wargv = CommandLineToArgvW (cmdline, &wargc); + if (G_UNLIKELY (wargv == NULL)) + return NULL; + + if (wargc > 0) + utf8_buf = g_utf16_to_utf8 (wargv[0], -1, NULL, NULL, NULL); + + LocalFree (wargv); + + if (G_UNLIKELY (utf8_buf == NULL)) + return NULL; + + /* We could just return cmdline, but I think it's better + * to hold on to a smaller malloc block; the arguments + * could be large. + */ + base_arg0 = g_path_get_basename (utf8_buf); + g_free (utf8_buf); + return base_arg0; #endif return NULL; diff --git a/glib/gutils.c b/glib/gutils.c index b4ca1cc3f..766248dec 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -1047,29 +1047,6 @@ g_get_prgname (void) gchar* retval; G_LOCK (g_prgname); -#ifdef G_OS_WIN32 - if (g_prgname == NULL) - { - static gboolean beenhere = FALSE; - - if (!beenhere) - { - gchar *utf8_buf = NULL; - wchar_t buf[MAX_PATH+1]; - - beenhere = TRUE; - if (GetModuleFileNameW (GetModuleHandle (NULL), - buf, G_N_ELEMENTS (buf)) > 0) - utf8_buf = g_utf16_to_utf8 (buf, -1, NULL, NULL, NULL); - - if (utf8_buf) - { - g_prgname = g_path_get_basename (utf8_buf); - g_free (utf8_buf); - } - } - } -#endif retval = g_prgname; G_UNLOCK (g_prgname); diff --git a/glib/tests/option-argv0.c b/glib/tests/option-argv0.c index f977625b5..5b626df70 100644 --- a/glib/tests/option-argv0.c +++ b/glib/tests/option-argv0.c @@ -51,7 +51,8 @@ test_platform_argv0 (void) /* This test must pass on platforms where platform_get_argv0() * is implemented. At the moment that means Linux/Cygwin, * (which uses /proc/self/cmdline) or OpenBSD (which uses - * sysctl and KERN_PROC_ARGS). On other platforms the test + * sysctl and KERN_PROC_ARGS) or Windows (which uses + * GetCommandlineW ()). On other platforms the test * is not expected to pass, but we'd still want to know * how it does (the test code itself doesn't use any platform-specific * functionality, the difference is internal to glib, so it's quite @@ -60,7 +61,10 @@ test_platform_argv0 (void) * to prevent them from crashing hard on failed assertions, * and make them call g_test_skip() instead. */ -#if !defined HAVE_PROC_SELF_CMDLINE && !defined __OpenBSD__ && !defined __linux +#if !defined HAVE_PROC_SELF_CMDLINE && \ + !defined __OpenBSD__ && \ + !defined __linux && \ + !defined G_OS_WIN32 fatal_errors = FALSE; #endif |