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 }