#![allow(non_camel_case_types)]
use std::ffi::{c_char, c_int, c_uint, c_void};
pub(crate) type plthook_t = *const c_void;
extern "C" {
pub(crate) fn plthook_open(object: *mut plthook_t, filename: *const c_char) -> c_int;
pub(crate) fn plthook_open_by_handle(object: *mut plthook_t, handle: *const c_void) -> c_int;
pub(crate) fn plthook_close(object: plthook_t) -> c_void;
#[cfg(not(windows))]
pub(crate) fn plthook_enum_with_prot(
object: plthook_t,
pos: *mut c_uint,
name_out: *mut *const c_char,
addr_out: *mut *const *const c_void,
prot: *mut c_int,
) -> c_int;
pub(crate) fn plthook_replace(
object: plthook_t,
funcname: *const c_char,
funcaddr: *const c_void,
oldfunc: *mut *const c_void,
) -> c_int;
pub(crate) fn plthook_error() -> *const c_char;
}
#[cfg(windows)]
pub(crate) unsafe fn plthook_enum_with_prot(
object: plthook_t,
pos: *mut c_uint,
name_out: *mut *const c_char,
addr_out: *mut *const *const c_void,
_prot: *mut c_int,
) -> c_int {
extern "C" {
fn plthook_enum(
object: plthook_t,
pos: *mut c_uint,
name_out: *mut *const c_char,
addr_out: *mut *const *const c_void,
) -> c_int;
}
plthook_enum(object, pos, name_out, addr_out)
}
pub(crate) mod exts {
use super::plthook_t;
use crate::errors::{Error, ErrorKind, Result};
use std::ffi::{c_char, c_int, CStr};
use std::mem::MaybeUninit;
pub(crate) unsafe fn open_cstr(filename: *const c_char) -> Result<plthook_t> {
let mut c_object = MaybeUninit::uninit();
check(super::plthook_open(c_object.as_mut_ptr(), filename))?;
Ok(c_object.assume_init())
}
#[cfg(windows)]
pub(crate) fn open_path_win32<S>(filename: S) -> Result<plthook_t>
where
S: AsRef<std::ffi::OsStr>,
{
use std::os::windows::ffi::OsStrExt;
use winapi::um::libloaderapi as l;
let mut filename: Vec<u16> = filename.as_ref().encode_wide().collect();
filename.push(0);
let mut handle = MaybeUninit::uninit();
let success = unsafe {
l::GetModuleHandleExW(
l::GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
filename.as_ptr(),
handle.as_mut_ptr(),
)
};
if success == 0 {
return Err(Error::new(ErrorKind::FileNotFound, String::new()));
}
let mut object = MaybeUninit::uninit();
unsafe {
check(super::plthook_open_by_handle(
object.as_mut_ptr(),
handle.assume_init() as *const _,
))?
};
Ok(unsafe { object.assume_init() })
}
pub(crate) fn check(ret: c_int) -> Result<()> {
if ret == 0 {
return Ok(());
}
let msg_ptr = unsafe { CStr::from_ptr(super::plthook_error()) };
let errmsg = msg_ptr.to_string_lossy().into_owned();
Err(Error::new(ErrorKind::from(ret), errmsg))
}
}