diff --git a/addon.gypi b/addon.gypi index 0b81fab202..d6066c16aa 100644 --- a/addon.gypi +++ b/addon.gypi @@ -29,6 +29,9 @@ }, }], [ 'OS=="win"', { + 'sources': [ + 'src/win_delay_load_hook.c', + ], 'libraries': [ '-lkernel32.lib', '-luser32.lib', @@ -47,6 +50,15 @@ # warning C4251: 'node::ObjectWrap::handle_' : class 'v8::Persistent' # needs to have dll-interface to be used by clients of class 'node::ObjectWrap' 'msvs_disabled_warnings': [ 4251 ], + # Set up delay-loading for node.exe/iojs.exe so the loadable module + # will still be able to find its imports if the binary is renamed. + 'msvs_settings': { + 'VCLinkerTool': { + 'DelayLoadDLLs': [ 'iojs.exe', 'node.exe' ], + # Don't print a linker warning when no imports from either .exe are used. + 'AdditionalOptions': [ '/ignore:4199' ], + } + }, }, { # OS!="win" 'defines': [ '_LARGEFILE_SOURCE', '_FILE_OFFSET_BITS=64' ], diff --git a/src/win_delay_load_hook.c b/src/win_delay_load_hook.c new file mode 100644 index 0000000000..05c4c39887 --- /dev/null +++ b/src/win_delay_load_hook.c @@ -0,0 +1,32 @@ +/* + * When this file is linked to a DLL, it sets up a delay-load hook that + * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe' + * dynamically. Instead of trying to locate the .exe file it'll just return + * a handle to the process image. + * + * This allows compiled addons to work when node.exe or iojs.exe is renamed. + */ + +#ifdef _MSC_VER + +#define WIN32_LEAN_AND_MEAN +#include + +#include +#include + +static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) { + if (event != dliNotePreLoadLibrary) + return NULL; + + if (_stricmp(info->szDll, "iojs.exe") != 0 && + _stricmp(info->szDll, "node.exe") != 0) + return NULL; + + HMODULE m = GetModuleHandle(NULL); + return (FARPROC) m; +} + +PfnDliHook __pfnDliNotifyHook2 = load_exe_hook; + +#endif