paavohtl Claude Opus 4.6 commited on
Commit
358ced0
·
1 Parent(s): 5bd09aa

refactor: extract hook::install() helper to reduce hook boilerplate

Browse files

Each hook installation was 12-14 lines of repeated MinHook setup.
New hook::install(name, addr, detour) handles create_hook, enable_hook,
and logging, returning the trampoline pointer. Each call site is now
4-5 lines.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

crates/openwa-wormkit/src/hook.rs ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! MinHook helper for installing inline hooks on WA.exe functions.
2
+
3
+ use std::ffi::c_void;
4
+
5
+ use minhook::MinHook;
6
+
7
+ use crate::log_line;
8
+ use crate::rebase::rb;
9
+
10
+ /// Install a MinHook inline hook on a WA.exe function.
11
+ ///
12
+ /// - `name`: human-readable name for log/error messages
13
+ /// - `ghidra_addr`: Ghidra VA of the target function (rebased automatically)
14
+ /// - `detour`: replacement function pointer
15
+ ///
16
+ /// Returns the trampoline pointer (for calling the original).
17
+ /// Caller can store it in an `AtomicU32` if needed, or discard with `let _ =`.
18
+ pub unsafe fn install(
19
+ name: &str,
20
+ ghidra_addr: u32,
21
+ detour: *const (),
22
+ ) -> Result<*mut c_void, String> {
23
+ let target = rb(ghidra_addr) as *mut c_void;
24
+ let detour = detour as *mut c_void;
25
+
26
+ let trampoline = MinHook::create_hook(target, detour)
27
+ .map_err(|e| format!("MinHook create_hook failed for {name}: {e}"))?;
28
+
29
+ MinHook::enable_hook(target)
30
+ .map_err(|e| format!("MinHook enable_hook failed for {name}: {e}"))?;
31
+
32
+ let _ = log_line(&format!(
33
+ " [REPLACE] {name}: target 0x{:08X}, trampoline 0x{:08X}",
34
+ target as u32, trampoline as u32
35
+ ));
36
+
37
+ Ok(trampoline)
38
+ }
crates/openwa-wormkit/src/lib.rs CHANGED
@@ -2,6 +2,7 @@
2
 
3
  use std::ffi::c_void;
4
 
 
5
  pub mod rebase;
6
  pub mod wa_call;
7
  mod replacements;
 
2
 
3
  use std::ffi::c_void;
4
 
5
+ pub mod hook;
6
  pub mod rebase;
7
  pub mod wa_call;
8
  mod replacements;
crates/openwa-wormkit/src/replacements/frontend.rs CHANGED
@@ -3,11 +3,8 @@
3
  //! Original: 0x447A20, stdcall(screen_id), ESI = dialog this (__usercall).
4
  //! Navigates between frontend menu screens via MFC CDialog::EndDialog.
5
 
6
- use std::ffi::c_void;
7
  use std::sync::atomic::{AtomicU32, Ordering};
8
 
9
- use minhook::MinHook;
10
-
11
  use crate::log_line;
12
  use crate::rebase::rb;
13
  use crate::wa_call;
@@ -97,21 +94,12 @@ unsafe extern "cdecl" fn frontend_change_screen_impl(dialog: u32, screen_id: u32
97
 
98
  pub fn install() -> Result<(), String> {
99
  unsafe {
100
- let target = rb(va::FRONTEND_CHANGE_SCREEN) as *mut c_void;
101
- let detour = trampoline as *const () as *mut c_void;
102
-
103
- let trampoline_ptr = MinHook::create_hook(target, detour)
104
- .map_err(|e| format!("MinHook create_hook failed for FrontendChangeScreen: {e}"))?;
105
-
106
- MinHook::enable_hook(target)
107
- .map_err(|e| format!("MinHook enable_hook failed for FrontendChangeScreen: {e}"))?;
108
-
109
  ORIG_FRONTEND_CHANGE_SCREEN.store(trampoline_ptr as u32, Ordering::Relaxed);
110
-
111
- let _ = log_line(&format!(
112
- " [REPLACE] FrontendChangeScreen: target 0x{:08X}, trampoline 0x{:08X}",
113
- target as u32, trampoline_ptr as u32
114
- ));
115
  }
116
 
117
  Ok(())
 
3
  //! Original: 0x447A20, stdcall(screen_id), ESI = dialog this (__usercall).
4
  //! Navigates between frontend menu screens via MFC CDialog::EndDialog.
5
 
 
6
  use std::sync::atomic::{AtomicU32, Ordering};
7
 
 
 
8
  use crate::log_line;
9
  use crate::rebase::rb;
10
  use crate::wa_call;
 
94
 
95
  pub fn install() -> Result<(), String> {
96
  unsafe {
97
+ let trampoline_ptr = crate::hook::install(
98
+ "FrontendChangeScreen",
99
+ va::FRONTEND_CHANGE_SCREEN,
100
+ trampoline as *const (),
101
+ )?;
 
 
 
 
102
  ORIG_FRONTEND_CHANGE_SCREEN.store(trampoline_ptr as u32, Ordering::Relaxed);
 
 
 
 
 
103
  }
104
 
105
  Ok(())
crates/openwa-wormkit/src/replacements/scheme.rs CHANGED
@@ -5,14 +5,11 @@
5
  //! - Scheme__ValidateExtendedOptions (0x4D5110): pure Rust validation
6
  //! - Scheme__FileExists (0x4D4CD0): Rust path check
7
 
8
- use std::ffi::{c_void, CStr};
9
  use std::path::Path;
10
  use std::sync::atomic::{AtomicU32, Ordering};
11
 
12
- use minhook::MinHook;
13
-
14
  use crate::log_line;
15
- use crate::rebase::rb;
16
  use openwa_types::address::va;
17
  use openwa_types::scheme::{
18
  ExtendedOptions, SchemeFile, SchemeVersion, EXTENDED_OPTIONS_DEFAULTS, EXTENDED_OPTIONS_SIZE,
@@ -225,62 +222,24 @@ unsafe extern "stdcall" fn hook_scheme_file_exists(name: u32) -> u32 {
225
 
226
  pub fn install() -> Result<(), String> {
227
  unsafe {
228
- // Hook Scheme__ReadFile (0x4D3890) — full Rust replacement
229
- {
230
- let target = rb(va::SCHEME_READ_FILE) as *mut c_void;
231
- let detour = hook_scheme_read_file as *const () as *mut c_void;
232
-
233
- let trampoline = MinHook::create_hook(target, detour)
234
- .map_err(|e| format!("MinHook create_hook failed for Scheme__ReadFile: {e}"))?;
235
-
236
- MinHook::enable_hook(target)
237
- .map_err(|e| format!("MinHook enable_hook failed for Scheme__ReadFile: {e}"))?;
238
-
239
- ORIG_SCHEME_READ_FILE.store(trampoline as u32, Ordering::Relaxed);
240
-
241
- let _ = log_line(&format!(
242
- " [REPLACE] Scheme__ReadFile: target 0x{:08X}, trampoline 0x{:08X}",
243
- target as u32, trampoline as u32
244
- ));
245
- }
246
-
247
- // Hook Scheme__ValidateExtendedOptions (0x4D5110) — full Rust replacement
248
- {
249
- let target = rb(va::SCHEME_VALIDATE_EXTENDED_OPTIONS) as *mut c_void;
250
- let detour = trampoline_validate_ext_opts as *const () as *mut c_void;
251
-
252
- MinHook::create_hook(target, detour).map_err(|e| {
253
- format!("MinHook create_hook failed for ValidateExtendedOptions: {e}")
254
- })?;
255
-
256
- MinHook::enable_hook(target).map_err(|e| {
257
- format!("MinHook enable_hook failed for ValidateExtendedOptions: {e}")
258
- })?;
259
-
260
- let _ = log_line(&format!(
261
- " [REPLACE] Scheme__ValidateExtendedOptions: target 0x{:08X}",
262
- target as u32
263
- ));
264
- }
265
-
266
- // Hook Scheme__FileExists (0x4D4CD0) — full Rust replacement
267
- {
268
- let target = rb(va::SCHEME_FILE_EXISTS) as *mut c_void;
269
- let detour = hook_scheme_file_exists as *const () as *mut c_void;
270
-
271
- MinHook::create_hook(target, detour).map_err(|e| {
272
- format!("MinHook create_hook failed for Scheme__FileExists: {e}")
273
- })?;
274
-
275
- MinHook::enable_hook(target).map_err(|e| {
276
- format!("MinHook enable_hook failed for Scheme__FileExists: {e}")
277
- })?;
278
-
279
- let _ = log_line(&format!(
280
- " [REPLACE] Scheme__FileExists: target 0x{:08X}",
281
- target as u32
282
- ));
283
- }
284
  }
285
 
286
  Ok(())
 
5
  //! - Scheme__ValidateExtendedOptions (0x4D5110): pure Rust validation
6
  //! - Scheme__FileExists (0x4D4CD0): Rust path check
7
 
8
+ use std::ffi::CStr;
9
  use std::path::Path;
10
  use std::sync::atomic::{AtomicU32, Ordering};
11
 
 
 
12
  use crate::log_line;
 
13
  use openwa_types::address::va;
14
  use openwa_types::scheme::{
15
  ExtendedOptions, SchemeFile, SchemeVersion, EXTENDED_OPTIONS_DEFAULTS, EXTENDED_OPTIONS_SIZE,
 
222
 
223
  pub fn install() -> Result<(), String> {
224
  unsafe {
225
+ let trampoline = crate::hook::install(
226
+ "Scheme__ReadFile",
227
+ va::SCHEME_READ_FILE,
228
+ hook_scheme_read_file as *const (),
229
+ )?;
230
+ ORIG_SCHEME_READ_FILE.store(trampoline as u32, Ordering::Relaxed);
231
+
232
+ let _ = crate::hook::install(
233
+ "Scheme__ValidateExtendedOptions",
234
+ va::SCHEME_VALIDATE_EXTENDED_OPTIONS,
235
+ trampoline_validate_ext_opts as *const (),
236
+ )?;
237
+
238
+ let _ = crate::hook::install(
239
+ "Scheme__FileExists",
240
+ va::SCHEME_FILE_EXISTS,
241
+ hook_scheme_file_exists as *const (),
242
+ )?;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  }
244
 
245
  Ok(())