forked from qt-creator/qt-creator
		
	
		
			
				
	
	
		
			151 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "windbgthread.h"
 | 
						|
#include <QDebug>
 | 
						|
 | 
						|
#define DBGHELP_TRANSLATE_TCHAR
 | 
						|
#include <Dbghelp.h>
 | 
						|
 | 
						|
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);
 | 
						|
}
 |