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 <volker.hilsheimer@qt.io>
This commit is contained in:
parent
95ac2072bb
commit
05a829f923
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
120
src/corelib/kernel/qwinregistry.cpp
Normal file
120
src/corelib/kernel/qwinregistry.cpp
Normal file
@ -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
|
89
src/corelib/kernel/qwinregistry_p.h
Normal file
89
src/corelib/kernel/qwinregistry_p.h
Normal file
@ -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
|
@ -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())
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include <QtCore/QtEndian>
|
||||
#include <QtCore/QThreadStorage>
|
||||
#include <QtCore/private/qsystemlibrary_p.h>
|
||||
#include <QtCore/private/qwinregistry_p.h>
|
||||
|
||||
#include <wchar.h>
|
||||
|
||||
@ -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<LPBYTE>(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<unsigned char> 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<const wchar_t *>(data.data()));
|
||||
}
|
||||
}
|
||||
RegCloseKey(handle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool QWindowsFontDatabase::isPrivateFontFamily(const QString &family) const
|
||||
{
|
||||
return m_eudcFonts.contains(family) || QPlatformFontDatabase::isPrivateFontFamily(family);
|
||||
|
@ -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();
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <QtCore/QFile>
|
||||
#include <private/qstringiterator_p.h>
|
||||
#include <QtCore/private/qsystemlibrary_p.h>
|
||||
#include <QtCore/private/qwinregistry_p.h>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <QtGui/private/qhighdpiscaling_p.h>
|
||||
@ -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<const wchar_t *>(familyName.utf16()));
|
||||
QWinRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
LR"(Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes)")
|
||||
.stringValue(familyName);
|
||||
return substitute.isEmpty() ? familyName : substitute;
|
||||
}
|
||||
|
||||
|
@ -79,6 +79,7 @@
|
||||
#include <QtCore/qscopedpointer.h>
|
||||
#include <QtCore/quuid.h>
|
||||
#include <QtCore/private/qsystemlibrary_p.h>
|
||||
#include <QtCore/private/qwinregistry_p.h>
|
||||
|
||||
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
|
||||
|
||||
@ -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<unsigned char *>(&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)
|
||||
|
@ -45,6 +45,8 @@
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qdir.h>
|
||||
|
||||
#include <QtCore/private/qwinregistry_p.h>
|
||||
|
||||
#include <shlobj.h>
|
||||
#include <intshcut.h>
|
||||
|
||||
@ -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<unsigned char*>(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<const wchar_t*>(keyName.utf16()), 0, KEY_READ, &handle)) {
|
||||
DWORD bufferSize = BufferSize;
|
||||
RegQueryValueEx(handle, L"", nullptr, nullptr, reinterpret_cast<unsigned char*>(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<const wchar_t *>(command.utf16()),
|
||||
expandedCommand, MAX_PATH)
|
||||
? QString::fromWCharArray(expandedCommand) : command;
|
||||
}
|
||||
|
||||
static inline bool launchMail(const QUrl &url)
|
||||
|
@ -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 += \
|
||||
|
@ -12,3 +12,6 @@ SUBDIRS=\
|
||||
qtendian \
|
||||
qglobalstatic \
|
||||
qhooks
|
||||
|
||||
win32:!winrt: SUBDIRS += \
|
||||
qwinregistry
|
||||
|
8
tests/auto/corelib/global/qwinregistry/qwinregistry.pro
Normal file
8
tests/auto/corelib/global/qwinregistry/qwinregistry.pro
Normal file
@ -0,0 +1,8 @@
|
||||
CONFIG += testcase
|
||||
QT += testlib core-private
|
||||
QT -= gui
|
||||
|
||||
TARGET = tst_qwinregistry
|
||||
CONFIG += console
|
||||
|
||||
SOURCES += tst_qwinregistry.cpp
|
68
tests/auto/corelib/global/qwinregistry/tst_qwinregistry.cpp
Normal file
68
tests/auto/corelib/global/qwinregistry/tst_qwinregistry.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the test suite of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** 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 General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** 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-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <QtCore/qoperatingsystemversion.h>
|
||||
|
||||
#include <QtCore/private/qwinregistry_p.h>
|
||||
|
||||
class tst_QWinRegistry : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public Q_SLOTS:
|
||||
void initTestCase();
|
||||
|
||||
private Q_SLOTS:
|
||||
void values();
|
||||
};
|
||||
|
||||
void tst_QWinRegistry::initTestCase()
|
||||
{
|
||||
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows10)
|
||||
QSKIP("This test requires registry values present in Windows 10");
|
||||
}
|
||||
|
||||
void tst_QWinRegistry::values()
|
||||
{
|
||||
QWinRegistryKey key(HKEY_LOCAL_MACHINE, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion)");
|
||||
QVERIFY(key.isValid());
|
||||
QVERIFY(!key.stringValue(L"ProductName").isEmpty());
|
||||
QVERIFY(key.stringValue(L"NonExistingKey").isEmpty());
|
||||
auto majorVersion = key.dwordValue(L"CurrentMajorVersionNumber");
|
||||
QVERIFY(majorVersion.second);
|
||||
QVERIFY(majorVersion.first > 0);
|
||||
auto nonExistingValue = key.dwordValue(L"NonExistingKey");
|
||||
QVERIFY(!nonExistingValue.second);
|
||||
QCOMPARE(nonExistingValue.first, 0u);
|
||||
}
|
||||
|
||||
QTEST_APPLESS_MAIN(tst_QWinRegistry);
|
||||
|
||||
#include "tst_qwinregistry.moc"
|
@ -49,6 +49,7 @@
|
||||
#ifdef Q_OS_WIN
|
||||
#include <qt_windows.h>
|
||||
#if !defined(Q_OS_WINRT)
|
||||
#include <private/qwinregistry_p.h>
|
||||
#include <lm.h>
|
||||
#endif
|
||||
#endif
|
||||
@ -1243,17 +1244,12 @@ void tst_QFileInfo::fileTimes()
|
||||
//In Vista the last-access timestamp is not updated when the file is accessed/touched (by default).
|
||||
//To enable this the HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate
|
||||
//is set to 0, in the test machine.
|
||||
HKEY key;
|
||||
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\FileSystem",
|
||||
0, KEY_READ, &key)) {
|
||||
DWORD disabledAccessTimes = 0;
|
||||
DWORD size = sizeof(DWORD);
|
||||
LONG error = RegQueryValueEx(key, L"NtfsDisableLastAccessUpdate"
|
||||
, NULL, NULL, (LPBYTE)&disabledAccessTimes, &size);
|
||||
if (ERROR_SUCCESS == error && disabledAccessTimes)
|
||||
noAccessTime = true;
|
||||
RegCloseKey(key);
|
||||
}
|
||||
const auto disabledAccessTimes =
|
||||
QWinRegistryKey(HKEY_LOCAL_MACHINE,
|
||||
LR"(SYSTEM\CurrentControlSet\Control\FileSystem)")
|
||||
.dwordValue(L"NtfsDisableLastAccessUpdate");
|
||||
if (disabledAccessTimes.second && disabledAccessTimes.first != 0)
|
||||
noAccessTime = true;
|
||||
#endif
|
||||
|
||||
if (noAccessTime)
|
||||
|
@ -54,6 +54,9 @@
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
#include <QtCore/qt_windows.h>
|
||||
#ifndef Q_OS_WINRT
|
||||
# include <private/qwinregistry_p.h>
|
||||
#endif
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
@ -3623,16 +3626,13 @@ void tst_QSettings::recursionBug()
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
|
||||
static DWORD readKeyType(HKEY handle, const QString &rSubKey)
|
||||
static DWORD readKeyType(HKEY handle, QStringView rSubKey)
|
||||
{
|
||||
DWORD dataType;
|
||||
DWORD dataSize;
|
||||
LONG res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, &dataType, 0, &dataSize);
|
||||
|
||||
if (res == ERROR_SUCCESS)
|
||||
return dataType;
|
||||
|
||||
return 0;
|
||||
LONG res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
|
||||
nullptr, &dataType, nullptr, &dataSize);
|
||||
return res == ERROR_SUCCESS ? dataType : 0;
|
||||
}
|
||||
|
||||
// This is a regression test for QTBUG-13249, where QSettings was storing
|
||||
@ -3652,29 +3652,12 @@ void tst_QSettings::consistentRegistryStorage()
|
||||
QCOMPARE(settings1.value("quint64_value").toULongLong(), (quint64)1024);
|
||||
settings1.sync();
|
||||
|
||||
HKEY handle;
|
||||
LONG res;
|
||||
QString keyName = "Software\\software.org\\KillerAPP";
|
||||
res = RegOpenKeyEx(HKEY_CURRENT_USER, reinterpret_cast<const wchar_t *>(keyName.utf16()), 0, KEY_READ, &handle);
|
||||
if (res == ERROR_SUCCESS)
|
||||
{
|
||||
DWORD dataType;
|
||||
dataType = readKeyType(handle, QString("qint32_value"));
|
||||
if (dataType != 0) {
|
||||
QCOMPARE((int)REG_DWORD, (int)dataType);
|
||||
}
|
||||
dataType = readKeyType(handle, QString("quint32_value"));
|
||||
if (dataType != 0) {
|
||||
QCOMPARE((int)REG_DWORD, (int)dataType);
|
||||
}
|
||||
dataType = readKeyType(handle, QString("qint64_value"));
|
||||
if (dataType != 0) {
|
||||
QCOMPARE((int)REG_QWORD, (int)dataType);
|
||||
}
|
||||
dataType = readKeyType(handle, QString("quint64_value"));
|
||||
if (dataType != 0) {
|
||||
QCOMPARE((int)REG_QWORD, (int)dataType);
|
||||
}
|
||||
QWinRegistryKey handle(HKEY_CURRENT_USER, LR"(Software\software.org\KillerAPP)");
|
||||
if (handle.isValid()) {
|
||||
QCOMPARE(readKeyType(handle, L"qint32_value"), DWORD(REG_DWORD));
|
||||
QCOMPARE(readKeyType(handle, L"quint32_value"), DWORD(REG_DWORD));
|
||||
QCOMPARE(readKeyType(handle, L"qint64_value"), DWORD(REG_QWORD));
|
||||
QCOMPARE(readKeyType(handle, L"quint64_value"), DWORD(REG_QWORD));
|
||||
RegCloseKey(handle);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user