From 26b2ad5a181eab7ad04ba819004bcc619c24147b Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Fri, 22 Apr 2016 20:54:51 -0700 Subject: Long live QOperatingSystemVersion! This class provides a "type safe" way to compare and access operating system version numbers. [ChangeLog][Deprecation Notice] QSysInfo::windowsVersion() and QSysInfo::macVersion() are deprecated and are replaced by the newly introduced QOperatingSystemVersion. Change-Id: I52b532de2e068ccf90faaa8342eee90c0a4145de Reviewed-by: Thiago Macieira --- src/corelib/global/global.pri | 6 + src/corelib/global/qglobal.cpp | 225 +++--------- src/corelib/global/qoperatingsystemversion.cpp | 394 +++++++++++++++++++++ src/corelib/global/qoperatingsystemversion.h | 125 +++++++ .../global/qoperatingsystemversion_darwin.mm | 101 ++++++ src/corelib/global/qoperatingsystemversion_p.h | 71 ++++ src/corelib/global/qoperatingsystemversion_win.cpp | 171 +++++++++ src/corelib/kernel/qcore_mac_objc.mm | 54 --- src/corelib/kernel/qcore_mac_p.h | 6 - src/tools/bootstrap/bootstrap.pro | 5 +- 10 files changed, 921 insertions(+), 237 deletions(-) create mode 100644 src/corelib/global/qoperatingsystemversion.cpp create mode 100644 src/corelib/global/qoperatingsystemversion.h create mode 100644 src/corelib/global/qoperatingsystemversion_darwin.mm create mode 100644 src/corelib/global/qoperatingsystemversion_p.h create mode 100644 src/corelib/global/qoperatingsystemversion_win.cpp (limited to 'src') diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 6a8948822c..afcd20a9c1 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -2,6 +2,8 @@ HEADERS += \ global/qglobal.h \ + global/qoperatingsystemversion.h \ + global/qoperatingsystemversion_p.h \ global/qsystemdetection.h \ global/qcompilerdetection.h \ global/qprocessordetection.h \ @@ -27,11 +29,15 @@ SOURCES += \ global/qlibraryinfo.cpp \ global/qmalloc.cpp \ global/qnumeric.cpp \ + global/qoperatingsystemversion.cpp \ global/qlogging.cpp \ global/qhooks.cpp VERSIONTAGGING_SOURCES = global/qversiontagging.cpp +darwin: SOURCES += global/qoperatingsystemversion_darwin.mm +win32: SOURCES += global/qoperatingsystemversion_win.cpp + # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 5687920c9b..692a7531ac 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -45,6 +45,8 @@ #include "qthreadstorage.h" #include "qdir.h" #include "qdatetime.h" +#include "qoperatingsystemversion.h" +#include "qoperatingsystemversion_p.h" #include #include @@ -1939,15 +1941,15 @@ QT_END_INCLUDE_NAMESPACE QSysInfo::MacVersion QSysInfo::macVersion() { - const QAppleOperatingSystemVersion version = qt_apple_os_version(); // qtcore_mac_objc.mm + const auto version = QOperatingSystemVersion::current(); #if defined(Q_OS_OSX) - return QSysInfo::MacVersion(Q_MV_OSX(version.major, version.minor)); + return QSysInfo::MacVersion(Q_MV_OSX(version.majorVersion(), version.minorVersion())); #elif defined(Q_OS_IOS) - return QSysInfo::MacVersion(Q_MV_IOS(version.major, version.minor)); + return QSysInfo::MacVersion(Q_MV_IOS(version.majorVersion(), version.minorVersion())); #elif defined(Q_OS_TVOS) - return QSysInfo::MacVersion(Q_MV_TVOS(version.major, version.minor)); + return QSysInfo::MacVersion(Q_MV_TVOS(version.majorVersion(), version.minorVersion())); #elif defined(Q_OS_WATCHOS) - return QSysInfo::MacVersion(Q_MV_WATCHOS(version.major, version.minor)); + return QSysInfo::MacVersion(Q_MV_WATCHOS(version.majorVersion(), version.minorVersion())); #else return QSysInfo::MV_Unknown; #endif @@ -1955,10 +1957,10 @@ QSysInfo::MacVersion QSysInfo::macVersion() const QSysInfo::MacVersion QSysInfo::MacintoshVersion = QSysInfo::macVersion(); #ifdef Q_OS_OSX -static const char *osxVer_helper(QAppleOperatingSystemVersion version = qt_apple_os_version()) +static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current()) { - if (version.major == 10) { - switch (version.minor) { + if (version.majorVersion() == 10) { + switch (version.minorVersion()) { case 9: return "Mavericks"; case 10: @@ -2010,140 +2012,27 @@ QWindowsSockInit::~QWindowsSockInit() Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit) # endif // QT_BOOTSTRAPPED -#ifdef Q_OS_WINRT -static inline HMODULE moduleHandleForFunction(LPCVOID address) -{ - // This is a widely used, decades-old technique for retrieving the handle - // of a module and is effectively equivalent to GetModuleHandleEx - // (which is unavailable on WinRT) - MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 }; - if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0) - return 0; - return reinterpret_cast(mbi.AllocationBase); -} -#endif - -static inline OSVERSIONINFOEX determineWinOsVersion() -{ - OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0}; - -#define GetProcAddressA GetProcAddress - - // GetModuleHandle is not supported in WinRT and linking to it at load time - // will not pass the Windows App Certification Kit... but it exists and is functional, - // so use some unusual but widely used techniques to get a pointer to it -#ifdef Q_OS_WINRT - // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL - HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast(VirtualQuery)); - if (Q_UNLIKELY(!kernelModule)) - return result; - - // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs) - typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR); - GetModuleHandleFunction pGetModuleHandle = reinterpret_cast( - GetProcAddressA(kernelModule, "GetModuleHandleW")); - if (Q_UNLIKELY(!pGetModuleHandle)) - return result; -#else -#define pGetModuleHandle GetModuleHandleW -#endif - -#ifndef Q_OS_WINCE - HMODULE ntdll = pGetModuleHandle(L"ntdll.dll"); - if (Q_UNLIKELY(!ntdll)) - return result; - - // NTSTATUS is not defined on WinRT - typedef LONG NTSTATUS; - typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO); - - // RtlGetVersion is documented public API but we must load it dynamically - // because linking to it at load time will not pass the Windows App Certification Kit - // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx - RtlGetVersionFunction pRtlGetVersion = reinterpret_cast( - GetProcAddressA(ntdll, "RtlGetVersion")); - if (Q_UNLIKELY(!pRtlGetVersion)) - return result; - - // GetVersionEx() has been deprecated in Windows 8.1 and will return - // only Windows 8 from that version on, so use the kernel API function. - pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS -#else // !Q_OS_WINCE - GetVersionEx(&result); -#endif - return result; -} - -static OSVERSIONINFOEX winOsVersion() -{ - OSVERSIONINFOEX realResult = determineWinOsVersion(); -#ifdef QT_DEBUG - { - if (Q_UNLIKELY(qEnvironmentVariableIsSet("QT_WINVER_OVERRIDE"))) { - OSVERSIONINFOEX result = realResult; - result.dwMajorVersion = 0; - result.dwMinorVersion = 0; - - // Erase any build number and service pack information - result.dwBuildNumber = 0; - result.szCSDVersion[0] = L'\0'; - result.wServicePackMajor = 0; - result.wServicePackMinor = 0; - - const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE"); - if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") { - result.dwMajorVersion = 6; - result.dwMinorVersion = 1; - } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") { - result.dwMajorVersion = 6; - result.dwMinorVersion = 2; - } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") { - result.dwMajorVersion = 6; - result.dwMinorVersion = 3; - } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") { - result.dwMajorVersion = 10; - } else { - return realResult; - } - - if (winVerOverride == "2008_R2" - || winVerOverride == "2012" - || winVerOverride == "2012_R2" - || winVerOverride == "2016") { - // If the current host OS is a domain controller and the override OS - // is also a server type OS, preserve that information - if (result.wProductType == VER_NT_WORKSTATION) - result.wProductType = VER_NT_SERVER; - } else { - // Any other OS must be a workstation OS type - result.wProductType = VER_NT_WORKSTATION; - } - } - } -#endif - return realResult; -} - QSysInfo::WinVersion QSysInfo::windowsVersion() { - const OSVERSIONINFOEX osver = winOsVersion(); - if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1) + const auto version = QOperatingSystemVersion::current(); + if (version.majorVersion() == 6 && version.minorVersion() == 1) return QSysInfo::WV_WINDOWS7; - if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2) + if (version.majorVersion() == 6 && version.minorVersion() == 2) return QSysInfo::WV_WINDOWS8; - if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3) + if (version.majorVersion() == 6 && version.minorVersion() == 3) return QSysInfo::WV_WINDOWS8_1; - if (osver.dwMajorVersion == 10 && osver.dwMinorVersion == 0) + if (version.majorVersion() == 10 && version.minorVersion() == 0) return QSysInfo::WV_WINDOWS10; return QSysInfo::WV_NT_based; } static QString winSp_helper() { - const qint16 major = winOsVersion().wServicePackMajor; + const auto osv = qWindowsVersionInfo(); + const qint16 major = osv.wServicePackMajor; if (major) { QString sp = QStringLiteral(" SP ") + QString::number(major); - const qint16 minor = winOsVersion().wServicePackMinor; + const qint16 minor = osv.wServicePackMinor; if (minor) sp += QLatin1Char('.') + QString::number(minor); @@ -2152,9 +2041,10 @@ static QString winSp_helper() return QString(); } -static const char *winVer_helper() +static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current()) { - const OSVERSIONINFOEX osver = winOsVersion(); + Q_UNUSED(version); + const OSVERSIONINFOEX osver = qWindowsVersionInfo(); const bool workstation = osver.wProductType == VER_NT_WORKSTATION; #define Q_WINVER(major, minor) (major << 8 | minor) @@ -2603,9 +2493,9 @@ QString QSysInfo::kernelType() QString QSysInfo::kernelVersion() { #ifdef Q_OS_WIN - const OSVERSIONINFOEX osver = winOsVersion(); - return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion)) - + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber)); + const auto osver = QOperatingSystemVersion::current(); + return QString::number(osver.majorVersion()) + QLatin1Char('.') + QString::number(osver.minorVersion()) + + QLatin1Char('.') + QString::number(osver.microVersion()); #else struct utsname u; if (uname(&u) == 0) @@ -2673,8 +2563,8 @@ QString QSysInfo::productType() #elif defined(Q_OS_WATCHOS) return QStringLiteral("watchos"); #elif defined(Q_OS_MACOS) - const QAppleOperatingSystemVersion version = qt_apple_os_version(); - if (version.major == 10 && version.minor < 12) + const auto version = QOperatingSystemVersion::current(); + if (version.majorVersion() == 10 && version.minorVersion() < 12) return QStringLiteral("osx"); return QStringLiteral("macos"); #elif defined(Q_OS_DARWIN) @@ -2714,11 +2604,11 @@ QString QSysInfo::productType() */ QString QSysInfo::productVersion() { -#if defined(Q_OS_MAC) - const QAppleOperatingSystemVersion version = qt_apple_os_version(); - return QString::number(version.major) + QLatin1Char('.') + QString::number(version.minor); +#if defined(Q_OS_DARWIN) + const auto version = QOperatingSystemVersion::current(); + return QString::number(version.majorVersion()) + QLatin1Char('.') + QString::number(version.minorVersion()); #elif defined(Q_OS_WIN) - const char *version = winVer_helper(); + const char *version = osVer_helper(); if (version) { const QLatin1Char spaceChar(' '); return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower(); @@ -2755,44 +2645,27 @@ QString QSysInfo::productVersion() */ QString QSysInfo::prettyProductName() { -#if defined(Q_OS_IOS) - return QLatin1String("iOS ") + productVersion(); -#elif defined(Q_OS_TVOS) - return QLatin1String("tvOS ") + productVersion(); -#elif defined(Q_OS_WATCHOS) - return QLatin1String("watchOS ") + productVersion(); -#elif defined(Q_OS_MACOS) - const QAppleOperatingSystemVersion version = qt_apple_os_version(); - const char *name = osxVer_helper(version); - if (name) { - return (version.major == 10 && version.minor < 12 - ? QLatin1String("OS X ") - : QLatin1String("macOS ")) - + QLatin1String(name) - + QLatin1String(" (") + QString::number(version.major) - + QLatin1Char('.') + QString::number(version.minor) - + QLatin1Char(')'); - } else { - return QLatin1String("macOS ") - + QString::number(version.major) + QLatin1Char('.') - + QString::number(version.minor); - } -#elif defined(Q_OS_WINPHONE) - return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper()); -#elif defined(Q_OS_WIN) - const char *name = winVer_helper(); - const OSVERSIONINFOEX osver = winOsVersion(); +#if defined(Q_OS_WINPHONE) + return QLatin1String("Windows Phone ") + QLatin1String(osVer_helper()); +#elif defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN) + const auto version = QOperatingSystemVersion::current(); +# if defined(Q_OS_MACOS) || defined(Q_OS_WIN) + const char *name = osVer_helper(version); if (name) - return QLatin1String("Windows ") + QLatin1String(name) + winSp_helper() - + QLatin1String(" (") + QString::number(osver.dwMajorVersion) - + QLatin1Char('.') + QString::number(osver.dwMinorVersion) + return version.name() + QLatin1Char(' ') + QLatin1String(name) +# if defined(Q_OS_WIN) + + winSp_helper() +# endif + + QLatin1String(" (") + QString::number(version.majorVersion()) + + QLatin1Char('.') + QString::number(version.minorVersion()) + QLatin1Char(')'); - else - return QLatin1String("Windows ") - + QString::number(osver.dwMajorVersion) + QLatin1Char('.') - + QString::number(osver.dwMinorVersion); -#elif defined(Q_OS_ANDROID) - return QLatin1String("Android ") + productVersion(); + else + return version.name() + QLatin1Char(' ') + + QString::number(version.majorVersion()) + QLatin1Char('.') + + QString::number(version.minorVersion()); +# else + return version.name() + QLatin1Char(' ') + productVersion(); +# endif #elif defined(Q_OS_HAIKU) return QLatin1String("Haiku ") + productVersion(); #elif defined(Q_OS_UNIX) diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp new file mode 100644 index 0000000000..14dc109b3e --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion.cpp @@ -0,0 +1,394 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qoperatingsystemversion.h" +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN) +#include "qoperatingsystemversion_p.h" +#endif + +#include + +#if defined(Q_OS_ANDROID) +#include +#endif + +QT_BEGIN_NAMESPACE + +/*! + \class QOperatingSystemVersion + \inmodule QtCore + \since 5.9 + \brief The QOperatingSystemVersion class provides information about the operating system version. + + Unlike other version functions in QSysInfo, QOperatingSystemVersion provides access to the full + version number that \a developers typically use to vary behavior or determine whether to enable + APIs or features based on the operating system version (as opposed to the kernel version number + or marketing version). + + This class is also a complete replacement for QSysInfo::macVersion and QSysInfo::windowsVersion, + additionally providing access to the third (micro) version number component. + + Presently, Android, Apple Platforms (iOS, macOS, tvOS, and watchOS), and Windows are supported. + + The \a majorVersion(), \a minorVersion(), and \a microVersion() functions return the parts of + the operating system version number based on: + + \table + \header \li Platforms \li Value + \row \li Android \li result of parsing + \l{https://developer.android.com/reference/android/os/Build.VERSION.html#RELEASE}{"android.os.Build.VERSION.RELEASE"} + using QVersionNumber, with a fallback to + \l{https://developer.android.com/reference/android/os/Build.VERSION.html#SDK_INT}{"android.os.Build.VERSION.SDK_INT"} + to determine the major and minor version component if the former fails + \row \li Apple Platforms \li majorVersion, minorVersion, and patchVersion from + \l{https://developer.apple.com/reference/foundation/nsprocessinfo/1410906-operatingsystemversion?language=objc}{"NSProcessInfo.operatingSystemVersion"} + \row \li Windows \li dwMajorVersion, dwMinorVersion, and dwBuildNumber from + \l{https://msdn.microsoft.com/en-us/library/mt723418.aspx}{"RtlGetVersion"} - + note that this function ALWAYS return the version number of the underlying operating system, + as opposed to the shim underneath GetVersionEx that hides the real version number + if the application is not manifested for that version of the OS + \endtable +*/ + +/*! + \fn QOperatingSystemVersion::QOperatingSystemVersion(int maj, int min, int mic) + + Constructs a QOperatingSystemVersion consisting of the OS type \a os, and + major, minor, and micro version numbers \a maj, \a min and \a mic, respectively. +*/ + +/*! + \fn QOperatingSystemVersion QOperatingSystemVersion::current() + + Returns a QOperatingSystemVersion indicating the current OS and its version number. +*/ +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN) +QOperatingSystemVersion QOperatingSystemVersion::current() +{ + QOperatingSystemVersion version; + version.m_os = currentType(); +#if defined(Q_OS_ANDROID) +#ifndef QT_BOOTSTRAPPED + const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField( + "android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString()); + if (!v.isNull()) { + version.m_major = v.majorVersion(); + version.m_minor = v.minorVersion(); + version.m_micro = v.microVersion(); + return version; + } +#endif + + version.m_major = -1; + version.m_minor = -1; + + static const int versions[][2] = { + { 1, 0 }, // API level 1 + { 1, 1 }, // API level 2 + { 1, 5 }, // API level 3 + { 1, 6 }, // API level 4 + { 2, 0 }, // API level 5 + { 2, 0 }, // API level 6 + { 2, 1 }, // API level 7 + { 2, 2 }, // API level 8 + { 2, 3 }, // API level 9 + { 2, 3 }, // API level 10 + { 3, 0 }, // API level 11 + { 3, 1 }, // API level 12 + { 3, 2 }, // API level 13 + { 4, 0 }, // API level 14 + { 4, 0 }, // API level 15 + { 4, 1 }, // API level 16 + { 4, 2 }, // API level 17 + { 4, 3 }, // API level 18 + { 4, 4 }, // API level 19 + { 4, 4 }, // API level 20 + { 5, 0 }, // API level 21 + { 5, 1 }, // API level 22 + { 6, 0 }, // API level 23 + { 7, 0 }, // API level 24 + }; + + // This will give us at least the first 2 version components + const int sdk = static_cast(QJNIObjectPrivate::getStaticField("android/os/Build$VERSION", "SDK_INT")); + if (sdk >= 1 && sdk <= sizeof(versions) / sizeof(versions[0])) { + version.m_major = versions[sdk - 1][0]; + version.m_minor = versions[sdk - 1][1]; + } + + // API level 6 was exactly version 2.0.1 + version.m_micro = sdk == 6 ? 1 : -1; +#else + version.m_major = -1; + version.m_minor = -1; + version.m_micro = -1; +#endif + return version; +} +#endif + +static inline int compareVersionComponents(int lhs, int rhs) +{ + return lhs >= 0 && rhs >= 0 ? lhs - rhs : 0; +} + +/*! + \fn int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1, + const QOperatingSystemVersion &v2) + + Compares \a v1 with \a v2 and returns an integer less than, equal to, or + greater than zero, depending on whether \a v1 is less than, equal to, or + greater than \a v2, respectively. + + Comparisons are performed by comparing the version number components of + \a v1 and \a v2. + + \note This function cannot take the OS type into account; you should use + the overloaded comparison operators to compare QOperatingSystemVersions + in a safe manner. +*/ +int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2) +{ + if (v1.m_major == v2.m_major) { + if (v1.m_minor == v2.m_minor) { + return compareVersionComponents(v1.m_micro, v2.m_micro); + } + return compareVersionComponents(v1.m_minor, v2.m_minor); + } + return compareVersionComponents(v1.m_major, v2.m_major); +} + +#ifndef QT_BOOTSTRAPPED +/*! + \fn QOperatingSystemVersion QOperatingSystemVersion::fromVersionNumber(const QVersionNumber &version, + QOperatingSystemVersion::OSType os) + + Returns a QOperatingSystemVersion consisting of the OS type \a os and version number \a version. +*/ +QOperatingSystemVersion QOperatingSystemVersion::fromVersionNumber(const QVersionNumber &version, + QOperatingSystemVersion::OSType os) +{ + return QOperatingSystemVersion(os, version.majorVersion(), version.minorVersion(), version.microVersion()); +} + +/*! + \fn QOperatingSystemVersion QOperatingSystemVersion::toVersionNumber() const + + Returns the QOperatingSystemVersion's version number as a QVersionNumber. +*/ +QVersionNumber QOperatingSystemVersion::toVersionNumber() const +{ + return QVersionNumber(m_major, m_minor, m_micro); +} +#endif + +/*! + \fn int QOperatingSystemVersion::majorVersion() const + + Returns the major version number, that is, the first segment of the operating system's version number. + + See the main class documentation for what the major version number is on a given operating system. + + -1 indicates an unknown or absent version number component. + + \sa minorVersion(), microVersion() +*/ + +/*! + \fn int QOperatingSystemVersion::minorVersion() const + + Returns the minor version number, that is, the second segment of the operating system's version number. + + See the main class documentation for what the minor version number is on a given operating system. + + -1 indicates an unknown or absent version number component. + + \sa majorVersion(), macro() +*/ + +/*! + \fn int QOperatingSystemVersion::microVersion() const + + Returns the micro version number, that is, the third segment of the operating system's version number. + + See the main class documentation for what the micro version number is on a given operating system. + + -1 indicates an unknown or absent version number component. + + \sa majorVersion(), minorVersion() +*/ + +/*! + \fn QOperatingSystemVersion::OSType QOperatingSystemVersion::type() const + + Returns the OS type identified by the QOperatingSystemVersion. + + \sa typeName() +*/ + +/*! + \fn QString QOperatingSystemVersion::name() const + + Returns a string representation of the OS type identified by the QOperatingSystemVersion. + + \sa type() +*/ +QString QOperatingSystemVersion::name() const +{ + switch (type()) { + case QOperatingSystemVersion::Windows: + return QStringLiteral("Windows"); + case QOperatingSystemVersion::MacOS: { + if (majorVersion() < 10) + return QStringLiteral("Mac OS"); + if (majorVersion() == 10 && minorVersion() < 8) + return QStringLiteral("Mac OS X"); + if (majorVersion() == 10 && minorVersion() < 12) + return QStringLiteral("OS X"); + return QStringLiteral("macOS"); + } + case QOperatingSystemVersion::IOS: { + if (majorVersion() < 4) + return QStringLiteral("iPhone OS"); + return QStringLiteral("iOS"); + } + case QOperatingSystemVersion::TvOS: + return QStringLiteral("tvOS"); + case QOperatingSystemVersion::WatchOS: + return QStringLiteral("watchOS"); + case QOperatingSystemVersion::Android: + return QStringLiteral("Android"); + case QOperatingSystemVersion::Unknown: + default: + return QString(); + } +} + +/*! + \variable QOperatingSystemVersion::Windows7 + \brief a version corresponding to Windows 7 (version 6.1). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows7 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 1); + +/*! + \variable QOperatingSystemVersion::Windows8 + \brief a version corresponding to Windows 8 (version 6.2). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows8 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 2); + +/*! + \variable QOperatingSystemVersion::Windows8_1 + \brief a version corresponding to Windows 8.1 (version 6.3). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows8_1 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 3); + +/*! + \variable QOperatingSystemVersion::Windows10 + \brief a version corresponding to Windows 10 (version 10.0). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows10 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10); + +/*! + \variable QOperatingSystemVersion::OSXMavericks + \brief a version corresponding to OS X Mavericks (version 10.9). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXMavericks = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 9); + +/*! + \variable QOperatingSystemVersion::OSXYosemite + \brief a version corresponding to OS X Yosemite (version 10.10). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXYosemite = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 10); + +/*! + \variable QOperatingSystemVersion::OSXElCapitan + \brief a version corresponding to OS X El Capitan (version 10.11). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXElCapitan = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 11); + +/*! + \variable QOperatingSystemVersion::MacOSSierra + \brief a version corresponding to macOS Sierra (version 10.12). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::MacOSSierra = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 12); + +/*! + \variable QOperatingSystemVersion::AndroidJellyBean + \brief a version corresponding to Android Jelly Bean (versions 4.1 - 4.3). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 1); + +/*! + \variable QOperatingSystemVersion::AndroidKitKat + \brief a version corresponding to Android KitKat (version 4.4). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidKitKat = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 4); + +/*! + \variable QOperatingSystemVersion::AndroidLollipop + \brief a version corresponding to Android Lollipop (versions 5.0 - 5.1). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop = QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 0); + +/*! + \variable QOperatingSystemVersion::AndroidMarshmallow + \brief a version corresponding to Android Marshmallow (version 6.0). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidMarshmallow = QOperatingSystemVersion(QOperatingSystemVersion::Android, 6); + +/*! + \variable QOperatingSystemVersion::AndroidNougat + \brief a version corresponding to Android Nougat (version 7.0). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat = QOperatingSystemVersion(QOperatingSystemVersion::Android, 7); + +QT_END_NAMESPACE diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h new file mode 100644 index 0000000000..33c3d33bcc --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifndef QOPERATINGSYSTEMVERSION_H +#define QOPERATINGSYSTEMVERSION_H + +QT_BEGIN_NAMESPACE + +class QString; +class QVersionNumber; + +class Q_CORE_EXPORT QOperatingSystemVersion +{ +public: + enum OSType { + Unknown = 0, + Windows, + MacOS, + IOS, + TvOS, + WatchOS, + Android + }; + + static const QOperatingSystemVersion Windows7; + static const QOperatingSystemVersion Windows8; + static const QOperatingSystemVersion Windows8_1; + static const QOperatingSystemVersion Windows10; + + static const QOperatingSystemVersion OSXMavericks; + static const QOperatingSystemVersion OSXYosemite; + static const QOperatingSystemVersion OSXElCapitan; + static const QOperatingSystemVersion MacOSSierra; + + static const QOperatingSystemVersion AndroidJellyBean; + static const QOperatingSystemVersion AndroidKitKat; + static const QOperatingSystemVersion AndroidLollipop; + static const QOperatingSystemVersion AndroidMarshmallow; + static const QOperatingSystemVersion AndroidNougat; + + QOperatingSystemVersion(const QOperatingSystemVersion &other) = default; + Q_DECL_CONSTEXPR QOperatingSystemVersion(OSType osType, int vmajor, int vminor = -1, int vmicro = -1) + : m_os(osType), m_major(vmajor), m_minor(vminor), m_micro(vmicro) { } + + static QOperatingSystemVersion current(); + + static int compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2); + + QOperatingSystemVersion fromVersionNumber(const QVersionNumber &version, OSType os); + QVersionNumber toVersionNumber() const; + + Q_DECL_CONSTEXPR int majorVersion() const { return m_major; } + Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; } + Q_DECL_CONSTEXPR int microVersion() const { return m_micro; } + + Q_DECL_CONSTEXPR OSType type() const { return m_os; } + QString name() const; + +private: + QOperatingSystemVersion() = default; + OSType m_os; + int m_major; + int m_minor; + int m_micro; +}; + +inline bool operator>(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) > 0; } + +inline bool operator>=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) >= 0; } + +inline bool operator<(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) < 0; } + +inline bool operator<=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) <= 0; } + +inline bool operator==(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) == 0; } + +inline bool operator!=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return !(lhs == rhs); } + +QT_END_NAMESPACE + +#endif // QOPERATINGSYSTEMVERSION_H diff --git a/src/corelib/global/qoperatingsystemversion_darwin.mm b/src/corelib/global/qoperatingsystemversion_darwin.mm new file mode 100644 index 0000000000..3dd007cbb3 --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion_darwin.mm @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qoperatingsystemversion_p.h" +#import + +#ifdef Q_OS_IOS +#import +#endif + +QT_BEGIN_NAMESPACE + +typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response); + +QOperatingSystemVersion QOperatingSystemVersion::current() +{ + QOperatingSystemVersion v; + v.m_os = currentType(); + v.m_major = -1; + v.m_minor = -1; + v.m_micro = -1; +#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_8_0) || defined(Q_OS_TVOS) || defined(Q_OS_WATCHOS) + if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) { + NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion; + v.m_major = osv.majorVersion; + v.m_minor = osv.minorVersion; + v.m_micro = osv.patchVersion; + return v; + } +#endif + // Use temporary variables so we can return 0.0.0 (unknown version) + // in case of an error partway through determining the OS version + qint32 major = 0, minor = 0, patch = 0; +#if QT_MACOS_IOS_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0) +#if defined(Q_OS_IOS) + @autoreleasepool { + NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."]; + major = parts.count > 0 ? [[parts objectAtIndex:0] intValue] : 0; + minor = parts.count > 1 ? [[parts objectAtIndex:1] intValue] : 0; + patch = parts.count > 2 ? [[parts objectAtIndex:2] intValue] : 0; + } +#elif defined(Q_OS_MACOS) + static GestaltFunction pGestalt = 0; + if (!pGestalt) { + CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices")); + pGestalt = reinterpret_cast(CFBundleGetFunctionPointerForName(b, + CFSTR("Gestalt"))); + } + if (!pGestalt) + return v; + if (pGestalt('sys1', &major) != 0) + return v; + if (pGestalt('sys2', &minor) != 0) + return v; + if (pGestalt('sys3', &patch) != 0) + return v; +#endif +#endif + v.m_major = major; + v.m_minor = minor; + v.m_micro = patch; + return v; +} + +QT_END_NAMESPACE diff --git a/src/corelib/global/qoperatingsystemversion_p.h b/src/corelib/global/qoperatingsystemversion_p.h new file mode 100644 index 0000000000..f227e98dd1 --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qoperatingsystemversion.h" + +#ifdef Q_OS_WIN +#include +#endif + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_WIN +OSVERSIONINFOEX qWindowsVersionInfo(); +#endif + +static inline QOperatingSystemVersion::OSType currentType() +{ +#if defined(Q_OS_WIN) + return QOperatingSystemVersion::Windows; +#elif defined(Q_OS_MACOS) + return QOperatingSystemVersion::MacOS; +#elif defined(Q_OS_IOS) + return QOperatingSystemVersion::IOS; +#elif defined(Q_OS_TVOS) + return QOperatingSystemVersion::TvOS; +#elif defined(Q_OS_WATCHOS) + return QOperatingSystemVersion::WatchOS; +#elif defined(Q_OS_ANDROID) + return QOperatingSystemVersion::Android; +#else + return QOperatingSystemVersion::Unknown; +#endif +} + +QT_END_NAMESPACE diff --git a/src/corelib/global/qoperatingsystemversion_win.cpp b/src/corelib/global/qoperatingsystemversion_win.cpp new file mode 100644 index 0000000000..060ca2f7da --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion_win.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qoperatingsystemversion_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_WINRT +static inline HMODULE moduleHandleForFunction(LPCVOID address) +{ + // This is a widely used, decades-old technique for retrieving the handle + // of a module and is effectively equivalent to GetModuleHandleEx + // (which is unavailable on WinRT) + MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 }; + if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0) + return 0; + return reinterpret_cast(mbi.AllocationBase); +} +#endif + +static inline OSVERSIONINFOEX determineWinOsVersion() +{ + OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0}; + +#define GetProcAddressA GetProcAddress + + // GetModuleHandle is not supported in WinRT and linking to it at load time + // will not pass the Windows App Certification Kit... but it exists and is functional, + // so use some unusual but widely used techniques to get a pointer to it +#ifdef Q_OS_WINRT + // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL + HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast(VirtualQuery)); + if (Q_UNLIKELY(!kernelModule)) + return result; + + // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs) + typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR); + GetModuleHandleFunction pGetModuleHandle = reinterpret_cast( + GetProcAddressA(kernelModule, "GetModuleHandleW")); + if (Q_UNLIKELY(!pGetModuleHandle)) + return result; +#else +#define pGetModuleHandle GetModuleHandleW +#endif + +#ifndef Q_OS_WINCE + HMODULE ntdll = pGetModuleHandle(L"ntdll.dll"); + if (Q_UNLIKELY(!ntdll)) + return result; + + // NTSTATUS is not defined on WinRT + typedef LONG NTSTATUS; + typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO); + + // RtlGetVersion is documented public API but we must load it dynamically + // because linking to it at load time will not pass the Windows App Certification Kit + // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx + RtlGetVersionFunction pRtlGetVersion = reinterpret_cast( + GetProcAddressA(ntdll, "RtlGetVersion")); + if (Q_UNLIKELY(!pRtlGetVersion)) + return result; + + // GetVersionEx() has been deprecated in Windows 8.1 and will return + // only Windows 8 from that version on, so use the kernel API function. + pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS +#else // !Q_OS_WINCE + GetVersionEx(&result); +#endif + return result; +} + +OSVERSIONINFOEX qWindowsVersionInfo() +{ + OSVERSIONINFOEX realResult = determineWinOsVersion(); +#ifdef QT_DEBUG + { + if (Q_UNLIKELY(qEnvironmentVariableIsSet("QT_WINVER_OVERRIDE"))) { + OSVERSIONINFOEX result = realResult; + result.dwMajorVersion = 0; + result.dwMinorVersion = 0; + + // Erase any build number and service pack information + result.dwBuildNumber = 0; + result.szCSDVersion[0] = L'\0'; + result.wServicePackMajor = 0; + result.wServicePackMinor = 0; + + const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE"); + if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") { + result.dwMajorVersion = 6; + result.dwMinorVersion = 1; + } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") { + result.dwMajorVersion = 6; + result.dwMinorVersion = 2; + } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") { + result.dwMajorVersion = 6; + result.dwMinorVersion = 3; + } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") { + result.dwMajorVersion = 10; + } else { + return realResult; + } + + if (winVerOverride == "2008_R2" + || winVerOverride == "2012" + || winVerOverride == "2012_R2" + || winVerOverride == "2016") { + // If the current host OS is a domain controller and the override OS + // is also a server type OS, preserve that information + if (result.wProductType == VER_NT_WORKSTATION) + result.wProductType = VER_NT_SERVER; + } else { + // Any other OS must be a workstation OS type + result.wProductType = VER_NT_WORKSTATION; + } + } + } +#endif + return realResult; +} + +QOperatingSystemVersion QOperatingSystemVersion::current() +{ + QOperatingSystemVersion v; + v.m_os = currentType(); + const OSVERSIONINFOEX osv = qWindowsVersionInfo(); + v.m_major = osv.dwMajorVersion; + v.m_minor = osv.dwMinorVersion; + v.m_micro = osv.dwBuildNumber; + return v; +} + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index ee1a290386..42f5699928 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -47,14 +47,8 @@ #include -#if defined(Q_OS_IOS) -#import -#endif - QT_BEGIN_NAMESPACE -typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response); - NSString *QCFString::toNSString(const QString &string) { // The const cast below is safe: CfStringRef is immutable and so is NSString. @@ -98,54 +92,6 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY // ------------------------------------------------------------------------- -QAppleOperatingSystemVersion qt_apple_os_version() -{ - QAppleOperatingSystemVersion v = {0, 0, 0}; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_8_0) || defined(Q_OS_TVOS) || defined(Q_OS_WATCHOS) - if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) { - NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion; - v.major = osv.majorVersion; - v.minor = osv.minorVersion; - v.patch = osv.patchVersion; - return v; - } -#endif - // Use temporary variables so we can return 0.0.0 (unknown version) - // in case of an error partway through determining the OS version - qint32 major = 0, minor = 0, patch = 0; -#if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0) -#if defined(Q_OS_IOS) - @autoreleasepool { - NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."]; - major = parts.count > 0 ? [[parts objectAtIndex:0] intValue] : 0; - minor = parts.count > 1 ? [[parts objectAtIndex:1] intValue] : 0; - patch = parts.count > 2 ? [[parts objectAtIndex:2] intValue] : 0; - } -#elif defined(Q_OS_OSX) - static GestaltFunction pGestalt = 0; - if (!pGestalt) { - CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices")); - pGestalt = reinterpret_cast(CFBundleGetFunctionPointerForName(b, - CFSTR("Gestalt"))); - } - if (!pGestalt) - return v; - if (pGestalt('sys1', &major) != 0) - return v; - if (pGestalt('sys2', &minor) != 0) - return v; - if (pGestalt('sys3', &patch) != 0) - return v; -#endif -#endif - v.major = major; - v.minor = minor; - v.patch = patch; - return v; -} - -// ------------------------------------------------------------------------- - QMacAutoReleasePool::QMacAutoReleasePool() : pool([[NSAutoreleasePool alloc] init]) { diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 63e1cb48dc..8a710a8a1f 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -137,12 +137,6 @@ private: QString string; }; -typedef struct { - int major, minor, patch; -} QAppleOperatingSystemVersion; - -QAppleOperatingSystemVersion qt_apple_os_version(); - #ifdef Q_OS_OSX Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key); Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 8a1e1fd6e3..68b6b28945 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -40,6 +40,7 @@ SOURCES += \ ../../corelib/global/qlogging.cpp \ ../../corelib/global/qmalloc.cpp \ ../../corelib/global/qnumeric.cpp \ + ../../corelib/global/qoperatingsystemversion.cpp \ ../../corelib/io/qabstractfileengine.cpp \ ../../corelib/io/qbuffer.cpp \ ../../corelib/io/qdatastream.cpp \ @@ -108,7 +109,8 @@ unix:SOURCES += ../../corelib/io/qfilesystemengine_unix.cpp \ ../../corelib/io/qfilesystemiterator_unix.cpp \ ../../corelib/io/qfsfileengine_unix.cpp -win32:SOURCES += ../../corelib/io/qfilesystemengine_win.cpp \ +win32:SOURCES += ../../corelib/global/qoperatingsystemversion_win.cpp \ + ../../corelib/io/qfilesystemengine_win.cpp \ ../../corelib/io/qfilesystemiterator_win.cpp \ ../../corelib/io/qfsfileengine_win.cpp \ ../../corelib/kernel/qcoreapplication_win.cpp \ @@ -119,6 +121,7 @@ mac { ../../corelib/kernel/qcoreapplication_mac.cpp \ ../../corelib/kernel/qcore_mac.cpp OBJECTIVE_SOURCES += \ + ../../corelib/global/qoperatingsystemversion_darwin.mm \ ../../corelib/kernel/qcore_mac_objc.mm \ ../../corelib/kernel/qcore_foundation.mm -- cgit v1.2.3