さまざまなバージョンの Windows 用ドライバーの記述
ドライバー プロジェクトを作成するときに、ドライバーを実行する Windows の最小バージョンである最小ターゲット オペレーティング システムを指定します。 たとえば、Windows 7 が最小ターゲット オペレーティング システムであることを指定できます。 その場合、ドライバーは Windows 7 以降のバージョンの Windows で実行されます。
手記
特定の最小バージョンの Windows 用のドライバーを開発し、ドライバーを新しいバージョンの Windows で動作させる場合は、文書化されていない関数を使用しないでください。また、ドキュメントで説明されている方法以外の方法で、文書化された関数を使用しないでください。 そうしないと、ドライバーが新しいバージョンの Windows で実行できない可能性があります。 文書化された関数のみを使用するように注意した場合でも、リリースされるたびに新しいバージョンの Windows でドライバーをテストする必要があります。
一般的な機能のみを使用して複数バージョンのドライバーを作成する
複数のバージョンの Windows で実行されるドライバーを設計する場合、最も簡単な方法は、ドライバーが実行されるすべてのバージョンの Windows に共通する DDI 関数と構造体のみを使用できるようにすることです。 この状況では、ドライバーがサポートする最も古いバージョンの Windows に最小ターゲット オペレーティング システムを設定します。
たとえば、Windows 7 以降のすべてのバージョンの Windows をサポートするには、次の手順を実行する必要があります。
Windows 7 に存在する機能のみを使用するようにドライバーを設計して実装します。
ドライバーをビルドするときは、最小ターゲット オペレーティング システムとして Windows 7 を指定します。
このプロセスは単純ですが、ドライバーは、新しいバージョンの Windows で使用できる機能のサブセットのみを使用するように制限する場合があります。 多くの場合、セキュリティの向上、信頼性の向上、または新しい機能の有効化のために、新しいオペレーティング システム機能を使用できる場合があります。
バージョンに依存する機能を使用するマルチバージョン ドライバーの作成
カーネル モード ドライバーは、オペレーティング システムが提供する API が使用可能かどうか、またはドライバーが実行されている Windows のバージョンを動的に判断し、その実行時環境で使用可能な機能を使用することを選択できます。 たとえば、Windows 7 以降のすべてのバージョンの Windows をサポートする必要があるドライバーは、実行時に実行されている Windows のバージョンを決定できます。 ドライバーが Windows 7 で実行されている場合は、Windows 7 でサポートされている DDI 関数のみを使用する必要があります。 ただし、同じドライバーは、Windows 8 に固有の追加の DDI 関数を使用できます。たとえば、実行時チェックでそれらの API が現在存在していると判断されたり、Windows 8 で実行されていると判断されたりした場合などです。
手記
ドライバーが特定のオペレーティング システムのバージョン以降で実行されているかどうかを確認するのではなく、可能な限り機能または API の可用性を確認することをお勧めします。
Windows のバージョン依存関数を条件付きで呼び出す
カーネル モード ドライバーは、MmGetSystemRoutineAddressまたは mmGetSystemRoutineAddressEx 関数を使用して、使用する特定の API が現在のランタイム環境で使用可能かどうかを動的に確認し、その API を呼び出すために使用する関数ポインターを取得できます。
手記
型チェックを維持し、意図しないエラーを防ぐには、元の関数型を反映する typedef を作成する必要があります。
例: 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.
//
}
...