From 725e596d2b09bcca615dc3b7c7fa583d2a67877f Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Wed, 24 Jun 2026 18:25:07 +0000 Subject: [PATCH] feat(windows-drivers): adapter WDF context type + init-before-interface (match SudoVDA) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On-glass diagnosis narrowed decisively. PROVEN it is the driver, NOT the box: enabling the installed SudoVDA devnode -> Status=OK (the box inits a self-signed IddCx adapter right now). SudoVDA uses the IDENTICAL UmdfExtensions=IddCx0102 and is built against IddCx 1.10 (DriverVer 1.10.9.289) — exactly our config. Matched SudoVDA/the oracle on every inspectable dimension, none fixed the IddCxAdapterInitAsync INVALID_PARAMETER: caps byte-perfect (offsets+sizes vs C + framework table), minimal SDR adapter fails identically, dispatch byte-identical to the oracle (IddFunctions[idx] + IddDriverGlobals), IddMinimumVersionRequired=4 (same as oracle), version pointers, ObjectAttributes, init order, and now an adapter WDF context type (this commit). The remaining difference is the Rust binary itself vs SudoVDA C++. Next: capture IddCx ETW/WPP rejection reason (or kernel debugger), or build the oracle (wdf-umdf Rust) on-glass to isolate Rust-wide vs wdk-sys-specific. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../windows/drivers/pf-vdisplay/src/adapter.rs | 17 +++++++++++++++++ .../windows/drivers/pf-vdisplay/src/entry.rs | 17 ++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/packaging/windows/drivers/pf-vdisplay/src/adapter.rs b/packaging/windows/drivers/pf-vdisplay/src/adapter.rs index d0dbd0c..ab8e853 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/adapter.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/adapter.rs @@ -40,6 +40,22 @@ unsafe impl Sync for SendAdapter {} static ADAPTER: OnceLock = OnceLock::new(); +/// A WDF context type for the adapter object. SudoVDA/the oracle create the adapter via +/// `WDF_OBJECT_ATTRIBUTES::init_context_type(..)`; passing attributes with NO `ContextTypeInfo` is the one +/// structural difference left vs the working SudoVDA driver. `WDF_OBJECT_CONTEXT_TYPE_INFO` holds raw +/// pointers (so a Sync wrapper to allow a `static`); `UniqueType` self-references per `WDF_DECLARE_CONTEXT_TYPE`. +#[repr(transparent)] +struct CtxTypeInfo(wdk_sys::WDF_OBJECT_CONTEXT_TYPE_INFO); +// SAFETY: immutable 'static type metadata; the inner raw pointers are 'static and never written. +unsafe impl Sync for CtxTypeInfo {} +static ADAPTER_CTX: CtxTypeInfo = CtxTypeInfo(wdk_sys::WDF_OBJECT_CONTEXT_TYPE_INFO { + Size: core::mem::size_of::() as u32, + ContextName: c"PfVdAdapterCtx".as_ptr().cast(), + ContextSize: core::mem::size_of::(), + UniqueType: &ADAPTER_CTX.0, + EvtDriverGetUniqueContextType: None, +}); + /// Build the adapter caps (FP16/HDR-capable) and kick off the async adapter creation. Called from /// `EvtDeviceD0Entry`; idempotent across re-entrant D0 transitions. pub fn init_adapter(device: WDFDEVICE) -> NTSTATUS { @@ -131,6 +147,7 @@ pub fn init_adapter(device: WDFDEVICE) -> NTSTATUS { attr.ExecutionLevel = wdk_sys::_WDF_EXECUTION_LEVEL::WdfExecutionLevelInheritFromParent; attr.SynchronizationScope = wdk_sys::_WDF_SYNCHRONIZATION_SCOPE::WdfSynchronizationScopeInheritFromParent; + attr.ContextTypeInfo = &ADAPTER_CTX.0; let init = iddcx::IDARG_IN_ADAPTER_INIT { WdfDevice: device, pCaps: &raw mut caps, diff --git a/packaging/windows/drivers/pf-vdisplay/src/entry.rs b/packaging/windows/drivers/pf-vdisplay/src/entry.rs index 80cfa2f..9a7a3f3 100644 --- a/packaging/windows/drivers/pf-vdisplay/src/entry.rs +++ b/packaging/windows/drivers/pf-vdisplay/src/entry.rs @@ -92,6 +92,16 @@ extern "C" fn driver_add(_driver: WDFDRIVER, mut init: PWDFDEVICE_INIT) -> NTSTA return status; } + // IddCx must be initialized on the device BEFORE other device setup (the canonical IddCx sample order). + // We previously created the device interface first — which can leave IddCx not fully ready by D0Entry, + // making IddCxAdapterInitAsync reject (INVALID_PARAMETER) despite byte-perfect caps. + // SAFETY: device is the just-created WDFDEVICE. + let status = unsafe { wdk_iddcx::IddCxDeviceInitialize(device) }; + dbglog!("[pf-vd] IddCxDeviceInitialize -> {status:#x}"); + if !nt_success(status) { + return status; + } + // Expose the owned pf-vdisplay control interface (the host opens this GUID; STEP 4 wires the host // side in lockstep). NOT SudoVDA's GUID. let (d1, d2, d3, d4) = pf_vdisplay_proto::interface_guid_fields(); @@ -111,12 +121,5 @@ extern "C" fn driver_add(_driver: WDFDRIVER, mut init: PWDFDEVICE_INIT) -> NTSTA ) }; dbglog!("[pf-vd] WdfDeviceCreateDeviceInterface -> {status:#x}"); - if !nt_success(status) { - return status; - } - - // SAFETY: device is the just-created WDFDEVICE. - let status = unsafe { wdk_iddcx::IddCxDeviceInitialize(device) }; - dbglog!("[pf-vd] IddCxDeviceInitialize -> {status:#x}"); status }