Skip to main content

install_replace/
install_replace.rs

1//! EN: `install`, `install_with`, `install_addr`, and `replace` helpers.
2//! CN: `install` / `install_with` / `install_addr` / `replace` 四种常用辅助 API。
3
4mod common;
5
6use core::ffi::c_void;
7use dobby_rs_framework::hook_utils;
8use dobby_rs_framework::prelude::*;
9
10#[inline(never)]
11fn detour_mul(x: i32) -> i32 {
12    // EN: Fetch the original function pointer by detour address.
13    // CN: 通过 detour 的地址拿到 original 函数指针。
14    let original = unsafe {
15        hook_utils::original::<fn(i32) -> i32>(detour_mul as *const () as *mut c_void)
16            .expect("original not found")
17    };
18    original(x) + 1
19}
20
21#[inline(never)]
22fn replacement_sub(_x: i32) -> i32 {
23    // EN: A replacement can ignore inputs and return a fixed value.
24    // CN: replace 可以完全忽略输入并返回固定值。
25    123
26}
27
28#[inline(never)]
29fn target_with_callbacks(x: i32) -> i32 {
30    x + 10
31}
32
33#[inline(never)]
34fn detour_with_callbacks(x: i32) -> i32 {
35    // EN: `install_with` stores callbacks, but you decide when to invoke them.
36    // CN: `install_with` 只负责注册回调;何时调用由 detour 自己决定。
37    hook_utils::call_before(detour_with_callbacks as *const () as *mut c_void);
38
39    let original = unsafe {
40        hook_utils::original::<fn(i32) -> i32>(detour_with_callbacks as *const () as *mut c_void)
41            .expect("original not found")
42    };
43    let out = original(x);
44
45    hook_utils::call_after(detour_with_callbacks as *const () as *mut c_void);
46    out
47}
48
49fn main() -> dobby_rs_framework::Result<()> {
50    common::init_example_logging();
51
52    // EN: 1) `install` -> typed handle.
53    // CN: 1) `install` -> 返回带类型的句柄。
54    let h1 = unsafe {
55        install(
56            common::target_mul as fn(i32) -> i32,
57            detour_mul as fn(i32) -> i32,
58        )?
59    };
60    println!("target_mul(3) after install = {}", common::target_mul(3));
61    unsafe { h1.unhook()? };
62
63    // EN: 2) `install_addr` -> raw pointer variant.
64    // CN: 2) `install_addr` -> 按地址安装(裸指针版本)。
65    let h1_addr = unsafe {
66        install_addr(
67            common::target_mul as *const () as *mut c_void,
68            detour_mul as *const () as *mut c_void,
69        )?
70    };
71    println!(
72        "target_mul(3) after install_addr = {}",
73        common::target_mul(3)
74    );
75    unsafe { h1_addr.unhook()? };
76
77    // EN: 3) `replace` -> temporary swap, with easy access to original.
78    // CN: 3) `replace` -> 临时替换,并且可以拿到 original。
79    let r = unsafe {
80        replace(
81            common::target_sub as fn(i32) -> i32,
82            replacement_sub as fn(i32) -> i32,
83        )?
84    };
85    println!("target_sub(10) after replace = {}", common::target_sub(10));
86    println!("original target_sub(10) = {}", (r.original())(10));
87    unsafe { r.unreplace()? };
88
89    // EN: 4) `install_with` -> before/after callbacks (invoked by detour).
90    // CN: 4) `install_with` -> before/after 回调(由 detour 调用)。
91    let h2 = unsafe {
92        install_with(
93            target_with_callbacks as fn(i32) -> i32,
94            detour_with_callbacks as fn(i32) -> i32,
95            Some(|| log::info!("before (install_with)")),
96            Some(|| log::info!("after (install_with)")),
97        )?
98    };
99    println!(
100        "target_with_callbacks(1) after install_with = {}",
101        target_with_callbacks(1)
102    );
103    unsafe { h2.unhook()? };
104
105    Ok(())
106}