| 66 | } |
| 67 | |
| 68 | static void buildModuleCache() noexcept { |
| 69 | HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); |
| 70 | if (snap == INVALID_HANDLE_VALUE) return; |
| 71 | MODULEENTRY32W me; |
| 72 | me.dwSize = sizeof(me); |
| 73 | int count = 0; |
| 74 | BOOL ok = Module32FirstW(snap, &me); |
| 75 | while (ok && count < MAX_CACHED_MODULES) { |
| 76 | const BYTE *dllBase = me.modBaseAddr; |
| 77 | if (dllBase && me.modBaseSize) { |
| 78 | __try { |
| 79 | const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER*)dllBase; |
| 80 | if (dos->e_magic == IMAGE_DOS_SIGNATURE) { |
| 81 | const IMAGE_NT_HEADERS64 *nt = (const IMAGE_NT_HEADERS64*)(dllBase + dos->e_lfanew); |
| 82 | if (nt->Signature == IMAGE_NT_SIGNATURE && |
| 83 | nt->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) { |
| 84 | const IMAGE_DATA_DIRECTORY &excDir = |
| 85 | nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]; |
| 86 | if (excDir.VirtualAddress && excDir.Size >= sizeof(RUNTIME_FUNCTION)) { |
| 87 | CachedModule &m = g_modules[count]; |
| 88 | m.base = (ULONG64)dllBase; |
| 89 | m.end = (ULONG64)dllBase + me.modBaseSize; |
| 90 | m.pdata = (PRUNTIME_FUNCTION)(dllBase + excDir.VirtualAddress); |
| 91 | m.pdataLast = (excDir.Size / sizeof(RUNTIME_FUNCTION)) - 1; |
| 92 | ++count; |
| 93 | } |
| 94 | } |
| 95 | } |
| 96 | } __except (EXCEPTION_EXECUTE_HANDLER) {} |
| 97 | } |
| 98 | ok = Module32NextW(snap, &me); |
| 99 | } |
| 100 | CloseHandle(snap); |
| 101 | std::sort(g_modules, g_modules + count, |
| 102 | [](const CachedModule &a, const CachedModule &b) { return a.base < b.base; }); |
| 103 | g_moduleCount.store(count, std::memory_order_release); |
| 104 | } |
| 105 | |
| 106 | static __declspec(noinline) void ensureCacheReady() noexcept { |
| 107 | if (g_cacheReady.load(std::memory_order_acquire)) return; |
no test coverage detected