diff --git a/addon.gypi b/addon.gypi index 3377942421..bda1516d39 100644 --- a/addon.gypi +++ b/addon.gypi @@ -36,16 +36,19 @@ # If the addon specifies `'win_delay_load_hook': 'true'` in its # binding.gyp, link a delay-load hook into the DLL. This hook ensures # that the addon will work regardless of whether the node/iojs binary - # is named node.exe, iojs.exe, or something else. + # is named node.exe, iojs.exe, node.dll or something else. 'conditions': [ [ 'OS=="win"', { 'sources': [ '<(node_gyp_dir)/src/win_delay_load_hook.c', ], + 'libraries': [ + '-lShlwapi.lib' + ], 'msvs_settings': { 'VCLinkerTool': { - 'DelayLoadDLLs': [ 'iojs.exe', 'node.exe' ], - # Don't print a linker warning when no imports from either .exe + 'DelayLoadDLLs': [ 'iojs.exe', 'node.exe', 'node.dll' ], + # Don't print a linker warning when no imports from delay loaded binary # are used. 'AdditionalOptions': [ '/ignore:4199' ], }, diff --git a/src/win_delay_load_hook.c b/src/win_delay_load_hook.c index f397cfa195..ef4823d72e 100644 --- a/src/win_delay_load_hook.c +++ b/src/win_delay_load_hook.c @@ -11,21 +11,48 @@ #define WIN32_LEAN_AND_MEAN #include - +#include #include #include static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) { - HMODULE m; + if (event != dliNotePreLoadLibrary) return NULL; if (_stricmp(info->szDll, "iojs.exe") != 0 && - _stricmp(info->szDll, "node.exe") != 0) + _stricmp(info->szDll, "node.exe") != 0 && + _stricmp(info->szDll, "node.dll") != 0) return NULL; - m = GetModuleHandle(NULL); - return (FARPROC) m; + // Get a handle to the current process executable. + HMODULE processModule = GetModuleHandle(NULL); + + // Get the path to the executable. + TCHAR processPath[_MAX_PATH]; + GetModuleFileName(processModule, processPath, _MAX_PATH); + + // Get the name of the current executable. + LPSTR processName = PathFindFileName(processPath); + + // If the current process is node or iojs, then just return the proccess module. + if (_stricmp(processName, "node.exe") == 0 || + _stricmp(processName, "iojs.exe") == 0) { + return (FARPROC)processModule; + } + + // If it is another process, attempt to load 'node.dll' from the same directory. + PathRemoveFileSpec(processPath); + PathAppend(processPath, "node.dll"); + + HMODULE nodeDllModule = GetModuleHandle(processPath); + if(nodeDllModule != NULL) { + // This application has a node.dll in the same directory as the executable, use that. + return (FARPROC)nodeDllModule; + } + + // Fallback to the current executable, which must statically link to node.lib. + return (FARPROC)processModule; } PfnDliHook __pfnDliNotifyHook2 = load_exe_hook;