Introduction to Writing a WDF Driver
The Windows Driver Frameworks (WDF) simplifies driver development by providing an object-oriented model and a set of built-in driver components. WDF abstracts many low-level operating system details, allowing developers to focus on the specific functionality of their hardware. This document outlines the fundamental steps and concepts involved in writing a WDF driver, covering both Kernel-Mode Driver Framework (KMDF) and User-Mode Driver Framework (UMDF).
Note: WDF provides two models: KMDF and UMDF. KMDF is generally recommended for most drivers due to its performance and privilege advantages, while UMDF is suitable for drivers that can run in user mode, offering enhanced stability and easier debugging.
Key Concepts in WDF
1. WDF Objects
WDF drivers are built around a hierarchical object model. Key objects include:
- Driver Object (
WDFDRIVER): Represents the driver itself. - Device Object (
WDFDEVICE): Represents a hardware device. - Configuration Object (
WDFCONFIGURATION): Used to configure device properties. - Request Object (
WDFREQUEST): Represents I/O requests. - I/O Target Objects (
WDFIOTARGET): Represent endpoints for I/O operations.
Each object has a lifecycle managed by the framework and is associated with a handle (e.g., WDFDRIVER, WDFDEVICE).
2. Event Callback Functions
WDF drivers interact with the framework through a set of predefined callback functions. The framework calls these functions in response to framework events (e.g., device power-up, I/O request arrival).
Common callback functions include:
EvtDriverDeviceAdd: Called when the framework detects a device that the driver should manage.EvtDevicePrepareHardware: Called when the device is about to be powered on and made ready for use.EvtDeviceD0Entry: Called when the device enters the D0 (working) power state.EvtIoRead,EvtIoWrite,EvtIoIoctl: Handle different types of I/O requests.
3. The Driver Entry Point
Every WDF driver must export a DriverEntry routine, similar to traditional drivers. This routine initializes the WDF driver environment and registers the driver's configuration.
For KMDF, this typically involves creating a WDF_DRIVER_CONFIG structure and calling WdfDriverCreate.
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
// Initialize the driver configuration structure
WDF_DRIVER_CONFIG_INIT(&config, EvtDriverDeviceAdd);
// Create the WDF driver object
status = WdfDriverCreate(
DriverObject,
RegistryPath,
&attributes,
&config,
WDF_NO_HANDLE // Optional WDFDRIVER handle
);
return status;
}
4. Device Initialization
When the framework detects a device, it calls the EvtDriverDeviceAdd callback. In this callback, you typically:
- Create a
WDFDEVICEobject. - Configure device properties, such as power management and PnP capabilities.
- Register device-specific callbacks.
VOID
EvtDriverDeviceAdd(
_In_ WDFDRIVER Driver,
_Inout_ PWDFDEVICE_INIT DeviceInit
)
{
NTSTATUS status;
WDFDEVICE hDevice;
WDF_OBJECT_ATTRIBUTES deviceAttributes;
// Initialize device attributes
WDF_OBJECT_ATTRIBUTES_INIT(&deviceAttributes);
// Create the WDFDEVICE object
status = WdfDeviceCreate(DeviceInit, &deviceAttributes, &hDevice);
if (!NT_SUCCESS(status)) {
// Handle error
return;
}
// Register other device callbacks (e.g., EvtDevicePrepareHardware)
// ...
}
Steps to Write a WDF Driver
- Set up your development environment: Install Visual Studio and the Windows Driver Kit (WDK).
- Choose your WDF model: Decide between KMDF and UMDF.
- Create a new WDF driver project: Use the Visual Studio templates.
- Implement
DriverEntry: Initialize the WDF driver. - Implement
EvtDriverDeviceAdd: Create theWDFDEVICEand register PnP/Power callbacks. - Implement PnP and Power callbacks: Handle device start, stop, and power state changes.
- Implement I/O handling callbacks: Process read, write, and I/O control requests.
- Manage device resources: Allocate and map hardware resources.
- Implement error handling: Ensure robust operation.
- Build, debug, and test: Use tools like WinDbg and the Debugging Tools for Windows.
Important: Always refer to the latest Windows SDK and WDK documentation for the most accurate and up-to-date information on WDF APIs and best practices.