diff --git a/packaging/windows/drivers/pf-vdisplay/src/adapter.rs b/packaging/windows/drivers/pf-vdisplay/src/adapter.rs index 2e9b198..bbb3601 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/adapter.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/adapter.rs @@ -66,6 +66,8 @@ pub fn init_adapter(device: WDFDEVICE) -> NTSTATUS { // Firmware/hardware version (telemetry). The oracle points BOTH at one IDDCX_ENDPOINT_VERSION. // `version` is a stack local read synchronously by IddCxAdapterInitAsync (same as the oracle). `.Size` // is `size_of` throughout — these are the IddCx 1.10 structs and the framework here is 1.10 (= upstream). + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDDCX_ENDPOINT_VERSION; + // the required `.Size` (+ version fields) are set immediately below before the struct is used. let mut version: iddcx::IDDCX_ENDPOINT_VERSION = unsafe { core::mem::zeroed() }; version.Size = core::mem::size_of::() as u32; version.MajorVer = env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap_or(0); @@ -76,6 +78,8 @@ pub fn init_adapter(device: WDFDEVICE) -> NTSTATUS { // zeroed value is IDDCX_FEATURE_IMPLEMENTATION_UNINITIALIZED (0), which the framework's adapter Validate // rejects with INVALID_PARAMETER (ddivalidation.cpp:797) — set it to NONE (1) like upstream. THIS was // the on-glass adapter-init blocker. + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // IDDCX_ENDPOINT_DIAGNOSTIC_INFO; the required `.Size` (+ the fields read by Validate) are set below. let mut diag: iddcx::IDDCX_ENDPOINT_DIAGNOSTIC_INFO = unsafe { core::mem::zeroed() }; diag.Size = core::mem::size_of::() as u32; diag.GammaSupport = iddcx::IDDCX_FEATURE_IMPLEMENTATION::IDDCX_FEATURE_IMPLEMENTATION_NONE; @@ -83,9 +87,13 @@ pub fn init_adapter(device: WDFDEVICE) -> NTSTATUS { diag.pEndPointFriendlyName = wstr!("punktfunk Virtual Display Adapter"); diag.pEndPointManufacturerName = wstr!("punktfunk"); diag.pEndPointModelName = wstr!("Virtual Display"); + // SAFETY: `version` is a stack local that outlives this `init_adapter` call; IddCxAdapterInitAsync + // (below) reads through these pointers SYNCHRONOUSLY, before `version` drops — the pointer never escapes. diag.pFirmwareVersion = (&raw mut version).cast(); diag.pHardwareVersion = (&raw mut version).cast(); + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDDCX_ADAPTER_CAPS; + // the required `.Size` (+ flags/limits/diag) are set immediately below. let mut caps: iddcx::IDDCX_ADAPTER_CAPS = unsafe { core::mem::zeroed() }; caps.Size = core::mem::size_of::() as u32; // STEP 7 (HDR): declare we can process FP16 (scRGB) desktop surfaces — this is what marks the virtual @@ -101,6 +109,8 @@ pub fn init_adapter(device: WDFDEVICE) -> NTSTATUS { // The adapter WDF object's attributes: Size + Synchronization/Execution = InheritFromParent (NOT zeroed, // since zero = *Invalid*) + the adapter context type (STEP 4 stores adapter state here). + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized WDF_OBJECT_ATTRIBUTES; + // the required `.Size` (+ execution/sync scope + context type) are set immediately below. let mut attr: wdk_sys::WDF_OBJECT_ATTRIBUTES = unsafe { core::mem::zeroed() }; attr.Size = core::mem::size_of::() as u32; attr.ExecutionLevel = wdk_sys::_WDF_EXECUTION_LEVEL::WdfExecutionLevelInheritFromParent; @@ -112,6 +122,8 @@ pub fn init_adapter(device: WDFDEVICE) -> NTSTATUS { pCaps: &raw mut caps, ObjectAttributes: &raw mut attr, }; + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDARG_OUT_ADAPTER_INIT + // (an out-param the framework fills). let mut out: iddcx::IDARG_OUT_ADAPTER_INIT = unsafe { core::mem::zeroed() }; // SAFETY: `init`/`out` are valid local storage; IddCxAdapterInitAsync reads the caps synchronously // (the adapter object itself is delivered later via adapter_init_finished). Called once per device. diff --git a/packaging/windows/drivers/pf-vdisplay/src/callbacks.rs b/packaging/windows/drivers/pf-vdisplay/src/callbacks.rs index 917cc1d..1d067a0 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/callbacks.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/callbacks.rs @@ -70,6 +70,8 @@ pub unsafe extern "C" fn parse_monitor_description( // SAFETY: `pMonitorModes` points to >= `count` IDDCX_MONITOR_MODE entries (validated above). let out = unsafe { core::slice::from_raw_parts_mut(in_args.pMonitorModes, count as usize) }; for (item, slot) in crate::monitor::flatten(&modes).zip(out.iter_mut()) { + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDDCX_MONITOR_MODE; + // the required `.Size` (+ origin / signal info) are set immediately below. let mut mode: iddcx::IDDCX_MONITOR_MODE = unsafe { core::mem::zeroed() }; mode.Size = core::mem::size_of::() as u32; mode.Origin = iddcx::IDDCX_MONITOR_MODE_ORIGIN::IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR; @@ -119,6 +121,8 @@ pub unsafe extern "C" fn parse_monitor_description2( // SAFETY: `pMonitorModes` points to >= `count` IDDCX_MONITOR_MODE2 entries (validated above). let out = unsafe { core::slice::from_raw_parts_mut(in_args.pMonitorModes, count as usize) }; for (item, slot) in crate::monitor::flatten(&modes).zip(out.iter_mut()) { + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDDCX_MONITOR_MODE2; + // the required `.Size` (+ origin / signal info / bit depth) are set immediately below. let mut mode: iddcx::IDDCX_MONITOR_MODE2 = unsafe { core::mem::zeroed() }; mode.Size = core::mem::size_of::() as u32; mode.Origin = iddcx::IDDCX_MONITOR_MODE_ORIGIN::IDDCX_MONITOR_MODE_ORIGIN_MONITORDESCRIPTOR; diff --git a/packaging/windows/drivers/pf-vdisplay/src/direct_3d_device.rs b/packaging/windows/drivers/pf-vdisplay/src/direct_3d_device.rs index fe4ce5d..b028c7f 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/direct_3d_device.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/direct_3d_device.rs @@ -60,14 +60,18 @@ pub struct Direct3DDevice { impl Direct3DDevice { pub fn init(adapter_luid: LUID) -> Result { + // SAFETY: a plain DXGI factory-creation call; `?` returns the error on failure. let dxgi_factory = unsafe { CreateDXGIFactory2::(DXGI_CREATE_FACTORY_FLAGS(0))? }; + // SAFETY: `dxgi_factory` is the live factory just created; `adapter_luid` is a by-value LUID. let adapter = unsafe { dxgi_factory.EnumAdapterByLuid::(adapter_luid)? }; let mut device = None; let mut device_context = None; + // SAFETY: `adapter` is a live IDXGIAdapter1; `device`/`device_context` are valid local out-params + // (checked for None below); the flag set + SDK version are valid constants. `?` returns on failure. unsafe { D3D11CreateDevice( &adapter, diff --git a/packaging/windows/drivers/pf-vdisplay/src/entry.rs b/packaging/windows/drivers/pf-vdisplay/src/entry.rs index d342069..4126844 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/entry.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/entry.rs @@ -60,6 +60,8 @@ pub unsafe extern "system" fn driver_entry( extern "C" fn driver_add(_driver: WDFDRIVER, mut init: PWDFDEVICE_INIT) -> NTSTATUS { dbglog!("[pf-vd] driver_add"); // Defer adapter creation to the first D0 entry. + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // WDF_PNPPOWER_EVENT_CALLBACKS; the required `.Size` (+ the D0-entry callback) are set immediately below. let mut pnp: WDF_PNPPOWER_EVENT_CALLBACKS = unsafe { core::mem::zeroed() }; pnp.Size = core::mem::size_of::() as ULONG; pnp.EvtDeviceD0Entry = Some(callbacks::device_d0_entry); @@ -69,6 +71,8 @@ extern "C" fn driver_add(_driver: WDFDRIVER, mut init: PWDFDEVICE_INIT) -> NTSTA } // Build the IddCx client config and wire the SDR callbacks. `.Size` = size_of (1.10 structs, 1.10 fw). + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDD_CX_CLIENT_CONFIG; + // the required `.Size` (+ the IddCx client callbacks) are set immediately below. let mut cfg: iddcx::IDD_CX_CLIENT_CONFIG = unsafe { core::mem::zeroed() }; cfg.Size = core::mem::size_of::() as u32; cfg.EvtIddCxAdapterInitFinished = Some(callbacks::adapter_init_finished); @@ -101,6 +105,8 @@ extern "C" fn driver_add(_driver: WDFDRIVER, mut init: PWDFDEVICE_INIT) -> NTSTA let mut device: WDFDEVICE = core::ptr::null_mut(); // Attach a device context type (like the working virtual-display-rs/oracle), not WDF_NO_OBJECT_ATTRIBUTES. + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized WDF_OBJECT_ATTRIBUTES; + // the required `.Size` (+ execution/sync scope + context type) are set immediately below. let mut dev_attr: wdk_sys::WDF_OBJECT_ATTRIBUTES = unsafe { core::mem::zeroed() }; dev_attr.Size = core::mem::size_of::() as u32; dev_attr.ExecutionLevel = wdk_sys::_WDF_EXECUTION_LEVEL::WdfExecutionLevelInheritFromParent; diff --git a/packaging/windows/drivers/pf-vdisplay/src/frame_transport.rs b/packaging/windows/drivers/pf-vdisplay/src/frame_transport.rs index 34e2358..c85e56a 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/frame_transport.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/frame_transport.rs @@ -90,6 +90,7 @@ impl FramePublisher { context: &ID3D11DeviceContext, ) -> windows::core::Result { // 1. Open the host-created header (RW). Err if the host hasn't created it yet. + // SAFETY: a plain Win32 call; the name HSTRING is valid for the call (`?` returns on failure). let map = unsafe { OpenFileMappingW( FILE_MAP_ALL_ACCESS.0, @@ -97,6 +98,8 @@ impl FramePublisher { &HSTRING::from(header_name(target_id)), )? }; + // SAFETY: `map` is the just-opened file mapping; mapping size_of::() bytes of it + // (the host created the mapping at >= that size). The null `view.Value` is checked below. let view = unsafe { MapViewOfFile( map, @@ -107,6 +110,7 @@ impl FramePublisher { ) }; if view.Value.is_null() { + // SAFETY: `map` is the just-opened mapping handle, closed once here on the error path. unsafe { let _ = CloseHandle(map); } @@ -115,16 +119,21 @@ impl FramePublisher { let header = view.Value.cast::(); // 2. Report our render adapter to the host immediately (lets it detect a mismatch). + // SAFETY: `header` points to the mapped, non-null host header (>= size_of::() bytes); + // these scalar writes are within it. The host opened the section with a permissive SDDL for us. unsafe { (*header).driver_render_luid_low = render_luid_low; (*header).driver_render_luid_high = render_luid_high; } // 3. The host sets magic==MAGIC only once the ring textures exist. Not ready → retry later. + // SAFETY: `header` is the mapped host header; `magic` lives within it and is read atomically + // (Acquire) to pair with the host's Release store once the ring textures are published. let magic = unsafe { (*(core::ptr::addr_of!((*header).magic) as *const AtomicU32)).load(Ordering::Acquire) }; if magic != MAGIC { + // SAFETY: `header`/`map` are the live mapped view + handle; unmapped + closed once on this path. unsafe { let _ = UnmapViewOfFile(MEMORY_MAPPED_VIEW_ADDRESS { Value: header.cast(), @@ -133,10 +142,12 @@ impl FramePublisher { } return Err(windows::core::Error::from_win32()); } + // SAFETY: `header` is the mapped host header; these scalar fields live within it. let (generation, ring_len) = unsafe { ((*header).generation, (*header).ring_len.min(RING_LEN)) }; // 4. Open the event (SYNCHRONIZE | EVENT_MODIFY_STATE so we can SetEvent). + // SAFETY: a plain Win32 call; the name HSTRING is valid for the call. let event = match unsafe { OpenEventW( SYNCHRONIZATION_ACCESS_RIGHTS(EVENT_ACCESS), @@ -146,6 +157,7 @@ impl FramePublisher { } { Ok(e) => e, Err(e) => { + // SAFETY: `header`/`map` are the live mapped view + handle; unmapped + closed once here. unsafe { let _ = UnmapViewOfFile(MEMORY_MAPPED_VIEW_ADDRESS { Value: header.cast(), @@ -160,6 +172,8 @@ impl FramePublisher { let device1: ID3D11Device1 = match device.cast() { Ok(d) => d, Err(e) => { + // SAFETY: `header` is the mapped host header (status write within it); `event`/`map` are the + // live handles, all released once on this error path. unsafe { (*header).driver_status = DRV_STATUS_NO_DEVICE1; let _ = CloseHandle(event); @@ -174,12 +188,15 @@ impl FramePublisher { let mut slots = Vec::new(); for k in 0..ring_len { let name = HSTRING::from(texture_name(target_id, generation, k)); + // SAFETY: `device1` is a live ID3D11Device1; the name HSTRING is valid for the call. let opened: windows::core::Result = unsafe { device1.OpenSharedResourceByName(&name, DXGI_SHARED_RESOURCE_RW) }; match opened { Ok(tex) => match tex.cast::() { Ok(mutex) => slots.push(Slot { tex, mutex }), Err(e) => { + // SAFETY: `header` is the mapped host header (status writes within it); `event`/`map` + // are the live handles, all released once on this error path. unsafe { (*header).driver_status = DRV_STATUS_TEX_FAIL; (*header).driver_status_detail = e.code().0 as u32; @@ -195,6 +212,8 @@ impl FramePublisher { Err(e) => { // Most likely a render-adapter mismatch (the host made the textures on a different // GPU than the swap-chain renders on). Tell the host so it can report it. + // SAFETY: `header` is the mapped host header (status writes within it); `event`/`map` + // are the live handles, all released once on this error path. unsafe { (*header).driver_status = DRV_STATUS_TEX_FAIL; (*header).driver_status_detail = e.code().0 as u32; @@ -209,6 +228,7 @@ impl FramePublisher { } } + // SAFETY: `header` is the mapped host header; the status field lives within it. unsafe { (*header).driver_status = DRV_STATUS_OPENED; } @@ -223,6 +243,7 @@ impl FramePublisher { slots, next: 0, seq: 0, + // SAFETY: `header` is the mapped host header; `dxgi_format` lives within it. ring_format: unsafe { (*header).dxgi_format }, generation, }) @@ -230,6 +251,8 @@ impl FramePublisher { #[inline] fn latest_cell(&self) -> &AtomicU64 { + // SAFETY: `self.header` stays mapped for the publisher's lifetime (unmapped only in Drop); the + // `latest` field lives within it and is naturally aligned, so this AtomicU64 reference is valid. unsafe { &*(core::ptr::addr_of!((*self.header).latest) as *const AtomicU64) } } @@ -237,6 +260,8 @@ impl FramePublisher { /// mode flipped, so the ring format changed (FP16 ⇄ BGRA) and the texture names now carry a new /// generation. `run_core` drops the publisher on this so it re-attaches to the new ring. pub fn is_stale(&self) -> bool { + // SAFETY: `self.header` stays mapped for the publisher's lifetime; `generation` lives within it and + // is read atomically (Acquire) to pair with the host's Release bump on a mid-session ring recreate. let cur = unsafe { (*(core::ptr::addr_of!((*self.header).generation) as *const AtomicU32)) .load(Ordering::Acquire) @@ -254,6 +279,7 @@ impl FramePublisher { // frame that doesn't match (e.g. an FP16 HDR surface arriving while the ring is still BGRA, before // the host recreates the ring as FP16) instead of corrupting / failing the copy. let mut desc = D3D11_TEXTURE2D_DESC::default(); + // SAFETY: `surface` is a live ID3D11Texture2D (borrowed from IddCx); `desc` is a valid local out-param. unsafe { surface.GetDesc(&mut desc) }; if desc.Format.0 as u32 != self.ring_format { return; @@ -262,6 +288,8 @@ impl FramePublisher { for attempt in 0..ring_len { let slot = (start + attempt) % ring_len; let s = &self.slots[slot as usize]; + // SAFETY: `s.mutex` is the live keyed mutex on this ring slot's shared texture; a 0 ms + // try-acquire of key 0 (released below or on WAIT_TIMEOUT it's never held). match unsafe { s.mutex.AcquireSync(0, 0) } { Ok(()) => { // STRAIGHT-LINE, NO `?` between acquire + release — a `?`-return here would leak the @@ -269,6 +297,8 @@ impl FramePublisher { // the CopyResource is GPU-ordered before the consumer via the slot keyed mutex, and the // `latest` store (Release) publishes the slot only AFTER the copy is queued + the mutex // released. + // SAFETY: `s.tex`/`surface` are live, format-matched (checked above) D3D textures on + // `self.context`'s device; the keyed mutex is held here, so we release it exactly once. unsafe { self.context.CopyResource(&s.tex, surface); let _ = s.mutex.ReleaseSync(0); @@ -285,6 +315,8 @@ impl FramePublisher { } .pack(); self.latest_cell().store(latest, Ordering::Release); + // SAFETY: `self.event` is the live host-created frame-ready event we opened with + // EVENT_MODIFY_STATE; signalling it wakes the host consumer. unsafe { let _ = SetEvent(self.event); } @@ -304,6 +336,8 @@ impl Drop for FramePublisher { // Slots FIRST (release the shared textures + keyed mutexes), THEN unmap the header, THEN the // handles. self.slots.clear(); + // SAFETY: drop runs once; `self.header` (if non-null) is the live mapped view and `self.event`/ + // `self.map` are the live handles this publisher opened — each unmapped/closed exactly once here. unsafe { if !self.header.is_null() { let _ = UnmapViewOfFile(MEMORY_MAPPED_VIEW_ADDRESS { diff --git a/packaging/windows/drivers/pf-vdisplay/src/monitor.rs b/packaging/windows/drivers/pf-vdisplay/src/monitor.rs index a5a4645..b1d0d24 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/monitor.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/monitor.rs @@ -87,6 +87,8 @@ pub fn display_info( refresh_rate: u32, ) -> wdk_sys::DISPLAYCONFIG_VIDEO_SIGNAL_INFO { let clock_rate = refresh_rate * (height + 4) * (height + 4) + 1000; + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // DISPLAYCONFIG_VIDEO_SIGNAL_INFO; every meaningful field is assigned below. let mut si: wdk_sys::DISPLAYCONFIG_VIDEO_SIGNAL_INFO = unsafe { core::mem::zeroed() }; si.pixelRate = u64::from(clock_rate); si.hSyncFreq = wdk_sys::DISPLAYCONFIG_RATIONAL { @@ -118,6 +120,8 @@ pub fn target_mode(width: u32, height: u32, refresh_rate: u32) -> iddcx::IDDCX_T cx: width, cy: height, }; + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // DISPLAYCONFIG_VIDEO_SIGNAL_INFO; every meaningful field is assigned below. let mut si: wdk_sys::DISPLAYCONFIG_VIDEO_SIGNAL_INFO = unsafe { core::mem::zeroed() }; si.pixelRate = u64::from(refresh_rate) * u64::from(width) * u64::from(height); si.hSyncFreq = wdk_sys::DISPLAYCONFIG_RATIONAL { @@ -134,6 +138,8 @@ pub fn target_mode(width: u32, height: u32, refresh_rate: u32) -> iddcx::IDDCX_T wdk_sys::DISPLAYCONFIG_SCANLINE_ORDERING::DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE; // videoStandard=255, vSyncFreqDivider=1 (bits 16..21) => 255 | (1<<16). si.__bindgen_anon_1.videoStandard = 255 | (1 << 16); + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDDCX_TARGET_MODE; + // the required `.Size` (+ signal info) are set immediately below. let mut tm: iddcx::IDDCX_TARGET_MODE = unsafe { core::mem::zeroed() }; tm.Size = core::mem::size_of::() as u32; tm.TargetVideoSignalInfo = wdk_sys::DISPLAYCONFIG_TARGET_MODE { @@ -151,6 +157,8 @@ pub fn target_mode(width: u32, height: u32, refresh_rate: u32) -> iddcx::IDDCX_T pub fn wire_bits() -> iddcx::IDDCX_WIRE_BITS_PER_COMPONENT { let rgb = iddcx::IDDCX_BITS_PER_COMPONENT::IDDCX_BITS_PER_COMPONENT_8 | iddcx::IDDCX_BITS_PER_COMPONENT::IDDCX_BITS_PER_COMPONENT_10; + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // IDDCX_WIRE_BITS_PER_COMPONENT; every field is assigned below. let mut w: iddcx::IDDCX_WIRE_BITS_PER_COMPONENT = unsafe { core::mem::zeroed() }; w.Rgb = rgb; w.YCbCr444 = iddcx::IDDCX_BITS_PER_COMPONENT::IDDCX_BITS_PER_COMPONENT_NONE; @@ -164,6 +172,8 @@ pub fn wire_bits() -> iddcx::IDDCX_WIRE_BITS_PER_COMPONENT { /// zeroed. pub fn target_mode2(width: u32, height: u32, refresh_rate: u32) -> iddcx::IDDCX_TARGET_MODE2 { let m1 = target_mode(width, height, refresh_rate); + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDDCX_TARGET_MODE2; + // the required `.Size` (+ signal info + bit depth) are set immediately below. let mut tm: iddcx::IDDCX_TARGET_MODE2 = unsafe { core::mem::zeroed() }; tm.Size = core::mem::size_of::() as u32; tm.TargetVideoSignalInfo = m1.TargetVideoSignalInfo; @@ -275,12 +285,18 @@ pub fn create_monitor( // EDID (serial = id) describes the monitor; the OS calls back into parse_monitor_description. let mut edid = crate::edid::Edid::generate_with(id); + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // IDDCX_MONITOR_DESCRIPTION; the required `.Size`/Type/DataSize/pData are set immediately below. let mut desc: iddcx::IDDCX_MONITOR_DESCRIPTION = unsafe { core::mem::zeroed() }; desc.Size = core::mem::size_of::() as u32; desc.Type = iddcx::IDDCX_MONITOR_DESCRIPTION_TYPE::IDDCX_MONITOR_DESCRIPTION_TYPE_EDID; desc.DataSize = edid.len() as u32; + // SAFETY: `edid` is a local Vec that outlives this `create_monitor` call; IddCxMonitorCreate (below) + // reads through `pData` SYNCHRONOUSLY, before `edid` drops — the pointer never escapes the call. desc.pData = edid.as_mut_ptr().cast(); + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDDCX_MONITOR_INFO; + // the required `.Size` (+ container id / type / connector / description) are set immediately below. let mut info: iddcx::IDDCX_MONITOR_INFO = unsafe { core::mem::zeroed() }; info.Size = core::mem::size_of::() as u32; info.MonitorContainerId = container_guid(id); @@ -289,6 +305,8 @@ pub fn create_monitor( info.ConnectorIndex = id; info.MonitorDescription = desc; + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized WDF_OBJECT_ATTRIBUTES; + // the required `.Size` (+ execution/sync scope) are set immediately below. let mut attr: wdk_sys::WDF_OBJECT_ATTRIBUTES = unsafe { core::mem::zeroed() }; attr.Size = core::mem::size_of::() as u32; attr.ExecutionLevel = wdk_sys::_WDF_EXECUTION_LEVEL::WdfExecutionLevelInheritFromParent; @@ -299,6 +317,8 @@ pub fn create_monitor( ObjectAttributes: &raw mut attr, pMonitorInfo: &raw mut info, }; + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDARG_OUT_MONITORCREATE + // (an out-param the framework fills). let mut create_out: iddcx::IDARG_OUT_MONITORCREATE = unsafe { core::mem::zeroed() }; // SAFETY: adapter is a valid IddCx adapter; create_in points to valid local storage read synchronously. let st = unsafe { wdk_iddcx::IddCxMonitorCreate(adapter, &create_in, &mut create_out) }; @@ -315,6 +335,8 @@ pub fn create_monitor( } // Tell the OS the monitor is plugged in. + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized IDARG_OUT_MONITORARRIVAL + // (an out-param the framework fills). let mut arrival_out: iddcx::IDARG_OUT_MONITORARRIVAL = unsafe { core::mem::zeroed() }; // SAFETY: `monitor` is the just-created IddCx monitor handle. let st = unsafe { wdk_iddcx::IddCxMonitorArrival(monitor, &mut arrival_out) }; diff --git a/packaging/windows/drivers/pf-vdisplay/src/swap_chain_processor.rs b/packaging/windows/drivers/pf-vdisplay/src/swap_chain_processor.rs index 50c196f..26a86f3 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/swap_chain_processor.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/swap_chain_processor.rs @@ -112,6 +112,8 @@ impl SwapChainProcessor { // Service. It will intelligently prioritize the thread for improved throughput in high // CPU-load scenarios. let mut av_task = 0u32; + // SAFETY: `w!("Distribution")` is a 'static null-terminated UTF-16 task name; `av_task` is a + // valid local out-param. The returned handle is reverted with AvRevertMmThreadCharacteristics. let res = unsafe { AvSetMmThreadCharacteristicsW(w!("Distribution"), &mut av_task) }; let Ok(av_handle) = res else { dbglog!("[pf-vd] swap-chain: failed to prioritize thread: {res:?}"); @@ -141,6 +143,8 @@ impl SwapChainProcessor { } // Revert the thread to normal once it's done. + // SAFETY: `av_handle` is the live characteristics handle returned by AvSetMmThreadCharacteristicsW + // above, reverted exactly once here at thread exit. let res = unsafe { AvRevertMmThreadCharacteristics(av_handle) }; if let Err(e) = res { dbglog!("[pf-vd] swap-chain: failed to revert prioritized thread: {e:?}"); @@ -179,6 +183,8 @@ impl SwapChainProcessor { } }; // Built zeroed + field-assigned (driver style) — robust against a bindgen field-set difference. + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // IDARG_IN_SWAPCHAINSETDEVICE; the `pDevice` field is set immediately below. let mut set_device: IDARG_IN_SWAPCHAINSETDEVICE = unsafe { core::mem::zeroed() }; set_device.pDevice = dxgi_device.as_raw().cast(); let mut set_ok = false; @@ -274,6 +280,8 @@ impl SwapChainProcessor { // the GPU surface (out.MetaData.pSurface) — STEP 6 publishes it into the shared ring in the // success branch below. Built zeroed + field-assigned (driver style) so a bindgen field-set // difference can't break a positional struct literal. + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // IDARG_IN_RELEASEANDACQUIREBUFFER2; the required `.Size`/AcquireSystemMemoryBuffer are set below. let mut in_args: IDARG_IN_RELEASEANDACQUIREBUFFER2 = unsafe { core::mem::zeroed() }; #[allow(clippy::cast_possible_truncation)] { @@ -283,6 +291,8 @@ impl SwapChainProcessor { // `core::mem::zeroed()` (not `::default()`) — consistent with every other IddCx out-struct // in this driver, and robust whether or not bindgen derives `Default` for this type (its // `MetaData` field carries a raw `pSurface` pointer + union which can suppress the derive). + // SAFETY: building a C POD — the all-zero bit pattern is a valid uninitialized + // IDARG_OUT_RELEASEANDACQUIREBUFFER2 (an out-param the framework fills). let mut buffer: IDARG_OUT_RELEASEANDACQUIREBUFFER2 = unsafe { core::mem::zeroed() }; // SAFETY: driver is loaded; `swap_chain` is valid; in/out point to valid local storage. let hr: NTSTATUS = unsafe {