diff options
Diffstat (limited to 'src/corelib/global/qglobal.cpp')
-rw-r--r-- | src/corelib/global/qglobal.cpp | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index aaad58e..e46894c 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -48,6 +48,8 @@ #include "qstringlist.h" #include "qdatetime.h" +#include <private/qsystemlibrary_p.h> + #ifndef QT_NO_QOBJECT #include <private/qthread_p.h> #endif @@ -1691,6 +1693,69 @@ QT_BEGIN_INCLUDE_NAMESPACE #include "qt_windows.h" QT_END_INCLUDE_NAMESPACE +# ifndef Q_OS_WINCE + +// Determine Windows versions >= 8 by querying the version of kernel32.dll. +static inline bool determineWinOsVersionPost8(OSVERSIONINFO *result) +{ + typedef WORD (WINAPI* PtrGetFileVersionInfoSizeW)(LPCWSTR, LPDWORD); + typedef BOOL (WINAPI* PtrVerQueryValueW)(LPCVOID, LPCWSTR, LPVOID, PUINT); + typedef BOOL (WINAPI* PtrGetFileVersionInfoW)(LPCWSTR, DWORD, DWORD, LPVOID); + + QSystemLibrary versionLib(QLatin1String("version")); + if (!versionLib.load()) + return false; + PtrGetFileVersionInfoSizeW getFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)versionLib.resolve("GetFileVersionInfoSizeW"); + PtrVerQueryValueW verQueryValueW = (PtrVerQueryValueW)versionLib.resolve("VerQueryValueW"); + PtrGetFileVersionInfoW getFileVersionInfoW = (PtrGetFileVersionInfoW)versionLib.resolve("GetFileVersionInfoW"); + if (!getFileVersionInfoSizeW || !verQueryValueW || !getFileVersionInfoW) + return false; + + const wchar_t kernel32Dll[] = L"kernel32.dll"; + DWORD handle; + const DWORD size = getFileVersionInfoSizeW(kernel32Dll, &handle); + if (!size) + return false; + QScopedArrayPointer<BYTE> versionInfo(new BYTE[size]); + if (!getFileVersionInfoW(kernel32Dll, handle, size, versionInfo.data())) + return false; + UINT uLen; + VS_FIXEDFILEINFO *fileInfo = 0; + if (!verQueryValueW(versionInfo.data(), L"\\", (LPVOID *)&fileInfo, &uLen)) + return false; + const DWORD fileVersionMS = fileInfo->dwFileVersionMS; + const DWORD fileVersionLS = fileInfo->dwFileVersionLS; + result->dwMajorVersion = HIWORD(fileVersionMS); + result->dwMinorVersion = LOWORD(fileVersionMS); + result->dwBuildNumber = HIWORD(fileVersionLS); + return true; +} + +// Fallback for determining Windows versions >= 8 by looping using the +// version check macros. Note that it will return build number=0 to avoid +// inefficient looping. +static inline void determineWinOsVersionFallbackPost8(OSVERSIONINFO *result) +{ + result->dwBuildNumber = 0; + DWORDLONG conditionMask = 0; + VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL); + OSVERSIONINFOEX checkVersion = { sizeof(OSVERSIONINFOEX), result->dwMajorVersion, 0, + result->dwBuildNumber, result->dwPlatformId, {'\0'}, 0, 0, 0, 0, 0 }; + for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMajorVersion) + result->dwMajorVersion = checkVersion.dwMajorVersion; + conditionMask = 0; + checkVersion.dwMajorVersion = result->dwMajorVersion; + checkVersion.dwMinorVersion = 0; + VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL); + for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMinorVersion) + result->dwMinorVersion = checkVersion.dwMinorVersion; +} + +# endif // !Q_OS_WINCE + static inline OSVERSIONINFO winOsVersion() { OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0, {'\0'}}; @@ -1706,16 +1771,8 @@ static inline OSVERSIONINFO winOsVersion() # endif # ifndef Q_OS_WINCE if (result.dwMajorVersion == 6 && result.dwMinorVersion == 2) { - // This could be Windows 8.1 or higher. Note that as of Windows 9, - // the major version needs to be checked as well. - DWORDLONG conditionMask = 0; - VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); - VER_SET_CONDITION(conditionMask, VER_PLATFORMID, VER_EQUAL); - OSVERSIONINFOEX checkVersion = { sizeof(OSVERSIONINFOEX), result.dwMajorVersion, result.dwMinorVersion, - result.dwBuildNumber, result.dwPlatformId, {'\0'}, 0, 0, 0, 0, 0 }; - for ( ; VerifyVersionInfo(&checkVersion, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, conditionMask); ++checkVersion.dwMinorVersion) - result.dwMinorVersion = checkVersion.dwMinorVersion; + if (!determineWinOsVersionPost8(&result)) + determineWinOsVersionFallbackPost8(&result); } # endif // !Q_OS_WINCE return result; |