summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qglobal.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/global/qglobal.cpp')
-rw-r--r--src/corelib/global/qglobal.cpp304
1 files changed, 197 insertions, 107 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index b5bdcedaa1..02220d0db2 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -42,6 +42,7 @@
#include <private/qlocale_tools_p.h>
#include <private/qsystemlibrary_p.h>
+#include <qmutex.h>
#ifndef QT_NO_QOBJECT
#include <private/qthread_p.h>
@@ -64,12 +65,22 @@
# endif
#endif
-#if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL)
-# include <envLib.h>
+#ifdef Q_OS_WINRT
+#include <wrl.h>
+#include <windows.networking.h>
+#include <windows.networking.sockets.h>
+#include <windows.networking.connectivity.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::Networking;
+using namespace ABI::Windows::Networking::Connectivity;
+using namespace ABI::Windows::Networking::Sockets;
#endif
-#if defined(Q_OS_MACX)
-#include <CoreServices/CoreServices.h>
+#if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL)
+# include <envLib.h>
#endif
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
@@ -89,6 +100,10 @@
#include <private/qcore_unix_p.h>
#endif
+#ifdef Q_OS_BSD4
+#include <sys/sysctl.h>
+#endif
+
#include "archdetect.cpp"
QT_BEGIN_NAMESPACE
@@ -105,7 +120,9 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n);
// (if this list becomes too long, consider factoring into a separate file)
Q_STATIC_ASSERT_X(sizeof(int) == 4, "Qt assumes that int is 32 bits");
Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
-
+#ifndef QT_BOOTSTRAPPED
+Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "configure test ptrsize failed to correctly determine QT_POINTER_SIZE");
+#endif
/*!
\class QFlag
@@ -1846,25 +1863,6 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qnamespace.h"
QT_END_INCLUDE_NAMESPACE
-#if defined(Q_OS_OSX)
-
-Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref)
-{
- return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0);
-}
-
-Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1)
-{
- Q_UNUSED(encoding);
- Q_UNUSED(len);
- CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding());
-}
-
-Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) {
- return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding()));
-}
-#endif // defined(Q_OS_OSX)
-
QSysInfo::MacVersion QSysInfo::macVersion()
{
const QAppleOperatingSystemVersion version = qt_apple_os_version(); // qtcore_mac_objc.mm
@@ -1886,91 +1884,99 @@ QT_END_INCLUDE_NAMESPACE
#ifndef Q_OS_WINRT
-# ifndef Q_OS_WINCE
-
-// Determine Windows versions >= 8 by querying the version of kernel32.dll.
-static inline bool determineWinOsVersionPost8(OSVERSIONINFO *result)
+# ifndef QT_BOOTSTRAPPED
+class QWindowsSockInit
{
- typedef WORD (WINAPI* PtrGetFileVersionInfoSizeW)(LPCWSTR, LPDWORD);
- typedef BOOL (WINAPI* PtrVerQueryValueW)(LPCVOID, LPCWSTR, LPVOID, PUINT);
- typedef BOOL (WINAPI* PtrGetFileVersionInfoW)(LPCWSTR, DWORD, DWORD, LPVOID);
+public:
+ QWindowsSockInit();
+ ~QWindowsSockInit();
+ int version;
+};
- QSystemLibrary versionLib(QStringLiteral("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;
+QWindowsSockInit::QWindowsSockInit()
+: version(0)
+{
+ //### should we try for 2.2 on all platforms ??
+ WSAData wsadata;
- 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 = Q_NULLPTR;
- 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;
+ // IPv6 requires Winsock v2.0 or better.
+ if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
+ qWarning("QTcpSocketAPI: WinSock v2.0 initialization failed.");
+ } else {
+ version = 0x20;
+ }
}
-// 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)
+QWindowsSockInit::~QWindowsSockInit()
{
- 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;
+ WSACleanup();
}
+Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit)
+# endif // QT_BOOTSTRAPPED
+
+#endif // !Q_OS_WINRT
-# endif // !Q_OS_WINCE
+#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<HMODULE>(mbi.AllocationBase);
+}
+#endif
static inline OSVERSIONINFO winOsVersion()
{
OSVERSIONINFO result = { sizeof(OSVERSIONINFO), 0, 0, 0, 0, {'\0'}};
+
+#ifndef Q_OS_WINCE
+#define GetProcAddressA GetProcAddress
+#endif
+
+ // 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<LPCVOID>(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<GetModuleHandleFunction>(
+ GetProcAddressA(kernelModule, "GetModuleHandleW"));
+ if (Q_UNLIKELY(!pGetModuleHandle))
+ return result;
+#else
+#define pGetModuleHandle GetModuleHandleW
+#endif
+
+ 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<RtlGetVersionFunction>(
+ 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.
-# if defined(_MSC_VER) && _MSC_VER >= 1800
-# pragma warning( push )
-# pragma warning( disable : 4996 )
-# endif
- GetVersionEx(&result);
-# if defined(_MSC_VER) && _MSC_VER >= 1800
-# pragma warning( pop )
-# endif
-# ifndef Q_OS_WINCE
- if (result.dwMajorVersion == 6 && result.dwMinorVersion == 2) {
- if (!determineWinOsVersionPost8(&result))
- determineWinOsVersionFallbackPost8(&result);
- }
-# endif // !Q_OS_WINCE
+ // only Windows 8 from that version on, so use the kernel API function.
+ pRtlGetVersion(&result); // always returns STATUS_SUCCESS
return result;
}
-#endif // !Q_OS_WINRT
QSysInfo::WinVersion QSysInfo::windowsVersion()
{
@@ -1990,11 +1996,10 @@ QSysInfo::WinVersion QSysInfo::windowsVersion()
static QSysInfo::WinVersion winver;
if (winver)
return winver;
-#ifdef Q_OS_WINRT
- winver = QSysInfo::WV_WINDOWS8_1;
-#else
winver = QSysInfo::WV_NT;
const OSVERSIONINFO osver = winOsVersion();
+ if (osver.dwMajorVersion == 0)
+ return QSysInfo::WV_None;
#ifdef Q_OS_WINCE
DWORD qt_cever = 0;
qt_cever = osver.dwMajorVersion * 100;
@@ -2074,7 +2079,6 @@ QSysInfo::WinVersion QSysInfo::windowsVersion()
}
}
#endif
-#endif // !Q_OS_WINRT
return winver;
}
@@ -2545,10 +2549,7 @@ QString QSysInfo::kernelType()
*/
QString QSysInfo::kernelVersion()
{
-#ifdef Q_OS_WINRT
- // TBD
- return QString();
-#elif defined(Q_OS_WIN)
+#ifdef Q_OS_WIN
const OSVERSIONINFO osver = winOsVersion();
return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion))
+ QLatin1Char('.') + QString::number(int(osver.dwBuildNumber));
@@ -2774,6 +2775,82 @@ QString QSysInfo::prettyProductName()
return unknownText();
}
+#ifndef QT_BOOTSTRAPPED
+/*!
+ \since 5.6
+
+ Returns this machine's host name, if one is configured. Note that hostnames
+ are not guaranteed to be globally unique, especially if they were
+ configured automatically.
+
+ This function does not guarantee the returned host name is a Fully
+ Qualified Domain Name (FQDN). For that, use QHostInfo to resolve the
+ returned name to an FQDN.
+
+ This function returns the same as QHostInfo::localHostName().
+
+ \sa QHostInfo::localDomainName
+ */
+QString QSysInfo::machineHostName()
+{
+#if defined(Q_OS_LINUX)
+ // gethostname(3) on Linux just calls uname(2), so do it ourselves
+ // and avoid a memcpy
+ struct utsname u;
+ if (uname(&u) == 0)
+ return QString::fromLocal8Bit(u.nodename);
+#elif defined(Q_OS_WINRT)
+ ComPtr<INetworkInformationStatics> statics;
+ GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Connectivity_NetworkInformation).Get(), &statics);
+
+ ComPtr<IVectorView<HostName *>> hostNames;
+ statics->GetHostNames(&hostNames);
+ if (!hostNames)
+ return QString();
+
+ unsigned int size;
+ hostNames->get_Size(&size);
+ if (size == 0)
+ return QString();
+
+ for (unsigned int i = 0; i < size; ++i) {
+ ComPtr<IHostName> hostName;
+ hostNames->GetAt(i, &hostName);
+ HostNameType type;
+ hostName->get_Type(&type);
+ if (type != HostNameType_DomainName)
+ continue;
+
+ HString name;
+ hostName->get_CanonicalName(name.GetAddressOf());
+ UINT32 length;
+ PCWSTR rawString = name.GetRawBuffer(&length);
+ return QString::fromWCharArray(rawString, length);
+ }
+ ComPtr<IHostName> firstHost;
+ hostNames->GetAt(0, &firstHost);
+
+ HString name;
+ firstHost->get_CanonicalName(name.GetAddressOf());
+ UINT32 length;
+ PCWSTR rawString = name.GetRawBuffer(&length);
+ return QString::fromWCharArray(rawString, length);
+#else
+# ifdef Q_OS_WIN
+ // Important: QtNetwork depends on machineHostName() initializing ws2_32.dll
+ winsockInit();
+# endif
+
+ char hostName[512];
+ if (gethostname(hostName, sizeof(hostName)) == -1)
+ return QString();
+ hostName[sizeof(hostName) - 1] = '\0';
+ return QString::fromLocal8Bit(hostName);
+#endif
+ return QString();
+}
+#endif // QT_BOOTSTRAPPED
+
/*!
\macro void Q_ASSERT(bool test)
\relates <QtGlobal>
@@ -2885,12 +2962,15 @@ QString QSysInfo::prettyProductName()
\macro void Q_CHECK_PTR(void *pointer)
\relates <QtGlobal>
- If \a pointer is 0, prints a warning message containing the source
+ If \a pointer is 0, prints a message containing the source
code's file name and line number, saying that the program ran out
- of memory.
+ of memory and aborts program execution. It throws \c std::bad_alloc instead
+ if exceptions are enabled.
- Q_CHECK_PTR does nothing if \c QT_NO_DEBUG was defined during
- compilation.
+ Q_CHECK_PTR does nothing if \c QT_NO_DEBUG and \c QT_NO_EXCEPTIONS were
+ defined during compilation. Therefore you must not use Q_CHECK_PTR to check
+ for successful memory allocations because the check will be disabled in
+ some cases.
Example:
@@ -3020,7 +3100,7 @@ namespace {
// depending on the return type
static inline Q_DECL_UNUSED QString fromstrerror_helper(int, const QByteArray &buf)
{
- return QString::fromLocal8Bit(buf);
+ return QString::fromLocal8Bit(buf.constData());
}
static inline Q_DECL_UNUSED QString fromstrerror_helper(const char *str, const QByteArray &)
{
@@ -3098,6 +3178,10 @@ QString qt_error_string(int errorCode)
return ret.trimmed();
}
+// In the C runtime on all platforms access to the environment is not thread-safe. We
+// add thread-safety for the Qt wrappers.
+static QBasicMutex environmentMutex;
+
// getenv is declared as deprecated in VS2005. This function
// makes use of the new secure getenv function.
/*!
@@ -3115,6 +3199,7 @@ QString qt_error_string(int errorCode)
*/
QByteArray qgetenv(const char *varName)
{
+ QMutexLocker locker(&environmentMutex);
#if defined(_MSC_VER) && _MSC_VER >= 1400
size_t requiredSize = 0;
QByteArray buffer;
@@ -3148,6 +3233,7 @@ QByteArray qgetenv(const char *varName)
*/
bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT
{
+ QMutexLocker locker(&environmentMutex);
#if defined(_MSC_VER) && _MSC_VER >= 1400
// we provide a buffer that can only hold the empty string, so
// when the env.var isn't empty, we'll get an ERANGE error (buffer
@@ -3179,6 +3265,7 @@ bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT
*/
int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
{
+ QMutexLocker locker(&environmentMutex);
#if defined(_MSC_VER) && _MSC_VER >= 1400
// we provide a buffer that can hold any int value:
static const int NumBinaryDigitsPerOctalDigit = 3;
@@ -3227,6 +3314,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
*/
bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT
{
+ QMutexLocker locker(&environmentMutex);
#if defined(_MSC_VER) && _MSC_VER >= 1400
size_t requiredSize = 0;
(void)getenv_s(&requiredSize, 0, 0, varName);
@@ -3256,6 +3344,7 @@ bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT
*/
bool qputenv(const char *varName, const QByteArray& value)
{
+ QMutexLocker locker(&environmentMutex);
#if defined(_MSC_VER) && _MSC_VER >= 1400
return _putenv_s(varName, value.constData()) == 0;
#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU)
@@ -3286,6 +3375,7 @@ bool qputenv(const char *varName, const QByteArray& value)
*/
bool qunsetenv(const char *varName)
{
+ QMutexLocker locker(&environmentMutex);
#if defined(_MSC_VER) && _MSC_VER >= 1400
return _putenv_s(varName, "") == 0;
#elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_BSD4) || defined(Q_OS_HAIKU)