fix(launcher): replace registry WA.exe lookup with hardcoded fallback paths
Browse filesSteam registry lookup was unreliable from a 32-bit process (WoW64 redirection
issues, key may not exist). Replace with a short list of hardcoded common Steam
locations; OPENWA_WA_PATH and explicit CLI arg remain the preferred override.
Also add start.ps1 (build + launch) and update start-debug.ps1 to build with
--features openwa-wormkit/debug-ui, which is required to enable the debug UI
overlay at runtime.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Cargo.lock +0 -3
- crates/openwa-launcher/Cargo.toml +0 -8
- crates/openwa-launcher/src/main.rs +12 -79
- start-debug.ps1 +7 -0
- start.ps1 +8 -0
Cargo.lock
CHANGED
|
@@ -1436,9 +1436,6 @@ dependencies = [
|
|
| 1436 |
[[package]]
|
| 1437 |
name = "openwa-launcher"
|
| 1438 |
version = "0.1.0"
|
| 1439 |
-
dependencies = [
|
| 1440 |
-
"windows-sys 0.59.0",
|
| 1441 |
-
]
|
| 1442 |
|
| 1443 |
[[package]]
|
| 1444 |
name = "openwa-wormkit"
|
|
|
|
| 1436 |
[[package]]
|
| 1437 |
name = "openwa-launcher"
|
| 1438 |
version = "0.1.0"
|
|
|
|
|
|
|
|
|
|
| 1439 |
|
| 1440 |
[[package]]
|
| 1441 |
name = "openwa-wormkit"
|
crates/openwa-launcher/Cargo.toml
CHANGED
|
@@ -9,11 +9,3 @@ name = "openwa-launcher"
|
|
| 9 |
path = "src/main.rs"
|
| 10 |
|
| 11 |
[dependencies]
|
| 12 |
-
windows-sys = { version = "0.59", features = [
|
| 13 |
-
"Win32_Foundation",
|
| 14 |
-
"Win32_System_Threading",
|
| 15 |
-
"Win32_System_Memory",
|
| 16 |
-
"Win32_System_LibraryLoader",
|
| 17 |
-
"Win32_System_Registry",
|
| 18 |
-
"Win32_System_Diagnostics_Debug",
|
| 19 |
-
] }
|
|
|
|
| 9 |
path = "src/main.rs"
|
| 10 |
|
| 11 |
[dependencies]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
crates/openwa-launcher/src/main.rs
CHANGED
|
@@ -7,11 +7,9 @@ use std::ptr;
|
|
| 7 |
|
| 8 |
// Declare Win32 types and functions directly to avoid windows-sys feature-flag issues.
|
| 9 |
#[allow(non_camel_case_types)] type HANDLE = *mut core::ffi::c_void;
|
| 10 |
-
#[allow(non_camel_case_types)] type HKEY = *mut core::ffi::c_void;
|
| 11 |
#[allow(non_camel_case_types)] type HMODULE = *mut core::ffi::c_void;
|
| 12 |
#[allow(non_camel_case_types)] type DWORD = u32;
|
| 13 |
#[allow(non_camel_case_types)] type BOOL = i32;
|
| 14 |
-
#[allow(non_camel_case_types)] type LONG = i32;
|
| 15 |
#[allow(non_camel_case_types)] type LPVOID = *mut core::ffi::c_void;
|
| 16 |
#[allow(non_camel_case_types)] type LPDWORD = *mut u32;
|
| 17 |
|
|
@@ -35,10 +33,6 @@ const CREATE_SUSPENDED: DWORD = 0x0000_0004;
|
|
| 35 |
const STARTF_USESHOWWINDOW: DWORD = 0x0000_0001;
|
| 36 |
const SW_SHOWMINIMIZED: u16 = 2;
|
| 37 |
const INFINITE: DWORD = 0xFFFF_FFFF;
|
| 38 |
-
const HKEY_LOCAL_MACHINE: HKEY = -2isize as HKEY;
|
| 39 |
-
const HKEY_CURRENT_USER: HKEY = -1isize as HKEY;
|
| 40 |
-
const KEY_READ: DWORD = 0x2_0019;
|
| 41 |
-
const REG_SZ: DWORD = 1;
|
| 42 |
|
| 43 |
#[link(name = "kernel32")]
|
| 44 |
extern "system" {
|
|
@@ -58,19 +52,6 @@ extern "system" {
|
|
| 58 |
fn GetModuleFileNameA(hModule: HMODULE, lpFilename: *mut u8, nSize: DWORD) -> DWORD;
|
| 59 |
}
|
| 60 |
|
| 61 |
-
#[link(name = "advapi32")]
|
| 62 |
-
extern "system" {
|
| 63 |
-
fn RegOpenKeyExA(
|
| 64 |
-
hKey: HKEY, lpSubKey: *const u8, ulOptions: DWORD,
|
| 65 |
-
samDesired: DWORD, phkResult: *mut HKEY,
|
| 66 |
-
) -> LONG;
|
| 67 |
-
fn RegQueryValueExA(
|
| 68 |
-
hKey: HKEY, lpValueName: *const u8, lpReserved: *const DWORD,
|
| 69 |
-
lpType: *mut DWORD, lpData: *mut u8, lpcbData: *mut DWORD,
|
| 70 |
-
) -> LONG;
|
| 71 |
-
fn RegCloseKey(hKey: HKEY) -> LONG;
|
| 72 |
-
}
|
| 73 |
-
|
| 74 |
fn main() {
|
| 75 |
if let Err(e) = run() {
|
| 76 |
eprintln!("openwa-launcher: error: {e}");
|
|
@@ -96,13 +77,13 @@ fn run() -> Result<(), String> {
|
|
| 96 |
}
|
| 97 |
}
|
| 98 |
|
| 99 |
-
// Locate WA.exe: explicit arg > env var >
|
| 100 |
let wa_exe = if let Some(p) = wa_path_arg {
|
| 101 |
PathBuf::from(p)
|
| 102 |
} else if let Ok(p) = std::env::var("OPENWA_WA_PATH") {
|
| 103 |
PathBuf::from(p)
|
| 104 |
} else {
|
| 105 |
-
|
| 106 |
.ok_or("WA.exe not found. Set OPENWA_WA_PATH or pass the path as an argument.")?
|
| 107 |
};
|
| 108 |
|
|
@@ -239,64 +220,16 @@ fn path_to_cstring(p: &Path) -> Result<CString, String> {
|
|
| 239 |
.map_err(|e| format!("path contains nul byte: {e}"))
|
| 240 |
}
|
| 241 |
|
| 242 |
-
/// Try
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
(
|
| 250 |
-
HKEY_LOCAL_MACHINE,
|
| 251 |
-
b"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 217200\0",
|
| 252 |
-
),
|
| 253 |
-
(
|
| 254 |
-
HKEY_CURRENT_USER,
|
| 255 |
-
b"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App 217200\0",
|
| 256 |
-
),
|
| 257 |
];
|
| 258 |
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
if wa.exists() {
|
| 263 |
-
return Some(wa);
|
| 264 |
-
}
|
| 265 |
-
}
|
| 266 |
-
}
|
| 267 |
-
None
|
| 268 |
-
}
|
| 269 |
-
|
| 270 |
-
fn read_reg_sz(hive: HKEY, subkey: &[u8], value: &[u8]) -> Option<String> {
|
| 271 |
-
unsafe {
|
| 272 |
-
let mut hkey: HKEY = ptr::null_mut();
|
| 273 |
-
let ret = RegOpenKeyExA(hive, subkey.as_ptr(), 0, KEY_READ, &mut hkey);
|
| 274 |
-
if ret != 0 {
|
| 275 |
-
return None;
|
| 276 |
-
}
|
| 277 |
-
|
| 278 |
-
let mut buf = vec![0u8; 4096];
|
| 279 |
-
let mut buf_len = buf.len() as DWORD;
|
| 280 |
-
let mut reg_type: DWORD = 0;
|
| 281 |
-
|
| 282 |
-
let ret = RegQueryValueExA(
|
| 283 |
-
hkey,
|
| 284 |
-
value.as_ptr(),
|
| 285 |
-
ptr::null(),
|
| 286 |
-
&mut reg_type,
|
| 287 |
-
buf.as_mut_ptr(),
|
| 288 |
-
&mut buf_len,
|
| 289 |
-
);
|
| 290 |
-
RegCloseKey(hkey);
|
| 291 |
-
|
| 292 |
-
if ret != 0 || reg_type != REG_SZ {
|
| 293 |
-
return None;
|
| 294 |
-
}
|
| 295 |
-
|
| 296 |
-
let s = std::str::from_utf8(&buf[..buf_len as usize])
|
| 297 |
-
.ok()?
|
| 298 |
-
.trim_end_matches('\0')
|
| 299 |
-
.to_string();
|
| 300 |
-
Some(s)
|
| 301 |
-
}
|
| 302 |
}
|
|
|
|
| 7 |
|
| 8 |
// Declare Win32 types and functions directly to avoid windows-sys feature-flag issues.
|
| 9 |
#[allow(non_camel_case_types)] type HANDLE = *mut core::ffi::c_void;
|
|
|
|
| 10 |
#[allow(non_camel_case_types)] type HMODULE = *mut core::ffi::c_void;
|
| 11 |
#[allow(non_camel_case_types)] type DWORD = u32;
|
| 12 |
#[allow(non_camel_case_types)] type BOOL = i32;
|
|
|
|
| 13 |
#[allow(non_camel_case_types)] type LPVOID = *mut core::ffi::c_void;
|
| 14 |
#[allow(non_camel_case_types)] type LPDWORD = *mut u32;
|
| 15 |
|
|
|
|
| 33 |
const STARTF_USESHOWWINDOW: DWORD = 0x0000_0001;
|
| 34 |
const SW_SHOWMINIMIZED: u16 = 2;
|
| 35 |
const INFINITE: DWORD = 0xFFFF_FFFF;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
#[link(name = "kernel32")]
|
| 38 |
extern "system" {
|
|
|
|
| 52 |
fn GetModuleFileNameA(hModule: HMODULE, lpFilename: *mut u8, nSize: DWORD) -> DWORD;
|
| 53 |
}
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
fn main() {
|
| 56 |
if let Err(e) = run() {
|
| 57 |
eprintln!("openwa-launcher: error: {e}");
|
|
|
|
| 77 |
}
|
| 78 |
}
|
| 79 |
|
| 80 |
+
// Locate WA.exe: explicit arg > env var > hardcoded fallback paths.
|
| 81 |
let wa_exe = if let Some(p) = wa_path_arg {
|
| 82 |
PathBuf::from(p)
|
| 83 |
} else if let Ok(p) = std::env::var("OPENWA_WA_PATH") {
|
| 84 |
PathBuf::from(p)
|
| 85 |
} else {
|
| 86 |
+
find_wa_hardcoded()
|
| 87 |
.ok_or("WA.exe not found. Set OPENWA_WA_PATH or pass the path as an argument.")?
|
| 88 |
};
|
| 89 |
|
|
|
|
| 220 |
.map_err(|e| format!("path contains nul byte: {e}"))
|
| 221 |
}
|
| 222 |
|
| 223 |
+
/// Try a few well-known default Steam install locations for WA.exe.
|
| 224 |
+
/// Users with non-standard library locations should set OPENWA_WA_PATH instead.
|
| 225 |
+
fn find_wa_hardcoded() -> Option<PathBuf> {
|
| 226 |
+
const CANDIDATES: &[&str] = &[
|
| 227 |
+
r"I:\games\SteamLibrary\steamapps\common\Worms Armageddon\WA.exe",
|
| 228 |
+
r"C:\Program Files (x86)\Steam\steamapps\common\Worms Armageddon\WA.exe",
|
| 229 |
+
r"C:\Program Files\Steam\steamapps\common\Worms Armageddon\WA.exe",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 230 |
];
|
| 231 |
|
| 232 |
+
CANDIDATES.iter()
|
| 233 |
+
.map(PathBuf::from)
|
| 234 |
+
.find(|p| p.exists())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
}
|
start-debug.ps1
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
$env:OPENWA_DEBUG_UI = "1"
|
| 2 |
& "target\i686-pc-windows-msvc\release\openwa-launcher.exe"
|
|
|
|
| 1 |
+
# start-debug.ps1 - Build and launch WA.exe with the debug UI overlay
|
| 2 |
+
$ErrorActionPreference = "Stop"
|
| 3 |
+
|
| 4 |
+
Write-Host "Building..." -ForegroundColor Cyan
|
| 5 |
+
cargo build --release -p openwa-launcher -p openwa-wormkit --features openwa-wormkit/debug-ui
|
| 6 |
+
if ($LASTEXITCODE -ne 0) { exit 1 }
|
| 7 |
+
|
| 8 |
$env:OPENWA_DEBUG_UI = "1"
|
| 9 |
& "target\i686-pc-windows-msvc\release\openwa-launcher.exe"
|
start.ps1
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# start.ps1 - Build and launch WA.exe
|
| 2 |
+
$ErrorActionPreference = "Stop"
|
| 3 |
+
|
| 4 |
+
Write-Host "Building..." -ForegroundColor Cyan
|
| 5 |
+
cargo build --release -p openwa-launcher -p openwa-wormkit
|
| 6 |
+
if ($LASTEXITCODE -ne 0) { exit 1 }
|
| 7 |
+
|
| 8 |
+
& "target\i686-pc-windows-msvc\release\openwa-launcher.exe"
|