diff --git a/addon.gypi b/addon.gypi index 0b81fab202..833e95adff 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 it's 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..c77b38efe7 --- /dev/null +++ b/src/win_delay_load_hook.c @@ -0,0 +1,30 @@ +/* + * 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 + +static FARPROC WINAPI DelayLoadHook(unsigned int dliNotify, PDelayLoadInfo pdli) { + if (dliNotify != dliNotePreLoadLibrary) + return NULL; + + if (strcmpi(pdli->szDll, "iojs.exe") != 0 && + strcmpi(pdli->szDll, "node.exe") != 0) + return NULL; + + HMODULE m = GetModuleHandle(NULL); + return (FARPROC) m; +} + +PfnDliHook __pfnDliNotifyHook2 = DelayLoadHook; + +#endif