diff options
Diffstat (limited to 'plugins/mumble_positional_audio_win32.h')
-rw-r--r-- | plugins/mumble_positional_audio_win32.h | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/plugins/mumble_positional_audio_win32.h b/plugins/mumble_positional_audio_win32.h new file mode 100644 index 000000000..246002d01 --- /dev/null +++ b/plugins/mumble_positional_audio_win32.h @@ -0,0 +1,141 @@ +// Copyright 2021 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at <https://www.mumble.info/LICENSE>. + +#ifndef MUMBLE_POSITIONAL_AUDIO_WIN32_H_ +#define MUMBLE_POSITIONAL_AUDIO_WIN32_H_ + +#ifndef MUMBLE_POSITIONAL_AUDIO_MAIN_H_ +# error "Include mumble_positional_audio_main.h instead of mumble_positional_audio_win32.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +// Define "NOMINMAX" only if it isn't already. +// MinGW defines it by default, which results in a redefinition warning. +#ifndef NOMINMAX +# define NOMINMAX +#endif +#include <windows.h> +#include <iostream> +#include <math.h> +#include <sstream> +#include <stdint.h> +#include <tlhelp32.h> + +static HANDLE hProcess; + +static inline procid_t getProcess(const wchar_t *exename) { + PROCESSENTRY32 pe; + procid_t pid = 0; + + pe.dwSize = sizeof(pe); + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnap != INVALID_HANDLE_VALUE) { + BOOL ok = Process32First(hSnap, &pe); + + while (ok) { + if (wcscmp(pe.szExeFile, exename) == 0) { + pid = pe.th32ProcessID; + break; + } + ok = Process32Next(hSnap, &pe); + } + CloseHandle(hSnap); + } + return pid; +} + +static inline procptr_t getModuleAddr(const procid_t &pid, const wchar_t *modname) { + MODULEENTRY32 me; + procptr_t ret = 0; + me.dwSize = sizeof(me); + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid); + if (hSnap != INVALID_HANDLE_VALUE) { + BOOL ok = Module32First(hSnap, &me); + + while (ok) { + if (wcscmp(me.szModule, modname) == 0) { + uintptr_t addr = reinterpret_cast< uintptr_t >(me.modBaseAddr); + ret = static_cast< procptr_t >(addr); + break; + } + ok = Module32Next(hSnap, &me); + } + CloseHandle(hSnap); + } + return ret; +} + +static inline bool peekProc(const procptr_t &addr, void *dest, const size_t &len) { + SIZE_T r; + const BOOL ok = ReadProcessMemory(hProcess, reinterpret_cast< void * >(addr), dest, len, &r); + return (ok && (r == len)); +} + +static void generic_unlock() { + if (hProcess) { + CloseHandle(hProcess); + hProcess = nullptr; + } + + pPid = 0; + pModule = 0; +} + +static bool initialize(const std::multimap< std::wstring, unsigned long long int > &pids, const wchar_t *procname, + const wchar_t *modname = nullptr) { + hProcess = nullptr; + pModule = 0; + + if (!pids.empty()) { + auto iter = pids.find(std::wstring(procname)); + + if (iter != pids.end()) { + pPid = static_cast< procid_t >(iter->second); + } else { + pPid = 0; + } + } else { + pPid = getProcess(procname); + } + + if (!pPid) { + return false; + } + + hProcess = OpenProcess(PROCESS_VM_READ, false, pPid); + if (!hProcess) { + pPid = 0; + return false; + } + + pModule = getModuleAddr(procname); + if (!pModule) { + generic_unlock(); + return false; + } + + const int8_t result = isProcess64Bit(pModule); + if (result == -1) { + generic_unlock(); + return false; + } + + if (modname) { + pModule = getModuleAddr(modname); + if (!pModule) { + generic_unlock(); + return false; + } + } + + // We compare to 1 to prevent the following warning: + // C4800: 'BOOL': forcing value to bool 'true' or 'false' (performance warning) + is64Bit = (result == 1); + + return true; +} + +#endif |