diff --git a/Cargo.lock b/Cargo.lock index 346651dc5a..f723f0f756 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1637,6 +1637,9 @@ dependencies = [ "deno_core", "deno_permissions", "libloading 0.7.4", + "minhook", + "widestring", + "winapi", ] [[package]] @@ -4075,6 +4078,16 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minhook" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a48ae87876aaa4622bad562f6565cc1961ab8a3394e45247211f20f110286b5e" +dependencies = [ + "cc", + "tracing", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -6999,6 +7012,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", diff --git a/ext/napi/Cargo.toml b/ext/napi/Cargo.toml index c6f3c76853..b95e91ef6f 100644 --- a/ext/napi/Cargo.toml +++ b/ext/napi/Cargo.toml @@ -17,3 +17,8 @@ path = "lib.rs" deno_core.workspace = true deno_permissions.workspace = true libloading = { version = "0.7" } + +[target.'cfg(windows)'.dependencies] +minhook = "0.5.0" +widestring = "1.1.0" +winapi.workspace = true diff --git a/ext/napi/lib.rs b/ext/napi/lib.rs index 39b303f860..b564bfb341 100644 --- a/ext/napi/lib.rs +++ b/ext/napi/lib.rs @@ -532,7 +532,10 @@ where // SAFETY: opening a DLL calls dlopen #[cfg(not(unix))] - let library = match unsafe { Library::load_with_flags(&path, flags) } { + let library = match unsafe { + install_load_library_hook(); + Library::load_with_flags(&path, flags) + } { Ok(lib) => lib, Err(e) => return Err(type_error(e.to_string())), }; @@ -569,3 +572,46 @@ where Ok(exports) } + +use minhook::MinHook; +use widestring::U16CStr; +use winapi::shared::minwindef::{DWORD, HMODULE, LPVOID}; +use winapi::shared::ntdef::HANDLE; +use winapi::um::libloaderapi::GetModuleHandleW; +use winapi::um::winnt::LPCWSTR; + +type LoadLibraryExWType = + unsafe extern "system" fn(LPCWSTR, HANDLE, DWORD) -> HMODULE; +static ORIGINAL_LOAD_LIBRARY_EX_W: std::sync::OnceLock = + std::sync::OnceLock::new(); + +fn install_load_library_hook() { + ORIGINAL_LOAD_LIBRARY_EX_W.get_or_init(|| unsafe { + let original = MinHook::create_hook_api( + "KernelBase.dll", + "LoadLibraryExW", + load_library_ex_w_hook as LPVOID, + ) + .unwrap(); + MinHook::enable_all_hooks().expect("Failed to enable hooks"); + std::mem::transmute(original) + }); +} + +unsafe extern "system" fn load_library_ex_w_hook( + lib_file_name: LPCWSTR, + file: HANDLE, + flags: DWORD, +) -> HMODULE { + if U16CStr::from_ptr_str(lib_file_name) + .to_string_lossy() + .to_lowercase() + == "node.exe" + { + // Return HMODULE of current process + return GetModuleHandleW(std::ptr::null()); + } + + let original_load_library_ex_w = ORIGINAL_LOAD_LIBRARY_EX_W.get().unwrap(); + original_load_library_ex_w(lib_file_name, file, flags) +}