Qt 4.8
qsettings_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qsettings.h"
43 
44 #ifndef QT_NO_SETTINGS
45 
46 #include "qsettings_p.h"
47 #include "qvector.h"
48 #include "qmap.h"
49 #include "qt_windows.h"
50 #include "qdebug.h"
51 
53 
54 /* Keys are stored in QStrings. If the variable name starts with 'u', this is a "user"
55  key, ie. "foo/bar/alpha/beta". If the variable name starts with 'r', this is a "registry"
56  key, ie. "\foo\bar\alpha\beta". */
57 
58 /*******************************************************************************
59 ** Some convenience functions
60 */
61 
62 /*
63  We don't use KEY_ALL_ACCESS because it gives more rights than what we
64  need. See task 199061.
65  */
66 static const REGSAM registryPermissions = KEY_READ | KEY_WRITE;
67 
68 static QString keyPath(const QString &rKey)
69 {
70  int idx = rKey.lastIndexOf(QLatin1Char('\\'));
71  if (idx == -1)
72  return QString();
73  return rKey.left(idx + 1);
74 }
75 
76 static QString keyName(const QString &rKey)
77 {
78  int idx = rKey.lastIndexOf(QLatin1Char('\\'));
79 
80  QString res;
81  if (idx == -1)
82  res = rKey;
83  else
84  res = rKey.mid(idx + 1);
85 
86  if (res == QLatin1String("Default") || res == QLatin1String("."))
87  res = QLatin1String("");
88 
89  return res;
90 }
91 
93 {
94  QChar *data = uKey.data();
95  int l = uKey.length();
96  for (int i = 0; i < l; ++i) {
97  ushort &ucs = data[i].unicode();
98  if (ucs == '\\')
99  ucs = '/';
100  else if (ucs == '/')
101  ucs = '\\';
102  }
103  return uKey;
104 }
105 
107 {
108  return escapedKey(rKey);
109 }
110 
112 
113 static void mergeKeySets(NameSet *dest, const NameSet &src)
114 {
116  for (; it != src.constEnd(); ++it)
117  dest->insert(unescapedKey(it.key()), QString());
118 }
119 
120 static void mergeKeySets(NameSet *dest, const QStringList &src)
121 {
123  for (; it != src.constEnd(); ++it)
124  dest->insert(unescapedKey(*it), QString());
125 }
126 
127 /*******************************************************************************
128 ** Wrappers for the insane windows registry API
129 */
130 
131 static QString errorCodeToString(DWORD errorCode)
132 {
133  wchar_t *data = 0;
134  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, 0, 0);
135  QString result = QString::fromWCharArray(data);
136 
137  if (data != 0)
138  LocalFree(data);
139 
140  if (result.endsWith(QLatin1Char('\n')))
141  result.truncate(result.length() - 1);
142 
143  return result;
144 }
145 
146 // Open a key with the specified perms
147 static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
148 {
149  HKEY resultHandle = 0;
150  LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
151  0, perms, &resultHandle);
152 
153  if (res == ERROR_SUCCESS)
154  return resultHandle;
155 
156  return 0;
157 }
158 
159 // Open a key with the specified perms, create it if it does not exist
160 static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
161 {
162  // try to open it
163  HKEY resultHandle = openKey(parentHandle, perms, rSubKey);
164  if (resultHandle != 0)
165  return resultHandle;
166 
167  // try to create it
168  LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0,
169  REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0);
170 
171  if (res == ERROR_SUCCESS)
172  return resultHandle;
173 
174  //qWarning("QSettings: Failed to create subkey \"%s\": %s",
175  // rSubKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
176 
177  return 0;
178 }
179 
180 // Open or create a key in read-write mode if possible, otherwise read-only
181 static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *readOnly)
182 {
183  // try to open or create it read/write
184  HKEY resultHandle = createOrOpenKey(parentHandle, registryPermissions, rSubKey);
185  if (resultHandle != 0) {
186  if (readOnly != 0)
187  *readOnly = false;
188  return resultHandle;
189  }
190 
191  // try to open or create it read/only
192  resultHandle = createOrOpenKey(parentHandle, KEY_READ, rSubKey);
193  if (resultHandle != 0) {
194  if (readOnly != 0)
195  *readOnly = true;
196  return resultHandle;
197  }
198  return 0;
199 }
200 
202 {
203  QStringList result;
204  DWORD numKeys;
205  DWORD maxKeySize;
206  DWORD numSubgroups;
207  DWORD maxSubgroupSize;
208 
209  // Find the number of keys and subgroups, as well as the max of their lengths.
210  LONG res = RegQueryInfoKey(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0,
211  &numKeys, &maxKeySize, 0, 0, 0);
212 
213  if (res != ERROR_SUCCESS) {
214  qWarning("QSettings: RegQueryInfoKey() failed: %s", errorCodeToString(res).toLatin1().data());
215  return result;
216  }
217 
218  ++maxSubgroupSize;
219  ++maxKeySize;
220 
221  int n;
222  int m;
223  if (spec == QSettingsPrivate::ChildKeys) {
224  n = numKeys;
225  m = maxKeySize;
226  } else {
227  n = numSubgroups;
228  m = maxSubgroupSize;
229  }
230 
231  /* The size does not include the terminating null character. */
232  ++m;
233 
234  // Get the list
235  QByteArray buff(m * sizeof(wchar_t), 0);
236  for (int i = 0; i < n; ++i) {
237  QString item;
238  DWORD l = buff.size() / sizeof(wchar_t);
239  if (spec == QSettingsPrivate::ChildKeys) {
240  res = RegEnumValue(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
241  } else {
242  res = RegEnumKeyEx(parentHandle, i, reinterpret_cast<wchar_t *>(buff.data()), &l, 0, 0, 0, 0);
243  }
244  if (res == ERROR_SUCCESS)
245  item = QString::fromWCharArray((const wchar_t *)buff.constData(), l);
246 
247  if (res != ERROR_SUCCESS) {
248  qWarning("QSettings: RegEnumValue failed: %s", errorCodeToString(res).toLatin1().data());
249  continue;
250  }
251  if (item.isEmpty())
252  item = QLatin1String(".");
253  result.append(item);
254  }
255  return result;
256 }
257 
258 static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result)
259 {
260  HKEY handle = openKey(parentHandle, KEY_READ, rSubKey);
261  if (handle == 0)
262  return;
263 
266  RegCloseKey(handle);
267 
268  for (int i = 0; i < childKeys.size(); ++i) {
269  QString s = rSubKey;
270  if (!s.isEmpty())
271  s += QLatin1Char('\\');
272  s += childKeys.at(i);
273  result->insert(s, QString());
274  }
275 
276  for (int i = 0; i < childGroups.size(); ++i) {
277  QString s = rSubKey;
278  if (!s.isEmpty())
279  s += QLatin1Char('\\');
280  s += childGroups.at(i);
281  allKeys(parentHandle, s, result);
282  }
283 }
284 
285 static void deleteChildGroups(HKEY parentHandle)
286 {
287  QStringList childGroups = childKeysOrGroups(parentHandle, QSettingsPrivate::ChildGroups);
288 
289  for (int i = 0; i < childGroups.size(); ++i) {
290  QString group = childGroups.at(i);
291 
292  // delete subgroups in group
293  HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group);
294  if (childGroupHandle == 0)
295  continue;
296  deleteChildGroups(childGroupHandle);
297  RegCloseKey(childGroupHandle);
298 
299  // delete group itself
300  LONG res = RegDeleteKey(parentHandle, reinterpret_cast<const wchar_t *>(group.utf16()));
301  if (res != ERROR_SUCCESS) {
302  qWarning("QSettings: RegDeleteKey failed on subkey \"%s\": %s",
303  group.toLatin1().data(), errorCodeToString(res).toLatin1().data());
304  return;
305  }
306  }
307 }
308 
309 /*******************************************************************************
310 ** class RegistryKey
311 */
312 
314 {
315 public:
316  RegistryKey(HKEY parent_handle = 0, const QString &key = QString(), bool read_only = true);
317  QString key() const;
318  HKEY handle() const;
319  HKEY parentHandle() const;
320  bool readOnly() const;
321  void close();
322 private:
324  mutable HKEY m_handle;
326  mutable bool m_read_only;
327 };
328 
329 RegistryKey::RegistryKey(HKEY parent_handle, const QString &key, bool read_only)
330 {
331  m_parent_handle = parent_handle;
332  m_handle = 0;
333  m_read_only = read_only;
334  m_key = key;
335 }
336 
338 {
339  return m_key;
340 }
341 
343 {
344  if (m_handle != 0)
345  return m_handle;
346 
347  if (m_read_only)
348  m_handle = openKey(m_parent_handle, KEY_READ, m_key);
349  else
351 
352  return m_handle;
353 }
354 
356 {
357  return m_parent_handle;
358 }
359 
361 {
362  return m_read_only;
363 }
364 
366 {
367  if (m_handle != 0)
368  RegCloseKey(m_handle);
369  m_handle = 0;
370 }
371 
373 
374 /*******************************************************************************
375 ** class QWinSettingsPrivate
376 */
377 
379 {
380 public:
381  QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
382  const QString &application);
385 
386  void remove(const QString &uKey);
387  void set(const QString &uKey, const QVariant &value);
388  bool get(const QString &uKey, QVariant *value) const;
389  QStringList children(const QString &uKey, ChildSpec spec) const;
390  void clear();
391  void sync();
392  void flush();
393  bool isWritable() const;
394  HKEY writeHandle() const;
395  bool readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const;
396  QString fileName() const;
397 
398 private:
399  RegistryKeyList regList; // list of registry locations to search for keys
401 };
402 
404  const QString &application)
405  : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application)
406 {
407  deleteWriteHandleOnExit = false;
408 
409  if (!organization.isEmpty()) {
410  QString prefix = QLatin1String("Software\\") + organization;
411  QString orgPrefix = prefix + QLatin1String("\\OrganizationDefaults");
412  QString appPrefix = prefix + QLatin1Char('\\') + application;
413 
414  if (scope == QSettings::UserScope) {
415  if (!application.isEmpty())
416  regList.append(RegistryKey(HKEY_CURRENT_USER, appPrefix, !regList.isEmpty()));
417 
418  regList.append(RegistryKey(HKEY_CURRENT_USER, orgPrefix, !regList.isEmpty()));
419  }
420 
421  if (!application.isEmpty())
422  regList.append(RegistryKey(HKEY_LOCAL_MACHINE, appPrefix, !regList.isEmpty()));
423 
424  regList.append(RegistryKey(HKEY_LOCAL_MACHINE, orgPrefix, !regList.isEmpty()));
425  }
426 
427  if (regList.isEmpty())
429 }
430 
432  : QSettingsPrivate(QSettings::NativeFormat)
433 {
434  deleteWriteHandleOnExit = false;
435 
436  if (rPath.startsWith(QLatin1String("\\")))
437  rPath = rPath.mid(1);
438 
439  if (rPath.startsWith(QLatin1String("HKEY_CURRENT_USER\\")))
440  regList.append(RegistryKey(HKEY_CURRENT_USER, rPath.mid(18), false));
441  else if (rPath == QLatin1String("HKEY_CURRENT_USER"))
442  regList.append(RegistryKey(HKEY_CURRENT_USER, QString(), false));
443  else if (rPath.startsWith(QLatin1String("HKEY_LOCAL_MACHINE\\")))
444  regList.append(RegistryKey(HKEY_LOCAL_MACHINE, rPath.mid(19), false));
445  else if (rPath == QLatin1String("HKEY_LOCAL_MACHINE"))
446  regList.append(RegistryKey(HKEY_LOCAL_MACHINE, QString(), false));
447  else if (rPath.startsWith(QLatin1String("HKEY_CLASSES_ROOT\\")))
448  regList.append(RegistryKey(HKEY_CLASSES_ROOT, rPath.mid(18), false));
449  else if (rPath == QLatin1String("HKEY_CLASSES_ROOT"))
450  regList.append(RegistryKey(HKEY_CLASSES_ROOT, QString(), false));
451  else if (rPath.startsWith(QLatin1String("HKEY_USERS\\")))
452  regList.append(RegistryKey(HKEY_USERS, rPath.mid(11), false));
453  else if (rPath == QLatin1String(QLatin1String("HKEY_USERS")))
454  regList.append(RegistryKey(HKEY_USERS, QString(), false));
455  else
456  regList.append(RegistryKey(HKEY_LOCAL_MACHINE, rPath, false));
457 }
458 
459 bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const
460 {
461  QString rSubkeyName = keyName(rSubKey);
462  QString rSubkeyPath = keyPath(rSubKey);
463 
464  // open a handle on the subkey
465  HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath);
466  if (handle == 0)
467  return false;
468 
469  // get the size and type of the value
470  DWORD dataType;
471  DWORD dataSize;
472  LONG res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize);
473  if (res != ERROR_SUCCESS) {
474  RegCloseKey(handle);
475  return false;
476  }
477 
478  // get the value
479  QByteArray data(dataSize, 0);
480  res = RegQueryValueEx(handle, reinterpret_cast<const wchar_t *>(rSubkeyName.utf16()), 0, 0,
481  reinterpret_cast<unsigned char*>(data.data()), &dataSize);
482  if (res != ERROR_SUCCESS) {
483  RegCloseKey(handle);
484  return false;
485  }
486 
487  switch (dataType) {
488  case REG_EXPAND_SZ:
489  case REG_SZ: {
490  QString s;
491  if (dataSize) {
492  s = QString::fromWCharArray(((const wchar_t *)data.constData()));
493  }
494  if (value != 0)
495  *value = stringToVariant(s);
496  break;
497  }
498 
499  case REG_MULTI_SZ: {
500  QStringList l;
501  if (dataSize) {
502  int i = 0;
503  for (;;) {
504  QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
505  i += s.length() + 1;
506 
507  if (s.isEmpty())
508  break;
509  l.append(s);
510  }
511  }
512  if (value != 0)
513  *value = stringListToVariantList(l);
514  break;
515  }
516 
517  case REG_NONE:
518  case REG_BINARY: {
519  QString s;
520  if (dataSize) {
521  s = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
522  }
523  if (value != 0)
524  *value = stringToVariant(s);
525  break;
526  }
527 
528  case REG_DWORD_BIG_ENDIAN:
529  case REG_DWORD: {
530  Q_ASSERT(data.size() == sizeof(int));
531  int i;
532  memcpy((char*)&i, data.constData(), sizeof(int));
533  if (value != 0)
534  *value = i;
535  break;
536  }
537 
538  case REG_QWORD: {
539  Q_ASSERT(data.size() == sizeof(qint64));
540  qint64 i;
541  memcpy((char*)&i, data.constData(), sizeof(qint64));
542  if (value != 0)
543  *value = i;
544  break;
545  }
546 
547  default:
548  qWarning("QSettings: Unknown data %d type in Windows registry", static_cast<int>(dataType));
549  if (value != 0)
550  *value = QVariant();
551  break;
552  }
553 
554  RegCloseKey(handle);
555  return true;
556 }
557 
559 {
560  if (regList.isEmpty())
561  return 0;
562  const RegistryKey &key = regList.at(0);
563  if (key.handle() == 0 || key.readOnly())
564  return 0;
565  return key.handle();
566 }
567 
569 {
570  if (deleteWriteHandleOnExit && writeHandle() != 0) {
571 #if defined(Q_OS_WINCE)
572  remove(regList.at(0).key());
573 #else
574  QString emptyKey;
575  DWORD res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(emptyKey.utf16()));
576  if (res != ERROR_SUCCESS) {
577  qWarning("QSettings: Failed to delete key \"%s\": %s",
579  }
580 #endif
581  }
582 
583  for (int i = 0; i < regList.size(); ++i)
584  regList[i].close();
585 }
586 
588 {
589  if (writeHandle() == 0) {
591  return;
592  }
593 
594  QString rKey = escapedKey(uKey);
595 
596  // try to delete value bar in key foo
597  LONG res;
598  HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey));
599  if (handle != 0) {
600  res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()));
601  RegCloseKey(handle);
602  }
603 
604  // try to delete key foo/bar and all subkeys
605  handle = openKey(writeHandle(), registryPermissions, rKey);
606  if (handle != 0) {
607  deleteChildGroups(handle);
608 
609  if (rKey.isEmpty()) {
611 
612  for (int i = 0; i < childKeys.size(); ++i) {
613  QString group = childKeys.at(i);
614 
615  LONG res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(group.utf16()));
616  if (res != ERROR_SUCCESS) {
617  qWarning("QSettings: RegDeleteValue failed on subkey \"%s\": %s",
618  group.toLatin1().data(), errorCodeToString(res).toLatin1().data());
619  }
620  }
621  } else {
622 #if defined(Q_OS_WINCE)
623  // For WinCE always Close the handle first.
624  RegCloseKey(handle);
625 #endif
626  res = RegDeleteKey(writeHandle(), reinterpret_cast<const wchar_t *>(rKey.utf16()));
627 
628  if (res != ERROR_SUCCESS) {
629  qWarning("QSettings: RegDeleteKey failed on key \"%s\": %s",
630  rKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
631  }
632  }
633  RegCloseKey(handle);
634  }
635 }
636 
637 static bool stringContainsNullChar(const QString &s)
638 {
639  for (int i = 0; i < s.length(); ++i) {
640  if (s.at(i).unicode() == 0)
641  return true;
642  }
643  return false;
644 }
645 
646 void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
647 {
648  if (writeHandle() == 0) {
650  return;
651  }
652 
653  QString rKey = escapedKey(uKey);
654 
655  HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey));
656  if (handle == 0) {
658  return;
659  }
660 
661  DWORD type;
662  QByteArray regValueBuff;
663 
664  // Determine the type
665  switch (value.type()) {
666  case QVariant::List:
667  case QVariant::StringList: {
668  // If none of the elements contains '\0', we can use REG_MULTI_SZ, the
669  // native registry string list type. Otherwise we use REG_BINARY.
670  type = REG_MULTI_SZ;
673  for (; it != l.constEnd(); ++it) {
674  if ((*it).length() == 0 || stringContainsNullChar(*it)) {
675  type = REG_BINARY;
676  break;
677  }
678  }
679 
680  if (type == REG_BINARY) {
681  QString s = variantToString(value);
682  regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
683  } else {
685  for (; it != l.constEnd(); ++it) {
686  const QString &s = *it;
687  regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
688  }
689  regValueBuff.append((char)0);
690  regValueBuff.append((char)0);
691  }
692  break;
693  }
694 
695  case QVariant::Int:
696  case QVariant::UInt: {
697  type = REG_DWORD;
698  qint32 i = value.toInt();
699  regValueBuff = QByteArray((const char*)&i, sizeof(qint32));
700  break;
701  }
702 
703  case QVariant::LongLong:
704  case QVariant::ULongLong: {
705  type = REG_QWORD;
706  qint64 i = value.toLongLong();
707  regValueBuff = QByteArray((const char*)&i, sizeof(qint64));
708  break;
709  }
710 
711  case QVariant::ByteArray:
712  // fallthrough intended
713 
714  default: {
715  // If the string does not contain '\0', we can use REG_SZ, the native registry
716  // string type. Otherwise we use REG_BINARY.
717  QString s = variantToString(value);
718  type = stringContainsNullChar(s) ? REG_BINARY : REG_SZ;
719  if (type == REG_BINARY) {
720  regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
721  } else {
722  regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1) * 2);
723  }
724  break;
725  }
726  }
727 
728  // set the value
729  LONG res = RegSetValueEx(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()), 0, type,
730  reinterpret_cast<const unsigned char*>(regValueBuff.constData()),
731  regValueBuff.size());
732 
733  if (res == ERROR_SUCCESS) {
734  deleteWriteHandleOnExit = false;
735  } else {
736  qWarning("QSettings: failed to set subkey \"%s\": %s",
737  rKey.toLatin1().data(), errorCodeToString(res).toLatin1().data());
739  }
740 
741  RegCloseKey(handle);
742 }
743 
744 bool QWinSettingsPrivate::get(const QString &uKey, QVariant *value) const
745 {
746  QString rKey = escapedKey(uKey);
747 
748  for (int i = 0; i < regList.size(); ++i) {
749  HKEY handle = regList.at(i).handle();
750  if (handle != 0 && readKey(handle, rKey, value))
751  return true;
752 
753  if (!fallbacks)
754  return false;
755  }
756 
757  return false;
758 }
759 
761 {
762  NameSet result;
763  QString rKey = escapedKey(uKey);
764 
765  for (int i = 0; i < regList.size(); ++i) {
766  HKEY parent_handle = regList.at(i).handle();
767  if (parent_handle == 0)
768  continue;
769  HKEY handle = openKey(parent_handle, KEY_READ, rKey);
770  if (handle == 0)
771  continue;
772 
773  if (spec == AllKeys) {
774  NameSet keys;
775  allKeys(handle, QLatin1String(""), &keys);
776  mergeKeySets(&result, keys);
777  } else { // ChildGroups or ChildKeys
778  QStringList names = childKeysOrGroups(handle, spec);
779  mergeKeySets(&result, names);
780  }
781 
782  RegCloseKey(handle);
783 
784  if (!fallbacks)
785  return result.keys();
786  }
787 
788  return result.keys();
789 }
790 
792 {
793  remove(QString());
795 }
796 
798 {
799  RegFlushKey(writeHandle());
800 }
801 
803 {
804  // Windows does this for us.
805 }
806 
808 {
809  if (regList.isEmpty())
810  return QString();
811 
812  const RegistryKey &key = regList.at(0);
813  QString result;
814  if (key.parentHandle() == HKEY_CURRENT_USER)
815  result = QLatin1String("\\HKEY_CURRENT_USER\\");
816  else
817  result = QLatin1String("\\HKEY_LOCAL_MACHINE\\");
818 
819  return result + regList.at(0).key();
820 }
821 
823 {
824  return writeHandle() != 0;
825 }
826 
828  const QString &organization, const QString &application)
829 {
831  return new QWinSettingsPrivate(scope, organization, application);
832  } else {
833  return new QConfFileSettingsPrivate(format, scope, organization, application);
834  }
835 }
836 
838 {
839  if (format == QSettings::NativeFormat) {
840  return new QWinSettingsPrivate(fileName);
841  } else {
842  return new QConfFileSettingsPrivate(fileName, format);
843  }
844 }
845 
847 #endif // QT_NO_SETTINGS
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QMap< QString, QString > NameSet
QString key() const
static QString fromWCharArray(const wchar_t *, int size=-1)
Returns a copy of the string, where the encoding of string depends on the size of wchar...
Definition: qstring.cpp:1019
Scope
) in file paths:
Definition: qsettings.h:115
static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result)
void setStatus(QSettings::Status status) const
Definition: qsettings.cpp:410
RegistryKey(HKEY parent_handle=0, const QString &key=QString(), bool read_only=true)
static QString unescapedKey(QString rKey)
static QString keyName(const QString &rKey)
int type
Definition: qmetatype.cpp:239
QString fileName() const
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int qint32
Definition: qglobal.h:937
static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildSpec spec)
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
ushort unicode() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qchar.h:251
#define it(className, varName)
QByteArray & append(char c)
Appends the character ch to this byte array.
static const REGSAM registryPermissions
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
QStringList children(const QString &uKey, ChildSpec spec) const
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
Format
This enum type specifies the storage format used by QSettings.
Definition: qsettings.h:92
static void clear(QVariant::Private *d)
Definition: qvariant.cpp:197
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the list.
Definition: qlist.h:269
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QWinSettingsPrivate(QSettings::Scope scope, const QString &organization, const QString &application)
QSettings::Scope scope
Definition: qsettings_p.h:259
QList< QVariant > toList() const
Returns the variant as a QVariantList if the variant has type() List or StringList ; otherwise return...
Definition: qvariant.cpp:2751
static QString keyPath(const QString &rKey)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
The QString class provides a Unicode character string.
Definition: qstring.h:83
static QSettingsPrivate * create(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application)
static QStringList variantListToStringList(const QVariantList &l)
Definition: qsettings.cpp:435
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static void deleteChildGroups(HKEY parentHandle)
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
QChar * data()
Returns a pointer to the data stored in the QString.
Definition: qstring.h:710
QStringList keys
RegistryKeyList regList
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
HKEY writeHandle() const
friend class const_iterator
Definition: qlist.h:264
static QString errorCodeToString(DWORD errorCode)
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
static bool stringContainsNullChar(const QString &s)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
qlonglong toLongLong(bool *ok=0) const
Returns the variant as a long long int if the variant has type() LongLong , Bool , ByteArray , Char , Double , Int , String , UInt , or ULongLong ; otherwise returns 0.
Definition: qvariant.cpp:2659
void truncate(int pos)
Truncates the string at the given position index.
Definition: qstring.cpp:4603
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void append(const T &t)
Inserts value at the end of the vector.
Definition: qvector.h:573
HKEY handle() const
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QList< Key > keys() const
Returns a list containing all the keys in the map in ascending order.
Definition: qmap.h:818
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
__int64 qint64
Definition: qglobal.h:942
static QString variantToString(const QVariant &v)
Definition: qsettings.cpp:464
static void mergeKeySets(NameSet *dest, const NameSet &src)
bool readOnly() const
const_iterator constBegin() const
Returns a const STL-style iterator pointing to the first item in the map.
Definition: qmap.h:374
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
static QVariant stringListToVariantList(const QStringList &l)
Definition: qsettings.cpp:444
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
QString mid(int position, int n=-1) const Q_REQUIRED_RESULT
Returns a string that contains n characters of this string, starting at the specified position index...
Definition: qstring.cpp:3706
void set(const QString &uKey, const QVariant &value)
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the map...
Definition: qmap.h:380
unsigned short ushort
Definition: qglobal.h:995
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
Type type() const
Returns the storage type of the value stored in the variant.
Definition: qvariant.cpp:1901
iterator insert(const Key &key, const T &value)
Inserts a new item with the key key and a value of value.
Definition: qmap.h:559
bool readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const
int key
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
QFactoryLoader * l
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
HKEY parentHandle() const
Q_CORE_EXPORT QTextStream & flush(QTextStream &s)
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
static QVariant stringToVariant(const QString &s)
Definition: qsettings.cpp:551
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
QVector< RegistryKey > RegistryKeyList
bool get(const QString &uKey, QVariant *value) const
static QString fileName(const QString &fileUrl)
bool isWritable() const
int size() const
Returns the number of items in the vector.
Definition: qvector.h:137
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
const_iterator constEnd() const
Returns a const STL-style iterator pointing to the imaginary item after the last item in the list...
Definition: qlist.h:272
static QString escapedKey(QString uKey)
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
friend class const_iterator
Definition: qmap.h:369
void remove(const QString &uKey)