#include "windbgthread.h" #include #define DBGHELP_TRANSLATE_TCHAR #include WinDbgThread::WinDbgThread(QObject* parent) : QThread(parent), m_state(Idle) { } WinDbgThread::~WinDbgThread() { stopProcess(); } void WinDbgThread::startProcess(const QString& filename) { stopProcess(); m_bOwnsProcess = true; m_processFileName = filename; m_pi.dwProcessId = 0; QThread::start(); } void WinDbgThread::stopProcess() { if (!QThread::isRunning()) return; switch (m_state) { case ProcessRunning: if (m_bOwnsProcess) { m_bOwnsProcess = false; // don't terminate in the loop again TerminateProcess(m_pi.hProcess, 0); } // don't break here case ProcessPaused: m_bAbortEventPollingLoop = true; resume(); break; } QThread::wait(5000); if (QThread::isRunning()) { qWarning("WinDbgThread still running... terminating!"); QThread::terminate(); } } void WinDbgThread::attachToProcess(DWORD processId) { m_bOwnsProcess = false; m_processFileName = QString(); m_pi.dwProcessId = processId; QThread::start(); } void WinDbgThread::run() { qDebug() << "WinDbgThread started"; // start process or attach process if (m_bOwnsProcess) { // create new process internalStartProcess(); } else { // attach to process qWarning("attach to process not yet implemented"); return; } m_hThisThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, GetCurrentThreadId()); if (!m_hThisThread) { qWarning("WinDbgThread: can't open thread handle"); return; } DEBUG_EVENT debugEvent; m_bAbortEventPollingLoop = false; while (WaitForDebugEvent(&debugEvent, INFINITE)) { setState(ProcessPaused); emit debugEventOccured(&debugEvent); suspend(); if (m_bAbortEventPollingLoop) break; ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE); setState(ProcessRunning); } setState(Idle); if (m_bOwnsProcess) { TerminateProcess(m_pi.hProcess, 0); } CloseHandle(m_pi.hProcess); CloseHandle(m_pi.hThread); CloseHandle(m_hThisThread); qDebug() << "WinDbgThread finished"; } void WinDbgThread::continueProcess() { if (m_state == ProcessPaused) resume(); } void WinDbgThread::pauseProcess() { if (m_state == ProcessRunning) DebugBreakProcess(m_pi.hProcess); } void WinDbgThread::internalStartProcess() { BOOL bSuccess; STARTUPINFO si; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.wShowWindow = TRUE; ZeroMemory(&m_pi, sizeof(m_pi)); DWORD dwCreationFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS; bSuccess = CreateProcess(m_processFileName.utf16(), NULL, NULL, NULL, FALSE, dwCreationFlags, NULL, NULL, &si, &m_pi ); if (bSuccess) setState(ProcessRunning); else setState(Idle); } void WinDbgThread::setState(State s) { m_state = s; } void WinDbgThread::suspend() { SuspendThread(m_hThisThread); } void WinDbgThread::resume() { ResumeThread(m_hThisThread); }