wdf-kmdf
Kernel-Mode Driver Framework (KMDF), the Microsoft-recommended way to write Windows kernel-mode drivers. Covers DriverEntry, EvtDeviceAdd, IRPs and IOCTLs, I/O queues, PnP and Power state machines, IRQL discipline, memory pools, WPP tracing, SAL annotations, and Driver Verifier. USE WHEN: user mentions "KMDF", "WDF kernel", "Windows kernel driver", "DriverEntry", "WdfDriverCreate", "EvtDeviceAdd", "IRP", "IOCTL", "DISPATCH_LEVEL", "PASSIVE_LEVEL", "NTSTATUS", "PoolTag", "WdfRequestComplete" DO NOT USE FOR: UMDF v2 (use `wdf-umdf`), classic WDM-only drivers, file-system filters (FltMgr is a separate framework)
What this skill does
# KMDF - Quick Reference
> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `wdf-kmdf`. Authoritative source: `learn.microsoft.com/en-us/windows-hardware/drivers/wdf/`.
## Driver entry + device add
```c
NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath) {
WDF_DRIVER_CONFIG config;
WDF_DRIVER_CONFIG_INIT(&config, MyEvtDeviceAdd);
config.DriverPoolTag = 'rvDM';
return WdfDriverCreate(DriverObject, RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
}
NTSTATUS MyEvtDeviceAdd(_In_ WDFDRIVER Driver, _Inout_ PWDFDEVICE_INIT DeviceInit) {
UNREFERENCED_PARAMETER(Driver);
// Filter? Function? FDO/PDO?
// WdfFdoInitSetFilter(DeviceInit); // <-- uncomment for filter
WDFDEVICE device;
NTSTATUS status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &device);
if (!NT_SUCCESS(status)) return status;
WDF_IO_QUEUE_CONFIG q;
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&q, WdfIoQueueDispatchParallel);
q.EvtIoDeviceControl = MyEvtIoDeviceControl;
q.EvtIoRead = MyEvtIoRead;
q.EvtIoWrite = MyEvtIoWrite;
return WdfIoQueueCreate(device, &q, WDF_NO_OBJECT_ATTRIBUTES, NULL);
}
```
## I/O queues — dispatch types
| Type | Behavior |
|------|----------|
| `WdfIoQueueDispatchSequential` | One request at a time |
| `WdfIoQueueDispatchParallel` | Many concurrent requests (your callbacks must be reentrant) |
| `WdfIoQueueDispatchManual` | You retrieve requests with `WdfIoQueueRetrieveNextRequest` |
Use **manual** queues for forwarding patterns (filter holds requests, completes them later when the underlying device responds).
## IRQL Cheat Sheet
| IRQL | Allowed | Forbidden |
|------|---------|-----------|
| `PASSIVE_LEVEL` (0) | Anything: paging OK, blocking OK | — |
| `APC_LEVEL` (1) | Most things; APCs disabled | — |
| `DISPATCH_LEVEL` (2) | Spinlocks, nonpaged pool, DPCs | Page faults, blocking, paged pool, `KeWaitForSingleObject` (with timeout > 0) |
| `DIRQL` / `HIGH_LEVEL` | ISR work only | Almost everything else |
**Annotate every function** so SDV / CodeQL can verify:
```c
_IRQL_requires_max_(DISPATCH_LEVEL)
_Must_inspect_result_
NTSTATUS Helper(_In_ WDFDEVICE dev);
```
## Memory allocation
```c
// Modern (preferred)
PVOID p = ExAllocatePool2(POOL_FLAG_NON_PAGED, size, 'rvDM');
if (!p) return STATUS_INSUFFICIENT_RESOURCES;
// ... use ...
ExFreePoolWithTag(p, 'rvDM');
// Pool flags
// POOL_FLAG_NON_PAGED - safe at DISPATCH_LEVEL
// POOL_FLAG_PAGED - PASSIVE_LEVEL only
// POOL_FLAG_NON_PAGED_EXECUTE - rarely needed; HVCI-hostile
// POOL_FLAG_UNINITIALIZED - skip zero-fill (perf, only if you fill it)
```
> **Never use `ExAllocatePool` / `ExAllocatePoolWithTag`** — flagged as deprecated/insecure since WDK 22000.
## IOCTL handling
```c
// Public.h (shared with usermode)
#define IOCTL_MYDRV_DO_THING \
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Driver
VOID MyEvtIoDeviceControl(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength, _In_ size_t InputBufferLength,
_In_ ULONG IoControlCode) {
UNREFERENCED_PARAMETER(Queue);
NTSTATUS status; size_t bytes = 0;
switch (IoControlCode) {
case IOCTL_MYDRV_DO_THING: {
PMY_INPUT in; PMY_OUTPUT out;
status = WdfRequestRetrieveInputBuffer(Request, sizeof(*in), (PVOID*)&in, NULL);
if (!NT_SUCCESS(status)) break;
status = WdfRequestRetrieveOutputBuffer(Request, sizeof(*out),(PVOID*)&out, NULL);
if (!NT_SUCCESS(status)) break;
out->Result = in->Value * 2;
bytes = sizeof(*out);
} break;
default:
status = STATUS_INVALID_DEVICE_REQUEST; break;
}
WdfRequestCompleteWithInformation(Request, status, bytes);
}
```
**Buffer methods**: `METHOD_BUFFERED` (kernel-allocated copy — safest), `METHOD_IN_DIRECT` / `METHOD_OUT_DIRECT` (MDL — for big buffers), `METHOD_NEITHER` (raw user pointer — dangerous, requires `ProbeForRead`/`ProbeForWrite` in a `try/except`).
## WPP tracing
```c
// Trace.h
#define WPP_CONTROL_GUIDS \
WPP_DEFINE_CONTROL_GUID(MyDriverCtl, (00000000,1111,2222,3333,444444444444), \
WPP_DEFINE_BIT(TRACE_DRIVER) WPP_DEFINE_BIT(TRACE_DEVICE))
// Driver.c — on top of file (after includes)
#include "Driver.h"
#include "Driver.tmh" // generated by WPP preprocessor
// Use
TraceEvents(TRACE_LEVEL_INFORMATION, TRACE_DRIVER, "DriverEntry: status=%!STATUS!", status);
```
Decode at runtime: `tracelog.exe -start mytrace -guid GuidFile -f .\trace.etl -flag 0xFF -level 5`. Decode the `.etl` with `tracerpt` or `traceview.exe` against the driver `.pdb`.
## Object lifetime + cleanup
Every WDF object has a parent. Destroying a parent destroys children. Wire cleanup explicitly when needed:
```c
WDF_OBJECT_ATTRIBUTES attrs;
WDF_OBJECT_ATTRIBUTES_INIT(&attrs);
attrs.EvtCleanupCallback = MyContextCleanup; // runs at PASSIVE_LEVEL
attrs.EvtDestroyCallback = MyContextDestroy; // may run at DISPATCH_LEVEL
WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attrs, MY_DEVICE_CONTEXT);
WdfDeviceCreate(&DeviceInit, &attrs, &device);
```
## Synchronization
| Primitive | Max IRQL | Use |
|-----------|----------|-----|
| `WDFSPINLOCK` (`WdfSpinLockAcquire`) | DISPATCH_LEVEL | Short, no blocking |
| `WDFWAITLOCK` (`WdfWaitLockAcquire`) | PASSIVE_LEVEL | Can block; never at DISPATCH |
| `KEVENT`, `FAST_MUTEX` | varies | Less common in WDF; prefer the above |
| WDF execution levels | — | Set on `WDF_OBJECT_ATTRIBUTES.ExecutionLevel` for callback serialization |
## PnP / Power callbacks (subset)
```c
WDF_PNPPOWER_EVENT_CALLBACKS pp;
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pp);
pp.EvtDevicePrepareHardware = MyEvtDevicePrepareHardware; // map resources
pp.EvtDeviceReleaseHardware = MyEvtDeviceReleaseHardware;
pp.EvtDeviceD0Entry = MyEvtDeviceD0Entry;
pp.EvtDeviceD0Exit = MyEvtDeviceD0Exit;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pp);
```
## Verification ladder
1. Compile with `/W4 /WX` and SAL annotations — fix every warning
2. **Static Driver Verifier (SDV)** — IRQL/locking/leak rules, must be clean before release
3. **WDK CodeQL queries** (Microsoft's `Windows-Driver-Developer-Supplemental-Tools` repo) — must-pass set
4. **Driver Verifier** at runtime: `verifier /standard /driver MyDrv.sys`, then reboot and exercise
5. **!analyze** any bugcheck on the test machine via WinDbg
## Anti-Patterns
| Anti-Pattern | Why It's Bad | Correct Approach |
|--------------|--------------|------------------|
| `ExAllocatePoolWithTag` | Deprecated since 22000 | `ExAllocatePool2(POOL_FLAG_NON_PAGED, ...)` |
| `KeWaitForSingleObject` at DISPATCH | Bugcheck | Schedule a workitem to PASSIVE |
| `try/except` around random kernel APIs | Hides real bugs | Use SEH only around user-buffer probing |
| Unprobed `METHOD_NEITHER` user pointer | Bluescreens / privilege escalation | Use `METHOD_BUFFERED` or probe explicitly |
| Forgetting `WdfRequestComplete` | I/O hangs forever | Complete on every code path (or `WdfRequestStopAcknowledge`) |
| Returning success but completing the request elsewhere asynchronously without marking it pending | Double-complete bugcheck | Mark with `WdfRequestMarkCancelable` and complete once |
| C++ STL / `new` / RTTI / exceptions | Not safe in kernel by default | Plain C, `wil::` helpers, `LIST_ENTRY` intrusive lists |
| `DbgPrint` for production diagnostics | No structured log, no levels filtering | WPP tracing |
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.