## DMF_BusFilter ----------------------------------------------------------------------------------------------------------------------------------- #### Module Summary ----------------------------------------------------------------------------------------------------------------------------------- Implements a bus filter driver pattern that intercepts the `IRP_MN_QUERY_DEVICE_RELATIONS`/`BusRelations` completion path of a WDF FDO and splices a proxy WDM filter device object onto every child PDO reported by the underlying bus driver. The proxy filter sits between the bus driver's PDO and the child devnode's FDO, giving the client driver visibility into PnP, power, and I/O traffic for each child device. This is a standalone dispatch-table-hooking library. It does not use the standard `DMFMODULE` handle or `DMF_*_Create` pattern. Clients interact through a plain `DMF_BusFilter_CONFIG` structure and three lifecycle entry points. Typical client driver usage flow: 1. **DriverEntry** – fill in `DMF_BusFilter_CONFIG` and call `DMF_BusFilter_Initialize` after `WdfDriverCreate` returns. 2. **EvtDriverDeviceAdd** – register `DMF_BusFilter_DeviceAdd` as the `EvtDriverDeviceAdd` callback (or call it directly from a wrapper). Proxy child teardown is automatic. The library registers an internal WDF context cleanup callback on the bus FDO so that any remaining proxy children are drained and destroyed when the FDO is deleted. No client-side cleanup call is required. Available only in kernel-mode builds (`DMF_KERNEL_MODE`). ----------------------------------------------------------------------------------------------------------------------------------- #### Module Configuration ----------------------------------------------------------------------------------------------------------------------------------- ##### DMF_BusFilter_CONFIG_INIT ```` VOID DMF_BusFilter_CONFIG_INIT( _Out_ DMF_BusFilter_CONFIG* BusFilterConfig, _In_ PDRIVER_OBJECT DriverObject ); ```` Zero-initializes a `DMF_BusFilter_CONFIG` structure and sets the required `DriverObject` field. The client must call this macro before setting any optional callback pointers and before passing the config to `DMF_BusFilter_Initialize`. All optional callback pointers default to `NULL`. `DeviceType` defaults to `0`, which causes the library to inherit the device type from each child PDO at attach time. ##### DMF_BusFilter_CONFIG ```` typedef struct { // // The WDM DRIVER_OBJECT for this driver. Required. // _In_ DRIVER_OBJECT* DriverObject; // // Device type for proxy child filter DOs. // 0 causes the library to inherit the type from the PDO (recommended). // _In_ DEVICE_TYPE DeviceType; // // Device characteristics flags for proxy child filter DOs. // FILE_AUTOGENERATED_DEVICE_NAME, FILE_CHARACTERISTIC_TS_DEVICE, // FILE_CHARACTERISTIC_WEBDAV_DEVICE, FILE_DEVICE_IS_MOUNTED, and // FILE_VIRTUAL_VOLUME are masked off by the library before use. // _In_ ULONG DeviceCharacteristics; // // Called before the bus filter FDO is created. // _In_opt_ EVT_DMF_BusFilter_PreBusDeviceAdd* EvtPreBusDeviceAdd; // // Called after the bus filter FDO has been successfully created. // _In_opt_ EVT_DMF_BusFilter_PostBusDeviceAdd* EvtPostBusDeviceAdd; // // Called when a proxy child filter device object has been attached to a PDO. // _In_opt_ EVT_DMF_BusFilter_DeviceAdd* EvtDeviceAdd; // // Called when a proxy child device is about to be destroyed. // _In_opt_ EVT_DMF_BusFilter_DeviceRemove* EvtDeviceRemove; // // Called after IRP_MN_START_DEVICE has been forwarded and the lower stack returned success. // _In_opt_ EVT_DMF_BusFilter_DeviceStarted* EvtDeviceStarted; // // Called when IRP_MN_DEVICE_ENUMERATED reaches the proxy child device. // _In_opt_ EVT_DMF_BusFilter_DeviceEnumerated* EvtDeviceEnumerated; // // Called when IRP_MN_QUERY_ID reaches the proxy child device. // _In_opt_ EVT_DMF_BusFilter_DeviceQueryId* EvtDeviceQueryId; // // Called when IRP_MN_QUERY_INTERFACE reaches the proxy child device. // _In_opt_ EVT_DMF_BusFilter_DeviceQueryInterface* EvtDeviceQueryInterface; } DMF_BusFilter_CONFIG; ```` Member | Description ----|---- DriverObject | The WDM `DRIVER_OBJECT` for this driver, as received by `DriverEntry`. Required; `DMF_BusFilter_Initialize` returns `STATUS_INVALID_PARAMETER` if this is `NULL`. DeviceType | Device type passed to `IoCreateDevice` for each proxy child filter DO. If `0`, the library inherits the type from the PDO at attach time (recommended for most bus filter scenarios). DeviceCharacteristics | Characteristics flags passed to `IoCreateDevice`. `FILE_AUTOGENERATED_DEVICE_NAME`, `FILE_CHARACTERISTIC_TS_DEVICE`, `FILE_CHARACTERISTIC_WEBDAV_DEVICE`, `FILE_DEVICE_IS_MOUNTED`, and `FILE_VIRTUAL_VOLUME` are always masked off by the library. EvtPreBusDeviceAdd | Optional callback invoked before the bus filter FDO is created. See `EVT_DMF_BusFilter_PreBusDeviceAdd`. EvtPostBusDeviceAdd | Optional callback invoked after the bus filter FDO has been successfully created. See `EVT_DMF_BusFilter_PostBusDeviceAdd`. EvtDeviceAdd | Optional callback invoked after a proxy child filter DO has been attached to a newly discovered PDO. See `EVT_DMF_BusFilter_DeviceAdd`. EvtDeviceRemove | Optional callback invoked just before a proxy child device is destroyed. See `EVT_DMF_BusFilter_DeviceRemove`. EvtDeviceStarted | Optional callback invoked after `IRP_MN_START_DEVICE` has been forwarded successfully to the lower stack. See `EVT_DMF_BusFilter_DeviceStarted`. EvtDeviceEnumerated | Optional callback invoked when `IRP_MN_DEVICE_ENUMERATED` reaches the proxy child device. See `EVT_DMF_BusFilter_DeviceEnumerated`. EvtDeviceQueryId | Optional callback invoked when `IRP_MN_QUERY_ID` reaches the proxy child device. See `EVT_DMF_BusFilter_DeviceQueryId`. EvtDeviceQueryInterface | Optional callback invoked when `IRP_MN_QUERY_INTERFACE` reaches the proxy child device. See `EVT_DMF_BusFilter_DeviceQueryInterface`. ----------------------------------------------------------------------------------------------------------------------------------- #### Module Callbacks ----------------------------------------------------------------------------------------------------------------------------------- ##### EVT_DMF_BusFilter_PreBusDeviceAdd ```` _IRQL_requires_same_ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS EVT_DMF_BusFilter_PreBusDeviceAdd( _In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit, _Out_ WDF_OBJECT_ATTRIBUTES* Attributes, _Outptr_result_maybenull_ PDMFDEVICE_INIT* DmfDeviceInit ); ```` Called by `DMF_BusFilter_DeviceAdd` before the bus filter FDO is created. The client may customize `DeviceInit` (e.g. set PnP capabilities or power policy) and optionally allocate a `PDMFDEVICE_INIT` if it wants to use DMF modules on the bus FDO. If the client allocates `*DmfDeviceInit` it must **not** free it; the library takes ownership regardless of success or failure. ##### Returns `STATUS_SUCCESS`, or an error status. A non-success value aborts `DMF_BusFilter_DeviceAdd`. ##### Parameters Parameter | Description ----|---- Driver | The `WDFDRIVER` for this driver. DeviceInit | The `WDFDEVICE_INIT` being prepared for the bus filter FDO. The client may call `WdfDeviceInitSet*` routines on it. Attributes | `WDF_OBJECT_ATTRIBUTES` to apply to the created device. The client may set a context type or parent here. DmfDeviceInit | On output: optionally set to a `PDMFDEVICE_INIT` if the client uses DMF modules on the bus FDO. Pass `NULL` if not needed. ----------------------------------------------------------------------------------------------------------------------------------- ##### EVT_DMF_BusFilter_PostBusDeviceAdd ```` _IRQL_requires_same_ _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS EVT_DMF_BusFilter_PostBusDeviceAdd( _In_ WDFDEVICE Device, _In_opt_ PDMFDEVICE_INIT DmfDeviceInit ); ```` Called by `DMF_BusFilter_DeviceAdd` after the bus filter FDO has been successfully created. The client may perform any post-creation initialization that requires a valid `WDFDEVICE` handle, such as creating I/O queues or registering interfaces. ##### Returns `STATUS_SUCCESS`, or an error status. A non-success value aborts `DMF_BusFilter_DeviceAdd` and causes the device object to be deleted. ##### Parameters Parameter | Description ----|---- Device | The newly created bus filter `WDFDEVICE`. DmfDeviceInit | The `PDMFDEVICE_INIT` that was optionally allocated in `EVT_DMF_BusFilter_PreBusDeviceAdd`, or `NULL` if DMF module support was not requested. ----------------------------------------------------------------------------------------------------------------------------------- ##### EVT_DMF_BusFilter_DeviceAdd ```` _IRQL_requires_max_(APC_LEVEL) _IRQL_requires_same_ NTSTATUS EVT_DMF_BusFilter_DeviceAdd( _In_ WDFDEVICE Device, _In_ DMFBUSCHILDDEVICE ChildDevice ); ```` Called when a proxy WDM filter device object has been created and attached to a newly discovered child PDO. The filter is already in the stack (attached above the PDO) when this callback fires. The client may associate per-child state or WDF objects with the `ChildDevice` handle at this point. If the callback returns a non-success status, the library immediately detaches and deletes the proxy filter device; the `ChildDevice` handle becomes invalid after the callback returns. ##### Returns `STATUS_SUCCESS`, or an error status to abort creation of this proxy child and roll back the attach. ##### Parameters Parameter | Description ----|---- Device | The parent bus filter `WDFDEVICE`. ChildDevice | Opaque `DMFBUSCHILDDEVICE` handle representing the newly created proxy child. Valid only for the duration of this callback (and subsequent callbacks) until `EVT_DMF_BusFilter_DeviceRemove` returns. ##### Remarks * The IRQL annotation is `APC_LEVEL` because this callback is invoked from `Relations_AddDevice`, which runs at `PASSIVE_LEVEL` but holds no spinlock. The annotation is intentionally conservative; in practice this callback fires at `PASSIVE_LEVEL`. ----------------------------------------------------------------------------------------------------------------------------------- ##### EVT_DMF_BusFilter_DeviceRemove ```` _IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_same_ VOID EVT_DMF_BusFilter_DeviceRemove( _In_ WDFDEVICE Device, _In_ DMFBUSCHILDDEVICE ChildDevice ); ```` Called when a proxy child device is about to be destroyed. This fires both during the normal `IRP_MN_REMOVE_DEVICE` path and during the automatic teardown that runs when the bus FDO is deleted. At this point in-flight I/O to the child has already been drained via the per-child `IO_REMOVE_LOCK`, so the child is quiescent. The callback must not attempt to forward any IRPs to the child or access the child's WDM stack; both are being torn down. After this callback returns the `ChildDevice` handle is deleted by the library. ##### Returns None. ##### Parameters Parameter | Description ----|---- Device | The parent bus filter `WDFDEVICE`. ChildDevice | Opaque handle for the proxy child being removed. Do not use after this callback returns. ----------------------------------------------------------------------------------------------------------------------------------- ##### EVT_DMF_BusFilter_DeviceStarted ```` _IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_same_ VOID EVT_DMF_BusFilter_DeviceStarted( _In_ DMFBUSCHILDDEVICE ChildDevice, _In_ IRP* Irp ); ```` Called after the library has successfully forwarded `IRP_MN_START_DEVICE` to the lower stack and the lower driver returned success. The IRP is still held by the library and will be completed after this callback returns; the client must not complete it. The client may use this callback to perform any work that requires the child device to be in the started state, such as sending I/O or enabling device interfaces. ##### Returns None. ##### Parameters Parameter | Description ----|---- ChildDevice | Opaque handle for the proxy child that has started. Irp | The `IRP_MN_START_DEVICE` IRP. For inspection only; the client must not complete it. ----------------------------------------------------------------------------------------------------------------------------------- ##### EVT_DMF_BusFilter_DeviceEnumerated ```` _IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_same_ VOID EVT_DMF_BusFilter_DeviceEnumerated( _In_ DMFBUSCHILDDEVICE ChildDevice, _In_ IRP* Irp ); ```` Called when `IRP_MN_DEVICE_ENUMERATED` reaches the proxy child device. This minor code is sent by the PnP manager after the device has been enumerated and its instance ID has been assigned. It is informational; the library always forwards the IRP to the lower stack after this callback returns. The client must not complete the IRP. ##### Returns None. ##### Parameters Parameter | Description ----|---- ChildDevice | Opaque handle for the proxy child being enumerated. Irp | The `IRP_MN_DEVICE_ENUMERATED` IRP. For inspection only; the client must not complete it. ----------------------------------------------------------------------------------------------------------------------------------- ##### EVT_DMF_BusFilter_DeviceQueryId ```` _IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_same_ BOOLEAN EVT_DMF_BusFilter_DeviceQueryId( _In_ DMFBUSCHILDDEVICE ChildDevice, _In_ IRP* Irp ); ```` Called when `IRP_MN_QUERY_ID` reaches the proxy child device. The client may inspect or modify the IRP stack location and set `IoStatus` fields to supply identity strings (hardware ID, instance ID, etc.). **Return value contract (load-bearing):** * `TRUE` – The client has fully handled the IRP (set `IoStatus.Status` and `Information`). The library completes the IRP without forwarding it to the lower stack. * `FALSE` – The client did not handle the IRP. The library forwards it synchronously to the lower driver with `IoForwardIrpSynchronously`, then completes it with the lower driver's status. ##### Returns `TRUE` if the client handled the IRP; `FALSE` to let the library forward it to the lower stack. ##### Parameters Parameter | Description ----|---- ChildDevice | Opaque handle for the proxy child. Irp | The `IRP_MN_QUERY_ID` IRP. ----------------------------------------------------------------------------------------------------------------------------------- ##### EVT_DMF_BusFilter_DeviceQueryInterface ```` _IRQL_requires_max_(PASSIVE_LEVEL) _IRQL_requires_same_ BOOLEAN EVT_DMF_BusFilter_DeviceQueryInterface( _In_ DMFBUSCHILDDEVICE ChildDevice, _In_ IRP* Irp ); ```` Called when `IRP_MN_QUERY_INTERFACE` reaches the proxy child device. The client may fill in the interface struct pointed to by the IRP stack location's `Parameters.QueryInterface` field. **Return value contract (load-bearing):** * `TRUE` – The client has fully handled the IRP (set `IoStatus.Status` and filled in the interface). The library completes the IRP without forwarding it to the lower stack. * `FALSE` – The client did not handle the IRP. The library forwards it synchronously to the lower driver with `IoForwardIrpSynchronously`, then completes it with the lower driver's status. ##### Returns `TRUE` if the client handled the IRP; `FALSE` to let the library forward it to the lower stack. ##### Parameters Parameter | Description ----|---- ChildDevice | Opaque handle for the proxy child. Irp | The `IRP_MN_QUERY_INTERFACE` IRP. ----------------------------------------------------------------------------------------------------------------------------------- #### Module Methods ----------------------------------------------------------------------------------------------------------------------------------- ##### DMF_BusFilter_Initialize ```` _IRQL_requires_max_(PASSIVE_LEVEL) _Must_inspect_result_ NTSTATUS DMF_BusFilter_Initialize( _In_ DMF_BusFilter_CONFIG* BusFilterConfig ); ```` Initializes the bus filter library for the current driver. Must be called once from `DriverEntry`, after `WdfDriverCreate` returns, and before the first call to `DMF_BusFilter_DeviceAdd`. Internally this routine hooks the driver's entire `MajorFunction` dispatch table so that IRPs sent to proxy child device objects are intercepted and routed through the library's dispatch handler. It also stores a copy of the client's configuration for use in subsequent callbacks. ##### Returns `STATUS_SUCCESS`, or: Status | Meaning ----|---- `STATUS_INVALID_PARAMETER` | `BusFilterConfig` or `BusFilterConfig->DriverObject` is `NULL`. `STATUS_NOT_SUPPORTED` | `WdfGetDriver` returned `NULL` (WDF is not yet ready; call after `WdfDriverCreate`). Any WDF context-allocation failure | Returned from `WdfObjectAllocateContext`. ##### Parameters Parameter | Description ----|---- BusFilterConfig | Pointer to a fully populated `DMF_BusFilter_CONFIG`. Initialize with `DMF_BusFilter_CONFIG_INIT` before setting callbacks. The library copies the struct internally; the pointer does not need to remain valid after `DMF_BusFilter_Initialize` returns, so a stack-local variable in `DriverEntry` is sufficient. ##### Remarks * Call `DMF_BusFilter_CONFIG_INIT` to zero-initialize the config before setting optional fields. * The library hooks `DriverObject->MajorFunction` for all major function codes. IRPs targeting devices that do not carry the internal `GUID_DMF_BUSFILTER_SIGNATURE` tag are delegated to the previously installed handler transparently. ----------------------------------------------------------------------------------------------------------------------------------- ##### DMF_BusFilter_DeviceAdd ```` EVT_WDF_DRIVER_DEVICE_ADD DMF_BusFilter_DeviceAdd; ```` WDF `EvtDriverDeviceAdd` callback implementation for the bus filter FDO. The client should register this function as its `EvtDriverDeviceAdd` (or call it directly from a wrapper). It creates the bus filter WDF device, installs the bus-relations IRP preprocessor, and initializes the internal child device list. `DMF_BusFilter_Initialize` must have been called before this function. ##### Returns `STATUS_SUCCESS`, or a failure status from `WdfDeviceCreate` or supporting framework calls. On failure, any partially created device is cleaned up. ##### Parameters Parameter | Description ----|---- Driver | The `WDFDRIVER`. DeviceInit | The `WDFDEVICE_INIT` prepared by the framework. ----------------------------------------------------------------------------------------------------------------------------------- ##### DMF_BusFilter_WdmDeviceObjectGet ```` PDEVICE_OBJECT DMF_BusFilter_WdmDeviceObjectGet( _In_ DMFBUSCHILDDEVICE ChildDevice ); ```` Returns the WDM `DEVICE_OBJECT` that represents the proxy child filter device itself (the filter DO created by `IoCreateDevice` inside this library). Use this to obtain the raw WDM object when the WDF handle is not sufficient. ##### Returns The proxy filter `DEVICE_OBJECT`, or `NULL` if the context is missing. ##### Parameters Parameter | Description ----|---- ChildDevice | Opaque handle for a proxy child device. ----------------------------------------------------------------------------------------------------------------------------------- ##### DMF_BusFilter_WdmAttachedDeviceGet ```` PDEVICE_OBJECT DMF_BusFilter_WdmAttachedDeviceGet( _In_ DMFBUSCHILDDEVICE ChildDevice ); ```` Returns the WDM `DEVICE_OBJECT` to which the proxy child filter is attached (i.e. the result of `IoAttachDeviceToDeviceStackSafe` — typically the PDO itself or the topmost device in the PDO's stack at attach time). This is the object that IRPs are forwarded to when the filter does not handle them. ##### Returns The attached (lower) `DEVICE_OBJECT`, or `NULL` if the child has an unrecognised signature or a missing context. ##### Parameters Parameter | Description ----|---- ChildDevice | Opaque handle for a proxy child device. ----------------------------------------------------------------------------------------------------------------------------------- ##### DMF_BusFilter_WdmPhysicalDeviceGet ```` PDEVICE_OBJECT DMF_BusFilter_WdmPhysicalDeviceGet( _In_ DMFBUSCHILDDEVICE ChildDevice ); ```` Returns the Physical Device Object (PDO) associated with a proxy child device. This is the PDO reported by the bus driver in the `DEVICE_RELATIONS` array that caused this proxy child to be created. ##### Returns The PDO `DEVICE_OBJECT`, or `NULL` if the child has an unrecognised signature or a missing context. ##### Parameters Parameter | Description ----|---- ChildDevice | Opaque handle for a proxy child device. ----------------------------------------------------------------------------------------------------------------------------------- #### Module IOCTLs * None ----------------------------------------------------------------------------------------------------------------------------------- #### Module Remarks * `DMF_BusFilter_Initialize` must be called before `DMF_BusFilter_DeviceAdd`. If `DeviceAdd` is called without a prior successful `Initialize`, it returns `STATUS_INVALID_DEVICE_STATE`. * Proxy child teardown is automatic. The library registers an internal WDF context `EvtCleanupCallback` on the bus FDO's `PARENT_BUS_DEVICE_CONTEXT`. When the FDO is deleted the callback drains and destroys any remaining proxy children. On the normal PnP path the child list is already empty (every `IRP_MN_REMOVE_DEVICE` self-drained it), so the callback is a safe no-op; it serves as the safety net for surprise-removal paths where children may not have received `REMOVE` before the parent. * The mandatory WDM filter teardown order for each proxy child is: (1) `IoReleaseRemoveLockAndWait` to drain in-flight I/O, (2) `IoDetachDevice` to detach the filter from the PDO stack, (3) `IoDeleteDevice` to lazy-free the device object. Nothing may access the device extension after `IoDeleteDevice` returns. * The bus-relations completion routine (`DMF_BusFilter_QueryBusRelationsCompleted`) may fire at `DISPATCH_LEVEL`. Because `IoCreateDevice` and `IoAttachDeviceToDeviceStackSafe` require `PASSIVE_LEVEL`, the library automatically defers child creation to a passive-level work item in that case. * The completion routine returns `STATUS_MORE_PROCESSING_REQUIRED` to hold the IRP (and therefore the bus driver's references on each PDO in `DEVICE_RELATIONS`) alive until the passive-level worker has finished attaching all filter devices. * `DeviceType` set to `0` in `DMF_BusFilter_CONFIG` causes the library to inherit the device type from each child PDO at attach time. A filter whose device type differs from the stack it joins can cause I/O manager policy mismatches. * All `EVT_*` callback pointers in `DMF_BusFilter_CONFIG` are optional. The library silently skips `NULL` callbacks. ----------------------------------------------------------------------------------------------------------------------------------- #### Module Children * None ----------------------------------------------------------------------------------------------------------------------------------- #### Module Implementation Details ----------------------------------------------------------------------------------------------------------------------------------- ##### Device Stack Placement The library attaches one proxy WDM filter DO above each PDO reported by the bus driver. The resulting per-child devnode stack looks like: ```mermaid flowchart TD FDO["Child FDO\n(loaded later by PnP)"] FilterDO["Proxy Filter DO\n(created by this library,\ntagged with GUID_DMF_BUSFILTER_SIGNATURE)"] PDO["Child PDO\n(reported by bus driver)"] FDO --> FilterDO --> PDO BusFDO["Bus Filter FDO\n(DMF_BusFilter_DeviceAdd)"] BusFDO -. "preprocesses\nQUERY_DEVICE_RELATIONS" .-> PDO ``` The bus filter FDO hooks `IRP_MN_QUERY_DEVICE_RELATIONS`/`BusRelations` via a WDF IRP preprocessor callback. When the completion fires it calls `IoAttachDeviceToDeviceStackSafe` once per PDO in `DEVICE_RELATIONS` that has not been seen before. ##### Dispatch-Table Hooking and Child Identification `DMF_BusFilter_Initialize` replaces every slot of `DriverObject->MajorFunction` with the library's own `DMF_BusFilter_DispatchHandler`. The original per-slot function pointer is saved in the driver-level context (`BusFilter_Context.MajorDispatchFunctions`). For each incoming IRP, `DispatchHandler` inspects the target device object's extension for the tag GUID `GUID_DMF_BUSFILTER_SIGNATURE` (`{678CBB8D-019F-4D07-912A-73E2E568B148}`). IRPs targeting non-child devices (e.g. the WDF FDO) are delegated to the saved original handler transparently. IRPs targeting proxy children are handled by the library. ##### Bus-Relations Attach Window and Work-Item Rundown The only safe window for a bus filter to attach to a PDO is between the bus driver populating `DEVICE_RELATIONS` and the PnP manager dispatching `IRP_MN_START_DEVICE` to the child FDO. Attaching outside this window races PDO creation or FDO construction. The parent bus device tracks outstanding passive-level workers with an atomic counter (`OutstandingWorkItems`) and a kernel event (`WorkItemsIdle`, signaled when the counter reaches zero). The internal teardown routine (invoked by the FDO context cleanup callback) waits on `WorkItemsIdle` before draining the child list, preventing a race between a concurrent `Relations_AddDevice` worker and list teardown. ```mermaid flowchart TD BusRelComp["BusRelations completion\n(may be DISPATCH_LEVEL)"] Check{"IRQL > PASSIVE_LEVEL?"} WorkItem["Queue passive-level\nwork item"] Inline["Process inline\nat PASSIVE_LEVEL"] AddDevice["Relations_AddDevice\nper PDO in DEVICE_RELATIONS\n(IoCreateDevice +\nIoAttachDeviceToDeviceStackSafe +\nEvtDeviceAdd)"] CompleteIrp["IoCompleteRequest\n(resume IRP propagation)"] BusRelComp --> Check Check -- Yes --> WorkItem --> AddDevice Check -- No --> Inline --> AddDevice AddDevice --> CompleteIrp ``` ##### Per-Child IO_REMOVE_LOCK Protocol Each proxy child device extension contains an `IO_REMOVE_LOCK`. `DispatchHandler` acquires the lock for every IRP that enters the filter. Release rules: * `IRP_MN_REMOVE_DEVICE` — released inside `Relations_RemoveDevice` via `IoReleaseRemoveLockAndWait`, which also drains all other in-flight holders. The dispatcher must not release the lock again after this call. * All other PnP minors — released with `IoReleaseRemoveLock` after `DispatchPnp` returns. * Non-PnP IRPs — released with `IoReleaseRemoveLock` **before** `IoCallDriver` so the lock does not span an asynchronous IRP completion. ----------------------------------------------------------------------------------------------------------------------------------- #### Examples ----------------------------------------------------------------------------------------------------------------------------------- The following sketch shows the minimum wiring for a client driver. Proxy child teardown is handled automatically by the library when the bus FDO is deleted, so no `EvtDeviceReleaseHardware` or explicit cleanup call is needed. ````c // // Optional: per-child callbacks. // static NTSTATUS MyDriver_EvtDeviceAdd( _In_ WDFDEVICE Device, _In_ DMFBUSCHILDDEVICE ChildDevice ) { UNREFERENCED_PARAMETER(Device); // Retrieve the raw PDO for this child if needed. PDEVICE_OBJECT pdo = DMF_BusFilter_WdmPhysicalDeviceGet(ChildDevice); UNREFERENCED_PARAMETER(pdo); return STATUS_SUCCESS; } static VOID MyDriver_EvtDeviceRemove( _In_ WDFDEVICE Device, _In_ DMFBUSCHILDDEVICE ChildDevice ) { UNREFERENCED_PARAMETER(Device); UNREFERENCED_PARAMETER(ChildDevice); } // // DriverEntry // NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NTSTATUS ntStatus; WDF_DRIVER_CONFIG driverConfig; WDF_DRIVER_CONFIG_INIT(&driverConfig, DMF_BusFilter_DeviceAdd); ntStatus = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &driverConfig, WDF_NO_HANDLE); if (!NT_SUCCESS(ntStatus)) { return ntStatus; } // Initialize the bus filter library after WdfDriverCreate. // The config struct can live on the stack: Initialize copies it internally // and never reads the pointer again after it returns. // DMF_BusFilter_CONFIG busFilterConfig; DMF_BusFilter_CONFIG_INIT(&busFilterConfig, DriverObject); busFilterConfig.EvtDeviceAdd = MyDriver_EvtDeviceAdd; busFilterConfig.EvtDeviceRemove = MyDriver_EvtDeviceRemove; return DMF_BusFilter_Initialize(&busFilterConfig); } ```` ----------------------------------------------------------------------------------------------------------------------------------- #### To Do ----------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------------------- #### Module Category ----------------------------------------------------------------------------------------------------------------------------------- Driver Patterns -----------------------------------------------------------------------------------------------------------------------------------