refactor: add openwa-lib crate with typed WA function wrappers
Browse filesMove 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 +8 -0
- crates/openwa-lib/Cargo.toml +8 -0
- crates/openwa-lib/src/lib.rs +5 -0
- crates/{openwa-wormkit → openwa-lib}/src/rebase.rs +0 -0
- crates/openwa-lib/src/wa/frontend.rs +23 -0
- crates/openwa-lib/src/wa/mfc.rs +33 -0
- crates/openwa-lib/src/wa/mod.rs +4 -0
- crates/{openwa-wormkit → openwa-lib}/src/wa_call.rs +0 -0
- crates/openwa-wormkit/Cargo.toml +1 -0
- crates/openwa-wormkit/src/hook.rs +1 -1
- crates/openwa-wormkit/src/lib.rs +1 -3
- crates/openwa-wormkit/src/replacements/frontend.rs +9 -24
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
|
| 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
|
| 10 |
-
use
|
| 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 |
-
|
| 41 |
-
wa_call::thiscall_1(0x5C647A, dialog, 0);
|
| 42 |
|
| 43 |
-
// Frontend__PaletteAnimation
|
| 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 |
-
|
| 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 |
-
|
| 68 |
-
|
| 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
|