Freigeben über


Verwenden von Geräteschnittstellen (WDF)

Eine Geräteschnittstelle ist eine symbolische Verknüpfung mit einem PnP-Gerät (Plug & Play), das eine Anwendung für den Zugriff auf das Gerät verwenden kann. Eine Anwendung im Benutzermodus kann den symbolischen Linknamen der Schnittstelle an ein API-Element übergeben, z. B. an die CreateFile-Funktion von Microsoft Win32. Um den symbolischen Linknamen einer Geräteschnittstelle abzurufen, kann die Benutzermodusanwendung Configuration Manager-Funktionen oder SetupApi-Funktionen aufrufen. Weitere Informationen finden Sie unter Auflisten installierter Geräteschnittstellen.

Jede Geräteschnittstelle gehört zu einer Geräteschnittstellenklasse. Beispielsweise kann ein Treiberstapel für ein CD-ROM-Gerät eine Schnittstelle bereitstellen, die zur GUID_DEVINTERFACE_CDROM-Klasse gehört. Einer der Treiber des CD-ROM-Geräts registriert eine instance der GUID_DEVINTERFACE_CDROM-Klasse, um das System und die Anwendungen darüber zu informieren, dass ein CD-ROM-Gerät verfügbar ist. Weitere Informationen zu Geräteschnittstellenklassen finden Sie unter Übersicht über Geräteschnittstellenklassen.

Registrieren einer Geräteschnittstelle

Um eine instance einer Geräteschnittstellenklasse zu registrieren, kann ein frameworkbasierter Treiber WdfDeviceCreateDeviceInterface entweder vor oder nach dem Starten des Geräts aufrufen. Wenn der Treiber mehrere Instanzen der Schnittstelle unterstützt, kann er jeder instance eine eindeutige Verweiszeichenfolge zuweisen.

Nachdem der Treiber eine Geräteschnittstelle registriert hat, kann der Treiber WdfDeviceRetrieveDeviceInterfaceString aufrufen, um den symbolischen Linknamen abzurufen, den das System der Geräteschnittstelle zugewiesen hat.

Informationen zu anderen Möglichkeiten, wie Treiber Geräteschnittstellen registrieren können, finden Sie unter Registrieren einer Geräteschnittstellenklasse.

Aktivieren und Deaktivieren einer Geräteschnittstelle

Schnittstellen, die vor dem Starten des Geräts erstellt wurden (z. B. evtDriverDeviceAdd, EvtChildListCreateDevice oder EvtDevicePrepareHardware) werden automatisch vom Framework aktiviert, wenn das Gerät die PnP-Enumeration durchläuft und startet. Um zu verhindern, dass die Schnittstelle während des PnP-Starts automatisch aktiviert wird, rufen Sie WdfDeviceSetDeviceInterfaceStateEx über dieselbe Rückruffunktion (legen Sie den EnableInterface-Parameter auf FALSE fest) für diese Schnittstelle vor dem PnP-Start.

Schnittstellen, die nach dem start des Geräts erstellt werden, werden nicht automatisch aktiviert. Der Treiber muss WdfDeviceSetDeviceInterfaceState oder WdfDeviceSetDeviceInterfaceStateEx aufrufen, um solche Schnittstellen zu aktivieren.

Alle Schnittstellen werden automatisch deaktiviert, wenn das Gerät entfernt wird. Beachten Sie, dass änderungen des Geräteenergiezustands oder eine neu ausgeglichene PnP-Ressource den Zustand der Schnittstelle nicht ändern.

Ein Treiber kann eine Geräteschnittstelle bei Bedarf deaktivieren und erneut aktivieren. Wenn ein Treiber beispielsweise feststellt, dass sein Gerät nicht mehr reagiert, kann der Treiber WdfDeviceSetDeviceInterfaceState oder WdfDeviceSetDeviceInterfaceStateEx aufrufen, um die Schnittstellen des Geräts zu deaktivieren und zu verhindern, dass Anwendungen neue Handles für die Schnittstelle abrufen. (Vorhandene Handles für die Schnittstelle sind nicht betroffen.) Wenn das Gerät später verfügbar wird, kann der Treiber WdfDeviceSetDeviceInterfaceState oder WdfDeviceSetDeviceInterfaceStateEx erneut aufrufen, um die Schnittstellen erneut zu aktivieren.

Empfangen von Anforderungen für den Zugriff auf eine Geräteschnittstelle

Wenn eine Anwendung oder Kernelmoduskomponente Zugriff auf die Geräteschnittstelle eines Treibers anfordert, ruft das Framework die Rückruffunktion EvtDeviceFileCreate des Treibers auf. Der Treiber kann WdfFileObjectGetFileName aufrufen, um den Namen des Geräts oder der Datei abzurufen, auf das die Anwendung oder Kernelmoduskomponente zugreift. Wenn der Treiber bei der Registrierung der Geräteschnittstelle eine Verweiszeichenfolge angegeben hat, schließt das Betriebssystem die Verweiszeichenfolge in den Datei- oder Gerätenamen ein, den WdfFileObjectGetFileName zurückgibt.

Zugreifen auf die Geräteschnittstelle eines anderen Treibers

In diesem Abschnitt wird gezeigt, wie ein KMDF-Treiber (Kernel-Mode Driver Framework) oder ein UMDF-Treiber (User-Mode Driver Framework, Version 2) registriert wird, um eine von einem anderen Treiber bereitgestellte Geräteschnittstelle zu erhalten oder zu entfernen. Anschließend wird ein Remote-E/A-Ziel für die Kommunikation mit dem Gerät erstellt, das durch die Geräteschnittstelle dargestellt wird.

Informationen dazu, wie Sie dies in einem UMDF-Treiber der Version 1 durchführen, finden Sie unter Verwenden von Geräteschnittstellen in UMDF-Treibern.

Um sich für die Benachrichtigung über Geräteschnittstellenereignisse zu registrieren, ruft ein KMDF-Treiber IoRegisterPlugPlayNotification auf, während ein UMDF 2-Treiber CM_Register_Notification aufruft. In beiden Fällen ruft der Treiber die entsprechende Routine über seine EvtDriverDeviceAdd-Rückruffunktion auf.

Das folgende Codebeispiel zeigt, wie sich ein lokaler UMDF 2-Treiber für Benachrichtigungen registriert und dann das Remote-E/A-Ziel öffnet.

  1. Der Remotetreiber registriert sich für eine Geräteschnittstelle, indem er WdfDeviceCreateDeviceInterface von EvtDriverDeviceAdd aufruft.

        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. Der lokale Treiber ruft CM_Register_Notification von EvtDriverDeviceAdd auf, um sich für eine Benachrichtigung zu registrieren, wenn eine Geräteschnittstelle verfügbar ist. Geben Sie einen Zeiger auf eine Benachrichtigungsrückrufroutine an, die das Framework aufruft, wenn Geräteschnittstellen verfügbar sind.

    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. Das System ruft die Benachrichtigungsrückrufroutine des lokalen Treibers jedes Mal auf, wenn die angegebene Geräteschnittstelle eingeht oder entfernt wird. Die Rückrufroutine kann den EventData-Parameter untersuchen, um zu bestimmen, welche Geräteschnittstelle eingetroffen ist. Es kann dann ein Arbeitselement in die Warteschlange stellen, um die Geräteschnittstelle zu öffnen.

    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. Über die Rückruffunktion für Arbeitselemente ruft der lokale Treiber WdfIoTargetCreate auf, um das Remoteziel zu erstellen, und WdfIoTargetOpen , um ein Remote-E/A-Ziel zu öffnen.

    Beim Aufrufen von WdfIoTargetOpen registriert der Treiber optional eine EvtIoTargetQueryRemove-Rückruffunktion , um eine Entfernungsbenachrichtigung zu erhalten, zusammen mit der Möglichkeit, die Entfernung abzulehnen. Wenn der Treiber EvtIoTargetQueryRemove nicht bereitstellt, schließt das Framework das E/A-Ziel, wenn das Gerät entfernt wird.

    In seltenen Fällen kann ein UMDF 2-Treiber CM_Register_Notification ein zweites Mal aufrufen, um sich für die Benachrichtigung über die Geräteentfernung zu registrieren. Wenn der Treiber beispielsweise CreateFile aufruft, um ein HANDLE für die Geräteschnittstelle zu erhalten, sollte er sich für die Benachrichtigung über die Geräteentfernung registrieren, damit er ordnungsgemäß auf Abfrageentfernungsversuche reagieren kann. In den meisten Fällen ruft der UMDF 2-Treiber CM_Register_Notification nur einmal auf und nutzt die WDF-Unterstützung für die Geräteentfernung.

    VOID 
    EvtWorkItem(
        _In_ WDFWORKITEM WorkItem
    )
    {
        // 
        // create and open remote target
        //
    
        return;
    }
    

Registrieren für die Benachrichtigung über die Ankunft der Geräteschnittstelle und Geräteentfernung