From a2de0a8b7d16325dc97727d61efda0fdfc7a4396 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 3 Jan 2022 11:40:22 +0000 Subject: [PATCH] Windows: factor out mutex lock/unlock from sharing.c. This will let me reuse them easily in Pageant setup. --- windows/CMakeLists.txt | 1 + windows/platform.h | 3 ++ windows/sharing.c | 42 ++++---------------------- windows/utils/interprocess_mutex.c | 48 ++++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 36 deletions(-) create mode 100644 windows/utils/interprocess_mutex.c diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 54a72018..5343e078 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -13,6 +13,7 @@ add_sources_from_current_dir(utils utils/getdlgitemtext_alloc.c utils/get_system_dir.c utils/get_username.c + utils/interprocess_mutex.c utils/is_console_handle.c utils/load_system32_dll.c utils/ltime.c diff --git a/windows/platform.h b/windows/platform.h index 454ae2f0..aa543982 100644 --- a/windows/platform.h +++ b/windows/platform.h @@ -740,4 +740,7 @@ void plug_closing_winsock_error(Plug *plug, DWORD error); SeatPromptResult make_spr_sw_abort_winerror(const char *prefix, DWORD error); +HANDLE lock_interprocess_mutex(const char *mutexname, char **error); +void unlock_interprocess_mutex(HANDLE mutex); + #endif /* PUTTY_WINDOWS_PLATFORM_H */ diff --git a/windows/sharing.c b/windows/sharing.c index 02eeb087..15b1da48 100644 --- a/windows/sharing.c +++ b/windows/sharing.c @@ -36,8 +36,6 @@ int platform_ssh_share(const char *pi_name, Conf *conf, char *name, *mutexname, *pipename; HANDLE mutex; Socket *retsock; - PSECURITY_DESCRIPTOR psd; - PACL acl; /* * Transform the platform-independent version of the connection @@ -57,39 +55,12 @@ int platform_ssh_share(const char *pi_name, Conf *conf, * Make a mutex name out of the connection identifier, and lock it * while we decide whether to be upstream or downstream. */ - { - SECURITY_ATTRIBUTES sa; - - mutexname = make_name(CONNSHARE_MUTEX_PREFIX, name); - if (!make_private_security_descriptor(MUTEX_ALL_ACCESS, - &psd, &acl, logtext)) { - sfree(mutexname); - sfree(name); - return SHARE_NONE; - } - - memset(&sa, 0, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = psd; - sa.bInheritHandle = false; - - mutex = CreateMutex(&sa, false, mutexname); - - if (!mutex) { - *logtext = dupprintf("CreateMutex(\"%s\") failed: %s", - mutexname, win_strerror(GetLastError())); - sfree(mutexname); - sfree(name); - LocalFree(psd); - LocalFree(acl); - return SHARE_NONE; - } - + mutexname = make_name(CONNSHARE_MUTEX_PREFIX, name); + mutex = lock_interprocess_mutex(mutexname, logtext); + if (!mutex) { sfree(mutexname); - LocalFree(psd); - LocalFree(acl); - - WaitForSingleObject(mutex, INFINITE); + sfree(name); + return SHARE_NONE; } pipename = make_name(CONNSHARE_PIPE_PREFIX, name); @@ -103,8 +74,7 @@ int platform_ssh_share(const char *pi_name, Conf *conf, *logtext = pipename; *sock = retsock; sfree(name); - ReleaseMutex(mutex); - CloseHandle(mutex); + unlock_interprocess_mutex(mutex); return SHARE_DOWNSTREAM; } sfree(*ds_err); diff --git a/windows/utils/interprocess_mutex.c b/windows/utils/interprocess_mutex.c new file mode 100644 index 00000000..a22ec820 --- /dev/null +++ b/windows/utils/interprocess_mutex.c @@ -0,0 +1,48 @@ +/* + * Lock and unlock a mutex with a globally visible name. Used to + * synchronise between unrelated processes, such as two + * connection-sharing PuTTYs deciding which will be the upstream. + */ + +#include "putty.h" +#include "security-api.h" + +HANDLE lock_interprocess_mutex(const char *mutexname, char **error) +{ + PSECURITY_DESCRIPTOR psd = NULL; + PACL acl = NULL; + HANDLE mutex = NULL; + + if (!make_private_security_descriptor(MUTEX_ALL_ACCESS, + &psd, &acl, error)) + goto out; + + SECURITY_ATTRIBUTES sa; + memset(&sa, 0, sizeof(sa)); + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = psd; + sa.bInheritHandle = false; + + mutex = CreateMutex(&sa, false, mutexname); + if (!mutex) { + *error = dupprintf("CreateMutex(\"%s\") failed: %s", + mutexname, win_strerror(GetLastError())); + goto out; + } + + WaitForSingleObject(mutex, INFINITE); + + out: + if (psd) + LocalFree(psd); + if (acl) + LocalFree(acl); + + return mutex; +} + +void unlock_interprocess_mutex(HANDLE mutex) +{ + ReleaseMutex(mutex); + CloseHandle(mutex); +}