Написание драйверов для различных версий Windows

При создании проекта драйвера необходимо указать минимальную целевую операционную систему, которая является минимальной версией Windows, в которой будет работать драйвер. Например, можно указать, что Windows 7 является минимальной целевой операционной системой. В этом случае драйвер будет работать в Windows 7 и более поздних версиях Windows.

Примечание.

Если вы разрабатываете драйвер для определенной минимальной версии Windows и хотите, чтобы драйвер работал в более поздних версиях Windows, вы не должны использовать какие-либо незадокументированные функции, и вы не должны использовать документированные функции каким-либо образом, кроме того, как он описан в документации. В противном случае драйвер может не запуститься в более поздних версиях Windows. Даже если вы тщательно использовали только документированные функции, следует протестировать драйвер в новой версии Windows каждый раз при каждом выпуске.

Написание драйвера с несколькими версиями с использованием только общих функций

При разработке драйвера, который будет работать в нескольких версиях Windows, самый простой подход заключается в том, чтобы драйвер мог использовать только функции и структуры DDI, которые являются общими для всех версий Windows, на которых будет работать драйвер. В этой ситуации для минимальной целевой операционной системы устанавливается самая ранняя версия Windows, которую будет поддерживать драйвер.

Например, для поддержки всех версий Windows, начиная с Windows 7, необходимо:

  1. Проектируйте и реализуйте драйвер таким образом, чтобы он использовал только те функции, которые присутствуют в Windows 7.

  2. При сборке драйвера укажите Windows 7 в качестве минимальной целевой операционной системы.

Хотя этот процесс прост, драйвер может ограничить использование только подмножества функций, доступных в более поздних версиях Windows. Во многих случаях вы хотите использовать более новые функциональные возможности операционной системы, если она доступна для повышения безопасности, повышения надежности или включения новых функций.

Написание драйвера с несколькими версиями, использующего функции, зависящие от версий

Драйвер в режиме ядра может динамически определить, доступна ли операционная система или какая версия Windows, в которой работает драйвер, и выбрать использование функций, доступных в этой среде во время выполнения. Например, драйвер, который должен поддерживать все версии Windows, начиная с Windows 7, может определить версию Windows, на которую она работает. Если драйвер работает в Windows 7, он должен использовать только функции DDI, поддерживаемые Windows 7. Однако тот же драйвер может использовать дополнительные функции DDI, уникальные для Windows 8, например, когда его проверка времени выполнения определяет, что эти API в настоящее время присутствуют или определяют, что он работает в Windows 8.

Примечание.

Рекомендуется проверка для доступности компонентов или API, если это возможно, а не пытаться проверка, если драйвер работает в определенной версии операционной системы или более поздней версии.

Условное вызов функций, зависящих от версии Windows

Драйвер режима ядра может использовать функции MmGetSystemRoutineAddress или MmGetSystemRoutineAddressEx для динамического проверка, если определенный API, который он хочет использовать, доступен в текущей среде времени выполнения и получить указатель функции для вызова этого API.

Примечание.

Чтобы сохранить тип проверка и предотвратить непреднамеренные ошибки, следует создать типдф, который зеркало исходного типа функции.

Пример. Определение доступности API и условно вызываемого 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
}

Определение версии Windows

Драйвер режима ядра может использовать функцию RtlVerifyVersionInfo для динамического проверка версии Windows, в которой она сейчас работает.

Примечание.

Рекомендуется проверка для доступности компонентов или API, если это возможно, а не пытаться проверка, если драйвер работает в определенной версии операционной системы или более поздней версии.

Пример. Определение версии Windows

В следующем примере обнаруживается, превышает ли текущую версию операционной системы или равна ли версия 10.0 и обнаруживает, больше ли номер сборки 22000 (Windows 11 версии 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.
    //

}
...