Writing the entry point
In order for our code to be executed on injection, we need an
entry point. In Windows, that entails implementing the DllMain
method. We could
roll our own, but hudhook
provides facilities to simplify that to a single
line of code.
The hudhook!
macro takes in the type of the hook we are targeting, and an instance of a struct
that implements the ImguiRenderLoop
trait.
We are targeting a DirectX 12 host application, so the target hook type is ImguiDx12Hooks
.
Our HelloHud
struct already implements ImguiRenderLoop
, so we can
instantiate it and use it as-is:
#![allow(unused)] fn main() { use hudhook::hooks::dx12::ImguiDX12Hooks; hudhook::hudhook!(ImguiDx12Hooks, HelloHud::new()); }
We are finally ready to build our library.
cargo build --release
This will generate a target/release/hello_hud.dll
. We can inject this library directly.
Roll your own DLL entry point
Some times, you may want to perform your own logic inside of the library's entry
point, or use more than one kind of hook. Instead of relying on the entry point
generation macro, you can write your own DllMain
function and use the Hudhook
builder object to build your hooks pipeline:
#![allow(unused)] fn main() { use hudhook::tracing::*; use hudhook::*; #[no_mangle] pub unsafe extern "stdcall" fn DllMain( hmodule: HINSTANCE, reason: u32, _: *mut std::ffi::c_void, ) { if reason == DLL_PROCESS_ATTACH { trace!("DllMain()"); std::thread::spawn(move || { if let Err(e) = Hudhook::builder() .with::<ImguiDx12Hooks>(HelloHud::new()) .with_hmodule(hmodule) .build() .apply() { error!("Couldn't apply hooks: {e:?}"); eject(); } }); } } }