From 05a829f923a88e69b2ceaa372820a2dcb8c083cd Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Sep 2019 13:36:38 +0200 Subject: Win32: Consolidate registry code Add a RAII class for registry keys and use it throughout the code base. Change-Id: I666b2fbb790f83436443101d6bc1e3c0525e78df Reviewed-by: Volker Hilsheimer --- src/corelib/global/qglobal.cpp | 29 +++-- src/corelib/io/qsettings_win.cpp | 2 + src/corelib/kernel/kernel.pri | 6 +- src/corelib/kernel/qwinregistry.cpp | 120 +++++++++++++++++++++ src/corelib/kernel/qwinregistry_p.h | 89 +++++++++++++++ src/corelib/time/qtimezoneprivate_win.cpp | 81 +++++--------- .../fontdatabases/windows/qwindowsfontdatabase.cpp | 52 +-------- .../fontdatabases/windows/qwindowsfontdatabase_p.h | 2 - .../windows/qwindowsfontenginedirectwrite.cpp | 7 +- src/plugins/platforms/windows/qwindowscontext.cpp | 26 ++--- src/plugins/platforms/windows/qwindowsservices.cpp | 27 ++--- src/tools/bootstrap/bootstrap.pro | 1 + 12 files changed, 276 insertions(+), 166 deletions(-) create mode 100644 src/corelib/kernel/qwinregistry.cpp create mode 100644 src/corelib/kernel/qwinregistry_p.h (limited to 'src') 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 #include @@ -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 + +#include + +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(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(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(buffer.data()), &size) == ERROR_SUCCESS) { + if (buffer.endsWith(QChar::Null)) + buffer.chop(1); + } else { + buffer.clear(); + } + return buffer; +} + +QPair QWinRegistryKey::dwordValue(QStringView subKey) const +{ + if (!isValid()) + return qMakePair(0, false); + DWORD type; + auto subKeyC = reinterpret_cast(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(&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 +#include +#include +#include + +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 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 -QT_BEGIN_NAMESPACE - #ifndef Q_OS_WINRT +#include // 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(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(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(&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(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 availableWindowsIds() #ifdef QT_USE_REGISTRY_TIMEZONE // TODO Consider caching results in a global static, very unlikely to change. QList 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 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(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()) diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index 79f7eb3d43..011476cf13 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include @@ -1210,33 +1211,8 @@ static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TE void QWindowsFontDatabase::addDefaultEUDCFont() { - QString path; - { - HKEY key; - if (RegOpenKeyEx(HKEY_CURRENT_USER, - L"EUDC\\1252", - 0, - KEY_READ, - &key) != ERROR_SUCCESS) { - return; - } - - WCHAR value[MAX_PATH]; - DWORD bufferSize = sizeof(value); - ZeroMemory(value, bufferSize); - - if (RegQueryValueEx(key, - L"SystemDefaultEUDCFont", - nullptr, - nullptr, - reinterpret_cast(value), - &bufferSize) == ERROR_SUCCESS) { - path = QString::fromWCharArray(value); - } - - RegCloseKey(key); - } - + const QString path = QWinRegistryKey(HKEY_CURRENT_USER, LR"(EUDC\1252)") + .stringValue(L"SystemDefaultEUDCFont"); if (!path.isEmpty()) { QFile file(path); if (!file.open(QIODevice::ReadOnly)) { @@ -2105,28 +2081,6 @@ int QWindowsFontDatabase::defaultVerticalDPI() return vDPI; } -QString QWindowsFontDatabase::readRegistryString(HKEY parentHandle, const wchar_t *keyPath, const wchar_t *keyName) -{ - QString result; - HKEY handle = 0; - if (RegOpenKeyEx(parentHandle, keyPath, 0, KEY_READ, &handle) == ERROR_SUCCESS) { - // get the size and type of the value - DWORD dataType; - DWORD dataSize; - if (RegQueryValueEx(handle, keyName, 0, &dataType, 0, &dataSize) == ERROR_SUCCESS) { - if (dataType == REG_SZ || dataType == REG_EXPAND_SZ) { - dataSize += 2; // '\0' missing? - QVarLengthArray data(dataSize); - data[dataSize - 2] = data[dataSize - 1] = '\0'; - if (RegQueryValueEx(handle, keyName, 0, 0, data.data(), &dataSize) == ERROR_SUCCESS) - result = QString::fromWCharArray(reinterpret_cast(data.data())); - } - } - RegCloseKey(handle); - } - return result; -} - bool QWindowsFontDatabase::isPrivateFontFamily(const QString &family) const { return m_eudcFonts.contains(family) || QPlatformFontDatabase::isPrivateFontFamily(family); diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h index a1cab17a87..f132e69d4d 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h @@ -133,8 +133,6 @@ public: static void setFontOptions(unsigned options); static unsigned fontOptions(); - static QString readRegistryString(HKEY parentHandle, const wchar_t *keyPath, const wchar_t *keyName); - private: void removeApplicationFonts(); void addDefaultEUDCFont(); diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp index a4490a6664..e796c18e79 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include #include @@ -945,10 +946,10 @@ void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request, QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyName) { - const wchar_t key[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes"; const QString substitute = - QWindowsFontDatabase::readRegistryString(HKEY_LOCAL_MACHINE, key, - reinterpret_cast(familyName.utf16())); + QWinRegistryKey(HKEY_LOCAL_MACHINE, + LR"(Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes)") + .stringValue(familyName); return substitute.isEmpty() ? familyName : substitute; } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index bb349f08a7..f7d04b667d 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -79,6 +79,7 @@ #include #include #include +#include #include @@ -1518,28 +1519,13 @@ QTouchDevice *QWindowsContext::touchDevice() const d->m_pointerHandler.touchDevice() : d->m_mouseHandler.touchDevice(); } -static DWORD readDwordRegistrySetting(const wchar_t *regKey, const wchar_t *subKey, DWORD defaultValue) -{ - DWORD result = defaultValue; - HKEY handle; - if (RegOpenKeyEx(HKEY_CURRENT_USER, regKey, 0, KEY_READ, &handle) == ERROR_SUCCESS) { - DWORD type; - if (RegQueryValueEx(handle, subKey, nullptr, &type, nullptr, nullptr) == ERROR_SUCCESS - && type == REG_DWORD) { - DWORD value; - DWORD size = sizeof(result); - if (RegQueryValueEx(handle, subKey, nullptr, nullptr, reinterpret_cast(&value), &size) == ERROR_SUCCESS) - result = value; - } - RegCloseKey(handle); - } - return result; -} - DWORD QWindowsContext::readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue) { - return readDwordRegistrySetting(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", - subKey, defaultValue); + const auto value = + QWinRegistryKey(HKEY_CURRENT_USER, + LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)") + .dwordValue(subKey); + return value.second ? value.first : defaultValue; } static inline bool isEmptyRect(const RECT &rect) diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp index b2b1dee232..83b052bb49 100644 --- a/src/plugins/platforms/windows/qwindowsservices.cpp +++ b/src/plugins/platforms/windows/qwindowsservices.cpp @@ -45,6 +45,8 @@ #include #include +#include + #include #include @@ -78,35 +80,24 @@ static inline QString mailCommand() const wchar_t mailUserKey[] = L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice"; - wchar_t command[MAX_PATH] = {0}; // Check if user has set preference, otherwise use default. - HKEY handle; - QString keyName; - if (!RegOpenKeyEx(HKEY_CURRENT_USER, mailUserKey, 0, KEY_READ, &handle)) { - DWORD bufferSize = BufferSize; - if (!RegQueryValueEx(handle, L"Progid", nullptr, nullptr, reinterpret_cast(command), &bufferSize)) - keyName = QString::fromWCharArray(command); - RegCloseKey(handle); - } + QString keyName = QWinRegistryKey(HKEY_CURRENT_USER, mailUserKey) + .stringValue( L"Progid"); const QLatin1String mailto = keyName.isEmpty() ? QLatin1String("mailto") : QLatin1String(); keyName += mailto + QLatin1String("\\Shell\\Open\\Command"); if (debug) qDebug() << __FUNCTION__ << "keyName=" << keyName; - command[0] = 0; - if (!RegOpenKeyExW(HKEY_CLASSES_ROOT, reinterpret_cast(keyName.utf16()), 0, KEY_READ, &handle)) { - DWORD bufferSize = BufferSize; - RegQueryValueEx(handle, L"", nullptr, nullptr, reinterpret_cast(command), &bufferSize); - RegCloseKey(handle); - } + const QString command = QWinRegistryKey(HKEY_CLASSES_ROOT, keyName).stringValue(L""); // QTBUG-57816: As of Windows 10, if there is no mail client installed, an entry like // "rundll32.exe .. url.dll,MailToProtocolHandler %l" is returned. Launching it // silently fails or brings up a broken dialog after a long time, so exclude it and // fall back to ShellExecute() which brings up the URL assocation dialog. - if (!command[0] || wcsstr(command, L",MailToProtocolHandler") != nullptr) + if (command.isEmpty() || command.contains(QLatin1String(",MailToProtocolHandler"))) return QString(); wchar_t expandedCommand[MAX_PATH] = {0}; - return ExpandEnvironmentStrings(command, expandedCommand, MAX_PATH) ? - QString::fromWCharArray(expandedCommand) : QString::fromWCharArray(command); + return ExpandEnvironmentStrings(reinterpret_cast(command.utf16()), + expandedCommand, MAX_PATH) + ? QString::fromWCharArray(expandedCommand) : command; } static inline bool launchMail(const QUrl &url) diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 09a1c68001..9863ff5e69 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -126,6 +126,7 @@ win32:SOURCES += ../../corelib/global/qoperatingsystemversion_win.cpp \ ../../corelib/kernel/qsharedmemory_win.cpp \ ../../corelib/kernel/qsystemsemaphore_win.cpp \ ../../corelib/plugin/qsystemlibrary.cpp \ + ../../corelib/kernel/qwinregistry.cpp \ mac { SOURCES += \ -- cgit v1.2.3