home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / MSGTRACE.ZIP / MyProjects / MsgTrace / MsgTracer / MsgTracerThread.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-30  |  8.9 KB  |  361 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File        : MsgTracerThread.cpp
  4. // Project     : MsgTrace
  5. // Component   : MsgTracer
  6. //---------------------------------------------------------------------------
  7. // Description : doing thread
  8. //
  9. /////////////////////////////////////////////////////////////////////////////
  10. //
  11. // SourceSafe Strings. Do not change.
  12. //---------------------------------------------------------------------------
  13. // $Author: jeskes $
  14. // $Date: $
  15. // $Revision: $
  16. //
  17. /////////////////////////////////////////////////////////////////////////////
  18.  
  19. #include "stdafx.h"
  20. #include "MsgTracerApp.h"
  21. #include "MsgTracerThread.h"
  22. #include "MsgTracerProcess.h"
  23. #include "OutputDoc.h"
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CMsgTracerThread: construction
  27. /////////////////////////////////////////////////////////////////////////////
  28.  
  29. CMsgTracerThread::CMsgTracerThread() : 
  30.  
  31.     m_pWinThread( NULL ), 
  32.     m_pProcessToAttach( NULL ), 
  33.     
  34.     m_bWantOutputDebugStringEvents ( TRUE )
  35.  
  36. {
  37.     m_hStopEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
  38.     m_hEndedEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
  39.     m_hAttachEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
  40.     m_hAttachedEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
  41.     m_hAttachMutex = ::CreateMutex( NULL, FALSE, NULL );
  42. }
  43.  
  44. /////////////////////////////////////////////////////////////////////////////
  45.  
  46. CMsgTracerThread::~CMsgTracerThread()
  47. {
  48.     ::CloseHandle( m_hStopEvent );
  49.     ::CloseHandle( m_hEndedEvent );
  50.     ::CloseHandle( m_hAttachEvent );
  51.     ::CloseHandle( m_hAttachedEvent );
  52.     ::CloseHandle( m_hAttachMutex );
  53. }
  54.  
  55. /////////////////////////////////////////////////////////////////////////////
  56. // CMsgTracerThread: thread proc
  57. /////////////////////////////////////////////////////////////////////////////
  58.  
  59. void CMsgTracerThread::Run()
  60. {
  61.     ASSERT( NULL == m_pWinThread );
  62.  
  63.     ::ResetEvent( m_hStopEvent );
  64.     ::ResetEvent( m_hEndedEvent );
  65.     ::ResetEvent( m_hAttachEvent );
  66.     ::ResetEvent( m_hAttachedEvent );
  67.  
  68.     m_pWinThread = AfxBeginThread( (AFX_THREADPROC) ThreadStub, this );
  69. }
  70.  
  71. /////////////////////////////////////////////////////////////////////////////
  72.  
  73. void CMsgTracerThread::Stop()
  74. {
  75.     ::SetEvent( m_hStopEvent );
  76. }
  77.  
  78. /////////////////////////////////////////////////////////////////////////////
  79.  
  80. UINT CMsgTracerThread::ThreadStub( CMsgTracerThread* pThis )
  81. {
  82.     return( pThis->ThreadProc() );
  83. }
  84.  
  85. /////////////////////////////////////////////////////////////////////////////
  86.  
  87. UINT CMsgTracerThread::ThreadProc()
  88. {
  89.     while( TRUE )
  90.     {
  91.         if( WAIT_OBJECT_0 == ::WaitForSingleObject( m_hStopEvent, 0 ) )
  92.         {
  93.             break;
  94.         }
  95.  
  96.         if( WAIT_OBJECT_0 == ::WaitForSingleObject( m_hAttachEvent, 0 ) )
  97.         {
  98.             m_pProcessToAttach->AttachProcess();
  99.             m_pProcessToAttach = NULL;
  100.             ::ResetEvent( m_hAttachEvent );
  101.             ::SetEvent( m_hAttachedEvent );
  102.         }
  103.  
  104.         if( ::WaitForDebugEvent( &m_de, ThisApp().m_nTimeoutWaitForDebugEvent ) )
  105.         {
  106.             DispatchDebugEvent();
  107.         }
  108.     }
  109.  
  110.     ::SetEvent( m_hEndedEvent );
  111.  
  112.     m_pWinThread = NULL;
  113.  
  114.     return( 0 );
  115. }
  116.  
  117. /////////////////////////////////////////////////////////////////////////////
  118.  
  119. BOOL CMsgTracerThread::IsRunning( DWORD dwTimeout )
  120. {
  121.     if( NULL == m_pWinThread )
  122.     {
  123.         return( FALSE );
  124.     }
  125.     return( WAIT_OBJECT_0 != ::WaitForSingleObject( m_hEndedEvent, dwTimeout ) );
  126. }
  127.  
  128. /////////////////////////////////////////////////////////////////////////////
  129.  
  130. void CMsgTracerThread::Suspend()
  131. {
  132.     if( NULL != m_pWinThread )
  133.     {
  134.         m_pWinThread->SuspendThread();
  135.     }
  136. }
  137.  
  138. /////////////////////////////////////////////////////////////////////////////
  139.  
  140. void CMsgTracerThread::Resume()
  141. {
  142.     if( NULL != m_pWinThread )
  143.     {
  144.         m_pWinThread->ResumeThread();
  145.     }
  146. }
  147.  
  148. /////////////////////////////////////////////////////////////////////////////
  149.  
  150. void CMsgTracerThread::DispatchDebugEvent()
  151. {
  152.     CSingleLock lock( &m_csDispatch, TRUE );
  153.  
  154.     DWORD dwContinueStatus = DBG_CONTINUE;
  155.  
  156.     switch( m_de.dwDebugEventCode )
  157.     {
  158.         case CREATE_PROCESS_DEBUG_EVENT:
  159.             OnCreateProcessDebugEvent();
  160.             break;
  161.  
  162.         case EXIT_PROCESS_DEBUG_EVENT:
  163.             OnExitProcessDebugEvent();
  164.             break;
  165.  
  166.         case OUTPUT_DEBUG_STRING_EVENT:
  167.             OnOutputDebugStringEvent();
  168.             break;
  169.  
  170.         case EXCEPTION_DEBUG_EVENT:
  171.             dwContinueStatus = OnExceptionDebugEvent();
  172.             break;
  173.     }
  174.  
  175.     ContinueDebugEvent( m_de.dwProcessId, m_de.dwThreadId, dwContinueStatus );
  176. }
  177.  
  178. /////////////////////////////////////////////////////////////////////////////
  179.  
  180. void CMsgTracerThread::OnCreateProcessDebugEvent()
  181. {
  182.     CString s;
  183.     s.Format( "[%08X/%08X] : Process attached", m_de.dwProcessId, m_de.dwThreadId );
  184.     ThisApp().GetOutputDoc().AddLine( s );
  185. }
  186.  
  187. /////////////////////////////////////////////////////////////////////////////
  188.  
  189. void CMsgTracerThread::OnExitProcessDebugEvent()
  190. {
  191.     CMsgTracerProcess* pProcess = NULL;
  192.  
  193.     if( ThisApp().IsAttached( m_de.dwProcessId, &pProcess ) )
  194.     {
  195.         pProcess->OnTerminateProcess( TRUE );
  196.     }
  197.  
  198.     CString s;
  199.     s.Format( "[%08X/%08X] : Process ended", m_de.dwProcessId, m_de.dwThreadId );
  200.     ThisApp().GetOutputDoc().AddLine( s );
  201. }
  202.  
  203. /////////////////////////////////////////////////////////////////////////////
  204.  
  205. void CMsgTracerThread::OnOutputDebugStringEvent()
  206. {
  207.     if( !m_bWantOutputDebugStringEvents )
  208.     {
  209.         return;
  210.     }
  211.  
  212.     HANDLE hProcess = ThisApp().ProcessIdToHandle( m_de.dwProcessId );
  213.  
  214.     if( NULL == hProcess )
  215.     {
  216.         return;
  217.     }
  218.  
  219.     static char szBuffer[ 2048 ];
  220.     int nLenPrefix = sprintf( szBuffer, 
  221.                               "[%08X/%08X] : ",
  222.                               m_de.dwProcessId,
  223.                               m_de.dwThreadId,
  224.                               m_de.u.DebugString.lpDebugStringData );
  225.     
  226.  
  227.     szBuffer[ nLenPrefix ] = '\0';
  228.  
  229.     ReadProcessMemory( hProcess,
  230.                        m_de.u.DebugString.lpDebugStringData,
  231.                        szBuffer + nLenPrefix,
  232.                        m_de.u.DebugString.nDebugStringLength,
  233.                        NULL );
  234.  
  235.     ThisApp().GetOutputDoc().AddLine( szBuffer );
  236. }
  237.  
  238. /////////////////////////////////////////////////////////////////////////////
  239.  
  240. DWORD CMsgTracerThread::OnExceptionDebugEvent()
  241. {
  242.     CString s;
  243.     s.Format( "[%08X/%08X] : Exception: first chance=%d, code = %08X, flags = %08X",
  244.               m_de.dwProcessId,
  245.               m_de.dwThreadId,
  246.               m_de.u.Exception.dwFirstChance,
  247.               m_de.u.Exception.ExceptionRecord.ExceptionCode,
  248.               m_de.u.Exception.ExceptionRecord.ExceptionFlags );
  249.  
  250.     ThisApp().GetOutputDoc().AddLine( s );
  251.  
  252.     if( EXCEPTION_NONCONTINUABLE & m_de.u.Exception.ExceptionRecord.ExceptionFlags )
  253.     {
  254.         return( DBG_EXCEPTION_NOT_HANDLED );
  255.     }
  256.  
  257.     if( EXCEPTION_BREAKPOINT == m_de.u.Exception.ExceptionRecord.ExceptionCode )
  258.     {
  259.         return( DBG_CONTINUE );
  260.     }
  261.  
  262.     if( 0 != m_de.u.Exception.dwFirstChance )
  263.     {
  264.         s.Format( "[%08X/%08X] : Exception: continue looking for an exception handler.",
  265.                   m_de.dwProcessId, m_de.dwThreadId );
  266.         ThisApp().GetOutputDoc().AddLine( s );
  267.  
  268.         return( DBG_EXCEPTION_NOT_HANDLED );
  269.     }
  270.  
  271.     // last-chance exception: must end the process
  272.  
  273.     s.Format( "[%08X/%08X] : Exception: not handled - tracer must terminate process.",
  274.               m_de.dwProcessId, m_de.dwThreadId );
  275.     ThisApp().GetOutputDoc().AddLine( s );
  276.  
  277.     TerminateProcess( ThisApp().ProcessIdToHandle( m_de.dwProcessId ), -1 );
  278.  
  279.     return( DBG_CONTINUE );
  280. }
  281.  
  282. /////////////////////////////////////////////////////////////////////////////
  283.  
  284. void CMsgTracerThread::AttachProcess( CMsgTracerProcess* pProcess, BOOL bWait )
  285. {
  286.     ASSERT( NULL != pProcess );
  287.  
  288.     SAttachStruct* pAttachStruct = new SAttachStruct;
  289.     ASSERT( NULL != pAttachStruct );
  290.  
  291.     pAttachStruct->m_pThis = this;
  292.     pAttachStruct->m_pProcessToAttach = pProcess;
  293.  
  294.     CWinThread* pThread = AfxBeginThread( (AFX_THREADPROC) AttachStub,
  295.                                           pAttachStruct,
  296.                                           THREAD_PRIORITY_NORMAL,
  297.                                           0,
  298.                                           CREATE_SUSPENDED );
  299.  
  300.     if( NULL == pThread )
  301.     {
  302.         return;
  303.     }
  304.  
  305.     HANDLE hThread = pThread->m_hThread;
  306.  
  307.     pThread->ResumeThread();
  308.  
  309.     if( bWait )
  310.     {
  311.         ::WaitForSingleObject( hThread, INFINITE );
  312.     }
  313. }
  314.  
  315. /////////////////////////////////////////////////////////////////////////////
  316.  
  317. UINT CMsgTracerThread::AttachStub( SAttachStruct* pAttachStruct )
  318. {
  319.     ASSERT( NULL != pAttachStruct );
  320.  
  321.     UINT nReturn = 0;
  322.  
  323.     __try
  324.     {
  325.         if( WAIT_OBJECT_0 == ::WaitForSingleObject( pAttachStruct->m_pThis->m_hAttachMutex, INFINITE ) )
  326.         {
  327.             nReturn = pAttachStruct->m_pThis->AttachProc( pAttachStruct->m_pProcessToAttach );
  328.         }
  329.     }
  330.     __except( EXCEPTION_EXECUTE_HANDLER )
  331.     {
  332.     }
  333.  
  334.     ::ReleaseMutex( pAttachStruct->m_pThis->m_hAttachMutex );
  335.  
  336.     delete pAttachStruct;
  337.  
  338.     return( nReturn );
  339. }
  340.  
  341. /////////////////////////////////////////////////////////////////////////////
  342.  
  343. UINT CMsgTracerThread::AttachProc( CMsgTracerProcess* pProcessToAttach )
  344. {
  345.     ASSERT( NULL != pProcessToAttach );
  346.  
  347.     ::ResetEvent( m_hAttachedEvent );
  348.  
  349.     if( !IsRunning() )
  350.     {
  351.         Run();
  352.     }
  353.  
  354.     m_pProcessToAttach = pProcessToAttach;
  355.     
  356.     ::SetEvent( m_hAttachEvent );
  357.     ::WaitForSingleObject( m_hAttachedEvent, INFINITE );
  358.  
  359.     return( 0 );
  360. }
  361.