dobby_rs_framework/hook_utils/
static_hook.rs1use super::{Callback, HookHandle, hook_fn};
2use crate::{Error, Result};
3use core::marker::PhantomData;
4use log::debug;
5use std::sync::{Arc, Mutex};
6
7pub struct StaticHook<F> {
8 handle: Mutex<Option<HookHandle>>,
9 before: Mutex<Option<Callback>>,
10 after: Mutex<Option<Callback>>,
11 _marker: PhantomData<F>,
12}
13
14impl<F: Copy> StaticHook<F> {
15 pub const fn new() -> Self {
16 Self {
17 handle: Mutex::new(None),
18 before: Mutex::new(None),
19 after: Mutex::new(None),
20 _marker: PhantomData,
21 }
22 }
23 pub fn set_before<C: Fn() + Send + Sync + 'static>(&self, cb: C) {
24 *self.before.lock().unwrap() = Some(Arc::new(cb));
25 }
26 pub fn set_after<C: Fn() + Send + Sync + 'static>(&self, cb: C) {
27 *self.after.lock().unwrap() = Some(Arc::new(cb));
28 }
29 pub fn call_before(&self) {
30 debug!("static hook before-callback");
31 if let Some(cb) = self.before.lock().unwrap().clone() {
32 cb();
33 }
34 }
35 pub fn call_after(&self) {
36 debug!("static hook after-callback");
37 if let Some(cb) = self.after.lock().unwrap().clone() {
38 cb();
39 }
40 }
41 pub unsafe fn install(&self, target: F, detour: F) -> Result<()> {
42 let mut s = self.handle.lock().unwrap();
43 if s.is_some() {
44 return Err(Error::AlreadyHooked);
45 }
46 *s = Some(hook_fn(target, detour)?.inner);
47 Ok(())
48 }
49 pub unsafe fn uninstall(&self) -> Result<()> {
50 let h = self
51 .handle
52 .lock()
53 .unwrap()
54 .take()
55 .ok_or(Error::HookNotFound)?;
56 h.unhook()
57 }
58 pub fn original(&self) -> F {
59 unsafe {
60 self.handle
61 .lock()
62 .unwrap()
63 .as_ref()
64 .expect("hook not installed")
65 .original()
66 }
67 }
68}
69
70impl<F: Copy> Default for StaticHook<F> {
71 fn default() -> Self {
72 Self::new()
73 }
74}