Kernel-Mode Driver Framework (KMDF) Getting Started

This guide provides an introduction to developing drivers using the Kernel-Mode Driver Framework (KMDF). KMDF simplifies driver development by abstracting away many of the complexities of Windows driver programming.

Note: KMDF is the recommended framework for developing most kernel-mode drivers for Windows. It provides a robust, object-oriented approach to driver design.

Prerequisites

Before you begin, ensure you have the following:

Setting Up Your Development Environment

Follow these steps to configure your environment for KMDF driver development:

  1. Install Visual Studio and WDK: If you haven't already, download and install the latest versions.
  2. Configure Driver Signing: For testing, you'll need to set up test signing for your drivers. Refer to the WDK documentation for detailed instructions.
  3. Create a New KMDF Driver Project:
    • Open Visual Studio.
    • Select "Create a new project".
    • Search for "Kernel Mode Driver (KMDF)" and select the template.
    • Configure your project settings (name, location, etc.).

Your First KMDF Driver: A "Hello, World!" Example

Let's create a simple driver that logs a message when it's loaded.

1. Driver Entry Point

The main entry point for a KMDF driver is the DriverEntry function. This function is called by the operating system when the driver is loaded.


NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
{
    WDF_DRIVER_CONFIG config;
    NTSTATUS status;

    // Initialize the framework driver object.
    WDF_DRIVER_CONFIG_INIT(
        &config,
        OnDeviceAdd // Callback function for device addition
    );

    // Create a framework driver object.
    status = WdfDriverCreate(
        DriverObject,
        RegistryPath,
        WDF_NO_OBJECT_ATTRIBUTES,
        &config,
        WDF_NO_HANDLE // Optional: receive a handle to the framework driver object
    );

    if (!NT_SUCCESS(status)) {
        // Log an error if driver creation fails
        KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "MyDriver: WdfDriverCreate failed with status 0x%X\n", status));
    } else {
        KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "MyDriver: DriverEntry successful.\n"));
    }

    return status;
}
            

2. Device Addition Callback

The OnDeviceAdd callback function is called by the framework when a device that matches one of the driver's PnP IDs is enumerated.


static NTSTATUS
OnDeviceAdd(
    _In_ WDFDRIVER Driver,
    _Inout_ PWDFDEVICE_INIT DeviceInit
    )
{
    NTSTATUS status;
    WDFDEVICE hDevice;

    UNREFERENCED_PARAMETER(Driver);

    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "MyDriver: OnDeviceAdd called.\n"));

    // Specify the device type, for example, a functional device.
    WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_UNKNOWN);
    WdfDeviceInitSetCharacteristics(DeviceInit, FILE_AUTOGENERATED_DEVICE_NAME, TRUE);

    // Create the framework device object.
    status = WdfDeviceCreate(
        &DeviceInit,
        WDF_NO_OBJECT_ATTRIBUTES,
        &hDevice
    );

    if (!NT_SUCCESS(status)) {
        KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "MyDriver: WdfDeviceCreate failed with status 0x%X\n", status));
        return status;
    }

    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "MyDriver: Device created successfully.\n"));

    // You would typically create device interfaces, queues, etc. here.

    return status;
}
            

Tip: Use KdPrintEx for logging messages in kernel mode. These messages can be viewed in tools like DebugView or the Visual Studio debugger.

Next Steps

After creating your first basic driver, you can explore more advanced topics:

Developing kernel-mode drivers can be complex. Always refer to the official Windows Driver Kit (WDK) documentation for the most accurate and up-to-date information.