forked from qt-creator/qt-creator
qmake: add $$read_registry() function
Fixes: QTCREATORBUG-21973 Written-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> (cherry-picked from qtbase/f89ac0101ad4a6cb5339a3bfe132aad897eafc9d) Change-Id: I6f67eec7c715686074dd3bdc121170c26daf56da Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
@@ -19,6 +19,10 @@ Project {
|
||||
"QMAKE_LIBRARY",
|
||||
"QMAKE_BUILTIN_PRFS",
|
||||
])
|
||||
Properties {
|
||||
condition: qbs.targetOS.contains("windows")
|
||||
cpp.dynamicLibraries: "advapi32"
|
||||
}
|
||||
|
||||
Export {
|
||||
Depends { name: "ProParser" }
|
||||
@@ -48,6 +52,8 @@ Project {
|
||||
"qmakeparser.h",
|
||||
"qmakevfs.cpp",
|
||||
"qmakevfs.h",
|
||||
"registry.cpp",
|
||||
"registry_p.h",
|
||||
]
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,7 @@ HEADERS += \
|
||||
proitems.h \
|
||||
prowriter.h \
|
||||
qmakevfs.h \
|
||||
registry_p.h \
|
||||
ioutils.h
|
||||
|
||||
SOURCES += \
|
||||
@@ -26,6 +27,7 @@ SOURCES += \
|
||||
proitems.cpp \
|
||||
prowriter.cpp \
|
||||
qmakevfs.cpp \
|
||||
registry.cpp \
|
||||
ioutils.cpp
|
||||
|
||||
RESOURCES += proparser.qrc
|
||||
|
@@ -31,6 +31,10 @@
|
||||
#include "qmakevfs.h"
|
||||
#include "ioutils.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include "registry_p.h"
|
||||
#endif
|
||||
|
||||
#include <qbytearray.h>
|
||||
#include <qdir.h>
|
||||
#include <qfile.h>
|
||||
@@ -88,7 +92,7 @@ enum ExpandFunc {
|
||||
E_UPPER, E_LOWER, E_TITLE, E_FILES, E_PROMPT, E_RE_ESCAPE, E_VAL_ESCAPE,
|
||||
E_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS,
|
||||
E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH,
|
||||
E_SYSTEM_PATH, E_SHELL_PATH, E_SYSTEM_QUOTE, E_SHELL_QUOTE, E_GETENV
|
||||
E_SYSTEM_PATH, E_SHELL_PATH, E_SYSTEM_QUOTE, E_SHELL_QUOTE, E_GETENV, E_READ_REGISTRY,
|
||||
};
|
||||
|
||||
enum TestFunc {
|
||||
@@ -153,6 +157,7 @@ void QMakeEvaluator::initFunctionStatics()
|
||||
{ "system_quote", E_SYSTEM_QUOTE },
|
||||
{ "shell_quote", E_SHELL_QUOTE },
|
||||
{ "getenv", E_GETENV },
|
||||
{ "read_registry", E_READ_REGISTRY },
|
||||
};
|
||||
statics.expands.reserve((int)(sizeof(expandInits)/sizeof(expandInits[0])));
|
||||
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
|
||||
@@ -1265,6 +1270,41 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
|
||||
ret << val;
|
||||
}
|
||||
break;
|
||||
#ifdef Q_OS_WIN
|
||||
case E_READ_REGISTRY: {
|
||||
HKEY tree;
|
||||
const auto par = args.at(0);
|
||||
if (!par.compare(QLatin1String("HKCU"), Qt::CaseInsensitive)
|
||||
|| !par.compare(QLatin1String("HKEY_CURRENT_USER"), Qt::CaseInsensitive)) {
|
||||
tree = HKEY_CURRENT_USER;
|
||||
} else if (!par.compare(QLatin1String("HKLM"), Qt::CaseInsensitive)
|
||||
|| !par.compare(QLatin1String("HKEY_LOCAL_MACHINE"), Qt::CaseInsensitive)) {
|
||||
tree = HKEY_LOCAL_MACHINE;
|
||||
} else {
|
||||
evalError(fL1S("read_registry(): invalid or unsupported registry tree %1.")
|
||||
.arg(par.toQString()));
|
||||
goto rrfail;
|
||||
}
|
||||
int flags = 0;
|
||||
if (args.count() > 2) {
|
||||
const auto opt = args.at(2);
|
||||
if (opt == "32"
|
||||
|| !opt.compare(QLatin1String("wow64_32key"), Qt::CaseInsensitive)) {
|
||||
flags = KEY_WOW64_32KEY;
|
||||
} else if (opt == "64"
|
||||
|| !opt.compare(QLatin1String("wow64_64key"), Qt::CaseInsensitive)) {
|
||||
flags = KEY_WOW64_64KEY;
|
||||
} else {
|
||||
evalError(fL1S("read_registry(): invalid option %1.")
|
||||
.arg(opt.toQString()));
|
||||
goto rrfail;
|
||||
}
|
||||
}
|
||||
ret << ProString(qt_readRegistryKey(tree, args.at(1).toQString(m_tmp1), flags));
|
||||
}
|
||||
rrfail:
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1)));
|
||||
break;
|
||||
|
158
src/shared/proparser/registry.cpp
Normal file
158
src/shared/proparser/registry.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the qmake application of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** 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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** 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-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore/qstringlist.h>
|
||||
#include "registry_p.h"
|
||||
|
||||
namespace QMakeInternal {
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
/*
|
||||
Returns the path part of a registry key.
|
||||
e.g.
|
||||
For a key
|
||||
"Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
|
||||
it returns
|
||||
"Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\"
|
||||
*/
|
||||
static QString keyPath(const QString &rKey)
|
||||
{
|
||||
int idx = rKey.lastIndexOf(QLatin1Char('\\'));
|
||||
if (idx == -1)
|
||||
return QString();
|
||||
return rKey.left(idx + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
Returns the name part of a registry key.
|
||||
e.g.
|
||||
For a key
|
||||
"Software\\Microsoft\\VisualStudio\\8.0\\Setup\\VC\\ProductDir"
|
||||
it returns
|
||||
"ProductDir"
|
||||
*/
|
||||
static QString keyName(const QString &rKey)
|
||||
{
|
||||
int idx = rKey.lastIndexOf(QLatin1Char('\\'));
|
||||
if (idx == -1)
|
||||
return rKey;
|
||||
|
||||
QString res(rKey.mid(idx + 1));
|
||||
if (res == QLatin1String("Default") || res == QLatin1String("."))
|
||||
res = QString();
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey, unsigned long options)
|
||||
{
|
||||
QString result;
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
QString rSubkeyName = keyName(rSubkey);
|
||||
QString rSubkeyPath = keyPath(rSubkey);
|
||||
|
||||
HKEY handle = nullptr;
|
||||
LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0,
|
||||
KEY_READ | options, &handle);
|
||||
|
||||
if (res != ERROR_SUCCESS)
|
||||
return QString();
|
||||
|
||||
// get the size and type of the value
|
||||
DWORD dataType;
|
||||
DWORD dataSize;
|
||||
res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), nullptr, &dataType, nullptr, &dataSize);
|
||||
if (res != ERROR_SUCCESS) {
|
||||
RegCloseKey(handle);
|
||||
return QString();
|
||||
}
|
||||
|
||||
// get the value
|
||||
QByteArray data(dataSize, 0);
|
||||
res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), nullptr, nullptr,
|
||||
reinterpret_cast<unsigned char*>(data.data()), &dataSize);
|
||||
if (res != ERROR_SUCCESS) {
|
||||
RegCloseKey(handle);
|
||||
return QString();
|
||||
}
|
||||
|
||||
switch (dataType) {
|
||||
case REG_EXPAND_SZ:
|
||||
case REG_SZ: {
|
||||
result = QString::fromWCharArray(((const wchar_t *)data.constData()));
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_MULTI_SZ: {
|
||||
QStringList l;
|
||||
int i = 0;
|
||||
for (;;) {
|
||||
QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i);
|
||||
i += s.length() + 1;
|
||||
|
||||
if (s.isEmpty())
|
||||
break;
|
||||
l.append(s);
|
||||
}
|
||||
result = l.join(QLatin1String(", "));
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_NONE:
|
||||
case REG_BINARY: {
|
||||
result = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
case REG_DWORD_BIG_ENDIAN:
|
||||
case REG_DWORD: {
|
||||
Q_ASSERT(data.size() == sizeof(int));
|
||||
int i;
|
||||
memcpy((char*)&i, data.constData(), sizeof(int));
|
||||
result = QString::number(i);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
qWarning("QSettings: unknown data %u type in windows registry", quint32(dataType));
|
||||
break;
|
||||
}
|
||||
|
||||
RegCloseKey(handle);
|
||||
#else
|
||||
Q_UNUSED(parentHandle);
|
||||
Q_UNUSED(rSubkey)
|
||||
Q_UNUSED(options);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace QMakeInternal
|
||||
|
55
src/shared/proparser/registry_p.h
Normal file
55
src/shared/proparser/registry_p.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** 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-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#include <QtCore/qt_windows.h>
|
||||
#else
|
||||
typedef void* HKEY;
|
||||
#endif
|
||||
|
||||
#include <QtCore/qstring.h>
|
||||
|
||||
namespace QMakeInternal {
|
||||
|
||||
/**
|
||||
* Read a value from the Windows registry.
|
||||
*
|
||||
* If the key is not found, or the registry cannot be accessed (for example
|
||||
* if this code is compiled for a platform other than Windows), a null
|
||||
* string is returned.
|
||||
*
|
||||
* 32-bit code reads from the registry's 32 bit view (Wow6432Node),
|
||||
* 64 bit code reads from the 64 bit view.
|
||||
* Pass KEY_WOW64_32KEY to access the 32 bit view regardless of the
|
||||
* application's architecture, KEY_WOW64_64KEY respectively.
|
||||
*/
|
||||
QString qt_readRegistryKey(HKEY parentHandle, const QString &rSubkey,
|
||||
unsigned long options = 0);
|
||||
|
||||
} // namespace QMakeInternal
|
@@ -18,7 +18,8 @@ QtcAutotest {
|
||||
"qmakeevaluator.h", "qmakeevaluator_p.h", "qmakeevaluator.cpp",
|
||||
"qmakeglobals.h", "qmakeglobals.cpp",
|
||||
"qmakeparser.h", "qmakeparser.cpp",
|
||||
"qmakevfs.h", "qmakevfs.cpp"
|
||||
"qmakevfs.h", "qmakevfs.cpp",
|
||||
"registry_p.h", "registry.cpp",
|
||||
]
|
||||
}
|
||||
Group {
|
||||
@@ -27,4 +28,8 @@ QtcAutotest {
|
||||
}
|
||||
cpp.includePaths: base.concat([proParserGroup.prefix])
|
||||
cpp.defines: base.concat("QT_USE_FAST_OPERATOR_PLUS")
|
||||
Properties {
|
||||
condition: qbs.targetOS.contains("windows")
|
||||
cpp.dynamicLibraries: "advapi32"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user