赞
踩
设备接口是指向应用程序可用于访问设备的即插即用 (PnP) 设备的符号链接。 用户模式应用程序可以将接口的符号链接名称传递给 API 元素,例如 Microsoft Win32 CreateFile 函数。 若要获取设备接口的符号链接名称,用户模式应用程序可以调用 配置管理器函数 或 SetupApi 函数。
每个设备接口都属于一个 设备接口类。 例如,CD-ROM 设备的驱动程序堆栈可能会提供属于 GUID_DEVINTERFACE_CDROM 类的接口。 其中一个 CD-ROM 设备的驱动程序会注册 GUID_DEVINTERFACE_CDROM 类的实例,以通知系统和应用程序 CD-ROM 设备可用。
若要注册设备接口类的实例,基于框架的驱动程序可以在设备启动之前或之后调用 WdfDeviceCreateDeviceInterface 。 如果驱动程序支持接口的多个实例,则可以为每个实例分配唯一的引用字符串。
驱动程序注册设备接口后,驱动程序可以调用 WdfDeviceRetrieveDeviceInterfaceString 来获取系统已分配给设备接口的符号链接名称。
在设备启动之前创建的接口 (例如,当设备通过 PnP 枚举并启动时,框架会自动启用从 EvtDriverDeviceAdd、 EvtChildListCreateDevice 或 EvtDevicePrepareHardware) 创建的接口。 若要防止在 PnP 启动期间自动启用接口,请从同一回调函数调用 WdfDeviceSetDeviceInterfaceStateEx , 在 PnP 启动之前将该接口的 EnableInterface 参数设置为 FALSE。
在设备已启动后创建的接口不会自动启用。 驱动程序必须调用 WdfDeviceSetDeviceInterfaceState 或 WdfDeviceSetDeviceInterfaceStateEx 才能启用此类接口。
当设备进行 PnP 删除时,将自动禁用所有接口。 请注意,任何设备电源状态更改或 PnP 资源重新平衡都不会更改接口的状态。
如有必要,驱动程序可以禁用和重新启用设备接口。 例如,如果驱动程序确定其设备已停止响应,则驱动程序可以调用 WdfDeviceSetDeviceInterfaceState 或 WdfDeviceSetDeviceInterfaceStateEx 来禁用设备的接口并禁止应用程序获取接口的新句柄。 (接口的现有句柄不受影响。) 如果设备稍后可用,驱动程序可以再次调用 WdfDeviceSetDeviceInterfaceState 或 WdfDeviceSetDeviceInterfaceStateEx 以重新启用接口。
当应用程序或内核模式组件请求访问驱动程序的设备接口时,框架会调用驱动程序的 EvtDeviceFileCreate 回调函数。 驱动程序可以调用 WdfFileObjectGetFileName ,以获取应用程序或内核模式组件正在访问的设备或文件的名称。 如果驱动程序在注册设备接口时指定了引用字符串,则操作系统将在 WdfFileObjectGetFileName 返回的文件或设备名称中包含引用字符串。
Kernel-Mode驱动程序框架 (KMDF) 驱动程序或User-Mode(UMDF版本 2) 驱动程序框架可以在驱动程序中注册以通知其他驱动程序提供的设备接口的到达或删除,然后创建 远程 I/O 目标 以与设备接口表示的设备通信。
为了注册设备接口事件的通知,KMDF 驱动程序调用 IoRegisterPlugPlayNotification,而 UMDF 2 驱动程序调用 CM_Register_Notification。 在这两种情况下,驱动程序从其 EvtDriverDeviceAdd 回调函数调用相应的例程。
1. 下面的代码示例演示本地 UMDF 2 驱动程序如何注册通知,然后打开远程 I/O 目标:
- UNICODE_STRING ref;
- RtlInitUnicodeString(&ref, MY_HID_FILTER_REFERENCE_STRING);
- status = WdfDeviceCreateDeviceInterface(
- hDevice,
- (LPGUID) &GUID_DEVINTERFACE_MY_HIDFILTER_DRIVER,
- &ref // ReferenceString
- );
-
- if (!NT_SUCCESS (status)) {
- MyKdPrint( ("WdfDeviceCreateDeviceInterface failed 0x%x\n", status));
- return status;
- }
2. 本地驱动程序从 EvtDriverDeviceAdd 调用 CM_Register_Notification,以便在设备接口可用时注册通知。 提供指向当设备接口可用时框架调用的通知回调例程的指针。
- DWORD cmRet;
- CM_NOTIFY_FILTER cmFilter;
-
- ZeroMemory(&cmFilter, sizeof(cmFilter));
- cmFilter.cbSize = sizeof(cmFilter);
- cmFilter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
- cmFilter.u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_MY_HIDFILTER_DRIVER;
-
- cmRet = CM_Register_Notification(
- &cmFilter, // PCM_NOTIFY_FILTER pFilter,
- (PVOID) hDevice, // PVOID pContext,
- MyCmInterfaceNotification, // PCM_NOTIFY_CALLBACK pCallback,
- &fdoData->CmNotificationHandle // PHCMNOTIFICATION pNotifyContext
- );
- if (cmRet != CR_SUCCESS) {
- MyKdPrint( ("CM_Register_Notification failed, error %d\n", cmRet));
- status = STATUS_UNSUCCESSFUL;
- return status;
- }
3. 每次指定的设备接口到达或删除时,系统都会调用本地驱动程序的通知回调例程。 回调例程可以检查 EventData 参数以确定到达的设备接口。 然后,它可能会将工作项排队以打开设备接口:
- DWORD
- MyCmInterfaceNotification(
- _In_ HCMNOTIFICATION hNotify,
- _In_opt_ PVOID Context,
- _In_ CM_NOTIFY_ACTION Action,
- _In_reads_bytes_(EventDataSize) PCM_NOTIFY_EVENT_DATA EventData,
- _In_ DWORD EventDataSize
- )
- {
- PFDO_DATA fdoData;
- UNICODE_STRING name;
- WDFDEVICE device;
- NTSTATUS status;
- WDFWORKITEM workitem;
-
- UNREFERENCED_PARAMETER(hNotify);
- UNREFERENCED_PARAMETER(EventDataSize);
-
- device = (WDFDEVICE) Context;
- fdoData = ToasterFdoGetData(device);
-
- switch(Action) {
- case CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL:
- MyKdPrint( ("MyCmInterfaceNotification: Arrival of %S\n",
- EventData->u.DeviceInterface.SymbolicLink));
-
- //
- // Enqueue a work item to open target
- //
-
- break;
- case CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL:
- MyKdPrint( ("MyCmInterfaceNotification: removal of %S\n",
- EventData->u.DeviceInterface.SymbolicLink));
- break;
- default:
- MyKdPrint( ("MyCmInterfaceNotification: Arrival unknown action\n"));
- break;
- }
-
- return 0;
- }
4. 从工作项回调函数中,本地驱动程序调用 WdfIoTargetCreate 来创建远程目标,并调用 WdfIoTargetOpen 打开远程 I/O 目标。
调用 WdfIoTargetOpen 时,驱动程序可以选择注册 EvtIoTargetQueryRemove 回调函数来接收删除通知以及拒绝删除的机会。 如果驱动程序不提供 EvtIoTargetQueryRemove,框架在删除设备时关闭 I/O 目标。
在极少数情况下,UMDF 2 驱动程序可以再次调用 CM_Register_Notification ,以注册设备删除通知。 例如,如果驱动程序调用 CreateFile 来获取设备接口的 HANDLE,它应注册设备删除通知,以便可以正确响应查询删除尝试。 在大多数情况下,UMDF 2 驱动程序只 调用CM_Register_Notification 一次,并且依赖于 WDF 支持来删除设备:
- VOID
- EvtWorkItem(
- _In_ WDFWORKITEM WorkItem
- )
- {
- //
- // create and open remote target
- //
-
- return;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。