Delen via


Zelfstudie: Een Hello World Windows-stuurprogramma schrijven (Kernel-Mode Driver Framework)

In dit artikel wordt beschreven hoe u een klein Universeel Windows-stuurprogramma schrijft met behulp van Kernel-Mode Driver Framework (KMDF) en vervolgens uw stuurprogramma op een afzonderlijke computer implementeert en installeert.

Voorwaarden

  • Volg de stappen voor het installeren van Windows Driver Kit (WDK). Hulpprogramma's voor foutopsporing voor Windows is opgenomen wanneer u de WDK installeert.

  • Installeer Visual Studio 2022. Wanneer u Visual Studio 2022 installeert, selecteert u de Desktopontwikkeling met C++ workload en voegt u vervolgens onder Afzonderlijke onderdelen toe:

    • MSVC v143 - VS 2022 C++ ARM64/ARM64EC spectre-verperkte bibliotheken (nieuwste)
    • MSVC v143 - VS 2022 C++ x64/x86 Spectre-verzachte bibliotheken (nieuwste)
    • C++ ATL voor de nieuwste v143-buildhulpprogramma's met Spectre-mitigaties (ARM64/ARM64EC)
    • C++ ATL voor de nieuwste v143-buildtools met Spectre Mitigations (x86 & x64)
    • C++ MFC voor de nieuwste v143-buildtools met Spectre-beveiligingsmaatregelen (ARM64/ARM64EC)
    • C++ MFC voor de nieuwste v143 buildtools met Spectre-beveiligingsmaatregelen (x86 & x64)
    • Windows Driver Kit

Een stuurprogramma maken en bouwen

  1. Open Microsoft Visual Studio. Kies in het menu BestandNieuw > Project.

  2. Selecteer in het dialoogvenster Een nieuw project maken de optie C++ in de keuzelijst links, kies Windows in de middelste keuzelijst, en kies stuurprogramma in de rechter keuzelijst.

  3. Selecteer stuurprogramma voor kernelmodus, leeg (KMDF) in de lijst met projecttypen. Selecteer Volgende.

    Schermopname van het dialoogvenster Nieuw project van Visual Studio met de optie voor het kernelmodusstuurprogramma geselecteerd.

    Fooi

    Als u geen stuurprogrammaprojectsjablonen in Visual Studio kunt vinden, is de WDK Visual Studio-extensie niet correct geïnstalleerd. U kunt dit oplossen door Visual Studio Installer-te starten, wijzigen te selecteren, Windows Driver Kits toe te voegen op het tabblad Afzonderlijke onderdelen en Wijzigente selecteren.

  4. Voer in het dialoogvenster Uw nieuwe project configureren 'KmdfHelloWorld' in het veld Projectnaam.

    Notitie

    Wanneer u een nieuw KMDF- of UMDF-stuurprogramma maakt, moet u een stuurprogrammanaam met 32 tekens of minder selecteren. Deze lengtelimiet wordt gedefinieerd in wdfglobals.h.

  5. Voer in het veld Locatie de map in waar u het nieuwe project wilt maken.

  6. Controleer Oplossing en project in dezelfde map plaatsen en selecteer maken.

    Schermopname van het dialoogvenster Uw nieuwe project configureren met de knop Maken gemarkeerd.

    Visual Studio maakt één project en een oplossing. U kunt deze zien in het Solution Explorer-venster. (Als het Solution Explorer-venster niet zichtbaar is, kiest u Solution Explorer- in het menu Weergave.) De oplossing heeft een stuurprogrammaproject met de naam KmdfHelloWorld.

    Schermopname van het visual Studio Solution Explorer-venster met de oplossing en het lege stuurprogrammaproject met de naam KmdfHelloWorld.

  7. Selecteer en houd in het Solution Explorer venster de KmdfHelloWorld-oplossing ingedrukt (of selecteer deze met de rechtermuisknop) en kies Configuration Manager-. Kies een configuratie en platform voor het stuurprogrammaproject. Kies bijvoorbeeld: Foutopsporing en x64.

  8. Selecteer in het venster Solution Explorer het KmdfHelloWorld project opnieuw en houd deze ingedrukt (of selecteer deze met de rechtermuisknop), kies Toevoegenen selecteer vervolgens Nieuw item.

  9. Selecteer in het dialoogvenster Nieuw item toevoegenC++-bestand. Voer voor Naam'Driver.c' in.

    Notitie

    De bestandsnaamextensie is .c, niet .cpp.

    Selecteer toevoegen. Het bestand Driver.c wordt toegevoegd onder Bronbestanden, zoals hier wordt weergegeven.

    Schermopname van het visual Studio Solution Explorer-venster met het bestand driver.c dat is toegevoegd aan het stuurprogrammaproject.

Uw eerste stuurprogrammacode schrijven

Nu u uw lege Hello World-project hebt gemaakt en het sourcebestand Driver.c hebt toegevoegd, schrijft u de meest eenvoudige code die nodig is om het stuurprogramma uit te voeren door twee eenvoudige callback-functies voor gebeurtenissen te implementeren.

  1. In Driver.c begint u met het opnemen van deze headers:

    #include <ntddk.h>
    #include <wdf.h>
    

    Fooi

    Als u geen Ntddk.hkunt toevoegen, opent u Configuratie -> C/C++ -> Algemeen -> aanvullende includemappen en voegt u C:\Program Files (x86)\Windows Kits\10\Include\<build#>\kmtoe, waarbij u <build#> vervangt door de juiste map in uw WDK-installatie.

    Ntddk.h bevat kern-Windows-kerneldefinities voor alle stuurprogramma's, terwijl Wdf.h definities voor stuurprogramma's bevat op basis van het Windows Driver Framework (WDF).

  2. Geef vervolgens declaraties op voor de twee callbacks die u gaat gebruiken:

    DRIVER_INITIALIZE DriverEntry;
    EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
    
  3. Gebruik de volgende code om uw DriverEntry-te schrijven:

    NTSTATUS 
    DriverEntry(
        _In_ PDRIVER_OBJECT     DriverObject, 
        _In_ PUNICODE_STRING    RegistryPath
    )
    {
        // NTSTATUS variable to record success or failure
        NTSTATUS status = STATUS_SUCCESS;
    
        // Allocate the driver configuration object
        WDF_DRIVER_CONFIG config;
    
        // Print "Hello World" for DriverEntry
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n" ));
    
        // Initialize the driver configuration object to register the
        // entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd
        WDF_DRIVER_CONFIG_INIT(&config, 
                               KmdfHelloWorldEvtDeviceAdd
                               );
    
        // Finally, create the driver object
        status = WdfDriverCreate(DriverObject, 
                                 RegistryPath, 
                                 WDF_NO_OBJECT_ATTRIBUTES, 
                                 &config, 
                                 WDF_NO_HANDLE
                                 );
        return status;
    }
    

    DriverEntry- is het startpunt voor alle stuurprogramma's, net zoals Main() dat is voor veel toepassingen in de gebruikersmodus. De taak van DriverEntry is het initialiseren van structuren en resources voor het hele stuurprogramma. In dit voorbeeld hebt u 'Hallo wereld' geprint bij DriverEntry, het stuurprogrammaobject geconfigureerd om uw EvtDeviceAdd callback-ingangspunt te registreren, vervolgens het stuurprogrammaobject gemaakt en geretourneerd.

    Het stuurprogrammaobject fungeert als het bovenliggende object voor alle andere frameworkobjecten die u in uw stuurprogramma kunt maken, waaronder apparaatobjecten, I/O-wachtrijen, timers, spinlocks en meer. Zie Inleiding tot frameworkobjectenvoor meer informatie over frameworkobjecten.

    Tip

    Voor DriverEntry-raden we u ten zeerste aan de naam 'DriverEntry' te gebruiken om te helpen bij codeanalyse en foutopsporing.

  4. Gebruik vervolgens de volgende code om uw KmdfHelloWorldEvtDeviceAdd-te schrijven:

    NTSTATUS 
    KmdfHelloWorldEvtDeviceAdd(
        _In_    WDFDRIVER       Driver, 
        _Inout_ PWDFDEVICE_INIT DeviceInit
    )
    {
        // We're not using the driver object,
        // so we need to mark it as unreferenced
        UNREFERENCED_PARAMETER(Driver);
    
        NTSTATUS status;
    
        // Allocate the device object
        WDFDEVICE hDevice;    
    
        // Print "Hello World"
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));
    
        // Create the device object
        status = WdfDeviceCreate(&DeviceInit, 
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &hDevice
                                 );
        return status;
    }
    

    EvtDeviceAdd wordt aangeroepen door het systeem wanneer wordt gedetecteerd dat uw apparaat is aangekomen. Het is de taak om structuren en resources voor dat apparaat te initialiseren. In dit voorbeeld hebt u gewoon een 'Hallo wereld'-bericht afgedrukt voor EvtDeviceAdd-, het apparaatobject gemaakt en geretourneerd. In andere stuurprogramma's die u schrijft, kunt u I/O-wachtrijen maken voor uw hardware, een apparaatcontext instellen opslagruimte voor apparaatspecifieke informatie of andere taken uitvoeren die nodig zijn om uw apparaat voor te bereiden.

    Fooi

    Voor het toevoegen van callback op het apparaat ziet u hoe u het benoemd hebt met de naam van uw stuurprogramma als voorvoegsel (KmdfHelloWorldEvtDeviceAdd). Over het algemeen raden we u aan de functies van uw stuurprogramma op deze manier te benoemen om deze te onderscheiden van de functies van andere stuurprogramma's. DriverEntry is de enige die u precies zo moet noemen.

  5. Uw volledige Driver.c ziet er nu als volgt uit:

    #include <ntddk.h>
    #include <wdf.h>
    DRIVER_INITIALIZE DriverEntry;
    EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
    
    NTSTATUS 
    DriverEntry(
        _In_ PDRIVER_OBJECT     DriverObject, 
        _In_ PUNICODE_STRING    RegistryPath
    )
    {
        // NTSTATUS variable to record success or failure
        NTSTATUS status = STATUS_SUCCESS;
    
        // Allocate the driver configuration object
        WDF_DRIVER_CONFIG config;
    
        // Print "Hello World" for DriverEntry
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n" ));
    
        // Initialize the driver configuration object to register the
        // entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd
        WDF_DRIVER_CONFIG_INIT(&config, 
                               KmdfHelloWorldEvtDeviceAdd
                               );
    
        // Finally, create the driver object
        status = WdfDriverCreate(DriverObject, 
                                 RegistryPath, 
                                 WDF_NO_OBJECT_ATTRIBUTES, 
                                 &config, 
                                 WDF_NO_HANDLE
                                 );
        return status;
    }
    
    NTSTATUS 
    KmdfHelloWorldEvtDeviceAdd(
        _In_    WDFDRIVER       Driver, 
        _Inout_ PWDFDEVICE_INIT DeviceInit
    )
    {
        // We're not using the driver object,
        // so we need to mark it as unreferenced
        UNREFERENCED_PARAMETER(Driver);
    
        NTSTATUS status;
    
        // Allocate the device object
        WDFDEVICE hDevice;    
    
        // Print "Hello World"
        KdPrintEx(( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n" ));
    
        // Create the device object
        status = WdfDeviceCreate(&DeviceInit, 
                                 WDF_NO_OBJECT_ATTRIBUTES,
                                 &hDevice
                                 );
        return status;
    }
    
  6. Opslaan Driver.c.

In dit voorbeeld ziet u een fundamenteel concept van stuurprogramma's: ze zijn een 'verzameling callbacks' die, na initialisatie, zitten en wachten totdat het systeem ze aanroept wanneer het iets nodig heeft. Een systeemaanroep kan een nieuwe gebeurtenis voor apparaatinkomst zijn, een I/O-aanvraag van een gebruikersmodustoepassing, een gebeurtenis voor het afsluiten van de systeemstroom, een aanvraag van een ander stuurprogramma of een onverwachte verwijderings gebeurtenis wanneer een gebruiker het apparaat onverwacht loskoppelt. Gelukkig hoefde u zich alleen maar zorgen te maken over het aanmaken van stuurprogramma's en apparaten om 'Hallo wereld' te zeggen.

Vervolgens bouwt u uw stuurprogramma.

Het stuurprogramma bouwen

  1. Selecteer in het Solution Explorer venster Solution KmdfHelloWorld (1 project) en houd deze vast (of selecteer deze met de rechtermuisknop) en kies Configuration Manager-. Kies een configuratie en platform voor het stuurprogrammaproject. Voor deze oefening, kies Foutopsporing en x64.

  2. Selecteer en houd in het Solution Explorer-venster de rechtermuisknop ingedrukt op KmdfHelloWorld en kies Eigenschappen. Stel in Wpp-tracering > Alle optiesde instelling Wpp-tracering uitvoeren in op Geen. Selecteer toepassen en selecteer vervolgens OK.

  3. Als u het stuurprogramma wilt bouwen, kiest u Build Solution in het menu Build. Visual Studio toont de voortgang van de build in het venster Output. (Als het venster Uitvoer niet zichtbaar is, kiest u Uitvoer in het menu Weergave.) Wanneer u hebt gecontroleerd of de oplossing is gebouwd, kunt u Visual Studio sluiten.

  4. Als u het ingebouwde stuurprogramma wilt zien, gaat u in Verkenner naar de map KmdfHelloWorld en gaat u naar x64\Debug\KmdfHelloWorld. De map bevat:

    • KmdfHelloWorld.sys - het stuurprogrammabestand voor de kernelmodus
    • KmdfHelloWorld.inf - een informatiebestand dat Windows gebruikt bij het installeren van het stuurprogramma
    • KmdfHelloWorld.cat - een catalogusbestand dat het installatieprogramma gebruikt om de testhandtekening van het stuurprogramma te controleren

Tip

Als u DriverVer set to a date in the future ziet bij het bouwen van uw stuurprogramma, wijzigt u de instellingen van het stuurprogrammaproject zodat Inf2Cat /uselocaltimeinstelt. Gebruik hiervoor configuratie-eigenschappen>Inf2Cat->Algemeen>Lokale tijd gebruiken. Nu gebruiken zowel Stampinf als Inf2Cat lokale tijd.

Het stuurprogramma implementeren

Normaal gesproken wordt het foutopsporingsprogramma en het stuurprogramma uitgevoerd op afzonderlijke computers wanneer u een stuurprogramma test en foutopsporing uitvoert. De computer waarop het foutopsporingsprogramma wordt uitgevoerd, wordt de hostcomputergenoemd en de computer waarop het stuurprogramma wordt uitgevoerd, wordt de doelcomputergenoemd. De doelcomputer wordt ook wel de testcomputergenoemd.

Tot nu toe hebt u Visual Studio gebruikt om een stuurprogramma op de hostcomputer te bouwen. Nu moet u een doelcomputer configureren.

  1. Volg de instructies in Een computer inrichten voor het implementeren en testen van stuurprogramma's (WDK 10).

    Tip

    Wanneer u de stappen volgt om de doelcomputer automatisch in te richten met behulp van een netwerkkabel, noteert u de poort en sleutel. U gebruikt deze later in de stap voor foutopsporing. In dit voorbeeld gebruiken we 50000 als poort en 1.2.3.4 als sleutel.

    In scenario's voor foutopsporing van echte stuurprogramma's wordt u aangeraden een door KDNET gegenereerde sleutel te gebruiken. Zie het onderwerp Foutopsporingsstuurprogramma's - Stapsgewijze lab (Sysvad-kernelmodus) voor meer informatie over het gebruik van KDNET om een willekeurige sleutel te genereren.

  2. Open uw oplossing op de hostcomputer in Visual Studio. U kunt dubbelklikken op het oplossingsbestand, KmdfHelloWorld.sln, in de map KmdfHelloWorld.

  3. Selecteer en houd in het Solution Explorer- venster het KmdfHelloWorld project ingedrukt (of klik erop met de rechtermuisknop) en kies Eigenschappen.

  4. Ga in het venster Eigenschappenpagina's van KmdfHelloWorld, naar Configuratie-eigenschappen, > Stuurprogramma installeren, > Implementatie, zoals hier wordt weergegeven.

  5. Controleer Vorige stuurprogrammaversies verwijderen vóór de implementatie.

  6. Selecteer voor doelapparaatnaamde naam van de computer die u hebt geconfigureerd voor testen en foutopsporing. In deze oefening gebruiken we een computer met de naam MyTestComputer.

  7. Selecteer hardware-id-stuurprogramma-updateen voer de hardware-id voor uw stuurprogramma in. Voor deze oefening is de hardware-id Root\KmdfHelloWorld. Selecteer OK-.

    Schermopname van het venster eigenschappenpagina's van kmdfhelloworld met de installatieoptie van het implementatiestuurprogramma geselecteerd.

    Notitie

    In deze oefening identificeert de hardware-id geen echt stukje hardware. Het identificeert een fictief apparaat dat een plaats krijgt in de apparaatboom als een kind van de root node. Selecteer voor echte hardware niet Stuurprogramma-update van hardware-id, maar kies Installeren en Verifiëren. U ziet de hardware-id in het INF-bestand (Informatie van het stuurprogramma). Ga in het venster Solution Explorer naar KmdfHelloWorld > Driver Filesen dubbelklik op KmdfHelloWorld.inf. De hardware-id bevindt zich onder [Standard.NT$ARCH$].

    [Standard.NT$ARCH$]
    %KmdfHelloWorld.DeviceDesc%=KmdfHelloWorld_Device, Root\KmdfHelloWorld
    
  8. Kies in het menu Build de optie Deploy Solution. Visual Studio kopieert automatisch de bestanden die nodig zijn om het stuurprogramma te installeren en uit te voeren naar de doelcomputer. De implementatie kan een paar minuten duren.

    Wanneer u een stuurprogramma implementeert, worden de stuurprogrammabestanden gekopieerd naar de map %Systemdrive%\drivertest\drivers op de testcomputer. Als er iets misgaat tijdens de implementatie, kunt u controleren of de bestanden naar de testcomputer worden gekopieerd. Controleer of de bestanden .inf, .cat, testcertificaat en .sys en eventuele andere benodigde bestanden aanwezig zijn in de map %systemdrive%\drivertest\drivers.

    Zie Een stuurprogramma implementeren op een testcomputervoor meer informatie over het implementeren van stuurprogramma's.

Het stuurprogramma installeren

Nu uw Hallo wereld-stuurprogramma is geïmplementeerd op de doelcomputer, installeert u het stuurprogramma. Wanneer u de doelcomputer eerder hebt ingericht met Visual Studio met behulp van de optie automatische, stelt Visual Studio de doelcomputer in om ondertekende stuurprogramma's uit te voeren als onderdeel van het inrichtingsproces. Nu hoeft u alleen het stuurprogramma te installeren met behulp van het DevCon-hulpprogramma.

  1. Navigeer op de hostcomputer naar de map Hulpprogramma's in uw WDK-installatie en zoek het DevCon-hulpprogramma. Kijk bijvoorbeeld in de volgende map:

    C:\Program Files (x86)\Windows Kits\10\Tools\x64\devcon.exe

    Kopieer het DevCon-hulpprogramma naar uw externe computer.

  2. Installeer het stuurprogramma op de doelcomputer door naar de map met de stuurprogrammabestanden te navigeren en vervolgens het DevCon-hulpprogramma uit te voeren.

    1. Hier volgt de algemene syntaxis voor het devcon-hulpprogramma dat u gebruikt om het stuurprogramma te installeren:

      devcon installeren <INF-bestand><hardware-id>

      Het INF-bestand dat is vereist voor het installeren van dit stuurprogramma is KmdfHelloWorld.inf. Het INF-bestand bevat de hardware-id voor het installeren van het binaire stuurprogramma, KmdfHelloWorld.sys. Zoals u weet, is de hardware-id, die zich in het INF-bestand bevindt, Root\KmdfHelloWorld.

    2. Open een opdrachtpromptvenster als beheerder. Navigeer naar de map met het ingebouwde stuurprogramma .sys bestand en voer deze opdracht in:

      devcon installeren kmdfhelloworld.inf root\kmdfhelloworld

      Als u een foutbericht krijgt waarin staat dat devcon niet wordt herkend, probeer dan het pad toe te voegen aan het devcon hulpprogramma. Als u deze bijvoorbeeld hebt gekopieerd naar een map op de doelcomputer met de naam C:\Tools, gebruikt u de volgende opdracht:

      c:\tools\devcon install kmdfhelloworld.inf root\kmdfhelloworld

      Er wordt een dialoogvenster weergegeven dat aangeeft dat het teststuurprogramma een niet-ondertekend stuurprogramma is. Selecteer Dit stuurprogramma toch installeren om door te gaan.

      Schermopname van de beveiligingswaarschuwing die wordt weergegeven tijdens het installatieproces van het stuurprogramma.

Fouten opsporen in het stuurprogramma

Nu u het KmdfHelloWorld-stuurprogramma op de doelcomputer hebt geïnstalleerd, koppelt u een foutopsporingsprogramma op afstand vanaf de hostcomputer.

  1. Open op de hostcomputer een opdrachtpromptvenster als administrator. Ga naar de directory WinDbg.exe. We gebruiken de x64version van WinDbg.exe van de Windows Driver Kit (WDK) die is geïnstalleerd als onderdeel van de windows-kitinstallatie. Dit is het standaardpad naar WinDbg.exe:

    C:\Program Files (x86)\Windows Kits\10\Debuggers\x64

  2. Start WinDbg om verbinding te maken met een kernelfoutopsporingssessie op de doelcomputer met behulp van de volgende opdracht. De waarde voor de poort en sleutel moet gelijk zijn aan de waarde die u hebt gebruikt om de doelcomputer in te richten. We gebruiken 50000 voor de poort en 1.2.3.4 voor de sleutel, de waarden die we tijdens de implementatiestap hebben gebruikt. De vlag k geeft aan dat dit een kernelfoutopsporingssessie is.

    WinDbg -k net:port=50000,key=1.2.3.4

  3. Kies in het menu FoutopsporingOnderbreking. Het foutopsporingsprogramma op de hostcomputer breekt in op de doelcomputer. In het venster Opdracht voor foutopsporingsprogramma ziet u de opdrachtprompt voor kernelfoutopsporing: kd>.

  4. Op dit moment kunt u experimenteren met het foutopsporingsprogramma door opdrachten in te voeren bij de kd> prompt. U kunt bijvoorbeeld de volgende opdrachten proberen:

  5. Als u de doelcomputer opnieuw wilt laten draaien, kiest u Go in het menu Foutopsporing of drukt u op 'g' en vervolgens op ' Enter '.

  6. Als u de foutopsporingssessie wilt stoppen, kiest u Foutopsporingsprogramma loskoppelen in het menu Foutopsporing.

    Belangrijk

    Zorg ervoor dat u de opdracht 'go' gebruikt om de doelcomputer opnieuw uit te voeren voordat u het foutopsporingsprogramma afsluit. De doelcomputer reageert niet op uw muis- en toetsenbordinvoer omdat deze nog steeds met het foutopsporingsprogramma praat.

Zie Debug Universal Drivers - Step by Step Lab (Echo Kernel-Mode)voor een gedetailleerd stapsgewijze procedure voor het foutopsporingsproces van stuurprogramma's.

Zie Remote Debugging using WinDbg(WinDbg-) voor meer informatie over foutopsporing op afstand.

Hulpprogramma's voor foutopsporing voor Windows

Foutopsporing van algemene stuurprogramma's - Stapsgewijze lab (echo Kernel-Mode)

Schrijf je eerste stuurprogramma