use open_coroutine_core::net::event_loop::EventLoops;
use retour::static_detour;
use std::error::Error;
use std::os::raw::c_void;
use std::time::Duration;
use std::{ffi::CString, iter, mem};
use windows_sys::Win32::Foundation::BOOL;
use windows_sys::Win32::System::LibraryLoader::{GetModuleHandleW, GetProcAddress};
use windows_sys::Win32::System::SystemServices::DLL_PROCESS_ATTACH;
#[no_mangle]
#[allow(non_snake_case, warnings)]
pub unsafe extern "system" fn DllMain(
_module: *mut c_void,
call_reason: u32,
_reserved: *mut c_void,
) -> BOOL {
if call_reason == DLL_PROCESS_ATTACH {
main().is_ok() as BOOL
} else {
1
}
}
static_detour! {
static SleepHook: unsafe extern "system" fn(u32);
}
type FnSleep = unsafe extern "system" fn(u32);
unsafe fn main() -> Result<(), Box<dyn Error>> {
let address =
get_module_symbol_address("kernel32.dll", "Sleep").expect("could not find 'Sleep' address");
let target: FnSleep = mem::transmute(address);
SleepHook.initialize(target, sleep_detour)?.enable()?;
Ok(())
}
fn get_module_symbol_address(module: &str, symbol: &str) -> Option<usize> {
let module = module
.encode_utf16()
.chain(iter::once(0))
.collect::<Vec<u16>>();
let symbol = CString::new(symbol).unwrap();
unsafe {
let handle = GetModuleHandleW(module.as_ptr());
GetProcAddress(handle, symbol.as_ptr() as _).map(|n| n as usize)
}
}
fn sleep_detour(dw_milliseconds: u32) {
open_coroutine_core::info!("Sleep hooked");
_ = EventLoops::wait_event(Some(Duration::from_millis(u64::from(dw_milliseconds))));
}