summaryrefslogtreecommitdiff
path: root/gio/gdbusaddress.c
diff options
context:
space:
mode:
authorVasily Galkin <galkin-vv@ya.ru>2019-02-12 02:21:51 +0300
committerVasily Galkin <galkin-vv@ya.ru>2019-03-07 15:56:44 +0300
commit4342dbbe4de3e07e26515a13e952e36fbbea74f2 (patch)
tree6f1c3e13561235261cfc724e087c189616f447b1 /gio/gdbusaddress.c
parent4ed5abda438e7f66c3765c4236cae962b7d8d1bf (diff)
downloadglib-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.c363
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)