summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/global/qglobal.cpp29
-rw-r--r--src/corelib/io/qsettings_win.cpp2
-rw-r--r--src/corelib/kernel/kernel.pri6
-rw-r--r--src/corelib/kernel/qwinregistry.cpp120
-rw-r--r--src/corelib/kernel/qwinregistry_p.h89
-rw-r--r--src/corelib/time/qtimezoneprivate_win.cpp81
6 files changed, 253 insertions, 74 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 17aab17fe4..6ae5bf299a 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -47,12 +47,11 @@
#include "qoperatingsystemversion.h"
#include "qoperatingsystemversion_p.h"
#if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) || defined(Q_OS_WINRT)
-#include "qoperatingsystemversion_win_p.h"
-# if QT_CONFIG(settings)
-# include "qsettings.h"
-# include "qvariant.h"
+# include "qoperatingsystemversion_win_p.h"
+# ifndef Q_OS_WINRT
+# include "private/qwinregistry_p.h"
# endif
-#endif
+#endif // Q_OS_WIN || Q_OS_CYGWIN
#include <private/qlocale_tools_p.h>
#include <qmutex.h>
@@ -2190,28 +2189,25 @@ const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion()
QT_WARNING_POP
#endif
-static QString readRegistryString(const QString &key, const QString &subKey)
+static QString readVersionRegistryString(const wchar_t *subKey)
{
-#if QT_CONFIG(settings)
- QSettings settings(key, QSettings::NativeFormat);
- return settings.value(subKey).toString();
+#if !defined(QT_BUILD_QMAKE) && !defined(Q_OS_WINRT)
+ return QWinRegistryKey(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)")
+ .stringValue(subKey);
#else
- Q_UNUSED(key);
- Q_UNUSED(subKey);
- return QString();
+ Q_UNUSED(subKey);
+ return QString();
#endif
}
-static inline QString windowsVersionKey() { return QStringLiteral(R"(HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion)"); }
-
static inline QString windows10ReleaseId()
{
- return readRegistryString(windowsVersionKey(), QStringLiteral("ReleaseId"));
+ return readVersionRegistryString(L"ReleaseId");
}
static inline QString windows7Build()
{
- return readRegistryString(windowsVersionKey(), QStringLiteral("CurrentBuild"));
+ return readVersionRegistryString(L"CurrentBuild");
}
static QString winSp_helper()
@@ -3078,6 +3074,7 @@ QByteArray QSysInfo::machineUniqueId()
}
#elif defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
// Let's poke at the registry
+ // ### Qt 6: Use new helpers from qwinregistry.cpp (once bootstrap builds are obsolete)
HKEY key = NULL;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ | KEY_WOW64_64KEY, &key)
== ERROR_SUCCESS) {
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index 679212ea21..6eb318006e 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -136,6 +136,8 @@ static void mergeKeySets(NameSet *dest, const QStringList &src)
** Wrappers for the insane windows registry API
*/
+// ### Qt 6: Use new helpers from qwinregistry.cpp (once bootstrap builds are obsolete)
+
// Open a key with the specified "perms".
// "access" is to explicitly use the 32- or 64-bit branch.
static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey, REGSAM access = 0)
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 789bcb7927..bd3cabc01a 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -88,8 +88,10 @@ win32 {
SOURCES += kernel/qeventdispatcher_winrt.cpp
HEADERS += kernel/qeventdispatcher_winrt_p.h
} else {
- SOURCES += kernel/qeventdispatcher_win.cpp
- HEADERS += kernel/qeventdispatcher_win_p.h
+ SOURCES += kernel/qeventdispatcher_win.cpp \
+ kernel/qwinregistry.cpp
+ HEADERS += kernel/qeventdispatcher_win_p.h \
+ kernel/qwinregistry_p.h
}
!winrt: LIBS_PRIVATE += -lversion
diff --git a/src/corelib/kernel/qwinregistry.cpp b/src/corelib/kernel/qwinregistry.cpp
new file mode 100644
index 0000000000..6566dd3c76
--- /dev/null
+++ b/src/corelib/kernel/qwinregistry.cpp
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 "qwinregistry_p.h"
+
+#include <QtCore/qvarlengtharray.h>
+
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+QWinRegistryKey::QWinRegistryKey() :
+ m_key(nullptr)
+{
+}
+
+// Open a key with the specified permissions (KEY_READ/KEY_WRITE).
+// "access" is to explicitly use the 32- or 64-bit branch.
+QWinRegistryKey::QWinRegistryKey(HKEY parentHandle, QStringView subKey,
+ REGSAM permissions, REGSAM access)
+{
+ if (RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(subKey.utf16()),
+ 0, permissions | access, &m_key) != ERROR_SUCCESS) {
+ m_key = nullptr;
+ }
+}
+
+QWinRegistryKey::~QWinRegistryKey()
+{
+ close();
+}
+
+void QWinRegistryKey::close()
+{
+ if (isValid()) {
+ RegCloseKey(m_key);
+ m_key = nullptr;
+ }
+}
+
+QString QWinRegistryKey::stringValue(QStringView subKey) const
+{
+ QString result;
+ if (!isValid())
+ return result;
+ DWORD type;
+ DWORD size;
+ auto subKeyC = reinterpret_cast<const wchar_t *>(subKey.utf16());
+ if (RegQueryValueEx(m_key, subKeyC, nullptr, &type, nullptr, &size) != ERROR_SUCCESS
+ || (type != REG_SZ && type != REG_EXPAND_SZ) || size <= 2) {
+ return result;
+ }
+ // Reserve more for rare cases where trailing '\0' are missing in registry,
+ // otherwise chop off the '\0' received.
+ QString buffer(int(size / sizeof(wchar_t)), Qt::Uninitialized);
+ if (RegQueryValueEx(m_key, subKeyC, nullptr, &type,
+ reinterpret_cast<LPBYTE>(buffer.data()), &size) == ERROR_SUCCESS) {
+ if (buffer.endsWith(QChar::Null))
+ buffer.chop(1);
+ } else {
+ buffer.clear();
+ }
+ return buffer;
+}
+
+QPair<DWORD, bool> QWinRegistryKey::dwordValue(QStringView subKey) const
+{
+ if (!isValid())
+ return qMakePair(0, false);
+ DWORD type;
+ auto subKeyC = reinterpret_cast<const wchar_t *>(subKey.utf16());
+ if (RegQueryValueEx(m_key, subKeyC, nullptr, &type, nullptr, nullptr) != ERROR_SUCCESS
+ || type != REG_DWORD) {
+ return qMakePair(0, false);
+ }
+ DWORD value = 0;
+ DWORD size = sizeof(value);
+ const bool ok =
+ RegQueryValueEx(m_key, subKeyC, nullptr, nullptr,
+ reinterpret_cast<unsigned char *>(&value), &size) == ERROR_SUCCESS;
+ return qMakePair(value, ok);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qwinregistry_p.h b/src/corelib/kernel/qwinregistry_p.h
new file mode 100644
index 0000000000..d249a97988
--- /dev/null
+++ b/src/corelib/kernel/qwinregistry_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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$
+**
+****************************************************************************/
+
+#ifndef QWINREGISTRY_H
+#define QWINREGISTRY_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qpair.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringview.h>
+#include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QWinRegistryKey
+{
+public:
+ Q_DISABLE_COPY(QWinRegistryKey)
+
+ QWinRegistryKey();
+ explicit QWinRegistryKey(HKEY parentHandle, QStringView subKey,
+ REGSAM permissions = KEY_READ, REGSAM access = 0);
+ ~QWinRegistryKey();
+
+ QWinRegistryKey(QWinRegistryKey &&other) noexcept { swap(other); }
+ QWinRegistryKey &operator=(QWinRegistryKey &&other) noexcept { swap(other); return *this; }
+
+ void swap(QWinRegistryKey &other) noexcept { qSwap(m_key, other.m_key); }
+
+ bool isValid() const { return m_key != nullptr; }
+ operator HKEY() const { return m_key; }
+ void close();
+
+ QString stringValue(QStringView subKey) const;
+ QPair<DWORD, bool> dwordValue(QStringView subKey) const;
+
+private:
+ HKEY m_key;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINREGISTRY_H
diff --git a/src/corelib/time/qtimezoneprivate_win.cpp b/src/corelib/time/qtimezoneprivate_win.cpp
index 5a480222e0..0fec5355b2 100644
--- a/src/corelib/time/qtimezoneprivate_win.cpp
+++ b/src/corelib/time/qtimezoneprivate_win.cpp
@@ -46,13 +46,14 @@
#include <algorithm>
-QT_BEGIN_NAMESPACE
-
#ifndef Q_OS_WINRT
+#include <private/qwinregistry_p.h>
// The registry-based timezone backend is not available on WinRT, which falls back to equivalent APIs.
#define QT_USE_REGISTRY_TIMEZONE 1
#endif
+QT_BEGIN_NAMESPACE
+
/*
Private
@@ -71,8 +72,8 @@ QT_BEGIN_NAMESPACE
// Vista introduced support for historic data, see MSDN docs on DYNAMIC_TIME_ZONE_INFORMATION
// http://msdn.microsoft.com/en-gb/library/windows/desktop/ms724253%28v=vs.85%29.aspx
#ifdef QT_USE_REGISTRY_TIMEZONE
-static const char tzRegPath[] = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
-static const char currTzRegPath[] = "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation";
+static const wchar_t tzRegPath[] = LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones)";
+static const wchar_t currTzRegPath[] = LR"(SYSTEM\CurrentControlSet\Control\TimeZoneInformation)";
#endif
enum {
@@ -138,27 +139,6 @@ bool equalTzi(const TIME_ZONE_INFORMATION &tzi1, const TIME_ZONE_INFORMATION &tz
}
#ifdef QT_USE_REGISTRY_TIMEZONE
-bool openRegistryKey(const QString &keyPath, HKEY *key)
-{
- return RegOpenKeyEx(HKEY_LOCAL_MACHINE, reinterpret_cast<const wchar_t*>(keyPath.utf16()),
- 0, KEY_READ, key) == ERROR_SUCCESS;
-}
-
-QString readRegistryString(const HKEY &key, const wchar_t *value)
-{
- wchar_t buffer[MAX_PATH] = {0};
- DWORD size = sizeof(wchar_t) * MAX_PATH;
- RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast<LPBYTE>(buffer), &size);
- return QString::fromWCharArray(buffer);
-}
-
-int readRegistryValue(const HKEY &key, const wchar_t *value)
-{
- DWORD buffer;
- DWORD size = sizeof(buffer);
- RegQueryValueEx(key, value, nullptr, nullptr, reinterpret_cast<LPBYTE>(&buffer), &size);
- return buffer;
-}
QWinTimeZonePrivate::QWinTransitionRule readRegistryRule(const HKEY &key,
const wchar_t *value, bool *ok)
@@ -185,12 +165,11 @@ TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *ok)
TIME_ZONE_INFORMATION tzi;
REG_TZI_FORMAT regTzi;
DWORD regTziSize = sizeof(regTzi);
- HKEY key = NULL;
- const QString tziKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\')
+ const QString tziKeyPath = QString::fromWCharArray(tzRegPath) + QLatin1Char('\\')
+ QString::fromUtf8(windowsId);
- if (openRegistryKey(tziKeyPath, &key)) {
-
+ QWinRegistryKey key(HKEY_LOCAL_MACHINE, tziKeyPath);
+ if (key.isValid()) {
DWORD size = sizeof(tzi.DaylightName);
RegQueryValueEx(key, L"Dlt", nullptr, nullptr, reinterpret_cast<LPBYTE>(tzi.DaylightName), &size);
@@ -206,8 +185,6 @@ TIME_ZONE_INFORMATION getRegistryTzi(const QByteArray &windowsId, bool *ok)
tzi.DaylightDate = regTzi.DaylightDate;
*ok = true;
}
-
- RegCloseKey(key);
}
return tzi;
@@ -299,8 +276,8 @@ QList<QByteArray> availableWindowsIds()
#ifdef QT_USE_REGISTRY_TIMEZONE
// TODO Consider caching results in a global static, very unlikely to change.
QList<QByteArray> list;
- HKEY key = NULL;
- if (openRegistryKey(QString::fromUtf8(tzRegPath), &key)) {
+ QWinRegistryKey key(HKEY_LOCAL_MACHINE, tzRegPath);
+ if (key.isValid()) {
DWORD idCount = 0;
if (RegQueryInfoKey(key, 0, 0, 0, &idCount, 0, 0, 0, 0, 0, 0, 0) == ERROR_SUCCESS
&& idCount > 0) {
@@ -311,7 +288,6 @@ QList<QByteArray> availableWindowsIds()
list.append(QString::fromWCharArray(buffer).toUtf8());
}
}
- RegCloseKey(key);
}
return list;
#else // QT_USE_REGISTRY_TIMEZONE
@@ -325,15 +301,10 @@ QByteArray windowsSystemZoneId()
{
#ifdef QT_USE_REGISTRY_TIMEZONE
// On Vista and later is held in the value TimeZoneKeyName in key currTzRegPath
- QString id;
- HKEY key = NULL;
- QString tziKeyPath = QString::fromUtf8(currTzRegPath);
- if (openRegistryKey(tziKeyPath, &key)) {
- id = readRegistryString(key, L"TimeZoneKeyName");
- RegCloseKey(key);
- if (!id.isEmpty())
- return std::move(id).toUtf8();
- }
+ const QString id = QWinRegistryKey(HKEY_LOCAL_MACHINE, currTzRegPath)
+ .stringValue(L"TimeZoneKeyName");
+ if (!id.isEmpty())
+ return id.toUtf8();
// On XP we have to iterate over the zones until we find a match on
// names/offsets with the current data
@@ -575,22 +546,22 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
if (!m_windowsId.isEmpty()) {
#ifdef QT_USE_REGISTRY_TIMEZONE
// Open the base TZI for the time zone
- HKEY baseKey = NULL;
- const QString baseKeyPath = QString::fromUtf8(tzRegPath) + QLatin1Char('\\')
+ const QString baseKeyPath = QString::fromWCharArray(tzRegPath) + QLatin1Char('\\')
+ QString::fromUtf8(m_windowsId);
- if (openRegistryKey(baseKeyPath, &baseKey)) {
+ QWinRegistryKey baseKey(HKEY_LOCAL_MACHINE, baseKeyPath);
+ if (baseKey.isValid()) {
// Load the localized names
- m_displayName = readRegistryString(baseKey, L"Display");
- m_standardName = readRegistryString(baseKey, L"Std");
- m_daylightName = readRegistryString(baseKey, L"Dlt");
+ m_displayName = baseKey.stringValue(L"Display");
+ m_standardName = baseKey.stringValue(L"Std");
+ m_daylightName = baseKey.stringValue(L"Dlt");
// On Vista and later the optional dynamic key holds historic data
const QString dynamicKeyPath = baseKeyPath + QLatin1String("\\Dynamic DST");
- HKEY dynamicKey = NULL;
- if (openRegistryKey(dynamicKeyPath, &dynamicKey)) {
+ QWinRegistryKey dynamicKey(HKEY_LOCAL_MACHINE, dynamicKeyPath);
+ if (dynamicKey.isValid()) {
// Find out the start and end years stored, then iterate over them
- int startYear = readRegistryValue(dynamicKey, L"FirstEntry");
- int endYear = readRegistryValue(dynamicKey, L"LastEntry");
- for (int year = startYear; year <= endYear; ++year) {
+ const auto startYear = dynamicKey.dwordValue(L"FirstEntry");
+ const auto endYear = dynamicKey.dwordValue(L"LastEntry");
+ for (int year = int(startYear.first); year <= int(endYear.first); ++year) {
bool ruleOk;
QWinTransitionRule rule = readRegistryRule(dynamicKey,
reinterpret_cast<LPCWSTR>(QString::number(year).utf16()),
@@ -611,7 +582,6 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
m_tranRules.append(rule);
}
}
- RegCloseKey(dynamicKey);
} else {
// No dynamic data so use the base data
bool ruleOk;
@@ -620,7 +590,6 @@ void QWinTimeZonePrivate::init(const QByteArray &ianaId)
if (ruleOk)
m_tranRules.append(rule);
}
- RegCloseKey(baseKey);
}
#else // QT_USE_REGISTRY_TIMEZONE
if (gTimeZones->isEmpty())