diff --git a/crates/tests/arch/Cargo.toml b/crates/tests/arch/Cargo.toml index f1b2a8116c..e3c7c7c6d5 100644 --- a/crates/tests/arch/Cargo.toml +++ b/crates/tests/arch/Cargo.toml @@ -9,3 +9,9 @@ path = "../../libs/windows" features = [ "Win32_System_Diagnostics_Debug", ] + +[dependencies.windows-sys] +path = "../../libs/sys" +features = [ + "Win32_System_Diagnostics_Debug", +] diff --git a/crates/tests/arch/tests/sys.rs b/crates/tests/arch/tests/sys.rs new file mode 100644 index 0000000000..ebdcbd152c --- /dev/null +++ b/crates/tests/arch/tests/sys.rs @@ -0,0 +1,13 @@ +use windows_sys::Win32::System::Diagnostics::Debug::KNONVOLATILE_CONTEXT_POINTERS; + +#[test] +#[cfg(target_arch = "x86_64")] +fn test() { + assert_eq!(256, core::mem::size_of::()); +} + +#[test] +#[cfg(target_arch = "x86")] +fn test() { + assert_eq!(4, core::mem::size_of::()); +} diff --git a/crates/tests/arch/tests/test.rs b/crates/tests/arch/tests/win.rs similarity index 100% rename from crates/tests/arch/tests/test.rs rename to crates/tests/arch/tests/win.rs diff --git a/crates/tests/arch_feature/Cargo.toml b/crates/tests/arch_feature/Cargo.toml index 2b1d58361d..74d2a96872 100644 --- a/crates/tests/arch_feature/Cargo.toml +++ b/crates/tests/arch_feature/Cargo.toml @@ -12,3 +12,12 @@ features = [ "Win32_System_Environment", "Win32_System_Kernel", ] + +[dependencies.windows-sys] +path = "../../libs/sys" +features = [ + "Win32_System_Diagnostics_Debug", + "Win32_System_SystemServices", + "Win32_System_Environment", + "Win32_System_Kernel", +] diff --git a/crates/tests/arch_feature/tests/sys.rs b/crates/tests/arch_feature/tests/sys.rs new file mode 100644 index 0000000000..4ab2f22c42 --- /dev/null +++ b/crates/tests/arch_feature/tests/sys.rs @@ -0,0 +1,31 @@ +use windows_sys::{Win32::System::Diagnostics::Debug::CONTEXT, Win32::System::Environment::VBS_BASIC_ENCLAVE_BASIC_CALL_CREATE_THREAD}; + +#[test] +#[cfg(target_arch = "x86_64")] +fn test() { + assert_eq!(1232, core::mem::size_of::()); + + use windows_sys::Win32::System::Environment::VBS_BASIC_ENCLAVE_THREAD_DESCRIPTOR64; + + extern "system" fn callback(_: *const VBS_BASIC_ENCLAVE_THREAD_DESCRIPTOR64) -> i32 { + 64 + } + + let callback: VBS_BASIC_ENCLAVE_BASIC_CALL_CREATE_THREAD = Some(callback); + assert_eq!(64, unsafe { callback.unwrap()(core::ptr::null()) }); +} + +#[test] +#[cfg(target_arch = "x86")] +fn test() { + assert_eq!(716, core::mem::size_of::()); + + use windows_sys::Win32::System::Environment::VBS_BASIC_ENCLAVE_THREAD_DESCRIPTOR32; + + extern "system" fn callback(_: *const VBS_BASIC_ENCLAVE_THREAD_DESCRIPTOR32) -> i32 { + 32 + } + + let callback: VBS_BASIC_ENCLAVE_BASIC_CALL_CREATE_THREAD = Some(callback); + assert_eq!(32, unsafe { callback.unwrap()(core::ptr::null()) }); +} diff --git a/crates/tests/arch_feature/tests/test.rs b/crates/tests/arch_feature/tests/win.rs similarity index 100% rename from crates/tests/arch_feature/tests/test.rs rename to crates/tests/arch_feature/tests/win.rs diff --git a/crates/tests/bcrypt/Cargo.toml b/crates/tests/bcrypt/Cargo.toml index 51d3985a10..c9345cfc65 100644 --- a/crates/tests/bcrypt/Cargo.toml +++ b/crates/tests/bcrypt/Cargo.toml @@ -10,3 +10,10 @@ features = [ "Win32_Foundation", "Win32_Security_Cryptography", ] + +[dependencies.windows-sys] +path = "../../libs/sys" +features = [ + "Win32_Foundation", + "Win32_Security_Cryptography", +] diff --git a/crates/tests/bcrypt/tests/sys.rs b/crates/tests/bcrypt/tests/sys.rs new file mode 100644 index 0000000000..4707edece7 --- /dev/null +++ b/crates/tests/bcrypt/tests/sys.rs @@ -0,0 +1,61 @@ +use windows_sys::{core::*, Win32::Foundation::*, Win32::Security::Cryptography::*}; + +#[test] +fn test() { + unsafe { + let mut rng = 0; + // TODO: workaround for https://github.com/microsoft/win32metadata/issues/1008 + assert_eq!(STATUS_SUCCESS, BCryptOpenAlgorithmProvider(&mut rng, w!("RNG"), std::ptr::null(), 0)); + + let mut des = 0; + assert_eq!(STATUS_SUCCESS, BCryptOpenAlgorithmProvider(&mut des, w!("3DES"), std::ptr::null(), 0)); + + let mut object_len = [0; 4]; + let mut bytes_copied = 0; + assert_eq!(STATUS_SUCCESS, BCryptGetProperty(des, w!("ObjectLength"), object_len.as_mut_ptr(), object_len.len() as _, &mut bytes_copied, 0)); + let object_len = u32::from_le_bytes(object_len); + + let mut shared_secret = vec![0; object_len as _]; + assert_eq!(STATUS_SUCCESS, BCryptGenRandom(rng, shared_secret.as_mut_ptr(), shared_secret.len() as _, 0)); + + let mut encrypt_key = 0; + assert_eq!(STATUS_SUCCESS, BCryptGenerateSymmetricKey(des, &mut encrypt_key, std::ptr::null_mut(), 0, shared_secret.as_ptr(), shared_secret.len() as _, 0)); + + let mut block_len = [0; 4]; + assert_eq!(STATUS_SUCCESS, BCryptGetProperty(des, w!("BlockLength"), block_len.as_mut_ptr(), block_len.len() as _, &mut bytes_copied, 0)); + let block_len = u32::from_le_bytes(block_len) as usize; + + let send_message = "I ❤️ Rust"; + let mut send_buffer = vec![0; block_len * ((send_message.len() + (block_len - 1)) / block_len)]; + send_buffer[..send_message.len()].copy_from_slice(send_message.as_bytes()); + + let mut encrypted_len = 0; + assert_eq!(STATUS_SUCCESS, BCryptEncrypt(encrypt_key, send_buffer.as_ptr(), send_buffer.len() as _, std::ptr::null(), std::ptr::null_mut(), 0, std::ptr::null_mut(), 0, &mut encrypted_len, 0)); + + let mut encrypted = vec![0; encrypted_len as _]; + assert_eq!(STATUS_SUCCESS, BCryptEncrypt(encrypt_key, send_buffer.as_ptr(), send_buffer.len() as _, std::ptr::null(), std::ptr::null_mut(), 0, encrypted.as_mut_ptr(), encrypted.len() as _, &mut encrypted_len, 0)); + + let mut decrypt_key = 0; + assert_eq!(STATUS_SUCCESS, BCryptGenerateSymmetricKey(des, &mut decrypt_key, std::ptr::null_mut(), 0, shared_secret.as_ptr(), shared_secret.len() as _, 0)); + + let mut decrypted_len = 0; + assert_eq!(STATUS_SUCCESS, BCryptDecrypt(decrypt_key, encrypted.as_ptr(), encrypted.len() as _, std::ptr::null(), std::ptr::null_mut(), 0, std::ptr::null_mut(), 0, &mut decrypted_len, 0)); + + let mut decrypted = vec![0; decrypted_len as _]; + assert_eq!(STATUS_SUCCESS, BCryptDecrypt(decrypt_key, encrypted.as_ptr(), encrypted.len() as _, std::ptr::null(), std::ptr::null_mut(), 0, decrypted.as_mut_ptr(), decrypted.len() as _, &mut decrypted_len, 0)); + + let receive_message = std::str::from_utf8(trim_null_end(&decrypted)).expect("Not a valid message"); + assert_eq!(send_message, receive_message); + } +} + +pub const fn trim_null_end(mut bytes: &[u8]) -> &[u8] { + while let [rest @ .., last] = bytes { + if *last == 0 { + bytes = rest; + } else { + break; + } + } + bytes +} diff --git a/crates/tests/bcrypt/tests/tests.rs b/crates/tests/bcrypt/tests/win.rs similarity index 98% rename from crates/tests/bcrypt/tests/tests.rs rename to crates/tests/bcrypt/tests/win.rs index 76f896dd7f..a0b2c4ec52 100644 --- a/crates/tests/bcrypt/tests/tests.rs +++ b/crates/tests/bcrypt/tests/win.rs @@ -45,7 +45,6 @@ fn test() -> Result<()> { BCryptDecrypt(decrypt_key, Some(&encrypted), None, None, Some(&mut decrypted), &mut decrypted_len, Default::default())?; let receive_message = std::str::from_utf8(trim_null_end(&decrypted)).expect("Not a valid message"); - println!("`{}`", receive_message); assert_eq!(send_message, receive_message); } Ok(()) diff --git a/crates/tests/literals/Cargo.toml b/crates/tests/literals/Cargo.toml index e365dc935f..f7420f76bf 100644 --- a/crates/tests/literals/Cargo.toml +++ b/crates/tests/literals/Cargo.toml @@ -6,3 +6,6 @@ edition = "2018" [dependencies.windows] path = "../../libs/windows" + +[dependencies.windows-sys] +path = "../../libs/sys" diff --git a/crates/tests/literals/tests/sys.rs b/crates/tests/literals/tests/sys.rs new file mode 100644 index 0000000000..5c7fce122f --- /dev/null +++ b/crates/tests/literals/tests/sys.rs @@ -0,0 +1,42 @@ +use windows_sys::core::*; + +#[test] +fn test() { + const A: PCSTR = s!(""); + assert_utf8(A, &[0]); + + const B: PCWSTR = w!(""); + assert_utf16(B, &[0]); + + assert_utf8(s!("hello"), &[b'h', b'e', b'l', b'l', b'o', 0]); + assert_utf16(w!("hello!"), &[0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x21, 0]); + assert_utf16(w!("α & ω ❤"), &[0x03B1, 0x20, 0x26, 0x20, 0x03C9, 0x20, 0x2764, 0]); + + assert_utf16(w!("\u{007f}"), &[0x007f, 0]); // Largest one byte UTF8 sequence + assert_utf16(w!("\u{0080}"), &[0x0080, 0]); // Smallest two byte UTF8 sequence + assert_utf16(w!("\u{07ff}"), &[0x07ff, 0]); // Largest two byte UTF8 sequence + assert_utf16(w!("\u{0800}"), &[0x0800, 0]); // Smallest three byte UTF8 sequence + assert_utf16(w!("\u{d7ff}"), &[0xd7ff, 0]); // Highest code point below surrogate range + assert_utf16(w!("\u{e000}"), &[0xe000, 0]); // Smallest code point above surrogate range + assert_utf16(w!("\u{010000}"), &[0xD800, 0xDC00, 0]); // Smallest four byte UTF8 sequence + assert_utf16(w!("\u{10ffff}"), &[0xDBFF, 0xDFFF, 0]); // Largest Unicode code point +} + +fn assert_utf8(left: PCSTR, right: &[u8]) { + let len = unsafe { strlen(left) }; + assert_eq!(len, right.len() - 1); + let left = unsafe { std::slice::from_raw_parts(left, right.len()) }; + assert_eq!(left, right); +} + +fn assert_utf16(left: PCWSTR, right: &[u16]) { + let len = unsafe { wcslen(left) }; + assert_eq!(len, right.len() - 1); + let left = unsafe { std::slice::from_raw_parts(left, right.len()) }; + assert_eq!(left, right); +} + +extern "C" { + pub fn strlen(s: PCSTR) -> usize; + pub fn wcslen(s: PCWSTR) -> usize; +} diff --git a/crates/tests/literals/tests/tests.rs b/crates/tests/literals/tests/win.rs similarity index 97% rename from crates/tests/literals/tests/tests.rs rename to crates/tests/literals/tests/win.rs index 57be90425c..25235dfc09 100644 --- a/crates/tests/literals/tests/tests.rs +++ b/crates/tests/literals/tests/win.rs @@ -1,5 +1,4 @@ -use windows::core::{HSTRING, PCSTR, PCWSTR}; -use windows::{s, w}; +use windows::core::*; #[test] fn test() { diff --git a/crates/tests/return_struct/Cargo.toml b/crates/tests/return_struct/Cargo.toml index d4c28a1479..acd0580802 100644 --- a/crates/tests/return_struct/Cargo.toml +++ b/crates/tests/return_struct/Cargo.toml @@ -9,3 +9,9 @@ path = "../../libs/windows" features = [ "Win32_Graphics_Direct2D_Common" ] + +[dependencies.windows-sys] +path = "../../libs/sys" +features = [ + "Win32_Graphics_Direct2D_Common" +] diff --git a/crates/tests/return_struct/tests/sys.rs b/crates/tests/return_struct/tests/sys.rs new file mode 100644 index 0000000000..ef3927f92b --- /dev/null +++ b/crates/tests/return_struct/tests/sys.rs @@ -0,0 +1,21 @@ +// This test validates that free functions are not affected by the Visual C++ quirk affecting member functions +// returning structs where the return value is effectively a trailing out parameter. +// +// TODO: D2D1ConvertColorSpace is exported by ordinal rather than by name and Rust doesn't appear to support +// this at the moment. It happens to work on x64 but not on x86, hence the cfg check below. +#[test] +#[cfg(target_pointer_width = "64")] +fn test() { + use windows_sys::Win32::Graphics::Direct2D::{Common::*, *}; + + let before = D2D1_COLOR_F { r: 1.0, g: 2.0, b: 3.0, a: 4.0 }; + + let after = unsafe { D2D1ConvertColorSpace(D2D1_COLOR_SPACE_SRGB, D2D1_COLOR_SPACE_SCRGB, &before) }; + + let expected = D2D1_COLOR_F { r: 1.0, g: 1.0, b: 1.0, a: 4.0 }; + + assert!(after.r == expected.r); + assert!(after.g == expected.g); + assert!(after.b == expected.b); + assert!(after.a == expected.a); +} diff --git a/crates/tests/return_struct/tests/free_function.rs b/crates/tests/return_struct/tests/win.rs similarity index 100% rename from crates/tests/return_struct/tests/free_function.rs rename to crates/tests/return_struct/tests/win.rs diff --git a/crates/tests/unions/Cargo.toml b/crates/tests/unions/Cargo.toml index 15b72ab40d..2c3d9529ba 100644 --- a/crates/tests/unions/Cargo.toml +++ b/crates/tests/unions/Cargo.toml @@ -11,3 +11,11 @@ features = [ "Win32_Graphics_Direct3D12", "Win32_System_IO", ] + +[dependencies.windows-sys] +path = "../../libs/sys" +features = [ + "Win32_Foundation", + "Win32_Graphics_Direct3D12", + "Win32_System_IO", +] diff --git a/crates/tests/unions/tests/indirect_argument_desc.rs b/crates/tests/unions/tests/indirect_argument_desc.rs deleted file mode 100644 index 006deec6da..0000000000 --- a/crates/tests/unions/tests/indirect_argument_desc.rs +++ /dev/null @@ -1,23 +0,0 @@ -use windows::Win32::Graphics::Direct3D12::*; - -#[test] -fn test() { - assert_eq!(core::mem::size_of::(), 16); - - assert_eq!(D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW.0, 3); - - let mut desc = D3D12_INDIRECT_ARGUMENT_DESC { - Type: D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, - Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 { VertexBuffer: D3D12_INDIRECT_ARGUMENT_DESC_0_4 { Slot: 123 } }, - }; - - assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW); - - desc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT; - - assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT); - - unsafe { - assert_eq!(desc.Anonymous.VertexBuffer.Slot, 123); - } -} diff --git a/crates/tests/unions/tests/sys.rs b/crates/tests/unions/tests/sys.rs new file mode 100644 index 0000000000..0a2f5bf03a --- /dev/null +++ b/crates/tests/unions/tests/sys.rs @@ -0,0 +1,85 @@ +use windows_sys::Win32::{ + Graphics::Direct3D12::*, + System::IO::{OVERLAPPED, OVERLAPPED_0_0}, +}; + +#[test] +fn test() { + let mut o = OVERLAPPED { Internal: 1, InternalHigh: 2, Anonymous: unsafe { std::mem::zeroed() }, hEvent: Default::default() }; + + assert_eq!(o.Internal, 1); + o.Internal = 10; + assert_eq!(o.Internal, 10); + + assert_eq!(o.InternalHigh, 2); + o.InternalHigh = 20; + assert_eq!(o.InternalHigh, 20); + + assert_eq!(o.hEvent, 0); + o.hEvent = 1; + assert_eq!(o.hEvent, 1); + + unsafe { + assert_eq!(o.Anonymous.Pointer, core::ptr::null_mut()); + } + + unsafe { + assert_eq!(o.Anonymous.Anonymous.Offset, 0); + assert_eq!(o.Anonymous.Anonymous.OffsetHigh, 0); + } + + o.Anonymous.Anonymous.Offset = 100; + o.Anonymous.Anonymous.OffsetHigh = 200; + + unsafe { + assert_eq!(o.Anonymous.Anonymous.Offset, 100); + assert_eq!(o.Anonymous.Anonymous.OffsetHigh, 200); + } + + o.Anonymous.Anonymous = OVERLAPPED_0_0 { Offset: 10, OffsetHigh: 20 }; + + unsafe { + assert_eq!(o.Anonymous.Anonymous.Offset, 10); + assert_eq!(o.Anonymous.Anonymous.OffsetHigh, 20); + } +} + +#[test] +#[cfg(target_arch = "aarch64")] +fn test_arch() { + assert_eq!(core::mem::size_of::(), 32); +} + +#[test] +#[cfg(target_arch = "x86_64")] +fn test_arch() { + assert_eq!(core::mem::size_of::(), 32); +} + +#[test] +#[cfg(target_arch = "x86")] +fn test_arch() { + assert_eq!(core::mem::size_of::(), 20); +} + +#[test] +fn d3d() { + assert_eq!(core::mem::size_of::(), 16); + + assert_eq!(D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, 3); + + let mut desc = D3D12_INDIRECT_ARGUMENT_DESC { + Type: D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, + Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 { VertexBuffer: D3D12_INDIRECT_ARGUMENT_DESC_0_4 { Slot: 123 } }, + }; + + assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW); + + desc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT; + + assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT); + + unsafe { + assert_eq!(desc.Anonymous.VertexBuffer.Slot, 123); + } +} diff --git a/crates/tests/unions/tests/overlapped.rs b/crates/tests/unions/tests/win.rs similarity index 68% rename from crates/tests/unions/tests/overlapped.rs rename to crates/tests/unions/tests/win.rs index 6e2ef987bc..03943ed450 100644 --- a/crates/tests/unions/tests/overlapped.rs +++ b/crates/tests/unions/tests/win.rs @@ -1,5 +1,6 @@ use windows::Win32::{ Foundation::HANDLE, + Graphics::Direct3D12::*, System::IO::{OVERLAPPED, OVERLAPPED_0_0}, }; @@ -61,3 +62,25 @@ fn test_arch() { fn test_arch() { assert_eq!(core::mem::size_of::(), 20); } + +#[test] +fn d3d() { + assert_eq!(core::mem::size_of::(), 16); + + assert_eq!(D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW.0, 3); + + let mut desc = D3D12_INDIRECT_ARGUMENT_DESC { + Type: D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW, + Anonymous: D3D12_INDIRECT_ARGUMENT_DESC_0 { VertexBuffer: D3D12_INDIRECT_ARGUMENT_DESC_0_4 { Slot: 123 } }, + }; + + assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW); + + desc.Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT; + + assert_eq!(desc.Type, D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT); + + unsafe { + assert_eq!(desc.Anonymous.VertexBuffer.Slot, 123); + } +}