diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index 3c39eafb0a..82c1b6d8e1 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -302,6 +302,8 @@ jobs: run: cargo clippy -p test_structs --tests - name: Check test_sys run: cargo clippy -p test_sys --tests + - name: Check test_sys_fn_ptrs + run: cargo clippy -p test_sys_fn_ptrs --tests - name: Check test_targets run: cargo clippy -p test_targets --tests - name: Check test_threading diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f1b3c48e6..82a32f8f78 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -331,6 +331,8 @@ jobs: run: cargo test -p test_structs --target ${{ matrix.target }} - name: Test test_sys run: cargo test -p test_sys --target ${{ matrix.target }} + - name: Test test_sys_fn_ptrs + run: cargo test -p test_sys_fn_ptrs --target ${{ matrix.target }} - name: Test test_targets run: cargo test -p test_targets --target ${{ matrix.target }} - name: Test test_threading @@ -359,10 +361,10 @@ jobs: run: cargo test -p tool_bindgen --target ${{ matrix.target }} - name: Test tool_bindings run: cargo test -p tool_bindings --target ${{ matrix.target }} - - name: Test tool_gnu - run: cargo test -p tool_gnu --target ${{ matrix.target }} - name: Clean run: cargo clean + - name: Test tool_gnu + run: cargo test -p tool_gnu --target ${{ matrix.target }} - name: Test tool_license run: cargo test -p tool_license --target ${{ matrix.target }} - name: Test tool_merge diff --git a/crates/libs/bindgen/src/config/mod.rs b/crates/libs/bindgen/src/config/mod.rs index 275c38119d..d84efb53a7 100644 --- a/crates/libs/bindgen/src/config/mod.rs +++ b/crates/libs/bindgen/src/config/mod.rs @@ -20,6 +20,7 @@ pub struct Config<'a> { pub package: bool, pub rustfmt: &'a str, pub sys: bool, + pub sys_fn_ptrs: bool, pub implement: bool, pub specific_deps: bool, pub derive: &'a Derive, diff --git a/crates/libs/bindgen/src/lib.rs b/crates/libs/bindgen/src/lib.rs index 94a3de5fd4..cf7c101f46 100644 --- a/crates/libs/bindgen/src/lib.rs +++ b/crates/libs/bindgen/src/lib.rs @@ -81,6 +81,7 @@ use method_names::*; /// | `--no-comment` | Avoids generating the code generation comment. | /// | `--no-deps` | Avoids dependencies on the various `windows-*` crates. | /// | `--sys` | Generates raw or sys-style Rust bindings. | +/// | `--sys-fn-ptrs` | Additionally generates function pointers for sys-style Rust bindings. | /// | `--implement` | Includes implementation traits for WinRT interfaces. | /// | `--link` | Overrides the default `windows-link` implementation for system calls. | /// @@ -278,6 +279,7 @@ where let mut rustfmt = String::new(); let mut output = String::new(); let mut sys = false; + let mut sys_fn_ptrs = false; let mut link = String::new(); let mut index = false; @@ -301,6 +303,7 @@ where "--no-toml" => no_toml = true, "--package" => package = true, "--sys" => sys = true, + "--sys-fn-ptrs" => sys_fn_ptrs = true, "--implement" => implement = true, "--specific-deps" => specific_deps = true, "--link" => kind = ArgKind::Link, @@ -435,6 +438,7 @@ where rustfmt: &rustfmt, output: &output, sys, + sys_fn_ptrs, implement, specific_deps, link: &link, diff --git a/crates/libs/bindgen/src/types/cpp_fn.rs b/crates/libs/bindgen/src/types/cpp_fn.rs index 873b478947..f274c33ebb 100644 --- a/crates/libs/bindgen/src/types/cpp_fn.rs +++ b/crates/libs/bindgen/src/types/cpp_fn.rs @@ -27,6 +27,35 @@ impl CppFn { self.type_name().write(config, &[]) } + pub fn write_fn_ptr(&self, config: &Config<'_>, underlying_types: bool) -> TokenStream { + let ptr_name = self.method.name().to_string(); + let name = to_ident(&ptr_name); + let abi = self.method.calling_convention(); + let signature = self.method.signature(self.namespace, &[]); + + let params = signature.params.iter().map(|param| { + let name = param.write_ident(); + let ty = if underlying_types { + param.underlying_type().write_abi(config) + } else { + param.write_abi(config) + }; + quote! { #name: #ty } + }); + + let return_sig = config.write_return_sig(self.method, &signature, underlying_types); + + let vararg = if config.sys && signature.call_flags.contains(MethodCallAttributes::VARARG) { + quote! { , ... } + } else { + quote! {} + }; + + quote! { + pub type #name = unsafe extern #abi fn(#(#params),* #vararg) #return_sig; + } + } + pub fn write_link(&self, config: &Config, underlying_types: bool) -> TokenStream { let library = self.method.module_name(); let symbol = self.method.import_name(); @@ -71,6 +100,7 @@ impl CppFn { let name = to_ident(self.method.name()); let signature = self.method.signature(self.namespace, &[]); + let fn_ptr = self.write_fn_ptr(config, false); let link = self.write_link(config, false); let arches = write_arches(self.method); let cfg = self.write_cfg(config); @@ -78,11 +108,22 @@ impl CppFn { let window_long = self.write_window_long(); if config.sys { - return quote! { - #cfg - #link - #window_long - }; + if config.sys_fn_ptrs { + return quote! { + #cfg + #fn_ptr + #window_long + #cfg + #link + #window_long + }; + } else { + return quote! { + #cfg + #link + #window_long + }; + } } let method = CppMethod::new(self.method, self.namespace); diff --git a/crates/tests/misc/sys_fn_ptrs/Cargo.toml b/crates/tests/misc/sys_fn_ptrs/Cargo.toml new file mode 100644 index 0000000000..1e76c45730 --- /dev/null +++ b/crates/tests/misc/sys_fn_ptrs/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "test_sys_fn_ptrs" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +doc = false +doctest = false + +[dependencies.windows-result] +workspace = true + +[dependencies.windows-strings] +workspace = true + +[dependencies.windows-link] +workspace = true + +[build-dependencies.windows-bindgen] +workspace = true + +[lints] +workspace = true diff --git a/crates/tests/misc/sys_fn_ptrs/build.rs b/crates/tests/misc/sys_fn_ptrs/build.rs new file mode 100644 index 0000000000..ffb4c30fff --- /dev/null +++ b/crates/tests/misc/sys_fn_ptrs/build.rs @@ -0,0 +1,18 @@ +fn main() { + windows_bindgen::bindgen([ + "--out", + "src/bindings.rs", + "--filter", + "WebAuthNAuthenticatorMakeCredential", + "WebAuthNAuthenticatorGetAssertion", + "LoadLibraryExA", + "GetProcAddress", + "FreeLibrary", + "LOAD_LIBRARY_SEARCH_DEFAULT_DIRS", + "--sys", + "--sys-fn-ptrs", + "--no-comment", + "--no-deps", + ]) + .unwrap(); +} diff --git a/crates/tests/misc/sys_fn_ptrs/src/bindings.rs b/crates/tests/misc/sys_fn_ptrs/src/bindings.rs new file mode 100644 index 0000000000..357af6a976 --- /dev/null +++ b/crates/tests/misc/sys_fn_ptrs/src/bindings.rs @@ -0,0 +1,377 @@ +#![allow( + non_snake_case, + non_upper_case_globals, + non_camel_case_types, + dead_code, + clippy::all +)] + +pub type BOOL = i32; +#[repr(C)] +#[derive(Clone, Copy)] +pub struct GUID { + pub data1: u32, + pub data2: u16, + pub data3: u16, + pub data4: [u8; 8], +} +impl GUID { + pub const fn from_u128(uuid: u128) -> Self { + Self { + data1: (uuid >> 96) as u32, + data2: (uuid >> 80 & 0xffff) as u16, + data3: (uuid >> 64 & 0xffff) as u16, + data4: (uuid as u64).to_be_bytes(), + } + } +} +pub type HRESULT = i32; +pub type PCSTR = *const u8; +pub type PCWSTR = *const u16; +pub mod Windows { + pub mod Win32 { + pub mod Foundation { + pub type FreeLibrary = + unsafe extern "system" fn(hlibmodule: HMODULE) -> super::super::super::BOOL; + windows_link::link!("kernel32.dll" "system" fn FreeLibrary(hlibmodule : HMODULE) -> super::super::super::BOOL); + pub type FARPROC = Option isize>; + pub type HANDLE = *mut core::ffi::c_void; + pub type HINSTANCE = *mut core::ffi::c_void; + pub type HMODULE = *mut core::ffi::c_void; + pub type HWND = *mut core::ffi::c_void; + } + pub mod Networking { + pub mod WindowsWebServices { + pub type WebAuthNAuthenticatorGetAssertion = unsafe extern "system" fn ( hwnd : super::super::Foundation:: HWND , pwszrpid : super::super::super::super::PCWSTR , pwebauthnclientdata : *const WEBAUTHN_CLIENT_DATA , pwebauthngetassertionoptions : *const WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS , ppwebauthnassertion : *mut *mut WEBAUTHN_ASSERTION ) -> super::super::super::super::HRESULT ; + windows_link::link!("webauthn.dll" "system" fn WebAuthNAuthenticatorGetAssertion(hwnd : super::super::Foundation:: HWND, pwszrpid : super::super::super::super::PCWSTR, pwebauthnclientdata : *const WEBAUTHN_CLIENT_DATA, pwebauthngetassertionoptions : *const WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS, ppwebauthnassertion : *mut *mut WEBAUTHN_ASSERTION) -> super::super::super::super::HRESULT); + pub type WebAuthNAuthenticatorMakeCredential = unsafe extern "system" fn ( hwnd : super::super::Foundation:: HWND , prpinformation : *const WEBAUTHN_RP_ENTITY_INFORMATION , puserinformation : *const WEBAUTHN_USER_ENTITY_INFORMATION , ppubkeycredparams : *const WEBAUTHN_COSE_CREDENTIAL_PARAMETERS , pwebauthnclientdata : *const WEBAUTHN_CLIENT_DATA , pwebauthnmakecredentialoptions : *const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS , ppwebauthncredentialattestation : *mut *mut WEBAUTHN_CREDENTIAL_ATTESTATION ) -> super::super::super::super::HRESULT ; + windows_link::link!("webauthn.dll" "system" fn WebAuthNAuthenticatorMakeCredential(hwnd : super::super::Foundation:: HWND, prpinformation : *const WEBAUTHN_RP_ENTITY_INFORMATION, puserinformation : *const WEBAUTHN_USER_ENTITY_INFORMATION, ppubkeycredparams : *const WEBAUTHN_COSE_CREDENTIAL_PARAMETERS, pwebauthnclientdata : *const WEBAUTHN_CLIENT_DATA, pwebauthnmakecredentialoptions : *const WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS, ppwebauthncredentialattestation : *mut *mut WEBAUTHN_CREDENTIAL_ATTESTATION) -> super::super::super::super::HRESULT); + #[repr(C)] + #[derive(Clone, Copy)] + pub struct CTAPCBOR_HYBRID_STORAGE_LINKED_DATA { + pub dwVersion: u32, + pub cbContactId: u32, + pub pbContactId: *mut u8, + pub cbLinkId: u32, + pub pbLinkId: *mut u8, + pub cbLinkSecret: u32, + pub pbLinkSecret: *mut u8, + pub cbPublicKey: u32, + pub pbPublicKey: *mut u8, + pub pwszAuthenticatorName: super::super::super::super::PCWSTR, + pub wEncodedTunnelServerDomain: u16, + } + impl Default for CTAPCBOR_HYBRID_STORAGE_LINKED_DATA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_ASSERTION { + pub dwVersion: u32, + pub cbAuthenticatorData: u32, + pub pbAuthenticatorData: *mut u8, + pub cbSignature: u32, + pub pbSignature: *mut u8, + pub Credential: WEBAUTHN_CREDENTIAL, + pub cbUserId: u32, + pub pbUserId: *mut u8, + pub Extensions: WEBAUTHN_EXTENSIONS, + pub cbCredLargeBlob: u32, + pub pbCredLargeBlob: *mut u8, + pub dwCredLargeBlobStatus: u32, + pub pHmacSecret: *mut WEBAUTHN_HMAC_SECRET_SALT, + pub dwUsedTransport: u32, + pub cbUnsignedExtensionOutputs: u32, + pub pbUnsignedExtensionOutputs: *mut u8, + } + impl Default for WEBAUTHN_ASSERTION { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS { + pub dwVersion: u32, + pub dwTimeoutMilliseconds: u32, + pub CredentialList: WEBAUTHN_CREDENTIALS, + pub Extensions: WEBAUTHN_EXTENSIONS, + pub dwAuthenticatorAttachment: u32, + pub dwUserVerificationRequirement: u32, + pub dwFlags: u32, + pub pwszU2fAppId: super::super::super::super::PCWSTR, + pub pbU2fAppId: *mut super::super::super::super::BOOL, + pub pCancellationId: *mut super::super::super::super::GUID, + pub pAllowCredentialList: *mut WEBAUTHN_CREDENTIAL_LIST, + pub dwCredLargeBlobOperation: u32, + pub cbCredLargeBlob: u32, + pub pbCredLargeBlob: *mut u8, + pub pHmacSecretSaltValues: *mut WEBAUTHN_HMAC_SECRET_SALT_VALUES, + pub bBrowserInPrivateMode: super::super::super::super::BOOL, + pub pLinkedDevice: *mut CTAPCBOR_HYBRID_STORAGE_LINKED_DATA, + pub bAutoFill: super::super::super::super::BOOL, + pub cbJsonExt: u32, + pub pbJsonExt: *mut u8, + } + impl Default for WEBAUTHN_AUTHENTICATOR_GET_ASSERTION_OPTIONS { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS { + pub dwVersion: u32, + pub dwTimeoutMilliseconds: u32, + pub CredentialList: WEBAUTHN_CREDENTIALS, + pub Extensions: WEBAUTHN_EXTENSIONS, + pub dwAuthenticatorAttachment: u32, + pub bRequireResidentKey: super::super::super::super::BOOL, + pub dwUserVerificationRequirement: u32, + pub dwAttestationConveyancePreference: u32, + pub dwFlags: u32, + pub pCancellationId: *mut super::super::super::super::GUID, + pub pExcludeCredentialList: *mut WEBAUTHN_CREDENTIAL_LIST, + pub dwEnterpriseAttestation: u32, + pub dwLargeBlobSupport: u32, + pub bPreferResidentKey: super::super::super::super::BOOL, + pub bBrowserInPrivateMode: super::super::super::super::BOOL, + pub bEnablePrf: super::super::super::super::BOOL, + pub pLinkedDevice: *mut CTAPCBOR_HYBRID_STORAGE_LINKED_DATA, + pub cbJsonExt: u32, + pub pbJsonExt: *mut u8, + } + impl Default for WEBAUTHN_AUTHENTICATOR_MAKE_CREDENTIAL_OPTIONS { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_CLIENT_DATA { + pub dwVersion: u32, + pub cbClientDataJSON: u32, + pub pbClientDataJSON: *mut u8, + pub pwszHashAlgId: super::super::super::super::PCWSTR, + } + impl Default for WEBAUTHN_CLIENT_DATA { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_COSE_CREDENTIAL_PARAMETER { + pub dwVersion: u32, + pub pwszCredentialType: super::super::super::super::PCWSTR, + pub lAlg: i32, + } + impl Default for WEBAUTHN_COSE_CREDENTIAL_PARAMETER { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_COSE_CREDENTIAL_PARAMETERS { + pub cCredentialParameters: u32, + pub pCredentialParameters: *mut WEBAUTHN_COSE_CREDENTIAL_PARAMETER, + } + impl Default for WEBAUTHN_COSE_CREDENTIAL_PARAMETERS { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_CREDENTIAL { + pub dwVersion: u32, + pub cbId: u32, + pub pbId: *mut u8, + pub pwszCredentialType: super::super::super::super::PCWSTR, + } + impl Default for WEBAUTHN_CREDENTIAL { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_CREDENTIALS { + pub cCredentials: u32, + pub pCredentials: *mut WEBAUTHN_CREDENTIAL, + } + impl Default for WEBAUTHN_CREDENTIALS { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_CREDENTIAL_ATTESTATION { + pub dwVersion: u32, + pub pwszFormatType: super::super::super::super::PCWSTR, + pub cbAuthenticatorData: u32, + pub pbAuthenticatorData: *mut u8, + pub cbAttestation: u32, + pub pbAttestation: *mut u8, + pub dwAttestationDecodeType: u32, + pub pvAttestationDecode: *mut core::ffi::c_void, + pub cbAttestationObject: u32, + pub pbAttestationObject: *mut u8, + pub cbCredentialId: u32, + pub pbCredentialId: *mut u8, + pub Extensions: WEBAUTHN_EXTENSIONS, + pub dwUsedTransport: u32, + pub bEpAtt: super::super::super::super::BOOL, + pub bLargeBlobSupported: super::super::super::super::BOOL, + pub bResidentKey: super::super::super::super::BOOL, + pub bPrfEnabled: super::super::super::super::BOOL, + pub cbUnsignedExtensionOutputs: u32, + pub pbUnsignedExtensionOutputs: *mut u8, + } + impl Default for WEBAUTHN_CREDENTIAL_ATTESTATION { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_CREDENTIAL_EX { + pub dwVersion: u32, + pub cbId: u32, + pub pbId: *mut u8, + pub pwszCredentialType: super::super::super::super::PCWSTR, + pub dwTransports: u32, + } + impl Default for WEBAUTHN_CREDENTIAL_EX { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_CREDENTIAL_LIST { + pub cCredentials: u32, + pub ppCredentials: *mut *mut WEBAUTHN_CREDENTIAL_EX, + } + impl Default for WEBAUTHN_CREDENTIAL_LIST { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT { + pub cbCredID: u32, + pub pbCredID: *mut u8, + pub pHmacSecretSalt: *mut WEBAUTHN_HMAC_SECRET_SALT, + } + impl Default for WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_EXTENSION { + pub pwszExtensionIdentifier: super::super::super::super::PCWSTR, + pub cbExtension: u32, + pub pvExtension: *mut core::ffi::c_void, + } + impl Default for WEBAUTHN_EXTENSION { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_EXTENSIONS { + pub cExtensions: u32, + pub pExtensions: *mut WEBAUTHN_EXTENSION, + } + impl Default for WEBAUTHN_EXTENSIONS { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_HMAC_SECRET_SALT { + pub cbFirst: u32, + pub pbFirst: *mut u8, + pub cbSecond: u32, + pub pbSecond: *mut u8, + } + impl Default for WEBAUTHN_HMAC_SECRET_SALT { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_HMAC_SECRET_SALT_VALUES { + pub pGlobalHmacSalt: *mut WEBAUTHN_HMAC_SECRET_SALT, + pub cCredWithHmacSecretSaltList: u32, + pub pCredWithHmacSecretSaltList: *mut WEBAUTHN_CRED_WITH_HMAC_SECRET_SALT, + } + impl Default for WEBAUTHN_HMAC_SECRET_SALT_VALUES { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_RP_ENTITY_INFORMATION { + pub dwVersion: u32, + pub pwszId: super::super::super::super::PCWSTR, + pub pwszName: super::super::super::super::PCWSTR, + pub pwszIcon: super::super::super::super::PCWSTR, + } + impl Default for WEBAUTHN_RP_ENTITY_INFORMATION { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct WEBAUTHN_USER_ENTITY_INFORMATION { + pub dwVersion: u32, + pub cbId: u32, + pub pbId: *mut u8, + pub pwszName: super::super::super::super::PCWSTR, + pub pwszIcon: super::super::super::super::PCWSTR, + pub pwszDisplayName: super::super::super::super::PCWSTR, + } + impl Default for WEBAUTHN_USER_ENTITY_INFORMATION { + fn default() -> Self { + unsafe { core::mem::zeroed() } + } + } + } + } + pub mod System { + pub mod LibraryLoader { + pub type GetProcAddress = + unsafe extern "system" fn( + hmodule: super::super::Foundation::HMODULE, + lpprocname: super::super::super::super::PCSTR, + ) + -> super::super::Foundation::FARPROC; + windows_link::link!("kernel32.dll" "system" fn GetProcAddress(hmodule : super::super::Foundation:: HMODULE, lpprocname : super::super::super::super::PCSTR) -> super::super::Foundation:: FARPROC); + pub type LoadLibraryExA = + unsafe extern "system" fn( + lplibfilename: super::super::super::super::PCSTR, + hfile: super::super::Foundation::HANDLE, + dwflags: LOAD_LIBRARY_FLAGS, + ) + -> super::super::Foundation::HMODULE; + windows_link::link!("kernel32.dll" "system" fn LoadLibraryExA(lplibfilename : super::super::super::super::PCSTR, hfile : super::super::Foundation:: HANDLE, dwflags : LOAD_LIBRARY_FLAGS) -> super::super::Foundation:: HMODULE); + pub type LOAD_LIBRARY_FLAGS = u32; + pub const LOAD_LIBRARY_SEARCH_DEFAULT_DIRS: LOAD_LIBRARY_FLAGS = 4096u32; + } + } + } +} diff --git a/crates/tests/misc/sys_fn_ptrs/src/lib.rs b/crates/tests/misc/sys_fn_ptrs/src/lib.rs new file mode 100644 index 0000000000..643ce9ad7c --- /dev/null +++ b/crates/tests/misc/sys_fn_ptrs/src/lib.rs @@ -0,0 +1,45 @@ +// Tests that --sys + --sys-fn-ptr bindings work and generate a function pointer for Win32 APIs. + +pub mod bindings; + +use bindings::Windows::Win32::System::LibraryLoader::*; + +use bindings::Windows::Win32::Networking::WindowsWebServices::WebAuthNAuthenticatorMakeCredential; + +unsafe fn delay_load(library: bindings::PCSTR, function: bindings::PCSTR) -> Option { + unsafe { + let library = LoadLibraryExA( + library, + std::ptr::null_mut(), + LOAD_LIBRARY_SEARCH_DEFAULT_DIRS, + ); + + if library.is_null() { + return None; + }; + + let address = GetProcAddress(library, function); + + if address.is_some() { + return Some(std::mem::transmute_copy(&address)); + } + + // In real code you'd need to manage your library lifetimes by calling FreeLibrary when you're done with your delay_load + None + } +} + +#[allow(unused)] +pub fn bind_getprocaddr_make_credential() -> Option { + unsafe { + delay_load( + windows_strings::s!("webauthn.dll").as_ptr(), + windows_strings::s!("WebAuthNAuthenticatorMakeCredential").as_ptr(), + ) + } +} + +#[allow(unused)] +pub fn bind_linked_make_credential() -> WebAuthNAuthenticatorMakeCredential { + bindings::Windows::Win32::Networking::WindowsWebServices::WebAuthNAuthenticatorMakeCredential +} diff --git a/crates/tests/misc/sys_fn_ptrs/tests/bind_webauthn.rs b/crates/tests/misc/sys_fn_ptrs/tests/bind_webauthn.rs new file mode 100644 index 0000000000..1f100566a9 --- /dev/null +++ b/crates/tests/misc/sys_fn_ptrs/tests/bind_webauthn.rs @@ -0,0 +1,10 @@ +use test_sys_fn_ptrs::bindings::Windows::Win32::Networking::WindowsWebServices::*; + +#[allow(unused)] +#[allow(unused_assignments)] +#[test] +fn test_binding() { + let mut f: WebAuthNAuthenticatorMakeCredential = WebAuthNAuthenticatorMakeCredential; + f = test_sys_fn_ptrs::bind_getprocaddr_make_credential().unwrap(); + f = test_sys_fn_ptrs::bind_linked_make_credential(); +}