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_LIBRARY",
|
||||||
"QMAKE_BUILTIN_PRFS",
|
"QMAKE_BUILTIN_PRFS",
|
||||||
])
|
])
|
||||||
|
Properties {
|
||||||
|
condition: qbs.targetOS.contains("windows")
|
||||||
|
cpp.dynamicLibraries: "advapi32"
|
||||||
|
}
|
||||||
|
|
||||||
Export {
|
Export {
|
||||||
Depends { name: "ProParser" }
|
Depends { name: "ProParser" }
|
||||||
@@ -48,6 +52,8 @@ Project {
|
|||||||
"qmakeparser.h",
|
"qmakeparser.h",
|
||||||
"qmakevfs.cpp",
|
"qmakevfs.cpp",
|
||||||
"qmakevfs.h",
|
"qmakevfs.h",
|
||||||
|
"registry.cpp",
|
||||||
|
"registry_p.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@ HEADERS += \
|
|||||||
proitems.h \
|
proitems.h \
|
||||||
prowriter.h \
|
prowriter.h \
|
||||||
qmakevfs.h \
|
qmakevfs.h \
|
||||||
|
registry_p.h \
|
||||||
ioutils.h
|
ioutils.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@@ -26,6 +27,7 @@ SOURCES += \
|
|||||||
proitems.cpp \
|
proitems.cpp \
|
||||||
prowriter.cpp \
|
prowriter.cpp \
|
||||||
qmakevfs.cpp \
|
qmakevfs.cpp \
|
||||||
|
registry.cpp \
|
||||||
ioutils.cpp
|
ioutils.cpp
|
||||||
|
|
||||||
RESOURCES += proparser.qrc
|
RESOURCES += proparser.qrc
|
||||||
|
@@ -31,6 +31,10 @@
|
|||||||
#include "qmakevfs.h"
|
#include "qmakevfs.h"
|
||||||
#include "ioutils.h"
|
#include "ioutils.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
# include "registry_p.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <qbytearray.h>
|
#include <qbytearray.h>
|
||||||
#include <qdir.h>
|
#include <qdir.h>
|
||||||
#include <qfile.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_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_REPLACE, E_SORT_DEPENDS, E_RESOLVE_DEPENDS, E_ENUMERATE_VARS,
|
||||||
E_SHADOWED, E_ABSOLUTE_PATH, E_RELATIVE_PATH, E_CLEAN_PATH,
|
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 {
|
enum TestFunc {
|
||||||
@@ -153,6 +157,7 @@ void QMakeEvaluator::initFunctionStatics()
|
|||||||
{ "system_quote", E_SYSTEM_QUOTE },
|
{ "system_quote", E_SYSTEM_QUOTE },
|
||||||
{ "shell_quote", E_SHELL_QUOTE },
|
{ "shell_quote", E_SHELL_QUOTE },
|
||||||
{ "getenv", E_GETENV },
|
{ "getenv", E_GETENV },
|
||||||
|
{ "read_registry", E_READ_REGISTRY },
|
||||||
};
|
};
|
||||||
statics.expands.reserve((int)(sizeof(expandInits)/sizeof(expandInits[0])));
|
statics.expands.reserve((int)(sizeof(expandInits)/sizeof(expandInits[0])));
|
||||||
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
|
for (unsigned i = 0; i < sizeof(expandInits)/sizeof(expandInits[0]); ++i)
|
||||||
@@ -1265,6 +1270,41 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
|
|||||||
ret << val;
|
ret << val;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1)));
|
evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1)));
|
||||||
break;
|
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",
|
"qmakeevaluator.h", "qmakeevaluator_p.h", "qmakeevaluator.cpp",
|
||||||
"qmakeglobals.h", "qmakeglobals.cpp",
|
"qmakeglobals.h", "qmakeglobals.cpp",
|
||||||
"qmakeparser.h", "qmakeparser.cpp",
|
"qmakeparser.h", "qmakeparser.cpp",
|
||||||
"qmakevfs.h", "qmakevfs.cpp"
|
"qmakevfs.h", "qmakevfs.cpp",
|
||||||
|
"registry_p.h", "registry.cpp",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Group {
|
Group {
|
||||||
@@ -27,4 +28,8 @@ QtcAutotest {
|
|||||||
}
|
}
|
||||||
cpp.includePaths: base.concat([proParserGroup.prefix])
|
cpp.includePaths: base.concat([proParserGroup.prefix])
|
||||||
cpp.defines: base.concat("QT_USE_FAST_OPERATOR_PLUS")
|
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