dobby_rs_framework/hook_utils/
mod.rs1mod 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}