Dela via


Skriva drivrutiner för olika versioner av Windows

När du skapar ett drivrutinsprojekt anger du det lägsta måloperativsystemet, vilket är den lägsta versionen av Windows som drivrutinen ska köras på. Du kan till exempel ange att Windows 7 är det lägsta måloperativsystemet. I så fall skulle drivrutinen köras på Windows 7 och senare versioner av Windows.

Not

Om du utvecklar en drivrutin för en viss lägsta version av Windows och du vill att drivrutinen ska fungera i senare versioner av Windows, får du inte använda några odokumenterade funktioner och du får inte använda dokumenterade funktioner på något annat sätt än hur det beskrivs i dokumentationen. Annars kan drivrutinen misslyckas med att köras i senare versioner av Windows. Även om du har varit noga med att endast använda dokumenterade funktioner bör du testa drivrutinen på den nya versionen av Windows varje gång en släpps.

Skriva en drivrutin med flera versioner med bara vanliga funktioner

När du utformar en drivrutin som ska köras på flera versioner av Windows är den enklaste metoden att låta drivrutinen endast använda DDI-funktioner och strukturer som är gemensamma för alla versioner av Windows som drivrutinen ska köras på. I den här situationen anger du det lägsta måloperativsystemet till den tidigaste versionen av Windows som drivrutinen stöder.

Om du till exempel vill ha stöd för alla versioner av Windows, från och med Windows 7, bör du:

  1. Utforma och implementera drivrutinen så att den endast använder de funktioner som finns i Windows 7.

  2. När du skapar drivrutinen anger du Windows 7 som det lägsta måloperativsystemet.

Även om den här processen är enkel kan den begränsa drivrutinen till att endast använda en delmängd av de funktioner som är tillgängliga i senare versioner av Windows. I många fall vill du använda nyare operativsystemfunktioner när det är tillgängligt för att förbättra säkerheten, förbättra tillförlitligheten eller aktivera nyare funktioner.

Skriva en drivrutin med flera versioner som använder versionsberoende funktioner

En kernel-mode-drivrutin kan dynamiskt avgöra om ett operativsystem som tillhandahålls API är tillgängligt eller vilken version av Windows drivrutinen körs på och välja att använda funktioner som är tillgängliga i körningsmiljön. Till exempel kan en drivrutin som måste ha stöd för alla versioner av Windows, från och med Windows 7, vid körning avgöra vilken version av Windows som den körs på. Om drivrutinen körs på Windows 7 får den endast använda de DDI-funktioner som Stöds av Windows 7. Samma drivrutin kan dock använda ytterligare DDI-funktioner som är unika för Windows 8, till exempel när körningskontrollen avgör att dessa API:er för närvarande finns eller avgör att de körs på Windows 8.

Obs

Vi rekommenderar att du söker efter funktions- eller API-tillgänglighet när det är möjligt i stället för att försöka kontrollera om drivrutinen körs på en viss operativsystemversion eller senare.

Villkorligt anropande av windows-versionsberoende funktioner

En drivrutin i kernelläge kan använda MmGetSystemRoutineAddress eller MmGetSystemRoutineAddressEx-funktioner för att dynamiskt kontrollera om ett visst API som det vill använda är tillgängligt i den aktuella körningsmiljön och för att få en funktionspekare att använda för att anropa api:et.

Anmärkning

För att bevara typkontroll och förhindra oavsiktliga fel bör du skapa en typedef som speglar den ursprungliga funktionstypen.

Exempel: Fastställa API-tillgänglighet och villkorligt anropa 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
}

Fastställa Windows-versionen

En drivrutin i kernelläge kan använda funktionen RtlVerifyVersionInfo för att dynamiskt kontrollera vilken version av Windows den körs på.

Not

Vi rekommenderar att du söker efter funktions- eller API-tillgänglighet när det är möjligt i stället för att försöka kontrollera om drivrutinen körs på en viss operativsystemversion eller senare.

Exempel: Fastställa Windows-versionen

I följande exempel identifieras om den operativsystemversion som körs för närvarande är större än eller lika med version 10.0 och identifierar om versionsnumret är större än eller lika med version 22000 (Windows 11, version 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.
    //

}
...