在写驱动程序时,我们发现对于Windows的不同版本,其对应的内核数据结构是不同的,所以在具体操作时同样要根据Windows的不同版本进行不同的操作,那么怎样获取Windows的版本,并且Windows的不同版本的结构模式应如何区别,这是下面要解决的问题。MSDN上提到PsGetVersion是已经过时的函数版本,如果要在XP或以后的版本上获取Windows的版本号,就用RtlGetVersion。所以这两个函数对应的版本还是有所不同的,那么怎样区别性的对待这两种不同的函数呢?下面是一个博客上提供的一种方法,就是用试探式区分:用RtlGetVersion获取版本号,如果成功,则认为当前版本是XP及以后版本,否则认为是XP以下的版本。
下面是函数的实现:
typedef enum WIN_VER_DETAIL {
WINDOWS_VERSION_NONE, // 0
WINDOWS_VERSION_2K,
WINDOWS_VERSION_XP,
WINDOWS_VERSION_2K3,
WINDOWS_VERSION_2K3_SP1_SP2,//2K3的SP1与SP2结构模式是相同的
WINDOWS_VERSION_VISTA,
} WIN_VER_DETAIL;
typedef NTSTATUS (NTAPI * PFN_RtlGetVersion)(OUT PRTL_OSVERSIONINFOW lpVersionInformation);
EXTERN_C WIN_VER_DETAIL GetWindowsVersion()
{
UNICODE_STRING ustrFuncName = { 0 };
RTL_OSVERSIONINFOEXW osverinfo = { sizeof(osverinfo) };
PFN_RtlGetVersion pfnRtlGetVersion = NULL;
RtlInitUnicodeString(&ustrFuncName, L"RtlGetVersion");
pfnRtlGetVersion = MmGetSystemRoutineAddress(&ustrFuncName);
//判断XP前后版本,调用不同的函数获得版本号
if (pfnRtlGetVersion)
{
kdprintf("[xxxxxxxx] Using \"RtlGetVersion\"\n");
pfnRtlGetVersion((PRTL_OSVERSIONINFOW)&osverinfo);
}
else
{
kdprintf("[xxxxxxxx] Using \"PsGetVersion\"\n");
PsGetVersion(&osverinfo.dwMajorVersion, &osverinfo.dwMinorVersion, &osverinfo.dwBuildNumber, NULL);
}
kdprintf("[xxxxxxxx] OSVersion NT %d.%d:%d sp%d.%d\n",
osverinfo.dwMajorVersion, osverinfo.dwMinorVersion, osverinfo.dwBuildNumber,
osverinfo.wServicePackMajor, osverinfo.wServicePackMinor);
//根据获得的版本号情况,返回结果
if (osverinfo.dwMajorVersion == 5 && osverinfo.dwMinorVersion == 0) {
return WINDOWS_VERSION_2K;
} else if (osverinfo.dwMajorVersion == 5 && osverinfo.dwMinorVersion == 1) {
return WINDOWS_VERSION_XP;
} else if (osverinfo.dwMajorVersion == 5 && osverinfo.dwMinorVersion == 2) {
if (osverinfo.wServicePackMajor==0) {
return WINDOWS_VERSION_2K3;
} else {
return WINDOWS_VERSION_2K3_SP1_SP2;
}
} else if (6 == OSVersionInfoEx.dwMajorVersion)
{
switch (OSVersionInfoEx.dwMinorVersion)
{
case 0:
return WINDOWS_VERSION_VISTA;
case 1:
return WINDOWS_VERSION_7;
}
}
return WINDOWS_VERSION_NONE;
}