Build RE baseline and initial Rust workspace

This commit is contained in:
Jan Petykiewicz 2026-04-02 23:11:15 -07:00
commit ffaf155ef0
39 changed files with 5974 additions and 8 deletions

View file

@ -0,0 +1,9 @@
[package]
name = "rrt-hook"
version.workspace = true
edition.workspace = true
license.workspace = true
[lib]
name = "dinput8"
crate-type = ["cdylib", "rlib"]

170
crates/rrt-hook/src/lib.rs Normal file
View file

@ -0,0 +1,170 @@
#![cfg_attr(not(windows), allow(dead_code))]
#[cfg(windows)]
mod windows_hook {
use core::ffi::{c_char, c_void};
use core::mem;
use core::ptr;
const DLL_PROCESS_ATTACH: u32 = 1;
const E_FAIL: i32 = 0x8000_4005_u32 as i32;
const FILE_APPEND_DATA: u32 = 0x0000_0004;
const FILE_SHARE_READ: u32 = 0x0000_0001;
const OPEN_ALWAYS: u32 = 4;
const FILE_ATTRIBUTE_NORMAL: u32 = 0x0000_0080;
const INVALID_HANDLE_VALUE: isize = -1;
const FILE_END: u32 = 2;
static LOG_PATH: &[u8] = b"rrt_hook_attach.log\0";
static ATTACH_MESSAGE: &[u8] = b"rrt-hook: process attach\n";
static DEBUG_MESSAGE: &[u8] = b"rrt-hook: DllMain process attach\0";
static DIRECT_INPUT8_CREATE_NAME: &[u8] = b"DirectInput8Create\0";
static mut REAL_DINPUT8_CREATE: Option<DirectInput8CreateFn> = None;
unsafe extern "system" {
fn CreateFileA(
lp_file_name: *const c_char,
desired_access: u32,
share_mode: u32,
security_attributes: *mut c_void,
creation_disposition: u32,
flags_and_attributes: u32,
template_file: *mut c_void,
) -> isize;
fn SetFilePointer(
file: isize,
distance: i32,
distance_high: *mut i32,
move_method: u32,
) -> u32;
fn WriteFile(
file: isize,
buffer: *const c_void,
bytes_to_write: u32,
bytes_written: *mut u32,
overlapped: *mut c_void,
) -> i32;
fn CloseHandle(handle: isize) -> i32;
fn DisableThreadLibraryCalls(module: *mut c_void) -> i32;
fn GetSystemDirectoryA(buffer: *mut u8, size: u32) -> u32;
fn GetProcAddress(module: isize, name: *const c_char) -> *mut c_void;
fn LoadLibraryA(name: *const c_char) -> isize;
fn OutputDebugStringA(output: *const c_char);
}
#[repr(C)]
pub struct Guid {
data1: u32,
data2: u16,
data3: u16,
data4: [u8; 8],
}
type DirectInput8CreateFn = unsafe extern "system" fn(
instance: *mut c_void,
version: u32,
riid: *const Guid,
out: *mut *mut c_void,
outer: *mut c_void,
) -> i32;
#[unsafe(no_mangle)]
pub extern "system" fn DllMain(
module: *mut c_void,
reason: u32,
_reserved: *mut c_void,
) -> i32 {
if reason == DLL_PROCESS_ATTACH {
unsafe {
let _ = DisableThreadLibraryCalls(module);
OutputDebugStringA(DEBUG_MESSAGE.as_ptr().cast());
append_attach_log();
}
}
1
}
#[unsafe(no_mangle)]
pub extern "system" fn DirectInput8Create(
instance: *mut c_void,
version: u32,
riid: *const Guid,
out: *mut *mut c_void,
outer: *mut c_void,
) -> i32 {
let direct_input8_create = unsafe { load_direct_input8_create() };
match direct_input8_create {
Some(callback) => unsafe { callback(instance, version, riid, out, outer) },
None => E_FAIL,
}
}
unsafe fn append_attach_log() {
let handle = unsafe {
CreateFileA(
LOG_PATH.as_ptr().cast(),
FILE_APPEND_DATA,
FILE_SHARE_READ,
ptr::null_mut(),
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
ptr::null_mut(),
)
};
if handle == INVALID_HANDLE_VALUE {
return;
}
let _ = unsafe { SetFilePointer(handle, 0, ptr::null_mut(), FILE_END) };
let mut bytes_written = 0_u32;
let _ = unsafe {
WriteFile(
handle,
ATTACH_MESSAGE.as_ptr().cast(),
ATTACH_MESSAGE.len() as u32,
&mut bytes_written,
ptr::null_mut(),
)
};
let _ = unsafe { CloseHandle(handle) };
}
unsafe fn load_direct_input8_create() -> Option<DirectInput8CreateFn> {
if let Some(callback) = unsafe { REAL_DINPUT8_CREATE } {
return Some(callback);
}
let mut system_directory = [0_u8; 260];
let length = unsafe {
GetSystemDirectoryA(system_directory.as_mut_ptr(), system_directory.len() as u32)
};
if length == 0 || length as usize >= system_directory.len() {
return None;
}
let mut dll_path = system_directory[..length as usize].to_vec();
dll_path.extend_from_slice(br"\dinput8.dll");
dll_path.push(0);
let module = unsafe { LoadLibraryA(dll_path.as_ptr().cast()) };
if module == 0 {
return None;
}
let symbol = unsafe { GetProcAddress(module, DIRECT_INPUT8_CREATE_NAME.as_ptr().cast()) };
if symbol.is_null() {
return None;
}
let callback: DirectInput8CreateFn = unsafe { mem::transmute(symbol) };
unsafe {
REAL_DINPUT8_CREATE = Some(callback);
}
Some(callback)
}
}
#[cfg(not(windows))]
pub fn host_build_marker() -> &'static str {
"rrt-hook host build"
}