mumble/plugins/HostWindows.cpp
Davide Beatrici 988b8417ac REFAC(positional-audio): Proper functions/classes for module-related operations
Previously, only module() was present: it retrieved the base address of the specified module.

It worked fine, but it iterated through the process' modules every time it was called.

This commit replaces it with modules(), which returns an std::unordered_map containing all modules.

The map uses the module name as key and Module as value.

Aside from the performance improvement, the new code also provides info for each module region:

- Start address.
- Size.
- Whether it's readable, writable and/or executable.
2020-11-06 21:37:06 +01:00

83 lines
2.2 KiB
C++

// Copyright 2020 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>.
#include "HostWindows.h"
#include "mumble_plugin_utils.h"
#include <windows.h>
#include <tlhelp32.h>
HostWindows::HostWindows(const procid_t pid) : m_pid(pid) {
}
HostWindows::~HostWindows() {
}
bool HostWindows::peek(const procptr_t address, void *dst, const size_t size) const {
SIZE_T read;
const auto ok = Toolhelp32ReadProcessMemory(m_pid, reinterpret_cast< void * >(address), dst, size, &read);
return (ok && read == size);
}
Modules HostWindows::modules() const {
const auto processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, false, m_pid);
if (!processHandle) {
return {};
}
const auto snapshotHandle = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, m_pid);
if (snapshotHandle == INVALID_HANDLE_VALUE) {
return {};
}
Modules modules;
MODULEENTRY32 me;
me.dwSize = sizeof(me);
for (auto ok = Module32First(snapshotHandle, &me); ok; ok = Module32Next(snapshotHandle, &me)) {
const auto name = utf16ToUtf8(reinterpret_cast< char16_t * >(me.szModule));
if (modules.find(name) != modules.cend()) {
continue;
}
Module module(name);
MEMORY_BASIC_INFORMATION64 mbi;
auto address = reinterpret_cast< procptr_t >(me.modBaseAddr);
while (VirtualQueryEx(processHandle, reinterpret_cast< LPCVOID >(address),
reinterpret_cast< PMEMORY_BASIC_INFORMATION >(&mbi), sizeof(mbi))) {
MemoryRegion region{};
region.address = address;
region.size = mbi.RegionSize;
switch (mbi.Protect) {
case PAGE_READWRITE:
region.writable = true;
case PAGE_READONLY:
case PAGE_WRITECOPY:
region.readable = true;
break;
case PAGE_EXECUTE_READWRITE:
region.writable = true;
case PAGE_EXECUTE_READ:
case PAGE_EXECUTE_WRITECOPY:
region.readable = true;
case PAGE_EXECUTE:
region.executable = true;
break;
}
module.addRegion(region);
address += region.size;
}
modules.insert(std::make_pair(name, module));
}
CloseHandle(processHandle);
CloseHandle(snapshotHandle);
return modules;
}