diff --git a/Cargo.lock b/Cargo.lock index 9cc3054..51a8b41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -259,9 +259,9 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "const_panic" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013b6c2c3a14d678f38cd23994b02da3a1a1b6a5d1eedddfe63a5a5f11b13a81" +checksum = "53857514f72ee4a2b583de67401e3ff63a5472ca4acf289d09a9ea7636dfec17" [[package]] name = "core-foundation" @@ -323,18 +323,18 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" @@ -1004,9 +1004,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", "simd-adler32", @@ -1603,12 +1603,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "sptr" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" - [[package]] name = "syn" version = "1.0.109" @@ -2273,7 +2267,6 @@ dependencies = [ "rand", "sha256", "shared", - "sptr", "tracing", "tracing-appender", "tracing-subscriber", diff --git a/crates/yabg3nml/Cargo.toml b/crates/yabg3nml/Cargo.toml index 0565c1f..821eeb6 100644 --- a/crates/yabg3nml/Cargo.toml +++ b/crates/yabg3nml/Cargo.toml @@ -25,8 +25,6 @@ tracing-appender = "0.2.3" pelite = "0.10.0" widestring = "1.1.0" rand = "0.8.5" -# todo: remove sptr when strict provenance apis are stable -sptr = "0.3.2" [dependencies.argh] git = "https://github.com/google/argh" diff --git a/crates/yabg3nml/src/wapi/enum_windows.rs b/crates/yabg3nml/src/wapi/enum_windows.rs index d7bb9cb..3e582a0 100644 --- a/crates/yabg3nml/src/wapi/enum_windows.rs +++ b/crates/yabg3nml/src/wapi/enum_windows.rs @@ -1,46 +1,84 @@ -use std::panic::{self, AssertUnwindSafe}; +use std::{ + mem, + panic::{self, AssertUnwindSafe}, + sync::Mutex, +}; use eyre::Result; -// TODO: remove when strict provenance apis are stable -use sptr::{from_exposed_addr_mut, Strict}; +use shared::utils::SuperLock; use tracing::{error, trace_span}; use windows::Win32::{ - Foundation::{BOOL, FALSE, HWND, LPARAM, TRUE}, + Foundation::{BOOL, HWND, LPARAM}, UI::WindowsAndMessaging::EnumWindows, }; type UserCallback<'a> = Box Result<()> + Send + Sync + 'a>; +struct FfiCb(UserCallback<'static>); + +trait StaticFfiCbMethods { + unsafe fn set_cb(&self, cb: UserCallback); + unsafe fn call(&self, hwnd: HWND) -> Result<()>; + fn drop(&self); +} + +impl StaticFfiCbMethods for Mutex> { + /// SAFETY: + /// Caller promises to drop before end of scope where original closure was created + /// this is because closure may have captures, this is !'static + unsafe fn set_cb(&self, cb: UserCallback) { + let _static = unsafe { mem::transmute::>(cb) }; + *self.super_lock() = Some(FfiCb(_static)); + } + + /// SAFETY: + /// This must be called in scope where closure captures are still valid + unsafe fn call(&self, hwnd: HWND) -> Result<()> { + if let Some(cb) = &mut *self.super_lock() { + cb.0(hwnd) + } else { + Ok(()) + } + } + + fn drop(&self) { + *self.super_lock() = None; + } +} + +static CB: Mutex> = Mutex::new(None); + #[allow(non_snake_case)] pub fn EnumWindowsRs(cb: impl FnMut(HWND) -> Result<()> + Send + Sync) { let span = trace_span!("EnumWindowsRs"); let _guard = span.enter(); - let mut cb: UserCallback = Box::new(cb); - // TODO: Use strict provenance apis when stable and remove sptr - _ = unsafe { EnumWindows(Some(enum_cb), LPARAM((&raw mut cb).expose_addr() as _)) }; + unsafe { + CB.set_cb(Box::new(cb)); + } + + _ = unsafe { EnumWindows(Some(enum_cb), None) }; + + CB.drop(); } -extern "system" fn enum_cb(param0: HWND, param1: LPARAM) -> BOOL { +extern "system" fn enum_cb(param0: HWND, _: LPARAM) -> BOOL { let span = trace_span!("enum_cb"); let _guard = span.enter(); - // TODO: Use strict provenance apis when stable and remove sptr - let cb = unsafe { &mut *from_exposed_addr_mut::(param1.0 as _) }; - - let result = panic::catch_unwind(AssertUnwindSafe(|| cb(param0))); + let result = panic::catch_unwind(AssertUnwindSafe(|| unsafe { CB.call(param0) })); match result { // no panic and cb returned Ok - Ok(Ok(_)) => TRUE, + Ok(Ok(_)) => true.into(), // no panic and callback returned Err Ok(Err(err)) => { error!("{err}"); - FALSE + false.into() } // panic - Err(_) => FALSE, + Err(_) => false.into(), } } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index fe9ad88..0da912e 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2024-11-17" +channel = "nightly-2024-12-17" components = ["rustfmt", "clippy"] profile = "minimal"