feat: Use EnumProcessModules to search loaded modules)
This commit is contained in:
parent
4cfeadf0be
commit
751c869435
2 changed files with 42 additions and 7 deletions
|
|
@ -12,10 +12,9 @@
|
||||||
#include "base/Log.h"
|
#include "base/Log.h"
|
||||||
#include "base/String.h"
|
#include "base/String.h"
|
||||||
|
|
||||||
#include <Wtsapi32.h>
|
#include <Psapi.h>
|
||||||
#pragma warning(disable : 4099)
|
|
||||||
#include <Userenv.h>
|
#include <Userenv.h>
|
||||||
#pragma warning(default : 4099)
|
#include <Wtsapi32.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
|
@ -505,12 +504,43 @@ std::string ArchMiscWindows::getActiveDesktopName()
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HMODULE ArchMiscWindows::findLoadedModule(std::array<const char *, 2> moduleNames)
|
||||||
|
{
|
||||||
|
std::array<HMODULE, 1024> hModules;
|
||||||
|
DWORD cbNeeded;
|
||||||
|
|
||||||
|
HANDLE hProcess = GetCurrentProcess();
|
||||||
|
if (!EnumProcessModules(hProcess, hModules.data(), sizeof(hModules), &cbNeeded)) {
|
||||||
|
errorMessageBox("Failed to enumerate process modules.");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string loadedModuleName;
|
||||||
|
for (size_t i = 0; i < (cbNeeded / sizeof(HMODULE)); ++i) {
|
||||||
|
if (!GetModuleBaseNameA(hProcess, hModules[i], loadedModuleName.data(), sizeof(loadedModuleName))) {
|
||||||
|
LOG_WARN("could not get base name of loaded module %d", i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &moduleName : moduleNames) {
|
||||||
|
if (_stricmp(loadedModuleName.data(), moduleName) == 0) {
|
||||||
|
return hModules[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Enforcing minimum MSVC runtime version is quite strict, but we have a good reason.
|
// Enforcing minimum MSVC runtime version is quite strict, but we have a good reason.
|
||||||
//
|
//
|
||||||
// Microsoft lets you run a program with an older version of the runtime DLL than the one it was
|
// Microsoft lets you run a program with an older version of the runtime DLL than the one it was
|
||||||
// compiled with. This is because the runtime DLLs are supposedly ABI-compatible when the major
|
// compiled with. This is because the runtime DLLs are supposedly ABI-compatible when the major
|
||||||
// version is the same, so hypothetically MSVC runtime 14.0 is compatible with 14.42.
|
// version is the same, so hypothetically MSVC runtime 14.0 is compatible with 14.42.
|
||||||
// However, we have found that subtle edge cases (such as mutex lock causes access violation).
|
// However, we have found subtle edge cases such as mutex lock causes access violation.
|
||||||
|
//
|
||||||
|
// Example of how Microsoft breaks ABI compatibility between minor runtime versions:
|
||||||
|
// https://stackoverflow.com/questions/69990339/why-is-stdmutex-so-much-worse-than-stdshared-mutex-in-visual-c
|
||||||
//
|
//
|
||||||
// Our CI is set up to build with the latest compiler, so in this case we should insist on at least
|
// Our CI is set up to build with the latest compiler, so in this case we should insist on at least
|
||||||
// the runtime DLL that was released at the same time as the compiler.
|
// the runtime DLL that was released at the same time as the compiler.
|
||||||
|
|
@ -519,10 +549,9 @@ std::string ArchMiscWindows::getActiveDesktopName()
|
||||||
// requirements for the current Qt version we support.
|
// requirements for the current Qt version we support.
|
||||||
void ArchMiscWindows::guardRuntimeVersion() // NOSONAR - `noreturn` is not available
|
void ArchMiscWindows::guardRuntimeVersion() // NOSONAR - `noreturn` is not available
|
||||||
{
|
{
|
||||||
const auto kRuntimeDll = "vcruntime140.dll";
|
auto hModule = findLoadedModule({"vcruntime140.dll", "vcruntime140d.dll"});
|
||||||
|
|
||||||
HMODULE hModule = nullptr;
|
if (!hModule) {
|
||||||
if (!GetModuleHandleEx(0, kRuntimeDll, &hModule)) {
|
|
||||||
errorMessageBox("Could not find Microsoft Visual C++ Runtime.");
|
errorMessageBox("Could not find Microsoft Visual C++ Runtime.");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,12 @@ private:
|
||||||
//! Calls `getProcessEntry` with the parent process ID
|
//! Calls `getProcessEntry` with the parent process ID
|
||||||
static BOOL WINAPI getParentProcessEntry(PROCESSENTRY32 &entry);
|
static BOOL WINAPI getParentProcessEntry(PROCESSENTRY32 &entry);
|
||||||
|
|
||||||
|
//! Searches the loaded modules and returns the matching module handle
|
||||||
|
/**
|
||||||
|
* @param moduleNames Provide two module names to search for both release and debug versions.
|
||||||
|
*/
|
||||||
|
static HMODULE findLoadedModule(std::array<const char *, 2> moduleNames);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Dialogs = std::set<HWND>;
|
using Dialogs = std::set<HWND>;
|
||||||
typedef DWORD(WINAPI *STES_t)(DWORD);
|
typedef DWORD(WINAPI *STES_t)(DWORD);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue