Sdílet prostřednictvím


Psaní ovladačů pro různé verze Windows

Při vytváření projektu ovladače zadáte minimální cílový operační systém, což je minimální verze Systému Windows, na které bude ovladač běžet. Můžete například určit, že Windows 7 je minimální cílový operační systém. V takovém případě by ovladač běžel ve Windows 7 a novějších verzích Windows.

Poznámka

Pokud vyvíjíte ovladač pro určitou minimální verzi Windows a chcete, aby ovladač fungoval v novějších verzích Windows, nesmíte používat žádné nezdokumentované funkce a nesmíte používat zdokumentované funkce žádným jiným způsobem, než jak je popsáno v dokumentaci. Jinak se ovladač nemusí podařit spustit v novějších verzích Windows. I když jste byli opatrní používat jenom zdokumentované funkce, měli byste otestovat ovladač na nové verzi Windows při každém vydání.

Zápis ovladače s více verzemi pomocí pouze běžných funkcí

Při návrhu ovladače, který se bude spouštět ve více verzích Systému Windows, je nejjednodušším přístupem umožnit ovladači používat pouze funkce a struktury DDI, které jsou společné pro všechny verze Systému Windows, na kterých bude ovladač spuštěn. V této situaci nastavíte minimální cílový operační systém na nejstarší verzi Systému Windows, kterou bude ovladač podporovat.

Pokud například chcete podporovat všechny verze Windows počínaje Windows 7, měli byste:

  1. Navrhujte a implementujte ovladač tak, aby používal pouze ty funkce, které jsou přítomné ve Windows 7.

  2. Při sestavování ovladače zadejte systém Windows 7 jako minimální cílový operační systém.

I když je tento proces jednoduchý, může ovladač omezit na použití pouze podmnožinu funkcí, které jsou k dispozici v novějších verzích Windows. V mnoha případech budete chtít využívat novější funkce operačního systému, pokud je k dispozici, abyste zlepšili zabezpečení, zlepšili spolehlivost nebo povolili novější funkce.

Zápis ovladače pro více verzí, který používá funkce závislé na verzích

Ovladač v režimu jádra může dynamicky určit, jestli je k dispozici rozhraní API poskytované operačním systémem nebo na které verzi Systému Windows ovladač běží, a zvolit použití funkcí dostupných v daném prostředí za běhu. Například ovladač, který musí podporovat všechny verze Windows počínaje Systémem Windows 7, může určit verzi systému Windows, na které běží za běhu. Pokud ovladač běží ve Windows 7, musí používat pouze funkce DDI, které Systém Windows 7 podporuje. Stejný ovladač však může používat další funkce DDI, které jsou jedinečné pro Systém Windows 8, například když kontrola za běhu zjistí, že tato rozhraní API jsou aktuálně k dispozici, nebo určuje, že je spuštěna ve Windows 8.

Poznámka

Doporučujeme zkontrolovat dostupnost funkcí nebo rozhraní API, kdykoli je to možné, místo abyste se pokusili zkontrolovat, jestli je ovladač spuštěný v určité verzi operačního systému nebo novější.

Podmíněné volání funkcí závislých na verzích Windows

Ovladač v režimu jádra může použít MmGetSystemRoutineAddress nebo MmGetSystemRoutineAddressEx funkce k dynamické kontrole, jestli je určité rozhraní API, které chce použít, k dispozici v aktuálním prostředí doby běhu a získat ukazatel funkce, který se má použít k volání tohoto rozhraní API.

Poznámka

Chcete-li zachovat kontrolu typů a zabránit neúmyslným chybám, měli byste vytvořit typedef, který zrcadlí původní typ funkce.

Příklad: Určení dostupnosti rozhraní API a podmíněného volání rozhraní API

typedef
NTSTATUS
(*PFN_IoOpenDriverRegistryKey)(
    PDRIVER_OBJECT     DriverObject,
    DRIVER_REGKEY_TYPE RegKeyType,
    ACCESS_MASK        DesiredAccess,
    ULONG              Flags,
    PHANDLE            DriverRegKey
    );

VOID ExampleFunction(VOID) {
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    HANDLE persistentStateKey = NULL;
    PFN_IoOpenDriverRegistryKey pfnIoOpenDriverRegistryKey = NULL;
    UNICODE_STRING functionName = {0};

    RtlInitUnicodeString(&functionName, L"IoOpenDriverRegistryKey");
    pfnIoOpenDriverRegistryKey = (PFN_IoOpenDriverRegistryKey)MmGetSystemRoutineAddress(&functionName);

    if (pfnIoOpenDriverRegistryKey != NULL) {
        // Open a key to where state can be stored under the driver service
        status = pfnIoOpenDriverRegistryKey(g_GlobalStructure.DriverObject,
                                            DriverRegKeyPersistentState,
                                            KEY_WRITE,
                                            0,
                                            &persistentStateKey);
    } else {
        // Fall back to opening up a different location to store state in
    }

    // Use the opened registry key
}

Určení verze Windows

Ovladač v režimu jádra může použít funkci RtlVerifyVersionInfo k dynamické kontrole, ve které verzi Windows je aktuálně spuštěná.

Poznámka

Doporučujeme zkontrolovat dostupnost funkcí nebo rozhraní API, kdykoli je to možné, místo abyste se pokusili zkontrolovat, jestli je ovladač spuštěný v určité verzi operačního systému nebo novější.

Příklad: Určení verze Systému Windows

Následující příklad zjistí, jestli je aktuálně spuštěná verze operačního systému větší nebo rovna verzi 10.0 a zjistí, jestli je číslo buildu větší nebo rovno buildu 22000 (Windows 11 verze 21H2).

...

NTSTATUS Status = STATUS_SUCCESS;
RTL_OSVERSIONINFOEXW VersionInfo = {0};
ULONG TypeMask = 0;
ULONGLONG ConditionMask = 0;

VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
VersionInfo.dwMajorVersion = 10;
VersionInfo.dwMinorVersion = 0;
VersionInfo.dwBuildNumber = 22000;

TypeMask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
VER_SET_CONDITION(ConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(ConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(ConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);

Status = RtlVerifyVersionInfo(&VersionInfo,
                              TypeMask,
                              ConditionMask);

if (NT_SUCCESS(Status)) {

    //
    // The call to RtlVerifyVersionInfo succeeded, so the running OS
    // version and build number is greater than or equal to the value
    // specified. Do appropriate action for newer OS versions.
    //

} else if (Status == STATUS_REVISION_MISMATCH) {

    //
    // The running OS version is less than the value specified. Do
    // appropriate action for older OS versions.
    //

} else {

    //
    // There was an error comparing to the running OS version. Do
    // appropriate action for when the OS version is not known.
    //

}
...