Skip to content

Commit 052630f

Browse files
authored
Clarify and test extern abi workaround for variadic function support (#3669)
1 parent 0dfbc25 commit 052630f

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

crates/tests/misc/calling_convention/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ features = [
2525
"Win32_System_SystemInformation",
2626
"Win32_UI_WindowsAndMessaging",
2727
]
28+
29+
[dependencies.windows-link]
30+
workspace = true
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use windows_sys::{
2+
core::{s, PCSTR, PSTR},
3+
Win32::Foundation::ERROR_BUSY,
4+
Win32::Networking::Ldap::LDAP_BUSY,
5+
};
6+
7+
windows_link::link!("wldap32.dll" "C" fn LdapMapErrorToWin32(ldaperror: u32) -> u32);
8+
windows_link::link!("kernel32.dll" "system" fn GetTickCount() -> u32);
9+
windows_link::link!("user32.dll" "C" fn wsprintfA(param0: PSTR, param1: PCSTR, ...) -> i32);
10+
11+
#[test]
12+
fn calling_convention() {
13+
unsafe {
14+
// This function requires cdecl on x86.
15+
assert_eq!(LdapMapErrorToWin32(LDAP_BUSY as u32), ERROR_BUSY);
16+
17+
// This function requires stdcall on x86.
18+
GetTickCount();
19+
}
20+
}
21+
22+
#[test]
23+
fn variadic() {
24+
unsafe {
25+
let mut buffer = vec![0u8; 1024];
26+
let len = wsprintfA(buffer.as_mut_ptr(), s!("test-%d-%d!"), 123u32, 456u32);
27+
let result = std::str::from_utf8_unchecked(std::slice::from_raw_parts(
28+
buffer.as_ptr(),
29+
len as usize,
30+
));
31+
assert_eq!(result, "test-123-456!");
32+
}
33+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This is a test specifically for the breaking change discussed in https://github.com/microsoft/windows-rs/pull/3669
2+
// and https://github.com/microsoft/windows-rs/issues/3626 where a function pointer is stored. All of this can be
3+
// removed if the hardcoding of "C" is removed in a future breaking change.
4+
5+
windows_link::link!("kernel32.dll" "system" fn GetTickCount() -> u32);
6+
7+
#[cfg(target_arch = "x86")]
8+
type GetTickCountType = unsafe extern "system" fn() -> u32;
9+
10+
#[cfg(not(target_arch = "x86"))]
11+
type GetTickCountType = unsafe extern "C" fn() -> u32;
12+
13+
static GET_TICK_COUNT: GetTickCountType = GetTickCount;
14+
15+
#[test]
16+
fn store_ptr() {
17+
unsafe {
18+
GET_TICK_COUNT();
19+
}
20+
}

0 commit comments

Comments
 (0)