diff options
author | Vasily Galkin <galkin-vv@ya.ru> | 2019-02-12 02:21:51 +0300 |
---|---|---|
committer | Vasily Galkin <galkin-vv@ya.ru> | 2019-03-07 15:56:44 +0300 |
commit | 4342dbbe4de3e07e26515a13e952e36fbbea74f2 (patch) | |
tree | 6f1c3e13561235261cfc724e087c189616f447b1 /gio/gdbusaddress.c | |
parent | 4ed5abda438e7f66c3765c4236cae962b7d8d1bf (diff) | |
download | glib-4342dbbe4de3e07e26515a13e952e36fbbea74f2.tar.gz |
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.
Diffstat (limited to 'gio/gdbusaddress.c')
-rw-r--r-- | gio/gdbusaddress.c | 363 |
1 files changed, 2 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) |