summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2019-04-16 08:40:55 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2019-04-16 08:40:55 +0000
commit422e5fb188f5164d0d4d871a195b65a51ed515ef (patch)
tree9e1d75c9af897a4e104b2b6f0748315b7fdbd98c
parentc95e2ae9c9f6642ca26b2bdba43c3c05b7113428 (diff)
parentcf39fbd08d063954f801aef23145dbf00290d9bb (diff)
downloadglib-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.c49
-rw-r--r--glib/gutils.c23
-rw-r--r--glib/tests/option-argv0.c8
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