1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use std::sync::atomic::{AtomicPtr, Ordering};
use std::ops::{Deref, DerefMut};
use std::{mem, ptr};
use error::*;
use {Function, GenericDetour};
#[doc(hidden)]
pub struct __StaticDetourInner<T: Function> {
pub closure: Box<Fn<T::Arguments, Output = T::Output>>,
pub detour: GenericDetour<T>,
}
pub struct StaticDetourController<T: Function> {
inner: &'static AtomicPtr<__StaticDetourInner<T>>,
ffi: T,
}
impl<T: Function> StaticDetourController<T> {
#[doc(hidden)]
pub const fn __new(inner: &'static AtomicPtr<__StaticDetourInner<T>>, ffi: T) -> Self {
StaticDetourController { inner, ffi }
}
pub unsafe fn initialize<C>(&self, target: T, closure: C) -> Result<StaticDetour<T>>
where C: Fn<T::Arguments, Output = T::Output> + Send + 'static {
let mut boxed = Box::new(__StaticDetourInner {
detour: GenericDetour::new(target, self.ffi)?,
closure: Box::new(closure),
});
if !self.inner.compare_and_swap(ptr::null_mut(), &mut *boxed, Ordering::SeqCst).is_null() {
bail!(ErrorKind::AlreadyExisting)
}
mem::forget(boxed);
Ok(StaticDetour(self.inner))
}
pub unsafe fn get(&self) -> Option<&GenericDetour<T>> {
self.inner.load(Ordering::SeqCst).as_ref().map(|i| &i.detour)
}
}
pub struct StaticDetour<T: Function>(&'static AtomicPtr<__StaticDetourInner<T>>);
impl<T: Function> StaticDetour<T> {
pub fn set_detour<C>(&mut self, closure: C)
where C: Fn<T::Arguments, Output = T::Output> + Send + 'static {
let data = unsafe { self.0.load(Ordering::SeqCst).as_mut().unwrap() };
data.closure = Box::new(closure);
}
}
impl<T: Function> Drop for StaticDetour<T> {
fn drop(&mut self) {
let data = self.0.swap(ptr::null_mut(), Ordering::SeqCst);
assert_eq!(data.is_null(), false);
unsafe { Box::from_raw(data) };
}
}
impl<T: Function> Deref for StaticDetour<T> {
type Target = GenericDetour<T>;
fn deref(&self) -> &GenericDetour<T> {
unsafe {
&self.0.load(Ordering::SeqCst).as_ref().unwrap().detour
}
}
}
impl<T: Function> DerefMut for StaticDetour<T> {
fn deref_mut(&mut self) -> &mut GenericDetour<T> {
unsafe {
&mut self.0.load(Ordering::SeqCst).as_mut().unwrap().detour
}
}
}