STORM-2105: Switch to VersionHelper API to determine Windows version

While we could set major and minor operating system version with the data
returned by GetVersionEx / GetVersion, we set them explicitly as named function
may be altered or removed in the future. In that case, only the build number
would be affected.

Also removed the old way of determing the build number via shell version. This
was only needed for Windows 9x, which aren't supported anymore and can't even
run the viewer.
master
Ansariel 2015-05-21 11:13:01 +02:00
parent 49d597db5d
commit f2d033ef59
1 changed files with 117 additions and 198 deletions

View File

@ -61,6 +61,7 @@ using namespace llsd;
#if LL_WINDOWS
# include "llwin32headerslean.h"
# include <psapi.h> // GetPerformanceInfo() et al.
# include <VersionHelpers.h>
#elif LL_DARWIN
# include <errno.h>
# include <sys/sysctl.h>
@ -215,221 +216,139 @@ static bool regex_search_no_exc(const S& string, M& match, const R& regex)
}
}
#if LL_WINDOWS
// GetVersionEx should not works correct with Windows 8.1 and the later version. We need to check this case
static bool check_for_version(WORD wMajorVersion, WORD wMinorVersion, WORD wServicePackMajor)
{
OSVERSIONINFOEXW osvi = { sizeof(osvi), 0, 0, 0, 0, {0}, 0, 0 };
DWORDLONG const dwlConditionMask = VerSetConditionMask(
VerSetConditionMask(
VerSetConditionMask(
0, VER_MAJORVERSION, VER_GREATER_EQUAL),
VER_MINORVERSION, VER_GREATER_EQUAL),
VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
osvi.dwMajorVersion = wMajorVersion;
osvi.dwMinorVersion = wMinorVersion;
osvi.wServicePackMajor = wServicePackMajor;
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE;
}
#endif
LLOSInfo::LLOSInfo() :
mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")
{
#if LL_WINDOWS
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
BOOL bShouldUseShellVersion = false;
if (IsWindowsVersionOrGreater(10, 0, 0))
{
mMajorVer = 10;
mMinorVer = 0;
mOSStringSimple = "Microsoft Windows 10 ";
}
else if (IsWindows8Point1OrGreater())
{
mMajorVer = 6;
mMinorVer = 3;
if (IsWindowsServer())
{
mOSStringSimple = "Windows Server 2012 R2 ";
}
else
{
mOSStringSimple = "Microsoft Windows 8.1 ";
}
}
else if (IsWindows8OrGreater())
{
mMajorVer = 6;
mMinorVer = 2;
if (IsWindowsServer())
{
mOSStringSimple = "Windows Server 2012 ";
}
else
{
mOSStringSimple = "Microsoft Windows 8 ";
}
}
else if (IsWindows7SP1OrGreater())
{
mMajorVer = 6;
mMinorVer = 1;
if (IsWindowsServer())
{
mOSStringSimple = "Windows Server 2008 R2 SP1 ";
}
else
{
mOSStringSimple = "Microsoft Windows 7 SP1 ";
}
}
else if (IsWindows7OrGreater())
{
mMajorVer = 6;
mMinorVer = 1;
if (IsWindowsServer())
{
mOSStringSimple = "Windows Server 2008 R2 ";
}
else
{
mOSStringSimple = "Microsoft Windows 7 ";
}
}
else if (IsWindowsVistaSP2OrGreater())
{
mMajorVer = 6;
mMinorVer = 0;
if (IsWindowsServer())
{
mOSStringSimple = "Windows Server 2008 SP2 ";
}
else
{
mOSStringSimple = "Microsoft Windows Vista SP2 ";
}
}
else
{
mOSStringSimple = "Unsupported Windows version ";
}
///get native system info if available..
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
SYSTEM_INFO si; //System Info object file contains architecture info
PGNSI pGNSI; //pointer object
ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
pGNSI = (PGNSI)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
if (NULL != pGNSI) //check if it has failed
pGNSI(&si); //success
else
GetSystemInfo(&si); //if it fails get regular system info
//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
//msdn microsoft finds 32 bit and 64 bit flavors this way..
//http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
//of windows than this code does (in case it is needed for the future)
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit
{
mOSStringSimple += "64-bit ";
}
else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
{
mOSStringSimple += "32-bit ";
}
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi)))
if (GetVersionEx((OSVERSIONINFO *)&osvi))
{
mBuild = osvi.dwBuildNumber & 0xffff;
}
else
{
// If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO.
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if(!GetVersionEx( (OSVERSIONINFO *) &osvi))
return;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (GetVersionEx((OSVERSIONINFO *)&osvi))
{
mBuild = osvi.dwBuildNumber & 0xffff;
}
}
mMajorVer = osvi.dwMajorVersion;
mMinorVer = osvi.dwMinorVersion;
mBuild = osvi.dwBuildNumber;
DWORD shell32_major, shell32_minor, shell32_build;
bool got_shell32_version = get_shell32_dll_version(shell32_major,
shell32_minor,
shell32_build);
switch(osvi.dwPlatformId)
mOSString = mOSStringSimple;
if (mBuild > 0)
{
case VER_PLATFORM_WIN32_NT:
{
// Test for the product.
if(osvi.dwMajorVersion <= 4)
{
mOSStringSimple = "Microsoft Windows NT ";
}
else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
{
mOSStringSimple = "Microsoft Windows 2000 ";
}
else if(osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1)
{
mOSStringSimple = "Microsoft Windows XP ";
}
else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows XP x64 Edition ";
else
mOSStringSimple = "Microsoft Windows Server 2003 ";
}
else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 2)
{
if(osvi.dwMinorVersion == 0)
{
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows Vista ";
else
mOSStringSimple = "Windows Server 2008 ";
}
else if(osvi.dwMinorVersion == 1)
{
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows 7 ";
else
mOSStringSimple = "Windows Server 2008 R2 ";
}
else if(osvi.dwMinorVersion == 2)
{
if (check_for_version(HIBYTE(WINNT_WINBLUE), LOBYTE(WINNT_WINBLUE), 0))
{
mOSStringSimple = "Microsoft Windows 8.1 ";
bShouldUseShellVersion = true; // GetVersionEx failed, going to use shell version
}
else
{
if(osvi.wProductType == VER_NT_WORKSTATION)
mOSStringSimple = "Microsoft Windows 8 ";
else
mOSStringSimple = "Windows Server 2012 ";
}
}
///get native system info if available..
typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); ///function pointer for loading GetNativeSystemInfo
SYSTEM_INFO si; //System Info object file contains architecture info
PGNSI pGNSI; //pointer object
ZeroMemory(&si, sizeof(SYSTEM_INFO)); //zero out the memory in information
pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
if(NULL != pGNSI) //check if it has failed
pGNSI(&si); //success
else
GetSystemInfo(&si); //if it fails get regular system info
//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
//msdn microsoft finds 32 bit and 64 bit flavors this way..
//http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
//of windows than this code does (in case it is needed for the future)
if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 ) //check for 64 bit
{
mOSStringSimple += "64-bit ";
}
else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
{
mOSStringSimple += "32-bit ";
}
}
else // Use the registry on early versions of Windows NT.
{
mOSStringSimple = "Microsoft Windows (unrecognized) ";
HKEY hKey;
WCHAR szProductType[80];
DWORD dwBufLen;
RegOpenKeyEx( HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
0, KEY_QUERY_VALUE, &hKey );
RegQueryValueEx( hKey, L"ProductType", NULL, NULL,
(LPBYTE) szProductType, &dwBufLen);
RegCloseKey( hKey );
if ( lstrcmpi( L"WINNT", szProductType) == 0 )
{
mOSStringSimple += "Professional ";
}
else if ( lstrcmpi( L"LANMANNT", szProductType) == 0 )
{
mOSStringSimple += "Server ";
}
else if ( lstrcmpi( L"SERVERNT", szProductType) == 0 )
{
mOSStringSimple += "Advanced Server ";
}
}
std::string csdversion = utf16str_to_utf8str(osvi.szCSDVersion);
// Display version, service pack (if any), and build number.
std::string tmpstr;
if(osvi.dwMajorVersion <= 4)
{
tmpstr = llformat("version %d.%d %s (Build %d)",
osvi.dwMajorVersion,
osvi.dwMinorVersion,
csdversion.c_str(),
(osvi.dwBuildNumber & 0xffff));
}
else
{
tmpstr = !bShouldUseShellVersion ? llformat("%s (Build %d)", csdversion.c_str(), (osvi.dwBuildNumber & 0xffff)):
llformat("%s (Build %d)", csdversion.c_str(), shell32_build);
}
mOSString = mOSStringSimple + tmpstr;
}
break;
case VER_PLATFORM_WIN32_WINDOWS:
// Test for the Windows 95 product family.
if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0)
{
mOSStringSimple = "Microsoft Windows 95 ";
if ( osvi.szCSDVersion[1] == 'C' || osvi.szCSDVersion[1] == 'B' )
{
mOSStringSimple += "OSR2 ";
}
}
if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
mOSStringSimple = "Microsoft Windows 98 ";
if ( osvi.szCSDVersion[1] == 'A' )
{
mOSStringSimple += "SE ";
}
}
if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
{
mOSStringSimple = "Microsoft Windows Millennium Edition ";
}
mOSString = mOSStringSimple;
break;
mOSString += llformat("(Build %d)", mBuild);
}
std::string compatibility_mode;
if(got_shell32_version)
{
if((osvi.dwMajorVersion != shell32_major || osvi.dwMinorVersion != shell32_minor) && !bShouldUseShellVersion)
{
compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)",
shell32_major,
shell32_minor,
shell32_build);
}
}
mOSString += compatibility_mode;
LLStringUtil::trim(mOSStringSimple);
LLStringUtil::trim(mOSString);
#elif LL_DARWIN