Sdílet prostřednictvím


Kurz: Napsání ovladače Hello World pro Windows (Kernel-Mode Driver Framework)

Tento článek popisuje, jak napsat malý univerzální ovladač windows pomocí rozhraní Kernel-Mode Driver Framework (KMDF) a potom nasadit a nainstalovat ovladač do samostatného počítače.

Požadavky

  • Postupujte podle kroků k instalaci Windows Driver Kit (WDK). Nástroje pro ladění Windows jsou součástí instalace sady WDK.

  • Nainstalujte visual Studio 2022. Při instalaci sady Visual Studio 2022 vyberte pracovní zátěž vývoj desktopových aplikací pomocí C++, a pak pod jednotlivé komponenty přidejte:

    • MSVC v143 – VS 2022 C++ ARM64/ARM64EC knihovny se zmírněním Spectre (nejnovější)
    • MSVC v143 – VS 2022 C++ x64/x86 knihovny se zmírněním Spectre (nejnovější)
    • C++ ATL pro nejnovější nástroje sestavení v143 se zmírněním Spectre (ARM64/ARM64EC)
    • C++ ATL pro nejnovější nástroje sestavení v143 se zmírněním zranitelností Spectre (x86 & x64)
    • C++ MFC pro nejnovější nástroje sestavení v143 s mitigacemi Spectre (ARM64/ARM64EC)
    • C++ MFC pro nejnovější nástroje pro sestavení v143 s mitigací Spectre (x86 & x64)
    • Windows Driver Kit

Vytvoření a sestavení ovladače

  1. Otevřete Microsoft Visual Studio. V nabídce Soubor zvolte Nový > Projekt.

  2. V dialogovém okně Vytvořit nový projekt vyberte C++ v levém rozevíracím seznamu, v prostředním rozevíracím seznamu zvolte Windows a v pravém rozevíracím seznamu zvolte Ovladač.

  3. V seznamu typů projektů vyberte ovladač režimu jádra, prázdný (KMDF). Vyberte Další.

    Snímek obrazovky s dialogovým oknem Nový projekt sady Visual Studio s vybranou možností ovladače režimu jádra

    Spropitné

    Pokud v sadě Visual Studio nemůžete najít šablony projektů ovladačů, rozšíření WDK Visual Studio se nenainstalovalo správně. Chcete-li tento problém vyřešit, spusťte Instalační program sady Visual Studio, vyberte Upravit, přidejte Windows Driver Kit na kartě jednotlivé součásti a vyberte Upravit.

  4. V dialogovém okně Konfigurovat nový projekt zadejte do pole Název projektu "KmdfHelloWorld".

    Poznámka

    Při vytváření nového ovladače KMDF nebo UMDF musíte vybrat název ovladače, který má 32 znaků nebo méně. Tento limit délky je definován v wdfglobals.h.

  5. Do pole Umístění zadejte adresář, do kterého chcete nový projekt vytvořit.

  6. Zaškrtněte Umístit řešení a projekt do stejného adresáře a vyberte Vytvořit.

    Snímek obrazovky s dialogovým oknem Konfigurace nového projektu v sadě Visual Studio se zvýrazněným tlačítkem Vytvořit

    Visual Studio vytvoří jeden projekt a řešení. Můžete je zobrazit v Průzkumníku řešení okně. (Pokud okno Průzkumníka řešení není viditelné, v nabídce Zobrazení zvolte Průzkumníka řešení.) Řešení obsahuje projekt ovladače s názvem KmdfHelloWorld.

    Snímek obrazovky s oknem Průzkumníka řešení sady Visual Studio zobrazující řešení a prázdný projekt ovladače s názvem KmdfHelloWorld

  7. V okně Průzkumníka řešení klikněte pravým tlačítkem myši na Řešení 'KmdfHelloWorld' (1 z 1 projektu) a zvolte Správce konfigurace. Zvolte konfiguraci a platformu pro projekt řidiče. Například zvolte Debug a x64.

  8. V okně Průzkumník řešení klikněte pravým tlačítkem myši na projekt KmdfHelloWorld, zvolte Přidata poté vyberte Nová položka.

  9. V dialogovém okně Přidat novou položku zadejte Driver.c.

    Poznámka

    Přípona názvu souboru je .c, nikoli .cpp.

    Vyberte Přidat. Soubor Driver.c se přidá do zdrojových souborů, jak je znázorněno zde.

    Snímek obrazovky s oknem Průzkumníka řešení sady Visual Studio zobrazující soubor driver.c přidaný do projektu ovladače

Napsání prvního kódu ovladače

Teď, když jste vytvořili prázdný projekt Hello World a přidali zdrojový soubor Driver.c, napíšete nejzákladnější kód potřebný ke spuštění ovladače implementací dvou základních funkcí zpětného volání událostí.

  1. V Driver.c začněte zahrnutím těchto hlaviček:

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

    Spropitné

    Pokud nemůžete přidat Ntddk.h, otevřete Konfigurace –> C/C++ –> Obecné –> Další adresáře Include a přidejte C:\Program Files (x86)\Windows Kits\10\Include\<build#>\km, přičemž nahraďte <build#> příslušným adresářem v instalaci WDK.

    Ntddk.h obsahuje základní definice jádra Systému Windows pro všechny ovladače, zatímco Wdf.h obsahuje definice pro ovladače založené na rozhraní WDF (Windows Driver Framework).

  2. Dále zadejte deklarace dvou zpětných volání:

    DRIVER_INITIALIZE DriverEntry;
    EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
    
  3. Ke psaní svého DriverEntrypoužijte následující kód:

    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 je vstupním bodem pro všechny ovladače, například Main() je pro mnoho aplikací uživatelského režimu. Úkolem DriverEntry je inicializovat struktury a prostředky pro ovladač jako celek. V tomto příkladu jste vytiskli "Hello World" pro DriverEntry, nakonfigurovali objekt ovladače pro registraci vstupního bodu vaší zpětné funkce EvtDeviceAdd, poté jste vytvořili objekt ovladače a vrátili se.

    Objekt ovladače funguje jako nadřazený objekt pro všechny ostatní objekty architektury, které můžete vytvořit v ovladači, včetně objektů zařízení, vstupně-výstupních front, časovačů, spinlocků a dalších. Další informace o frameworkových objektech naleznete v tématu Úvod do frameworkových objektů.

    Spropitné

    Pro DriverEntrydůrazně doporučujeme zachovat název jako DriverEntry, který vám pomůže s analýzou a laděním kódu.

  4. Dále pomocí následujícího kódu napište KmdfHelloWorldEvtDeviceAdd:

    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 je vyvolán systémem, když zjistí, že vaše zařízení dorazilo. Jejím úkolem je inicializovat struktury a prostředky pro toto zařízení. V tomto příkladu jste vytiskli zprávu "Hello World" pro EvtDeviceAdd, vytvořili objekt zařízení a vrátili se. V jiných ovladačích, které píšete, můžete vytvořit fronty vstupně-výstupních operací pro hardware, nastavit kontext zařízení prostor úložiště pro informace specifické pro zařízení nebo provádět jiné úlohy potřebné k přípravě zařízení.

    Spropitné

    V případě zpětného volání pro přidání zařízení si všimněte, že jste použili název svého ovladače jako předponu názvu (KmdfHelloWorldEvtDeviceAdd). Obecně doporučujeme pojmet funkce ovladače tímto způsobem, abyste je odlišili od funkcí ostatních ovladačů. DriverEntry je jediný, který byste měli pojmenovat přesně tak.

  5. Váš úplný Driver.c teď vypadá takto:

    #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. Uložit Driver.c.

Tento příklad ukazuje základní koncept ovladačů: představují "kolekci zpětných volání", která po inicializaci sedí a čeká na to, až je systém zavolá, když něco potřebuje. Systémovým voláním může být událost příjezdu nového zařízení, vstupně-výstupní požadavek z aplikace v uživatelském režimu, událost vypnutí napájení systému, žádost od jiného ovladače nebo neočekávané odebrání, když uživatel zařízení neočekávaně odpojí. Naštěstí, abyste řekli "Hello World", museli jste se starat pouze o ovladač a vytváření zařízení.

Dále sestavíte ovladač.

Postavte ovladač

  1. V okně Průzkumníka řešení klikněte pravým tlačítkem myši na řešení 'KmdfHelloWorld' (1 z 1 projektu) a zvolte Configuration Manager. Zvolte konfiguraci a platformu pro projekt řidiče. Pro toto cvičení zvolte Ladění a x64.

  2. V okně Průzkumník řešení klikněte pravým tlačítkem na KmdfHelloWorld a zvolte Vlastnosti. Ve Wpp trasování > všechny možnosti, nastavte Spuštění Wpp trasování na hodnotu Žádné. Vyberte Použít a poté OK.

  3. Pokud chcete vytvořit ovladač, v nabídce Sestavení zvolte Řešení sestavení. Visual Studio zobrazuje průběh sestavení v okně Výstup. (Pokud okno Výstup není viditelné, vyberte z nabídky Zobrazení položku Výstup.) Jakmile ověříte, že řešení bylo úspěšně sestaveno, můžete Visual Studio zavřít.

  4. Pokud chcete zobrazit integrovaný ovladač, přejděte v Průzkumníkovi souborů do složky KmdfHelloWorld a pak přejděte na x64\Debug\KmdfHelloWorld. Složka obsahuje:

    • KmdfHelloWorld.sys – soubor ovladače režimu jádra
    • KmdfHelloWorld.inf – informační soubor, který systém Windows používá při instalaci ovladače
    • KmdfHelloWorld.cat – soubor katalogu, který instalační program používá k ověření testovacího podpisu ovladače

Spropitné

Pokud se při sestavování ovladače zobrazí DriverVer set to a date in the future, změňte nastavení projektu ovladače tak, aby inf2Cat nastavil /uselocaltime. Uděláte to tak, že použijete vlastnosti konfigurace –>Inf2Cat –>Obecné –>Použít místní čas. Teď Stampinf i Inf2Cat používají místní čas.

Nasazení ovladače

Obvykle při testování a ladění ovladače, ladicí program a ovladač běží na samostatných počítačích. Počítač, na kterém běží ladicí program, se nazývá hostitelský počítača počítač, na kterém běží ovladač, se nazývá cílový počítač. Cílový počítač se také nazývá testovací počítač.

Zatím jste pomocí sady Visual Studio vytvořili ovladač na hostitelském počítači. Teď potřebujete nakonfigurovat cílový počítač.

  1. Postupujte podle pokynů v Zřízení počítače pro nasazení a testování ovladačů (WDK 10).

    Spropitné

    Když použijete postup automatického zřízení cílového počítače pomocí síťového kabelu, poznamenejte si port a klíč. Použijete je později v kroku ladění. V tomto příkladu použijete jako port 50000 a jako klíč 1.2.3.4.

    Ve scénářích ladění skutečných ovladačů doporučujeme použít klíč vygenerovaný KDNET. Další informace o tom, jak použít KDNET k vygenerování náhodného klíče, najdete v tématu Debug Drivers – Step by Step Lab (Režim jádra Sysvad).

  2. Na hostitelském počítači otevřete řešení v sadě Visual Studio. Ve složce KmdfHelloWorld můžete dvakrát kliknout na soubor řešení KmdfHelloWorld.sln.

  3. V okně Průzkumníka řešení klikněte pravým tlačítkem na projekt KmdfHelloWorld a zvolte Vlastnosti.

  4. Přejděte na Instalace ovladače > Nasazení.

  5. U položky název cílového zařízení vyberte název počítače, který jste nakonfigurovali pro testování a ladění. V tomto cvičení používáme počítač s názvem MyTestComputer.

  6. Pokud chcete zajistit, že testujete nejnovější verzi ovladače, zkontrolujte Odebrat předchozí verze ovladačů před nasazením.

  7. Vyberte aktualizace ovladače ID hardwarua zadejte ID hardwaru pro ovladač. V tomto cvičení je ID hardwaru Root\KmdfHelloWorld. Vyberte OK.

    Poznámka

    V tomto cvičení ID hardwaru neidentifikuje skutečnou část hardwaru. Identifikuje imaginární zařízení, kterému je přiděleno místo ve stromu zařízení jako podřízený uzel kořenového uzlu. Pro skutečný hardware nevybírejte aktualizace ovladače ID hardwaru; místo toho vyberte Nainstalovat a ověřit. V souboru s informacemi o ovladači (INF) se zobrazí ID hardwaru. V Průzkumníku řešení okno přejděte na KmdfHelloWorld > Soubory ovladačůa poklikejte na KmdfHelloWorld.inf. ID hardwaru se nachází ve složce [Standard.NT$ARCH$].

    [Standard.NT$ARCH$]
    %KmdfHelloWorld.DeviceDesc%=KmdfHelloWorld_Device, Root\KmdfHelloWorld
    
  8. V nabídce Sestavení zvolte Nasadit řešení. Visual Studio automaticky zkopíruje soubory potřebné k instalaci a spuštění ovladače do cílového počítače. Nasazení může trvat minutu nebo dvě.

    Při nasazení ovladače se soubory ovladačů zkopírují do složky %Systemdrive%\drivertest\drivers na testovacím počítači. Pokud se během nasazování něco nepovede, můžete zkontrolovat, jestli se soubory zkopírují do testovacího počítače. Ověřte, zda jsou soubory .inf, .cat, test cert a .sys a všechny další potřebné soubory přítomny ve složce %systemdrive%\drivertest\drivers.

    Další informace o nasazení ovladačů naleznete v tématu Nasazení ovladače do testovacího počítače.

Instalace ovladače

S ovladačem Hello World nasazeným do cílového počítače teď ovladač nainstalujete. Když jste dříve zřídili cílový počítač se sadou Visual Studio pomocí možnosti automatického, sada Visual Studio nastavila cílový počítač tak, aby v rámci procesu zřizování spouštěl testovací podepsané ovladače. Teď stačí nainstalovat ovladač pomocí nástroje DevCon.

  1. Na hostitelském počítači přejděte do složky Nástroje v instalaci WDK a vyhledejte nástroj DevCon. Podívejte se například do následující složky:

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

    Zkopírujte nástroj DevCon do vzdáleného počítače.

  2. Na cílovém počítači nainstalujte ovladač tak, že přejdete do složky obsahující soubory ovladačů a potom spustíte nástroj DevCon.

    1. Tady je obecná syntaxe nástroje devcon, který použijete k instalaci ovladače:

      devcon instalace <souboru INF><ID hardwaru>

      Soubor INF vyžadovaný pro instalaci tohoto ovladače je KmdfHelloWorld.inf. Soubor INF obsahuje ID hardwaru pro instalaci binárního souboru ovladače KmdfHelloWorld.sys. Vzpomeňte si, že ID hardwaru umístěné v souboru INF je Root\KmdfHelloWorld.

    2. Otevřete okno příkazového řádku jako správce. Přejděte do složky obsahující sestavený soubor ovladače .sys a zadejte tento příkaz:

      devcon install kmdfhelloworld.inf root\kmdfhelloworld

      Pokud se zobrazí chybová zpráva o tom, není rozpoznán, zkuste přidat cestu k nástroji devcon. Pokud jste ji například zkopírovali do složky v cílovém počítači s názvem C:\Tools, zkuste použít následující příkaz:

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

      Zobrazí se dialogové okno označující, že testovací ovladač je nepodepsaný ovladač. Chcete-li pokračovat, vyberte Nainstalovat tento ovladač.

      Snímek obrazovky s upozorněním zabezpečení zobrazeným během procesu instalace ovladače

Ladění ovladače

Teď, když jste nainstalovali ovladač KmdfHelloWorld na cílový počítač, připojíte ladicí program vzdáleně z hostitelského počítače.

  1. Na hostitelském počítači otevřete okno příkazového řádku jako správce. Přejděte do adresáře WinDbg.exe. Použijete x64version WinDbg.exe ze sady Windows Driver Kit (WDK), která byla nainstalována jako součást instalace sady Windows Kit. Tady je výchozí cesta k WinDbg.exe:

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

  2. Spusťte WinDbg a připojte se na ladicí relaci jádra na cílovém počítači pomocí následujícího příkazu. Hodnota portu a klíče by měla být stejná jako hodnota, kterou jste použili ke zřízení cílového počítače. Pro port použijete 50000 a 1.2.3.4 pro klíč, hodnoty, které jste použili v kroku nasazení. Příznak k označuje, že se jedná o ladicí relaci jádra.

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

  3. V nabídce Ladění zvolte Break. Ladicí program na hostitelském počítači přerušuje cílový počítač. V okně Příkaz ladicího programu můžete zobrazit příkazový řádek ladění jádra: kd>.

  4. V tomto okamžiku můžete experimentovat s ladicím programem zadáním příkazů na kd> příkazovém řádku. Můžete například vyzkoušet tyto příkazy:

  5. Pokud chcete cílový počítač spustit znovu, zvolte Přejít v nabídce Ladění nebo stiskněte "g", poté stiskněte klávesu Enter.

  6. Chcete-li zastavit ladicí relaci, v nabídce Ladění zvolte Odpojit ladicí program.

    Důležitý

    Před ukončením ladicího programu se ujistěte, že pomocí příkazu "go" necháte cílový počítač běžet znovu, nebo cílový počítač přestane reagovat na vstup myši a klávesnice, protože stále mluví s ladicím programem.

Podrobný návod k procesu ladění ovladačů najdete v tématu Ladění univerzálních ovladačů – podrobné cvičení (Echo Kernel-Mode).

Další informace o vzdáleném ladění naleznete v tématu vzdálené ladění pomocí WinDbg.

nástroje pro ladění pro Windows

ladění univerzálních ovladačů – podrobné cvičení (echo Kernel-Mode)

Napište svůj první ovladač