Написание драйверов для различных версий Windows
При создании проекта драйвера необходимо указать минимальную целевую операционную систему, которая является минимальной версией Windows, в которой будет работать драйвер. Например, можно указать, что Windows 7 является минимальной целевой операционной системой. В этом случае драйвер будет работать в Windows 7 и более поздних версиях Windows.
Заметка
Если вы разрабатываете драйвер для определенной минимальной версии Windows и хотите, чтобы драйвер работал в более поздних версиях Windows, вы не должны использовать какие-либо незадокументированные функции, и вы не должны использовать документированные функции каким-либо образом, кроме того, как он описан в документации. В противном случае драйвер может не запуститься в более поздних версиях Windows. Даже если вы тщательно использовали только документированные функции, следует протестировать драйвер в новой версии Windows каждый раз при каждом выпуске.
Написание драйвера с несколькими версиями с использованием только общих функций
При разработке драйвера, который будет работать в нескольких версиях Windows, самый простой подход заключается в том, чтобы драйвер мог использовать только функции и структуры DDI, которые являются общими для всех версий Windows, на которых будет работать драйвер. В этой ситуации для минимальной целевой операционной системы устанавливается самая ранняя версия Windows, которую будет поддерживать драйвер.
Например, для поддержки всех версий Windows, начиная с Windows 7, необходимо:
Проектируйте и реализуйте драйвер таким образом, чтобы он использовал только те функции, которые присутствуют в Windows 7.
При сборке драйвера укажите Windows 7 в качестве минимальной целевой операционной системы.
Хотя этот процесс прост, драйвер может ограничить использование только подмножества функций, доступных в более поздних версиях Windows. Во многих случаях вы хотите использовать более новые функциональные возможности операционной системы, если она доступна для повышения безопасности, повышения надежности или включения новых функций.
Написание драйвера с несколькими версиями, использующего функции, зависящие от версий
Драйвер в режиме ядра может динамически определить, доступен ли API, предоставляемый операционной системой, или на какой версии Windows работает драйвер, и выбрать использование функций, доступных в этой среде выполнения. Например, драйвер, который должен поддерживать все версии Windows, начиная с Windows 7, может определить версию Windows, на которую она работает. Если драйвер работает в Windows 7, он должен использовать только функции DDI, поддерживаемые Windows 7. Однако тот же драйвер может использовать дополнительные функции DDI, уникальные для Windows 8, например, когда проверка времени выполнения определяет, что эти API в настоящее время присутствуют или определяют, что он работает в Windows 8.
Заметка
Рекомендуется проверять доступность компонентов или API, если это возможно, а не пытаться проверить, работает ли драйвер в определенной версии операционной системы или более поздней версии.
Условный вызов функций, зависящих от версии Windows
Драйвер режима ядра может использовать функции MmGetSystemRoutineAddress или MmGetSystemRoutineAddressEx для динамического проверки доступности определенного API в текущей среде времени выполнения и получения указателя функции для вызова этого API.
Заметка
Чтобы сохранить проверку типов и предотвратить непреднамеренные ошибки, вы должны создать typedef, который соответствует исходному типу функции.
Пример: Определение доступности 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.
//
}
...