Merge branch 'windows-static-build-postfixes' into 'main'

Fix tests with static build on Windows

See merge request GNOME/glib!2442
This commit is contained in:
Philip Withnall 2022-01-27 14:33:40 +00:00
commit e01e6ef771
9 changed files with 213 additions and 119 deletions

View File

@ -23,27 +23,28 @@
#include <stdlib.h>
#include <string.h>
#include "giotypes.h"
#include "gioenumtypes.h"
#include "gsocket.h"
#include "gdbusauthobserver.h"
#include "gdbusprivate.h"
#include "gdbusmessage.h"
#include "gdbusconnection.h"
#include "gdbusproxy.h"
#include "gdbusdaemon.h"
#include "gdbuserror.h"
#include "gdbusintrospection.h"
#include "gdbusdaemon.h"
#include "giomodule-priv.h"
#include "gtask.h"
#include "gdbusmessage.h"
#include "gdbusprivate.h"
#include "gdbusproxy.h"
#include "ginputstream.h"
#include "gmemoryinputstream.h"
#include "gioenumtypes.h"
#include "giomodule-priv.h"
#include "giostream.h"
#include "giotypes.h"
#include "glib-private.h"
#include "glib/gstdio.h"
#include "gmemoryinputstream.h"
#include "gsocket.h"
#include "gsocketaddress.h"
#include "gsocketcontrolmessage.h"
#include "gsocketconnection.h"
#include "gsocketcontrolmessage.h"
#include "gsocketoutputstream.h"
#include "gtask.h"
#ifdef G_OS_UNIX
#include "gunixfdmessage.h"
@ -2275,6 +2276,26 @@ g_win32_run_session_bus (void* hwnd, void* hinst, const char* cmdline, int cmdsh
static gboolean autolaunch_binary_absent = FALSE;
static wchar_t *
find_dbus_process_path (void)
{
wchar_t *dbus_path;
gchar *exe_path = GLIB_PRIVATE_CALL (g_win32_find_helper_executable_path) ("gdbus.exe", _g_io_win32_get_module ());
dbus_path = g_utf8_to_utf16 (exe_path, -1, NULL, NULL, NULL);
g_free (exe_path);
if (dbus_path == NULL)
return NULL;
if (GetFileAttributesW (dbus_path) == INVALID_FILE_ATTRIBUTES)
{
g_free (dbus_path);
return NULL;
}
return dbus_path;
}
gchar *
_g_dbus_win32_get_session_address_dbus_launch (GError **error)
{
@ -2292,61 +2313,53 @@ _g_dbus_win32_get_session_address_dbus_launch (GError **error)
if (address == NULL && !autolaunch_binary_absent)
{
wchar_t gio_path[MAX_PATH + 2] = { 0 };
int gio_path_len = GetModuleFileNameW (_g_io_win32_get_module (), gio_path, MAX_PATH + 1);
wchar_t *dbus_path = find_dbus_process_path ();
if (dbus_path == NULL)
{
/* warning won't be raised another time
* since autolaunch_binary_absent would be already set.
*/
autolaunch_binary_absent = TRUE;
g_warning ("win32 session dbus binary not found");
}
else
{
PROCESS_INFORMATION pi = { 0 };
STARTUPINFOW si = { 0 };
BOOL res = FALSE;
wchar_t args[MAX_PATH * 2 + 100] = { 0 };
wchar_t working_dir[MAX_PATH + 2] = { 0 };
wchar_t *p;
/* The <= MAX_PATH check prevents truncated path usage */
if (gio_path_len > 0 && gio_path_len <= MAX_PATH)
{
PROCESS_INFORMATION pi = { 0 };
STARTUPINFOW si = { 0 };
BOOL res = FALSE;
wchar_t exe_path[MAX_PATH + 100] = { 0 };
/* calculate index of first char of dll file name inside full path */
int gio_name_index = gio_path_len;
for (; gio_name_index > 0; --gio_name_index)
{
wchar_t prev_char = gio_path[gio_name_index - 1];
if (prev_char == L'\\' || prev_char == L'/')
break;
}
gio_path[gio_name_index] = L'\0';
wcscpy (exe_path, gio_path);
wcscat (exe_path, L"\\gdbus.exe");
wcscpy (working_dir, dbus_path);
p = wcsrchr (working_dir, L'\\');
if (p != NULL)
*p = L'\0';
if (GetFileAttributesW (exe_path) == INVALID_FILE_ATTRIBUTES)
{
/* warning won't be raised another time
* since autolaunch_binary_absent would be already set.
*/
autolaunch_binary_absent = TRUE;
g_warning ("win32 session dbus binary not found: %S", exe_path );
}
else
{
wchar_t args[MAX_PATH*2 + 100] = { 0 };
wcscpy (args, L"\"");
wcscat (args, exe_path);
wcscat (args, L"\" ");
wcscpy (args, L"\"");
wcscat (args, dbus_path);
wcscat (args, L"\" ");
#define _L_PREFIX_FOR_EXPANDED(arg) L##arg
#define _L_PREFIX(arg) _L_PREFIX_FOR_EXPANDED (arg)
wcscat (args, _L_PREFIX (_GDBUS_ARG_WIN32_RUN_SESSION_BUS));
wcscat (args, _L_PREFIX (_GDBUS_ARG_WIN32_RUN_SESSION_BUS));
#undef _L_PREFIX
#undef _L_PREFIX_FOR_EXPANDED
res = CreateProcessW (exe_path, args,
0, 0, FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | DETACHED_PROCESS,
0, gio_path,
&si, &pi);
}
if (res)
{
address = read_shm (DBUS_DAEMON_ADDRESS_INFO);
if (address == NULL)
g_warning ("%S dbus binary failed to launch bus, maybe incompatible version", exe_path );
}
}
res = CreateProcessW (dbus_path, args,
0, 0, FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | DETACHED_PROCESS,
0, working_dir,
&si, &pi);
if (res)
{
address = read_shm (DBUS_DAEMON_ADDRESS_INFO);
if (address == NULL)
g_warning ("%S dbus binary failed to launch bus, maybe incompatible version", dbus_path);
}
g_free (dbus_path);
}
}
release_mutex (autolaunch_mutex);

View File

@ -40,7 +40,9 @@ void g_clock_win32_init (void);
void g_crash_handler_win32_init (void);
void g_crash_handler_win32_deinit (void);
gboolean _g_win32_call_rtl_version (OSVERSIONINFOEXW *info);
extern HMODULE glib_dll;
gchar *g_win32_find_helper_executable_path (const gchar *process_name, void *dll_handle);
#endif
#endif /* __GLIB_INIT_H__ */

View File

@ -54,6 +54,7 @@ glib__private__ (void)
g_win32_lstat_utf8,
g_win32_readlink_utf8,
g_win32_fstat,
g_win32_find_helper_executable_path,
#endif
};

View File

@ -120,7 +120,6 @@ gboolean g_check_setuid (void);
GMainContext * g_main_context_new_with_next_id (guint next_id);
#ifdef G_OS_WIN32
gchar *_glib_get_dll_directory (void);
GLIB_AVAILABLE_IN_ALL
gchar *_glib_get_locale_dir (void);
#endif
@ -168,6 +167,10 @@ typedef struct {
int (* g_win32_fstat) (int fd,
GWin32PrivateStat *buf);
/* See gwin32.c */
gchar *(*g_win32_find_helper_executable_path) (const gchar *process_name,
void *dll_handle);
#endif

View File

@ -42,10 +42,11 @@
#include "config.h"
#include "glib.h"
#include "glib-init.h"
#include "glib-private.h"
#include "gprintfint.h"
#include "glib.h"
#include "glibintl.h"
#include "gprintfint.h"
#include "gspawn-private.h"
#include "gthread.h"
@ -586,7 +587,6 @@ fork_exec (gint *exit_status,
gint conv_error_index;
gchar *helper_process;
wchar_t *whelper, **wargv, **wenvp;
gchar *glib_dll_directory;
int stdin_pipe[2] = { -1, -1 };
int stdout_pipe[2] = { -1, -1 };
int stderr_pipe[2] = { -1, -1 };
@ -651,16 +651,8 @@ fork_exec (gint *exit_status,
helper_process = HELPER_PROCESS "-console.exe";
else
helper_process = HELPER_PROCESS ".exe";
glib_dll_directory = _glib_get_dll_directory ();
if (glib_dll_directory != NULL)
{
helper_process = g_build_filename (glib_dll_directory, helper_process, NULL);
g_free (glib_dll_directory);
}
else
helper_process = g_strdup (helper_process);
helper_process = g_win32_find_helper_executable_path (helper_process, glib_dll);
new_argv[0] = protect_argv_string (helper_process);
_g_sprintf (args[ARG_CHILD_ERR_REPORT], "%d", child_err_report_pipe[1]);

View File

@ -104,47 +104,6 @@
#include <langinfo.h>
#endif
#ifdef G_PLATFORM_WIN32
gchar *
_glib_get_dll_directory (void)
{
gchar *retval;
gchar *p;
wchar_t wc_fn[MAX_PATH];
#ifdef DLL_EXPORT
if (glib_dll == NULL)
return NULL;
#endif
/* This code is different from that in
* g_win32_get_package_installation_directory_of_module() in that
* here we return the actual folder where the GLib DLL is. We don't
* do the check for it being in a "bin" or "lib" subfolder and then
* returning the parent of that.
*
* In a statically built GLib, glib_dll will be NULL and we will
* thus look up the application's .exe file's location.
*/
if (!GetModuleFileNameW (glib_dll, wc_fn, MAX_PATH))
return NULL;
retval = g_utf16_to_utf8 (wc_fn, -1, NULL, NULL, NULL);
p = strrchr (retval, G_DIR_SEPARATOR);
if (p == NULL)
{
/* Wtf? */
return NULL;
}
*p = '\0';
return retval;
}
#endif
/**
* g_memmove:
* @dest: the destination address to copy the bytes to.

View File

@ -1336,4 +1336,123 @@ g_crash_handler_win32_deinit (void)
WinVEH_handle = NULL;
}
/**
* g_win32_find_helper_executable_path:
* @executable_name: (transfer none): name of the helper executable to find
* (something like gspawn-win64-helper.exe or gdbus.exe for example).
* @dll_handle: handle of the DLL to use as searching base path. Pass NULL
* to take current process executable as searching base path.
*
* Find an external executable path and name starting in the same folder
* as a specified DLL or current process executable path. Helper executables
* (like gspawn-win64-helper.exe, gspawn-win64-helper-console.exe or
* gdbus.exe for example) are generally installed in the same folder as the
* corresponding DLL file.
*
* So, if package has been correctly installed, with a dynamic build of GLib,
* the helper executable should be in the same directory as the corresponding
* DLL file and searching should be straightforward.
*
* But if built statically, DLL handle is not available and we have to start
* searching from the directory holding current executable. It may be very
* different from the directory containing the helper program. In order to
* find the right helper program automatically in all common situations, we
* use this pattern:
*
* current directory
* |-- ???
* |-- bin
* | |-- ???
* |-- lib
* | |-- ???
* |-- glib
* | |-- ???
* |-- gio
* |-- ???
*
* starting at base searching path (DLL or current executable directory) and
* getting up until the root path. If we cannot still find the helper program,
* we'll rely on PATH as the last resort.
*
* Returns: (transfer full) (type filename) (nullable): the helper executable
* path and name in the GLib filename encoding or NULL in case of error. It
* should be deallocated with g_free().
*/
gchar *
g_win32_find_helper_executable_path (const gchar *executable_name, void *dll_handle)
{
static const gchar *const subdirs[] = { "", "bin", "lib", "glib", "gio" };
static const gsize nb_subdirs = G_N_ELEMENTS (subdirs);
DWORD module_path_len;
wchar_t module_path[MAX_PATH + 2] = { 0 };
gchar *base_searching_path;
gchar *p;
gchar *executable_path;
gsize i;
g_return_val_if_fail (executable_name && *executable_name, NULL);
module_path_len = GetModuleFileNameW (dll_handle, module_path, MAX_PATH + 1);
/* The > MAX_PATH check prevents truncated module path usage */
if (module_path_len == 0 || module_path_len > MAX_PATH)
return NULL;
base_searching_path = g_utf16_to_utf8 (module_path, -1, NULL, NULL, NULL);
if (base_searching_path == NULL)
return NULL;
p = strrchr (base_searching_path, G_DIR_SEPARATOR);
if (p == NULL)
{
g_free (base_searching_path);
return NULL;
}
*p = '\0';
for (;;)
{
/* Search in subdirectories */
for (i = 0; i < nb_subdirs; ++i)
{
/* As this function is exclusively used on Windows, the
* executable_path is always an absolute path. At worse, when
* reaching the root of the filesystem, base_searching_path may
* equal something like "[Drive letter]:" but never "/" like on
* Linux or Mac.
* For the peace of mind we still assert this, just in case that
* one day someone tries to use this function on Linux or Mac.
*/
executable_path = g_build_filename (base_searching_path, subdirs[i], executable_name, NULL);
g_assert (g_path_is_absolute (executable_path));
if (g_file_test (executable_path, G_FILE_TEST_IS_REGULAR))
break;
g_free (executable_path);
executable_path = NULL;
}
if (executable_path != NULL)
break;
/* Let's get one directory level up */
p = strrchr (base_searching_path, G_DIR_SEPARATOR);
if (p == NULL)
break;
*p = '\0';
}
g_free (base_searching_path);
if (executable_path == NULL)
{
/* Search in system PATH */
executable_path = g_find_program_in_path (executable_name);
if (executable_path == NULL)
executable_path = g_strdup (executable_name);
}
return executable_path;
}
#endif

View File

@ -34,6 +34,11 @@
static void
test_completion (void)
{
static const char *const a1 = "a\302\243";
static const char *const a2 = "a\302\244";
static const char *const bb = "bb";
static const char *const bc = "bc";
GCompletion *cmp;
GList *items;
gchar *prefix;
@ -42,10 +47,10 @@ test_completion (void)
g_completion_set_compare (cmp, strncmp);
items = NULL;
items = g_list_append (items, "a\302\243");
items = g_list_append (items, "a\302\244");
items = g_list_append (items, "bb");
items = g_list_append (items, "bc");
items = g_list_append (items, (gpointer) a1);
items = g_list_append (items, (gpointer) a2);
items = g_list_append (items, (gpointer) bb);
items = g_list_append (items, (gpointer) bc);
g_completion_add_items (cmp, items);
g_list_free (items);
@ -75,7 +80,7 @@ test_completion (void)
items = g_completion_complete_utf8 (cmp, "a", NULL);
g_assert_cmpint (g_list_length (items), ==, 2);
items = g_list_append (NULL, "bb");
items = g_list_append (NULL, (gpointer) bb);
g_completion_remove_items (cmp, items);
g_list_free (items);

View File

@ -1,5 +1,5 @@
[wrap-git]
directory=proxy-libintl
url=https://github.com/frida/proxy-libintl.git
revision=0.2
revision=c03e1a74b17fa7ec467e110130775409e4828a4c
depth=1