dfa2c9afc7
The DLL now reads openfut.cfg from its own directory on DLL_PROCESS_ATTACH and uses the IP it contains as the redirect target instead of hardcoding 127.0.0.1. Falls back to 127.0.0.1 if the file is absent. The launcher writes openfut.cfg alongside version.dll when deploying, and the Setup tab exposes a "Redirect IP" field with an "Update" button that rewrites openfut.cfg in-place without redeploying the DLL. Useful when running the emulator on a different machine on the LAN. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
55 lines
1.6 KiB
Rust
55 lines
1.6 KiB
Rust
use std::{ffi::CStr, sync::OnceLock};
|
|
|
|
use windows_sys::Win32::Networking::WinSock::{ADDRINFOA, getaddrinfo as sys_getaddrinfo};
|
|
|
|
const INTERCEPT: &[&str] = &[
|
|
"fut.ea.com",
|
|
"utas.mob.v4.fut.ea.com",
|
|
"utas.s2.fut.ea.com",
|
|
];
|
|
|
|
type GetaddrinfoFn = unsafe extern "system" fn(
|
|
*const u8,
|
|
*const u8,
|
|
*const ADDRINFOA,
|
|
*mut *mut ADDRINFOA,
|
|
) -> i32;
|
|
|
|
static REAL: OnceLock<GetaddrinfoFn> = OnceLock::new();
|
|
// Stored as a NUL-terminated byte string so the hook can pass it to getaddrinfo.
|
|
static REDIRECT_IP: OnceLock<Vec<u8>> = OnceLock::new();
|
|
|
|
pub fn set_real(f: GetaddrinfoFn) {
|
|
let _ = REAL.set(f);
|
|
}
|
|
|
|
pub fn set_redirect_ip(ip: String) {
|
|
let mut bytes = ip.into_bytes();
|
|
bytes.push(0); // NUL-terminate for passing to getaddrinfo
|
|
let _ = REDIRECT_IP.set(bytes);
|
|
}
|
|
|
|
pub unsafe extern "system" fn hooked_getaddrinfo(
|
|
node_name: *const u8,
|
|
service_name: *const u8,
|
|
hints: *const ADDRINFOA,
|
|
result: *mut *mut ADDRINFOA,
|
|
) -> i32 {
|
|
if !node_name.is_null() {
|
|
if let Ok(host) = CStr::from_ptr(node_name as *const i8).to_str() {
|
|
for target in INTERCEPT {
|
|
if host.eq_ignore_ascii_case(target) {
|
|
let redirect = REDIRECT_IP
|
|
.get()
|
|
.map(|v| v.as_ptr())
|
|
.unwrap_or(b"127.0.0.1\0".as_ptr());
|
|
let real = REAL.get().copied().unwrap_or(sys_getaddrinfo);
|
|
return real(redirect, service_name, hints, result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let real = REAL.get().copied().unwrap_or(sys_getaddrinfo);
|
|
real(node_name, service_name, hints, result)
|
|
}
|