From d61b52a60e6c94c39f5e12b2e8d8e62511287f08 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 30 Oct 2015 23:20:47 +0100 Subject: [PATCH] Use RtlGetVersion() to retrieve the real OS version in wxMSW Unlike GetVersionEx(), this function still returns the real version and not the fiction concocted by the OS for each program depending on its manifest. Also use OSVERSIONINFOEXW instead of OSVERSIONINFOEX as RtlGetVersion() only exists in the Unicode version. Closes #15321. --- docs/changes.txt | 1 + src/msw/utils.cpp | 33 ++++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index f37f01c488..6f3aa89244 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -181,6 +181,7 @@ wxMSW: - Correct wxGetOsDescription() for Windows 10 (Tobias Taschner). - Make wxListCtrl &c appearance more native on modern systems (Tobias Taschner). - Don't send wxActivateEvent for minimized windows (bzcdr). +- Return correct OS version under Windows 8 and later. wxOSX/Cocoa: diff --git a/src/msw/utils.cpp b/src/msw/utils.cpp index 1a4e8137d6..4e17bbe659 100644 --- a/src/msw/utils.cpp +++ b/src/msw/utils.cpp @@ -997,23 +997,34 @@ wxLoadUserResource(const wxString& resourceName, namespace { -// Helper function wrapping Windows GetVersionEx() which is deprecated since -// Windows 8. For now, all we do in this wrapper is to avoid the deprecation -// warnings but this is not enough as the function now actually doesn't return -// the correct value any more and we need to use VerifyVersionInfo() to perform -// binary search to find the real Windows version. -OSVERSIONINFOEX wxGetWindowsVersionInfo() +// Helper trying to get the real Windows version which is needed because +// GetVersionEx() doesn't return it any more since Windows 8. +OSVERSIONINFOEXW wxGetWindowsVersionInfo() { - OSVERSIONINFOEX info; + OSVERSIONINFOEXW info; wxZeroMemory(info); + info.dwOSVersionInfoSize = sizeof(info); + + // The simplest way to get the version is to call the kernel + // RtlGetVersion() directly, if it is available. +#if wxUSE_DYNLIB_CLASS + wxDynamicLibrary dllNtDll; + if ( dllNtDll.RawLoad(wxS("ntdll.dll")) ) + { + typedef LONG /* NTSTATUS */ (WINAPI *RtlGetVersion_t)(OSVERSIONINFOEXW*); + + RtlGetVersion_t wxDL_INIT_FUNC(pfn, RtlGetVersion, dllNtDll); + if ( pfnRtlGetVersion && pfnRtlGetVersion(&info) ) + return info; + } +#endif // wxUSE_DYNLIB_CLASS #ifdef __VISUALC__ #pragma warning(push) #pragma warning(disable:4996) // 'xxx': was declared deprecated #endif - info.dwOSVersionInfoSize = sizeof(info); - if ( !::GetVersionEx(reinterpret_cast(&info)) ) + if ( !::GetVersionExW(reinterpret_cast(&info)) ) { // This really shouldn't ever happen. wxFAIL_MSG( "GetVersionEx() unexpectedly failed" ); @@ -1056,7 +1067,7 @@ wxString wxGetOsDescription() { wxString str; - const OSVERSIONINFOEX info = wxGetWindowsVersionInfo(); + const OSVERSIONINFOEXW info = wxGetWindowsVersionInfo(); switch ( info.dwPlatformId ) { #ifdef VER_PLATFORM_WIN32_CE @@ -1236,7 +1247,7 @@ wxOperatingSystemId wxGetOsVersion(int *verMaj, int *verMin) // query the OS info only once as it's not supposed to change if ( !s_version.initialized ) { - const OSVERSIONINFOEX info = wxGetWindowsVersionInfo(); + const OSVERSIONINFOEXW info = wxGetWindowsVersionInfo(); s_version.initialized = true;