Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qwinregistry.cpp
Go to the documentation of this file.
1
// Copyright (C) 2019 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
// Qt-Security score:critical reason:data-parser
4
5
#
define
UMDF_USING_NTSTATUS
// Avoid ntstatus redefinitions
6
7
#
include
"qwinregistry_p.h"
8
#
include
<
QtCore
/
qvarlengtharray
.
h
>
9
#
include
<
QtCore
/
qdebug
.
h
>
10
#
include
<
QtCore
/
qendian
.
h
>
11
#
include
<
QtCore
/
qlist
.
h
>
12
#
include
<
QtCore
/
qwineventnotifier
.
h
>
13
#
include
<
QtCore
/
private
/
qsystemerror_p
.
h
>
14
15
#
include
<
ntstatus
.
h
>
16
17
// User mode version of ZwQueryKey, as per:
18
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-zwquerykey
19
extern
"C"
NTSTATUS NTSYSCALLAPI NTAPI NtQueryKey(HANDLE KeyHandle,
int
KeyInformationClass,
20
PVOID KeyInformation, ULONG Length, PULONG ResultLength);
21
22
QT_BEGIN_NAMESPACE
23
24
using
namespace
Qt::StringLiterals;
25
26
static
const
wchar_t
*
nullTerminate
(
const
QString &s)
27
{
28
// ### port to QString::nullTerminate() if this stays around for longer
29
return
reinterpret_cast
<
const
wchar_t
*>(s.utf16());
30
}
31
32
// Open a key with the specified permissions (KEY_READ/KEY_WRITE).
33
// "access" is to explicitly use the 32- or 64-bit branch.
34
QWinRegistryKey::QWinRegistryKey(HKEY parentHandle,
const
wchar_t
*subKey,
35
REGSAM permissions, REGSAM access)
36
{
37
if
(RegOpenKeyExW(parentHandle, subKey,
38
0, permissions | access, &m_key) != ERROR_SUCCESS) {
39
m_key =
nullptr
;
40
}
41
}
42
43
QWinRegistryKey::QWinRegistryKey(HKEY parentHandle,
const
QString &subKey,
44
REGSAM permissions, REGSAM access)
45
: QWinRegistryKey(parentHandle, nullTerminate(subKey), permissions, access)
46
{
47
}
48
49
QWinRegistryKey::~QWinRegistryKey()
50
{
51
close();
52
}
53
54
void
QWinRegistryKey::close()
55
{
56
if
(isValid()) {
57
RegCloseKey(m_key);
58
m_key =
nullptr
;
59
}
60
}
61
62
QString QWinRegistryKey::name()
const
63
{
64
if
(!isValid())
65
return
{};
66
67
// https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_key_name_information
68
constexpr
int
kKeyNameInformation = 3;
69
struct
KeyNameInformation { ULONG length = 0; WCHAR name[1] = {}; };
70
71
// Resolve name of key iteratively by first computing the needed size,
72
// and then querying the name, accounting for the possibility that the
73
// name length changes behind our back a few times.
74
DWORD keyInformationSize = 0;
75
for
(
int
i = 0; i < 5; ++i) {
76
QByteArray buffer(keyInformationSize, 0u);
77
auto
*keyNameInformation =
reinterpret_cast
<KeyNameInformation *>(buffer.data());
78
switch
(NtQueryKey(m_key, kKeyNameInformation, keyNameInformation,
79
keyInformationSize, &keyInformationSize)) {
80
case
STATUS_BUFFER_TOO_SMALL:
81
case
STATUS_BUFFER_OVERFLOW:
82
continue
;
83
case
STATUS_SUCCESS: {
84
return
QString::fromWCharArray(keyNameInformation->name,
85
keyNameInformation->length /
sizeof
(
wchar_t
));
86
}
87
default
:
88
return
{};
89
}
90
}
91
92
return
{};
93
}
94
95
QVariant QWinRegistryKey::value(
const
wchar_t
*subKey)
const
96
{
97
// NOTE: Empty value name is allowed in Windows registry, it means the default
98
// or unnamed value of a key, you can read/write/delete such value normally.
99
100
if
(!isValid())
101
return
{};
102
103
// Get the size and type of the value.
104
DWORD dataType = REG_NONE;
105
DWORD dataSize = 0;
106
LONG ret = RegQueryValueExW(m_key, subKey,
nullptr
, &dataType,
nullptr
, &dataSize);
107
if
(ret != ERROR_SUCCESS)
108
return
{};
109
110
// Workaround for rare cases where the trailing '\0' is missing.
111
if
(dataType == REG_SZ || dataType == REG_EXPAND_SZ)
112
dataSize += 2;
113
else
if
(dataType == REG_MULTI_SZ)
114
dataSize += 4;
115
116
// Get the value.
117
QVarLengthArray<
unsigned
char
> data(dataSize);
118
std::fill(data.data(), data.data() + dataSize, 0u);
119
120
ret = RegQueryValueExW(m_key, subKey,
nullptr
,
nullptr
, data.data(), &dataSize);
121
if
(ret != ERROR_SUCCESS)
122
return
{};
123
124
switch
(dataType) {
125
case
REG_SZ:
126
case
REG_EXPAND_SZ: {
127
if
(dataSize > 0) {
128
return
QString::fromWCharArray(
129
reinterpret_cast
<
const
wchar_t
*>(data.constData()));
130
}
131
return
QString();
132
}
133
134
case
REG_MULTI_SZ: {
135
if
(dataSize > 0) {
136
QStringList list = {};
137
int
i = 0;
138
while
(
true
) {
139
const
QString str = QString::fromWCharArray(
140
reinterpret_cast
<
const
wchar_t
*>(data.constData()) + i);
141
i += str.length() + 1;
142
if
(str.isEmpty())
143
break
;
144
list.append(str);
145
}
146
return
list;
147
}
148
return
QStringList();
149
}
150
151
case
REG_NONE:
// No specific type, treat as binary data.
152
case
REG_BINARY: {
153
if
(dataSize > 0) {
154
return
QString::fromWCharArray(
155
reinterpret_cast
<
const
wchar_t
*>(data.constData()), data.size() / 2);
156
}
157
return
QString();
158
}
159
160
case
REG_DWORD:
// Same as REG_DWORD_LITTLE_ENDIAN
161
return
qFromLittleEndian<quint32>(data.constData());
162
163
case
REG_DWORD_BIG_ENDIAN:
164
return
qFromBigEndian<quint32>(data.constData());
165
166
case
REG_QWORD:
// Same as REG_QWORD_LITTLE_ENDIAN
167
return
qFromLittleEndian<quint64>(data.constData());
168
169
default
:
170
break
;
171
}
172
173
return
{};
174
}
175
176
QVariant QWinRegistryKey::value(
const
QString &subKey)
const
177
{
178
return
value(nullTerminate(subKey));
179
}
180
181
// Returns the value of the specified subKey as a string, obtained using
182
// qvariant_cast from the underlying QVariant. If that value is not a string,
183
// or the subKey has no value, a string whose isNull() is true is returned.
184
// Otherwise, the resulting string (which may be empty) is returned.
185
QString QWinRegistryKey::stringValue(
const
wchar_t
*subKey)
const
186
{
187
if
(
auto
v = value<QString>(subKey))
188
return
std::move(*v);
189
return
QString();
190
}
191
192
QString QWinRegistryKey::stringValue(
const
QString &subKey)
const
193
{
194
return
stringValue(nullTerminate(subKey));
195
}
196
197
QWinRegistryNotifier::QWinRegistryNotifier(HKEY parentHandle,
const
wchar_t
*subKey,
198
QObject *parent)
199
: QWinRegistryNotifier(QWinRegistryKey(parentHandle, subKey), parent)
200
{
201
}
202
203
QWinRegistryNotifier::QWinRegistryNotifier(HKEY parentHandle,
const
QString &subKey,
204
QObject *parent)
205
: QWinRegistryNotifier(QWinRegistryKey(parentHandle, subKey), parent)
206
{
207
}
208
209
QWinRegistryNotifier::QWinRegistryNotifier(QWinRegistryKey &&key, QObject *parent)
210
: QObject(parent), m_key(std::move(key))
211
{
212
if
(!m_key.isValid())
213
return
;
214
215
m_keyChangedEvent.reset(CreateEvent(
nullptr
,
false
,
false
,
nullptr
));
216
auto
*notifier =
new
QWinEventNotifier(m_keyChangedEvent.get(),
this
);
217
218
auto
registerForNotification = [
this
] {
219
constexpr
auto
changeFilter =
220
REG_NOTIFY_CHANGE_NAME
221
| REG_NOTIFY_CHANGE_ATTRIBUTES
222
| REG_NOTIFY_CHANGE_LAST_SET
223
| REG_NOTIFY_CHANGE_SECURITY;
224
225
if
(
auto
status = RegNotifyChangeKeyValue(m_key.handle(),
true
, changeFilter,
226
m_keyChangedEvent.get(),
true
); status != ERROR_SUCCESS) {
227
qWarning() <<
"Failed to register notification for registry key"
228
<<
this
<<
"due to"
<< QSystemError::windowsString(status);
229
}
230
};
231
232
QObject::connect(notifier, &QWinEventNotifier::activated,
this
,
233
[
this
, registerForNotification] {
234
emit valueChanged();
235
registerForNotification();
236
});
237
238
registerForNotification();
239
}
240
241
#
ifndef
QT_NO_DEBUG_STREAM
242
QDebug
operator
<<(QDebug debug,
const
QWinRegistryKey &key)
243
{
244
QDebugStateSaver saver(debug);
245
debug.nospace();
246
debug <<
"QWinRegistryKey("
;
247
if
(key.isValid())
248
debug << key.name();
249
debug <<
')'
;
250
return
debug;
251
}
252
#
endif
253
254
QT_END_NAMESPACE
operator<<
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
Definition
qfileinfo.cpp:1830
nullTerminate
static const wchar_t * nullTerminate(const QString &s)
Definition
qwinregistry.cpp:26
qtbase
src
corelib
kernel
qwinregistry.cpp
Generated on
for Qt by
1.18.0