Copy win_delay_load_hook from Neon
This commit is contained in:
parent
b062c0fd6e
commit
e36e1e1fbb
3 changed files with 84 additions and 0 deletions
|
@ -18,6 +18,9 @@ tokio_rt = ["futures", "tokio", "once_cell"]
|
|||
[dependencies]
|
||||
napi-sys = {version = "0.4", path = "../sys"}
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = "0.3.9"
|
||||
|
||||
[dependencies.encoding_rs]
|
||||
optional = true
|
||||
version = "0.8"
|
||||
|
|
|
@ -110,6 +110,8 @@ mod tokio_rt;
|
|||
#[cfg(all(feature = "libuv", napi4))]
|
||||
mod uv;
|
||||
mod version;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod win_delay_load_hook;
|
||||
|
||||
pub use napi_sys as sys;
|
||||
|
||||
|
|
79
napi/src/win_delay_load_hook.rs
Normal file
79
napi/src/win_delay_load_hook.rs
Normal file
|
@ -0,0 +1,79 @@
|
|||
//! The following directly was copied from [neon][].
|
||||
//!
|
||||
//! Rust port of [win_delay_load_hook.cc][].
|
||||
//!
|
||||
//! When the addon tries to load the "node.exe" DLL module, this module gives it the pointer to the
|
||||
//! .exe we are running in instead. Typically, that will be the same value. But if the node executable
|
||||
//! was renamed, you would not otherwise get the correct DLL.
|
||||
//!
|
||||
//! [neon]: https://github.com/neon-bindings/neon/blob/5ffa2d282177b63094c46e92b20b8e850d122e65/src/win_delay_load_hook.rs
|
||||
//! [win_delay_load_hook.cc]: https://github.com/nodejs/node-gyp/blob/e18a61afc1669d4897e6c5c8a6694f4995a0f4d6/src/win_delay_load_hook.cc
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::ptr::null_mut;
|
||||
use winapi::shared::minwindef::{BOOL, DWORD, FARPROC, HMODULE, LPVOID};
|
||||
use winapi::shared::ntdef::LPCSTR;
|
||||
use winapi::um::libloaderapi::GetModuleHandleA;
|
||||
|
||||
// Structures hand-copied from
|
||||
// https://docs.microsoft.com/en-us/cpp/build/reference/structure-and-constant-definitions
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_snake_case)]
|
||||
struct DelayLoadProc {
|
||||
fImportByName: BOOL,
|
||||
// Technically this is `union{LPCSTR; DWORD;}` but we don't access it anyways.
|
||||
szProcName: LPCSTR,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_snake_case)]
|
||||
struct DelayLoadInfo {
|
||||
/// size of structure
|
||||
cb: DWORD,
|
||||
/// raw form of data (everything is there)
|
||||
/// Officially a pointer to ImgDelayDescr but we don't access it.
|
||||
pidd: LPVOID,
|
||||
/// points to address of function to load
|
||||
ppfn: *mut FARPROC,
|
||||
/// name of dll
|
||||
szDll: LPCSTR,
|
||||
/// name or ordinal of procedure
|
||||
dlp: DelayLoadProc,
|
||||
/// the hInstance of the library we have loaded
|
||||
hmodCur: HMODULE,
|
||||
/// the actual function that will be called
|
||||
pfnCur: FARPROC,
|
||||
/// error received (if an error notification)
|
||||
dwLastError: DWORD,
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
type PfnDliHook = unsafe extern "C" fn(dliNotify: usize, pdli: *const DelayLoadInfo) -> FARPROC;
|
||||
|
||||
const HOST_BINARIES: &[&[u8]] = &[b"node.exe", b"electron.exe"];
|
||||
|
||||
unsafe extern "C" fn load_exe_hook(event: usize, info: *const DelayLoadInfo) -> FARPROC {
|
||||
if event != 0x01
|
||||
/* dliNotePreLoadLibrary */
|
||||
{
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let dll_name = CStr::from_ptr((*info).szDll);
|
||||
if !HOST_BINARIES
|
||||
.iter()
|
||||
.any(|&host_name| host_name == dll_name.to_bytes())
|
||||
{
|
||||
return null_mut();
|
||||
}
|
||||
|
||||
let exe_handle = GetModuleHandleA(null_mut());
|
||||
|
||||
// PfnDliHook sometimes has to return a FARPROC, sometimes an HMODULE, but only one
|
||||
// of them could be specified in the header, so we have to cast our HMODULE to that.
|
||||
exe_handle as FARPROC
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
static mut __pfnDliNotifyHook2: *mut PfnDliHook = load_exe_hook as *mut PfnDliHook;
|
Loading…
Reference in a new issue