paavohtl Claude Opus 4.6 commited on
Commit
21a08ee
·
1 Parent(s): 559d0fd

refactor: add openwa-lib crate with typed WA function wrappers

Browse files

Move rebase + wa_call primitives to shared openwa-lib crate. Add
zero-cost handle types (CWndHandle, CDialogHandle) with methods and
a wa::frontend module that encapsulates inline asm for PaletteAnimation.

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

Cargo.lock CHANGED
@@ -55,6 +55,13 @@ dependencies = [
55
  "windows-sys",
56
  ]
57
 
 
 
 
 
 
 
 
58
  [[package]]
59
  name = "openwa-types"
60
  version = "0.1.0"
@@ -73,6 +80,7 @@ name = "openwa-wormkit"
73
  version = "0.1.0"
74
  dependencies = [
75
  "minhook",
 
76
  "openwa-types",
77
  "windows-sys",
78
  ]
 
55
  "windows-sys",
56
  ]
57
 
58
+ [[package]]
59
+ name = "openwa-lib"
60
+ version = "0.1.0"
61
+ dependencies = [
62
+ "openwa-types",
63
+ ]
64
+
65
  [[package]]
66
  name = "openwa-types"
67
  version = "0.1.0"
 
80
  version = "0.1.0"
81
  dependencies = [
82
  "minhook",
83
+ "openwa-lib",
84
  "openwa-types",
85
  "windows-sys",
86
  ]
crates/openwa-lib/Cargo.toml ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ [package]
2
+ name = "openwa-lib"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ description = "Shared library for calling WA.exe functions with typed wrappers"
6
+
7
+ [dependencies]
8
+ openwa-types = { path = "../openwa-types" }
crates/openwa-lib/src/lib.rs ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ #![allow(non_snake_case)]
2
+
3
+ pub mod rebase;
4
+ pub mod wa;
5
+ pub mod wa_call;
crates/{openwa-wormkit → openwa-lib}/src/rebase.rs RENAMED
File without changes
crates/openwa-lib/src/wa/frontend.rs ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! WA-internal frontend function wrappers.
2
+
3
+ use crate::rebase::rb;
4
+ use openwa_types::address::va;
5
+
6
+ /// Frontend__PaletteAnimation (0x422180)
7
+ ///
8
+ /// `__usercall`: EAX = implicit param (from dialog+0x12c),
9
+ /// 2 stack params: &DAT_007be560 (palette data), palette_param (from dialog+0x134).
10
+ pub unsafe fn palette_animation(eax_value: u32, palette_param: u32) {
11
+ let addr = rb(va::FRONTEND_PALETTE_ANIMATION);
12
+ let data = rb(0x7be560);
13
+ core::arch::asm!(
14
+ "push {param}",
15
+ "push {palette}",
16
+ "call {func}",
17
+ param = in(reg) palette_param,
18
+ palette = in(reg) data,
19
+ func = in(reg) addr,
20
+ in("eax") eax_value,
21
+ clobber_abi("C"),
22
+ );
23
+ }
crates/openwa-lib/src/wa/mfc.rs ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ //! MFC library function wrappers.
2
+
3
+ use crate::wa_call;
4
+
5
+ /// Zero-cost handle to a CWnd-derived MFC window (raw pointer as u32).
6
+ #[derive(Clone, Copy)]
7
+ #[repr(transparent)]
8
+ pub struct CWndHandle(pub u32);
9
+
10
+ impl CWndHandle {
11
+ /// CWnd::EnableWindow (0x5C647A) — thiscall(this, bEnable)
12
+ pub unsafe fn enable_window(&self, enable: bool) {
13
+ wa_call::thiscall_1(0x5C647A, self.0, enable as u32);
14
+ }
15
+ }
16
+
17
+ /// Zero-cost handle to a CDialog-derived MFC dialog.
18
+ #[derive(Clone, Copy)]
19
+ #[repr(transparent)]
20
+ pub struct CDialogHandle(pub u32);
21
+
22
+ impl CDialogHandle {
23
+ /// CDialog::EndDialog (0x5CAB72) — thiscall(this, nResult)
24
+ pub unsafe fn end_dialog(&self, result: u32) {
25
+ wa_call::thiscall_1(0x5CAB72, self.0, result);
26
+ }
27
+ }
28
+
29
+ impl From<CDialogHandle> for CWndHandle {
30
+ fn from(d: CDialogHandle) -> Self {
31
+ CWndHandle(d.0)
32
+ }
33
+ }
crates/openwa-lib/src/wa/mod.rs ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ //! Typed wrappers for calling WA.exe and library functions.
2
+
3
+ pub mod frontend;
4
+ pub mod mfc;
crates/{openwa-wormkit → openwa-lib}/src/wa_call.rs RENAMED
File without changes
crates/openwa-wormkit/Cargo.toml CHANGED
@@ -9,6 +9,7 @@ crate-type = ["cdylib"]
9
 
10
  [dependencies]
11
  openwa-types = { path = "../openwa-types" }
 
12
  minhook = "0.9"
13
 
14
  [target.'cfg(target_os = "windows")'.dependencies]
 
9
 
10
  [dependencies]
11
  openwa-types = { path = "../openwa-types" }
12
+ openwa-lib = { path = "../openwa-lib" }
13
  minhook = "0.9"
14
 
15
  [target.'cfg(target_os = "windows")'.dependencies]
crates/openwa-wormkit/src/hook.rs CHANGED
@@ -60,7 +60,7 @@ use std::ffi::c_void;
60
  use minhook::MinHook;
61
 
62
  use crate::log_line;
63
- use crate::rebase::rb;
64
 
65
  /// Install a MinHook inline hook on a WA.exe function.
66
  ///
 
60
  use minhook::MinHook;
61
 
62
  use crate::log_line;
63
+ use openwa_lib::rebase::rb;
64
 
65
  /// Install a MinHook inline hook on a WA.exe function.
66
  ///
crates/openwa-wormkit/src/lib.rs CHANGED
@@ -3,8 +3,6 @@
3
  use std::ffi::c_void;
4
 
5
  pub mod hook;
6
- pub mod rebase;
7
- pub mod wa_call;
8
  mod replacements;
9
 
10
  // ---------------------------------------------------------------------------
@@ -55,7 +53,7 @@ fn clear_log() -> std::io::Result<()> {
55
  fn run() -> Result<(), String> {
56
  let _ = clear_log();
57
 
58
- let delta = rebase::init();
59
  let _ = log_line(&format!(
60
  "=== OpenWA WormKit DLL loaded ===\n ASLR delta: 0x{delta:08X}"
61
  ));
 
3
  use std::ffi::c_void;
4
 
5
  pub mod hook;
 
 
6
  mod replacements;
7
 
8
  // ---------------------------------------------------------------------------
 
53
  fn run() -> Result<(), String> {
54
  let _ = clear_log();
55
 
56
+ let delta = openwa_lib::rebase::init();
57
  let _ = log_line(&format!(
58
  "=== OpenWA WormKit DLL loaded ===\n ASLR delta: 0x{delta:08X}"
59
  ));
crates/openwa-wormkit/src/replacements/frontend.rs CHANGED
@@ -6,8 +6,8 @@
6
  use std::sync::atomic::{AtomicU32, Ordering};
7
 
8
  use crate::log_line;
9
- use crate::rebase::rb;
10
- use crate::wa_call;
11
  use openwa_types::address::va;
12
  use openwa_types::frontend::ScreenId;
13
 
@@ -36,27 +36,15 @@ unsafe extern "cdecl" fn frontend_change_screen_impl(dialog: u32, screen_id: u32
36
  }
37
  } else {
38
  // Normal path: full screen transition
 
 
39
 
40
- // CWnd::EnableWindow(dialog, FALSE)
41
- wa_call::thiscall_1(0x5C647A, dialog, 0);
42
 
43
- // Frontend__PaletteAnimation(&DAT_007be560, [dialog+0x134])
44
- // Note: original also loads [ESI+0x12c] into EAX before the call.
45
- // We replicate this with inline asm to set EAX as the implicit param.
46
  let palette_param = *((dialog + 0x134) as *const u32);
47
  let eax_value = *((dialog + 0x12c) as *const u32);
48
- let palette_anim_addr = rb(va::FRONTEND_PALETTE_ANIMATION);
49
- let palette_data_addr = rb(0x7be560);
50
- core::arch::asm!(
51
- "push {param}",
52
- "push {palette}",
53
- "call {func}",
54
- param = in(reg) palette_param,
55
- palette = in(reg) palette_data_addr,
56
- func = in(reg) palette_anim_addr,
57
- in("eax") eax_value,
58
- clobber_abi("C"),
59
- );
60
 
61
  // Virtual calls: vtable[0x15C](1) then vtable[0x15C](2)
62
  for i in 1u32..=2 {
@@ -64,11 +52,8 @@ unsafe extern "cdecl" fn frontend_change_screen_impl(dialog: u32, screen_id: u32
64
  wa_call::thiscall_indirect_1(vtable + 0x15C, dialog, i);
65
  }
66
 
67
- // CWnd::EnableWindow(dialog, TRUE)
68
- wa_call::thiscall_1(0x5C647A, dialog, 1);
69
-
70
- // CDialog::EndDialog(dialog, screen_id)
71
- wa_call::thiscall_1(0x5CAB72, dialog, screen_id);
72
  }
73
 
74
  // Log the transition
 
6
  use std::sync::atomic::{AtomicU32, Ordering};
7
 
8
  use crate::log_line;
9
+ use openwa_lib::wa::mfc::{CDialogHandle, CWndHandle};
10
+ use openwa_lib::wa_call;
11
  use openwa_types::address::va;
12
  use openwa_types::frontend::ScreenId;
13
 
 
36
  }
37
  } else {
38
  // Normal path: full screen transition
39
+ let wnd = CWndHandle(dialog);
40
+ let dlg = CDialogHandle(dialog);
41
 
42
+ wnd.enable_window(false);
 
43
 
44
+ // Frontend__PaletteAnimation: EAX = [dialog+0x12c], param = [dialog+0x134]
 
 
45
  let palette_param = *((dialog + 0x134) as *const u32);
46
  let eax_value = *((dialog + 0x12c) as *const u32);
47
+ openwa_lib::wa::frontend::palette_animation(eax_value, palette_param);
 
 
 
 
 
 
 
 
 
 
 
48
 
49
  // Virtual calls: vtable[0x15C](1) then vtable[0x15C](2)
50
  for i in 1u32..=2 {
 
52
  wa_call::thiscall_indirect_1(vtable + 0x15C, dialog, i);
53
  }
54
 
55
+ wnd.enable_window(true);
56
+ dlg.end_dialog(screen_id);
 
 
 
57
  }
58
 
59
  // Log the transition