forked from qt-creator/qt-creator
Code Cleanup: Remove sharedlibraryinjector.
Make NameDemangler's message non-translateable.
This commit is contained in:
@@ -31,17 +31,15 @@
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "name_demangler.h"
|
||||
|
||||
#include <QtCore/QChar>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QLatin1String>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QRegExp>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include "name_demangler.h"
|
||||
|
||||
// Debugging facility.
|
||||
//#define DO_TRACE
|
||||
#ifdef DO_TRACE
|
||||
@@ -59,7 +57,6 @@ namespace Internal {
|
||||
|
||||
class NameDemanglerPrivate
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(NameDemanglerPrivate)
|
||||
public:
|
||||
NameDemanglerPrivate();
|
||||
~NameDemanglerPrivate();
|
||||
@@ -332,7 +329,7 @@ bool NameDemanglerPrivate::demangle(const QString &mangledName)
|
||||
if (m_demangledName.startsWith(QLatin1String("::")))
|
||||
m_demangledName.remove(0, 2);
|
||||
if (!parseError && pos != mangledName.size())
|
||||
error(tr("Premature end of input"));
|
||||
error(QString::fromLatin1("Premature end of input"));
|
||||
|
||||
#ifdef DO_TRACE
|
||||
qDebug("%d", substitutions.size());
|
||||
@@ -422,7 +419,7 @@ const QString NameDemanglerPrivate::parseEncoding()
|
||||
} else if (firstSetSpecialName.contains(next)) {
|
||||
encoding = parseSpecialName();
|
||||
} else {
|
||||
error(tr("Invalid encoding"));
|
||||
error(QString::fromLatin1("Invalid encoding"));
|
||||
}
|
||||
|
||||
FUNC_END(encoding);
|
||||
@@ -476,7 +473,7 @@ const QString NameDemanglerPrivate::parseName()
|
||||
} else if (firstSetLocalName.contains(next)) {
|
||||
name = parseLocalName();
|
||||
} else {
|
||||
error(tr("Invalid name"));
|
||||
error(QString::fromLatin1("Invalid name"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,7 +513,7 @@ const QString NameDemanglerPrivate::parseNestedName()
|
||||
|
||||
QString name;
|
||||
if (advance() != 'N') {
|
||||
error(tr("Invalid nested-name"));
|
||||
error(QString::fromLatin1("Invalid nested-name"));
|
||||
} else {
|
||||
QString cvQualifiers;
|
||||
if (firstSetCvQualifiers.contains(peek()) && peek(1) != 'm'
|
||||
@@ -525,7 +522,7 @@ const QString NameDemanglerPrivate::parseNestedName()
|
||||
if (!parseError) {
|
||||
name = parsePrefix();
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid nested-name"));
|
||||
error(QString::fromLatin1("Invalid nested-name"));
|
||||
|
||||
/*
|
||||
* These are member function qualifiers which will have to
|
||||
@@ -636,7 +633,7 @@ const QString NameDemanglerPrivate::parseTemplateArgs()
|
||||
|
||||
QString args = QLatin1String("<");
|
||||
if (advance() != 'I') {
|
||||
error(tr("Invalid template args"));
|
||||
error(QString::fromLatin1("Invalid template args"));
|
||||
} else {
|
||||
do {
|
||||
if (args.length() > 1)
|
||||
@@ -644,7 +641,7 @@ const QString NameDemanglerPrivate::parseTemplateArgs()
|
||||
args += parseTemplateArg();
|
||||
} while (!parseError && firstSetTemplateArg.contains(peek()));
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid template args"));
|
||||
error(QString::fromLatin1("Invalid template args"));
|
||||
}
|
||||
|
||||
args += '>';
|
||||
@@ -662,7 +659,7 @@ const QString NameDemanglerPrivate::parseTemplateParam()
|
||||
|
||||
QString param;
|
||||
if (advance() != 'T') {
|
||||
error(tr("Invalid template-param"));
|
||||
error(QString::fromLatin1("Invalid template-param"));
|
||||
} else {
|
||||
int index;
|
||||
if (peek() == '_')
|
||||
@@ -670,7 +667,7 @@ const QString NameDemanglerPrivate::parseTemplateParam()
|
||||
else
|
||||
index = parseNonNegativeNumber() + 1;
|
||||
if (!parseError && advance() != '_')
|
||||
error(tr("Invalid template-param"));
|
||||
error(QString::fromLatin1("Invalid template-param"));
|
||||
param = templateParams.at(index);
|
||||
}
|
||||
|
||||
@@ -689,7 +686,7 @@ const QString NameDemanglerPrivate::parseCvQualifiers()
|
||||
while (true) {
|
||||
if (peek() == 'V') {
|
||||
if (volatileFound || constFound) {
|
||||
error(tr("Invalid qualifiers: unexpected 'volatile'"));
|
||||
error(QString::fromLatin1("Invalid qualifiers: unexpected 'volatile'"));
|
||||
break;
|
||||
} else {
|
||||
volatileFound = true;
|
||||
@@ -698,7 +695,7 @@ const QString NameDemanglerPrivate::parseCvQualifiers()
|
||||
}
|
||||
} else if (peek() == 'K') {
|
||||
if (constFound) {
|
||||
error(tr("Invalid qualifiers: 'const' appears twice"));
|
||||
error(QString::fromLatin1("Invalid qualifiers: 'const' appears twice"));
|
||||
break;
|
||||
} else {
|
||||
constFound = true;
|
||||
@@ -741,7 +738,7 @@ int NameDemanglerPrivate::parseNonNegativeNumber(int base)
|
||||
advance();
|
||||
int number;
|
||||
if (pos == startPos) {
|
||||
error(tr("Invalid non-negative number"));
|
||||
error(QString::fromLatin1("Invalid non-negative number"));
|
||||
number = 0;
|
||||
} else {
|
||||
number = mangledName.mid(startPos, pos - startPos).toInt(0, base);
|
||||
@@ -799,7 +796,7 @@ const QString NameDemanglerPrivate::parseTemplateArg()
|
||||
advance();
|
||||
arg = parseExpression();
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid template-arg"));
|
||||
error(QString::fromLatin1("Invalid template-arg"));
|
||||
} else if (next == 'I') {
|
||||
advance();
|
||||
while (!parseError && firstSetTemplateArg.contains(peek())) {
|
||||
@@ -808,9 +805,9 @@ const QString NameDemanglerPrivate::parseTemplateArg()
|
||||
arg += parseTemplateArg();
|
||||
}
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid template-arg"));
|
||||
error(QString::fromLatin1("Invalid template-arg"));
|
||||
} else {
|
||||
error(tr("Invalid template-arg"));
|
||||
error(QString::fromLatin1("Invalid template-arg"));
|
||||
}
|
||||
|
||||
templateParams.append(arg);
|
||||
@@ -874,7 +871,7 @@ const QString NameDemanglerPrivate::parseExpression()
|
||||
while (!parseError && firstSetExpression.contains(peek()))
|
||||
expr += parseExpression();
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid expression"));
|
||||
error(QString::fromLatin1("Invalid expression"));
|
||||
} else if (str == QLatin1String("cv")) {
|
||||
advance(2);
|
||||
expr = parseType() + QLatin1String("(");
|
||||
@@ -889,7 +886,7 @@ const QString NameDemanglerPrivate::parseExpression()
|
||||
expr += parseExpression();
|
||||
}
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid expression"));
|
||||
error(QString::fromLatin1("Invalid expression"));
|
||||
} else {
|
||||
expr += parseExpression();
|
||||
}
|
||||
@@ -932,7 +929,7 @@ const QString NameDemanglerPrivate::parseExpression()
|
||||
} else if (firstSetExprPrimary.contains(next)) {
|
||||
expr = parseExprPrimary();
|
||||
} else {
|
||||
error(tr("Invalid expression"));
|
||||
error(QString::fromLatin1("Invalid expression"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -952,7 +949,7 @@ const QString NameDemanglerPrivate::parseExprPrimary()
|
||||
|
||||
QString expr;
|
||||
if (advance() != 'L') {
|
||||
error(tr("Invalid primary expression"));
|
||||
error(QString::fromLatin1("Invalid primary expression"));
|
||||
} else {
|
||||
QChar next = peek();
|
||||
if (firstSetType.contains(next)) {
|
||||
@@ -963,15 +960,15 @@ const QString NameDemanglerPrivate::parseExprPrimary()
|
||||
else if (true /* type just parsed indicates float */)
|
||||
expr += QString::number(parseFloat());
|
||||
else
|
||||
error(tr("Invalid expr-primary"));
|
||||
error(QString::fromLatin1("Invalid expr-primary"));
|
||||
}
|
||||
} else if (firstSetMangledName.contains(next)) {
|
||||
expr = parseMangledName();
|
||||
} else {
|
||||
error(tr("Invalid expr-primary"));
|
||||
error(QString::fromLatin1("Invalid expr-primary"));
|
||||
}
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid expr-primary"));
|
||||
error(QString::fromLatin1("Invalid expr-primary"));
|
||||
}
|
||||
|
||||
FUNC_END(expr);
|
||||
@@ -1106,12 +1103,12 @@ const QString NameDemanglerPrivate::parseType()
|
||||
advance(2);
|
||||
type = parseExpression(); // TODO: See above
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid type"));
|
||||
error(QString::fromLatin1("Invalid type"));
|
||||
} else if (str == QLatin1String("DT")) {
|
||||
advance(2);
|
||||
type = parseExpression(); // TODO: See above
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid type"));
|
||||
error(QString::fromLatin1("Invalid type"));
|
||||
} else {
|
||||
QChar next = peek();
|
||||
if (str == QLatin1String("Dd") || str == QLatin1String("De")
|
||||
@@ -1179,7 +1176,7 @@ const QString NameDemanglerPrivate::parseType()
|
||||
if (!parseError)
|
||||
type += parseType(); // TODO: handle this correctly
|
||||
} else {
|
||||
error(tr("Invalid type"));
|
||||
error(QString::fromLatin1("Invalid type"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1317,14 +1314,14 @@ const QString NameDemanglerPrivate::parseBuiltinType()
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
error(tr("Invalid built-in type"));
|
||||
error(QString::fromLatin1("Invalid built-in type"));
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
type = parseSourceName();
|
||||
break;
|
||||
default:
|
||||
error(tr("Invalid builtin-type"));
|
||||
error(QString::fromLatin1("Invalid builtin-type"));
|
||||
}
|
||||
|
||||
FUNC_END(type);
|
||||
@@ -1340,7 +1337,7 @@ const QString NameDemanglerPrivate::parseFunctionType()
|
||||
QString funcType;
|
||||
bool externC = false;
|
||||
if (advance() != 'F') {
|
||||
error(tr("Invalid function type"));
|
||||
error(QString::fromLatin1("Invalid function type"));
|
||||
} else {
|
||||
if (peek() == 'Y') {
|
||||
advance();
|
||||
@@ -1348,7 +1345,7 @@ const QString NameDemanglerPrivate::parseFunctionType()
|
||||
}
|
||||
const QStringList &signature = parseBareFunctionType();
|
||||
if (!parseError && advance() != 'E')
|
||||
error(tr("Invalid function type"));
|
||||
error(QString::fromLatin1("Invalid function type"));
|
||||
if (!parseError) {
|
||||
QString returnType = signature.first();
|
||||
QString argList = QLatin1String("(");
|
||||
@@ -1428,7 +1425,7 @@ const QString NameDemanglerPrivate::parseUnqualifiedName()
|
||||
else if (firstSetSourceName.contains(next))
|
||||
name = QLatin1String("::") + parseSourceName();
|
||||
else
|
||||
error(tr("Invalid unqualified-name"));
|
||||
error(QString::fromLatin1("Invalid unqualified-name"));
|
||||
|
||||
FUNC_END(name);
|
||||
return name;
|
||||
@@ -1519,7 +1516,7 @@ const NameDemanglerPrivate::Operator &NameDemanglerPrivate::parseOperatorName()
|
||||
static const UnaryOperator pseudoOp(QLatin1String("invalid"),
|
||||
QLatin1String("invalid"));
|
||||
op = &pseudoOp;
|
||||
error(tr("Invalid operator-name '%s'").arg(id));
|
||||
error(QString::fromLatin1("Invalid operator-name '%s'").arg(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1541,7 +1538,7 @@ const QString NameDemanglerPrivate::parseArrayType()
|
||||
|
||||
QString type;
|
||||
if (advance() != 'A') {
|
||||
error(tr("Invalid array-type"));
|
||||
error(QString::fromLatin1("Invalid array-type"));
|
||||
} else {
|
||||
QChar next = peek();
|
||||
QString dimension;
|
||||
@@ -1551,7 +1548,7 @@ const QString NameDemanglerPrivate::parseArrayType()
|
||||
dimension = parseExpression();
|
||||
}
|
||||
if (!parseError && advance() != '_')
|
||||
error(tr("Invalid array-type"));
|
||||
error(QString::fromLatin1("Invalid array-type"));
|
||||
if (!parseError)
|
||||
type = QString::fromLocal8Bit("%1[%2]").
|
||||
arg(parseType()).arg(dimension);
|
||||
@@ -1568,7 +1565,7 @@ const QString NameDemanglerPrivate::parsePointerToMemberType()
|
||||
|
||||
QString type;
|
||||
if (advance() != 'M') {
|
||||
error(tr("Invalid pointer-to-member-type"));
|
||||
error(QString::fromLatin1("Invalid pointer-to-member-type"));
|
||||
} else {
|
||||
const QString classType = parseType();
|
||||
QString memberType;
|
||||
@@ -1615,22 +1612,22 @@ const QString NameDemanglerPrivate::parseSubstitution()
|
||||
|
||||
QString substitution;
|
||||
if (advance() != 'S') {
|
||||
error(tr("Invalid substitution"));
|
||||
error(QString::fromLatin1("Invalid substitution"));
|
||||
} else if (firstSetSeqId.contains(peek())) {
|
||||
int substIndex = parseSeqId() + 1;
|
||||
if (!parseError && substIndex >= substitutions.size())
|
||||
error(tr("Invalid substitution: element %1 was requested, "
|
||||
error(QString::fromLatin1("Invalid substitution: element %1 was requested, "
|
||||
"but there are only %2").
|
||||
arg(substIndex + 1).arg(substitutions.size()));
|
||||
else
|
||||
substitution = substitutions.at(substIndex);
|
||||
if (!parseError && advance() != '_')
|
||||
error(tr("Invalid substitution"));
|
||||
error(QString::fromLatin1("Invalid substitution"));
|
||||
} else {
|
||||
switch (advance().toAscii()) {
|
||||
case '_':
|
||||
if (substitutions.isEmpty())
|
||||
error(tr("Invalid substitution: There are no elements"));
|
||||
error(QString::fromLatin1("Invalid substitution: There are no elements"));
|
||||
else
|
||||
substitution = substitutions.first();
|
||||
break;
|
||||
@@ -1661,7 +1658,7 @@ const QString NameDemanglerPrivate::parseSubstitution()
|
||||
"::std::basic_iostream<char, std::char_traits<char> >");
|
||||
break;
|
||||
default:
|
||||
error(tr("Invalid substitution"));
|
||||
error(QString::fromLatin1("Invalid substitution"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1733,7 +1730,7 @@ const QString NameDemanglerPrivate::parseSpecialName()
|
||||
if (!parseError)
|
||||
parseEncoding();
|
||||
} else {
|
||||
error(tr("Invalid special-name"));
|
||||
error(QString::fromLatin1("Invalid special-name"));
|
||||
}
|
||||
|
||||
FUNC_END(name);
|
||||
@@ -1756,7 +1753,7 @@ const QString NameDemanglerPrivate::parseUnscopedName()
|
||||
} else if (firstSetUnqualifiedName.contains(peek())) {
|
||||
name = parseUnqualifiedName();
|
||||
} else {
|
||||
error(tr("Invalid unqualified-name"));
|
||||
error(QString::fromLatin1("Invalid unqualified-name"));
|
||||
}
|
||||
|
||||
FUNC_END(name);
|
||||
@@ -1776,11 +1773,11 @@ const QString NameDemanglerPrivate::parseLocalName()
|
||||
|
||||
QString name;
|
||||
if (advance() != 'Z') {
|
||||
error(tr("Invalid local-name"));
|
||||
error(QString::fromLatin1("Invalid local-name"));
|
||||
} else {
|
||||
name = parseEncoding();
|
||||
if (!parseError && advance() != 'E') {
|
||||
error(tr("Invalid local-name"));
|
||||
error(QString::fromLatin1("Invalid local-name"));
|
||||
} else {
|
||||
QString str = readAhead(2);
|
||||
QChar next = peek();
|
||||
@@ -1793,7 +1790,7 @@ const QString NameDemanglerPrivate::parseLocalName()
|
||||
advance();
|
||||
name += QLatin1String("::\"string literal\"");
|
||||
} else {
|
||||
error(tr("Invalid local-name"));
|
||||
error(QString::fromLatin1("Invalid local-name"));
|
||||
}
|
||||
if (!parseError && firstSetDiscriminator.contains(peek()))
|
||||
parseDiscriminator();
|
||||
@@ -1809,7 +1806,7 @@ int NameDemanglerPrivate::parseDiscriminator()
|
||||
{
|
||||
int index;
|
||||
if (advance() != '_') {
|
||||
error(tr("Invalid discriminator"));
|
||||
error(QString::fromLatin1("Invalid discriminator"));
|
||||
index = -1;
|
||||
} else {
|
||||
index = parseNonNegativeNumber();
|
||||
@@ -1841,7 +1838,7 @@ const QString NameDemanglerPrivate::parseCtorDtorName()
|
||||
case '3':
|
||||
break;
|
||||
default:
|
||||
error(tr("Invalid ctor-dtor-name"));
|
||||
error(QString::fromLatin1("Invalid ctor-dtor-name"));
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
@@ -1852,11 +1849,11 @@ const QString NameDemanglerPrivate::parseCtorDtorName()
|
||||
destructor = true;
|
||||
break;
|
||||
default:
|
||||
error(tr("Invalid ctor-dtor-name"));
|
||||
error(QString::fromLatin1("Invalid ctor-dtor-name"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error(tr("Invalid ctor-dtor-name"));
|
||||
error(QString::fromLatin1("Invalid ctor-dtor-name"));
|
||||
}
|
||||
|
||||
if (!parseError) {
|
||||
@@ -1904,10 +1901,10 @@ void NameDemanglerPrivate::parseCallOffset()
|
||||
parseVOffset();
|
||||
break;
|
||||
default:
|
||||
error(tr("Invalid call-offset"));
|
||||
error(QString::fromLatin1("Invalid call-offset"));
|
||||
}
|
||||
if (!parseError && advance() != '_')
|
||||
error(tr("Invalid call-offset"));
|
||||
error(QString::fromLatin1("Invalid call-offset"));
|
||||
FUNC_END(QString());
|
||||
}
|
||||
|
||||
@@ -1929,7 +1926,7 @@ void NameDemanglerPrivate::parseVOffset()
|
||||
|
||||
parseNumber();
|
||||
if (advance() != '_')
|
||||
error(tr("Invalid v-offset"));
|
||||
error(QString::fromLatin1("Invalid v-offset"));
|
||||
parseNumber();
|
||||
|
||||
FUNC_END(QString());
|
||||
@@ -1941,7 +1938,7 @@ int NameDemanglerPrivate::parseDigit()
|
||||
|
||||
int digit = advance().digitValue();
|
||||
if (digit == -1)
|
||||
error(tr("Invalid digit"));
|
||||
error(QString::fromLatin1("Invalid digit"));
|
||||
|
||||
FUNC_END(QString::number(digit));
|
||||
return digit;
|
||||
@@ -1950,7 +1947,7 @@ int NameDemanglerPrivate::parseDigit()
|
||||
void NameDemanglerPrivate::error(const QString &errorSpec)
|
||||
{
|
||||
parseError = true;
|
||||
m_errorString = tr("At position %1: ").arg(pos) + errorSpec;
|
||||
m_errorString = QString::fromLatin1("At position %1: ").arg(pos) + errorSpec;
|
||||
}
|
||||
|
||||
QChar NameDemanglerPrivate::peek(int ahead)
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#ifndef NAME_DEMANGLER_H
|
||||
#define NAME_DEMANGLER_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QString;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -8,12 +8,10 @@ INCLUDEPATH+=$$PWD
|
||||
|
||||
win32 {
|
||||
SOURCES += $$PWD/peutils.cpp \
|
||||
$$PWD/dbgwinutils.cpp \
|
||||
$$PWD/sharedlibraryinjector.cpp
|
||||
$$PWD/dbgwinutils.cpp
|
||||
|
||||
HEADERS += $$PWD/peutils.h \
|
||||
$$PWD/dbgwinutils.h \
|
||||
$$PWD/sharedlibraryinjector.h
|
||||
$$PWD/dbgwinutils.h
|
||||
|
||||
contains(QMAKE_CXX, cl) {
|
||||
# For the Privilege manipulation functions in sharedlibraryinjector.cpp.
|
||||
|
||||
@@ -1,465 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Marius Storm-Olsen
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** 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 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "sharedlibraryinjector.h"
|
||||
#include <utils/winutils.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#ifdef __GNUC__ // MinGW does not have a complete windows.h
|
||||
|
||||
typedef DWORD (__stdcall *PTHREAD_START_ROUTINE) (LPVOID lpThreadParameter);
|
||||
|
||||
#endif
|
||||
|
||||
enum { debug = 0 };
|
||||
|
||||
static QString msgFuncFailed(const char *f, unsigned long error)
|
||||
{
|
||||
return QString::fromLatin1("%1 failed: %2").arg(QLatin1String(f), Utils::winErrorMessage(error));
|
||||
}
|
||||
|
||||
// Resolve a symbol from a library handle
|
||||
template <class SymbolType>
|
||||
inline bool resolveSymbol(const char *libraryName, HMODULE libraryHandle, const char *symbolName, SymbolType *s, QString *errorMessage)
|
||||
{
|
||||
*s = 0;
|
||||
FARPROC vs = ::GetProcAddress(libraryHandle, symbolName);
|
||||
if (vs == 0) {
|
||||
*errorMessage = QString::fromLatin1("Unable to resolve '%2' in '%1'.").arg(QString::fromAscii(symbolName), QString::fromAscii(libraryName));
|
||||
return false;
|
||||
}
|
||||
*s = reinterpret_cast<SymbolType>(vs);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Resolve a symbol from a library
|
||||
template <class SymbolType>
|
||||
inline bool resolveSymbol(const char *library, const char *symbolName, SymbolType *s, QString *errorMessage)
|
||||
{
|
||||
*s = 0;
|
||||
const HMODULE hm = ::GetModuleHandleA(library);
|
||||
if (hm == NULL) {
|
||||
*errorMessage = QString::fromLatin1("Module '%1' does not exist.").arg(QString::fromAscii(library));
|
||||
return false;
|
||||
}
|
||||
return resolveSymbol(library, hm , symbolName, s, errorMessage);
|
||||
}
|
||||
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
SharedLibraryInjector::SharedLibraryInjector(unsigned long processId,
|
||||
unsigned long threadId) :
|
||||
m_processId(processId),
|
||||
m_threadId(threadId),
|
||||
m_hasEscalatedPrivileges(false)
|
||||
{
|
||||
}
|
||||
|
||||
SharedLibraryInjector::~SharedLibraryInjector()
|
||||
{
|
||||
}
|
||||
|
||||
void SharedLibraryInjector::setPid(unsigned long pid)
|
||||
{
|
||||
m_processId = pid;
|
||||
}
|
||||
|
||||
void SharedLibraryInjector::setThreadId(unsigned long tid)
|
||||
{
|
||||
m_threadId = tid;
|
||||
}
|
||||
|
||||
void SharedLibraryInjector::setModulePath(const QString &modulePath)
|
||||
{
|
||||
m_modulePath = modulePath;
|
||||
}
|
||||
|
||||
bool SharedLibraryInjector::remoteInject(const QString &modulePath,
|
||||
bool waitForThread, QString *errorMessage)
|
||||
{
|
||||
setModulePath(modulePath);
|
||||
return doRemoteInjection(m_processId, NULL, m_modulePath, waitForThread, errorMessage);
|
||||
}
|
||||
|
||||
bool SharedLibraryInjector::stubInject(const QString &modulePath, unsigned long entryPoint, QString *errorMessage)
|
||||
{
|
||||
setModulePath(modulePath);
|
||||
return doStubInjection(m_processId, m_modulePath, entryPoint, errorMessage);
|
||||
}
|
||||
|
||||
bool SharedLibraryInjector::unload(HMODULE hFreeModule, QString *errorMessage)
|
||||
{
|
||||
return doRemoteInjection(m_processId, hFreeModule, QString(), true, errorMessage); // Always use remote thread to unload
|
||||
}
|
||||
|
||||
bool SharedLibraryInjector::unload(const QString &modulePath, QString *errorMessage)
|
||||
{
|
||||
const HMODULE hMod = modulePath.isEmpty() ?
|
||||
findModuleHandle(m_modulePath, errorMessage) :
|
||||
findModuleHandle(modulePath, errorMessage);
|
||||
if (!hMod)
|
||||
return false;
|
||||
|
||||
return doRemoteInjection(m_processId, hMod, NULL, true, errorMessage); // Always use remote thread to unload
|
||||
}
|
||||
|
||||
bool SharedLibraryInjector::hasLoaded(const QString &modulePath)
|
||||
{
|
||||
QString errorMessage;
|
||||
return findModuleHandle(modulePath.isEmpty() ? m_modulePath : modulePath, &errorMessage) != NULL;
|
||||
}
|
||||
|
||||
QString SharedLibraryInjector::findModule(const QString &moduleName)
|
||||
{
|
||||
const TCHAR *moduleNameC = reinterpret_cast<const TCHAR*>(moduleName.utf16());
|
||||
if (GetFileAttributesW(moduleNameC) != INVALID_FILE_ATTRIBUTES)
|
||||
return moduleName;
|
||||
|
||||
TCHAR testpathC[MAX_PATH];
|
||||
// Check application path first
|
||||
GetModuleFileNameW(NULL, testpathC, MAX_PATH);
|
||||
QString testPath = QString::fromUtf16(reinterpret_cast<unsigned short*>(testpathC));
|
||||
const int lastSlash = testPath.lastIndexOf(QLatin1Char('\\'));
|
||||
if (lastSlash != -1)
|
||||
testPath.truncate(lastSlash + 1);
|
||||
testPath += moduleName;
|
||||
if (GetFileAttributesW(reinterpret_cast<const TCHAR*>(testPath.utf16())) != INVALID_FILE_ATTRIBUTES)
|
||||
return testPath;
|
||||
// Path Search
|
||||
if (SearchPathW(NULL, reinterpret_cast<const TCHAR*>(moduleName.utf16()), NULL, sizeof(testpathC)/2, testpathC, NULL))
|
||||
return QString::fromUtf16(reinterpret_cast<unsigned short*>(testpathC));
|
||||
// Last chance, if the module has already been loaded in this process, then use that path
|
||||
const HMODULE loadedModule = GetModuleHandleW(reinterpret_cast<const TCHAR*>(moduleName.utf16()));
|
||||
if (loadedModule) {
|
||||
GetModuleFileNameW(loadedModule, testpathC, sizeof(testpathC));
|
||||
if (GetFileAttributes(testpathC) != INVALID_FILE_ATTRIBUTES)
|
||||
return QString::fromUtf16(reinterpret_cast<unsigned short*>(testpathC));
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
unsigned long SharedLibraryInjector::getModuleEntryPoint(const QString &moduleName)
|
||||
{
|
||||
// If file doesn't exist, just treat it like we cannot figure out the entry point
|
||||
if (moduleName.isEmpty() || GetFileAttributesW(reinterpret_cast<const TCHAR*>(moduleName.utf16())) == INVALID_FILE_ATTRIBUTES)
|
||||
return 0;
|
||||
|
||||
// Read the first 1K of data from the file
|
||||
unsigned char peData[1024];
|
||||
unsigned long peDataSize = 0;
|
||||
const HANDLE hFile = CreateFileW(reinterpret_cast<const WCHAR*>(moduleName.utf16()), FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (hFile == INVALID_HANDLE_VALUE
|
||||
|| !ReadFile(hFile, peData, sizeof(peData), &peDataSize, NULL))
|
||||
return 0;
|
||||
CloseHandle(hFile);
|
||||
|
||||
// Now we check to see if there is an optional header we can read
|
||||
IMAGE_DOS_HEADER *dosHeader = reinterpret_cast<IMAGE_DOS_HEADER *>(peData);
|
||||
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE // DOS signature is incorrect, or
|
||||
|| dosHeader->e_lfanew == 0) // executable's PE data contains no offset to New EXE header
|
||||
return 0;
|
||||
|
||||
IMAGE_NT_HEADERS *ntHeaders = (IMAGE_NT_HEADERS *)(peData + dosHeader->e_lfanew);
|
||||
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE // NT signature is incorrect, or
|
||||
|| !ntHeaders->OptionalHeader.ImageBase // ImageBase or EntryPoint addresses are incorrect
|
||||
|| !ntHeaders->OptionalHeader.AddressOfEntryPoint)
|
||||
return 0;
|
||||
|
||||
return ntHeaders->OptionalHeader.ImageBase
|
||||
+ ntHeaders->OptionalHeader.AddressOfEntryPoint;
|
||||
}
|
||||
|
||||
bool SharedLibraryInjector::escalatePrivileges(QString *errorMessage)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << m_hasEscalatedPrivileges;
|
||||
|
||||
if (m_hasEscalatedPrivileges)
|
||||
return true;
|
||||
|
||||
bool success = false;
|
||||
HANDLE hToken = 0;
|
||||
do {
|
||||
TOKEN_PRIVILEGES Debug_Privileges;
|
||||
if (!LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &Debug_Privileges.Privileges[0].Luid)) {
|
||||
*errorMessage = msgFuncFailed("LookupPrivilegeValue", GetLastError());
|
||||
break;
|
||||
}
|
||||
|
||||
Debug_Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; // set to enable privilege
|
||||
Debug_Privileges.PrivilegeCount = 1; // working with only 1
|
||||
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {
|
||||
*errorMessage = msgFuncFailed("OpenProcessToken", GetLastError());
|
||||
break;
|
||||
}
|
||||
if (!AdjustTokenPrivileges(hToken, FALSE, &Debug_Privileges, 0, NULL, NULL)) {
|
||||
*errorMessage = msgFuncFailed("AdjustTokenPrivileges", GetLastError());
|
||||
break;
|
||||
|
||||
}
|
||||
success = true;
|
||||
} while (false);
|
||||
|
||||
if (hToken)
|
||||
CloseHandle (hToken);
|
||||
|
||||
m_hasEscalatedPrivileges = success;
|
||||
return success;
|
||||
}
|
||||
|
||||
static void *writeDataToProcess(HANDLE process, void *data, unsigned size, QString *errorMessage)
|
||||
{
|
||||
void *memory = VirtualAllocEx(process, NULL, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (!memory) {
|
||||
*errorMessage = msgFuncFailed("VirtualAllocEx", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
if (!WriteProcessMemory(process, memory, data, size, NULL)) {
|
||||
*errorMessage = msgFuncFailed("WriteProcessMemory", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
|
||||
static void *writeUtf16StringToProcess(HANDLE process, const QString &what, QString *errorMessage)
|
||||
{
|
||||
QByteArray whatData = QByteArray(reinterpret_cast<const char*>(what.utf16()), what.size() * 2);
|
||||
whatData += '\0';
|
||||
whatData += '\0';
|
||||
return writeDataToProcess(process, whatData.data(), whatData.size(), errorMessage);
|
||||
}
|
||||
|
||||
bool SharedLibraryInjector::doStubInjection(unsigned long pid,
|
||||
const QString &modulePath,
|
||||
unsigned long entryPoint,
|
||||
QString *errorMessage)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << pid << modulePath << entryPoint;
|
||||
if (modulePath.isEmpty())
|
||||
return false;
|
||||
|
||||
if (!escalatePrivileges(errorMessage))
|
||||
return false;
|
||||
// MinGW lacks OpenThread() and the advapi.lib as of 6.5.2009
|
||||
#if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) || defined(__GNUC__)
|
||||
*errorMessage = QLatin1String("Not implemented for this architecture.");
|
||||
return false;
|
||||
#else
|
||||
byte stubCode[] = {
|
||||
0x68, 0, 0, 0, 0, // push 0x00000000 - Placeholder for the entrypoint address
|
||||
0x9C, // pushfd - Save the flags and registers
|
||||
0x60, // pushad
|
||||
0x68, 0, 0, 0, 0, // push 0x00000000 - Placeholder for the string address
|
||||
0xB8, 0, 0, 0, 0, // mov eax, 0x00000000 - Placeholder for the LoadLibrary address
|
||||
0xFF, 0xD0, // call eax - Call LoadLibrary with string address
|
||||
0x61, // popad - Restore flags and registry
|
||||
0x9D, // popfd
|
||||
0xC3 // retn - Return (pops the entrypoint, and executes)
|
||||
};
|
||||
|
||||
const HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
if (!hProcess)
|
||||
return false;
|
||||
|
||||
const HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_SET_CONTEXT, false, m_threadId);
|
||||
if (!hThread) {
|
||||
CloseHandle(hProcess);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get address of LoadLibraryW in kernel32.dll
|
||||
unsigned long funcPtr;
|
||||
if (!resolveSymbol("kernel32.dll", "LoadLibraryW", &funcPtr, errorMessage))
|
||||
return false;
|
||||
|
||||
// Allocate and write DLL path to target process' memory
|
||||
// 0-terminated Utf16 string.
|
||||
void *dllString = writeUtf16StringToProcess(hProcess, modulePath, errorMessage);
|
||||
if (!dllString)
|
||||
return false;
|
||||
|
||||
// Allocate memory in target process, for the stubCode which will load the module, and execute
|
||||
// the process' entry-point
|
||||
const unsigned long stubLen = sizeof(stubCode);
|
||||
// Modify the stubCode to have the proper entry-point, DLL module string, and function pointer
|
||||
*(unsigned long*)(stubCode+1) = entryPoint;
|
||||
*(unsigned long*)(stubCode+8) = reinterpret_cast<unsigned long>(dllString);
|
||||
*(unsigned long*)(stubCode+13) = funcPtr;
|
||||
|
||||
// If we cannot write the stubCode into the process, we simply bail out, and the process will
|
||||
// continues execution as normal
|
||||
void *stub = writeDataToProcess(hProcess, stubCode, stubLen, errorMessage);
|
||||
if (!stub)
|
||||
return false;
|
||||
// Set the process' main thread to start executing from the stubCode address which we've just
|
||||
// allocated in the process' memory.. If we cannot do that, bail out
|
||||
CONTEXT ctx;
|
||||
ctx.ContextFlags = CONTEXT_CONTROL;
|
||||
if(!GetThreadContext(hThread, &ctx))
|
||||
return false;
|
||||
ctx.Eip = reinterpret_cast<DWORD>(stub);
|
||||
ctx.ContextFlags = CONTEXT_CONTROL;
|
||||
if(!SetThreadContext(hThread, &ctx))
|
||||
return false;
|
||||
|
||||
CloseHandle(hProcess);
|
||||
CloseHandle(hThread);
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
bool SharedLibraryInjector::doRemoteInjection(unsigned long pid,
|
||||
HMODULE hFreeModule,
|
||||
const QString &modulePath,
|
||||
bool waitForThread,
|
||||
QString *errorMessage)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << '\n' << hFreeModule << pid << waitForThread<< modulePath;
|
||||
|
||||
if (!hFreeModule && modulePath.isEmpty())
|
||||
return false;
|
||||
|
||||
escalatePrivileges(errorMessage);
|
||||
|
||||
const HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
||||
if (hProcess == NULL) {
|
||||
*errorMessage = msgFuncFailed("OpenProcess", GetLastError());
|
||||
qDebug() << "Failed to open process PID %d with all access\n" << pid;
|
||||
return false;
|
||||
}
|
||||
|
||||
void *pszLibFileRemote = 0;
|
||||
HANDLE hThread = 0;
|
||||
// Call "FreeLibrary(hFreeModule)" to unload
|
||||
if (hFreeModule) {
|
||||
PTHREAD_START_ROUTINE pfnThreadRtn;
|
||||
if (!resolveSymbol("Kernel32", "FreeLibrary", &pfnThreadRtn, errorMessage))
|
||||
return false;
|
||||
hThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, hFreeModule, 0, NULL);
|
||||
} else {
|
||||
pszLibFileRemote = writeUtf16StringToProcess(hProcess, modulePath, errorMessage);
|
||||
if (!pszLibFileRemote)
|
||||
return false;
|
||||
// Loadlibrary routine
|
||||
PTHREAD_START_ROUTINE pfnThreadRtn;
|
||||
if (!resolveSymbol("Kernel32", "LoadLibraryW", &pfnThreadRtn, errorMessage))
|
||||
return false;
|
||||
hThread = ::CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, pszLibFileRemote, 0, NULL);
|
||||
}
|
||||
if (hThread == NULL) {
|
||||
*errorMessage = msgFuncFailed("CreateRemoteThread", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST)) {
|
||||
*errorMessage = msgFuncFailed("SetThreadPriority", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (waitForThread) {
|
||||
if (::WaitForSingleObject(hThread, 20000) != WAIT_OBJECT_0) {
|
||||
*errorMessage = QString::fromLatin1("WaitForSingleObject timeout");
|
||||
::CloseHandle(hThread);
|
||||
::CloseHandle(hProcess);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pszLibFileRemote)
|
||||
::VirtualFreeEx(hProcess, pszLibFileRemote, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
if (hThread)
|
||||
::CloseHandle(hThread);
|
||||
|
||||
if (hProcess)
|
||||
::CloseHandle(hProcess);
|
||||
if (debug)
|
||||
qDebug() << "success" << Q_FUNC_INFO;
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef BOOL (WINAPI *PFNENUMPROCESSMODULES) (HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded);
|
||||
typedef DWORD (WINAPI *PFNGETMODULEFILENAMEEXW) (HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
|
||||
|
||||
// We will require this function to get a module handle of our original module
|
||||
HMODULE SharedLibraryInjector::findModuleHandle(const QString &modulePath, QString *errorMessage)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << Q_FUNC_INFO << modulePath;
|
||||
|
||||
if (!escalatePrivileges(errorMessage))
|
||||
return 0;
|
||||
|
||||
HMODULE hMods[1024];
|
||||
DWORD cbNeeded;
|
||||
|
||||
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, m_processId);
|
||||
if (hProcess == NULL)
|
||||
return 0;
|
||||
|
||||
const char *psAPI_Lib = "PSAPI.DLL";
|
||||
HMODULE m_hModPSAPI = ::LoadLibraryA(psAPI_Lib);
|
||||
PFNENUMPROCESSMODULES m_pfnEnumProcessModules;
|
||||
PFNGETMODULEFILENAMEEXW m_pfnGetModuleFileNameExW;
|
||||
if (!resolveSymbol(psAPI_Lib, m_hModPSAPI, "EnumProcessModules", &m_pfnEnumProcessModules, errorMessage)
|
||||
|| !resolveSymbol(psAPI_Lib, m_hModPSAPI, "GetModuleFileNameExW", &m_pfnGetModuleFileNameExW, errorMessage))
|
||||
return false;
|
||||
|
||||
if(m_pfnEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
|
||||
const unsigned count = cbNeeded / sizeof(HMODULE);
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
TCHAR szModName[MAX_PATH];
|
||||
if (m_pfnGetModuleFileNameExW(hProcess, hMods[i], szModName, sizeof(szModName))) {
|
||||
if (QString::fromUtf16(reinterpret_cast<const unsigned short *>(szModName)) == modulePath) {
|
||||
::FreeLibrary(m_hModPSAPI);
|
||||
::CloseHandle(hProcess);
|
||||
return hMods[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::CloseHandle(hProcess);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
@@ -1,89 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Marius Storm-Olsen
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** 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 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef SHAREDLIBRARYINJECTOR_H
|
||||
#define SHAREDLIBRARYINJECTOR_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
/* SharedLibraryInjector: Injects a DLL into a remote process.
|
||||
* Escalates the calling process rights. */
|
||||
class SharedLibraryInjector {
|
||||
Q_DISABLE_COPY(SharedLibraryInjector)
|
||||
public:
|
||||
|
||||
explicit SharedLibraryInjector(unsigned long remotePid, unsigned long remoteThreadId = 0);
|
||||
~SharedLibraryInjector();
|
||||
|
||||
void setModulePath(const QString &modulePath);
|
||||
bool hasLoaded(const QString &modulePath = QString());
|
||||
|
||||
// Remote injection, to be used for running processes
|
||||
bool remoteInject(const QString &modulePath, bool waitForThread, QString *errorMessage);
|
||||
|
||||
// Stub injection, to be used before execution starts
|
||||
bool stubInject(const QString &modulePath, unsigned long entryPoint, QString *errorMessage);
|
||||
|
||||
bool unload(const QString &modulePath /* = QString()*/, QString *errorMessage);
|
||||
bool unload(HMODULE hFreeModule, QString *errorMessage);
|
||||
|
||||
void setPid(unsigned long pid);
|
||||
void setThreadId(unsigned long tid);
|
||||
|
||||
static QString findModule(const QString &moduleName);
|
||||
static unsigned long getModuleEntryPoint(const QString &moduleName);
|
||||
|
||||
private:
|
||||
bool escalatePrivileges(QString *errorMessage);
|
||||
bool doRemoteInjection(unsigned long pid, HMODULE hFreeModule,
|
||||
const QString &modulePath, bool waitForThread,
|
||||
QString *errorMessage);
|
||||
bool doStubInjection(unsigned long pid, const QString &modulePath,
|
||||
unsigned long entryPoint, QString *errorMessage);
|
||||
|
||||
HMODULE findModuleHandle(const QString &modulePath, QString *errorMessage);
|
||||
|
||||
unsigned long m_processId;
|
||||
unsigned long m_threadId;
|
||||
QString m_modulePath;
|
||||
bool m_hasEscalatedPrivileges;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // SHAREDLIBRARYINJECTOR_H
|
||||
Reference in New Issue
Block a user