Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qsettings.h"
41
42#include "qsettings_p.h"
43#include "qvector.h"
44#include "qmap.h"
45#include "qdebug.h"
46#include <qt_windows.h>
47
48// See "Accessing an Alternate Registry View" at:
49// http://msdn.microsoft.com/en-us/library/aa384129%28VS.85%29.aspx
50#ifndef KEY_WOW64_64KEY
51 // Access a 32-bit key from either a 32-bit or 64-bit application.
52# define KEY_WOW64_64KEY 0x0100
53#endif
54
55#ifndef KEY_WOW64_32KEY
56 // Access a 64-bit key from either a 32-bit or 64-bit application.
57# define KEY_WOW64_32KEY 0x0200
58#endif
59
60QT_BEGIN_NAMESPACE
61
62/* Keys are stored in QStrings. If the variable name starts with 'u', this is a "user"
63 key, ie. "foo/bar/alpha/beta". If the variable name starts with 'r', this is a "registry"
64 key, ie. "\foo\bar\alpha\beta". */
65
66/*******************************************************************************
67** Some convenience functions
68*/
69
70/*
71 We don't use KEY_ALL_ACCESS because it gives more rights than what we
72 need. See task 199061.
73 */
74static const REGSAM registryPermissions = KEY_READ | KEY_WRITE;
75
76static QString keyPath(const QString &rKey)
77{
78 int idx = rKey.lastIndexOf(QLatin1Char('\\'));
79 if (idx == -1)
80 return QString();
81 return rKey.left(idx + 1);
82}
83
84static QString keyName(const QString &rKey)
85{
86 int idx = rKey.lastIndexOf(QLatin1Char('\\'));
87
88 QString res;
89 if (idx == -1)
90 res = rKey;
91 else
92 res = rKey.mid(idx + 1);
93
94 if (res == QLatin1String("Default") || res == QLatin1String("."))
95 res = QLatin1String("");
96
97 return res;
98}
99
100static QString escapedKey(QString uKey)
101{
102 QChar *data = uKey.data();
103 int l = uKey.length();
104 for (int i = 0; i < l; ++i) {
105 ushort &ucs = data[i].unicode();
106 if (ucs == '\\')
107 ucs = '/';
108 else if (ucs == '/')
109 ucs = '\\';
110 }
111 return uKey;
112}
113
114static QString unescapedKey(QString rKey)
115{
116 return escapedKey(rKey);
117}
118
119typedef QMap<QString, QString> NameSet;
120
121static void mergeKeySets(NameSet *dest, const NameSet &src)
122{
123 NameSet::const_iterator it = src.constBegin();
124 for (; it != src.constEnd(); ++it)
125 dest->insert(unescapedKey(it.key()), QString());
126}
127
128static void mergeKeySets(NameSet *dest, const QStringList &src)
129{
130 QStringList::const_iterator it = src.constBegin();
131 for (; it != src.constEnd(); ++it)
132 dest->insert(unescapedKey(*it), QString());
133}
134
135/*******************************************************************************
136** Wrappers for the insane windows registry API
137*/
138
139// Open a key with the specified "perms".
140// "access" is to explicitly use the 32- or 64-bit branch.
141static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey, REGSAM access = 0)
142{
143 HKEY resultHandle = 0;
144 LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
145 0, perms | access, &resultHandle);
146
147 if (res == ERROR_SUCCESS)
148 return resultHandle;
149
150 return 0;
151}
152
153// Open a key with the specified "perms", create it if it does not exist.
154// "access" is to explicitly use the 32- or 64-bit branch.
155static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey, REGSAM access = 0)
156{
157 // try to open it
158 HKEY resultHandle = openKey(parentHandle, perms, rSubKey, access);
159 if (resultHandle != 0)
160 return resultHandle;
161
162 // try to create it
163 LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0,
164 REG_OPTION_NON_VOLATILE, perms | access, 0, &resultHandle, 0);
165
166 if (res == ERROR_SUCCESS)
167 return resultHandle;
168
169 //qErrnoWarning(int(res), "QSettings: Failed to create subkey \"%ls\"",
170 // qUtf16Printable(rSubKey));
171
172 return 0;
173}
174
175// Open or create a key in read-write mode if possible, otherwise read-only.
176// "access" is to explicitly use the 32- or 64-bit branch.
177static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *readOnly, REGSAM access = 0)
178{
179 // try to open or create it read/write
180 HKEY resultHandle = createOrOpenKey(parentHandle, registryPermissions, rSubKey, access);
181 if (resultHandle != 0) {
182 if (readOnly != 0)
183 *readOnly = false;
184 return resultHandle;
185 }
186
187 // try to open or create it read/only
188 resultHandle = createOrOpenKey(parentHandle, KEY_READ, rSubKey, access);
189 if (resultHandle != 0) {
190 if (readOnly != 0)
191 *readOnly = true;
192 return resultHandle;
193 }
194 return 0;
195}
196
197static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildSpec spec)
198{
199 QStringList result;
200 DWORD numKeys;
201 DWORD maxKeySize;
202 DWORD numSubgroups;
203 DWORD maxSubgroupSize;
204
205 // Find the number of keys and subgroups, as well as the max of their lengths.
206 LONG res = RegQueryInfoKey(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0,
207 &numKeys, &maxKeySize, 0, 0, 0);
208
209 if (res != ERROR_SUCCESS) {
210 qErrnoWarning(int(res), "QSettings: RegQueryInfoKey() failed");
211 return result;
212 }
213
214 ++maxSubgroupSize;
215 ++maxKeySize;
216
217 int n;
218 int m;
219 if (spec == QSettingsPrivate::ChildKeys) {
220 n = numKeys;
221 m = maxKeySize;
222 } else {
223 n = numSubgroups;
224 m = maxSubgroupSize;
225 }
226
227 /* The size does not include the terminating null character. */
228 ++m;
229
230 // Get the list
231 QByteArray buff(m * sizeof(wchar_t), 0);
232 for (int i = 0; i < n; ++i) {
233 QString item;
234 DWORD l = buff.size() / sizeof(wchar_t);
235 if (spec == QSettingsPrivate::ChildKeys) {
236 res = RegEnumValue(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
237 } else {
238 res = RegEnumKeyEx(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
239 }
240 if (res == ERROR_SUCCESS)
241 item = QString::fromWCharArray((const wchar_t *)buff.constData(), l);
242
243 if (res != ERROR_SUCCESS) {
244 qErrnoWarning(int(res), "QSettings: RegEnumValue failed");
245 continue;
246 }
247 if (item.isEmpty())
248 item = QLatin1String(".");
249 result.append(item);
250 }
251 return result;
252}
253
254static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result, REGSAM access = 0)
255{
256 HKEY handle = openKey(parentHandle, KEY_READ, rSubKey, access);
257 if (handle == 0)
258 return;
259
260 QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
261 QStringList childGroups = childKeysOrGroups(handle, QSettingsPrivate::ChildGroups);
262 RegCloseKey(handle);
263
264 for (int i = 0; i < childKeys.size(); ++i) {
265 QString s = rSubKey;
266 if (!s.isEmpty())
267 s += QLatin1Char('\\');
268 s += childKeys.at(i);
269 result->insert(s, QString());
270 }
271
272 for (int i = 0; i < childGroups.size(); ++i) {
273 QString s = rSubKey;
274 if (!s.isEmpty())
275 s += QLatin1Char('\\');
276 s += childGroups.at(i);
277 allKeys(parentHandle, s, result, access);
278 }
279}
280
281static void deleteChildGroups(HKEY parentHandle, REGSAM access = 0)
282{
283 QStringList childGroups = childKeysOrGroups(parentHandle, QSettingsPrivate::ChildGroups);
284
285 for (int i = 0; i < childGroups.size(); ++i) {
286 QString group = childGroups.at(i);
287
288 // delete subgroups in group
289 HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group, access);
290 if (childGroupHandle == 0)
291 continue;
292 deleteChildGroups(childGroupHandle, access);
293 RegCloseKey(childGroupHandle);
294
295 // delete group itself
296 LONG res = RegDeleteKey(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16()));
297 if (res != ERROR_SUCCESS) {
298 qErrnoWarning(int(res), "QSettings: RegDeleteKey failed on subkey \"%ls\"",
299 qUtf16Printable(group));
300 return;
301 }
302 }
303}
304
305/*******************************************************************************
306** class RegistryKey
307*/
308
309class RegistryKey
310{
311public:
312 RegistryKey(HKEY parent_handle = 0, const QString &key = QString(), bool read_only = true, REGSAM access = 0);
313 QString key() const;
314 HKEY handle() const;
315 HKEY parentHandle() const;
316 bool readOnly() const;
317 void close();
318private:
319 HKEY m_parent_handle;
320 mutable HKEY m_handle;
321 QString m_key;
322 mutable bool m_read_only;
323 REGSAM m_access;
324};
325
326RegistryKey::RegistryKey(HKEY parent_handle, const QString &key, bool read_only, REGSAM access)
327 : m_parent_handle(parent_handle),
328 m_handle(0),
329 m_key(key),
330 m_read_only(read_only),
331 m_access(access)
332{
333}
334
335QString RegistryKey::key() const
336{
337 return m_key;
338}
339
340HKEY RegistryKey::handle() const
341{
342 if (m_handle != 0)
343 return m_handle;
344
345 if (m_read_only)
346 m_handle = openKey(m_parent_handle, KEY_READ, m_key, m_access);
347 else
348 m_handle = createOrOpenKey(m_parent_handle, m_key, &m_read_only, m_access);
349
350 return m_handle;
351}
352
353HKEY RegistryKey::parentHandle() const
354{
355 return m_parent_handle;
356}
357
358bool RegistryKey::readOnly() const
359{
360 return m_read_only;
361}
362
363void RegistryKey::close()
364{
365 if (m_handle != 0)
366 RegCloseKey(m_handle);
367 m_handle = 0;
368}
369
370typedef QVector<RegistryKey> RegistryKeyList;
371
372/*******************************************************************************
373** class QWinSettingsPrivate
374*/
375
376class QWinSettingsPrivate : public QSettingsPrivate
377{
378 Q_DISABLE_COPY(QWinSettingsPrivate)
379public:
380 QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
381 const QString &application, REGSAM access = 0);
382 QWinSettingsPrivate(QString rKey, REGSAM access = 0);
383 ~QWinSettingsPrivate() override;
384
385 void remove(const QString &uKey) override;
386 void set(const QString &uKey, const QVariant &value) override;
387 bool get(const QString &uKey, QVariant *value) const override;
388 QStringList children(const QString &uKey, ChildSpec spec) const override;
389 void clear() override;
390 void sync() override;
391 void flush() override;
392 bool isWritable() const override;
393 HKEY writeHandle() const;
394 bool readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const;
395 QString fileName() const override;
396
397private:
398 RegistryKeyList regList; // list of registry locations to search for keys
399 bool deleteWriteHandleOnExit;
400 REGSAM access;
401};
402
403QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
404 const QString &application, REGSAM access)
405 : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application),
406 access(access)
407{
408 deleteWriteHandleOnExit = false;
409
410 if (!organization.isEmpty()) {
411 QString prefix = QLatin1String("Software\\") + organization;
412 QString orgPrefix = prefix + QLatin1String("\\OrganizationDefaults");
413 QString appPrefix = prefix + QLatin1Char('\\') + application;
414
415 if (scope == QSettings::UserScope) {
416 if (!application.isEmpty())
417 regList.append(RegistryKey(HKEY_CURRENT_USER, appPrefix, !regList.isEmpty(), access));
418
419 regList.append(RegistryKey(HKEY_CURRENT_USER, orgPrefix, !regList.isEmpty(), access));
420 }
421
422 if (!application.isEmpty())
423 regList.append(RegistryKey(HKEY_LOCAL_MACHINE, appPrefix, !regList.isEmpty(), access));
424
425 regList.append(RegistryKey(HKEY_LOCAL_MACHINE, orgPrefix, !regList.isEmpty(), access));
426 }
427
428 if (regList.isEmpty())
429 setStatus(QSettings::AccessError);
430}
431
432QWinSettingsPrivate::QWinSettingsPrivate(QString rPath, REGSAM access)
433 : QSettingsPrivate(QSettings::NativeFormat),
434 access(access)
435{
436 deleteWriteHandleOnExit = false;
437
438 if (rPath.startsWith(QLatin1Char('\\')))
439 rPath.remove(0, 1);
440
441 int keyLength;
442 HKEY keyName;
443
444 if (rPath.startsWith(QLatin1String("HKEY_CURRENT_USER"))) {
445 keyLength = 17;
446 keyName = HKEY_CURRENT_USER;
447 } else if (rPath.startsWith(QLatin1String("HKCU"))) {
448 keyLength = 4;
449 keyName = HKEY_CURRENT_USER;
450 } else if (rPath.startsWith(QLatin1String("HKEY_LOCAL_MACHINE"))) {
451 keyLength = 18;
452 keyName = HKEY_LOCAL_MACHINE;
453 } else if (rPath.startsWith(QLatin1String("HKLM"))) {
454 keyLength = 4;
455 keyName = HKEY_LOCAL_MACHINE;
456 } else if (rPath.startsWith(QLatin1String("HKEY_CLASSES_ROOT"))) {
457 keyLength = 17;
458 keyName = HKEY_CLASSES_ROOT;
459 } else if (rPath.startsWith(QLatin1String("HKCR"))) {
460 keyLength = 4;
461 keyName = HKEY_CLASSES_ROOT;
462 } else if (rPath.startsWith(QLatin1String("HKEY_USERS"))) {
463 keyLength = 10;
464 keyName = HKEY_USERS;
465 } else if (rPath.startsWith(QLatin1String("HKU"))) {
466 keyLength = 3;
467 keyName = HKEY_USERS;
468 } else {
469 return;
470 }
471
472 if (rPath.length() == keyLength)
473 regList.append(RegistryKey(keyName, QString(), false, access));
474 else if (rPath[keyLength] == QLatin1Char('\\'))
475 regList.append(RegistryKey(keyName, rPath.mid(keyLength+1), false, access));
476}
477
478bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const
479{
480 QString rSubkeyName = keyName(rSubKey);
481 QString rSubkeyPath = keyPath(rSubKey);
482
483 // open a handle on the subkey
484 HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath, access);
485 if (handle == 0)
486 return false;
487
488 // get the size and type of the value
489 DWORD dataType;
490 DWORD dataSize;
491 LONG res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize);
492 if (res != ERROR_SUCCESS) {
493 RegCloseKey(handle);
494 return false;
495 }
496
497 // workaround for rare cases where trailing '\0' are missing in registry
498 if (dataType == REG_SZ || dataType == REG_EXPAND_SZ)
499 dataSize += 2;
500 else if (dataType == REG_MULTI_SZ)
501 dataSize += 4;
502
503 // get the value
504 QByteArray data(dataSize, 0);
505 res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, 0,
506 reinterpret_cast<unsigned char*>(data.data()), &dataSize);
507 if (res != ERROR_SUCCESS) {
508 RegCloseKey(handle);
509 return false;
510 }
511
512 switch (dataType) {
513 case REG_EXPAND_SZ:
514 case REG_SZ: {
515 QString s;
516 if (dataSize) {
517 s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()));
518 }
519 if (value != 0)
520 *value = stringToVariant(s);
521 break;
522 }
523
524 case REG_MULTI_SZ: {
525 QStringList l;
526 if (dataSize) {
527 int i = 0;
528 for (;;) {
529 QString s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()) + i);
530 i += s.length() + 1;
531
532 if (s.isEmpty())
533 break;
534 l.append(s);
535 }
536 }
537 if (value != 0)
538 *value = stringListToVariantList(l);
539 break;
540 }
541
542 case REG_NONE:
543 case REG_BINARY: {
544 QString s;
545 if (dataSize) {
546 s = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.constData()), data.size() / 2);
547 }
548 if (value != 0)
549 *value = stringToVariant(s);
550 break;
551 }
552
553 case REG_DWORD_BIG_ENDIAN:
554 case REG_DWORD: {
555 Q_ASSERT(data.size() == sizeof(int));
556 int i;
557 memcpy(reinterpret_cast<char*>(&i), data.constData(), sizeof(int));
558 if (value != 0)
559 *value = i;
560 break;
561 }
562
563 case REG_QWORD: {
564 Q_ASSERT(data.size() == sizeof(qint64));
565 qint64 i;
566 memcpy(reinterpret_cast<char*>(&i), data.constData(), sizeof(qint64));
567 if (value != 0)
568 *value = i;
569 break;
570 }
571
572 default:
573 qWarning("QSettings: Unknown data %d type in Windows registry", static_cast<int>(dataType));
574 if (value != 0)
575 *value = QVariant();
576 break;
577 }
578
579 RegCloseKey(handle);
580 return true;
581}
582
583HKEY QWinSettingsPrivate::writeHandle() const
584{
585 if (regList.isEmpty())
586 return 0;
587 const RegistryKey &key = regList.at(0);
588 if (key.handle() == 0 || key.readOnly())
589 return 0;
590 return key.handle();
591}
592
593QWinSettingsPrivate::~QWinSettingsPrivate()
594{
595 if (deleteWriteHandleOnExit && writeHandle() != 0) {
596 QString emptyKey;
597 DWORD res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16()));
598 if (res != ERROR_SUCCESS) {
599 qErrnoWarning(int(res), "QSettings: Failed to delete key \"%ls\"",
600 qUtf16Printable(regList.constFirst().key()));
601 }
602 }
603
604 for (int i = 0; i < regList.size(); ++i)
605 regList[i].close();
606}
607
608void QWinSettingsPrivate::remove(const QString &uKey)
609{
610 if (writeHandle() == 0) {
611 setStatus(QSettings::AccessError);
612 return;
613 }
614
615 QString rKey = escapedKey(uKey);
616
617 // try to delete value bar in key foo
618 LONG res;
619 HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey), access);
620 if (handle != 0) {
621 res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()));
622 RegCloseKey(handle);
623 }
624
625 // try to delete key foo/bar and all subkeys
626 handle = openKey(writeHandle(), registryPermissions, rKey, access);
627 if (handle != 0) {
628 deleteChildGroups(handle, access);
629
630 if (rKey.isEmpty()) {
631 const QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
632
633 for (const QString &group : childKeys) {
634 LONG res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(group.utf16()));
635 if (res != ERROR_SUCCESS) {
636 qErrnoWarning(int(res), "QSettings: RegDeleteValue failed on subkey \"%ls\"",
637 qUtf16Printable(group));
638 }
639 }
640 } else {
641 res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(rKey.utf16()));
642
643 if (res != ERROR_SUCCESS) {
644 qErrnoWarning(int(res), "QSettings: RegDeleteKey failed on key \"%ls\"",
645 qUtf16Printable(rKey));
646 }
647 }
648 RegCloseKey(handle);
649 }
650}
651
652void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
653{
654 if (writeHandle() == 0) {
655 setStatus(QSettings::AccessError);
656 return;
657 }
658
659 QString rKey = escapedKey(uKey);
660
661 HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey), access);
662 if (handle == 0) {
663 setStatus(QSettings::AccessError);
664 return;
665 }
666
667 DWORD type;
668 QByteArray regValueBuff;
669
670 // Determine the type
671 switch (value.type()) {
672 case QVariant::List:
673 case QVariant::StringList: {
674 // If none of the elements contains '\0', we can use REG_MULTI_SZ, the
675 // native registry string list type. Otherwise we use REG_BINARY.
676 type = REG_MULTI_SZ;
677 QStringList l = variantListToStringList(value.toList());
678 QStringList::const_iterator it = l.constBegin();
679 for (; it != l.constEnd(); ++it) {
680 if ((*it).length() == 0 || it->contains(QChar::Null)) {
681 type = REG_BINARY;
682 break;
683 }
684 }
685
686 if (type == REG_BINARY) {
687 QString s = variantToString(value);
688 regValueBuff = QByteArray(reinterpret_cast<const char*>(s.utf16()), s.length() * 2);
689 } else {
690 QStringList::const_iterator it = l.constBegin();
691 for (; it != l.constEnd(); ++it) {
692 const QString &s = *it;
693 regValueBuff += QByteArray(reinterpret_cast<const char*>(s.utf16()), (s.length() + 1) * 2);
694 }
695 regValueBuff.append((char)0);
696 regValueBuff.append((char)0);
697 }
698 break;
699 }
700
701 case QVariant::Int:
702 case QVariant::UInt: {
703 type = REG_DWORD;
704 qint32 i = value.toInt();
705 regValueBuff = QByteArray(reinterpret_cast<const char*>(&i), sizeof(qint32));
706 break;
707 }
708
709 case QVariant::LongLong:
710 case QVariant::ULongLong: {
711 type = REG_QWORD;
712 qint64 i = value.toLongLong();
713 regValueBuff = QByteArray(reinterpret_cast<const char*>(&i), sizeof(qint64));
714 break;
715 }
716
717 case QVariant::ByteArray:
718 Q_FALLTHROUGH();
719
720 default: {
721 // If the string does not contain '\0', we can use REG_SZ, the native registry
722 // string type. Otherwise we use REG_BINARY.
723 QString s = variantToString(value);
724 type = s.contains(QChar::Null) ? REG_BINARY : REG_SZ;
725 int length = s.length();
726 if (type == REG_SZ)
727 ++length;
728 regValueBuff = QByteArray(reinterpret_cast<const char *>(s.utf16()),
729 int(sizeof(wchar_t)) * length);
730 break;
731 }
732 }
733
734 // set the value
735 LONG res = RegSetValueEx(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()), 0, type,
736 reinterpret_cast<const unsigned char*>(regValueBuff.constData()),
737 regValueBuff.size());
738
739 if (res == ERROR_SUCCESS) {
740 deleteWriteHandleOnExit = false;
741 } else {
742 qErrnoWarning(int(res), "QSettings: failed to set subkey \"%ls\"",
743 qUtf16Printable(rKey));
744 setStatus(QSettings::AccessError);
745 }
746
747 RegCloseKey(handle);
748}
749
750bool QWinSettingsPrivate::get(const QString &uKey, QVariant *value) const
751{
752 QString rKey = escapedKey(uKey);
753
754 for (const RegistryKey &r : regList) {
755 HKEY handle = r.handle();
756 if (handle != 0 && readKey(handle, rKey, value))
757 return true;
758
759 if (!fallbacks)
760 return false;
761 }
762
763 return false;
764}
765
766QStringList QWinSettingsPrivate::children(const QString &uKey, ChildSpec spec) const
767{
768 NameSet result;
769 QString rKey = escapedKey(uKey);
770
771 for (const RegistryKey &r : regList) {
772 HKEY parent_handle = r.handle();
773 if (parent_handle == 0)
774 continue;
775 HKEY handle = openKey(parent_handle, KEY_READ, rKey, access);
776 if (handle == 0)
777 continue;
778
779 if (spec == AllKeys) {
780 NameSet keys;
781 allKeys(handle, QLatin1String(""), &keys, access);
782 mergeKeySets(&result, keys);
783 } else { // ChildGroups or ChildKeys
784 QStringList names = childKeysOrGroups(handle, spec);
785 mergeKeySets(&result, names);
786 }
787
788 RegCloseKey(handle);
789
790 if (!fallbacks)
791 return result.keys();
792 }
793
794 return result.keys();
795}
796
797void QWinSettingsPrivate::clear()
798{
799 remove(QString());
800 deleteWriteHandleOnExit = true;
801}
802
803void QWinSettingsPrivate::sync()
804{
805 RegFlushKey(writeHandle());
806}
807
808void QWinSettingsPrivate::flush()
809{
810 // Windows does this for us.
811}
812
813QString QWinSettingsPrivate::fileName() const
814{
815 if (regList.isEmpty())
816 return QString();
817
818 const RegistryKey &key = regList.at(0);
819 QString result;
820 if (key.parentHandle() == HKEY_CURRENT_USER)
821 result = QLatin1String("\\HKEY_CURRENT_USER\\");
822 else
823 result = QLatin1String("\\HKEY_LOCAL_MACHINE\\");
824
825 return result + regList.at(0).key();
826}
827
828bool QWinSettingsPrivate::isWritable() const
829{
830 return writeHandle() != 0;
831}
832
833QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
834 const QString &organization, const QString &application)
835{
836 switch (format) {
837 case QSettings::NativeFormat:
838 return new QWinSettingsPrivate(scope, organization, application);
839 case QSettings::Registry32Format:
840 return new QWinSettingsPrivate(scope, organization, application, KEY_WOW64_32KEY);
841 case QSettings::Registry64Format:
842 return new QWinSettingsPrivate(scope, organization, application, KEY_WOW64_64KEY);
843 default:
844 break;
845 }
846 return new QConfFileSettingsPrivate(format, scope, organization, application);
847}
848
849QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
850{
851 switch (format) {
852 case QSettings::NativeFormat:
853 return new QWinSettingsPrivate(fileName);
854 case QSettings::Registry32Format:
855 return new QWinSettingsPrivate(fileName, KEY_WOW64_32KEY);
856 case QSettings::Registry64Format:
857 return new QWinSettingsPrivate(fileName, KEY_WOW64_64KEY);
858 default:
859 break;
860 }
861 return new QConfFileSettingsPrivate(fileName, format);
862}
863
864QT_END_NAMESPACE
865

Warning: That file was not part of the compilation database. It may have many parsing errors.