[glib: 2/7] gdbus, win32: move most W32 dbus autolaunch code to gdbusprivate



commit 4342dbbe4de3e07e26515a13e952e36fbbea74f2
Author: Vasily Galkin <galkin-vv ya ru>
Date:   Tue Feb 12 02:21:51 2019 +0300

    gdbus, win32: move most W32 dbus autolaunch code to gdbusprivate
    
    This allows referencig them from more than single .c file.
    
    Implementation moved without changes
    from gdbusaddress.c to gdbusprivate.c
    
    g_win32_run_session_bus signature also kept, so ABI unchanged.

 gio/gdbusaddress.c | 363 +---------------------------------------------------
 gio/gdbusprivate.c | 366 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 gio/gdbusprivate.h |  10 ++
 3 files changed, 378 insertions(+), 361 deletions(-)
---
diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c
index 8b3c858ba..024e93b43 100644
--- a/gio/gdbusaddress.c
+++ b/gio/gdbusaddress.c
@@ -37,8 +37,6 @@
 #include "gtask.h"
 #include "glib-private.h"
 #include "gdbusprivate.h"
-#include "giomodule-priv.h"
-#include "gdbusdaemon.h"
 #include "gstdio.h"
 
 #ifdef G_OS_UNIX
@@ -50,8 +48,6 @@
 
 #ifdef G_OS_WIN32
 #include <windows.h>
-#include <io.h>
-#include <conio.h>
 #endif
 
 #include "glibintl.h"
@@ -1195,367 +1191,12 @@ get_session_address_dbus_launch (GError **error)
 /* end of G_OS_UNIX case */
 #elif defined(G_OS_WIN32)
 
-#define DBUS_DAEMON_ADDRESS_INFO "DBusDaemonAddressInfo"
-#define DBUS_DAEMON_MUTEX "DBusDaemonMutex"
-#define UNIQUE_DBUS_INIT_MUTEX "UniqueDBusInitMutex"
-#define DBUS_AUTOLAUNCH_MUTEX "DBusAutolaunchMutex"
-
-static void
-release_mutex (HANDLE mutex)
-{
-  ReleaseMutex (mutex);
-  CloseHandle (mutex);
-}
-
-static HANDLE
-acquire_mutex (const char *mutexname)
-{
-  HANDLE mutex;
-  DWORD res;
-
-  mutex = CreateMutexA (NULL, FALSE, mutexname);
-  if (!mutex)
-    return 0;
-
-  res = WaitForSingleObject (mutex, INFINITE);
-  switch (res)
-    {
-    case WAIT_ABANDONED:
-      release_mutex (mutex);
-      return 0;
-    case WAIT_FAILED:
-    case WAIT_TIMEOUT:
-      return 0;
-    }
-
-  return mutex;
-}
-
-static gboolean
-is_mutex_owned (const char *mutexname)
-{
-  HANDLE mutex;
-  gboolean res = FALSE;
-
-  mutex = CreateMutexA (NULL, FALSE, mutexname);
-  if (WaitForSingleObject (mutex, 10) == WAIT_TIMEOUT)
-    res = TRUE;
-  else
-    ReleaseMutex (mutex);
-  CloseHandle (mutex);
-
-  return res;
-}
-
-static char *
-read_shm (const char *shm_name)
-{
-  HANDLE shared_mem;
-  char *shared_data;
-  char *res;
-  int i;
-
-  res = NULL;
-
-  for (i = 0; i < 20; i++)
-    {
-      shared_mem = OpenFileMappingA (FILE_MAP_READ, FALSE, shm_name);
-      if (shared_mem != 0)
-       break;
-      Sleep (100);
-    }
-
-  if (shared_mem != 0)
-    {
-      shared_data = MapViewOfFile (shared_mem, FILE_MAP_READ, 0, 0, 0);
-      /* It looks that a race is possible here:
-       * if the dbus process already created mapping but didn't fill it
-       * the code below may read incorrect address.
-       * Also this is a bit complicated by the fact that
-       * any change in the "synchronization contract" between processes
-       * should be accompanied with renaming all of used win32 named objects:
-       * otherwise libgio-2.0-0.dll of different versions shipped with
-       * different apps may break each other due to protocol difference.
-       */
-      if (shared_data != NULL)
-       {
-         res = g_strdup (shared_data);
-         UnmapViewOfFile (shared_data);
-       }
-      CloseHandle (shared_mem);
-    }
-
-  return res;
-}
-
-static HANDLE
-set_shm (const char *shm_name, const char *value)
-{
-  HANDLE shared_mem;
-  char *shared_data;
-
-  shared_mem = CreateFileMappingA (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
-                                  0, strlen (value) + 1, shm_name);
-  if (shared_mem == 0)
-    return 0;
-
-  shared_data = MapViewOfFile (shared_mem, FILE_MAP_WRITE, 0, 0, 0 );
-  if (shared_data == NULL)
-    return 0;
-
-  strcpy (shared_data, value);
-
-  UnmapViewOfFile (shared_data);
-
-  return shared_mem;
-}
-
-/* These keep state between publish_session_bus and unpublish_session_bus */
-static HANDLE published_daemon_mutex;
-static HANDLE published_shared_mem;
-
-static gboolean
-publish_session_bus (const char *address)
-{
-  HANDLE init_mutex;
-
-  init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX);
-
-  published_daemon_mutex = CreateMutexA (NULL, FALSE, DBUS_DAEMON_MUTEX);
-  if (WaitForSingleObject (published_daemon_mutex, 10 ) != WAIT_OBJECT_0)
-    {
-      release_mutex (init_mutex);
-      CloseHandle (published_daemon_mutex);
-      published_daemon_mutex = NULL;
-      return FALSE;
-    }
-
-  published_shared_mem = set_shm (DBUS_DAEMON_ADDRESS_INFO, address);
-  if (!published_shared_mem)
-    {
-      release_mutex (init_mutex);
-      CloseHandle (published_daemon_mutex);
-      published_daemon_mutex = NULL;
-      return FALSE;
-    }
-
-  release_mutex (init_mutex);
-  return TRUE;
-}
-
-static void
-unpublish_session_bus (void)
-{
-  HANDLE init_mutex;
-
-  init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX);
-
-  CloseHandle (published_shared_mem);
-  published_shared_mem = NULL;
-
-  release_mutex (published_daemon_mutex);
-  published_daemon_mutex = NULL;
-
-  release_mutex (init_mutex);
-}
-
-static void
-wait_console_window (void)
-{
-  FILE *console = fopen ("CONOUT$", "w");
-
-  SetConsoleTitleW (L"gdbus-daemon output. Type any character to close this window.");
-  fprintf (console, _("(Type any character to close this window)\n"));
-  fflush (console);
-  _getch ();
-}
-
-static void
-open_console_window (void)
-{
-  if (((HANDLE) _get_osfhandle (fileno (stdout)) == INVALID_HANDLE_VALUE ||
-       (HANDLE) _get_osfhandle (fileno (stderr)) == INVALID_HANDLE_VALUE) && AllocConsole ())
-    {
-      if ((HANDLE) _get_osfhandle (fileno (stdout)) == INVALID_HANDLE_VALUE)
-        freopen ("CONOUT$", "w", stdout);
-
-      if ((HANDLE) _get_osfhandle (fileno (stderr)) == INVALID_HANDLE_VALUE)
-        freopen ("CONOUT$", "w", stderr);
-
-      SetConsoleTitleW (L"gdbus-daemon debug output.");
-
-      atexit (wait_console_window);
-    }
-}
-
-static void
-idle_timeout_cb (GDBusDaemon *daemon, gpointer user_data)
-{
-  GMainLoop *loop = user_data;
-  g_main_loop_quit (loop);
-}
-
-/* Satisfies STARTF_FORCEONFEEDBACK */
-static void
-turn_off_the_starting_cursor (void)
-{
-  MSG msg;
-  BOOL bRet;
-
-  PostQuitMessage (0);
-
-  while ((bRet = GetMessage (&msg, 0, 0, 0)) != 0)
-    {
-      if (bRet == -1)
-        continue;
-
-      TranslateMessage (&msg);
-      DispatchMessage (&msg);
-    }
-}
-
-__declspec(dllexport) void CALLBACK g_win32_run_session_bus (HWND hwnd, HINSTANCE hinst, char *cmdline, int 
nCmdShow);
-
-__declspec(dllexport) void CALLBACK
-g_win32_run_session_bus (HWND hwnd, HINSTANCE hinst, char *cmdline, int nCmdShow)
-{
-  GDBusDaemon *daemon;
-  GMainLoop *loop;
-  const char *address;
-  GError *error = NULL;
-
-  turn_off_the_starting_cursor ();
-
-  if (g_getenv ("GDBUS_DAEMON_DEBUG") != NULL)
-    open_console_window ();
-
-  loop = g_main_loop_new (NULL, FALSE);
-
-  address = "nonce-tcp:";
-  daemon = _g_dbus_daemon_new (address, NULL, &error);
-  if (daemon == NULL)
-    {
-      g_printerr ("Can't init bus: %s\n", error->message);
-      g_error_free (error);
-      return;
-    }
-
-  /* There is a subtle detail with "idle-timeout" signal of dbus daemon:
-   * It is fired on idle after last client disconnection,
-   * but (at least with glib 2.59.1) it is NEVER fired
-   * if no clients connect to daemon at all.
-   * This may lead to infinite run of this daemon process.
-   */
-  g_signal_connect (daemon, "idle-timeout", G_CALLBACK (idle_timeout_cb), loop);
-
-  if (publish_session_bus (_g_dbus_daemon_get_address (daemon)))
-    {
-      g_main_loop_run (loop);
-
-      unpublish_session_bus ();
-    }
-
-  g_main_loop_unref (loop);
-  g_object_unref (daemon);
-}
-
 static gchar *
 get_session_address_dbus_launch (GError **error)
 {
-  HANDLE autolaunch_mutex, init_mutex;
-  char *address = NULL;
-
-  autolaunch_mutex = acquire_mutex (DBUS_AUTOLAUNCH_MUTEX);
-
-  init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX);
-
-  if (is_mutex_owned (DBUS_DAEMON_MUTEX))
-    address = read_shm (DBUS_DAEMON_ADDRESS_INFO);
-
-  release_mutex (init_mutex);
-
-  if (address == NULL)
-    {
-      /* rundll32 doesn't support neither spaces, nor quotes in cmdline:
-       * https://support.microsoft.com/en-us/help/164787/info-windows-rundll-and-rundll32-interface
-       * Since the dll path may have spaces, it is used as working directory,
-       * and the plain dll name is passed as argument to rundll32 like
-       * "C:\Windows\System32\rundll32.exe" .\libgio-2.0-0.dll,g_win32_run_session_bus
-       *
-       * Using relative path to dll rises a question if correct dll is loaded.
-       * According to docs if relative path like .\libgio-2.0-0.dll is passed
-       * the System32 directory may be searched before current directory:
-       * 
https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-search-order#standard-search-order-for-desktop-applications
-       * Internally rundll32 uses "undefined behavior" parameter combination
-       * LoadLibraryExW(".\libgio-2.0-0.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH)
-       * Actual testing shows that if relative name starts from ".\"
-       * the current directory is searched before System32 (win7, win10 1607).
-       * So wrong dll would be loaded only if the BOTH of the following holds:
-       * - rundll32 will change so it would prefer system32 even for .\ paths
-       * - some app would place libgio-2.0-0.dll in system32 directory
-       *
-       * In point of that using .\libgio-2.0-0.dll looks fine.
-       */
-      wchar_t gio_path[MAX_PATH + 2] = { 0 };
-      int gio_path_len = GetModuleFileNameW (_g_io_win32_get_module (), gio_path, MAX_PATH + 1);
-
-      /* 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 rundll_path[MAX_PATH + 100] = { 0 };
-         wchar_t args[MAX_PATH*2 + 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;
-         }
-         GetWindowsDirectoryW (rundll_path, MAX_PATH);
-         wcscat (rundll_path, L"\\rundll32.exe");
-         if (GetFileAttributesW (rundll_path) == INVALID_FILE_ATTRIBUTES)
-           {
-             GetSystemDirectoryW (rundll_path, MAX_PATH);
-             wcscat (rundll_path, L"\\rundll32.exe");
-           }
-
-         wcscpy (args, L"\"");
-         wcscat (args, rundll_path);
-         wcscat (args, L"\" .\\");
-         wcscat (args, gio_path + gio_name_index);
-#if defined(_WIN64) || defined(_M_X64) || defined(_M_AMD64)
-         wcscat (args, L",g_win32_run_session_bus");
-#elif defined (_MSC_VER)
-         wcscat (args, L",_g_win32_run_session_bus@16");
-#else
-         wcscat (args, L",g_win32_run_session_bus@16");
-#endif
-
-         gio_path[gio_name_index] = L'\0';
-         res = CreateProcessW (rundll_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);
-       }
-    }
-
-  release_mutex (autolaunch_mutex);
-
-  if (address == NULL)
-    g_set_error (error,
-                G_IO_ERROR,
-                G_IO_ERROR_FAILED,
-                _("Session dbus not running, and autolaunch failed"));
-
-  return address;
+  return _g_dbus_win32_get_session_address_dbus_launch (error);
 }
+
 #else /* neither G_OS_UNIX nor G_OS_WIN32 */
 static gchar *
 get_session_address_dbus_launch (GError **error)
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index 1e8e1d64b..385b5a4d6 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -33,6 +33,8 @@
 #include "gdbusproxy.h"
 #include "gdbuserror.h"
 #include "gdbusintrospection.h"
+#include "gdbusdaemon.h"
+#include "giomodule-priv.h"
 #include "gtask.h"
 #include "ginputstream.h"
 #include "gmemoryinputstream.h"
@@ -51,6 +53,8 @@
 
 #ifdef G_OS_WIN32
 #include <windows.h>
+#include <io.h>
+#include <conio.h>
 #endif
 
 #include "glibintl.h"
@@ -2054,6 +2058,368 @@ out:
     CloseHandle (h);
   return ret;
 }
+
+
+#define DBUS_DAEMON_ADDRESS_INFO "DBusDaemonAddressInfo"
+#define DBUS_DAEMON_MUTEX "DBusDaemonMutex"
+#define UNIQUE_DBUS_INIT_MUTEX "UniqueDBusInitMutex"
+#define DBUS_AUTOLAUNCH_MUTEX "DBusAutolaunchMutex"
+
+static void
+release_mutex (HANDLE mutex)
+{
+  ReleaseMutex (mutex);
+  CloseHandle (mutex);
+}
+
+static HANDLE
+acquire_mutex (const char *mutexname)
+{
+  HANDLE mutex;
+  DWORD res;
+
+  mutex = CreateMutexA (NULL, FALSE, mutexname);
+  if (!mutex)
+    return 0;
+
+  res = WaitForSingleObject (mutex, INFINITE);
+  switch (res)
+    {
+    case WAIT_ABANDONED:
+      release_mutex (mutex);
+      return 0;
+    case WAIT_FAILED:
+    case WAIT_TIMEOUT:
+      return 0;
+    }
+
+  return mutex;
+}
+
+static gboolean
+is_mutex_owned (const char *mutexname)
+{
+  HANDLE mutex;
+  gboolean res = FALSE;
+
+  mutex = CreateMutexA (NULL, FALSE, mutexname);
+  if (WaitForSingleObject (mutex, 10) == WAIT_TIMEOUT)
+    res = TRUE;
+  else
+    ReleaseMutex (mutex);
+  CloseHandle (mutex);
+
+  return res;
+}
+
+static char *
+read_shm (const char *shm_name)
+{
+  HANDLE shared_mem;
+  char *shared_data;
+  char *res;
+  int i;
+
+  res = NULL;
+
+  for (i = 0; i < 20; i++)
+    {
+      shared_mem = OpenFileMappingA (FILE_MAP_READ, FALSE, shm_name);
+      if (shared_mem != 0)
+       break;
+      Sleep (100);
+    }
+
+  if (shared_mem != 0)
+    {
+      shared_data = MapViewOfFile (shared_mem, FILE_MAP_READ, 0, 0, 0);
+      /* It looks that a race is possible here:
+       * if the dbus process already created mapping but didn't fill it
+       * the code below may read incorrect address.
+       * Also this is a bit complicated by the fact that
+       * any change in the "synchronization contract" between processes
+       * should be accompanied with renaming all of used win32 named objects:
+       * otherwise libgio-2.0-0.dll of different versions shipped with
+       * different apps may break each other due to protocol difference.
+       */
+      if (shared_data != NULL)
+       {
+         res = g_strdup (shared_data);
+         UnmapViewOfFile (shared_data);
+       }
+      CloseHandle (shared_mem);
+    }
+
+  return res;
+}
+
+static HANDLE
+set_shm (const char *shm_name, const char *value)
+{
+  HANDLE shared_mem;
+  char *shared_data;
+
+  shared_mem = CreateFileMappingA (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
+                                  0, strlen (value) + 1, shm_name);
+  if (shared_mem == 0)
+    return 0;
+
+  shared_data = MapViewOfFile (shared_mem, FILE_MAP_WRITE, 0, 0, 0 );
+  if (shared_data == NULL)
+    return 0;
+
+  strcpy (shared_data, value);
+
+  UnmapViewOfFile (shared_data);
+
+  return shared_mem;
+}
+
+/* These keep state between publish_session_bus and unpublish_session_bus */
+static HANDLE published_daemon_mutex;
+static HANDLE published_shared_mem;
+
+static gboolean
+publish_session_bus (const char *address)
+{
+  HANDLE init_mutex;
+
+  init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX);
+
+  published_daemon_mutex = CreateMutexA (NULL, FALSE, DBUS_DAEMON_MUTEX);
+  if (WaitForSingleObject (published_daemon_mutex, 10 ) != WAIT_OBJECT_0)
+    {
+      release_mutex (init_mutex);
+      CloseHandle (published_daemon_mutex);
+      published_daemon_mutex = NULL;
+      return FALSE;
+    }
+
+  published_shared_mem = set_shm (DBUS_DAEMON_ADDRESS_INFO, address);
+  if (!published_shared_mem)
+    {
+      release_mutex (init_mutex);
+      CloseHandle (published_daemon_mutex);
+      published_daemon_mutex = NULL;
+      return FALSE;
+    }
+
+  release_mutex (init_mutex);
+  return TRUE;
+}
+
+static void
+unpublish_session_bus (void)
+{
+  HANDLE init_mutex;
+
+  init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX);
+
+  CloseHandle (published_shared_mem);
+  published_shared_mem = NULL;
+
+  release_mutex (published_daemon_mutex);
+  published_daemon_mutex = NULL;
+
+  release_mutex (init_mutex);
+}
+
+static void
+wait_console_window (void)
+{
+  FILE *console = fopen ("CONOUT$", "w");
+
+  SetConsoleTitleW (L"gdbus-daemon output. Type any character to close this window.");
+  fprintf (console, _("(Type any character to close this window)\n"));
+  fflush (console);
+  _getch ();
+}
+
+static void
+open_console_window (void)
+{
+  if (((HANDLE) _get_osfhandle (fileno (stdout)) == INVALID_HANDLE_VALUE ||
+       (HANDLE) _get_osfhandle (fileno (stderr)) == INVALID_HANDLE_VALUE) && AllocConsole ())
+    {
+      if ((HANDLE) _get_osfhandle (fileno (stdout)) == INVALID_HANDLE_VALUE)
+        freopen ("CONOUT$", "w", stdout);
+
+      if ((HANDLE) _get_osfhandle (fileno (stderr)) == INVALID_HANDLE_VALUE)
+        freopen ("CONOUT$", "w", stderr);
+
+      SetConsoleTitleW (L"gdbus-daemon debug output.");
+
+      atexit (wait_console_window);
+    }
+}
+
+static void
+idle_timeout_cb (GDBusDaemon *daemon, gpointer user_data)
+{
+  GMainLoop *loop = user_data;
+  g_main_loop_quit (loop);
+}
+
+/* Satisfies STARTF_FORCEONFEEDBACK */
+static void
+turn_off_the_starting_cursor (void)
+{
+  MSG msg;
+  BOOL bRet;
+
+  PostQuitMessage (0);
+
+  while ((bRet = GetMessage (&msg, 0, 0, 0)) != 0)
+    {
+      if (bRet == -1)
+        continue;
+
+      TranslateMessage (&msg);
+      DispatchMessage (&msg);
+    }
+}
+
+__declspec(dllexport) void __stdcall
+g_win32_run_session_bus (void* hwnd, void* hinst, const char* cmdline, int cmdshow)
+{
+  GDBusDaemon *daemon;
+  GMainLoop *loop;
+  const char *address;
+  GError *error = NULL;
+
+  turn_off_the_starting_cursor ();
+
+  if (g_getenv ("GDBUS_DAEMON_DEBUG") != NULL)
+    open_console_window ();
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  address = "nonce-tcp:";
+  daemon = _g_dbus_daemon_new (address, NULL, &error);
+  if (daemon == NULL)
+    {
+      g_printerr ("Can't init bus: %s\n", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  /* There is a subtle detail with "idle-timeout" signal of dbus daemon:
+   * It is fired on idle after last client disconnection,
+   * but (at least with glib 2.59.1) it is NEVER fired
+   * if no clients connect to daemon at all.
+   * This may lead to infinite run of this daemon process.
+   */
+  g_signal_connect (daemon, "idle-timeout", G_CALLBACK (idle_timeout_cb), loop);
+
+  if (publish_session_bus (_g_dbus_daemon_get_address (daemon)))
+    {
+      g_main_loop_run (loop);
+
+      unpublish_session_bus ();
+    }
+
+  g_main_loop_unref (loop);
+  g_object_unref (daemon);
+}
+
+gchar *
+_g_dbus_win32_get_session_address_dbus_launch (GError **error)
+{
+  HANDLE autolaunch_mutex, init_mutex;
+  char *address = NULL;
+
+  autolaunch_mutex = acquire_mutex (DBUS_AUTOLAUNCH_MUTEX);
+
+  init_mutex = acquire_mutex (UNIQUE_DBUS_INIT_MUTEX);
+
+  if (is_mutex_owned (DBUS_DAEMON_MUTEX))
+    address = read_shm (DBUS_DAEMON_ADDRESS_INFO);
+
+  release_mutex (init_mutex);
+
+  if (address == NULL)
+    {
+      /* rundll32 doesn't support neither spaces, nor quotes in cmdline:
+       * https://support.microsoft.com/en-us/help/164787/info-windows-rundll-and-rundll32-interface
+       * Since the dll path may have spaces, it is used as working directory,
+       * and the plain dll name is passed as argument to rundll32 like
+       * "C:\Windows\System32\rundll32.exe" .\libgio-2.0-0.dll,g_win32_run_session_bus
+       *
+       * Using relative path to dll rises a question if correct dll is loaded.
+       * According to docs if relative path like .\libgio-2.0-0.dll is passed
+       * the System32 directory may be searched before current directory:
+       * 
https://docs.microsoft.com/en-us/windows/desktop/dlls/dynamic-link-library-search-order#standard-search-order-for-desktop-applications
+       * Internally rundll32 uses "undefined behavior" parameter combination
+       * LoadLibraryExW(".\libgio-2.0-0.dll", NULL, LOAD_WITH_ALTERED_SEARCH_PATH)
+       * Actual testing shows that if relative name starts from ".\"
+       * the current directory is searched before System32 (win7, win10 1607).
+       * So wrong dll would be loaded only if the BOTH of the following holds:
+       * - rundll32 will change so it would prefer system32 even for .\ paths
+       * - some app would place libgio-2.0-0.dll in system32 directory
+       *
+       * In point of that using .\libgio-2.0-0.dll looks fine.
+       */
+      wchar_t gio_path[MAX_PATH + 2] = { 0 };
+      int gio_path_len = GetModuleFileNameW (_g_io_win32_get_module (), gio_path, MAX_PATH + 1);
+
+      /* 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 rundll_path[MAX_PATH + 100] = { 0 };
+         wchar_t args[MAX_PATH*2 + 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;
+         }
+         GetWindowsDirectoryW (rundll_path, MAX_PATH);
+         wcscat (rundll_path, L"\\rundll32.exe");
+         if (GetFileAttributesW (rundll_path) == INVALID_FILE_ATTRIBUTES)
+           {
+             GetSystemDirectoryW (rundll_path, MAX_PATH);
+             wcscat (rundll_path, L"\\rundll32.exe");
+           }
+
+         wcscpy (args, L"\"");
+         wcscat (args, rundll_path);
+         wcscat (args, L"\" .\\");
+         wcscat (args, gio_path + gio_name_index);
+#if defined(_WIN64) || defined(_M_X64) || defined(_M_AMD64)
+         wcscat (args, L",g_win32_run_session_bus");
+#elif defined (_MSC_VER)
+         wcscat (args, L",_g_win32_run_session_bus@16");
+#else
+         wcscat (args, L",g_win32_run_session_bus@16");
+#endif
+
+         gio_path[gio_name_index] = L'\0';
+         res = CreateProcessW (rundll_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);
+       }
+    }
+
+  release_mutex (autolaunch_mutex);
+
+  if (address == NULL)
+    g_set_error (error,
+                G_IO_ERROR,
+                G_IO_ERROR_FAILED,
+                _("Session dbus not running, and autolaunch failed"));
+
+  return address;
+}
+
 #endif
 
 /* ---------------------------------------------------------------------------------------------------- */
diff --git a/gio/gdbusprivate.h b/gio/gdbusprivate.h
index a319166ee..7f5845f47 100644
--- a/gio/gdbusprivate.h
+++ b/gio/gdbusprivate.h
@@ -109,6 +109,16 @@ gchar *_g_dbus_hexdump (const gchar *data, gsize len, guint indent);
 
 #ifdef G_OS_WIN32
 gchar *_g_dbus_win32_get_user_sid (void);
+
+/* The g_win32_run_session_bus is exported from libgio dll on win32,
+ * but still is NOT part of API/ABI since it is declared in private header
+ * and used only by tool built from same sources.
+ * Initially this function was introduces for usage with rundll,
+ * so the signature is kept rundll-compatible, though parameters aren't used.
+ */
+__declspec(dllexport) void __stdcall
+g_win32_run_session_bus (void* hwnd, void* hinst, const char* cmdline, int cmdshow);
+gchar *_g_dbus_win32_get_session_address_dbus_launch (GError **error);
 #endif
 
 gchar *_g_dbus_get_machine_id (GError **error);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]