#[cfg(all(windows, target_arch = "x86"))]
macro_rules! __winlink {
($library:literal $abi:literal $($link_name:literal)? fn $($function:tt)*) => (
#[link(name = $library, kind = "raw-dylib", modifiers = "+verbatim", import_name_type = "undecorated")]
unsafe extern $abi { $(#[link_name=$link_name])? pub fn $($function)*; }
)
}
#[cfg(all(windows, not(target_arch = "x86")))]
macro_rules! __winlink {
($library:literal $abi:literal $($link_name:literal)? fn $($function:tt)*) => (
#[link(name = $library, kind = "raw-dylib", modifiers = "+verbatim")]
unsafe extern $abi { $(#[link_name=$link_name])? pub fn $($function)*; }
)
}
#[inline(never)]
pub fn resolve<T: Sized + Copy>(dll: &str, name: &str) -> Option<T> {
__winlink!("kernel32.dll" "system" fn GetModuleHandleA(lpmodulename: *const u8) -> *mut ::core::ffi::c_void);
__winlink!("kernel32.dll" "system" fn GetProcAddress(hmodule: *mut ::core::ffi::c_void, lpprocname: *const u8) -> *const u8);
__winlink!("kernel32.dll" "system" fn LoadLibraryA(lplibfilename: *const u8) -> *mut ::core::ffi::c_void);
const MAX_LEN: usize = 260;
if dll.len() >= MAX_LEN || name.len() >= MAX_LEN {
return None;
}
let dll_bytes = dll.as_bytes();
let name_bytes = name.as_bytes();
if dll_bytes.contains(&0) || name_bytes.contains(&0) {
return None;
}
let mut dll_buf = [0u8; MAX_LEN];
let mut name_buf = [0u8; MAX_LEN];
dll_buf[..dll.len()].copy_from_slice(dll_bytes);
name_buf[..name.len()].copy_from_slice(name_bytes);
let module = unsafe {
let mut h = GetModuleHandleA(dll_buf.as_ptr());
if h.is_null() {
h = LoadLibraryA(dll_buf.as_ptr());
}
h
};
if module.is_null() {
return None;
}
let proc = unsafe { GetProcAddress(module, name_buf.as_ptr()) };
(!proc.is_null()).then(|| unsafe { ::core::mem::transmute_copy(&proc) })
}