mumble-voip_mumble/plugins/mumble_positional_audio_win...

142 lines
3.2 KiB
C++

// Copyright 2021-2023 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