编写简单的WDF驱动程序

编写简单的WDF驱动程序

  • 在创建新的KMDF或UMDF程序时,必须选择一个不多于32个字符的驱动程序名称。此长度限制在wdfglobals.h中定义。如果驱动程序的名称超出最大尺度,则驱动程序无法加载。
  • 每个基于框架的驱动程序都包含一个DriverEntry例程和一组事件回调函数,框架在发生特定于对象的事件时将调用该函数。

基于框架的简单驱动程序可能由以下内容组成:

  • DriverEntry例程,在加载驱动程序并调用WdfDriverCreate时调用。

  • 一个EvtDriverDeviceAdd事件回调函数,当即插即用(PnP)管理器使用与驱动程序支持的硬件ID匹配的硬件标识符(ID)报告设备检测时,框架将调用该函数。

    可以通过提供一个INF文件来指定驱动程序支持的硬件ID,操作系统会在第一次将设备连接到计算机时使用该文件来安装驱动程序。
    驱动程序的EvtDriverDeviceAdd回调函数调用WdfDeviceCreate为检测到的设备创建框架设备对象。

  • 当i/o管理器向驱动程序发送i/o请求时,框架调用请求处理程序(如EvtIoDefault回调函数)。
    当i/o管理器将i/o请求发送到驱动程序时,框架会将请求放入i/o队列,然后通过调用请求处理程序通知你的驱动程序。
    驱动程序必须为每个设备创建至少一个i/o队列,以便驱动程序可以接收设备的i/o请求。若要创建i/o队列,驱动程序将调用WdfQueueCreate,这将创建一个框架队列对象并注册设备的请求处理程序。

WDF驱动程序例程的DriverEntry

  • DriverEntry是加载驱动程序后调用的第一个驱动程序提供的例程。它负责初始化驱动程序。

  • 语法

    NTSTATUS DriverEntry(
    	_In_ PDRIVER_OBJECT DriverObject,
    	_In_ PUNICODE_STRING RegistryPath
    );
    
  • 参数

    DriverObject:指向驱动程序_对象结构的指针,该结构表示驱动程序的WDM驱动程序对象。

    RegistryPath:指向UNICODE_字符串结构的指针,该字符串结构指定注册表中驱动程序的Parameters项的路径。

  • 返回值
    如果例程成功,则必须返回状态“_成功”,否则,它必须返回在ntstatus中定义的错误状态值之一。

  • 备注
    与所有WDM驱动程序一样,基于框架的驱动程序必须具有DriverEntry例程,该例程是在加载驱动程序后调用的。基于框架的驱动程序的DriverEntry例程必须:

    • 激活WPP软件跟踪
      DriverEntry应包含一个WPP_INIT_TRACING宏来激活软件跟踪。
    • 调用WdfDriverCreate
      对WdfDriverCreate的调用使驱动程序可以使用Windows驱动程序框架接口。在调用WdfDriverCreate之前,驱动程序无法调用其他框架例程。
    • 分配任何特定于设备的系统资源和可能需要的全局变量
      通常驱动程序将系统资源与单个设备相关联。因此,基于框架的驱动程序在EvtDriverDeviceAdd回调中分配大多数资源,在检测到各个设备时将调用该回调。因为UMDF驱动程序的多个实例可能由单独的Wudfhost实例托管,所以全局变量可能无法在UMDF驱动程序的所有实例中使用。
    • 从注册表获取驱动程序特定的参数
      某些驱动程序从注册表中获取参数,这些驱动程序可以调用WdfDriverOpenParametersRegistryKey来打开包含这些参数的注册表项。
    • 提供DriverEntry返回值

串行(KMDF)示例驱动程序的DriverEntry例程

NTSTATUS
DriverEntry(
	IN PDRIVEROBJECT DriverObject,
	IN PUNICODE RegistryPath
	)
{
	WDF_DRIVER_CONFIG config;
	WDFDRIVER hDriver;
	NTSTATUS status;
	WDF_OBJECT_ATTRIBUTES attributes;
	SERIAL_FIRMWARE_DATA driverDefaults;

	//初始化WPP 跟踪
	WPP_INIT_TRACING(
						DriverObject,
						RegistryPath
						);
	SerialDbgPrintEx(
						TRACING_LEVEL_INFORMATION,
						DBG_INIT,
						"Serial Sample (WDF Version) - Built %s %s\n",
						__DATE__,__TIME__
							);
	WDF_OBJECT_CONFIG_INIT(
							&config,
							SerialEvtDeviceAdd
							);
	status = WdfDriverCreate(
								DriverObject,
								RegistryPath,
								&attributes,
								&config,
								&hDriver
								);
	if(!NT_SUCCESS(status)){
		SreialDbgPrintEx(
							TRACE_LEVEL_ERROR,
							DBG_INIT,
							"WdfDriverCreate failed with status 0x%x\n",
							ststus
							);
		WPP_CLEANUP(DriverObject);
		return status;
	}
	SerialGetConfigDefaults(
								&driverDefaults,
								hDriver
								);
	if(driverDefaults.ShouldBreakOnEntry){
		DbgBreakPoint();
	}
	return status;
}