Freigeben über


Schreiben von Treibern für verschiedene Versionen von Windows

Wenn Sie ein Treiberprojekt erstellen, geben Sie das Mindestzielbetriebssystem an. Dabei handelt es sich um die Mindestversion von Windows, auf der Ihr Treiber ausgeführt wird. Sie können beispielsweise angeben, dass Windows 7 das Mindestzielbetriebssystem ist. In diesem Fall würde Ihr Treiber unter Windows 7 und höheren Versionen von Windows ausgeführt.

Hinweis

Wenn Sie einen Treiber für eine bestimmte Mindestversion von Windows entwickeln und möchten, dass Ihr Treiber in späteren Versionen von Windows funktioniert, dürfen Sie keine nicht dokumentierten Funktionen verwenden, und Sie dürfen keine dokumentierten Funktionen auf andere Weise als die beschreibung in der Dokumentation verwenden. Andernfalls kann der Treiber auf den späteren Versionen von Windows nicht ausgeführt werden. Auch wenn Sie sorgfältig darauf achten, nur dokumentierte Funktionen zu verwenden, sollten Sie ihren Treiber bei jeder Veröffentlichung auf der neuen Version von Windows testen.

Schreiben eines Mehrversionstreibers mit nur allgemeinen Features

Wenn Sie einen Treiber entwerfen, der auf mehreren Versionen von Windows ausgeführt wird, besteht der einfachste Ansatz darin, dem Treiber nur DDI-Funktionen und -Strukturen zu ermöglichen, die für alle Versionen von Windows gemeinsam sind, auf denen der Treiber ausgeführt wird. In diesem Fall legen Sie das Mindestzielbetriebssystem auf die früheste Windows-Version fest, die der Treiber unterstützt.

Um beispielsweise alle Versionen von Windows zu unterstützen, sollten Sie ab Windows 7:

  1. Entwerfen und implementieren Sie den Treiber so, dass er nur die Features verwendet, die in Windows 7 vorhanden sind.

  2. Wenn Sie Ihren Treiber erstellen, geben Sie Windows 7 als Mindestzielbetriebssystem an.

Während dieser Vorgang einfach ist, kann es den Treiber einschränken, nur eine Teilmenge der Funktionen zu verwenden, die in späteren Versionen von Windows verfügbar sind. In vielen Fällen sollten Sie neuere Betriebssystemfunktionen nutzen, wenn sie verfügbar sind, um die Sicherheit zu verbessern, die Zuverlässigkeit zu verbessern oder neuere Features zu aktivieren.

Schreiben eines Mehrversionstreibers, der versionsabhängige Features verwendet

Ein Kernelmodustreiber kann dynamisch ermitteln, ob eine bereitgestellte API des Betriebssystems verfügbar ist oder auf welcher Version von Windows der Treiber ausgeführt wird, und wählen Sie die Verwendung von Features aus, die in dieser Laufzeitumgebung verfügbar sind. Beispielsweise kann ein Treiber, der alle Versionen von Windows unterstützt, beginnend mit Windows 7, zur Laufzeit die Version von Windows ermitteln, auf der sie ausgeführt wird. Wenn der Treiber unter Windows 7 ausgeführt wird, darf er nur die von Windows 7 unterstützten DDI-Funktionen verwenden. Derselbe Treiber kann jedoch zusätzliche DDI-Funktionen verwenden, die für Windows 8 eindeutig sind, z. B. wenn die Laufzeitüberprüfung bestimmt, dass diese APIs derzeit vorhanden sind oder bestimmt, dass sie unter Windows 8 ausgeführt wird.

Hinweis

Es wird empfohlen, nach Der Verfügbarkeit von Features oder APIs zu suchen, anstatt zu versuchen, zu überprüfen, ob Ihr Treiber auf einer bestimmten Betriebssystemversion oder höher ausgeführt wird.

Bedingtes Aufrufen von versionsabhängigen Windows-Funktionen

Ein Kernelmodustreiber kann die Funktionen MmGetSystemRoutineAddress oder MmGetSystemRoutineAddressEx verwenden, um dynamisch zu überprüfen, ob eine bestimmte API, die sie verwenden möchte, in der aktuellen Laufzeitumgebung verfügbar ist, und einen Funktionszeiger abzurufen, der verwendet werden soll, um diese API aufzurufen.

Hinweis

Um die Typüberprüfung beizubehalten und unbeabsichtigte Fehler zu verhindern, sollten Sie einen Typedef erstellen, der den ursprünglichen Funktionstyp Spiegel.

Beispiel: Ermitteln der API-Verfügbarkeit und bedingten Aufrufen der 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
}

Ermitteln der Windows-Version

Ein Kernelmodustreiber kann die RtlVerifyVersionInfo-Funktion verwenden, um dynamisch zu überprüfen, auf welcher Version von Windows es derzeit ausgeführt wird.

Hinweis

Es wird empfohlen, nach Der Verfügbarkeit von Features oder APIs zu suchen, anstatt zu versuchen, zu überprüfen, ob Ihr Treiber auf einer bestimmten Betriebssystemversion oder höher ausgeführt wird.

Beispiel: Ermitteln der Windows-Version

Im folgenden Beispiel wird erkannt, ob die derzeit ausgeführte Betriebssystemversion größer oder gleich Version 10.0 ist und erkennt, ob die Buildnummer größer oder gleich Build 22000 (Windows 11, Version 21H2) ist.

...

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.
    //

}
...