Skip to main content

dobby_rs_framework/hook_utils/
mod.rs

1mod builder;
2mod handle;
3mod macros;
4mod registry;
5mod static_hook;
6
7use crate::Result;
8use crate::hook;
9use core::ffi::c_void;
10use core::marker::PhantomData;
11
12pub(crate) type Callback = std::sync::Arc<dyn Fn() + Send + Sync + 'static>;
13pub use builder::HookBuilder;
14pub use handle::{HookHandle, TypedHookHandle};
15pub use static_hook::StaticHook;
16
17unsafe fn fn_to_ptr<F: Copy>(f: F) -> *mut c_void {
18    debug_assert_eq!(
19        core::mem::size_of::<F>(),
20        core::mem::size_of::<*mut c_void>()
21    );
22    let raw: *const () = core::mem::transmute_copy(&f);
23    raw as *mut c_void
24}
25
26pub unsafe fn hook_fn<F: Copy>(target: F, detour: F) -> Result<TypedHookHandle<F>> {
27    let handle = HookBuilder::new(fn_to_ptr(target), fn_to_ptr(detour)).install()?;
28    Ok(TypedHookHandle {
29        inner: handle,
30        _marker: PhantomData,
31    })
32}
33
34pub unsafe fn install<F: Copy>(target: F, detour: F) -> Result<TypedHookHandle<F>> {
35    hook_fn(target, detour)
36}
37
38pub unsafe fn hook_fn_with<F: Copy, B, A>(
39    target: F,
40    detour: F,
41    before: Option<B>,
42    after: Option<A>,
43) -> Result<TypedHookHandle<F>>
44where
45    B: Fn() + Send + Sync + 'static,
46    A: Fn() + Send + Sync + 'static,
47{
48    let mut b = HookBuilder::new(fn_to_ptr(target), fn_to_ptr(detour));
49    if let Some(before) = before {
50        b = b.before(before);
51    }
52    if let Some(after) = after {
53        b = b.after(after);
54    }
55    let handle = b.install()?;
56    Ok(TypedHookHandle {
57        inner: handle,
58        _marker: PhantomData,
59    })
60}
61
62pub fn call_before(detour: *mut c_void) {
63    if let Some(cb) = registry::get_before(detour as usize) {
64        cb();
65    }
66}
67pub fn call_after(detour: *mut c_void) {
68    if let Some(cb) = registry::get_after(detour as usize) {
69        cb();
70    }
71}
72pub unsafe fn original<T: Copy>(detour: *mut c_void) -> Option<T> {
73    let p = registry::get_original(detour as usize)?;
74    debug_assert_eq!(core::mem::size_of::<T>(), core::mem::size_of::<usize>());
75    Some(core::mem::transmute_copy(&p))
76}
77
78pub unsafe fn install_addr(target: *mut c_void, detour: *mut c_void) -> Result<HookHandle> {
79    HookBuilder::new(target, detour).install()
80}
81
82pub(crate) unsafe fn install_raw(
83    target: *mut c_void,
84    detour: *mut c_void,
85    before: Option<Callback>,
86    after: Option<Callback>,
87) -> Result<HookHandle> {
88    let original = hook(target, detour)?;
89    let h = HookHandle {
90        target: target as usize,
91        detour: detour as usize,
92        original: original as usize,
93    };
94    registry::insert(h.target, h.detour, h.original, before, after);
95    Ok(h)
96}