test(scsi/windows): cross-check all FFI structs + constants vs SDK headers

Audited every #[repr(C)] struct and IOCTL/flag constant in scsi/windows.rs
against the authoritative Windows SDK headers (ntddscsi.h, winioctl.h,
devioctl.h, winnt.h, fileapi.h). All correct except the already-reverted
ScsiPassThroughDirect packing. Add the missing regression guards:
- StoragePropertyQuery layout (STORAGE_PROPERTY_QUERY: 0/4/8, size 12).
- IOCTL/flag constants, with IOCTLs asserted against an independent CTL_CODE
  re-derivation (not a tautological literal) so a mistyped code is caught.
Validated compiling via cargo xwin check --target x86_64-pc-windows-msvc.
This commit is contained in:
Matthew Jackson
2026-06-23 10:44:21 -07:00
parent f177d61bbf
commit e633a7d3af
+55
View File
@@ -686,4 +686,59 @@ mod tests {
assert_eq!(offset_of!(SptwbDirect, sense), 56); assert_eq!(offset_of!(SptwbDirect, sense), 56);
assert_eq!(size_of::<SptwbDirect>(), 56 + K_SENSE_SIZE); assert_eq!(size_of::<SptwbDirect>(), 56 + K_SENSE_SIZE);
} }
/// Cross-checked against `STORAGE_PROPERTY_QUERY` (winioctl.h):
/// `STORAGE_PROPERTY_ID PropertyId; STORAGE_QUERY_TYPE QueryType;
/// BYTE AdditionalParameters[1];`. Both enums are `int`-sized (4 bytes),
/// so PropertyId@0, QueryType@4, AdditionalParameters@8, size 12.
#[test]
fn storage_property_query_matches_sdk_layout() {
use std::mem::{offset_of, size_of};
assert_eq!(offset_of!(StoragePropertyQuery, PropertyId), 0);
assert_eq!(offset_of!(StoragePropertyQuery, QueryType), 4);
assert_eq!(offset_of!(StoragePropertyQuery, AdditionalParameters), 8);
assert_eq!(size_of::<StoragePropertyQuery>(), 12);
}
/// Cross-checked against the Windows SDK headers. Each IOCTL is asserted
/// against an INDEPENDENT re-derivation of the `CTL_CODE` macro
/// (devioctl.h: `(DeviceType<<16) | (Access<<14) | (Function<<2) | Method`),
/// not just its literal — so a mistyped constant fails the derivation, not
/// a tautology. Flag/enum values cite their defining header.
#[test]
fn windows_ffi_constants_match_sdk() {
// CTL_CODE re-derivation. FILE_DEVICE_CONTROLLER=0x4,
// FILE_DEVICE_MASS_STORAGE=0x2D, METHOD_BUFFERED=0,
// FILE_ANY_ACCESS=0, FILE_READ_ACCESS=1, FILE_WRITE_ACCESS=2.
const fn ctl_code(dev: u32, func: u32, method: u32, access: u32) -> u32 {
(dev << 16) | (access << 14) | (func << 2) | method
}
// ntddscsi.h: CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, READ|WRITE)
assert_eq!(
IOCTL_SCSI_PASS_THROUGH_DIRECT,
ctl_code(0x4, 0x405, 0, 1 | 2)
);
// winioctl.h: CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, ANY)
assert_eq!(IOCTL_STORAGE_QUERY_PROPERTY, ctl_code(0x2D, 0x500, 0, 0));
// winioctl.h: CTL_CODE(IOCTL_STORAGE_BASE, 0x0401, METHOD_BUFFERED, READ)
assert_eq!(IOCTL_STORAGE_RESET_DEVICE, ctl_code(0x2D, 0x401, 0, 1));
// winioctl.h STORAGE_PROPERTY_ID / STORAGE_QUERY_TYPE enums.
assert_eq!(STORAGE_ADAPTER_PROPERTY, 1); // StorageAdapterProperty (Device=0, Adapter=1)
assert_eq!(PROPERTY_STANDARD_QUERY, 0); // PropertyStandardQuery
// ntddscsi.h SCSI_IOCTL_DATA_*.
assert_eq!(SCSI_IOCTL_DATA_OUT, 0);
assert_eq!(SCSI_IOCTL_DATA_IN, 1);
assert_eq!(SCSI_IOCTL_DATA_UNSPECIFIED, 2);
// winnt.h GENERIC_* / FILE_SHARE_* / FILE_ATTRIBUTE_*; fileapi.h OPEN_EXISTING.
assert_eq!(GENERIC_READ, 0x8000_0000);
assert_eq!(GENERIC_WRITE, 0x4000_0000);
assert_eq!(FILE_SHARE_READ, 0x1);
assert_eq!(FILE_SHARE_WRITE, 0x2);
assert_eq!(OPEN_EXISTING, 3);
assert_eq!(FILE_ATTRIBUTE_NORMAL, 0x80);
assert_eq!(INVALID_HANDLE_VALUE, -1);
}
} }