應用程式可用的裝置介面是對隨插即用(PnP)裝置的符號鏈接,用於存取該裝置。 使用者模式應用程式可以將介面的符號連結名稱傳遞至 API 元素,例如 Microsoft Win32 CreateFile 函式。 為了取得裝置介面的符號連結名稱,使用者模式應用程式可以呼叫 組態管理員函式 或 SetupApi 函式。 如需詳細資訊,請參閱 列舉已安裝的裝置介面。
每個裝置介面都屬於 裝置介面類別。 例如,CD-ROM 裝置的驅動程式堆疊可能會提供屬於GUID_DEVINTERFACE_CDROM類別的介面。 其中一個 CD-ROM 裝置的驅動程式會註冊 GUID_DEVINTERFACE_CDROM 類別的實例,以通知系統和應用程式有可用的 CD-ROM 裝置。 如需裝置介面類別的詳細資訊,請參閱 裝置介面類別概觀。
註冊裝置介面
若要註冊裝置介面類別的實例,架構型驅動程式可以在裝置啟動之前或之後呼叫 WdfDeviceCreateDeviceInterface。 如果驅動程式支援介面的多個實例,它可以將唯一的參考字串指派給每個實例。
驅動程式註冊裝置介面之後,驅動程式可以呼叫 WdfDeviceRetrieveDeviceInterfaceString,以取得系統指派給裝置介面的符號連結名稱。
如需驅動程式可註冊裝置介面之其他方式的詳細資訊,請參閱 註冊裝置介面類別。
啟用和停用裝置介面
在裝置啟動之前建立的介面(例如,從 EvtDriverDeviceAdd、EvtChildListCreateDevice或 EvtDevicePrepareHardware),當裝置通過 PnP 列舉並開始時,架構會自動啟用。 若要防止在 PnP 啟動期間自動啟用介面,請在 PnP 啟動之前,從相同的回呼函式呼叫 WdfDeviceSetDeviceInterfaceStateEx,將該介面的 EnableInterface 參數設定為 FALSE。
裝置啟動之後所建立的介面將不會自動啟用。 驅動程式必須呼叫 WdfDeviceSetDeviceInterfaceState 或 WdfDeviceSetDeviceInterfaceStateEx,才能啟用這類介面。
當裝置進行 PnP 移除時,系統會自動停用所有介面。 請注意,任何裝置電源狀態變更或 PnP 資源重新平衡都不會變更介面的狀態。
如有必要,驅動程式可以停用並重新啟用裝置介面。 例如,如果驅動程式判斷其裝置已停止響應,驅動程式可以呼叫 WdfDeviceSetDeviceSetDeviceInterfaceState 或 WdfDeviceSetDeviceInterfaceStateEx 來停用裝置的介面,並禁止應用程式取得介面的新句柄。 (介面的現有句柄不會受到影響。)如果裝置稍後可供使用,驅動程式可以再次呼叫 WdfDeviceSetDeviceInterfaceState 或 WdfDeviceSetDeviceInterfaceStateEx 來重新啟用介面。
接收裝置介面的存取要求
當應用程式或內核模式元件要求存取驅動程式的裝置介面時,架構會呼叫驅動程式的 EvtDeviceFileCreate 回呼函式。 驅動程式可以呼叫 WdfFileObjectGetFileName,以取得應用程式或內核模式元件正在存取的裝置或檔名。 如果驅動程式在註冊裝置介面時指定參考字串,則作系統會在 WdfFileObjectGetFileName 傳回的檔案或裝置名稱中包含參考字符串。
存取其他驅動程式的裝置介面
本節說明 Kernel-Mode Driver Framework (KMDF) 驅動程式或 User-Mode Driver Framework (UMDF) 第 2 版驅動程式如何註冊以通知另一個驅動程式提供的抵達或移除裝置介面,然後建立 遠端 I/O 目標,以與裝置介面所代表的裝置通訊。
如需如何在 UMDF 第 1 版驅動程式中執行這項作的詳細資訊,請參閱 在 UMDF 驅動程式中使用裝置介面。
若要註冊裝置介面事件的通知,KMDF 驅動程式會呼叫 IoRegisterPlugPlayNotification,而 UMDF 2 驅動程式會呼叫 CM_Register_Notification。 在這兩種情況下,驅動程式會從其 EvtDriverDeviceAdd 回呼函式呼叫適當的例程。
下列程式代碼範例示範本機 UMDF 2 驅動程式如何註冊通知,然後開啟遠端 I/O 目標。
遠端驅動程式會從 EvtDriverDeviceAdd呼叫 WdfDeviceCreateDeviceInterface 來註冊裝置介面。
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; }本機驅動程式會從 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; }每次指定的裝置介面到達或移除時,系統都會呼叫本機驅動程式的通知回呼例程。 回呼例程可以檢查 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; }從工作專案回呼函式中,本機驅動程式會呼叫 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; }