还有另一种选择:将 DLL 设置为延迟加载,并使用the delay load DLL import hook 显式加载所需的 DLL。
在解决延迟加载的 DLL 时,通常系统(虽然我不确定哪个部分 - 大概是 CRT?)会发现有一个 plugin.dll 已经加载并分配另一个句柄给它。但是使用延迟加载 DLL 挂钩,您可以使用 LoadLibrary 加载另一个 DLL - 在这种情况下,共享 DLL 的插件特定副本。提供完整路径,因此LoadLibrary 不可能返回现有 DLL 的句柄。
为此,请将 DLL 的 HINSTANCE 存储在 DllMain 中。
static HINSTANCE g_hinstDLL;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_ATTACH)
g_hinstDLL = hinstDLL;
return TRUE;
}
并且有一个合适的延迟加载钩子来监视dliNotePreLoadLibrary。
static FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli) {
if (dliNotify == dliNotePreLoadLibrary) {
if (strcmp(pdli->szDll, "plugin.dll") == 0) {
char path[MAX_PATH];
GetModuleFileNameA(g_hinstDLL, path, sizeof path);
PathRemoveFileSpecA(path);
PathAppendA(path, "plugin.dll");
HMODULE hModule = LoadLibraryA(path);
return (FARPROC)hModule;
}
}
return 0;
}
const PfnDliHook __pfnDliNotifyHook2 = &DliHook;
(最后我不得不放弃整个方法 - lib.dll 似乎认为它只会在每个进程中加载一次,并非不合理,并且在多次加载时会以各种方式与自身发生冲突。可能可以解决原则上,但我希望我只需要为 Linux 和 OS X 再次做同样的事情......)