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
Otevřete Microsoft Visual Studio. V nabídce Soubor zvolte Nový > Projekt.
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č.
V seznamu typů projektů vyberte ovladač režimu jádra, prázdný (KMDF). Vyberte Další.
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.
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.
Do pole Umístění zadejte adresář, do kterého chcete nový projekt vytvořit.
Zaškrtněte Umístit řešení a projekt do stejného adresáře a vyberte 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.
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.
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.
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.
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í.
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řidejteC:\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).
Dále zadejte deklarace dvou zpětných volání:
DRIVER_INITIALIZE DriverEntry; EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;
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.
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.
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; }
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č
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.
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.
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.
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č.
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).
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.
V okně Průzkumníka řešení klikněte pravým tlačítkem na projekt KmdfHelloWorld a zvolte Vlastnosti.
Přejděte na Instalace ovladače > Nasazení.
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.
Pokud chcete zajistit, že testujete nejnovější verzi ovladače, zkontrolujte Odebrat předchozí verze ovladačů před nasazením.
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
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.
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.
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.
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.
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č.
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.
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
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
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>.
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:
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.
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.
Související články
nástroje pro ladění pro Windows
ladění univerzálních ovladačů – podrobné cvičení (echo Kernel-Mode)