qtbase/src/corelib/kernel/qwinregistry.cpp
Marc Mutz 2d5a239285 QtCore platform code: s/QPair/std::pair/
Also port qMakePair() to just braced initialization and CTAD.

Task-number: QTBUG-115841
Change-Id: I46ee214ab47513375a6e28e3b439c7b060581235
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
(cherry picked from commit 87361727ffafbee460970cdb8e72056653fd2443)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
2023-12-13 20:58:24 +00:00

135 lines
3.9 KiB
C++

// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qwinregistry_p.h"
#include <QtCore/qvarlengtharray.h>
#include <QtCore/qendian.h>
#include <QtCore/qlist.h>
QT_BEGIN_NAMESPACE
QWinRegistryKey::QWinRegistryKey()
{
}
// 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 (RegOpenKeyExW(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;
}
}
QVariant QWinRegistryKey::value(QStringView subKey) const
{
// NOTE: Empty value name is allowed in Windows registry, it means the default
// or unnamed value of a key, you can read/write/delete such value normally.
if (!isValid())
return {};
// Use nullptr when we need to access the default value.
const auto subKeyC = subKey.isEmpty() ? nullptr : reinterpret_cast<const wchar_t *>(subKey.utf16());
// Get the size and type of the value.
DWORD dataType = REG_NONE;
DWORD dataSize = 0;
LONG ret = RegQueryValueExW(m_key, subKeyC, nullptr, &dataType, nullptr, &dataSize);
if (ret != ERROR_SUCCESS)
return {};
// Workaround for rare cases where the trailing '\0' is missing.
if (dataType == REG_SZ || dataType == REG_EXPAND_SZ)
dataSize += 2;
else if (dataType == REG_MULTI_SZ)
dataSize += 4;
// Get the value.
QVarLengthArray<unsigned char> data(dataSize);
std::fill(data.data(), data.data() + dataSize, 0u);
ret = RegQueryValueExW(m_key, subKeyC, nullptr, nullptr, data.data(), &dataSize);
if (ret != ERROR_SUCCESS)
return {};
switch (dataType) {
case REG_SZ:
case REG_EXPAND_SZ: {
if (dataSize > 0) {
return QString::fromWCharArray(
reinterpret_cast<const wchar_t *>(data.constData()));
}
return QString();
}
case REG_MULTI_SZ: {
if (dataSize > 0) {
QStringList list = {};
int i = 0;
while (true) {
const QString str = QString::fromWCharArray(
reinterpret_cast<const wchar_t *>(data.constData()) + i);
i += str.length() + 1;
if (str.isEmpty())
break;
list.append(str);
}
return list;
}
return QStringList();
}
case REG_NONE: // No specific type, treat as binary data.
case REG_BINARY: {
if (dataSize > 0) {
return QString::fromWCharArray(
reinterpret_cast<const wchar_t *>(data.constData()), data.size() / 2);
}
return QString();
}
case REG_DWORD: // Same as REG_DWORD_LITTLE_ENDIAN
return qFromLittleEndian<quint32>(data.constData());
case REG_DWORD_BIG_ENDIAN:
return qFromBigEndian<quint32>(data.constData());
case REG_QWORD: // Same as REG_QWORD_LITTLE_ENDIAN
return qFromLittleEndian<quint64>(data.constData());
default:
break;
}
return {};
}
QString QWinRegistryKey::stringValue(QStringView subKey) const
{
return value<QString>(subKey).value_or(QString());
}
std::pair<DWORD, bool> QWinRegistryKey::dwordValue(QStringView subKey) const
{
const std::optional<DWORD> val = value<DWORD>(subKey);
return {val.value_or(0), val.has_value()};
}
QT_END_NAMESPACE