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();
            }
        });
    }
}
}