Support accessing 32-bit Registry from 64-bit programs and vice versa
For details see "Accessing an Alternate Registry View": http://msdn.microsoft.com/en-us/library/aa384129%28VS.85%29.aspx Task-number: QTBUG-3845 Change-Id: Iecf24b15dc01830686ddd708871bc3392d95282f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
bfecc2dbc6
commit
64261c0871
@ -2393,14 +2393,24 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
|
|||||||
|
|
||||||
This enum type specifies the storage format used by QSettings.
|
This enum type specifies the storage format used by QSettings.
|
||||||
|
|
||||||
\value NativeFormat Store the settings using the most
|
\value NativeFormat Store the settings using the most
|
||||||
appropriate storage format for the platform.
|
appropriate storage format for the platform.
|
||||||
On Windows, this means the system registry;
|
On Windows, this means the system registry;
|
||||||
on OS X and iOS, this means the CFPreferences
|
on OS X and iOS, this means the CFPreferences
|
||||||
API; on Unix, this means textual
|
API; on Unix, this means textual
|
||||||
configuration files in INI format.
|
configuration files in INI format.
|
||||||
\value IniFormat Store the settings in INI files.
|
\value Registry32Format Windows only: Explicitly access the 32-bit system registry
|
||||||
\value InvalidFormat Special value returned by registerFormat().
|
from a 64-bit application running on 64-bit Windows.
|
||||||
|
On 32-bit Windows or from a 32-bit application on 64-bit Windows,
|
||||||
|
this works the same as specifying NativeFormat.
|
||||||
|
This enum value was added in Qt 5.6.
|
||||||
|
\value Registry64Format Windows only: Explicitly access the 64-bit system registry
|
||||||
|
from a 32-bit application running on 64-bit Windows.
|
||||||
|
On 32-bit Windows or from a 64-bit application on 64-bit Windows,
|
||||||
|
this works the same as specifying NativeFormat.
|
||||||
|
This enum value was added in Qt 5.6.
|
||||||
|
\value IniFormat Store the settings in INI files.
|
||||||
|
\value InvalidFormat Special value returned by registerFormat().
|
||||||
\omitvalue CustomFormat1
|
\omitvalue CustomFormat1
|
||||||
\omitvalue CustomFormat2
|
\omitvalue CustomFormat2
|
||||||
\omitvalue CustomFormat3
|
\omitvalue CustomFormat3
|
||||||
|
@ -79,6 +79,11 @@ public:
|
|||||||
NativeFormat,
|
NativeFormat,
|
||||||
IniFormat,
|
IniFormat,
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
Registry32Format,
|
||||||
|
Registry64Format,
|
||||||
|
#endif
|
||||||
|
|
||||||
InvalidFormat = 16,
|
InvalidFormat = 16,
|
||||||
CustomFormat1,
|
CustomFormat1,
|
||||||
CustomFormat2,
|
CustomFormat2,
|
||||||
|
@ -41,6 +41,18 @@
|
|||||||
#include "qdebug.h"
|
#include "qdebug.h"
|
||||||
#include <qt_windows.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
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
/* Keys are stored in QStrings. If the variable name starts with 'u', this is a "user"
|
/* Keys are stored in QStrings. If the variable name starts with 'u', this is a "user"
|
||||||
@ -135,12 +147,13 @@ static QString errorCodeToString(DWORD errorCode)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open a key with the specified perms
|
// Open a key with the specified "perms".
|
||||||
static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
|
// "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;
|
HKEY resultHandle = 0;
|
||||||
LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
|
LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()),
|
||||||
0, perms, &resultHandle);
|
0, perms | access, &resultHandle);
|
||||||
|
|
||||||
if (res == ERROR_SUCCESS)
|
if (res == ERROR_SUCCESS)
|
||||||
return resultHandle;
|
return resultHandle;
|
||||||
@ -148,17 +161,18 @@ static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open a key with the specified perms, create it if it does not exist
|
// Open a key with the specified "perms", create it if it does not exist.
|
||||||
static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey)
|
// "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
|
// try to open it
|
||||||
HKEY resultHandle = openKey(parentHandle, perms, rSubKey);
|
HKEY resultHandle = openKey(parentHandle, perms, rSubKey, access);
|
||||||
if (resultHandle != 0)
|
if (resultHandle != 0)
|
||||||
return resultHandle;
|
return resultHandle;
|
||||||
|
|
||||||
// try to create it
|
// try to create it
|
||||||
LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast<const wchar_t *>(rSubKey.utf16()), 0, 0,
|
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)
|
if (res == ERROR_SUCCESS)
|
||||||
return resultHandle;
|
return resultHandle;
|
||||||
@ -169,11 +183,12 @@ static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSub
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open or create a key in read-write mode if possible, otherwise read-only
|
// Open or create a key in read-write mode if possible, otherwise read-only.
|
||||||
static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *readOnly)
|
// "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
|
// 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 (resultHandle != 0) {
|
||||||
if (readOnly != 0)
|
if (readOnly != 0)
|
||||||
*readOnly = false;
|
*readOnly = false;
|
||||||
@ -181,7 +196,7 @@ static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *rea
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to open or create it read/only
|
// 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 (resultHandle != 0) {
|
||||||
if (readOnly != 0)
|
if (readOnly != 0)
|
||||||
*readOnly = true;
|
*readOnly = true;
|
||||||
@ -247,9 +262,9 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS
|
|||||||
return result;
|
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)
|
if (handle == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -270,11 +285,11 @@ static void allKeys(HKEY parentHandle, const QString &rSubKey, NameSet *result)
|
|||||||
if (!s.isEmpty())
|
if (!s.isEmpty())
|
||||||
s += QLatin1Char('\\');
|
s += QLatin1Char('\\');
|
||||||
s += childGroups.at(i);
|
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);
|
QStringList childGroups = childKeysOrGroups(parentHandle, QSettingsPrivate::ChildGroups);
|
||||||
|
|
||||||
@ -282,10 +297,10 @@ static void deleteChildGroups(HKEY parentHandle)
|
|||||||
QString group = childGroups.at(i);
|
QString group = childGroups.at(i);
|
||||||
|
|
||||||
// delete subgroups in group
|
// delete subgroups in group
|
||||||
HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group);
|
HKEY childGroupHandle = openKey(parentHandle, registryPermissions, group, access);
|
||||||
if (childGroupHandle == 0)
|
if (childGroupHandle == 0)
|
||||||
continue;
|
continue;
|
||||||
deleteChildGroups(childGroupHandle);
|
deleteChildGroups(childGroupHandle, access);
|
||||||
RegCloseKey(childGroupHandle);
|
RegCloseKey(childGroupHandle);
|
||||||
|
|
||||||
// delete group itself
|
// delete group itself
|
||||||
@ -305,7 +320,7 @@ static void deleteChildGroups(HKEY parentHandle)
|
|||||||
class RegistryKey
|
class RegistryKey
|
||||||
{
|
{
|
||||||
public:
|
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;
|
QString key() const;
|
||||||
HKEY handle() const;
|
HKEY handle() const;
|
||||||
HKEY parentHandle() const;
|
HKEY parentHandle() const;
|
||||||
@ -316,13 +331,15 @@ private:
|
|||||||
mutable HKEY m_handle;
|
mutable HKEY m_handle;
|
||||||
QString m_key;
|
QString m_key;
|
||||||
mutable bool m_read_only;
|
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_parent_handle(parent_handle),
|
||||||
m_handle(0),
|
m_handle(0),
|
||||||
m_key(key),
|
m_key(key),
|
||||||
m_read_only(read_only)
|
m_read_only(read_only),
|
||||||
|
m_access(access)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,9 +354,9 @@ HKEY RegistryKey::handle() const
|
|||||||
return m_handle;
|
return m_handle;
|
||||||
|
|
||||||
if (m_read_only)
|
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
|
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;
|
return m_handle;
|
||||||
}
|
}
|
||||||
@ -371,8 +388,8 @@ class QWinSettingsPrivate : public QSettingsPrivate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
|
QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
|
||||||
const QString &application);
|
const QString &application, REGSAM access = 0);
|
||||||
QWinSettingsPrivate(QString rKey);
|
QWinSettingsPrivate(QString rKey, REGSAM access = 0);
|
||||||
~QWinSettingsPrivate();
|
~QWinSettingsPrivate();
|
||||||
|
|
||||||
void remove(const QString &uKey);
|
void remove(const QString &uKey);
|
||||||
@ -390,11 +407,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
RegistryKeyList regList; // list of registry locations to search for keys
|
RegistryKeyList regList; // list of registry locations to search for keys
|
||||||
bool deleteWriteHandleOnExit;
|
bool deleteWriteHandleOnExit;
|
||||||
|
REGSAM access;
|
||||||
};
|
};
|
||||||
|
|
||||||
QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
|
QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &organization,
|
||||||
const QString &application)
|
const QString &application, REGSAM access)
|
||||||
: QSettingsPrivate(QSettings::NativeFormat, scope, organization, application)
|
: QSettingsPrivate(QSettings::NativeFormat, scope, organization, application),
|
||||||
|
access(access)
|
||||||
{
|
{
|
||||||
deleteWriteHandleOnExit = false;
|
deleteWriteHandleOnExit = false;
|
||||||
|
|
||||||
@ -405,23 +424,24 @@ QWinSettingsPrivate::QWinSettingsPrivate(QSettings::Scope scope, const QString &
|
|||||||
|
|
||||||
if (scope == QSettings::UserScope) {
|
if (scope == QSettings::UserScope) {
|
||||||
if (!application.isEmpty())
|
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())
|
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())
|
if (regList.isEmpty())
|
||||||
setStatus(QSettings::AccessError);
|
setStatus(QSettings::AccessError);
|
||||||
}
|
}
|
||||||
|
|
||||||
QWinSettingsPrivate::QWinSettingsPrivate(QString rPath)
|
QWinSettingsPrivate::QWinSettingsPrivate(QString rPath, REGSAM access)
|
||||||
: QSettingsPrivate(QSettings::NativeFormat)
|
: QSettingsPrivate(QSettings::NativeFormat),
|
||||||
|
access(access)
|
||||||
{
|
{
|
||||||
deleteWriteHandleOnExit = false;
|
deleteWriteHandleOnExit = false;
|
||||||
|
|
||||||
@ -460,9 +480,9 @@ QWinSettingsPrivate::QWinSettingsPrivate(QString rPath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rPath.length() == keyLength)
|
if (rPath.length() == keyLength)
|
||||||
regList.append(RegistryKey(keyName, QString(), false));
|
regList.append(RegistryKey(keyName, QString(), false, access));
|
||||||
else if (rPath[keyLength] == QLatin1Char('\\'))
|
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
|
bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVariant *value) const
|
||||||
@ -471,7 +491,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa
|
|||||||
QString rSubkeyPath = keyPath(rSubKey);
|
QString rSubkeyPath = keyPath(rSubKey);
|
||||||
|
|
||||||
// open a handle on the subkey
|
// open a handle on the subkey
|
||||||
HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath);
|
HKEY handle = openKey(parentHandle, KEY_READ, rSubkeyPath, access);
|
||||||
if (handle == 0)
|
if (handle == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -604,16 +624,16 @@ void QWinSettingsPrivate::remove(const QString &uKey)
|
|||||||
|
|
||||||
// try to delete value bar in key foo
|
// try to delete value bar in key foo
|
||||||
LONG res;
|
LONG res;
|
||||||
HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey));
|
HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey), access);
|
||||||
if (handle != 0) {
|
if (handle != 0) {
|
||||||
res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()));
|
res = RegDeleteValue(handle, reinterpret_cast<const wchar_t *>(keyName(rKey).utf16()));
|
||||||
RegCloseKey(handle);
|
RegCloseKey(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to delete key foo/bar and all subkeys
|
// try to delete key foo/bar and all subkeys
|
||||||
handle = openKey(writeHandle(), registryPermissions, rKey);
|
handle = openKey(writeHandle(), registryPermissions, rKey, access);
|
||||||
if (handle != 0) {
|
if (handle != 0) {
|
||||||
deleteChildGroups(handle);
|
deleteChildGroups(handle, access);
|
||||||
|
|
||||||
if (rKey.isEmpty()) {
|
if (rKey.isEmpty()) {
|
||||||
QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
|
QStringList childKeys = childKeysOrGroups(handle, QSettingsPrivate::ChildKeys);
|
||||||
@ -661,7 +681,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
|
|||||||
|
|
||||||
QString rKey = escapedKey(uKey);
|
QString rKey = escapedKey(uKey);
|
||||||
|
|
||||||
HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey));
|
HKEY handle = createOrOpenKey(writeHandle(), registryPermissions, keyPath(rKey), access);
|
||||||
if (handle == 0) {
|
if (handle == 0) {
|
||||||
setStatus(QSettings::AccessError);
|
setStatus(QSettings::AccessError);
|
||||||
return;
|
return;
|
||||||
@ -775,13 +795,13 @@ QStringList QWinSettingsPrivate::children(const QString &uKey, ChildSpec spec) c
|
|||||||
HKEY parent_handle = regList.at(i).handle();
|
HKEY parent_handle = regList.at(i).handle();
|
||||||
if (parent_handle == 0)
|
if (parent_handle == 0)
|
||||||
continue;
|
continue;
|
||||||
HKEY handle = openKey(parent_handle, KEY_READ, rKey);
|
HKEY handle = openKey(parent_handle, KEY_READ, rKey, access);
|
||||||
if (handle == 0)
|
if (handle == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (spec == AllKeys) {
|
if (spec == AllKeys) {
|
||||||
NameSet keys;
|
NameSet keys;
|
||||||
allKeys(handle, QLatin1String(""), &keys);
|
allKeys(handle, QLatin1String(""), &keys, access);
|
||||||
mergeKeySets(&result, keys);
|
mergeKeySets(&result, keys);
|
||||||
} else { // ChildGroups or ChildKeys
|
} else { // ChildGroups or ChildKeys
|
||||||
QStringList names = childKeysOrGroups(handle, spec);
|
QStringList names = childKeysOrGroups(handle, spec);
|
||||||
@ -836,20 +856,26 @@ bool QWinSettingsPrivate::isWritable() const
|
|||||||
QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
|
QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format, QSettings::Scope scope,
|
||||||
const QString &organization, const QString &application)
|
const QString &organization, const QString &application)
|
||||||
{
|
{
|
||||||
if (format == QSettings::NativeFormat) {
|
if (format == QSettings::NativeFormat)
|
||||||
return new QWinSettingsPrivate(scope, organization, application);
|
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);
|
return new QConfFileSettingsPrivate(format, scope, organization, application);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
|
QSettingsPrivate *QSettingsPrivate::create(const QString &fileName, QSettings::Format format)
|
||||||
{
|
{
|
||||||
if (format == QSettings::NativeFormat) {
|
if (format == QSettings::NativeFormat)
|
||||||
return new QWinSettingsPrivate(fileName);
|
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);
|
return new QConfFileSettingsPrivate(fileName, format);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -121,6 +121,7 @@ private slots:
|
|||||||
void testEmptyKey();
|
void testEmptyKey();
|
||||||
void testResourceFiles();
|
void testResourceFiles();
|
||||||
void testRegistryShortRootNames();
|
void testRegistryShortRootNames();
|
||||||
|
void testRegistry32And64Bit();
|
||||||
void trailingWhitespace();
|
void trailingWhitespace();
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
void fileName();
|
void fileName();
|
||||||
@ -2075,6 +2076,52 @@ void tst_QSettings::testRegistryShortRootNames()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QSettings::testRegistry32And64Bit()
|
||||||
|
{
|
||||||
|
#if !defined (Q_OS_WIN) || defined(Q_OS_WINRT)
|
||||||
|
QSKIP("This test is specific to the Windows registry.", SkipAll);
|
||||||
|
#else
|
||||||
|
|
||||||
|
const QString key("HKEY_LOCAL_MACHINE\\Software");
|
||||||
|
const QString keyWow("HKEY_LOCAL_MACHINE\\Software\\Wow6432Node");
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN64
|
||||||
|
// This branch is taken at compile time if targeting 32-bit; it does not
|
||||||
|
// necessarily mean that the OS running the test is 32-bit (it could be
|
||||||
|
// e.g. 64-bit).
|
||||||
|
QCOMPARE(QSettings(key, QSettings::NativeFormat).childGroups(),
|
||||||
|
QSettings(key, QSettings::Registry32Format).childGroups());
|
||||||
|
|
||||||
|
// Detect whether we are running under 64-bit Windows.
|
||||||
|
typedef BOOL (WINAPI *IsWow64ProcessPtr)(HANDLE hProcess, PBOOL Wow64Process);
|
||||||
|
IsWow64ProcessPtr IsWow64Process = (IsWow64ProcessPtr)QLibrary::resolve(
|
||||||
|
"kernel32.dll", "IsWow64Process");
|
||||||
|
|
||||||
|
if (IsWow64Process) {
|
||||||
|
BOOL IsWow64 = FALSE;
|
||||||
|
if (IsWow64Process(GetCurrentProcess(), &IsWow64) && IsWow64) {
|
||||||
|
// The 64-bit registry's "Wow6432Node" key should match the 32-bit registry.
|
||||||
|
// If we are not on 32-bit Windows, these should never be the same,
|
||||||
|
// because the 64-bit registry has a "Wow6432Node" key.
|
||||||
|
QCOMPARE(QSettings(keyWow, QSettings::Registry64Format).childGroups(),
|
||||||
|
QSettings(key, QSettings::Registry32Format).childGroups());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// This branch is taken at compile time if targeting 64-bit; it does not
|
||||||
|
// necessarily mean that the OS running the test is 64-bit (it could be
|
||||||
|
// e.g. 128-bit).
|
||||||
|
QCOMPARE(QSettings(key, QSettings::NativeFormat).childGroups(),
|
||||||
|
QSettings(key, QSettings::Registry64Format).childGroups());
|
||||||
|
|
||||||
|
// The 64-bit registry's "Wow6432Node" key should match the 32-bit registry.
|
||||||
|
QCOMPARE(QSettings(keyWow, QSettings::Registry64Format).childGroups(),
|
||||||
|
QSettings(key, QSettings::Registry32Format).childGroups());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QSettings::trailingWhitespace()
|
void tst_QSettings::trailingWhitespace()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user