From 3408b6a73112c6abdc3775e289d26f01ba33c90f Mon Sep 17 00:00:00 2001 From: branchseer Date: Sun, 28 Sep 2025 17:17:46 +0800 Subject: [PATCH 01/15] chore: use in-house detours ffi bindings --- .gitmodules | 3 +++ crates/fspy_detours_sys/Cargo.toml | 12 ++++++++++++ crates/fspy_detours_sys/README.md | 3 +++ crates/fspy_detours_sys/detours | 1 + crates/fspy_detours_sys/src/lib.rs | 14 ++++++++++++++ 5 files changed, 33 insertions(+) create mode 100644 .gitmodules create mode 100644 crates/fspy_detours_sys/Cargo.toml create mode 100644 crates/fspy_detours_sys/README.md create mode 160000 crates/fspy_detours_sys/detours create mode 100644 crates/fspy_detours_sys/src/lib.rs diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..ab8b378fe1 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "crates/fspy_detours_sys/detours"] + path = crates/fspy_detours_sys/detours + url = https://github.com/microsoft/Detours diff --git a/crates/fspy_detours_sys/Cargo.toml b/crates/fspy_detours_sys/Cargo.toml new file mode 100644 index 0000000000..cbd234f425 --- /dev/null +++ b/crates/fspy_detours_sys/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "fspy_detours_sys" +version = "0.0.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +rust-version.workspace = true + +[dependencies] + +[lints] +workspace = true diff --git a/crates/fspy_detours_sys/README.md b/crates/fspy_detours_sys/README.md new file mode 100644 index 0000000000..2b7d1dc765 --- /dev/null +++ b/crates/fspy_detours_sys/README.md @@ -0,0 +1,3 @@ +# fspy_detours_sys + +Raw FFI bindings to [Detours](https://github.com/Microsoft/Detours) diff --git a/crates/fspy_detours_sys/detours b/crates/fspy_detours_sys/detours new file mode 160000 index 0000000000..9764cebcb1 --- /dev/null +++ b/crates/fspy_detours_sys/detours @@ -0,0 +1 @@ +Subproject commit 9764cebcb1a75940e68fa83d6730ffaf0f669401 diff --git a/crates/fspy_detours_sys/src/lib.rs b/crates/fspy_detours_sys/src/lib.rs new file mode 100644 index 0000000000..b93cf3ffd9 --- /dev/null +++ b/crates/fspy_detours_sys/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} From c557afd91f83adf4705f55db9aea6461d36cb096 Mon Sep 17 00:00:00 2001 From: branchseer Date: Sun, 28 Sep 2025 23:58:55 +0800 Subject: [PATCH 02/15] init bindgen test --- Cargo.lock | 29 +++++++++++++++- crates/fspy_detours_sys/Cargo.toml | 3 ++ crates/fspy_detours_sys/src/lib.rs | 13 ------- crates/fspy_detours_sys/tests/bindings.rs | 41 +++++++++++++++++++++++ 4 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 crates/fspy_detours_sys/tests/bindings.rs diff --git a/Cargo.lock b/Cargo.lock index f6529b9cd1..5517c763ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -484,6 +484,26 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags 2.9.4", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn 2.0.106", +] + [[package]] name = "bit-set" version = "0.5.3" @@ -1562,6 +1582,13 @@ dependencies = [ "xxhash-rust", ] +[[package]] +name = "fspy_detours_sys" +version = "0.0.0" +dependencies = [ + "bindgen 0.72.1", +] + [[package]] name = "fspy_e2e" version = "0.0.0" @@ -2571,7 +2598,7 @@ version = "4.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "787ffff01b8cccea08858cf318738c6122aa1ca9b20ed6505036fefe466c2029" dependencies = [ - "bindgen", + "bindgen 0.71.1", "cc", "winapi", ] diff --git a/crates/fspy_detours_sys/Cargo.toml b/crates/fspy_detours_sys/Cargo.toml index cbd234f425..9f15cb1a69 100644 --- a/crates/fspy_detours_sys/Cargo.toml +++ b/crates/fspy_detours_sys/Cargo.toml @@ -10,3 +10,6 @@ rust-version.workspace = true [lints] workspace = true + +[dev-dependencies] +bindgen = "0.72.1" diff --git a/crates/fspy_detours_sys/src/lib.rs b/crates/fspy_detours_sys/src/lib.rs index b93cf3ffd9..8b13789179 100644 --- a/crates/fspy_detours_sys/src/lib.rs +++ b/crates/fspy_detours_sys/src/lib.rs @@ -1,14 +1 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right -} -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn it_works() { - let result = add(2, 2); - assert_eq!(result, 4); - } -} diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs new file mode 100644 index 0000000000..7379f10b6a --- /dev/null +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -0,0 +1,41 @@ +#[test] +fn detours_bindings() { + let bindings = bindgen::Builder::default() + .header("detours/src/detours.h") + .clang_args(["-DWIN32_LEAN_AND_MEAN"]) + .allowlist_function("Detour.*") + .blocklist_type("LP.*") + .blocklist_type("_GUID") + .blocklist_type("GUID") + .blocklist_type("ULONG") + .blocklist_type("PVOID") + .blocklist_type("DWORD") + .blocklist_type("wchar_t") + .blocklist_type("BOOL") + .blocklist_type("BYTE") + .blocklist_type("WORD") + .blocklist_type("PBYTE") + .blocklist_type("PDWORD") + .blocklist_type("INT") + .blocklist_type("CHAR") + .blocklist_type("LONG") + .blocklist_type("WCHAR") + .blocklist_type("HANDLE") + .blocklist_type("HMODULE") + .blocklist_type("HINSTANCE.*") + .blocklist_type("HWND.*") + .blocklist_type("_SECURITY_ATTRIBUTES") + .blocklist_type("_PROCESS_INFORMATION") + .blocklist_type("_STARTUPINFOA") + .blocklist_type("_STARTUPINFOW") + .raw_line("use winapi::shared::minwindef::*;") + .raw_line("use winapi::um::winnt::*;") + .raw_line("use winapi::um::winnt::{INT};") + .raw_line("use winapi::um::minwinbase::*;") + .raw_line("use winapi::um::processthreadsapi::*;") + .raw_line("use winapi::shared::guiddef::*;") + .raw_line("use winapi::shared::windef::*;") + .layout_tests(false) + .generate() + .expect("Unable to generate bindings"); +} From cf8ae356b214526ac3dc79fe592e25b435634a78 Mon Sep 17 00:00:00 2001 From: branchseer Date: Sun, 28 Sep 2025 19:38:36 -0700 Subject: [PATCH 03/15] implement bindgen --- Cargo.lock | 1 + crates/fspy_detours_sys/Cargo.toml | 1 + .../src/generated_bindings.rs | 433 ++++++++++++++++++ crates/fspy_detours_sys/src/lib.rs | 4 + crates/fspy_detours_sys/tests/bindings.rs | 22 +- 5 files changed, 459 insertions(+), 2 deletions(-) create mode 100644 crates/fspy_detours_sys/src/generated_bindings.rs diff --git a/Cargo.lock b/Cargo.lock index 5517c763ff..bafbf5f604 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1587,6 +1587,7 @@ name = "fspy_detours_sys" version = "0.0.0" dependencies = [ "bindgen 0.72.1", + "winapi", ] [[package]] diff --git a/crates/fspy_detours_sys/Cargo.toml b/crates/fspy_detours_sys/Cargo.toml index 9f15cb1a69..cfa3a30008 100644 --- a/crates/fspy_detours_sys/Cargo.toml +++ b/crates/fspy_detours_sys/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true rust-version.workspace = true [dependencies] +winapi = { version = "0.3.9", features = ["minwindef", "libloaderapi", "processthreadsapi", "windef"] } [lints] workspace = true diff --git a/crates/fspy_detours_sys/src/generated_bindings.rs b/crates/fspy_detours_sys/src/generated_bindings.rs new file mode 100644 index 0000000000..567db5781e --- /dev/null +++ b/crates/fspy_detours_sys/src/generated_bindings.rs @@ -0,0 +1,433 @@ +use winapi::shared::minwindef::*; +use winapi::um::winnt::*; +use winapi::um::winnt::{INT}; +use winapi::um::minwinbase::*; +use winapi::um::processthreadsapi::*; +use winapi::shared::guiddef::*; +use winapi::shared::windef::*; + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _DETOUR_TRAMPOLINE { + _unused: [u8; 0], +} +pub type PDETOUR_TRAMPOLINE = *mut _DETOUR_TRAMPOLINE; +#[doc = " Binary Typedefs."] +pub type PF_DETOUR_BINARY_BYWAY_CALLBACK = ::std::option::Option< + unsafe extern "C" fn(pContext: PVOID, pszFile: LPCSTR, ppszOutFile: *mut LPCSTR) -> BOOL, +>; +pub type PF_DETOUR_BINARY_FILE_CALLBACK = ::std::option::Option< + unsafe extern "C" fn( + pContext: PVOID, + pszOrigFile: LPCSTR, + pszFile: LPCSTR, + ppszOutFile: *mut LPCSTR, + ) -> BOOL, +>; +pub type PF_DETOUR_BINARY_SYMBOL_CALLBACK = ::std::option::Option< + unsafe extern "C" fn( + pContext: PVOID, + nOrigOrdinal: ULONG, + nOrdinal: ULONG, + pnOutOrdinal: *mut ULONG, + pszOrigSymbol: LPCSTR, + pszSymbol: LPCSTR, + ppszOutSymbol: *mut LPCSTR, + ) -> BOOL, +>; +pub type PF_DETOUR_BINARY_COMMIT_CALLBACK = + ::std::option::Option BOOL>; +pub type PF_DETOUR_ENUMERATE_EXPORT_CALLBACK = ::std::option::Option< + unsafe extern "C" fn(pContext: PVOID, nOrdinal: ULONG, pszName: LPCSTR, pCode: PVOID) -> BOOL, +>; +pub type PF_DETOUR_IMPORT_FILE_CALLBACK = ::std::option::Option< + unsafe extern "C" fn(pContext: PVOID, hModule: HMODULE, pszFile: LPCSTR) -> BOOL, +>; +pub type PF_DETOUR_IMPORT_FUNC_CALLBACK = ::std::option::Option< + unsafe extern "C" fn(pContext: PVOID, nOrdinal: DWORD, pszFunc: LPCSTR, pvFunc: PVOID) -> BOOL, +>; +pub type PF_DETOUR_IMPORT_FUNC_CALLBACK_EX = ::std::option::Option< + unsafe extern "C" fn( + pContext: PVOID, + nOrdinal: DWORD, + pszFunc: LPCSTR, + ppvFunc: *mut PVOID, + ) -> BOOL, +>; +pub type PDETOUR_BINARY = *mut ::std::os::raw::c_void; +unsafe extern "C" { + #[doc = " Transaction APIs."] + pub fn DetourTransactionBegin() -> LONG; +} +unsafe extern "C" { + pub fn DetourTransactionAbort() -> LONG; +} +unsafe extern "C" { + pub fn DetourTransactionCommit() -> LONG; +} +unsafe extern "C" { + pub fn DetourTransactionCommitEx(pppFailedPointer: *mut *mut PVOID) -> LONG; +} +unsafe extern "C" { + pub fn DetourUpdateThread(hThread: HANDLE) -> LONG; +} +unsafe extern "C" { + pub fn DetourAttach(ppPointer: *mut PVOID, pDetour: PVOID) -> LONG; +} +unsafe extern "C" { + pub fn DetourAttachEx( + ppPointer: *mut PVOID, + pDetour: PVOID, + ppRealTrampoline: *mut PDETOUR_TRAMPOLINE, + ppRealTarget: *mut PVOID, + ppRealDetour: *mut PVOID, + ) -> LONG; +} +unsafe extern "C" { + pub fn DetourDetach(ppPointer: *mut PVOID, pDetour: PVOID) -> LONG; +} +unsafe extern "C" { + pub fn DetourSetIgnoreTooSmall(fIgnore: BOOL) -> BOOL; +} +unsafe extern "C" { + pub fn DetourSetRetainRegions(fRetain: BOOL) -> BOOL; +} +unsafe extern "C" { + pub fn DetourSetSystemRegionLowerBound(pSystemRegionLowerBound: PVOID) -> PVOID; +} +unsafe extern "C" { + pub fn DetourSetSystemRegionUpperBound(pSystemRegionUpperBound: PVOID) -> PVOID; +} +unsafe extern "C" { + #[doc = " Code Functions."] + pub fn DetourFindFunction(pszModule: LPCSTR, pszFunction: LPCSTR) -> PVOID; +} +unsafe extern "C" { + pub fn DetourCodeFromPointer(pPointer: PVOID, ppGlobals: *mut PVOID) -> PVOID; +} +unsafe extern "C" { + pub fn DetourCopyInstruction( + pDst: PVOID, + ppDstPool: *mut PVOID, + pSrc: PVOID, + ppTarget: *mut PVOID, + plExtra: *mut LONG, + ) -> PVOID; +} +unsafe extern "C" { + pub fn DetourSetCodeModule(hModule: HMODULE, fLimitReferencesToModule: BOOL) -> BOOL; +} +unsafe extern "C" { + pub fn DetourAllocateRegionWithinJumpBounds( + pbTarget: LPCVOID, + pcbAllocatedSize: PDWORD, + ) -> PVOID; +} +unsafe extern "C" { + pub fn DetourIsFunctionImported(pbCode: PBYTE, pbAddress: PBYTE) -> BOOL; +} +unsafe extern "C" { + #[doc = " Loaded Binary Functions."] + pub fn DetourGetContainingModule(pvAddr: PVOID) -> HMODULE; +} +unsafe extern "C" { + pub fn DetourEnumerateModules(hModuleLast: HMODULE) -> HMODULE; +} +unsafe extern "C" { + pub fn DetourGetEntryPoint(hModule: HMODULE) -> PVOID; +} +unsafe extern "C" { + pub fn DetourGetModuleSize(hModule: HMODULE) -> ULONG; +} +unsafe extern "C" { + pub fn DetourEnumerateExports( + hModule: HMODULE, + pContext: PVOID, + pfExport: PF_DETOUR_ENUMERATE_EXPORT_CALLBACK, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourEnumerateImports( + hModule: HMODULE, + pContext: PVOID, + pfImportFile: PF_DETOUR_IMPORT_FILE_CALLBACK, + pfImportFunc: PF_DETOUR_IMPORT_FUNC_CALLBACK, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourEnumerateImportsEx( + hModule: HMODULE, + pContext: PVOID, + pfImportFile: PF_DETOUR_IMPORT_FILE_CALLBACK, + pfImportFuncEx: PF_DETOUR_IMPORT_FUNC_CALLBACK_EX, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourFindPayload(hModule: HMODULE, rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; +} +unsafe extern "C" { + pub fn DetourFindPayloadEx(rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; +} +unsafe extern "C" { + pub fn DetourGetSizeOfPayloads(hModule: HMODULE) -> DWORD; +} +unsafe extern "C" { + pub fn DetourFreePayload(pvData: PVOID) -> BOOL; +} +unsafe extern "C" { + #[doc = " Persistent Binary Functions."] + pub fn DetourBinaryOpen(hFile: HANDLE) -> PDETOUR_BINARY; +} +unsafe extern "C" { + pub fn DetourBinaryEnumeratePayloads( + pBinary: PDETOUR_BINARY, + pGuid: *mut GUID, + pcbData: *mut DWORD, + pnIterator: *mut DWORD, + ) -> PVOID; +} +unsafe extern "C" { + pub fn DetourBinaryFindPayload( + pBinary: PDETOUR_BINARY, + rguid: *const GUID, + pcbData: *mut DWORD, + ) -> PVOID; +} +unsafe extern "C" { + pub fn DetourBinarySetPayload( + pBinary: PDETOUR_BINARY, + rguid: *const GUID, + pData: PVOID, + cbData: DWORD, + ) -> PVOID; +} +unsafe extern "C" { + pub fn DetourBinaryDeletePayload(pBinary: PDETOUR_BINARY, rguid: *const GUID) -> BOOL; +} +unsafe extern "C" { + pub fn DetourBinaryPurgePayloads(pBinary: PDETOUR_BINARY) -> BOOL; +} +unsafe extern "C" { + pub fn DetourBinaryResetImports(pBinary: PDETOUR_BINARY) -> BOOL; +} +unsafe extern "C" { + pub fn DetourBinaryEditImports( + pBinary: PDETOUR_BINARY, + pContext: PVOID, + pfByway: PF_DETOUR_BINARY_BYWAY_CALLBACK, + pfFile: PF_DETOUR_BINARY_FILE_CALLBACK, + pfSymbol: PF_DETOUR_BINARY_SYMBOL_CALLBACK, + pfCommit: PF_DETOUR_BINARY_COMMIT_CALLBACK, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourBinaryWrite(pBinary: PDETOUR_BINARY, hFile: HANDLE) -> BOOL; +} +unsafe extern "C" { + pub fn DetourBinaryClose(pBinary: PDETOUR_BINARY) -> BOOL; +} +unsafe extern "C" { + #[doc = " Create Process & Load Dll."] + pub fn DetourFindRemotePayload( + hProcess: HANDLE, + rguid: *const GUID, + pcbData: *mut DWORD, + ) -> PVOID; +} +pub type PDETOUR_CREATE_PROCESS_ROUTINEA = ::std::option::Option< + unsafe extern "C" fn( + lpApplicationName: LPCSTR, + lpCommandLine: LPSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCSTR, + lpStartupInfo: LPSTARTUPINFOA, + lpProcessInformation: LPPROCESS_INFORMATION, + ) -> BOOL, +>; +pub type PDETOUR_CREATE_PROCESS_ROUTINEW = ::std::option::Option< + unsafe extern "C" fn( + lpApplicationName: LPCWSTR, + lpCommandLine: LPWSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCWSTR, + lpStartupInfo: LPSTARTUPINFOW, + lpProcessInformation: LPPROCESS_INFORMATION, + ) -> BOOL, +>; +unsafe extern "C" { + pub fn DetourCreateProcessWithDllA( + lpApplicationName: LPCSTR, + lpCommandLine: LPSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCSTR, + lpStartupInfo: LPSTARTUPINFOA, + lpProcessInformation: LPPROCESS_INFORMATION, + lpDllName: LPCSTR, + pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourCreateProcessWithDllW( + lpApplicationName: LPCWSTR, + lpCommandLine: LPWSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCWSTR, + lpStartupInfo: LPSTARTUPINFOW, + lpProcessInformation: LPPROCESS_INFORMATION, + lpDllName: LPCSTR, + pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourCreateProcessWithDllExA( + lpApplicationName: LPCSTR, + lpCommandLine: LPSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCSTR, + lpStartupInfo: LPSTARTUPINFOA, + lpProcessInformation: LPPROCESS_INFORMATION, + lpDllName: LPCSTR, + pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourCreateProcessWithDllExW( + lpApplicationName: LPCWSTR, + lpCommandLine: LPWSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCWSTR, + lpStartupInfo: LPSTARTUPINFOW, + lpProcessInformation: LPPROCESS_INFORMATION, + lpDllName: LPCSTR, + pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourCreateProcessWithDllsA( + lpApplicationName: LPCSTR, + lpCommandLine: LPSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCSTR, + lpStartupInfo: LPSTARTUPINFOA, + lpProcessInformation: LPPROCESS_INFORMATION, + nDlls: DWORD, + rlpDlls: *mut LPCSTR, + pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourCreateProcessWithDllsW( + lpApplicationName: LPCWSTR, + lpCommandLine: LPWSTR, + lpProcessAttributes: LPSECURITY_ATTRIBUTES, + lpThreadAttributes: LPSECURITY_ATTRIBUTES, + bInheritHandles: BOOL, + dwCreationFlags: DWORD, + lpEnvironment: LPVOID, + lpCurrentDirectory: LPCWSTR, + lpStartupInfo: LPSTARTUPINFOW, + lpProcessInformation: LPPROCESS_INFORMATION, + nDlls: DWORD, + rlpDlls: *mut LPCSTR, + pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourProcessViaHelperA( + dwTargetPid: DWORD, + lpDllName: LPCSTR, + pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourProcessViaHelperW( + dwTargetPid: DWORD, + lpDllName: LPCSTR, + pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourProcessViaHelperDllsA( + dwTargetPid: DWORD, + nDlls: DWORD, + rlpDlls: *mut LPCSTR, + pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourProcessViaHelperDllsW( + dwTargetPid: DWORD, + nDlls: DWORD, + rlpDlls: *mut LPCSTR, + pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourUpdateProcessWithDll(hProcess: HANDLE, rlpDlls: *mut LPCSTR, nDlls: DWORD) + -> BOOL; +} +unsafe extern "C" { + pub fn DetourUpdateProcessWithDllEx( + hProcess: HANDLE, + hImage: HMODULE, + bIs32Bit: BOOL, + rlpDlls: *mut LPCSTR, + nDlls: DWORD, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourCopyPayloadToProcess( + hProcess: HANDLE, + rguid: *const GUID, + pvData: LPCVOID, + cbData: DWORD, + ) -> BOOL; +} +unsafe extern "C" { + pub fn DetourCopyPayloadToProcessEx( + hProcess: HANDLE, + rguid: *const GUID, + pvData: LPCVOID, + cbData: DWORD, + ) -> PVOID; +} +unsafe extern "C" { + pub fn DetourRestoreAfterWith() -> BOOL; +} +unsafe extern "C" { + pub fn DetourRestoreAfterWithEx(pvData: PVOID, cbData: DWORD) -> BOOL; +} +unsafe extern "C" { + pub fn DetourIsHelperProcess() -> BOOL; +} +unsafe extern "C" { + pub fn DetourFinishHelperProcess(arg1: HWND, arg2: HINSTANCE, arg3: LPSTR, arg4: INT); +} diff --git a/crates/fspy_detours_sys/src/lib.rs b/crates/fspy_detours_sys/src/lib.rs index 8b13789179..2a7a065aba 100644 --- a/crates/fspy_detours_sys/src/lib.rs +++ b/crates/fspy_detours_sys/src/lib.rs @@ -1 +1,5 @@ +#[allow(non_camel_case_types, non_snake_case)] +mod generated_bindings; + +pub use generated_bindings::*; diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs index 7379f10b6a..4b03585b80 100644 --- a/crates/fspy_detours_sys/tests/bindings.rs +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -1,8 +1,12 @@ +use std::{env, fs}; + #[test] +#[cfg(windows)] fn detours_bindings() { + // https://github.com/0xC9C3/rust-ms-detours/blob/0abc7b11c038afbc2f976de88d44e5691f43bd9a/build.rs#L78 let bindings = bindgen::Builder::default() - .header("detours/src/detours.h") - .clang_args(["-DWIN32_LEAN_AND_MEAN"]) + .clang_args(["-Idetours/src", "-DWIN32_LEAN_AND_MEAN"]) + .header_contents("wrapper.h", "#include \n#include \n") .allowlist_function("Detour.*") .blocklist_type("LP.*") .blocklist_type("_GUID") @@ -28,6 +32,7 @@ fn detours_bindings() { .blocklist_type("_PROCESS_INFORMATION") .blocklist_type("_STARTUPINFOA") .blocklist_type("_STARTUPINFOW") + .disable_header_comment() .raw_line("use winapi::shared::minwindef::*;") .raw_line("use winapi::um::winnt::*;") .raw_line("use winapi::um::winnt::{INT};") @@ -38,4 +43,17 @@ fn detours_bindings() { .layout_tests(false) .generate() .expect("Unable to generate bindings"); + + let bindings_content = bindings.to_string(); + let bindings_path = "src/generated_bindings.rs"; + + if env::var("FSPY_DETOURS_WRITE_BINDINGS") == Ok("1".into()) { + fs::write(bindings_path, bindings_content).unwrap(); + } else { + let existing_bindings_content = fs::read_to_string(bindings_path).unwrap_or_default(); + assert_eq!( + existing_bindings_content, bindings_content, + "Bindings are out of date. Run this test with FSPY_DETOURS_WRITE_BINDINGS=1 to update them." + ); + } } From e930618e4a3d38175e11ae6258ed2f229a06ad46 Mon Sep 17 00:00:00 2001 From: branchseer Date: Sun, 28 Sep 2025 19:46:14 -0700 Subject: [PATCH 04/15] compile detours with cc --- Cargo.lock | 9 +++++---- Cargo.toml | 2 ++ crates/fspy/Cargo.toml | 12 +++++------- crates/fspy_detours_sys/Cargo.toml | 5 ++++- crates/fspy_detours_sys/build.rs | 14 ++++++++++++++ crates/fspy_preload_windows/Cargo.toml | 2 +- crates/fspy_shared/Cargo.toml | 2 +- 7 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 crates/fspy_detours_sys/build.rs diff --git a/Cargo.lock b/Cargo.lock index bafbf5f604..13c57a2f3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -665,9 +665,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.36" +version = "1.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" +checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f" dependencies = [ "find-msvc-tools", "shlex", @@ -1477,9 +1477,9 @@ dependencies = [ [[package]] name = "find-msvc-tools" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" +checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959" [[package]] name = "fixedbitset" @@ -1587,6 +1587,7 @@ name = "fspy_detours_sys" version = "0.0.0" dependencies = [ "bindgen 0.72.1", + "cc", "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 22fd8fa824..12a8488b08 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ backon = "1.3.0" bincode = "2.0.1" brush-parser = "0.2.18" bstr = "1.12.0" +cc = "1.2.39" clap = "4.5.40" color-eyre = "0.6.5" compact_str = "0.9.0" @@ -102,6 +103,7 @@ vite_path = { path = "crates/vite_path" } vite_str = { path = "crates/vite_str" } vite_task = { path = "crates/vite_task" } wax = "0.6.0" +winapi = "0.3.9" napi = { version = "3.0.0", default-features = false, features = ["async", "error_anyhow"] } napi-build = "2" diff --git a/crates/fspy/Cargo.toml b/crates/fspy/Cargo.toml index a7b2e98e9c..21da93d247 100644 --- a/crates/fspy/Cargo.toml +++ b/crates/fspy/Cargo.toml @@ -27,19 +27,17 @@ allocator-api2 = { version = "0.2.21", default-features = false, features = [ tokio-seqpacket = "0.8.0" arrayvec = "0.7.6" nix = { version = "0.30.1", features = ["uio"] } -fspy_seccomp_unotify = { workspace = true, features = ["supervisor"]} -blink-alloc = { version = "0.3.1", features = ["sync"]} +fspy_seccomp_unotify = { workspace = true, features = ["supervisor"] } +blink-alloc = { version = "0.3.1", features = ["sync"] } thread_local = "1.1.9" tokio = { version = "1.44.2", features = ["bytes"] } -syscalls = { version = "0.6.18", default-features = false, features = ["std"]} +syscalls = { version = "0.6.18", default-features = false, features = ["std"] } [target.'cfg(unix)'.dependencies] fspy_shared_unix = { workspace = true } fspy_preload_unix = { workspace = true } nix = { version = "0.30.1", features = ["fs", "process", "socket", "feature"] } -passfd = { git = "https://github.com/polachok/passfd", features = [ - "async", -] } +passfd = { git = "https://github.com/polachok/passfd", features = ["async"] } memmap2 = "0.9.7" # asyncfd = "0.1.2" @@ -55,7 +53,7 @@ const_format = { version = "0.2.34", features = ["fmt"] } [target.'cfg(target_os = "windows")'.dependencies] ms-detours = "4.0.5" winsafe = { version = "0.0.24", features = ["kernel"] } -winapi = { version = "0.3.9", features = [ +winapi = { workspace = true, features = [ "winbase", "securitybaseapi", "handleapi", diff --git a/crates/fspy_detours_sys/Cargo.toml b/crates/fspy_detours_sys/Cargo.toml index cfa3a30008..213397101a 100644 --- a/crates/fspy_detours_sys/Cargo.toml +++ b/crates/fspy_detours_sys/Cargo.toml @@ -6,8 +6,11 @@ edition.workspace = true license.workspace = true rust-version.workspace = true +[build-dependencies] +cc ={ workspace = true } + [dependencies] -winapi = { version = "0.3.9", features = ["minwindef", "libloaderapi", "processthreadsapi", "windef"] } +winapi = { workspace = true, features = ["minwindef", "libloaderapi", "processthreadsapi", "windef"] } [lints] workspace = true diff --git a/crates/fspy_detours_sys/build.rs b/crates/fspy_detours_sys/build.rs new file mode 100644 index 0000000000..fabe872a4d --- /dev/null +++ b/crates/fspy_detours_sys/build.rs @@ -0,0 +1,14 @@ +fn main() { + // https://github.com/Berrysoft/detours/blob/c9bc2ad6e9cd8f5f7b74cfa65365d61ecc45203f/detours-sys/build.rs + cc::Build::new() + .include("detours/src") + .define("WIN32_LEAN_AND_MEAN", "1") + .define("_WIN32_WINNT", "0x501") + .file("detours/src/detours.cpp") + .file("detours/src/modules.cpp") + .file("detours/src/disasm.cpp") + .file("detours/src/image.cpp") + .file("detours/src/creatwth.cpp") + .cpp(true) + .compile("detours"); +} diff --git a/crates/fspy_preload_windows/Cargo.toml b/crates/fspy_preload_windows/Cargo.toml index 7ff64bacef..e8f7bfb41b 100644 --- a/crates/fspy_preload_windows/Cargo.toml +++ b/crates/fspy_preload_windows/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["cdylib"] # windows-sys = { version = "0.59.0", features = ["Win32_Foundation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_Security", "Win32_System_LibraryLoader"] } winsafe = { version = "0.0.24", features = ["kernel"] } ms-detours = "4.0.5" -winapi = { version = "0.3.9", features = [ +winapi = { workspace = true, features = [ "winerror", "winbase", "namedpipeapi", diff --git a/crates/fspy_shared/Cargo.toml b/crates/fspy_shared/Cargo.toml index 179d4d00ef..1e6daa0a5f 100644 --- a/crates/fspy_shared/Cargo.toml +++ b/crates/fspy_shared/Cargo.toml @@ -11,7 +11,7 @@ allocator-api2 = { version = "0.2.21", default-features = false, features = ["st # stable_deref_trait = { version = "1.2.0", optional = true } [target.'cfg(target_os = "windows")'.dependencies] -winapi = { version = "0.3.9", features = ["std"] } +winapi = { workspace = true, features = ["std"] } ms-detours = "4.0.5" bytemuck = { version = "1.23.0", features = ["must_cast", "extern_crate_alloc"] } winsafe = { version = "0.0.24", features = ["kernel"] } From 788c0e60ac42c00c2068b8314ff1aa99215a051f Mon Sep 17 00:00:00 2001 From: branchseer Date: Sun, 28 Sep 2025 23:49:34 -0700 Subject: [PATCH 05/15] replace ms-detours with fspy_detours_sys --- Cargo.lock | 37 +--- Cargo.toml | 1 + crates/fspy/Cargo.toml | 1 - crates/fspy_detours_sys/build.rs | 1 + .../src/generated_bindings.rs | 204 ++++++++++++------ crates/fspy_detours_sys/tests/bindings.rs | 10 +- crates/fspy_preload_windows/Cargo.toml | 2 +- .../src/windows/client.rs | 2 +- .../src/windows/detour.rs | 2 +- .../src/windows/detours/create_process.rs | 2 +- .../fspy_preload_windows/src/windows/mod.rs | 2 +- crates/fspy_shared/Cargo.toml | 1 - 12 files changed, 151 insertions(+), 114 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13c57a2f3e..3a4cb0d58a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -464,26 +464,6 @@ dependencies = [ "virtue", ] -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags 2.9.4", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.106", -] - [[package]] name = "bindgen" version = "0.72.1" @@ -1563,7 +1543,6 @@ dependencies = [ "futures-util", "libc", "memmap2", - "ms-detours", "nix 0.30.1", "ouroboros", "passfd 0.2.0 (git+https://github.com/polachok/passfd)", @@ -1586,7 +1565,7 @@ dependencies = [ name = "fspy_detours_sys" version = "0.0.0" dependencies = [ - "bindgen 0.72.1", + "bindgen", "cc", "winapi", ] @@ -1641,8 +1620,8 @@ dependencies = [ "constcat", "dashmap", "derive-where", + "fspy_detours_sys", "fspy_shared", - "ms-detours", "ntapi", "path-dedot", "ref-cast", @@ -1684,7 +1663,6 @@ dependencies = [ "bytemuck", "derive-where", "libc", - "ms-detours", "nix 0.30.1", "os_str_bytes", "phf", @@ -2594,17 +2572,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "ms-detours" -version = "4.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "787ffff01b8cccea08858cf318738c6122aa1ca9b20ed6505036fefe466c2029" -dependencies = [ - "bindgen 0.71.1", - "cc", - "winapi", -] - [[package]] name = "napi" version = "3.3.0" diff --git a/Cargo.toml b/Cargo.toml index 12a8488b08..ce240eb5e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ directories = "6.0.0" edit = "0.1.5" flate2 = "1.0.35" fspy = { path = "crates/fspy" } +fspy_detours_sys = { path = "crates/fspy_detours_sys" } fspy_preload_unix = { path = "crates/fspy_preload_unix", artifact = "cdylib" } fspy_preload_windows = { path = "crates/fspy_preload_windows", artifact = "cdylib" } fspy_seccomp_unotify = { path = "crates/fspy_seccomp_unotify" } diff --git a/crates/fspy/Cargo.toml b/crates/fspy/Cargo.toml index 21da93d247..b1c7cdb2c8 100644 --- a/crates/fspy/Cargo.toml +++ b/crates/fspy/Cargo.toml @@ -51,7 +51,6 @@ const_format = { version = "0.2.34", features = ["fmt"] } [target.'cfg(target_os = "windows")'.dependencies] -ms-detours = "4.0.5" winsafe = { version = "0.0.24", features = ["kernel"] } winapi = { workspace = true, features = [ "winbase", diff --git a/crates/fspy_detours_sys/build.rs b/crates/fspy_detours_sys/build.rs index fabe872a4d..23b2d33dbe 100644 --- a/crates/fspy_detours_sys/build.rs +++ b/crates/fspy_detours_sys/build.rs @@ -1,4 +1,5 @@ fn main() { + println!("cargo:rerun-if-changed=detours/src"); // https://github.com/Berrysoft/detours/blob/c9bc2ad6e9cd8f5f7b74cfa65365d61ecc45203f/detours-sys/build.rs cc::Build::new() .include("detours/src") diff --git a/crates/fspy_detours_sys/src/generated_bindings.rs b/crates/fspy_detours_sys/src/generated_bindings.rs index 567db5781e..35022125c6 100644 --- a/crates/fspy_detours_sys/src/generated_bindings.rs +++ b/crates/fspy_detours_sys/src/generated_bindings.rs @@ -14,10 +14,10 @@ pub struct _DETOUR_TRAMPOLINE { pub type PDETOUR_TRAMPOLINE = *mut _DETOUR_TRAMPOLINE; #[doc = " Binary Typedefs."] pub type PF_DETOUR_BINARY_BYWAY_CALLBACK = ::std::option::Option< - unsafe extern "C" fn(pContext: PVOID, pszFile: LPCSTR, ppszOutFile: *mut LPCSTR) -> BOOL, + unsafe extern "system" fn(pContext: PVOID, pszFile: LPCSTR, ppszOutFile: *mut LPCSTR) -> BOOL, >; pub type PF_DETOUR_BINARY_FILE_CALLBACK = ::std::option::Option< - unsafe extern "C" fn( + unsafe extern "system" fn( pContext: PVOID, pszOrigFile: LPCSTR, pszFile: LPCSTR, @@ -25,7 +25,7 @@ pub type PF_DETOUR_BINARY_FILE_CALLBACK = ::std::option::Option< ) -> BOOL, >; pub type PF_DETOUR_BINARY_SYMBOL_CALLBACK = ::std::option::Option< - unsafe extern "C" fn( + unsafe extern "system" fn( pContext: PVOID, nOrigOrdinal: ULONG, nOrdinal: ULONG, @@ -36,18 +36,28 @@ pub type PF_DETOUR_BINARY_SYMBOL_CALLBACK = ::std::option::Option< ) -> BOOL, >; pub type PF_DETOUR_BINARY_COMMIT_CALLBACK = - ::std::option::Option BOOL>; + ::std::option::Option BOOL>; pub type PF_DETOUR_ENUMERATE_EXPORT_CALLBACK = ::std::option::Option< - unsafe extern "C" fn(pContext: PVOID, nOrdinal: ULONG, pszName: LPCSTR, pCode: PVOID) -> BOOL, + unsafe extern "system" fn( + pContext: PVOID, + nOrdinal: ULONG, + pszName: LPCSTR, + pCode: PVOID, + ) -> BOOL, >; pub type PF_DETOUR_IMPORT_FILE_CALLBACK = ::std::option::Option< - unsafe extern "C" fn(pContext: PVOID, hModule: HMODULE, pszFile: LPCSTR) -> BOOL, + unsafe extern "system" fn(pContext: PVOID, hModule: HMODULE, pszFile: LPCSTR) -> BOOL, >; pub type PF_DETOUR_IMPORT_FUNC_CALLBACK = ::std::option::Option< - unsafe extern "C" fn(pContext: PVOID, nOrdinal: DWORD, pszFunc: LPCSTR, pvFunc: PVOID) -> BOOL, + unsafe extern "system" fn( + pContext: PVOID, + nOrdinal: DWORD, + pszFunc: LPCSTR, + pvFunc: PVOID, + ) -> BOOL, >; pub type PF_DETOUR_IMPORT_FUNC_CALLBACK_EX = ::std::option::Option< - unsafe extern "C" fn( + unsafe extern "system" fn( pContext: PVOID, nOrdinal: DWORD, pszFunc: LPCSTR, @@ -55,26 +65,33 @@ pub type PF_DETOUR_IMPORT_FUNC_CALLBACK_EX = ::std::option::Option< ) -> BOOL, >; pub type PDETOUR_BINARY = *mut ::std::os::raw::c_void; -unsafe extern "C" { +unsafe extern "system" { #[doc = " Transaction APIs."] + #[link_name = "\u{1}_DetourTransactionBegin@0"] pub fn DetourTransactionBegin() -> LONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourTransactionAbort@0"] pub fn DetourTransactionAbort() -> LONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourTransactionCommit@0"] pub fn DetourTransactionCommit() -> LONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourTransactionCommitEx@4"] pub fn DetourTransactionCommitEx(pppFailedPointer: *mut *mut PVOID) -> LONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourUpdateThread@4"] pub fn DetourUpdateThread(hThread: HANDLE) -> LONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourAttach@8"] pub fn DetourAttach(ppPointer: *mut PVOID, pDetour: PVOID) -> LONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourAttachEx@20"] pub fn DetourAttachEx( ppPointer: *mut PVOID, pDetour: PVOID, @@ -83,29 +100,37 @@ unsafe extern "C" { ppRealDetour: *mut PVOID, ) -> LONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourDetach@8"] pub fn DetourDetach(ppPointer: *mut PVOID, pDetour: PVOID) -> LONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourSetIgnoreTooSmall@4"] pub fn DetourSetIgnoreTooSmall(fIgnore: BOOL) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourSetRetainRegions@4"] pub fn DetourSetRetainRegions(fRetain: BOOL) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourSetSystemRegionLowerBound@4"] pub fn DetourSetSystemRegionLowerBound(pSystemRegionLowerBound: PVOID) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourSetSystemRegionUpperBound@4"] pub fn DetourSetSystemRegionUpperBound(pSystemRegionUpperBound: PVOID) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { #[doc = " Code Functions."] + #[link_name = "\u{1}_DetourFindFunction@8"] pub fn DetourFindFunction(pszModule: LPCSTR, pszFunction: LPCSTR) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCodeFromPointer@8"] pub fn DetourCodeFromPointer(pPointer: PVOID, ppGlobals: *mut PVOID) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCopyInstruction@20"] pub fn DetourCopyInstruction( pDst: PVOID, ppDstPool: *mut PVOID, @@ -114,39 +139,48 @@ unsafe extern "C" { plExtra: *mut LONG, ) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourSetCodeModule@8"] pub fn DetourSetCodeModule(hModule: HMODULE, fLimitReferencesToModule: BOOL) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourAllocateRegionWithinJumpBounds@8"] pub fn DetourAllocateRegionWithinJumpBounds( pbTarget: LPCVOID, pcbAllocatedSize: PDWORD, ) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourIsFunctionImported@8"] pub fn DetourIsFunctionImported(pbCode: PBYTE, pbAddress: PBYTE) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { #[doc = " Loaded Binary Functions."] + #[link_name = "\u{1}_DetourGetContainingModule@4"] pub fn DetourGetContainingModule(pvAddr: PVOID) -> HMODULE; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourEnumerateModules@4"] pub fn DetourEnumerateModules(hModuleLast: HMODULE) -> HMODULE; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourGetEntryPoint@4"] pub fn DetourGetEntryPoint(hModule: HMODULE) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourGetModuleSize@4"] pub fn DetourGetModuleSize(hModule: HMODULE) -> ULONG; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourEnumerateExports@12"] pub fn DetourEnumerateExports( hModule: HMODULE, pContext: PVOID, pfExport: PF_DETOUR_ENUMERATE_EXPORT_CALLBACK, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourEnumerateImports@16"] pub fn DetourEnumerateImports( hModule: HMODULE, pContext: PVOID, @@ -154,7 +188,8 @@ unsafe extern "C" { pfImportFunc: PF_DETOUR_IMPORT_FUNC_CALLBACK, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourEnumerateImportsEx@16"] pub fn DetourEnumerateImportsEx( hModule: HMODULE, pContext: PVOID, @@ -162,23 +197,29 @@ unsafe extern "C" { pfImportFuncEx: PF_DETOUR_IMPORT_FUNC_CALLBACK_EX, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourFindPayload@12"] pub fn DetourFindPayload(hModule: HMODULE, rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourFindPayloadEx@8"] pub fn DetourFindPayloadEx(rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourGetSizeOfPayloads@4"] pub fn DetourGetSizeOfPayloads(hModule: HMODULE) -> DWORD; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourFreePayload@4"] pub fn DetourFreePayload(pvData: PVOID) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { #[doc = " Persistent Binary Functions."] + #[link_name = "\u{1}_DetourBinaryOpen@4"] pub fn DetourBinaryOpen(hFile: HANDLE) -> PDETOUR_BINARY; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinaryEnumeratePayloads@16"] pub fn DetourBinaryEnumeratePayloads( pBinary: PDETOUR_BINARY, pGuid: *mut GUID, @@ -186,14 +227,16 @@ unsafe extern "C" { pnIterator: *mut DWORD, ) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinaryFindPayload@12"] pub fn DetourBinaryFindPayload( pBinary: PDETOUR_BINARY, rguid: *const GUID, pcbData: *mut DWORD, ) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinarySetPayload@16"] pub fn DetourBinarySetPayload( pBinary: PDETOUR_BINARY, rguid: *const GUID, @@ -201,16 +244,20 @@ unsafe extern "C" { cbData: DWORD, ) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinaryDeletePayload@8"] pub fn DetourBinaryDeletePayload(pBinary: PDETOUR_BINARY, rguid: *const GUID) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinaryPurgePayloads@4"] pub fn DetourBinaryPurgePayloads(pBinary: PDETOUR_BINARY) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinaryResetImports@4"] pub fn DetourBinaryResetImports(pBinary: PDETOUR_BINARY) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinaryEditImports@24"] pub fn DetourBinaryEditImports( pBinary: PDETOUR_BINARY, pContext: PVOID, @@ -220,14 +267,17 @@ unsafe extern "C" { pfCommit: PF_DETOUR_BINARY_COMMIT_CALLBACK, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinaryWrite@8"] pub fn DetourBinaryWrite(pBinary: PDETOUR_BINARY, hFile: HANDLE) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourBinaryClose@4"] pub fn DetourBinaryClose(pBinary: PDETOUR_BINARY) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { #[doc = " Create Process & Load Dll."] + #[link_name = "\u{1}_DetourFindRemotePayload@12"] pub fn DetourFindRemotePayload( hProcess: HANDLE, rguid: *const GUID, @@ -235,7 +285,7 @@ unsafe extern "C" { ) -> PVOID; } pub type PDETOUR_CREATE_PROCESS_ROUTINEA = ::std::option::Option< - unsafe extern "C" fn( + unsafe extern "system" fn( lpApplicationName: LPCSTR, lpCommandLine: LPSTR, lpProcessAttributes: LPSECURITY_ATTRIBUTES, @@ -249,7 +299,7 @@ pub type PDETOUR_CREATE_PROCESS_ROUTINEA = ::std::option::Option< ) -> BOOL, >; pub type PDETOUR_CREATE_PROCESS_ROUTINEW = ::std::option::Option< - unsafe extern "C" fn( + unsafe extern "system" fn( lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR, lpProcessAttributes: LPSECURITY_ATTRIBUTES, @@ -262,7 +312,8 @@ pub type PDETOUR_CREATE_PROCESS_ROUTINEW = ::std::option::Option< lpProcessInformation: LPPROCESS_INFORMATION, ) -> BOOL, >; -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCreateProcessWithDllA@48"] pub fn DetourCreateProcessWithDllA( lpApplicationName: LPCSTR, lpCommandLine: LPSTR, @@ -278,7 +329,8 @@ unsafe extern "C" { pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCreateProcessWithDllW@48"] pub fn DetourCreateProcessWithDllW( lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR, @@ -294,7 +346,8 @@ unsafe extern "C" { pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCreateProcessWithDllExA@48"] pub fn DetourCreateProcessWithDllExA( lpApplicationName: LPCSTR, lpCommandLine: LPSTR, @@ -310,7 +363,8 @@ unsafe extern "C" { pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCreateProcessWithDllExW@48"] pub fn DetourCreateProcessWithDllExW( lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR, @@ -326,7 +380,8 @@ unsafe extern "C" { pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCreateProcessWithDllsA@52"] pub fn DetourCreateProcessWithDllsA( lpApplicationName: LPCSTR, lpCommandLine: LPSTR, @@ -343,7 +398,8 @@ unsafe extern "C" { pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCreateProcessWithDllsW@52"] pub fn DetourCreateProcessWithDllsW( lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR, @@ -360,21 +416,24 @@ unsafe extern "C" { pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourProcessViaHelperA@12"] pub fn DetourProcessViaHelperA( dwTargetPid: DWORD, lpDllName: LPCSTR, pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourProcessViaHelperW@12"] pub fn DetourProcessViaHelperW( dwTargetPid: DWORD, lpDllName: LPCSTR, pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourProcessViaHelperDllsA@16"] pub fn DetourProcessViaHelperDllsA( dwTargetPid: DWORD, nDlls: DWORD, @@ -382,7 +441,8 @@ unsafe extern "C" { pfCreateProcessA: PDETOUR_CREATE_PROCESS_ROUTINEA, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourProcessViaHelperDllsW@16"] pub fn DetourProcessViaHelperDllsW( dwTargetPid: DWORD, nDlls: DWORD, @@ -390,11 +450,13 @@ unsafe extern "C" { pfCreateProcessW: PDETOUR_CREATE_PROCESS_ROUTINEW, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourUpdateProcessWithDll@12"] pub fn DetourUpdateProcessWithDll(hProcess: HANDLE, rlpDlls: *mut LPCSTR, nDlls: DWORD) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourUpdateProcessWithDllEx@20"] pub fn DetourUpdateProcessWithDllEx( hProcess: HANDLE, hImage: HMODULE, @@ -403,7 +465,8 @@ unsafe extern "C" { nDlls: DWORD, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCopyPayloadToProcess@16"] pub fn DetourCopyPayloadToProcess( hProcess: HANDLE, rguid: *const GUID, @@ -411,7 +474,8 @@ unsafe extern "C" { cbData: DWORD, ) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourCopyPayloadToProcessEx@16"] pub fn DetourCopyPayloadToProcessEx( hProcess: HANDLE, rguid: *const GUID, @@ -419,15 +483,19 @@ unsafe extern "C" { cbData: DWORD, ) -> PVOID; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourRestoreAfterWith@0"] pub fn DetourRestoreAfterWith() -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourRestoreAfterWithEx@8"] pub fn DetourRestoreAfterWithEx(pvData: PVOID, cbData: DWORD) -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourIsHelperProcess@0"] pub fn DetourIsHelperProcess() -> BOOL; } -unsafe extern "C" { +unsafe extern "system" { + #[link_name = "\u{1}_DetourFinishHelperProcess@16"] pub fn DetourFinishHelperProcess(arg1: HWND, arg2: HINSTANCE, arg3: LPSTR, arg4: INT); } diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs index 4b03585b80..2311a966a4 100644 --- a/crates/fspy_detours_sys/tests/bindings.rs +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -1,11 +1,12 @@ +#![cfg(windows)] + use std::{env, fs}; #[test] -#[cfg(windows)] fn detours_bindings() { // https://github.com/0xC9C3/rust-ms-detours/blob/0abc7b11c038afbc2f976de88d44e5691f43bd9a/build.rs#L78 let bindings = bindgen::Builder::default() - .clang_args(["-Idetours/src", "-DWIN32_LEAN_AND_MEAN"]) + .clang_args(["-Idetours/src", "-DWIN32_LEAN_AND_MEAN", "-target", "i686-pc-windows-msvc"]) .header_contents("wrapper.h", "#include \n#include \n") .allowlist_function("Detour.*") .blocklist_type("LP.*") @@ -41,13 +42,14 @@ fn detours_bindings() { .raw_line("use winapi::shared::guiddef::*;") .raw_line("use winapi::shared::windef::*;") .layout_tests(false) + // Detour functions are stdcall on 32-bit Windows + .override_abi(bindgen::Abi::System, ".*") .generate() .expect("Unable to generate bindings"); - let bindings_content = bindings.to_string(); let bindings_path = "src/generated_bindings.rs"; - if env::var("FSPY_DETOURS_WRITE_BINDINGS") == Ok("1".into()) { + if env::var("FSPY_DETOURS_WRITE_BINDINGS").as_deref() == Ok("1") { fs::write(bindings_path, bindings_content).unwrap(); } else { let existing_bindings_content = fs::read_to_string(bindings_path).unwrap_or_default(); diff --git a/crates/fspy_preload_windows/Cargo.toml b/crates/fspy_preload_windows/Cargo.toml index e8f7bfb41b..4023c3df3d 100644 --- a/crates/fspy_preload_windows/Cargo.toml +++ b/crates/fspy_preload_windows/Cargo.toml @@ -9,7 +9,6 @@ crate-type = ["cdylib"] [target.'cfg(target_os = "windows")'.dependencies] # windows-sys = { version = "0.59.0", features = ["Win32_Foundation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_Security", "Win32_System_LibraryLoader"] } winsafe = { version = "0.0.24", features = ["kernel"] } -ms-detours = "4.0.5" winapi = { workspace = true, features = [ "winerror", "winbase", @@ -29,6 +28,7 @@ path-dedot = "3.1.1" ref-cast = "1.0.24" which = "7.0.3" fspy_shared = { workspace = true } +fspy_detours_sys = { workspace = true } ntapi = "0.4.1" diff --git a/crates/fspy_preload_windows/src/windows/client.rs b/crates/fspy_preload_windows/src/windows/client.rs index 1e3699e51a..955fd056df 100644 --- a/crates/fspy_preload_windows/src/windows/client.rs +++ b/crates/fspy_preload_windows/src/windows/client.rs @@ -11,7 +11,7 @@ use fspy_shared::{ ipc::{BINCODE_CONFIG, PathAccess}, windows::{PAYLOAD_ID, Payload}, }; -use ms_detours::DetourCopyPayloadToProcess; +use fspy_detours_sys::DetourCopyPayloadToProcess; use ntapi::ntobapi::DUPLICATE_SAME_ACCESS; use smallvec::SmallVec; use winapi::{ diff --git a/crates/fspy_preload_windows/src/windows/detour.rs b/crates/fspy_preload_windows/src/windows/detour.rs index 75a05ab0fb..0b8a2ddc40 100644 --- a/crates/fspy_preload_windows/src/windows/detour.rs +++ b/crates/fspy_preload_windows/src/windows/detour.rs @@ -1,6 +1,6 @@ use std::{cell::UnsafeCell, ffi::CStr, mem::transmute_copy, os::raw::c_void, ptr::null_mut}; -use ms_detours::{DetourAttach, DetourDetach}; +use fspy_detours_sys::{DetourAttach, DetourDetach}; use winapi::{ shared::minwindef::HMODULE, um::libloaderapi::{GetProcAddress, LoadLibraryA}, diff --git a/crates/fspy_preload_windows/src/windows/detours/create_process.rs b/crates/fspy_preload_windows/src/windows/detours/create_process.rs index e0cfcb89ce..d5b4c4b3dd 100644 --- a/crates/fspy_preload_windows/src/windows/detours/create_process.rs +++ b/crates/fspy_preload_windows/src/windows/detours/create_process.rs @@ -1,7 +1,7 @@ use std::ffi::CStr; use fspy_shared::ipc::{AccessMode, NativeStr, PathAccess}; -use ms_detours::{DetourCreateProcessWithDllExA, DetourCreateProcessWithDllExW}; +use fspy_detours_sys::{DetourCreateProcessWithDllExA, DetourCreateProcessWithDllExW}; use widestring::U16CStr; use winapi::{ shared::{ diff --git a/crates/fspy_preload_windows/src/windows/mod.rs b/crates/fspy_preload_windows/src/windows/mod.rs index 4b82217f15..37303de4df 100644 --- a/crates/fspy_preload_windows/src/windows/mod.rs +++ b/crates/fspy_preload_windows/src/windows/mod.rs @@ -9,7 +9,7 @@ use std::slice; use client::{Client, set_global_client}; use detours::DETOURS; use fspy_shared::windows::PAYLOAD_ID; -use ms_detours::{ +use fspy_detours_sys::{ DetourFindPayloadEx, DetourIsHelperProcess, DetourRestoreAfterWith, DetourTransactionBegin, DetourTransactionCommit, DetourUpdateThread, }; diff --git a/crates/fspy_shared/Cargo.toml b/crates/fspy_shared/Cargo.toml index 1e6daa0a5f..1fa383f34e 100644 --- a/crates/fspy_shared/Cargo.toml +++ b/crates/fspy_shared/Cargo.toml @@ -12,7 +12,6 @@ allocator-api2 = { version = "0.2.21", default-features = false, features = ["st [target.'cfg(target_os = "windows")'.dependencies] winapi = { workspace = true, features = ["std"] } -ms-detours = "4.0.5" bytemuck = { version = "1.23.0", features = ["must_cast", "extern_crate_alloc"] } winsafe = { version = "0.0.24", features = ["kernel"] } os_str_bytes = { workspace = true } From e65bf0886af69bdbf50e15e248f7a5e9d7ddf82b Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 00:53:53 -0700 Subject: [PATCH 06/15] fix link error --- Cargo.lock | 1 + crates/fspy/Cargo.toml | 1 + crates/fspy/src/windows/mod.rs | 2 +- crates/fspy_detours_sys/build.rs | 3 + .../src/generated_bindings.rs | 58 ------------------- crates/fspy_detours_sys/src/lib.rs | 3 +- crates/fspy_detours_sys/tests/bindings.rs | 3 +- 7 files changed, 9 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a4cb0d58a..3ee7838b93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1535,6 +1535,7 @@ dependencies = [ "csv-async", "ctor 0.4.3", "flate2", + "fspy_detours_sys", "fspy_preload_unix", "fspy_preload_windows", "fspy_seccomp_unotify", diff --git a/crates/fspy/Cargo.toml b/crates/fspy/Cargo.toml index b1c7cdb2c8..bfa2c7c284 100644 --- a/crates/fspy/Cargo.toml +++ b/crates/fspy/Cargo.toml @@ -58,6 +58,7 @@ winapi = { workspace = true, features = [ "handleapi", ] } fspy_preload_windows = { workspace = true } +fspy_detours_sys = { workspace = true } [target.'cfg(target_os = "macos")'.dev-dependencies] tempfile = "3.19.1" diff --git a/crates/fspy/src/windows/mod.rs b/crates/fspy/src/windows/mod.rs index 8a2af19190..83bd42ede2 100644 --- a/crates/fspy/src/windows/mod.rs +++ b/crates/fspy/src/windows/mod.rs @@ -15,7 +15,7 @@ use fspy_shared::{ windows::{PAYLOAD_ID, Payload}, }; use futures_util::FutureExt; -use ms_detours::{DetourCopyPayloadToProcess, DetourUpdateProcessWithDll}; +use fspy_detours_sys::{DetourCopyPayloadToProcess, DetourUpdateProcessWithDll}; use tokio::{ io::AsyncReadExt, net::windows::named_pipe::{PipeMode, ServerOptions}, diff --git a/crates/fspy_detours_sys/build.rs b/crates/fspy_detours_sys/build.rs index 23b2d33dbe..121aac5525 100644 --- a/crates/fspy_detours_sys/build.rs +++ b/crates/fspy_detours_sys/build.rs @@ -1,4 +1,7 @@ fn main() { + if std::env::var_os("CARGO_CFG_TARGET_OS").unwrap() != "windows" { + return; + } println!("cargo:rerun-if-changed=detours/src"); // https://github.com/Berrysoft/detours/blob/c9bc2ad6e9cd8f5f7b74cfa65365d61ecc45203f/detours-sys/build.rs cc::Build::new() diff --git a/crates/fspy_detours_sys/src/generated_bindings.rs b/crates/fspy_detours_sys/src/generated_bindings.rs index 35022125c6..eeeb4997b1 100644 --- a/crates/fspy_detours_sys/src/generated_bindings.rs +++ b/crates/fspy_detours_sys/src/generated_bindings.rs @@ -67,31 +67,24 @@ pub type PF_DETOUR_IMPORT_FUNC_CALLBACK_EX = ::std::option::Option< pub type PDETOUR_BINARY = *mut ::std::os::raw::c_void; unsafe extern "system" { #[doc = " Transaction APIs."] - #[link_name = "\u{1}_DetourTransactionBegin@0"] pub fn DetourTransactionBegin() -> LONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourTransactionAbort@0"] pub fn DetourTransactionAbort() -> LONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourTransactionCommit@0"] pub fn DetourTransactionCommit() -> LONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourTransactionCommitEx@4"] pub fn DetourTransactionCommitEx(pppFailedPointer: *mut *mut PVOID) -> LONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourUpdateThread@4"] pub fn DetourUpdateThread(hThread: HANDLE) -> LONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourAttach@8"] pub fn DetourAttach(ppPointer: *mut PVOID, pDetour: PVOID) -> LONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourAttachEx@20"] pub fn DetourAttachEx( ppPointer: *mut PVOID, pDetour: PVOID, @@ -101,36 +94,28 @@ unsafe extern "system" { ) -> LONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourDetach@8"] pub fn DetourDetach(ppPointer: *mut PVOID, pDetour: PVOID) -> LONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourSetIgnoreTooSmall@4"] pub fn DetourSetIgnoreTooSmall(fIgnore: BOOL) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourSetRetainRegions@4"] pub fn DetourSetRetainRegions(fRetain: BOOL) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourSetSystemRegionLowerBound@4"] pub fn DetourSetSystemRegionLowerBound(pSystemRegionLowerBound: PVOID) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourSetSystemRegionUpperBound@4"] pub fn DetourSetSystemRegionUpperBound(pSystemRegionUpperBound: PVOID) -> PVOID; } unsafe extern "system" { #[doc = " Code Functions."] - #[link_name = "\u{1}_DetourFindFunction@8"] pub fn DetourFindFunction(pszModule: LPCSTR, pszFunction: LPCSTR) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCodeFromPointer@8"] pub fn DetourCodeFromPointer(pPointer: PVOID, ppGlobals: *mut PVOID) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCopyInstruction@20"] pub fn DetourCopyInstruction( pDst: PVOID, ppDstPool: *mut PVOID, @@ -140,39 +125,31 @@ unsafe extern "system" { ) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourSetCodeModule@8"] pub fn DetourSetCodeModule(hModule: HMODULE, fLimitReferencesToModule: BOOL) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourAllocateRegionWithinJumpBounds@8"] pub fn DetourAllocateRegionWithinJumpBounds( pbTarget: LPCVOID, pcbAllocatedSize: PDWORD, ) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourIsFunctionImported@8"] pub fn DetourIsFunctionImported(pbCode: PBYTE, pbAddress: PBYTE) -> BOOL; } unsafe extern "system" { #[doc = " Loaded Binary Functions."] - #[link_name = "\u{1}_DetourGetContainingModule@4"] pub fn DetourGetContainingModule(pvAddr: PVOID) -> HMODULE; } unsafe extern "system" { - #[link_name = "\u{1}_DetourEnumerateModules@4"] pub fn DetourEnumerateModules(hModuleLast: HMODULE) -> HMODULE; } unsafe extern "system" { - #[link_name = "\u{1}_DetourGetEntryPoint@4"] pub fn DetourGetEntryPoint(hModule: HMODULE) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourGetModuleSize@4"] pub fn DetourGetModuleSize(hModule: HMODULE) -> ULONG; } unsafe extern "system" { - #[link_name = "\u{1}_DetourEnumerateExports@12"] pub fn DetourEnumerateExports( hModule: HMODULE, pContext: PVOID, @@ -180,7 +157,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourEnumerateImports@16"] pub fn DetourEnumerateImports( hModule: HMODULE, pContext: PVOID, @@ -189,7 +165,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourEnumerateImportsEx@16"] pub fn DetourEnumerateImportsEx( hModule: HMODULE, pContext: PVOID, @@ -198,28 +173,22 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourFindPayload@12"] pub fn DetourFindPayload(hModule: HMODULE, rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourFindPayloadEx@8"] pub fn DetourFindPayloadEx(rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourGetSizeOfPayloads@4"] pub fn DetourGetSizeOfPayloads(hModule: HMODULE) -> DWORD; } unsafe extern "system" { - #[link_name = "\u{1}_DetourFreePayload@4"] pub fn DetourFreePayload(pvData: PVOID) -> BOOL; } unsafe extern "system" { #[doc = " Persistent Binary Functions."] - #[link_name = "\u{1}_DetourBinaryOpen@4"] pub fn DetourBinaryOpen(hFile: HANDLE) -> PDETOUR_BINARY; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinaryEnumeratePayloads@16"] pub fn DetourBinaryEnumeratePayloads( pBinary: PDETOUR_BINARY, pGuid: *mut GUID, @@ -228,7 +197,6 @@ unsafe extern "system" { ) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinaryFindPayload@12"] pub fn DetourBinaryFindPayload( pBinary: PDETOUR_BINARY, rguid: *const GUID, @@ -236,7 +204,6 @@ unsafe extern "system" { ) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinarySetPayload@16"] pub fn DetourBinarySetPayload( pBinary: PDETOUR_BINARY, rguid: *const GUID, @@ -245,19 +212,15 @@ unsafe extern "system" { ) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinaryDeletePayload@8"] pub fn DetourBinaryDeletePayload(pBinary: PDETOUR_BINARY, rguid: *const GUID) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinaryPurgePayloads@4"] pub fn DetourBinaryPurgePayloads(pBinary: PDETOUR_BINARY) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinaryResetImports@4"] pub fn DetourBinaryResetImports(pBinary: PDETOUR_BINARY) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinaryEditImports@24"] pub fn DetourBinaryEditImports( pBinary: PDETOUR_BINARY, pContext: PVOID, @@ -268,16 +231,13 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinaryWrite@8"] pub fn DetourBinaryWrite(pBinary: PDETOUR_BINARY, hFile: HANDLE) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourBinaryClose@4"] pub fn DetourBinaryClose(pBinary: PDETOUR_BINARY) -> BOOL; } unsafe extern "system" { #[doc = " Create Process & Load Dll."] - #[link_name = "\u{1}_DetourFindRemotePayload@12"] pub fn DetourFindRemotePayload( hProcess: HANDLE, rguid: *const GUID, @@ -313,7 +273,6 @@ pub type PDETOUR_CREATE_PROCESS_ROUTINEW = ::std::option::Option< ) -> BOOL, >; unsafe extern "system" { - #[link_name = "\u{1}_DetourCreateProcessWithDllA@48"] pub fn DetourCreateProcessWithDllA( lpApplicationName: LPCSTR, lpCommandLine: LPSTR, @@ -330,7 +289,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCreateProcessWithDllW@48"] pub fn DetourCreateProcessWithDllW( lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR, @@ -347,7 +305,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCreateProcessWithDllExA@48"] pub fn DetourCreateProcessWithDllExA( lpApplicationName: LPCSTR, lpCommandLine: LPSTR, @@ -364,7 +321,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCreateProcessWithDllExW@48"] pub fn DetourCreateProcessWithDllExW( lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR, @@ -381,7 +337,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCreateProcessWithDllsA@52"] pub fn DetourCreateProcessWithDllsA( lpApplicationName: LPCSTR, lpCommandLine: LPSTR, @@ -399,7 +354,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCreateProcessWithDllsW@52"] pub fn DetourCreateProcessWithDllsW( lpApplicationName: LPCWSTR, lpCommandLine: LPWSTR, @@ -417,7 +371,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourProcessViaHelperA@12"] pub fn DetourProcessViaHelperA( dwTargetPid: DWORD, lpDllName: LPCSTR, @@ -425,7 +378,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourProcessViaHelperW@12"] pub fn DetourProcessViaHelperW( dwTargetPid: DWORD, lpDllName: LPCSTR, @@ -433,7 +385,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourProcessViaHelperDllsA@16"] pub fn DetourProcessViaHelperDllsA( dwTargetPid: DWORD, nDlls: DWORD, @@ -442,7 +393,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourProcessViaHelperDllsW@16"] pub fn DetourProcessViaHelperDllsW( dwTargetPid: DWORD, nDlls: DWORD, @@ -451,12 +401,10 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourUpdateProcessWithDll@12"] pub fn DetourUpdateProcessWithDll(hProcess: HANDLE, rlpDlls: *mut LPCSTR, nDlls: DWORD) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourUpdateProcessWithDllEx@20"] pub fn DetourUpdateProcessWithDllEx( hProcess: HANDLE, hImage: HMODULE, @@ -466,7 +414,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCopyPayloadToProcess@16"] pub fn DetourCopyPayloadToProcess( hProcess: HANDLE, rguid: *const GUID, @@ -475,7 +422,6 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourCopyPayloadToProcessEx@16"] pub fn DetourCopyPayloadToProcessEx( hProcess: HANDLE, rguid: *const GUID, @@ -484,18 +430,14 @@ unsafe extern "system" { ) -> PVOID; } unsafe extern "system" { - #[link_name = "\u{1}_DetourRestoreAfterWith@0"] pub fn DetourRestoreAfterWith() -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourRestoreAfterWithEx@8"] pub fn DetourRestoreAfterWithEx(pvData: PVOID, cbData: DWORD) -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourIsHelperProcess@0"] pub fn DetourIsHelperProcess() -> BOOL; } unsafe extern "system" { - #[link_name = "\u{1}_DetourFinishHelperProcess@16"] pub fn DetourFinishHelperProcess(arg1: HWND, arg2: HINSTANCE, arg3: LPSTR, arg4: INT); } diff --git a/crates/fspy_detours_sys/src/lib.rs b/crates/fspy_detours_sys/src/lib.rs index 2a7a065aba..36b684d34c 100644 --- a/crates/fspy_detours_sys/src/lib.rs +++ b/crates/fspy_detours_sys/src/lib.rs @@ -1,5 +1,6 @@ -#[allow(non_camel_case_types, non_snake_case)] +#![cfg(windows)] +#[allow(non_camel_case_types, non_snake_case)] mod generated_bindings; pub use generated_bindings::*; diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs index 2311a966a4..a62397b9b9 100644 --- a/crates/fspy_detours_sys/tests/bindings.rs +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -4,9 +4,8 @@ use std::{env, fs}; #[test] fn detours_bindings() { - // https://github.com/0xC9C3/rust-ms-detours/blob/0abc7b11c038afbc2f976de88d44e5691f43bd9a/build.rs#L78 let bindings = bindgen::Builder::default() - .clang_args(["-Idetours/src", "-DWIN32_LEAN_AND_MEAN", "-target", "i686-pc-windows-msvc"]) + .clang_args(["-Idetours/src", "-DWIN32_LEAN_AND_MEAN"]) .header_contents("wrapper.h", "#include \n#include \n") .allowlist_function("Detour.*") .blocklist_type("LP.*") From 1addf86e060ce38b269f69a8cedf3785ff90be17 Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 15:56:30 +0800 Subject: [PATCH 07/15] cargo fmt --- crates/fspy/src/windows/mod.rs | 2 +- crates/fspy_detours_sys/src/generated_bindings.rs | 15 ++++++++------- crates/fspy_preload_windows/src/windows/client.rs | 2 +- .../src/windows/detours/create_process.rs | 2 +- crates/fspy_preload_windows/src/windows/mod.rs | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/crates/fspy/src/windows/mod.rs b/crates/fspy/src/windows/mod.rs index 83bd42ede2..0add51f3cd 100644 --- a/crates/fspy/src/windows/mod.rs +++ b/crates/fspy/src/windows/mod.rs @@ -10,12 +10,12 @@ use std::{ use bincode::borrow_decode_from_slice; use const_format::formatcp; +use fspy_detours_sys::{DetourCopyPayloadToProcess, DetourUpdateProcessWithDll}; use fspy_shared::{ ipc::{BINCODE_CONFIG, PathAccess}, windows::{PAYLOAD_ID, Payload}, }; use futures_util::FutureExt; -use fspy_detours_sys::{DetourCopyPayloadToProcess, DetourUpdateProcessWithDll}; use tokio::{ io::AsyncReadExt, net::windows::named_pipe::{PipeMode, ServerOptions}, diff --git a/crates/fspy_detours_sys/src/generated_bindings.rs b/crates/fspy_detours_sys/src/generated_bindings.rs index eeeb4997b1..395fb02f9d 100644 --- a/crates/fspy_detours_sys/src/generated_bindings.rs +++ b/crates/fspy_detours_sys/src/generated_bindings.rs @@ -1,10 +1,11 @@ -use winapi::shared::minwindef::*; -use winapi::um::winnt::*; -use winapi::um::winnt::{INT}; -use winapi::um::minwinbase::*; -use winapi::um::processthreadsapi::*; -use winapi::shared::guiddef::*; -use winapi::shared::windef::*; +use winapi::{ + shared::{guiddef::*, minwindef::*, windef::*}, + um::{ + minwinbase::*, + processthreadsapi::*, + winnt::{INT, *}, + }, +}; #[repr(C)] #[derive(Debug, Copy, Clone)] diff --git a/crates/fspy_preload_windows/src/windows/client.rs b/crates/fspy_preload_windows/src/windows/client.rs index 955fd056df..abb7eb3850 100644 --- a/crates/fspy_preload_windows/src/windows/client.rs +++ b/crates/fspy_preload_windows/src/windows/client.rs @@ -7,11 +7,11 @@ use std::{ use bincode::{borrow_decode_from_slice, encode_into_std_write, encode_to_vec}; use dashmap::DashSet; +use fspy_detours_sys::DetourCopyPayloadToProcess; use fspy_shared::{ ipc::{BINCODE_CONFIG, PathAccess}, windows::{PAYLOAD_ID, Payload}, }; -use fspy_detours_sys::DetourCopyPayloadToProcess; use ntapi::ntobapi::DUPLICATE_SAME_ACCESS; use smallvec::SmallVec; use winapi::{ diff --git a/crates/fspy_preload_windows/src/windows/detours/create_process.rs b/crates/fspy_preload_windows/src/windows/detours/create_process.rs index d5b4c4b3dd..505b8a3d13 100644 --- a/crates/fspy_preload_windows/src/windows/detours/create_process.rs +++ b/crates/fspy_preload_windows/src/windows/detours/create_process.rs @@ -1,7 +1,7 @@ use std::ffi::CStr; -use fspy_shared::ipc::{AccessMode, NativeStr, PathAccess}; use fspy_detours_sys::{DetourCreateProcessWithDllExA, DetourCreateProcessWithDllExW}; +use fspy_shared::ipc::{AccessMode, NativeStr, PathAccess}; use widestring::U16CStr; use winapi::{ shared::{ diff --git a/crates/fspy_preload_windows/src/windows/mod.rs b/crates/fspy_preload_windows/src/windows/mod.rs index 37303de4df..d806e9c517 100644 --- a/crates/fspy_preload_windows/src/windows/mod.rs +++ b/crates/fspy_preload_windows/src/windows/mod.rs @@ -8,11 +8,11 @@ use std::slice; use client::{Client, set_global_client}; use detours::DETOURS; -use fspy_shared::windows::PAYLOAD_ID; use fspy_detours_sys::{ DetourFindPayloadEx, DetourIsHelperProcess, DetourRestoreAfterWith, DetourTransactionBegin, DetourTransactionCommit, DetourUpdateThread, }; +use fspy_shared::windows::PAYLOAD_ID; use winapi::{ shared::minwindef::{BOOL, DWORD, FALSE, HINSTANCE, TRUE}, um::{ From 1da6b29e7cb37b34959f969670d591fe553515d5 Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 16:10:11 +0800 Subject: [PATCH 08/15] checkout submodules in gh actions --- .github/workflows/ci.yml | 5 +++++ .github/workflows/deny.yml | 13 +++++++------ .github/workflows/release.yml | 6 ++++-- .github/workflows/zizmor.yml | 7 ++++--- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b45be19abb..17700897d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,6 +42,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false + submodules: true - uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.0 with: @@ -61,6 +62,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false + submodules: true - uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.0 with: @@ -89,6 +91,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false + submodules: true - uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.0 with: @@ -126,6 +129,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false + submodules: true - run: | brew install rustup @@ -161,6 +165,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false + submodules: true - uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.0 with: diff --git a/.github/workflows/deny.yml b/.github/workflows/deny.yml index a81bb07b6f..06cb44784a 100644 --- a/.github/workflows/deny.yml +++ b/.github/workflows/deny.yml @@ -7,16 +7,16 @@ on: pull_request: types: [opened, synchronize] paths: - - "Cargo.lock" - - "deny.toml" - - ".github/workflows/deny.yml" + - 'Cargo.lock' + - 'deny.toml' + - '.github/workflows/deny.yml' push: branches: - main paths: - - "Cargo.lock" - - "deny.toml" - - ".github/workflows/deny.yml" + - 'Cargo.lock' + - 'deny.toml' + - '.github/workflows/deny.yml' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} @@ -30,6 +30,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false + submodules: true - uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.0 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6302186729..52a95fe520 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,6 +23,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false + submodules: true - uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.2 with: @@ -93,6 +94,7 @@ jobs: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false + submodules: true - uses: oxc-project/setup-node@fdbf0dfd334c4e6d56ceeb77d91c76339c2a0885 # v1.0.4 @@ -120,8 +122,8 @@ jobs: - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 with: node-version-file: .node-version - registry-url: "https://npm.pkg.github.com" - scope: "@voidzero-dev" + registry-url: 'https://npm.pkg.github.com' + scope: '@voidzero-dev' package-manager-cache: false - run: npm install -g npm@latest # For trusted publishing support diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 22b536430b..476977bc92 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -7,13 +7,13 @@ on: pull_request: types: [opened, synchronize] paths: - - ".github/workflows/**" + - '.github/workflows/**' push: branches: - main - - "renovate/**" + - 'renovate/**' paths: - - ".github/workflows/**" + - '.github/workflows/**' jobs: zizmor: @@ -26,6 +26,7 @@ jobs: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: persist-credentials: false + submodules: true - uses: taiki-e/install-action@ae97ff9daf1cd2e216671a047d80ff48461e30bb # v2.49.1 with: From c9650d2663f70eed259b701da4e2466141e7d194 Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 16:12:15 +0800 Subject: [PATCH 09/15] ignore detours submodule and generated_bindings.rs in typos --- .typos.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.typos.toml b/.typos.toml index 700244c2b5..038573c4f5 100644 --- a/.typos.toml +++ b/.typos.toml @@ -5,4 +5,6 @@ PUNICODE = "PUNICODE" [files] extend-exclude = [ "**/snap-tests/**/snap.txt", + "crates/fspy_detours_sys/detours", + "crates/fspy_detours_sys/src/generated_bindings.rs", ] From 89346774903072e38598acbec6af4a46e2b36d58 Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 01:28:49 -0700 Subject: [PATCH 10/15] use prettyplease to format generated bindings --- .../src/generated_bindings.rs | 63 ++++++++++++------- crates/fspy_detours_sys/tests/bindings.rs | 1 + 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/crates/fspy_detours_sys/src/generated_bindings.rs b/crates/fspy_detours_sys/src/generated_bindings.rs index 395fb02f9d..7fa844b3e2 100644 --- a/crates/fspy_detours_sys/src/generated_bindings.rs +++ b/crates/fspy_detours_sys/src/generated_bindings.rs @@ -1,11 +1,10 @@ -use winapi::{ - shared::{guiddef::*, minwindef::*, windef::*}, - um::{ - minwinbase::*, - processthreadsapi::*, - winnt::{INT, *}, - }, -}; +use winapi::shared::minwindef::*; +use winapi::um::winnt::*; +use winapi::um::winnt::{INT}; +use winapi::um::minwinbase::*; +use winapi::um::processthreadsapi::*; +use winapi::shared::guiddef::*; +use winapi::shared::windef::*; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -13,9 +12,13 @@ pub struct _DETOUR_TRAMPOLINE { _unused: [u8; 0], } pub type PDETOUR_TRAMPOLINE = *mut _DETOUR_TRAMPOLINE; -#[doc = " Binary Typedefs."] +/// Binary Typedefs. pub type PF_DETOUR_BINARY_BYWAY_CALLBACK = ::std::option::Option< - unsafe extern "system" fn(pContext: PVOID, pszFile: LPCSTR, ppszOutFile: *mut LPCSTR) -> BOOL, + unsafe extern "system" fn( + pContext: PVOID, + pszFile: LPCSTR, + ppszOutFile: *mut LPCSTR, + ) -> BOOL, >; pub type PF_DETOUR_BINARY_FILE_CALLBACK = ::std::option::Option< unsafe extern "system" fn( @@ -36,8 +39,9 @@ pub type PF_DETOUR_BINARY_SYMBOL_CALLBACK = ::std::option::Option< ppszOutSymbol: *mut LPCSTR, ) -> BOOL, >; -pub type PF_DETOUR_BINARY_COMMIT_CALLBACK = - ::std::option::Option BOOL>; +pub type PF_DETOUR_BINARY_COMMIT_CALLBACK = ::std::option::Option< + unsafe extern "system" fn(pContext: PVOID) -> BOOL, +>; pub type PF_DETOUR_ENUMERATE_EXPORT_CALLBACK = ::std::option::Option< unsafe extern "system" fn( pContext: PVOID, @@ -67,7 +71,7 @@ pub type PF_DETOUR_IMPORT_FUNC_CALLBACK_EX = ::std::option::Option< >; pub type PDETOUR_BINARY = *mut ::std::os::raw::c_void; unsafe extern "system" { - #[doc = " Transaction APIs."] + /// Transaction APIs. pub fn DetourTransactionBegin() -> LONG; } unsafe extern "system" { @@ -110,7 +114,7 @@ unsafe extern "system" { pub fn DetourSetSystemRegionUpperBound(pSystemRegionUpperBound: PVOID) -> PVOID; } unsafe extern "system" { - #[doc = " Code Functions."] + /// Code Functions. pub fn DetourFindFunction(pszModule: LPCSTR, pszFunction: LPCSTR) -> PVOID; } unsafe extern "system" { @@ -138,7 +142,7 @@ unsafe extern "system" { pub fn DetourIsFunctionImported(pbCode: PBYTE, pbAddress: PBYTE) -> BOOL; } unsafe extern "system" { - #[doc = " Loaded Binary Functions."] + /// Loaded Binary Functions. pub fn DetourGetContainingModule(pvAddr: PVOID) -> HMODULE; } unsafe extern "system" { @@ -174,7 +178,11 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - pub fn DetourFindPayload(hModule: HMODULE, rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; + pub fn DetourFindPayload( + hModule: HMODULE, + rguid: *const GUID, + pcbData: *mut DWORD, + ) -> PVOID; } unsafe extern "system" { pub fn DetourFindPayloadEx(rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; @@ -186,7 +194,7 @@ unsafe extern "system" { pub fn DetourFreePayload(pvData: PVOID) -> BOOL; } unsafe extern "system" { - #[doc = " Persistent Binary Functions."] + /// Persistent Binary Functions. pub fn DetourBinaryOpen(hFile: HANDLE) -> PDETOUR_BINARY; } unsafe extern "system" { @@ -213,7 +221,10 @@ unsafe extern "system" { ) -> PVOID; } unsafe extern "system" { - pub fn DetourBinaryDeletePayload(pBinary: PDETOUR_BINARY, rguid: *const GUID) -> BOOL; + pub fn DetourBinaryDeletePayload( + pBinary: PDETOUR_BINARY, + rguid: *const GUID, + ) -> BOOL; } unsafe extern "system" { pub fn DetourBinaryPurgePayloads(pBinary: PDETOUR_BINARY) -> BOOL; @@ -238,7 +249,7 @@ unsafe extern "system" { pub fn DetourBinaryClose(pBinary: PDETOUR_BINARY) -> BOOL; } unsafe extern "system" { - #[doc = " Create Process & Load Dll."] + /// Create Process & Load Dll. pub fn DetourFindRemotePayload( hProcess: HANDLE, rguid: *const GUID, @@ -402,8 +413,11 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - pub fn DetourUpdateProcessWithDll(hProcess: HANDLE, rlpDlls: *mut LPCSTR, nDlls: DWORD) - -> BOOL; + pub fn DetourUpdateProcessWithDll( + hProcess: HANDLE, + rlpDlls: *mut LPCSTR, + nDlls: DWORD, + ) -> BOOL; } unsafe extern "system" { pub fn DetourUpdateProcessWithDllEx( @@ -440,5 +454,10 @@ unsafe extern "system" { pub fn DetourIsHelperProcess() -> BOOL; } unsafe extern "system" { - pub fn DetourFinishHelperProcess(arg1: HWND, arg2: HINSTANCE, arg3: LPSTR, arg4: INT); + pub fn DetourFinishHelperProcess( + arg1: HWND, + arg2: HINSTANCE, + arg3: LPSTR, + arg4: INT, + ); } diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs index a62397b9b9..6ee28fac65 100644 --- a/crates/fspy_detours_sys/tests/bindings.rs +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -41,6 +41,7 @@ fn detours_bindings() { .raw_line("use winapi::shared::guiddef::*;") .raw_line("use winapi::shared::windef::*;") .layout_tests(false) + .formatter(bindgen::Formatter::Prettyplease) // Detour functions are stdcall on 32-bit Windows .override_abi(bindgen::Abi::System, ".*") .generate() From c7d5401fe069eb2f6835abde20a287c03491536e Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 01:31:49 -0700 Subject: [PATCH 11/15] skip formatting generated bindings --- crates/fspy_detours_sys/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/fspy_detours_sys/src/lib.rs b/crates/fspy_detours_sys/src/lib.rs index 36b684d34c..46396b47fd 100644 --- a/crates/fspy_detours_sys/src/lib.rs +++ b/crates/fspy_detours_sys/src/lib.rs @@ -1,6 +1,7 @@ #![cfg(windows)] #[allow(non_camel_case_types, non_snake_case)] +#[rustfmt::skip] // generated code is formatted by prettyplease, not rustfmt mod generated_bindings; pub use generated_bindings::*; From 75c1d3c555757583b187c590eb18ccee23d80287 Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 16:51:03 +0800 Subject: [PATCH 12/15] replace CRLF with LF in generated bindings --- crates/fspy_detours_sys/tests/bindings.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs index 6ee28fac65..2d332f4dff 100644 --- a/crates/fspy_detours_sys/tests/bindings.rs +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -46,13 +46,18 @@ fn detours_bindings() { .override_abi(bindgen::Abi::System, ".*") .generate() .expect("Unable to generate bindings"); - let bindings_content = bindings.to_string(); + + // bindgen produces raw_lines with \r\n line endings on Windows; + // Git on Windows may check out files using CRLF line endings, depending on user config. + // To avoid unnecessary diffs, normalize all line endings to \n. + let bindings_content = bindings.to_string().replace("\r\n", "\n"); let bindings_path = "src/generated_bindings.rs"; if env::var("FSPY_DETOURS_WRITE_BINDINGS").as_deref() == Ok("1") { fs::write(bindings_path, bindings_content).unwrap(); } else { - let existing_bindings_content = fs::read_to_string(bindings_path).unwrap_or_default(); + let existing_bindings_content = + fs::read_to_string(bindings_path).unwrap_or_default().replace("\r\n", "\n"); assert_eq!( existing_bindings_content, bindings_content, "Bindings are out of date. Run this test with FSPY_DETOURS_WRITE_BINDINGS=1 to update them." From cbe075d7337ff2fe31846d9525181d8428851b8b Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 17:20:11 +0800 Subject: [PATCH 13/15] address review comments --- crates/fspy_detours_sys/Cargo.toml | 2 +- .../src/generated_bindings.rs | 51 ++++++------------- crates/fspy_detours_sys/tests/bindings.rs | 2 +- 3 files changed, 18 insertions(+), 37 deletions(-) diff --git a/crates/fspy_detours_sys/Cargo.toml b/crates/fspy_detours_sys/Cargo.toml index 213397101a..87301eb0dd 100644 --- a/crates/fspy_detours_sys/Cargo.toml +++ b/crates/fspy_detours_sys/Cargo.toml @@ -7,7 +7,7 @@ license.workspace = true rust-version.workspace = true [build-dependencies] -cc ={ workspace = true } +cc = { workspace = true } [dependencies] winapi = { workspace = true, features = ["minwindef", "libloaderapi", "processthreadsapi", "windef"] } diff --git a/crates/fspy_detours_sys/src/generated_bindings.rs b/crates/fspy_detours_sys/src/generated_bindings.rs index 7fa844b3e2..d4dc31c72d 100644 --- a/crates/fspy_detours_sys/src/generated_bindings.rs +++ b/crates/fspy_detours_sys/src/generated_bindings.rs @@ -1,10 +1,11 @@ -use winapi::shared::minwindef::*; -use winapi::um::winnt::*; -use winapi::um::winnt::{INT}; -use winapi::um::minwinbase::*; -use winapi::um::processthreadsapi::*; -use winapi::shared::guiddef::*; -use winapi::shared::windef::*; +use winapi::{ + shared::{guiddef::*, minwindef::*, windef::*}, + um::{ + minwinbase::*, + processthreadsapi::*, + winnt::{INT, *}, + }, +}; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -14,11 +15,7 @@ pub struct _DETOUR_TRAMPOLINE { pub type PDETOUR_TRAMPOLINE = *mut _DETOUR_TRAMPOLINE; /// Binary Typedefs. pub type PF_DETOUR_BINARY_BYWAY_CALLBACK = ::std::option::Option< - unsafe extern "system" fn( - pContext: PVOID, - pszFile: LPCSTR, - ppszOutFile: *mut LPCSTR, - ) -> BOOL, + unsafe extern "system" fn(pContext: PVOID, pszFile: LPCSTR, ppszOutFile: *mut LPCSTR) -> BOOL, >; pub type PF_DETOUR_BINARY_FILE_CALLBACK = ::std::option::Option< unsafe extern "system" fn( @@ -39,9 +36,8 @@ pub type PF_DETOUR_BINARY_SYMBOL_CALLBACK = ::std::option::Option< ppszOutSymbol: *mut LPCSTR, ) -> BOOL, >; -pub type PF_DETOUR_BINARY_COMMIT_CALLBACK = ::std::option::Option< - unsafe extern "system" fn(pContext: PVOID) -> BOOL, ->; +pub type PF_DETOUR_BINARY_COMMIT_CALLBACK = + ::std::option::Option BOOL>; pub type PF_DETOUR_ENUMERATE_EXPORT_CALLBACK = ::std::option::Option< unsafe extern "system" fn( pContext: PVOID, @@ -178,11 +174,7 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - pub fn DetourFindPayload( - hModule: HMODULE, - rguid: *const GUID, - pcbData: *mut DWORD, - ) -> PVOID; + pub fn DetourFindPayload(hModule: HMODULE, rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; } unsafe extern "system" { pub fn DetourFindPayloadEx(rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; @@ -221,10 +213,7 @@ unsafe extern "system" { ) -> PVOID; } unsafe extern "system" { - pub fn DetourBinaryDeletePayload( - pBinary: PDETOUR_BINARY, - rguid: *const GUID, - ) -> BOOL; + pub fn DetourBinaryDeletePayload(pBinary: PDETOUR_BINARY, rguid: *const GUID) -> BOOL; } unsafe extern "system" { pub fn DetourBinaryPurgePayloads(pBinary: PDETOUR_BINARY) -> BOOL; @@ -413,11 +402,8 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - pub fn DetourUpdateProcessWithDll( - hProcess: HANDLE, - rlpDlls: *mut LPCSTR, - nDlls: DWORD, - ) -> BOOL; + pub fn DetourUpdateProcessWithDll(hProcess: HANDLE, rlpDlls: *mut LPCSTR, nDlls: DWORD) + -> BOOL; } unsafe extern "system" { pub fn DetourUpdateProcessWithDllEx( @@ -454,10 +440,5 @@ unsafe extern "system" { pub fn DetourIsHelperProcess() -> BOOL; } unsafe extern "system" { - pub fn DetourFinishHelperProcess( - arg1: HWND, - arg2: HINSTANCE, - arg3: LPSTR, - arg4: INT, - ); + pub fn DetourFinishHelperProcess(arg1: HWND, arg2: HINSTANCE, arg3: LPSTR, arg4: INT); } diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs index 2d332f4dff..24d97262e6 100644 --- a/crates/fspy_detours_sys/tests/bindings.rs +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -35,7 +35,7 @@ fn detours_bindings() { .disable_header_comment() .raw_line("use winapi::shared::minwindef::*;") .raw_line("use winapi::um::winnt::*;") - .raw_line("use winapi::um::winnt::{INT};") + .raw_line("use winapi::um::winnt::INT;") .raw_line("use winapi::um::minwinbase::*;") .raw_line("use winapi::um::processthreadsapi::*;") .raw_line("use winapi::shared::guiddef::*;") From b8f3d0483a4bf28ea5ebdccf771a467facb6184d Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 02:26:08 -0700 Subject: [PATCH 14/15] fix skipping rustfmt --- .../src/generated_bindings.rs | 52 +++++++++++++------ crates/fspy_detours_sys/tests/bindings.rs | 1 + 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/crates/fspy_detours_sys/src/generated_bindings.rs b/crates/fspy_detours_sys/src/generated_bindings.rs index d4dc31c72d..a14523c989 100644 --- a/crates/fspy_detours_sys/src/generated_bindings.rs +++ b/crates/fspy_detours_sys/src/generated_bindings.rs @@ -1,11 +1,11 @@ -use winapi::{ - shared::{guiddef::*, minwindef::*, windef::*}, - um::{ - minwinbase::*, - processthreadsapi::*, - winnt::{INT, *}, - }, -}; +#![rustfmt::skip] +use winapi::shared::minwindef::*; +use winapi::um::winnt::*; +use winapi::um::winnt::INT; +use winapi::um::minwinbase::*; +use winapi::um::processthreadsapi::*; +use winapi::shared::guiddef::*; +use winapi::shared::windef::*; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -15,7 +15,11 @@ pub struct _DETOUR_TRAMPOLINE { pub type PDETOUR_TRAMPOLINE = *mut _DETOUR_TRAMPOLINE; /// Binary Typedefs. pub type PF_DETOUR_BINARY_BYWAY_CALLBACK = ::std::option::Option< - unsafe extern "system" fn(pContext: PVOID, pszFile: LPCSTR, ppszOutFile: *mut LPCSTR) -> BOOL, + unsafe extern "system" fn( + pContext: PVOID, + pszFile: LPCSTR, + ppszOutFile: *mut LPCSTR, + ) -> BOOL, >; pub type PF_DETOUR_BINARY_FILE_CALLBACK = ::std::option::Option< unsafe extern "system" fn( @@ -36,8 +40,9 @@ pub type PF_DETOUR_BINARY_SYMBOL_CALLBACK = ::std::option::Option< ppszOutSymbol: *mut LPCSTR, ) -> BOOL, >; -pub type PF_DETOUR_BINARY_COMMIT_CALLBACK = - ::std::option::Option BOOL>; +pub type PF_DETOUR_BINARY_COMMIT_CALLBACK = ::std::option::Option< + unsafe extern "system" fn(pContext: PVOID) -> BOOL, +>; pub type PF_DETOUR_ENUMERATE_EXPORT_CALLBACK = ::std::option::Option< unsafe extern "system" fn( pContext: PVOID, @@ -174,7 +179,11 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - pub fn DetourFindPayload(hModule: HMODULE, rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; + pub fn DetourFindPayload( + hModule: HMODULE, + rguid: *const GUID, + pcbData: *mut DWORD, + ) -> PVOID; } unsafe extern "system" { pub fn DetourFindPayloadEx(rguid: *const GUID, pcbData: *mut DWORD) -> PVOID; @@ -213,7 +222,10 @@ unsafe extern "system" { ) -> PVOID; } unsafe extern "system" { - pub fn DetourBinaryDeletePayload(pBinary: PDETOUR_BINARY, rguid: *const GUID) -> BOOL; + pub fn DetourBinaryDeletePayload( + pBinary: PDETOUR_BINARY, + rguid: *const GUID, + ) -> BOOL; } unsafe extern "system" { pub fn DetourBinaryPurgePayloads(pBinary: PDETOUR_BINARY) -> BOOL; @@ -402,8 +414,11 @@ unsafe extern "system" { ) -> BOOL; } unsafe extern "system" { - pub fn DetourUpdateProcessWithDll(hProcess: HANDLE, rlpDlls: *mut LPCSTR, nDlls: DWORD) - -> BOOL; + pub fn DetourUpdateProcessWithDll( + hProcess: HANDLE, + rlpDlls: *mut LPCSTR, + nDlls: DWORD, + ) -> BOOL; } unsafe extern "system" { pub fn DetourUpdateProcessWithDllEx( @@ -440,5 +455,10 @@ unsafe extern "system" { pub fn DetourIsHelperProcess() -> BOOL; } unsafe extern "system" { - pub fn DetourFinishHelperProcess(arg1: HWND, arg2: HINSTANCE, arg3: LPSTR, arg4: INT); + pub fn DetourFinishHelperProcess( + arg1: HWND, + arg2: HINSTANCE, + arg3: LPSTR, + arg4: INT, + ); } diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs index 24d97262e6..4956e066fb 100644 --- a/crates/fspy_detours_sys/tests/bindings.rs +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -33,6 +33,7 @@ fn detours_bindings() { .blocklist_type("_STARTUPINFOA") .blocklist_type("_STARTUPINFOW") .disable_header_comment() + .raw_line("#![rustfmt::skip]") // generated code is formatted by prettyplease, not rustfmt .raw_line("use winapi::shared::minwindef::*;") .raw_line("use winapi::um::winnt::*;") .raw_line("use winapi::um::winnt::INT;") From bd4314f621ef20a5846caffc525c39935cba7a6d Mon Sep 17 00:00:00 2001 From: branchseer Date: Mon, 29 Sep 2025 17:32:15 +0800 Subject: [PATCH 15/15] remove file-level rustfmt::skip --- crates/fspy_detours_sys/src/generated_bindings.rs | 1 - crates/fspy_detours_sys/tests/bindings.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/crates/fspy_detours_sys/src/generated_bindings.rs b/crates/fspy_detours_sys/src/generated_bindings.rs index a14523c989..daab4d09c3 100644 --- a/crates/fspy_detours_sys/src/generated_bindings.rs +++ b/crates/fspy_detours_sys/src/generated_bindings.rs @@ -1,4 +1,3 @@ -#![rustfmt::skip] use winapi::shared::minwindef::*; use winapi::um::winnt::*; use winapi::um::winnt::INT; diff --git a/crates/fspy_detours_sys/tests/bindings.rs b/crates/fspy_detours_sys/tests/bindings.rs index 4956e066fb..24d97262e6 100644 --- a/crates/fspy_detours_sys/tests/bindings.rs +++ b/crates/fspy_detours_sys/tests/bindings.rs @@ -33,7 +33,6 @@ fn detours_bindings() { .blocklist_type("_STARTUPINFOA") .blocklist_type("_STARTUPINFOW") .disable_header_comment() - .raw_line("#![rustfmt::skip]") // generated code is formatted by prettyplease, not rustfmt .raw_line("use winapi::shared::minwindef::*;") .raw_line("use winapi::um::winnt::*;") .raw_line("use winapi::um::winnt::INT;")