UMDF v2 - Quick Reference
Deep Knowledge: Use mcp__documentation__fetch_docs with technology: wdf-umdf. Authoritative source: learn.microsoft.com/en-us/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2.
When UMDF is the right answer
- Driver runs in
WUDFHost.exe, a user-mode service host. No bugchecks if it crashes — reflector restarts it.
- Same WDF object model and APIs as KMDF (
WdfDriverCreate, WdfDeviceCreate, WdfRequest*). Differences are mostly which APIs are available, not how to call them.
- Required model for: Indirect Display Drivers (IDD), many HID over Bluetooth scenarios, sensor drivers, camera drivers (MFT/AVStream is a separate path).
- Recommended for: anything where the device protocol is reachable from user mode (USB, Bluetooth, network, mostly-software devices) and you don't need to be in the IRP path of a kernel-only stack.
DriverEntry equivalent
UMDF drivers expose the same DriverEntry symbol; the host loads the DLL and calls it:
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
WDF_DRIVER_CONFIG config;
WDF_DRIVER_CONFIG_INIT(&config, MyEvtDeviceAdd);
return WdfDriverCreate(DriverObject, RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);
}
What's different from KMDF
| Concern |
KMDF |
UMDF |
| Process |
System (ntoskrnl.exe) |
WUDFHost.exe (user mode) |
| Crash impact |
Bugcheck |
Host restart, device disappears briefly |
| C++ usage |
Discouraged (no exceptions/RTTI) |
Full C++ allowed (use the cpp skill freely) |
| Direct hardware access |
MMIO, port I/O, DMA |
Through reflector / a kernel companion driver if needed |
| Synchronous kernel APIs |
Available |
Not available — use Win32 / WDF user-mode equivalents |
| IRQL |
Real IRQL discipline |
Always at PASSIVE-equivalent (no DISPATCH worries) |
| Pool |
ExAllocatePool2 |
new / malloc / HeapAlloc |
| Tracing |
WPP |
WPP or standard ETW providers |
Practical consequence: UMDF is almost C++17/20 application code with WDF idioms wrapped around it. Memory bugs are caught by ASan-style tooling at user-mode dev time; kernel pitfalls disappear.
INF entries (UMDF v2)
[Manufacturer]
%MfgName% = Standard,NT$ARCH$.10.0...19041
[Standard.NT$ARCH$.10.0...19041]
%Device.DeviceDesc% = MyDevice_Install, ROOT\MyDevice
[MyDevice_Install.NT]
CopyFiles = MyDevice.CopyFiles
AddReg = MyDevice.AddReg
[MyDevice_Install.NT.Services]
AddService = WUDFRd, 0x000001fa, WUDFRD_ServiceInstall
[WUDFRD_ServiceInstall]
DisplayName = "WUDF Reflector"
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary= %12%\WUDFRd.sys
LoadOrderGroup = Base
[MyDevice_Install.NT.Wdf]
UmdfDispatcher = NativeUSB ; or NativeIDD, NativeHID, etc.
UmdfServiceOrder = MyUmdfDriver
UmdfKernelModeClientPolicy = AllowKernelModeClients
[MyUmdfDriver]
UmdfLibraryVersion = $UMDFVERSION$
DriverCLSID = {01234567-89AB-CDEF-0123-456789ABCDEF}
ServiceBinary = %13%\MyDevice.dll
Reflector — what it actually does
WUDFRd.sys (the Reflector) sits in the kernel as the proxy for the user-mode driver. It:
- Receives the kernel IRPs
- Marshals them across the user/kernel boundary into WDF requests delivered to your DLL
- Marshals your completions back into IRPs
- Restarts the host if your DLL crashes
You don't write reflector code; you write DLL code and the framework + reflector deliver requests to it.
Companion kernel driver (when UMDF can't reach what you need)
UMDF cannot call arbitrary kernel APIs. Patterns:
- Inbox kernel client (e.g. WinUSB, HIDClass, WUDFRd) handles the kernel side
- Custom companion KMDF driver + a private inverted-call IOCTL channel — your UMDF driver opens it and sends commands
Project structure (UMDF DLL + INF + driver package)
DriverSolution/
├── MyUmdfDriver/ (.vcxproj — UMDF v2)
│ ├── Driver.cpp DriverEntry, EvtDeviceAdd
│ ├── Device.cpp Device-level WDF callbacks
│ ├── Queue.cpp IOCTL / Read / Write handlers
│ ├── MyUmdfDriver.def Exports
│ └── MyUmdfDriver.inf
├── MyUmdfDriverPackage/ Driver package (.cab + signing)
└── MyUmdfDriverTests/ User-mode test app (Win32 console / GTest)
Debugging UMDF
- Attach a normal user-mode debugger (WinDbg / Visual Studio) to
WUDFHost.exe — much friendlier than KMDF
- Set
HKLM\System\CurrentControlSet\Services\WUDFHost\Parameters\HostProcessDbgBreakOnStart=1 to break before driver load
- Use
Application Verifier for memory/handle bugs (much like Driver Verifier for KMDF)
- ETW + WPP traces work the same as KMDF
Anti-Patterns
| Anti-Pattern |
Why It's Bad |
Correct Approach |
| Treating UMDF callbacks as background work |
They serialize requests |
Hand off long work to a separate worker thread; complete the request when done |
| Calling kernel-only APIs |
Won't link |
Use Win32 / WDF user-mode equivalents |
| Holding a request indefinitely with no cancel handler |
App hangs |
Mark cancelable, handle EvtRequestCancel |
| Using process global state |
Multiple device instances share the host |
Per-device context via WDF_OBJECT_ATTRIBUTES |
Logging via OutputDebugString only |
Lost in production |
WPP/ETW with a published GUID |
| Assuming the host stays up |
Reflector can recycle it |
Persist nothing in process memory; reload from registry/file on EvtDevicePrepareHardware |
1---2name: wdf-umdf3description: User-Mode Driver Framework v2 (UMDF). User-mode driver model that uses the same WDF object model as KMDF but runs in a host process (WUDFHost.exe) protected by the reflector. Required for some categories (Indirect Display Drivers, many sensor and camera drivers) and recommended for any driver that doesn't strictly need kernel mode. USE WHEN: user mentions "UMDF", "WUDFHost", "user-mode driver", "reflector", "IDD", "ISensor", "WDFHOST", "UMDF v2", "FX2" DO NOT USE FOR: KMDF (use `wdf-kmdf`), classic UMDF v1 (deprecated, COM-based)4---5# UMDF v2 - Quick Reference67> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `wdf-umdf`. Authoritative source: `learn.microsoft.com/en-us/windows-hardware/drivers/wdf/getting-started-with-umdf-version-2`.89## When UMDF is the right answer1011- **Driver runs in `WUDFHost.exe`**, a user-mode service host. No bugchecks if it crashes — reflector restarts it.12- **Same WDF object model and APIs as KMDF** (`WdfDriverCreate`, `WdfDeviceCreate`, `WdfRequest*`). Differences are mostly which APIs are available, not how to call them.13- Required model for: **Indirect Display Drivers (IDD)**, many HID over Bluetooth scenarios, sensor drivers, camera drivers (MFT/AVStream is a separate path).14- Recommended for: anything where the device protocol is reachable from user mode (USB, Bluetooth, network, mostly-software devices) and you don't need to be in the IRP path of a kernel-only stack.1516## DriverEntry equivalent1718UMDF drivers expose the same `DriverEntry` symbol; the host loads the DLL and calls it:1920```c21NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {22 WDF_DRIVER_CONFIG config;23 WDF_DRIVER_CONFIG_INIT(&config, MyEvtDeviceAdd);24 return WdfDriverCreate(DriverObject, RegistryPath,25 WDF_NO_OBJECT_ATTRIBUTES, &config, WDF_NO_HANDLE);26}27```2829## What's different from KMDF3031| Concern | KMDF | UMDF |32|---------|------|------|33| Process | `System` (`ntoskrnl.exe`) | `WUDFHost.exe` (user mode) |34| Crash impact | Bugcheck | Host restart, device disappears briefly |35| C++ usage | Discouraged (no exceptions/RTTI) | **Full C++ allowed** (use the `cpp` skill freely) |36| Direct hardware access | MMIO, port I/O, DMA | Through reflector / a kernel companion driver if needed |37| Synchronous kernel APIs | Available | Not available — use Win32 / WDF user-mode equivalents |38| IRQL | Real IRQL discipline | Always at PASSIVE-equivalent (no DISPATCH worries) |39| Pool | `ExAllocatePool2` | `new` / `malloc` / `HeapAlloc` |40| Tracing | WPP | WPP **or** standard ETW providers |4142> **Practical consequence**: UMDF is almost C++17/20 application code with WDF idioms wrapped around it. Memory bugs are caught by ASan-style tooling at user-mode dev time; kernel pitfalls disappear.4344## INF entries (UMDF v2)4546```inf47[Manufacturer]48%MfgName% = Standard,NT$ARCH$.10.0...190414950[Standard.NT$ARCH$.10.0...19041]51%Device.DeviceDesc% = MyDevice_Install, ROOT\MyDevice5253[MyDevice_Install.NT]54CopyFiles = MyDevice.CopyFiles55AddReg = MyDevice.AddReg5657[MyDevice_Install.NT.Services]58AddService = WUDFRd, 0x000001fa, WUDFRD_ServiceInstall5960[WUDFRD_ServiceInstall]61DisplayName = "WUDF Reflector"62ServiceType = 163StartType = 364ErrorControl = 165ServiceBinary= %12%\WUDFRd.sys66LoadOrderGroup = Base6768[MyDevice_Install.NT.Wdf]69UmdfDispatcher = NativeUSB ; or NativeIDD, NativeHID, etc.70UmdfServiceOrder = MyUmdfDriver71UmdfKernelModeClientPolicy = AllowKernelModeClients7273[MyUmdfDriver]74UmdfLibraryVersion = $UMDFVERSION$75DriverCLSID = {01234567-89AB-CDEF-0123-456789ABCDEF}76ServiceBinary = %13%\MyDevice.dll77```7879## Reflector — what it actually does8081`WUDFRd.sys` (the Reflector) sits in the kernel as the proxy for the user-mode driver. It:82- Receives the kernel IRPs83- Marshals them across the user/kernel boundary into WDF requests delivered to your DLL84- Marshals your completions back into IRPs85- Restarts the host if your DLL crashes8687You don't write reflector code; you write DLL code and the framework + reflector deliver requests to it.8889## Companion kernel driver (when UMDF can't reach what you need)9091UMDF cannot call arbitrary kernel APIs. Patterns:921. **Inbox kernel client** (e.g. WinUSB, HIDClass, WUDFRd) handles the kernel side932. **Custom companion KMDF driver** + a private inverted-call IOCTL channel — your UMDF driver opens it and sends commands9495## Project structure (UMDF DLL + INF + driver package)9697```98DriverSolution/99├── MyUmdfDriver/ (.vcxproj — UMDF v2)100│ ├── Driver.cpp DriverEntry, EvtDeviceAdd101│ ├── Device.cpp Device-level WDF callbacks102│ ├── Queue.cpp IOCTL / Read / Write handlers103│ ├── MyUmdfDriver.def Exports104│ └── MyUmdfDriver.inf105├── MyUmdfDriverPackage/ Driver package (.cab + signing)106└── MyUmdfDriverTests/ User-mode test app (Win32 console / GTest)107```108109## Debugging UMDF110111- Attach a normal **user-mode debugger (WinDbg / Visual Studio)** to `WUDFHost.exe` — much friendlier than KMDF112- Set `HKLM\System\CurrentControlSet\Services\WUDFHost\Parameters\HostProcessDbgBreakOnStart=1` to break before driver load113- Use `Application Verifier` for memory/handle bugs (much like Driver Verifier for KMDF)114- ETW + WPP traces work the same as KMDF115116## Anti-Patterns117118| Anti-Pattern | Why It's Bad | Correct Approach |119|--------------|--------------|------------------|120| Treating UMDF callbacks as background work | They serialize requests | Hand off long work to a separate worker thread; complete the request when done |121| Calling kernel-only APIs | Won't link | Use Win32 / WDF user-mode equivalents |122| Holding a request indefinitely with no cancel handler | App hangs | Mark cancelable, handle `EvtRequestCancel` |123| Using process global state | Multiple device instances share the host | Per-device context via WDF_OBJECT_ATTRIBUTES |124| Logging via `OutputDebugString` only | Lost in production | WPP/ETW with a published GUID |125| Assuming the host stays up | Reflector can recycle it | Persist nothing in process memory; reload from registry/file on `EvtDevicePrepareHardware` |