1
0

Docs overhaul

This commit is contained in:
2026-07-02 23:20:48 +02:00
parent 5ac3e9161d
commit 2ed01972fb
2 changed files with 796 additions and 2 deletions
+793
View File
@@ -0,0 +1,793 @@
## 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).
3. **EvtDeviceReleaseHardware or EvtCleanupCallback** call `DMF_BusFilter_DeviceCleanup` to drain and destroy any remaining
proxy child devices and prevent resource leaks.
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 forced teardown in `DMF_BusFilter_DeviceCleanup`. 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 caller retains ownership; the library copies the config internally.
##### 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_DeviceCleanup
````
_IRQL_requires_max_(PASSIVE_LEVEL)
VOID
DMF_BusFilter_DeviceCleanup(
_In_ WDFDEVICE Device
);
````
Tears down all proxy child filter devices still associated with the bus device. The client **must** call this from its
`EvtDeviceReleaseHardware` or `EvtCleanupCallback` to prevent WDM device object leaks. Without this call, any child devices
remaining in the internal list at unload time will be leaked and will fault when the I/O manager later dereferences them.
Under normal PnP operation the child list is already empty when this function runs (`IRP_MN_REMOVE_DEVICE` has been dispatched
to every child). This function is a safety net for abnormal paths such as surprise removal of the parent before all children
received `REMOVE`.
The function first waits for any outstanding bus-relations work items to drain (preventing a race with a pending passive-level
`Relations_AddDevice` call), then for each remaining child: acquires the per-child `IO_REMOVE_LOCK` to drain in-flight I/O,
calls `EvtDeviceRemove` (if set), and detaches and deletes the proxy filter device in the mandatory order.
If a child's `IO_REMOVE_LOCK` cannot be acquired (`STATUS_DELETE_PENDING`), it means a concurrent `IRP_MN_REMOVE_DEVICE` is
already processing that child; this function skips it and lets the `REMOVE` path handle teardown.
##### Returns
None.
##### Parameters
Parameter | Description
----|----
Device | The bus filter `WDFDEVICE` whose proxy children should be cleaned up.
-----------------------------------------------------------------------------------------------------------------------------------
##### 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`.
* `DMF_BusFilter_DeviceCleanup` must be called from `EvtDeviceReleaseHardware` or `EvtCleanupCallback`. Omitting this call
leaks WDM device objects that remain in the child list at driver unload.
* 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). `DMF_BusFilter_DeviceCleanup` 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.
````c
//
// Global configuration block (or stored in driver context).
//
static DMF_BusFilter_CONFIG g_BusFilterConfig;
//
// Optional: per-child callback.
//
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);
}
//
// Called when the bus filter FDO's hardware is being released.
//
static
NTSTATUS
MyDriver_EvtDeviceReleaseHardware(
_In_ WDFDEVICE Device,
_In_ WDFCMRESLIST ResourcesTranslated
)
{
UNREFERENCED_PARAMETER(ResourcesTranslated);
// Mandatory: drain and destroy all remaining proxy children.
DMF_BusFilter_DeviceCleanup(Device);
return STATUS_SUCCESS;
}
//
// 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.
//
DMF_BusFilter_CONFIG_INIT(&g_BusFilterConfig, DriverObject);
g_BusFilterConfig.EvtDeviceAdd = MyDriver_EvtDeviceAdd;
g_BusFilterConfig.EvtDeviceRemove = MyDriver_EvtDeviceRemove;
return DMF_BusFilter_Initialize(&g_BusFilterConfig);
}
````
-----------------------------------------------------------------------------------------------------------------------------------
#### To Do
-----------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------
#### Module Category
-----------------------------------------------------------------------------------------------------------------------------------
Driver Patterns
-----------------------------------------------------------------------------------------------------------------------------------