diff --git a/crates/tests/misc/calling_convention/Cargo.toml b/crates/tests/misc/calling_convention/Cargo.toml index 2f61794c6e..98c20096da 100644 --- a/crates/tests/misc/calling_convention/Cargo.toml +++ b/crates/tests/misc/calling_convention/Cargo.toml @@ -25,3 +25,6 @@ features = [ "Win32_System_SystemInformation", "Win32_UI_WindowsAndMessaging", ] + +[dependencies.windows-link] +workspace = true diff --git a/crates/tests/misc/calling_convention/tests/link.rs b/crates/tests/misc/calling_convention/tests/link.rs new file mode 100644 index 0000000000..9edebda174 --- /dev/null +++ b/crates/tests/misc/calling_convention/tests/link.rs @@ -0,0 +1,33 @@ +use windows_sys::{ + core::{s, PCSTR, PSTR}, + Win32::Foundation::ERROR_BUSY, + Win32::Networking::Ldap::LDAP_BUSY, +}; + +windows_link::link!("wldap32.dll" "C" fn LdapMapErrorToWin32(ldaperror: u32) -> u32); +windows_link::link!("kernel32.dll" "system" fn GetTickCount() -> u32); +windows_link::link!("user32.dll" "C" fn wsprintfA(param0: PSTR, param1: PCSTR, ...) -> i32); + +#[test] +fn calling_convention() { + unsafe { + // This function requires cdecl on x86. + assert_eq!(LdapMapErrorToWin32(LDAP_BUSY as u32), ERROR_BUSY); + + // This function requires stdcall on x86. + GetTickCount(); + } +} + +#[test] +fn variadic() { + unsafe { + let mut buffer = vec![0u8; 1024]; + let len = wsprintfA(buffer.as_mut_ptr(), s!("test-%d-%d!"), 123u32, 456u32); + let result = std::str::from_utf8_unchecked(std::slice::from_raw_parts( + buffer.as_ptr(), + len as usize, + )); + assert_eq!(result, "test-123-456!"); + } +} diff --git a/crates/tests/misc/calling_convention/tests/ptr.rs b/crates/tests/misc/calling_convention/tests/ptr.rs new file mode 100644 index 0000000000..52bf1138ce --- /dev/null +++ b/crates/tests/misc/calling_convention/tests/ptr.rs @@ -0,0 +1,20 @@ +// This is a test specifically for the breaking change discussed in https://github.com/microsoft/windows-rs/pull/3669 +// and https://github.com/microsoft/windows-rs/issues/3626 where a function pointer is stored. All of this can be +// removed if the hardcoding of "C" is removed in a future breaking change. + +windows_link::link!("kernel32.dll" "system" fn GetTickCount() -> u32); + +#[cfg(target_arch = "x86")] +type GetTickCountType = unsafe extern "system" fn() -> u32; + +#[cfg(not(target_arch = "x86"))] +type GetTickCountType = unsafe extern "C" fn() -> u32; + +static GET_TICK_COUNT: GetTickCountType = GetTickCount; + +#[test] +fn store_ptr() { + unsafe { + GET_TICK_COUNT(); + } +}