home *** CD-ROM | disk | FTP | other *** search
- /////////////////////////////////////////////////////////////////////////////
- //
- // File : MsgTracerThread.cpp
- // Project : MsgTrace
- // Component : MsgTracer
- //---------------------------------------------------------------------------
- // Description : doing thread
- //
- /////////////////////////////////////////////////////////////////////////////
- //
- // SourceSafe Strings. Do not change.
- //---------------------------------------------------------------------------
- // $Author: jeskes $
- // $Date: $
- // $Revision: $
- //
- /////////////////////////////////////////////////////////////////////////////
-
- #include "stdafx.h"
- #include "MsgTracerApp.h"
- #include "MsgTracerThread.h"
- #include "MsgTracerProcess.h"
- #include "OutputDoc.h"
-
- /////////////////////////////////////////////////////////////////////////////
- // CMsgTracerThread: construction
- /////////////////////////////////////////////////////////////////////////////
-
- CMsgTracerThread::CMsgTracerThread() :
-
- m_pWinThread( NULL ),
- m_pProcessToAttach( NULL ),
-
- m_bWantOutputDebugStringEvents ( TRUE )
-
- {
- m_hStopEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
- m_hEndedEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
- m_hAttachEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
- m_hAttachedEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
- m_hAttachMutex = ::CreateMutex( NULL, FALSE, NULL );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- CMsgTracerThread::~CMsgTracerThread()
- {
- ::CloseHandle( m_hStopEvent );
- ::CloseHandle( m_hEndedEvent );
- ::CloseHandle( m_hAttachEvent );
- ::CloseHandle( m_hAttachedEvent );
- ::CloseHandle( m_hAttachMutex );
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CMsgTracerThread: thread proc
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::Run()
- {
- ASSERT( NULL == m_pWinThread );
-
- ::ResetEvent( m_hStopEvent );
- ::ResetEvent( m_hEndedEvent );
- ::ResetEvent( m_hAttachEvent );
- ::ResetEvent( m_hAttachedEvent );
-
- m_pWinThread = AfxBeginThread( (AFX_THREADPROC) ThreadStub, this );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::Stop()
- {
- ::SetEvent( m_hStopEvent );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- UINT CMsgTracerThread::ThreadStub( CMsgTracerThread* pThis )
- {
- return( pThis->ThreadProc() );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- UINT CMsgTracerThread::ThreadProc()
- {
- while( TRUE )
- {
- if( WAIT_OBJECT_0 == ::WaitForSingleObject( m_hStopEvent, 0 ) )
- {
- break;
- }
-
- if( WAIT_OBJECT_0 == ::WaitForSingleObject( m_hAttachEvent, 0 ) )
- {
- m_pProcessToAttach->AttachProcess();
- m_pProcessToAttach = NULL;
- ::ResetEvent( m_hAttachEvent );
- ::SetEvent( m_hAttachedEvent );
- }
-
- if( ::WaitForDebugEvent( &m_de, ThisApp().m_nTimeoutWaitForDebugEvent ) )
- {
- DispatchDebugEvent();
- }
- }
-
- ::SetEvent( m_hEndedEvent );
-
- m_pWinThread = NULL;
-
- return( 0 );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- BOOL CMsgTracerThread::IsRunning( DWORD dwTimeout )
- {
- if( NULL == m_pWinThread )
- {
- return( FALSE );
- }
- return( WAIT_OBJECT_0 != ::WaitForSingleObject( m_hEndedEvent, dwTimeout ) );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::Suspend()
- {
- if( NULL != m_pWinThread )
- {
- m_pWinThread->SuspendThread();
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::Resume()
- {
- if( NULL != m_pWinThread )
- {
- m_pWinThread->ResumeThread();
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::DispatchDebugEvent()
- {
- CSingleLock lock( &m_csDispatch, TRUE );
-
- DWORD dwContinueStatus = DBG_CONTINUE;
-
- switch( m_de.dwDebugEventCode )
- {
- case CREATE_PROCESS_DEBUG_EVENT:
- OnCreateProcessDebugEvent();
- break;
-
- case EXIT_PROCESS_DEBUG_EVENT:
- OnExitProcessDebugEvent();
- break;
-
- case OUTPUT_DEBUG_STRING_EVENT:
- OnOutputDebugStringEvent();
- break;
-
- case EXCEPTION_DEBUG_EVENT:
- dwContinueStatus = OnExceptionDebugEvent();
- break;
- }
-
- ContinueDebugEvent( m_de.dwProcessId, m_de.dwThreadId, dwContinueStatus );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::OnCreateProcessDebugEvent()
- {
- CString s;
- s.Format( "[%08X/%08X] : Process attached", m_de.dwProcessId, m_de.dwThreadId );
- ThisApp().GetOutputDoc().AddLine( s );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::OnExitProcessDebugEvent()
- {
- CMsgTracerProcess* pProcess = NULL;
-
- if( ThisApp().IsAttached( m_de.dwProcessId, &pProcess ) )
- {
- pProcess->OnTerminateProcess( TRUE );
- }
-
- CString s;
- s.Format( "[%08X/%08X] : Process ended", m_de.dwProcessId, m_de.dwThreadId );
- ThisApp().GetOutputDoc().AddLine( s );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::OnOutputDebugStringEvent()
- {
- if( !m_bWantOutputDebugStringEvents )
- {
- return;
- }
-
- HANDLE hProcess = ThisApp().ProcessIdToHandle( m_de.dwProcessId );
-
- if( NULL == hProcess )
- {
- return;
- }
-
- static char szBuffer[ 2048 ];
- int nLenPrefix = sprintf( szBuffer,
- "[%08X/%08X] : ",
- m_de.dwProcessId,
- m_de.dwThreadId,
- m_de.u.DebugString.lpDebugStringData );
-
-
- szBuffer[ nLenPrefix ] = '\0';
-
- ReadProcessMemory( hProcess,
- m_de.u.DebugString.lpDebugStringData,
- szBuffer + nLenPrefix,
- m_de.u.DebugString.nDebugStringLength,
- NULL );
-
- ThisApp().GetOutputDoc().AddLine( szBuffer );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- DWORD CMsgTracerThread::OnExceptionDebugEvent()
- {
- CString s;
- s.Format( "[%08X/%08X] : Exception: first chance=%d, code = %08X, flags = %08X",
- m_de.dwProcessId,
- m_de.dwThreadId,
- m_de.u.Exception.dwFirstChance,
- m_de.u.Exception.ExceptionRecord.ExceptionCode,
- m_de.u.Exception.ExceptionRecord.ExceptionFlags );
-
- ThisApp().GetOutputDoc().AddLine( s );
-
- if( EXCEPTION_NONCONTINUABLE & m_de.u.Exception.ExceptionRecord.ExceptionFlags )
- {
- return( DBG_EXCEPTION_NOT_HANDLED );
- }
-
- if( EXCEPTION_BREAKPOINT == m_de.u.Exception.ExceptionRecord.ExceptionCode )
- {
- return( DBG_CONTINUE );
- }
-
- if( 0 != m_de.u.Exception.dwFirstChance )
- {
- s.Format( "[%08X/%08X] : Exception: continue looking for an exception handler.",
- m_de.dwProcessId, m_de.dwThreadId );
- ThisApp().GetOutputDoc().AddLine( s );
-
- return( DBG_EXCEPTION_NOT_HANDLED );
- }
-
- // last-chance exception: must end the process
-
- s.Format( "[%08X/%08X] : Exception: not handled - tracer must terminate process.",
- m_de.dwProcessId, m_de.dwThreadId );
- ThisApp().GetOutputDoc().AddLine( s );
-
- TerminateProcess( ThisApp().ProcessIdToHandle( m_de.dwProcessId ), -1 );
-
- return( DBG_CONTINUE );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- void CMsgTracerThread::AttachProcess( CMsgTracerProcess* pProcess, BOOL bWait )
- {
- ASSERT( NULL != pProcess );
-
- SAttachStruct* pAttachStruct = new SAttachStruct;
- ASSERT( NULL != pAttachStruct );
-
- pAttachStruct->m_pThis = this;
- pAttachStruct->m_pProcessToAttach = pProcess;
-
- CWinThread* pThread = AfxBeginThread( (AFX_THREADPROC) AttachStub,
- pAttachStruct,
- THREAD_PRIORITY_NORMAL,
- 0,
- CREATE_SUSPENDED );
-
- if( NULL == pThread )
- {
- return;
- }
-
- HANDLE hThread = pThread->m_hThread;
-
- pThread->ResumeThread();
-
- if( bWait )
- {
- ::WaitForSingleObject( hThread, INFINITE );
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- UINT CMsgTracerThread::AttachStub( SAttachStruct* pAttachStruct )
- {
- ASSERT( NULL != pAttachStruct );
-
- UINT nReturn = 0;
-
- __try
- {
- if( WAIT_OBJECT_0 == ::WaitForSingleObject( pAttachStruct->m_pThis->m_hAttachMutex, INFINITE ) )
- {
- nReturn = pAttachStruct->m_pThis->AttachProc( pAttachStruct->m_pProcessToAttach );
- }
- }
- __except( EXCEPTION_EXECUTE_HANDLER )
- {
- }
-
- ::ReleaseMutex( pAttachStruct->m_pThis->m_hAttachMutex );
-
- delete pAttachStruct;
-
- return( nReturn );
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- UINT CMsgTracerThread::AttachProc( CMsgTracerProcess* pProcessToAttach )
- {
- ASSERT( NULL != pProcessToAttach );
-
- ::ResetEvent( m_hAttachedEvent );
-
- if( !IsRunning() )
- {
- Run();
- }
-
- m_pProcessToAttach = pProcessToAttach;
-
- ::SetEvent( m_hAttachEvent );
- ::WaitForSingleObject( m_hAttachedEvent, INFINITE );
-
- return( 0 );
- }
-