mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
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.
This commit is contained in:
parent
4ed5abda43
commit
4342dbbe4d
@ -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)
|
||||
|
@ -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
|
||||
|
||||
/* ---------------------------------------------------------------------------------------------------- */
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user