summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qsettings_win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/io/qsettings_win.cpp')
-rw-r--r--src/corelib/io/qsettings_win.cpp154
1 files changed, 93 insertions, 61 deletions
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index f6ad182c37..53e1ed360b 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -1,31 +1,37 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 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:LGPL21$
+** $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 http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** 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 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** 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.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** 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$
**
@@ -41,6 +47,18 @@
#include "qdebug.h"
#include <qt_windows.h>
+// See "Accessing an Alternate Registry View" at:
+// http://msdn.microsoft.com/en-us/library/aa384129%28VS.85%29.aspx
+#ifndef KEY_WOW64_64KEY
+ // Access a 32-bit key from either a 32-bit or 64-bit application.
+# define KEY_WOW64_64KEY 0x0100
+#endif
+
+#ifndef KEY_WOW64_32KEY
+ // Access a 64-bit key from either a 32-bit or 64-bit application.
+# define KEY_WOW64_32KEY 0x0200
+#endif
+
QT_BEGIN_NAMESPACE
/* Keys are stored in QStrings. If the variable name starts with 'u', this is a "user"
@@ -135,12 +153,13 @@ static QString errorCodeToString(DWORD errorCode)
return result;
}
-// Open a key with the specified perms
-static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
+// 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)
{
HKEY resultHandle = 0;
LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
- 0, perms, &resultHandle);
+ 0, perms | access, &resultHandle);
if (res == ERROR_SUCCESS)
return resultHandle;
@@ -148,17 +167,18 @@ static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
return 0;
}
-// Open a key with the specified perms, create it if it does not exist
-static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
+// Open a key with the specified "perms", create it if it does not exist.
+// "access" is to explicitly use the 32- or 64-bit branch.
+static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey, REGSAM access = 0)
{
// try to open it
- HKEY resultHandle = openKey(parentHandle, perms, rSubKey);
+ HKEY resultHandle = openKey(parentHandle, perms, rSubKey, access);
if (resultHandle != 0)
return resultHandle;
// try to create it
LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0,
- REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0);
+ REG_OPTION_NON_VOLATILE, perms | access, 0, &resultHandle, 0);
if (res == ERROR_SUCCESS)
return resultHandle;
@@ -169,11 +189,12 @@ static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSub
return 0;
}
-// Open or create a key in read-write mode if possible, otherwise read-only
-static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *readOnly)
+// Open or create a key in read-write mode if possible, otherwise read-only.
+// "access" is to explicitly use the 32- or 64-bit branch.
+static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *readOnly, REGSAM access = 0)
{
// try to open or create it read/write
- HKEY resultHandle = createOrOpenKey(parentHandle, registryPermissions, rSubKey);
+ HKEY resultHandle = createOrOpenKey(parentHandle, registryPermissions, rSubKey, access);
if (resultHandle != 0) {
if (readOnly != 0)
*readOnly = false;
@@ -181,7 +202,7 @@ static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *rea
}
// try to open or create it read/only
- resultHandle = createOrOpenKey(parentHandle, KEY_READ, rSubKey);
+ resultHandle = createOrOpenKey(parentHandle, KEY_READ, rSubKey, access);
if (resultHandle != 0) {
if (readOnly != 0)
*readOnly = true;
@@ -247,9 +268,9 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
return result;
}
-static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result)
+static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result, REGSAM access = 0)
{
- HKEY handle = openKey(parentHandle, KEY_READ, rSubKey);
+ HKEY handle = openKey(parentHandle, KEY_READ, rSubKey, access);
if (handle == 0)
return;
@@ -270,11 +291,11 @@ static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result)
if (!s.isEmpty())
s += QLatin1Char('\\');
s += childGroups.at(i);
- allKeys(parentHandle, s, result);
+ allKeys(parentHandle, s, result, access);
}
}
-static void deleteChildGroups(HKEY parentHandle)
+static void deleteChildGroups(HKEY parentHandle, REGSAM access = 0)
{
QStringList childGroups = childKeysOrGroups(parentHandle, QSettingsPrivate::ChildGroups);
@@ -282,10 +303,10 @@ static void deleteChildGroups(HKEY parentHandle)
QString group = childGroups.at(i);
// delete subgroups in group
- HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group);
+ HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group, access);
if (childGroupHandle == 0)
continue;
- deleteChildGroups(childGroupHandle);
+ deleteChildGroups(childGroupHandle, access);
RegCloseKey(childGroupHandle);
// delete group itself
@@ -305,7 +326,7 @@ static void deleteChildGroups(HKEY parentHandle)
class RegistryKey
{
public:
- RegistryKey(HKEY parent_handle = 0, const QString &key = QString(), bool read_only = true);
+ RegistryKey(HKEY parent_handle = 0, const QString &key = QString(), bool read_only = true, REGSAM access = 0);
QString key() const;
HKEY handle() const;
HKEY parentHandle() const;
@@ -316,13 +337,15 @@ private:
mutable HKEY m_handle;
QString m_key;
mutable bool m_read_only;
+ REGSAM m_access;
};
-RegistryKey::RegistryKey(HKEY parent_handle, const QString &key, bool read_only)
+RegistryKey::RegistryKey(HKEY parent_handle, const QString &key, bool read_only, REGSAM access)
: m_parent_handle(parent_handle),
m_handle(0),
m_key(key),
- m_read_only(read_only)
+ m_read_only(read_only),
+ m_access(access)
{
}
@@ -337,9 +360,9 @@ HKEY RegistryKey::handle() const
return m_handle;
if (m_read_only)
- m_handle = openKey(m_parent_handle, KEY_READ, m_key);
+ m_handle = openKey(m_parent_handle, KEY_READ, m_key, m_access);
else
- m_handle = createOrOpenKey(m_parent_handle, m_key, &m_read_only);
+ m_handle = createOrOpenKey(m_parent_handle, m_key, &m_read_only, m_access);
return m_handle;
}
@@ -371,8 +394,8 @@ class QWinSettingsPrivate : public QSettingsPrivate
{
public:
QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
- const QString &application);
- QWinSettingsPrivate(QString rKey);
+ const QString &application, REGSAM access = 0);
+ QWinSettingsPrivate(QString rKey, REGSAM access = 0);
~QWinSettingsPrivate();
void remove(const QString &uKey);
@@ -390,11 +413,13 @@ public:
private:
RegistryKeyList regList; // list of registry locations to search for keys
bool deleteWriteHandleOnExit;
+ REGSAM access;
};
QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
- const QString &application)
- : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application)
+ const QString &application, REGSAM access)
+ : QSettingsPrivate(QSettings::NativeFormat, scope, organization, application),
+ access(access)
{
deleteWriteHandleOnExit = false;
@@ -405,23 +430,24 @@ QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &
if (scope == QSettings::UserScope) {
if (!application.isEmpty())
- regList.append(RegistryKey(HKEY_CURRENT_USER, appPrefix, !regList.isEmpty()));
+ regList.append(RegistryKey(HKEY_CURRENT_USER, appPrefix, !regList.isEmpty(), access));
- regList.append(RegistryKey(HKEY_CURRENT_USER, orgPrefix, !regList.isEmpty()));
+ regList.append(RegistryKey(HKEY_CURRENT_USER, orgPrefix, !regList.isEmpty(), access));
}
if (!application.isEmpty())
- regList.append(RegistryKey(HKEY_LOCAL_MACHINE, appPrefix, !regList.isEmpty()));
+ regList.append(RegistryKey(HKEY_LOCAL_MACHINE, appPrefix, !regList.isEmpty(), access));
- regList.append(RegistryKey(HKEY_LOCAL_MACHINE, orgPrefix, !regList.isEmpty()));
+ regList.append(RegistryKey(HKEY_LOCAL_MACHINE, orgPrefix, !regList.isEmpty(), access));
}
if (regList.isEmpty())
setStatus(QSettings::AccessError);
}
-QWinSettingsPrivate::QWinSettingsPrivate(QString rPath)
- : QSettingsPrivate(QSettings::NativeFormat)
+QWinSettingsPrivate::QWinSettingsPrivate(QString rPath, REGSAM access)
+ : QSettingsPrivate(QSettings::NativeFormat),
+ access(access)
{
deleteWriteHandleOnExit = false;
@@ -460,9 +486,9 @@ QWinSettingsPrivate::QWinSettingsPrivate(QString rPath)
}
if (rPath.length() == keyLength)
- regList.append(RegistryKey(keyName, QString(), false));
+ regList.append(RegistryKey(keyName, QString(), false, access));
else if (rPath[keyLength] == QLatin1Char('\\'))
- regList.append(RegistryKey(keyName, rPath.mid(keyLength+1), false));
+ regList.append(RegistryKey(keyName, rPath.mid(keyLength+1), false, access));
}
bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const
@@ -471,7 +497,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
QString rSubkeyPath = keyPath(rSubKey);
// open a handle on the subkey
- HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath);
+ HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath, access);
if (handle == 0)
return false;
@@ -610,16 +636,16 @@ void QWinSettingsPrivate::remove(const QString &uKey)
// try to delete value bar in key foo
LONG res;
- HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey));
+ HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey), access);
if (handle != 0) {
res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()));
RegCloseKey(handle);
}
// try to delete key foo/bar and all subkeys
- handle = openKey(writeHandle(), registryPermissions, rKey);
+ handle = openKey(writeHandle(), registryPermissions, rKey, access);
if (handle != 0) {
- deleteChildGroups(handle);
+ deleteChildGroups(handle, access);
if (rKey.isEmpty()) {
QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
@@ -658,7 +684,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
QString rKey = escapedKey(uKey);
- HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey));
+ HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey), access);
if (handle == 0) {
setStatus(QSettings::AccessError);
return;
@@ -772,13 +798,13 @@ QStringList QWinSettingsPrivate::children(const QString &uKey, ChildSpec spec) c
HKEY parent_handle = regList.at(i).handle();
if (parent_handle == 0)
continue;
- HKEY handle = openKey(parent_handle, KEY_READ, rKey);
+ HKEY handle = openKey(parent_handle, KEY_READ, rKey, access);
if (handle == 0)
continue;
if (spec == AllKeys) {
NameSet keys;
- allKeys(handle, QLatin1String(""), &keys);
+ allKeys(handle, QLatin1String(""), &keys, access);
mergeKeySets(&result, keys);
} else { // ChildGroups or ChildKeys
QStringList names = childKeysOrGroups(handle, spec);
@@ -833,20 +859,26 @@ bool QWinSettingsPrivate::isWritable() const
QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
const QString &organization, const QString &application)
{
- if (format == QSettings::NativeFormat) {
+ if (format == QSettings::NativeFormat)
return new QWinSettingsPrivate(scope, organization, application);
- } else {
+ else if (format == QSettings::Registry32Format)
+ return new QWinSettingsPrivate(scope, organization, application, KEY_WOW64_32KEY);
+ else if (format == QSettings::Registry64Format)
+ return new QWinSettingsPrivate(scope, organization, application, KEY_WOW64_64KEY);
+ else
return new QConfFileSettingsPrivate(format, scope, organization, application);
- }
}
QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
{
- if (format == QSettings::NativeFormat) {
+ if (format == QSettings::NativeFormat)
return new QWinSettingsPrivate(fileName);
- } else {
+ else if (format == QSettings::Registry32Format)
+ return new QWinSettingsPrivate(fileName, KEY_WOW64_32KEY);
+ else if (format == QSettings::Registry64Format)
+ return new QWinSettingsPrivate(fileName, KEY_WOW64_64KEY);
+ else
return new QConfFileSettingsPrivate(fileName, format);
- }
}
QT_END_NAMESPACE