forked from qt-creator/qt-creator
Clean up code
This commit is contained in:
@@ -40,9 +40,10 @@
|
|||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QTimerEvent>
|
#include <QtCore/QTimerEvent>
|
||||||
#include <QFileInfo>
|
#include <QtCore/QFileInfo>
|
||||||
|
#include <QtCore/QDir>
|
||||||
|
|
||||||
#define DBGHELP_TRANSLATE_TCHAR
|
#define DBGHELP_TRANSLATE_TCHAR
|
||||||
#include <inc/Dbghelp.h>
|
#include <inc/Dbghelp.h>
|
||||||
@@ -57,11 +58,10 @@ CdbDebugEnginePrivate::CdbDebugEnginePrivate(DebuggerManager *parent, CdbDebugEn
|
|||||||
m_watchTimer(-1),
|
m_watchTimer(-1),
|
||||||
m_debugEventCallBack(engine),
|
m_debugEventCallBack(engine),
|
||||||
m_debugOutputCallBack(engine),
|
m_debugOutputCallBack(engine),
|
||||||
m_engine(engine)
|
m_engine(engine),
|
||||||
|
m_debuggerManager(parent),
|
||||||
|
m_debuggerManagerAccess(parent->engineInterface())
|
||||||
{
|
{
|
||||||
q = parent;
|
|
||||||
qq = parent->engineInterface();
|
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = DebugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient));
|
hr = DebugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient));
|
||||||
if (FAILED(hr)) m_pDebugClient = 0;
|
if (FAILED(hr)) m_pDebugClient = 0;
|
||||||
@@ -100,7 +100,6 @@ CdbDebugEnginePrivate::~CdbDebugEnginePrivate()
|
|||||||
CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent)
|
CdbDebugEngine::CdbDebugEngine(DebuggerManager *parent)
|
||||||
: IDebuggerEngine(parent),
|
: IDebuggerEngine(parent),
|
||||||
m_d(new CdbDebugEnginePrivate(parent, this))
|
m_d(new CdbDebugEnginePrivate(parent, this))
|
||||||
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +133,7 @@ void CdbDebugEngine::setToolTipExpression(const QPoint & /*pos*/, const QString
|
|||||||
|
|
||||||
bool CdbDebugEngine::startDebugger()
|
bool CdbDebugEngine::startDebugger()
|
||||||
{
|
{
|
||||||
m_d->q->showStatusMessage("Starting Debugger", -1);
|
m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
|
||||||
|
|
||||||
//if (!q->m_workingDir.isEmpty())
|
//if (!q->m_workingDir.isEmpty())
|
||||||
// m_gdbProc.setWorkingDirectory(q->m_workingDir);
|
// m_gdbProc.setWorkingDirectory(q->m_workingDir);
|
||||||
@@ -145,19 +144,21 @@ bool CdbDebugEngine::startDebugger()
|
|||||||
memset(&dbgopts, 0, sizeof(dbgopts));
|
memset(&dbgopts, 0, sizeof(dbgopts));
|
||||||
dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
|
dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
|
||||||
|
|
||||||
HRESULT hr;
|
const QString filename(m_d->m_debuggerManager->m_executable);
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO <<filename;
|
||||||
|
|
||||||
QString filename(m_d->q->m_executable);
|
const QFileInfo fi(filename);
|
||||||
QFileInfo fi(filename);
|
m_d->m_pDebugSymbols->AppendImagePathWide(QDir::toNativeSeparators(fi.absolutePath()).utf16());
|
||||||
m_d->m_pDebugSymbols->AppendImagePathWide(fi.absolutePath().replace('/','\\').utf16());
|
|
||||||
//m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
|
//m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
|
||||||
m_d->m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
|
m_d->m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
|
||||||
//m_pDebugSymbols->AddSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS | SYMOPT_NO_IMAGE_SEARCH);
|
//m_pDebugSymbols->AddSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS | SYMOPT_NO_IMAGE_SEARCH);
|
||||||
|
|
||||||
if (m_d->q->startMode() == DebuggerManager::AttachExternal) {
|
if (m_d->m_debuggerManager->startMode() == DebuggerManager::AttachExternal) {
|
||||||
qWarning("CdbDebugEngine: attach to process not yet implemented!");
|
qWarning("CdbDebugEngine: attach to process not yet implemented!");
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
hr = m_d->m_pDebugClient->CreateProcess2Wide(NULL,
|
HRESULT hr = m_d->m_pDebugClient->CreateProcess2Wide(NULL,
|
||||||
const_cast<PWSTR>(filename.utf16()),
|
const_cast<PWSTR>(filename.utf16()),
|
||||||
&dbgopts,
|
&dbgopts,
|
||||||
sizeof(dbgopts),
|
sizeof(dbgopts),
|
||||||
@@ -165,18 +166,21 @@ bool CdbDebugEngine::startDebugger()
|
|||||||
NULL); // TODO: think about setting the environment
|
NULL); // TODO: think about setting the environment
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
//qWarning("CreateProcess2Wide failed");
|
//qWarning("CreateProcess2Wide failed");
|
||||||
m_d->qq->notifyInferiorExited();
|
m_d->m_debuggerManagerAccess->notifyInferiorExited();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_d->q->showStatusMessage(tr("Debugger Running"), -1);
|
m_d->m_debuggerManager->showStatusMessage(tr("Debugger Running"), -1);
|
||||||
startWatchTimer();
|
startWatchTimer();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::exitDebugger()
|
void CdbDebugEngine::exitDebugger()
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
m_d->m_pDebugClient->TerminateCurrentProcess();
|
m_d->m_pDebugClient->TerminateCurrentProcess();
|
||||||
killWatchTimer();
|
killWatchTimer();
|
||||||
}
|
}
|
||||||
@@ -187,7 +191,9 @@ void CdbDebugEngine::updateWatchModel()
|
|||||||
|
|
||||||
void CdbDebugEngine::stepExec()
|
void CdbDebugEngine::stepExec()
|
||||||
{
|
{
|
||||||
//qDebug() << "CdbDebugEngine::stepExec()";
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
//m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
|
//m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_INTO);
|
hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_INTO);
|
||||||
@@ -197,8 +203,10 @@ void CdbDebugEngine::stepExec()
|
|||||||
|
|
||||||
void CdbDebugEngine::stepOutExec()
|
void CdbDebugEngine::stepOutExec()
|
||||||
{
|
{
|
||||||
//qDebug() << "CdbDebugEngine::stepOutExec()";
|
if (debugCDB)
|
||||||
StackHandler* sh = m_d->qq->stackHandler();
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
StackHandler* sh = m_d->m_debuggerManagerAccess->stackHandler();
|
||||||
const int idx = sh->currentIndex() + 1;
|
const int idx = sh->currentIndex() + 1;
|
||||||
QList<StackFrame> stackframes = sh->frames();
|
QList<StackFrame> stackframes = sh->frames();
|
||||||
if (idx < 0 || idx >= stackframes.size()) {
|
if (idx < 0 || idx >= stackframes.size()) {
|
||||||
@@ -238,7 +246,9 @@ void CdbDebugEngine::stepOutExec()
|
|||||||
|
|
||||||
void CdbDebugEngine::nextExec()
|
void CdbDebugEngine::nextExec()
|
||||||
{
|
{
|
||||||
//qDebug() << "CdbDebugEngine::nextExec()";
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER);
|
hr = m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_STEP_OVER);
|
||||||
startWatchTimer();
|
startWatchTimer();
|
||||||
@@ -251,14 +261,20 @@ void CdbDebugEngine::stepIExec()
|
|||||||
|
|
||||||
void CdbDebugEngine::nextIExec()
|
void CdbDebugEngine::nextIExec()
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
|
m_d->m_pDebugControl->Execute(DEBUG_OUTCTL_THIS_CLIENT, "p", 0);
|
||||||
startWatchTimer();
|
startWatchTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::continueInferior()
|
void CdbDebugEngine::continueInferior()
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
killWatchTimer();
|
killWatchTimer();
|
||||||
m_d->q->resetLocation();
|
m_d->m_debuggerManager->resetLocation();
|
||||||
|
|
||||||
ULONG executionStatus;
|
ULONG executionStatus;
|
||||||
HRESULT hr = m_d->m_pDebugControl->GetExecutionStatus(&executionStatus);
|
HRESULT hr = m_d->m_pDebugControl->GetExecutionStatus(&executionStatus);
|
||||||
@@ -266,11 +282,14 @@ void CdbDebugEngine::continueInferior()
|
|||||||
m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO);
|
m_d->m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_GO);
|
||||||
|
|
||||||
startWatchTimer();
|
startWatchTimer();
|
||||||
m_d->qq->notifyInferiorRunning();
|
m_d->m_debuggerManagerAccess->notifyInferiorRunning();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::interruptInferior()
|
void CdbDebugEngine::interruptInferior()
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
//TODO: better use IDebugControl::SetInterrupt?
|
//TODO: better use IDebugControl::SetInterrupt?
|
||||||
if (!m_d->m_hDebuggeeProcess)
|
if (!m_d->m_hDebuggeeProcess)
|
||||||
return;
|
return;
|
||||||
@@ -278,42 +297,48 @@ void CdbDebugEngine::interruptInferior()
|
|||||||
qWarning("DebugBreakProcess failed.");
|
qWarning("DebugBreakProcess failed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_d->qq->notifyInferiorStopped();
|
m_d->m_debuggerManagerAccess->notifyInferiorStopped();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber)
|
void CdbDebugEngine::runToLineExec(const QString &fileName, int lineNumber)
|
||||||
{
|
{
|
||||||
Q_UNUSED(fileName)
|
if (debugCDB)
|
||||||
Q_UNUSED(lineNumber)
|
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::runToFunctionExec(const QString &functionName)
|
void CdbDebugEngine::runToFunctionExec(const QString &functionName)
|
||||||
{
|
{
|
||||||
Q_UNUSED(functionName)
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << functionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::jumpToLineExec(const QString &fileName, int lineNumber)
|
void CdbDebugEngine::jumpToLineExec(const QString &fileName, int lineNumber)
|
||||||
{
|
{
|
||||||
Q_UNUSED(fileName)
|
if (debugCDB)
|
||||||
Q_UNUSED(lineNumber)
|
qDebug() << Q_FUNC_INFO << fileName << lineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &value)
|
void CdbDebugEngine::assignValueInDebugger(const QString &expr, const QString &value)
|
||||||
{
|
{
|
||||||
Q_UNUSED(expr)
|
if (debugCDB)
|
||||||
Q_UNUSED(value)
|
qDebug() << Q_FUNC_INFO << expr << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::executeDebuggerCommand(const QString &/*command*/)
|
void CdbDebugEngine::executeDebuggerCommand(const QString &command)
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << command;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::activateFrame(int frameIndex)
|
void CdbDebugEngine::activateFrame(int frameIndex)
|
||||||
{
|
{
|
||||||
if (m_d->q->status() != DebuggerInferiorStopped)
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << frameIndex;
|
||||||
|
|
||||||
|
if (m_d->m_debuggerManager->status() != DebuggerInferiorStopped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
StackHandler *stackHandler = m_d->qq->stackHandler();
|
StackHandler *stackHandler = m_d->m_debuggerManagerAccess->stackHandler();
|
||||||
const int oldIndex = stackHandler->currentIndex();
|
const int oldIndex = stackHandler->currentIndex();
|
||||||
//qDebug() << "ACTIVATE FRAME: " << frameIndex << oldIndex
|
//qDebug() << "ACTIVATE FRAME: " << frameIndex << oldIndex
|
||||||
// << stackHandler->currentIndex();
|
// << stackHandler->currentIndex();
|
||||||
@@ -329,40 +354,61 @@ void CdbDebugEngine::activateFrame(int frameIndex)
|
|||||||
|
|
||||||
const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
|
const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
|
||||||
if (usable)
|
if (usable)
|
||||||
m_d->q->gotoLocation(frame.file, frame.line, true);
|
m_d->m_debuggerManager->gotoLocation(frame.file, frame.line, true);
|
||||||
else
|
else
|
||||||
qDebug() << "FULL NAME NOT USABLE: " << frame.file;
|
qDebug() << "FULL NAME NOT USABLE: " << frame.file;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::selectThread(int index)
|
void CdbDebugEngine::selectThread(int index)
|
||||||
{
|
{
|
||||||
//reset location arrow
|
if (debugCDB)
|
||||||
m_d->q->resetLocation();
|
qDebug() << Q_FUNC_INFO << index;
|
||||||
|
|
||||||
ThreadsHandler *threadsHandler = m_d->qq->threadsHandler();
|
//reset location arrow
|
||||||
|
m_d->m_debuggerManager->resetLocation();
|
||||||
|
|
||||||
|
ThreadsHandler *threadsHandler = m_d->m_debuggerManagerAccess->threadsHandler();
|
||||||
threadsHandler->setCurrentThread(index);
|
threadsHandler->setCurrentThread(index);
|
||||||
m_d->m_currentThreadId = index;
|
m_d->m_currentThreadId = index;
|
||||||
m_d->updateStackTrace();
|
m_d->updateStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline QString breakPointExpression(const QString &fileName, const QString &lineNumber)
|
||||||
|
{
|
||||||
|
QString str;
|
||||||
|
str += QLatin1Char('`');
|
||||||
|
str += QDir::toNativeSeparators(fileName);
|
||||||
|
str += QLatin1Char(':');
|
||||||
|
str += lineNumber;
|
||||||
|
str += QLatin1Char('`');
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::attemptBreakpointSynchronization()
|
void CdbDebugEngine::attemptBreakpointSynchronization()
|
||||||
{
|
{
|
||||||
BreakHandler *handler = m_d->qq->breakHandler();
|
if (debugCDB)
|
||||||
//qDebug() << "attemptBreakpointSynchronization";
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
if (!m_d->m_hDebuggeeProcess) {
|
||||||
|
qWarning("attemptBreakpointSynchronization() called while debugger is not running");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BreakHandler *handler = m_d->m_debuggerManagerAccess->breakHandler();
|
||||||
for (int i=0; i < handler->size(); ++i) {
|
for (int i=0; i < handler->size(); ++i) {
|
||||||
BreakpointData* breakpoint = handler->at(i);
|
BreakpointData* breakpoint = handler->at(i);
|
||||||
if (breakpoint->pending) {
|
if (breakpoint->pending) {
|
||||||
|
const QString expr = breakPointExpression(breakpoint->fileName, breakpoint->lineNumber);
|
||||||
IDebugBreakpoint2* pBP = 0;
|
IDebugBreakpoint2* pBP = 0;
|
||||||
HRESULT hr = m_d->m_pDebugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP);
|
HRESULT hr = m_d->m_pDebugControl->AddBreakpoint2(DEBUG_BREAKPOINT_CODE, DEBUG_ANY_ID, &pBP);
|
||||||
if (FAILED(hr) || !pBP) {
|
if (FAILED(hr) || !pBP) {
|
||||||
qWarning("m_pDebugControl->AddBreakpoint2 failed");
|
qWarning("m_pDebugControl->AddBreakpoint2 %s failed.", qPrintable(expr));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString str = '`' + breakpoint->fileName + ':' + breakpoint->lineNumber + '`';
|
hr = pBP->SetOffsetExpressionWide(expr.utf16());
|
||||||
hr = pBP->SetOffsetExpressionWide(str.utf16());
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
qWarning("SetOffsetExpressionWide failed");
|
qWarning("SetOffsetExpressionWide %s failed", qPrintable(expr));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,11 +444,14 @@ void CdbDebugEngine::reloadModules()
|
|||||||
|
|
||||||
void CdbDebugEngine::loadSymbols(const QString &moduleName)
|
void CdbDebugEngine::loadSymbols(const QString &moduleName)
|
||||||
{
|
{
|
||||||
Q_UNUSED(moduleName)
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << moduleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::loadAllSymbols()
|
void CdbDebugEngine::loadAllSymbols()
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::reloadRegisters()
|
void CdbDebugEngine::reloadRegisters()
|
||||||
@@ -410,40 +459,53 @@ void CdbDebugEngine::reloadRegisters()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEngine::timerEvent(QTimerEvent* te)
|
void CdbDebugEngine::timerEvent(QTimerEvent* te)
|
||||||
{
|
{
|
||||||
if (te->timerId() != m_d->m_watchTimer)
|
if (te->timerId() != m_d->m_watchTimer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (debugCDB > 1)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = m_d->m_pDebugControl->WaitForEvent(0, 1);
|
hr = m_d->m_pDebugControl->WaitForEvent(0, 1);
|
||||||
switch (hr) {
|
switch (hr) {
|
||||||
case S_OK:
|
case S_OK:
|
||||||
//qDebug() << "WaitForEvent S_OK";
|
if (debugCDB > 1)
|
||||||
|
qDebug() << "WaitForEvent S_OK";
|
||||||
|
|
||||||
killWatchTimer();
|
killWatchTimer();
|
||||||
m_d->handleDebugEvent();
|
m_d->handleDebugEvent();
|
||||||
break;
|
break;
|
||||||
case S_FALSE:
|
case S_FALSE:
|
||||||
//qDebug() << "S_FALSE";
|
if (debugCDB > 1)
|
||||||
|
qDebug() << "WaitForEvent S_FALSE";
|
||||||
break;
|
break;
|
||||||
case E_PENDING:
|
case E_PENDING:
|
||||||
qDebug() << "E_PENDING";
|
if (debugCDB > 1)
|
||||||
|
qDebug() << "WaitForEvent E_PENDING";
|
||||||
break;
|
break;
|
||||||
case E_UNEXPECTED:
|
case E_UNEXPECTED:
|
||||||
|
if (debugCDB > 1)
|
||||||
|
qDebug() << "WaitForEvent E_UNEXPECTED";
|
||||||
killWatchTimer();
|
killWatchTimer();
|
||||||
break;
|
break;
|
||||||
case E_FAIL:
|
case E_FAIL:
|
||||||
qDebug() << "E_FAIL";
|
if (debugCDB > 1)
|
||||||
|
qDebug() << "WaitForEvent E_FAIL";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEnginePrivate::handleDebugEvent()
|
void CdbDebugEnginePrivate::handleDebugEvent()
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
if (m_bIgnoreNextDebugEvent) {
|
if (m_bIgnoreNextDebugEvent) {
|
||||||
m_engine->startWatchTimer();
|
m_engine->startWatchTimer();
|
||||||
m_bIgnoreNextDebugEvent = false;
|
m_bIgnoreNextDebugEvent = false;
|
||||||
} else {
|
} else {
|
||||||
qq->notifyInferiorStopped();
|
m_debuggerManagerAccess->notifyInferiorStopped();
|
||||||
updateThreadList();
|
updateThreadList();
|
||||||
updateStackTrace();
|
updateStackTrace();
|
||||||
}
|
}
|
||||||
@@ -462,7 +524,10 @@ void CdbDebugEnginePrivate::handleDebugEvent()
|
|||||||
|
|
||||||
void CdbDebugEnginePrivate::updateThreadList()
|
void CdbDebugEnginePrivate::updateThreadList()
|
||||||
{
|
{
|
||||||
ThreadsHandler* th = qq->threadsHandler();
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
ThreadsHandler* th = m_debuggerManagerAccess->threadsHandler();
|
||||||
QList<ThreadData> threads;
|
QList<ThreadData> threads;
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
@@ -483,6 +548,9 @@ void CdbDebugEnginePrivate::updateThreadList()
|
|||||||
|
|
||||||
void CdbDebugEnginePrivate::updateStackTrace()
|
void CdbDebugEnginePrivate::updateStackTrace()
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
//qDebug() << "updateStackTrace()";
|
//qDebug() << "updateStackTrace()";
|
||||||
HRESULT hr = m_pDebugSystemObjects->SetCurrentThreadId(m_currentThreadId);
|
HRESULT hr = m_pDebugSystemObjects->SetCurrentThreadId(m_currentThreadId);
|
||||||
|
|
||||||
@@ -510,7 +578,7 @@ void CdbDebugEnginePrivate::updateStackTrace()
|
|||||||
StackFrame frame;
|
StackFrame frame;
|
||||||
frame.line = 0;
|
frame.line = 0;
|
||||||
frame.level = i;
|
frame.level = i;
|
||||||
frame.address = QString("0x%1").arg(frames[i].InstructionOffset, 0, 16);
|
frame.address = QString::fromLatin1("0x%1").arg(frames[i].InstructionOffset, 0, 16);
|
||||||
|
|
||||||
m_pDebugSymbols->GetNameByOffsetWide(frames[i].InstructionOffset, wszBuf, MAX_PATH, 0, 0);
|
m_pDebugSymbols->GetNameByOffsetWide(frames[i].InstructionOffset, wszBuf, MAX_PATH, 0, 0);
|
||||||
frame.function = QString::fromUtf16(wszBuf);
|
frame.function = QString::fromUtf16(wszBuf);
|
||||||
@@ -526,15 +594,15 @@ void CdbDebugEnginePrivate::updateStackTrace()
|
|||||||
stackFrames.append(frame);
|
stackFrames.append(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
qq->stackHandler()->setFrames(stackFrames);
|
m_debuggerManagerAccess->stackHandler()->setFrames(stackFrames);
|
||||||
|
|
||||||
// find the first usable frame and select it
|
// find the first usable frame and select it
|
||||||
for (int i=0; i < stackFrames.count(); ++i) {
|
for (int i=0; i < stackFrames.count(); ++i) {
|
||||||
const StackFrame &frame = stackFrames.at(i);
|
const StackFrame &frame = stackFrames.at(i);
|
||||||
bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
|
const bool usable = !frame.file.isEmpty() && QFileInfo(frame.file).isReadable();
|
||||||
if (usable) {
|
if (usable) {
|
||||||
qq->stackHandler()->setCurrentIndex(i);
|
m_debuggerManagerAccess->stackHandler()->setCurrentIndex(i);
|
||||||
q->gotoLocation(frame.file, frame.line, true);
|
m_debuggerManager->gotoLocation(frame.file, frame.line, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -550,13 +618,14 @@ void CdbDebugEnginePrivate::updateStackTrace()
|
|||||||
|
|
||||||
void CdbDebugEnginePrivate::handleDebugOutput(const char* szOutputString)
|
void CdbDebugEnginePrivate::handleDebugOutput(const char* szOutputString)
|
||||||
{
|
{
|
||||||
qq->showApplicationOutput(QString::fromLocal8Bit(szOutputString));
|
m_debuggerManagerAccess->showApplicationOutput(QString::fromLocal8Bit(szOutputString));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT pBP)
|
void CdbDebugEnginePrivate::handleBreakpointEvent(PDEBUG_BREAKPOINT pBP)
|
||||||
{
|
{
|
||||||
Q_UNUSED(pBP)
|
Q_UNUSED(pBP)
|
||||||
qDebug() << "CdbDebugEngine::handleBreakpointEvent()";
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDebuggerEngine *createWinEngine(DebuggerManager *parent)
|
IDebuggerEngine *createWinEngine(DebuggerManager *parent)
|
||||||
|
@@ -34,7 +34,6 @@
|
|||||||
#ifndef DEBUGGER_CDBENGINEPRIVATE_H
|
#ifndef DEBUGGER_CDBENGINEPRIVATE_H
|
||||||
#define DEBUGGER_CDBENGINEPRIVATE_H
|
#define DEBUGGER_CDBENGINEPRIVATE_H
|
||||||
|
|
||||||
#include "cdbdebugengine.h"
|
|
||||||
#include "cdbdebugeventcallback.h"
|
#include "cdbdebugeventcallback.h"
|
||||||
#include "cdbdebugoutput.h"
|
#include "cdbdebugoutput.h"
|
||||||
|
|
||||||
@@ -71,10 +70,12 @@ struct CdbDebugEnginePrivate
|
|||||||
CdbDebugOutput m_debugOutputCallBack;
|
CdbDebugOutput m_debugOutputCallBack;
|
||||||
|
|
||||||
CdbDebugEngine* m_engine;
|
CdbDebugEngine* m_engine;
|
||||||
DebuggerManager *q;
|
DebuggerManager *m_debuggerManager;
|
||||||
IDebuggerManagerAccessForEngines *qq;
|
IDebuggerManagerAccessForEngines *m_debuggerManagerAccess;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum { debugCDB = 0 };
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|
||||||
|
@@ -41,6 +41,11 @@
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine* dbg) :
|
||||||
|
m_pEngine(dbg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
STDMETHODIMP CdbDebugEventCallback::QueryInterface(
|
STDMETHODIMP CdbDebugEventCallback::QueryInterface(
|
||||||
THIS_
|
THIS_
|
||||||
IN REFIID InterfaceId,
|
IN REFIID InterfaceId,
|
||||||
@@ -49,14 +54,11 @@ STDMETHODIMP CdbDebugEventCallback::QueryInterface(
|
|||||||
*Interface = NULL;
|
*Interface = NULL;
|
||||||
|
|
||||||
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
|
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
|
||||||
IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
|
IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks))) {
|
||||||
{
|
|
||||||
*Interface = (IDebugOutputCallbacks *)this;
|
*Interface = (IDebugOutputCallbacks *)this;
|
||||||
AddRef();
|
AddRef();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,7 +89,8 @@ STDMETHODIMP CdbDebugEventCallback::GetInterestMask(THIS_ __out PULONG mask)
|
|||||||
|
|
||||||
STDMETHODIMP CdbDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT Bp)
|
STDMETHODIMP CdbDebugEventCallback::Breakpoint(THIS_ __in PDEBUG_BREAKPOINT Bp)
|
||||||
{
|
{
|
||||||
qDebug() << "MSVCDebugEventCallback::Breakpoint";
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
m_pEngine->m_d->handleBreakpointEvent(Bp);
|
m_pEngine->m_d->handleBreakpointEvent(Bp);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -98,7 +101,9 @@ STDMETHODIMP CdbDebugEventCallback::Exception(
|
|||||||
__in ULONG FirstChance
|
__in ULONG FirstChance
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
qDebug() << "MSVCDebugEventCallback::Exception";
|
Q_UNUSED(Exception)
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << FirstChance;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +114,12 @@ STDMETHODIMP CdbDebugEventCallback::CreateThread(
|
|||||||
__in ULONG64 StartOffset
|
__in ULONG64 StartOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(Handle)
|
||||||
|
Q_UNUSED(DataOffset)
|
||||||
|
Q_UNUSED(StartOffset)
|
||||||
|
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
//Debugger::ThreadInfo ti;
|
//Debugger::ThreadInfo ti;
|
||||||
//ti.handle = Handle;
|
//ti.handle = Handle;
|
||||||
//ti.dataOffset = DataOffset;
|
//ti.dataOffset = DataOffset;
|
||||||
@@ -121,6 +132,9 @@ STDMETHODIMP CdbDebugEventCallback::ExitThread(
|
|||||||
__in ULONG ExitCode
|
__in ULONG ExitCode
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << ExitCode;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,10 +153,21 @@ STDMETHODIMP CdbDebugEventCallback::CreateProcess(
|
|||||||
__in ULONG64 StartOffset
|
__in ULONG64 StartOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(ImageFileHandle)
|
||||||
|
Q_UNUSED(BaseOffset)
|
||||||
|
Q_UNUSED(ModuleSize)
|
||||||
|
Q_UNUSED(ModuleName)
|
||||||
|
Q_UNUSED(ImageName)
|
||||||
|
Q_UNUSED(CheckSum)
|
||||||
|
Q_UNUSED(TimeDateStamp)
|
||||||
|
Q_UNUSED(ThreadDataOffset)
|
||||||
|
Q_UNUSED(StartOffset)
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << ModuleName;
|
||||||
|
|
||||||
m_pEngine->m_d->m_hDebuggeeProcess = (HANDLE)Handle;
|
m_pEngine->m_d->m_hDebuggeeProcess = (HANDLE)Handle;
|
||||||
m_pEngine->m_d->m_hDebuggeeThread = (HANDLE)InitialThreadHandle;
|
m_pEngine->m_d->m_hDebuggeeThread = (HANDLE)InitialThreadHandle;
|
||||||
//m_pEngine->qq->notifyStartupFinished();
|
m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorRunning();
|
||||||
m_pEngine->m_d->qq->notifyInferiorRunning();
|
|
||||||
|
|
||||||
ULONG currentThreadId;
|
ULONG currentThreadId;
|
||||||
if (SUCCEEDED(m_pEngine->m_d->m_pDebugSystemObjects->GetThreadIdByHandle(InitialThreadHandle, ¤tThreadId)))
|
if (SUCCEEDED(m_pEngine->m_d->m_pDebugSystemObjects->GetThreadIdByHandle(InitialThreadHandle, ¤tThreadId)))
|
||||||
@@ -159,10 +184,12 @@ STDMETHODIMP CdbDebugEventCallback::ExitProcess(
|
|||||||
__in ULONG ExitCode
|
__in ULONG ExitCode
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UNREFERENCED_PARAMETER(ExitCode);
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << ExitCode;
|
||||||
|
|
||||||
m_pEngine->m_d->m_hDebuggeeProcess = 0;
|
m_pEngine->m_d->m_hDebuggeeProcess = 0;
|
||||||
m_pEngine->m_d->m_hDebuggeeThread = 0;
|
m_pEngine->m_d->m_hDebuggeeThread = 0;
|
||||||
m_pEngine->m_d->qq->notifyInferiorExited();
|
m_pEngine->m_d->m_debuggerManagerAccess->notifyInferiorExited();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,6 +204,16 @@ STDMETHODIMP CdbDebugEventCallback::LoadModule(
|
|||||||
__in ULONG TimeDateStamp
|
__in ULONG TimeDateStamp
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(ImageFileHandle)
|
||||||
|
Q_UNUSED(BaseOffset)
|
||||||
|
Q_UNUSED(ModuleSize)
|
||||||
|
Q_UNUSED(ModuleName)
|
||||||
|
Q_UNUSED(ImageName)
|
||||||
|
Q_UNUSED(CheckSum)
|
||||||
|
Q_UNUSED(TimeDateStamp)
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << ModuleName;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,6 +223,11 @@ STDMETHODIMP CdbDebugEventCallback::UnloadModule(
|
|||||||
__in ULONG64 BaseOffset
|
__in ULONG64 BaseOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(ImageBaseName)
|
||||||
|
Q_UNUSED(BaseOffset)
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << ImageBaseName;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,6 +237,8 @@ STDMETHODIMP CdbDebugEventCallback::SystemError(
|
|||||||
__in ULONG Level
|
__in ULONG Level
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
if (debugCDB)
|
||||||
|
qDebug() << Q_FUNC_INFO << Error << Level;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,6 +247,7 @@ STDMETHODIMP CdbDebugEventCallback::SessionStatus(
|
|||||||
__in ULONG Status
|
__in ULONG Status
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(Status)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,6 +257,8 @@ STDMETHODIMP CdbDebugEventCallback::ChangeDebuggeeState(
|
|||||||
__in ULONG64 Argument
|
__in ULONG64 Argument
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(Flags)
|
||||||
|
Q_UNUSED(Argument)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +268,8 @@ STDMETHODIMP CdbDebugEventCallback::ChangeEngineState(
|
|||||||
__in ULONG64 Argument
|
__in ULONG64 Argument
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(Flags)
|
||||||
|
Q_UNUSED(Argument)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,6 +279,8 @@ STDMETHODIMP CdbDebugEventCallback::ChangeSymbolState(
|
|||||||
__in ULONG64 Argument
|
__in ULONG64 Argument
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(Flags)
|
||||||
|
Q_UNUSED(Argument)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,9 +45,7 @@ class CdbDebugEngine;
|
|||||||
class CdbDebugEventCallback : public IDebugEventCallbacks
|
class CdbDebugEventCallback : public IDebugEventCallbacks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CdbDebugEventCallback(CdbDebugEngine* dbg)
|
explicit CdbDebugEventCallback(CdbDebugEngine* dbg);
|
||||||
: m_pEngine(dbg)
|
|
||||||
{}
|
|
||||||
|
|
||||||
// IUnknown.
|
// IUnknown.
|
||||||
STDMETHOD(QueryInterface)(
|
STDMETHOD(QueryInterface)(
|
||||||
@@ -158,7 +156,7 @@ public:
|
|||||||
);
|
);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CdbDebugEngine* m_pEngine;
|
CdbDebugEngine *m_pEngine;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -31,16 +31,22 @@
|
|||||||
**
|
**
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <inc/dbgeng.h>
|
|
||||||
|
|
||||||
#include "cdbdebugoutput.h"
|
#include "cdbdebugoutput.h"
|
||||||
#include "cdbdebugengine.h"
|
#include "cdbdebugengine.h"
|
||||||
#include "cdbdebugengine_p.h"
|
#include "cdbdebugengine_p.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <inc/dbgeng.h>
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
CdbDebugOutput::CdbDebugOutput(CdbDebugEngine* engine) :
|
||||||
|
m_pEngine(engine)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
STDMETHODIMP CdbDebugOutput::QueryInterface(
|
STDMETHODIMP CdbDebugOutput::QueryInterface(
|
||||||
THIS_
|
THIS_
|
||||||
IN REFIID InterfaceId,
|
IN REFIID InterfaceId,
|
||||||
@@ -55,9 +61,7 @@ STDMETHODIMP CdbDebugOutput::QueryInterface(
|
|||||||
*Interface = (IDebugOutputCallbacks *)this;
|
*Interface = (IDebugOutputCallbacks *)this;
|
||||||
AddRef();
|
AddRef();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,9 @@
|
|||||||
#ifndef DEBUGGER_CDBOUTPUT_H
|
#ifndef DEBUGGER_CDBOUTPUT_H
|
||||||
#define DEBUGGER_CDBOUTPUT_H
|
#define DEBUGGER_CDBOUTPUT_H
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <inc/dbgeng.h>
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -42,9 +45,7 @@ class CdbDebugEngine;
|
|||||||
class CdbDebugOutput : public IDebugOutputCallbacks
|
class CdbDebugOutput : public IDebugOutputCallbacks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CdbDebugOutput(CdbDebugEngine* engine)
|
explicit CdbDebugOutput(CdbDebugEngine* engine);
|
||||||
: m_pEngine(engine)
|
|
||||||
{}
|
|
||||||
|
|
||||||
// IUnknown.
|
// IUnknown.
|
||||||
STDMETHOD(QueryInterface)(
|
STDMETHOD(QueryInterface)(
|
||||||
|
Reference in New Issue
Block a user