Improved get_real_os_version() function. Now also detects the real build number.

This commit is contained in:
LoRd_MuldeR 2016-05-15 23:03:38 +02:00
parent 6185f67786
commit cb53f41a01
2 changed files with 90 additions and 26 deletions

View File

@ -49,19 +49,20 @@ namespace MUtils
os_type_t; os_type_t;
//OS version struct //OS version struct
typedef struct _os_info_t typedef struct _os_version_t
{ {
unsigned int type; unsigned int type;
unsigned int versionMajor; unsigned int versionMajor;
unsigned int versionMinor; unsigned int versionMinor;
unsigned int versionBuild;
bool overrideFlag; bool overrideFlag;
MUTILS_API bool operator== (const _os_info_t &rhs) const; MUTILS_API bool operator== (const _os_version_t &rhs) const;
MUTILS_API bool operator!= (const _os_info_t &rhs) const; MUTILS_API bool operator!= (const _os_version_t &rhs) const;
MUTILS_API bool operator> (const _os_info_t &rhs) const; MUTILS_API bool operator> (const _os_version_t &rhs) const;
MUTILS_API bool operator>= (const _os_info_t &rhs) const; MUTILS_API bool operator>= (const _os_version_t &rhs) const;
MUTILS_API bool operator< (const _os_info_t &rhs) const; MUTILS_API bool operator< (const _os_version_t &rhs) const;
MUTILS_API bool operator<= (const _os_info_t &rhs) const; MUTILS_API bool operator<= (const _os_version_t &rhs) const;
} }
os_version_t; os_version_t;

View File

@ -284,7 +284,7 @@ g_os_version_lut[] =
{ MUtils::OS::Version::WINDOWS_WIN70, "Windows 7 or Windows Server 2008 R2" }, //7 { MUtils::OS::Version::WINDOWS_WIN70, "Windows 7 or Windows Server 2008 R2" }, //7
{ MUtils::OS::Version::WINDOWS_WIN80, "Windows 8 or Windows Server 2012" }, //8 { MUtils::OS::Version::WINDOWS_WIN80, "Windows 8 or Windows Server 2012" }, //8
{ MUtils::OS::Version::WINDOWS_WIN81, "Windows 8.1 or Windows Server 2012 R2" }, //8.1 { MUtils::OS::Version::WINDOWS_WIN81, "Windows 8.1 or Windows Server 2012 R2" }, //8.1
{ MUtils::OS::Version::WINDOWS_WN100, "Windows 10 or Windows Server 2014 (Preview)" }, //10 { MUtils::OS::Version::WINDOWS_WN100, "Windows 10 or Windows Server 2016" }, //10
{ MUtils::OS::Version::UNKNOWN_OPSYS, "N/A" } { MUtils::OS::Version::UNKNOWN_OPSYS, "N/A" }
}; };
@ -319,6 +319,12 @@ namespace MUtils
} }
} }
static inline DWORD SAFE_ADD(const DWORD &a, const DWORD &b)
{
const DWORD temp = a + b;
return ((temp >= a) && (temp >= b)) ? temp : MAXDWORD;
}
static void initialize_os_version(OSVERSIONINFOEXW *const osInfo) static void initialize_os_version(OSVERSIONINFOEXW *const osInfo)
{ {
memset(osInfo, 0, sizeof(OSVERSIONINFOEXW)); memset(osInfo, 0, sizeof(OSVERSIONINFOEXW));
@ -367,10 +373,9 @@ static bool verify_os_version(const DWORD major, const DWORD minor)
{ {
OSVERSIONINFOEXW osvi; OSVERSIONINFOEXW osvi;
DWORDLONG dwlConditionMask = 0; DWORDLONG dwlConditionMask = 0;
initialize_os_version(&osvi);
//Initialize the OSVERSIONINFOEX structure //Initialize the OSVERSIONINFOEX structure
memset(&osvi, 0, sizeof(OSVERSIONINFOEXW));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
osvi.dwMajorVersion = major; osvi.dwMajorVersion = major;
osvi.dwMinorVersion = minor; osvi.dwMinorVersion = minor;
osvi.dwPlatformId = VER_PLATFORM_WIN32_NT; osvi.dwPlatformId = VER_PLATFORM_WIN32_NT;
@ -395,9 +400,40 @@ static bool verify_os_version(const DWORD major, const DWORD minor)
return (ret != FALSE); return (ret != FALSE);
} }
static bool get_real_os_version(unsigned int *major, unsigned int *minor, bool *pbOverride) static bool verify_os_build(const DWORD build)
{ {
*major = *minor = 0; OSVERSIONINFOEXW osvi;
DWORDLONG dwlConditionMask = 0;
initialize_os_version(&osvi);
//Initialize the OSVERSIONINFOEX structure
osvi.dwBuildNumber = build;
osvi.dwPlatformId = VER_PLATFORM_WIN32_NT;
//Initialize the condition mask
VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_PLATFORMID, VER_EQUAL);
// Perform the test
const BOOL ret = rtl_verify_version(&osvi, VER_BUILDNUMBER | VER_PLATFORMID, dwlConditionMask);
//Error checking
if (!ret)
{
if (GetLastError() != ERROR_OLD_WIN_VERSION)
{
qWarning("VerifyVersionInfo() system call has failed!");
}
}
return (ret != FALSE);
}
static bool get_real_os_version(unsigned int *major, unsigned int *minor, unsigned int *build, bool *pbOverride)
{
static const DWORD MAX_VERSION = 0xFFFF;
*major = *minor = *build = 0;
*pbOverride = false; *pbOverride = false;
//Initialize local variables //Initialize local variables
@ -417,35 +453,61 @@ static bool get_real_os_version(unsigned int *major, unsigned int *minor, bool *
{ {
*major = osvi.dwMajorVersion; *major = osvi.dwMajorVersion;
*minor = osvi.dwMinorVersion; *minor = osvi.dwMinorVersion;
*build = osvi.dwBuildNumber;
}
else
{
if (verify_os_version(4, 0))
{
*major = 4;
*build = 1381;
*pbOverride = true;
} }
else else
{ {
qWarning("Not running on Windows NT, unsupported operating system!"); qWarning("Not running on Windows NT, unsupported operating system!");
return false; return false;
} }
}
//Determine the real *major* version first //Major Version
forever for (DWORD nextMajor = (*major) + 1; nextMajor <= MAX_VERSION; nextMajor++)
{ {
const DWORD nextMajor = (*major) + 1; if (verify_os_version(nextMajor, 0))
if(verify_os_version(nextMajor, 0))
{ {
*pbOverride = true;
*major = nextMajor; *major = nextMajor;
*minor = 0; *minor = 0;
*pbOverride = true;
continue; continue;
} }
break; break;
} }
//Now also determine the real *minor* version //Minor Version
forever for (DWORD nextMinor = (*minor) + 1; nextMinor <= MAX_VERSION; nextMinor++)
{ {
const DWORD nextMinor = (*minor) + 1; if (verify_os_version((*major), nextMinor))
if(verify_os_version((*major), nextMinor))
{ {
*pbOverride = true;
*minor = nextMinor; *minor = nextMinor;
*pbOverride = true;
continue;
}
break;
}
//Build Version
DWORD stepSize = 32768;
for (DWORD nextBuildNo = SAFE_ADD((*build), stepSize); (*build) < MAXDWORD; nextBuildNo = SAFE_ADD((*build), stepSize))
{
if (verify_os_build(nextBuildNo))
{
*build = nextBuildNo;
*pbOverride = true;
continue;
}
if (stepSize > 1)
{
stepSize = stepSize / 2;
continue; continue;
} }
break; break;
@ -474,12 +536,13 @@ const MUtils::OS::Version::os_version_t &MUtils::OS::os_version(void)
} }
//Detect OS version //Detect OS version
unsigned int major, minor; bool overrideFlg; unsigned int major, minor, build; bool overrideFlg;
if(get_real_os_version(&major, &minor, &overrideFlg)) if(get_real_os_version(&major, &minor, &build, &overrideFlg))
{ {
g_os_version_info.type = Version::OS_WINDOWS; g_os_version_info.type = Version::OS_WINDOWS;
g_os_version_info.versionMajor = major; g_os_version_info.versionMajor = major;
g_os_version_info.versionMinor = minor; g_os_version_info.versionMinor = minor;
g_os_version_info.versionBuild = build;
g_os_version_info.overrideFlag = overrideFlg; g_os_version_info.overrideFlag = overrideFlg;
} }
else else