From 2780c9c5223f4b8f2d3848477f270f925b7f5ed7 Mon Sep 17 00:00:00 2001 From: baldurk Date: Tue, 7 Mar 2017 16:43:15 +0000 Subject: [PATCH] Handle the same dll filename being loaded from multiple places * This happens with atidxx64.dll which gets loaded as a stub and a real thing. If we hook the wrong dll then we might not intercept some calls that go to the real thing. * In particular, LiquidVR tries to use the AMD extensions and if we don't properly block those calls, it will lead to a crash on replay. --- renderdoc/os/win32/win32_hook.cpp | 51 +++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/renderdoc/os/win32/win32_hook.cpp b/renderdoc/os/win32/win32_hook.cpp index c39d2fe8a..0e6ad3218 100644 --- a/renderdoc/os/win32/win32_hook.cpp +++ b/renderdoc/os/win32/win32_hook.cpp @@ -105,6 +105,9 @@ struct DllHookset { DllHookset() : module(NULL), OrdinalBase(0) {} HMODULE module; + // if we have multiple copies of the dll loaded (unlikely), the other module handles will be + // stored here + vector altmodules; vector FunctionHooks; DWORD OrdinalBase; vector OrdinalNames; @@ -208,9 +211,43 @@ struct CachedHookData it->second.module = module; it->second.FetchOrdinalNames(); } - else + else if(it->second.module != module) { - it->second.module = module; + // if it's already in altmodules, bail + bool already = false; + + for(size_t i = 0; i < it->second.altmodules.size(); i++) + { + if(it->second.altmodules[i] == module) + { + already = true; + break; + } + } + + if(already) + break; + + // check if the previous module is still valid + SetLastError(0); + char filename[MAX_PATH] = {}; + GetModuleFileNameA(it->second.module, filename, MAX_PATH - 1); + DWORD err = GetLastError(); + char *slash = strrchr(filename, L'\\'); + + string basename = slash ? strlower(string(slash + 1)) : ""; + + if(err == 0 && basename == it->first) + { + // previous module is still loaded, add this to the alt modules list + it->second.altmodules.push_back(module); + } + else + { + // previous module is no longer loaded or there's a new file there now, add this as the + // new location + it->second.module = module; + } } } } @@ -592,7 +629,15 @@ FARPROC WINAPI Hooked_GetProcAddress(HMODULE mod, LPCSTR func) if(it->second.module == NULL) it->second.module = GetModuleHandleA(it->first.c_str()); - if(mod == it->second.module) + bool match = (mod == it->second.module); + + if(!match && !it->second.altmodules.empty()) + { + for(size_t i = 0; !match && i < it->second.altmodules.size(); i++) + match = (mod == it->second.altmodules[i]); + } + + if(match) { #if ENABLED(VERBOSE_DEBUG_HOOK) RDCDEBUG("Located module %s", it->first.c_str());