diff options
author | Oz Linden <oz@lindenlab.com> | 2017-07-10 16:30:28 -0400 |
---|---|---|
committer | Oz Linden <oz@lindenlab.com> | 2017-07-10 16:30:28 -0400 |
commit | b0d8f3a1ab671668abb98fe1327f0fd73fca0fc7 (patch) | |
tree | 3eb0768772b99db06d5cdd2cbf59d201d5f22cf8 /indra | |
parent | 7eb53d4ccbfcb692a2edc7539e651b14c888742e (diff) |
MAINT-4532: properly detect Windows 10 in the 64bit build (only - 32bit runs in Windows 8 compatibility mode)
Diffstat (limited to 'indra')
-rw-r--r-- | indra/CMakeLists.txt | 4 | ||||
-rw-r--r-- | indra/llcommon/llsys.cpp | 377 | ||||
-rw-r--r-- | indra/newview/CMakeLists.txt | 9 | ||||
-rw-r--r-- | indra/newview/windows.manifest | 20 |
4 files changed, 143 insertions, 267 deletions
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 39f8697e8c..a40b2c0846 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -3,8 +3,8 @@ # cmake_minimum_required should appear before any # other commands to guarantee full compatibility # with the version specified -## prior to 2.8, the add_custom_target commands used in setting the version did not work correctly -cmake_minimum_required(VERSION 2.8.8 FATAL_ERROR) +## prior to 3.4, the Windows manifest handling was missing +cmake_minimum_required(VERSION 3.4.0 FATAL_ERROR) set(ROOT_PROJECT_NAME "SecondLife" CACHE STRING "The root project/makefile/solution name. Defaults to SecondLife.") diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index fd1828b1cc..1ef6c538ba 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -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> @@ -110,78 +111,6 @@ static const F32 MEM_INFO_THROTTLE = 20; // dropped below the login framerate, we'd have very little additional data. static const F32 MEM_INFO_WINDOW = 10*60; -#if LL_WINDOWS -// We cannot trust GetVersionEx function on Win8.1 , we should check this value when creating OS string -static const U32 WINNT_WINBLUE = 0x0603; - -#ifndef DLLVERSIONINFO -typedef struct _DllVersionInfo -{ - DWORD cbSize; - DWORD dwMajorVersion; - DWORD dwMinorVersion; - DWORD dwBuildNumber; - DWORD dwPlatformID; -}DLLVERSIONINFO; -#endif - -#ifndef DLLGETVERSIONPROC -typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *); -#endif - -bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number) -{ - bool result = false; - const U32 BUFF_SIZE = 32767; - WCHAR tempBuf[BUFF_SIZE]; - if(GetSystemDirectory((LPWSTR)&tempBuf, BUFF_SIZE)) - { - - std::basic_string<WCHAR> shell32_path(tempBuf); - - // Shell32.dll contains the DLLGetVersion function. - // according to msdn its not part of the API - // so you have to go in and get it. - // http://msdn.microsoft.com/en-us/library/bb776404(VS.85).aspx - shell32_path += TEXT("\\shell32.dll"); - - HMODULE hDllInst = LoadLibrary(shell32_path.c_str()); //load the DLL - if(hDllInst) - { // Could successfully load the DLL - DLLGETVERSIONPROC pDllGetVersion; - /* - You must get this function explicitly because earlier versions of the DLL - don't implement this function. That makes the lack of implementation of the - function a version marker in itself. - */ - pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hDllInst, - "DllGetVersion"); - - if(pDllGetVersion) - { - // DLL supports version retrieval function - DLLVERSIONINFO dvi; - - ZeroMemory(&dvi, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - HRESULT hr = (*pDllGetVersion)(&dvi); - - if(SUCCEEDED(hr)) - { // Finally, the version is at our hands - major = dvi.dwMajorVersion; - minor = dvi.dwMinorVersion; - build_number = dvi.dwBuildNumber; - result = true; - } - } - - FreeLibrary(hDllInst); // Release DLL - } - } - return result; -} -#endif // LL_WINDOWS - // Wrap boost::regex_match() with a function that doesn't throw. template <typename S, typename M, typename R> static bool regex_match_no_exc(const S& string, M& match, const R& regex) @@ -214,221 +143,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; - // Try calling GetVersionEx using the OSVERSIONINFOEX structure. - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - if(!(bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO *) &osvi))) + if (IsWindowsVersionOrGreater(10, 0, 0)) { - // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. - osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - if(!GetVersionEx( (OSVERSIONINFO *) &osvi)) - return; + mMajorVer = 10; + mMinorVer = 0; + mOSStringSimple = "Microsoft Windows 10 "; } - 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) + else if (IsWindows8Point1OrGreater()) { - case VER_PLATFORM_WIN32_NT: + mMajorVer = 6; + mMinorVer = 3; + if (IsWindowsServer()) { - // 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; + mOSStringSimple = "Windows Server 2012 R2 "; } - break; - - case VER_PLATFORM_WIN32_WINDOWS: - // Test for the Windows 95 product family. - if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0) + else { - 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 8.1 "; + } + } + else if (IsWindows8OrGreater()) + { + mMajorVer = 6; + mMinorVer = 2; + if (IsWindowsServer()) { - mOSStringSimple = "Microsoft Windows 98 "; - if ( osvi.szCSDVersion[1] == 'A' ) - { - mOSStringSimple += "SE "; - } - } - if(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90) + mOSStringSimple = "Windows Server 2012 "; + } + else { - mOSStringSimple = "Microsoft Windows Millennium Edition "; + 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 "; } - mOSString = mOSStringSimple; - break; } + 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) - std::string compatibility_mode; - if(got_shell32_version) + //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 { - if((osvi.dwMajorVersion != shell32_major || osvi.dwMinorVersion != shell32_minor) && !bShouldUseShellVersion) + 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 (GetVersionEx((OSVERSIONINFO *)&osvi)) + { + mBuild = osvi.dwBuildNumber & 0xffff; + } + else + { + // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if (GetVersionEx((OSVERSIONINFO *)&osvi)) { - compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)", - shell32_major, - shell32_minor, - shell32_build); + mBuild = osvi.dwBuildNumber & 0xffff; } } - mOSString += compatibility_mode; + + mOSString = mOSStringSimple; + if (mBuild > 0) + { + mOSString += llformat("(Build %d)", mBuild); + } + + LLStringUtil::trim(mOSStringSimple); + LLStringUtil::trim(mOSString); #elif LL_DARWIN diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 266de7277d..f353109deb 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1561,6 +1561,15 @@ if (WINDOWS) if (INTEL_MEMOPS_LIBRARY) list(APPEND viewer_LIBRARIES ${INTEL_MEMOPS_LIBRARY}) endif (INTEL_MEMOPS_LIBRARY) + + if (ADDRESS_SIZE EQUAL 64) + # We deliberately omit this from the 32bit build because it declares that + # the viewer is compatible with Windows 10; we need that to properly detect + # the Windows version, but doing so causes systems with certain HD video + # cards to fail because Windows 10 does not support them. Leaving this out + # causes those systems to run in a Windows 8 compatibility mode, which works. + LIST(APPEND viewer_SOURCE_FILES windows.manifest) + endif (ADDRESS_SIZE EQUAL 64) endif (WINDOWS) # Add the xui files. This is handy for searching for xui elements diff --git a/indra/newview/windows.manifest b/indra/newview/windows.manifest new file mode 100644 index 0000000000..8321ac5337 --- /dev/null +++ b/indra/newview/windows.manifest @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" > + <asmv3:application> + <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> + <dpiAware>True/PM</dpiAware> + </asmv3:windowsSettings> + </asmv3:application> + <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> + <application> + <!-- Windows 7 --> + <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> + <!-- Windows 8 --> + <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> + <!-- Windows 8.1 --> + <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> + <!-- Windows 10 --> + <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/> + </application> + </compatibility> +</assembly> |