Delen via


Apparaatinterfaces (WDF) gebruiken

Een apparaatinterface is een symbolische koppeling naar een Plug and Play-apparaat (PnP) dat een toepassing kan gebruiken voor toegang tot het apparaat. Een toepassing in de gebruikersmodus kan de symbolische koppelingsnaam van de interface doorgeven aan een API-element, zoals de functie Microsoft Win32 CreateFile. Als u de symbolische koppelingsnaam van een apparaatinterface wilt verkrijgen, kan de gebruikersmodustoepassing Configuration Manager-functies aanroepen of SetupApi-functies. Zie Geïnstalleerde apparaatinterfaces opsommenvoor meer informatie.

Elke apparaatinterface behoort tot een apparaatinterfaceklasse. Een stuurprogrammastack voor een CD-ROM apparaat kan bijvoorbeeld een interface bieden die deel uitmaakt van de GUID_DEVINTERFACE_CDROM-klasse. Een van de stuurprogramma's van het CD-ROM apparaat registreert een exemplaar van de GUID_DEVINTERFACE_CDROM-klasse om het systeem en de toepassingen te informeren dat er een CD-ROM apparaat beschikbaar is. Zie Overzicht van apparaatinterfaceklassenvoor meer informatie over apparaatinterfaceklassen.

Een apparaatinterface registreren

Om een exemplaar van een apparaatinterfaceklasse te registreren, kan een stuurprogramma de functie WdfDeviceCreateDeviceInterface aanroepen voordat of nadat het apparaat is gestart. Als het stuurprogramma meerdere exemplaren van de interface ondersteunt, kan er een unieke referentietekenreeks aan elk exemplaar worden toegewezen.

Nadat het stuurprogramma een apparaatinterface heeft geregistreerd, kan het stuurprogramma WdfDeviceRetrieveDeviceInterfaceString aanroepen om de symbolische koppelingsnaam te verkrijgen die het systeem aan de apparaatinterface heeft toegewezen.

Zie Een Apparaatinterfaceklasse registrerenvoor meer informatie over andere manieren waarop stuurprogramma's apparaatinterfaces kunnen registreren.

Een apparaatinterface in- en uitschakelen

Interfaces die zijn gemaakt voordat het apparaat wordt gestart (bijvoorbeeld van EvtDriverDeviceAdd, EvtChildListCreateDeviceof EvtDevicePrepareHardware) worden automatisch ingeschakeld door het framework wanneer het apparaat door PnP-opsomming gaat en wordt gestart. Als u wilt voorkomen dat de interface automatisch wordt ingeschakeld tijdens het starten van PnP, roept u WdfDeviceSetDeviceInterfaceStateEx aan vanuit dezelfde callback-functie (stel de EnableInterface parameter in op FALSE) voor die interface voordat PnP wordt gestart.

Interfaces die zijn gemaakt nadat het apparaat al is gestart, worden niet automatisch ingeschakeld. Het stuurprogramma moet WdfDeviceSetDeviceInterfaceState of WdfDeviceSetDeviceInterfaceStateEx aanroepen om dergelijke interfaces in te schakelen.

Alle interfaces worden automatisch uitgeschakeld wanneer het apparaat PnP-verwijdering ondergaat. Houd er rekening mee dat wijzigingen in de energiestatus van het apparaat of het opnieuw verdelen van PnP-resources de status van de interface niet wijzigen.

Een stuurprogramma kan een apparaatinterface indien nodig uitschakelen en opnieuw inschakelen. Als een stuurprogramma bijvoorbeeld vaststelt dat het apparaat niet meer reageert, kan het stuurprogramma WdfDeviceSetDeviceInterfaceState of WdfDeviceSetDeviceInterfaceStateEx aanroepen om de interfaces van het apparaat uit te schakelen en te voorkomen dat toepassingen nieuwe ingangen voor de interface verkrijgen. (Bestaande ingangen voor de interface worden niet beïnvloed.) Als het apparaat later beschikbaar komt, kan het stuurprogramma WdfDeviceSetDeviceInterfaceState of WdfDeviceSetDeviceInterfaceStateEx opnieuw aanroepen om de interfaces opnieuw in te schakelen.

Aanvragen ontvangen voor toegang tot een apparaatinterface

Wanneer een toepassing of kernelmodusonderdeel toegang vraagt tot de apparaatinterface van een stuurprogramma, roept het framework de EvtDeviceFileCreate callback-functie van het stuurprogramma aan. Het stuurprogramma kan WdfFileObjectGetFileName aanroepen om de naam op te halen van het apparaat of bestand waartoe het onderdeel van de toepassing of kernelmodus toegang heeft. Als het stuurprogramma een referentietekenreeks heeft opgegeven bij het registreren van de apparaatinterface, bevat het besturingssysteem de referentietekenreeks in de bestandsnaam of apparaatnaam die WdfFileObjectGetFileName retourneert.

Toegang tot de apparaatinterface van een ander stuurprogramma

In deze sectie wordt beschreven hoe een stuurprogramma van Kernel-Mode Driver Framework (KMDF) of een User-Mode Driver Framework (UMDF) versie 2-stuurprogramma zich registreert voor de melding van aankomst of het verwijderen van een apparaatinterface die door een ander stuurprogramma wordt geleverd, en vervolgens een externe I/O-doel maakt om te communiceren met het apparaat dat wordt vertegenwoordigd door de apparaatinterface.

Zie Device Interfaces gebruiken in UMDF-stuurprogramma'svoor meer informatie over hoe u dit doet in een UMDF-versie 1-stuurprogramma.

Als u zich wilt registreren voor meldingen van apparaatinterfacegebeurtenissen, roept een KMDF-stuurprogramma IoRegisterPlugPlayNotificationaan, terwijl een UMDF 2-stuurprogramma CM_Register_Notificationaanroept. In beide gevallen roept het stuurprogramma de juiste routine aan vanuit de EvtDriverDeviceAdd callback-functie.

In het volgende codevoorbeeld wordt gekeken hoe een lokaal UMDF 2-stuurprogramma zich registreert voor meldingen en vervolgens het externe I/O-doel opent.

  1. Het externe stuurprogramma meldt zich aan voor een apparaatinterface door WdfDeviceCreateDeviceInterface aan te roepen vanuit EvtDriverDeviceAdd.

        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. Het lokale stuurprogramma roept CM_Register_Notification aan vanuit EvtDriverDeviceAdd om meldingen te registreren wanneer een apparaatinterface beschikbaar is. Geef een aanwijzer op voor een callback-routine voor meldingen die door het framework wordt aangeroepen wanneer apparaatinterfaces beschikbaar zijn.

    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. Het systeem roept de callbackroutine voor meldingen van het lokale stuurprogramma aan telkens wanneer de opgegeven apparaatinterface binnenkomt of wordt verwijderd. De callback-routine kan de parameter EventData onderzoeken om te bepalen welke apparaatinterface is aangekomen. Het kan vervolgens een werkitem in de wachtrij plaatsen om de apparaatinterface te openen.

    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. Vanuit de callbackfunctie van het werkitem roept het lokale stuurprogramma WdfIoTargetCreate aan om het externe doel te maken en WdfIoTargetOpen om een extern I/O-doel te openen.

    Bij het aanroepen van WdfIoTargetOpen, registreert het stuurprogramma optioneel een EvtIoTargetQueryRemove callback-functie voor het ontvangen van verwijderingsmeldingen, samen met de mogelijkheid om de verwijdering te weigeren. Als het stuurprogramma geen EvtIoTargetQueryRemovebiedt, sluit het framework het I/O-doel wanneer het apparaat wordt verwijderd.

    In zeldzame gevallen kan een UMDF 2-stuurprogramma een tweede keer CM_Register_Notification aanroepen om zich aan te melden voor notificatie bij het verwijderen van het apparaat. Als het stuurprogramma bijvoorbeeld CreateFile aanroept om een HANDLE te verkrijgen voor de apparaatinterface, moet het zich registreren voor notificaties van apparaatverwijderingen, zodat het correct kan reageren op pogingen om apparaten te verwijderen. In de meeste gevallen roept het UMDF 2-stuurprogramma CM_Register_Notification slechts één keer aan en is afhankelijk van WDF-ondersteuning voor het verwijderen van apparaten.

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

Registreren voor Melding van Aankomst van Apparaatinterface en Verwijdering van Apparaten