home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 39 / IOPROG_39.ISO / SOFT / sdkjava40.exe / data1.cab / fg_Samples / Samples / Debugger / calltrace / CallTrace.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-04  |  18.5 KB  |  831 lines

  1. /*
  2.  * CallTrace.cpp - Java method call tracing tool.
  3.  */
  4.  
  5.  
  6. /* Headers
  7.  **********/
  8.  
  9. #include <javadbg.h>
  10.  
  11. #include <stdio.h>
  12.  
  13.  
  14. /* Constants
  15.  ************/
  16.  
  17. #define QUOTE                               '\''
  18. #define QUOTES                              '"'
  19. #define SPACE                               ' '
  20. #define TAB                                 '\t'
  21.  
  22.  
  23. /* Macros
  24.  *********/
  25.  
  26. #define DECLARE_STANDARD_TYPES(type)        typedef type *P##type; \
  27.                                             typedef const type C##type; \
  28.                                             typedef const type *PC##type;
  29.  
  30. #define SAFE_CAST(type, obj)                (((type)(obj) == (obj) ? 0 : 0), (type)(obj))
  31.  
  32. #define WIN32_ERROR_TO_HRESULT(err)         MAKE_SCODE(SEVERITY_ERROR, FACILITY_WIN32, (err))
  33.  
  34. #define WIN32_RESULT_TO_HRESULT(err)        ((err) == ERROR_SUCCESS ? S_OK : WIN32_ERROR_TO_HRESULT(err))
  35.  
  36. #define LAST_WIN32_ERROR_TO_HRESULT()       WIN32_RESULT_TO_HRESULT(GetLastError())
  37.  
  38.  
  39. /* Classes
  40.  **********/
  41.  
  42. typedef LPOLESTR POLESTR;
  43. typedef LPCOLESTR PCOLESTR;
  44.  
  45. DECLARE_STANDARD_TYPES(IRemoteClassField);
  46. DECLARE_STANDARD_TYPES(IRemoteContainerField);
  47. DECLARE_STANDARD_TYPES(IRemoteContainerObject);
  48. DECLARE_STANDARD_TYPES(IRemoteDebugManager);
  49. DECLARE_STANDARD_TYPES(IRemoteDebugManagerCallback);
  50. DECLARE_STANDARD_TYPES(IRemoteField);
  51. DECLARE_STANDARD_TYPES(IRemoteMethodField);
  52. DECLARE_STANDARD_TYPES(IRemoteObject);
  53. DECLARE_STANDARD_TYPES(IRemoteProcess);
  54. DECLARE_STANDARD_TYPES(IRemoteProcessCallback);
  55. DECLARE_STANDARD_TYPES(IRemoteStackFrame);
  56. DECLARE_STANDARD_TYPES(IRemoteThread);
  57. DECLARE_STANDARD_TYPES(IRemoteThreadEx);
  58. DECLARE_STANDARD_TYPES(IRemoteThreadGroup);
  59.  
  60. class RefCount;
  61. DECLARE_STANDARD_TYPES(RefCount);
  62.  
  63. // Generic reference counting virtual base class.
  64.  
  65. class RefCount
  66. {
  67. private:
  68.  
  69.     /* Fields
  70.      *********/
  71.  
  72.    ULONG m_ulcRef;
  73.  
  74. public:
  75.  
  76.     /* Methods
  77.      **********/
  78.  
  79.     RefCount(void)
  80.     {
  81.         m_ulcRef = 1;
  82.     }
  83.  
  84.     ~RefCount(void)
  85.     {
  86.     }
  87.  
  88.     // IUnknown methods
  89.  
  90.     // N.b., ulcRef is only guaranteed to match the new reference count in sign
  91.     // and zero-ness.
  92.  
  93.     ULONG STDMETHODCALLTYPE AddRef(void)
  94.     {
  95.         return((ULONG)InterlockedIncrement((PLONG)&m_ulcRef));
  96.     }
  97.  
  98.     ULONG STDMETHODCALLTYPE Release(void)
  99.     {
  100.         return((ULONG)InterlockedDecrement((PLONG)&m_ulcRef));
  101.     }
  102. };
  103.  
  104. class CallTracer;
  105. DECLARE_STANDARD_TYPES(CallTracer);
  106.  
  107. class CallTracer : public RefCount,
  108.                    public IRemoteDebugManagerCallback,
  109.                    public IRemoteProcessCallback
  110. {
  111. private:
  112.     /* Fields
  113.      *********/
  114.  
  115.     PIRemoteDebugManager m_pirdm;
  116.     PIRemoteProcess m_pirp;
  117.     DWORD m_dwMsgLoopThreadID;
  118.  
  119.     /* Methods
  120.      **********/
  121.  
  122.     UINT RunMessageLoop(void);
  123.     BOOL QuitMessageLoop(UINT uResult);
  124.     HRESULT DebugProcess(PCSTR pcszDebuggeeCmdLine);
  125.     static PCSTR GetFRAMEKINDString(FRAMEKIND fk);
  126.     static ULONG CountParentFrames(PIRemoteStackFrame pirsf);
  127.     static HRESULT DumpContext(PIRemoteThread pirth);
  128.  
  129. public:
  130.     /* Methods
  131.      **********/
  132.  
  133.     CallTracer(void);
  134.     ~CallTracer(void);
  135.  
  136.     HRESULT Initialize(PIRemoteDebugManager pirdm);
  137.     void Terminate(void);
  138.     HRESULT Run(PCSTR pcszDebuggeeCmdLine);
  139.  
  140.     // IRemoteDebugManagerCallback methods
  141.  
  142.     STDMETHODIMP ProcessCreateEvent(PIRemoteProcess pirpNew, PIRemoteProcess pirpParent);
  143.  
  144.     // IRemoteProcessCallback methods
  145.  
  146.     STDMETHODIMP DebugStringEvent(PIRemoteThread pirth, PCOLESTR pcwszDebugMsg);
  147.     STDMETHODIMP CodeBreakpointEvent(PIRemoteThread pirth);
  148.     STDMETHODIMP DataBreakpointEvent(PIRemoteThread pirth, PIRemoteObject piro);
  149.     STDMETHODIMP ExceptionEvent(PIRemoteThread pirth, PIRemoteClassField pircfException, EXCEPTIONKIND exk);
  150.     STDMETHODIMP StepEvent(PIRemoteThread pirth);
  151.     STDMETHODIMP CanStopEvent(PIRemoteThread pirth);
  152.     STDMETHODIMP BreakEvent(PIRemoteThread pirth);
  153.     STDMETHODIMP ThreadCreateEvent(PIRemoteThread pirth);
  154.     STDMETHODIMP ThreadDestroyEvent(PIRemoteThread pirth);
  155.     STDMETHODIMP ThreadGroupCreateEvent(PIRemoteThread pirth, PIRemoteThreadGroup pirthg);
  156.     STDMETHODIMP ThreadGroupDestroyEvent(PIRemoteThread pirth, PIRemoteThreadGroup pirthg);
  157.     STDMETHODIMP ClassLoadEvent(PIRemoteThread pirth, PIRemoteClassField pircfClass);
  158.     STDMETHODIMP ClassUnloadEvent(PIRemoteThread pirth, PIRemoteClassField pircfClass);
  159.     STDMETHODIMP ProcessDestroyEvent(PIRemoteThread pirth);
  160.     STDMETHODIMP TraceEvent(PIRemoteThread pirth);
  161.     STDMETHODIMP LoadCompleteEvent(PIRemoteThread pirth);
  162.  
  163.     // IUnknown methods
  164.  
  165.     ULONG STDMETHODCALLTYPE AddRef(void)
  166.     {
  167.         return(RefCount::AddRef());
  168.     }
  169.  
  170.     // Wrap RefCount::Release() here so we don't need a virtual base class.
  171.     ULONG STDMETHODCALLTYPE Release(void)
  172.     {
  173.         ULONG ulcRef;
  174.  
  175.         ulcRef = RefCount::Release();
  176.  
  177.         // N.b., there is a race condition here we're ignoring.
  178.  
  179.         if (! ulcRef)
  180.             delete(this);
  181.  
  182.         return(ulcRef);
  183.     }
  184.  
  185.     STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppvObject);
  186. };
  187.  
  188.  
  189. /* Module Constants
  190.  *******************/
  191.  
  192. #pragma data_seg(".rdata")
  193.  
  194. const char s_cszDebugKey[]          = "Software\\Microsoft\\Java VM\\Debug";
  195.  
  196. #pragma data_seg()
  197.  
  198.  
  199. /***************************** Private Functions *****************************/
  200.  
  201.  
  202. PCSTR SkipWhiteSpace(PCSTR pcsz)
  203. {
  204.     while (*pcsz == SPACE ||
  205.            *pcsz == TAB)
  206.         pcsz = CharNext(pcsz);
  207.  
  208.     return(pcsz);
  209. }
  210.  
  211.  
  212. PCSTR SkipNonWhiteSpace(PCSTR pcsz)
  213. {
  214.     while (*pcsz &&
  215.            *pcsz != SPACE &&
  216.            *pcsz != TAB)
  217.         pcsz = CharNext(pcsz);
  218.  
  219.     return(pcsz);
  220. }
  221.  
  222.  
  223. PCSTR SkipQuotedArg(PCSTR pcsz)
  224. {
  225.     char chQ;
  226.  
  227.     // Skip over quoted argument to matching quote.
  228.  
  229.     chQ = *pcsz;
  230.     pcsz = CharNext(pcsz);
  231.  
  232.     while (*pcsz &&
  233.            *pcsz != chQ)
  234.         pcsz = CharNext(pcsz);
  235.  
  236.     if (*pcsz == chQ)
  237.         pcsz = CharNext(pcsz);
  238.  
  239.     return(pcsz);
  240. }
  241.  
  242.  
  243. PCSTR SkipPossiblyQuotedArg(PCSTR pcsz)
  244. {
  245.     pcsz = SkipWhiteSpace(pcsz);
  246.  
  247.     switch (*pcsz)
  248.     {
  249.         case QUOTE:
  250.         case QUOTES:
  251.             // Skip over quoted argument to matching quote.
  252.             pcsz = SkipQuotedArg(pcsz);
  253.             break;
  254.  
  255.         default:
  256.             // Skip over unquoted argument.
  257.             pcsz = SkipNonWhiteSpace(pcsz);
  258.             break;
  259.     }
  260.  
  261.     return(pcsz);
  262. }
  263.  
  264.  
  265. PCSTR GetDebuggeeCmdLine(PCSTR pcszCmdLine)
  266. {
  267.     PCSTR pcszDebuggeeCmdLine;
  268.  
  269.     pcszDebuggeeCmdLine = SkipWhiteSpace(SkipPossiblyQuotedArg(pcszCmdLine));
  270.  
  271.     if (! *pcszDebuggeeCmdLine)
  272.         pcszDebuggeeCmdLine = NULL;
  273.  
  274.     return(pcszDebuggeeCmdLine);
  275. }
  276.  
  277.  
  278. BOOL CreateDebugKey(void)
  279. {
  280.     BOOL bResult;
  281.     DWORD dwDisposition;
  282.     HKEY hkeyDebug;
  283.  
  284.     bResult = (RegCreateKeyEx(HKEY_LOCAL_MACHINE, s_cszDebugKey, 0, NULL, 0, KEY_WRITE, NULL, &hkeyDebug, &dwDisposition)
  285.                == ERROR_SUCCESS);
  286.  
  287.     if (bResult)
  288.         RegCloseKey(hkeyDebug);
  289.  
  290.     return(bResult);
  291. }
  292.  
  293.  
  294. BOOL DeleteDebugKey(void)
  295. {
  296.     return(RegDeleteKey(HKEY_LOCAL_MACHINE, s_cszDebugKey) == ERROR_SUCCESS);
  297. }
  298.  
  299.  
  300. /****************************** Public Functions *****************************/
  301.  
  302.  
  303. HRESULT RunDebugger(PCSTR pcszDebuggeeCmdLine)
  304. {
  305.     HRESULT hr;
  306.  
  307.     hr = CoInitialize(NULL);
  308.  
  309.     if (SUCCEEDED(hr))
  310.     {
  311.         PIRemoteDebugManager pirdm;
  312.  
  313.         hr = CoCreateInstance(CLSID_RemoteJavaDebugManager, NULL, CLSCTX_LOCAL_SERVER, IID_IRemoteDebugManager, (PVOID *)&pirdm);
  314.  
  315.         if (hr == S_OK)
  316.         {
  317.             PCallTracer pct;
  318.  
  319.             pct = new(CallTracer);
  320.  
  321.             if (pct)
  322.             {
  323.                 hr = pct->Initialize(pirdm);
  324.  
  325.                 if (hr == S_OK)
  326.                 {
  327.                     hr = pct->Run(pcszDebuggeeCmdLine);
  328.  
  329.                     pct->Terminate();
  330.                 }
  331.  
  332.                 pct->Release();
  333.                 pct = NULL;
  334.             }
  335.             else
  336.                 hr = E_OUTOFMEMORY;
  337.  
  338.             pirdm->Release();
  339.             pirdm = NULL;
  340.         }
  341.  
  342.         CoUninitialize();
  343.     }
  344.  
  345.     return(hr);
  346. }
  347.  
  348.  
  349. #pragma warning(disable:4100)   // "unreferenced formal parameter" warning
  350.  
  351. int __cdecl main(int argc, char *argv[])
  352. {
  353.     HRESULT hr = E_FAIL;
  354.     PCSTR pcszDebuggeeCmdLine;
  355.  
  356.     printf("Java method call tracing application.\n\n");
  357.  
  358.     pcszDebuggeeCmdLine = GetDebuggeeCmdLine(GetCommandLine());
  359.  
  360.     if (pcszDebuggeeCmdLine)
  361.         hr = RunDebugger(pcszDebuggeeCmdLine);
  362.  
  363.     return(hr);
  364. }
  365.  
  366. #pragma warning(default:4100)   // "unreferenced formal parameter" warning
  367.  
  368.  
  369. /********************************** Methods **********************************/
  370.  
  371.  
  372. CallTracer::CallTracer(void)
  373. {
  374.     m_pirdm = NULL;
  375.     m_pirp = NULL;
  376.     m_dwMsgLoopThreadID = 0;
  377. }
  378.  
  379.  
  380. CallTracer::~CallTracer(void)
  381. {
  382.     Terminate();
  383. }
  384.  
  385.  
  386. HRESULT CallTracer::Initialize(PIRemoteDebugManager pirdm)
  387. {
  388.     HRESULT hr;
  389.  
  390.     hr = pirdm->RegisterCallback(this);
  391.  
  392.     if (hr == S_OK)
  393.     {
  394.         m_pirdm = pirdm;
  395.         m_pirdm->AddRef();
  396.     }
  397.  
  398.     return(hr);
  399. }
  400.  
  401.  
  402. void CallTracer::Terminate(void)
  403. {
  404.     if (m_pirdm)
  405.     {
  406.         m_pirdm->Detach();
  407.  
  408.         m_pirdm->Release();
  409.         m_pirdm = NULL;
  410.     }
  411. }
  412.  
  413.  
  414. UINT CallTracer::RunMessageLoop(void)
  415. {
  416.     UINT uResult;
  417.     MSG msg;
  418.  
  419.     // No accelerators to load.
  420.  
  421.     // Get and dispatch messages until a WM_QUIT message is received.
  422.  
  423.     m_dwMsgLoopThreadID = GetCurrentThreadId();
  424.  
  425.     ZeroMemory(&msg, sizeof(msg));
  426.  
  427.     while (GetMessage(&msg, NULL, 0, 0))
  428.     {
  429.         TranslateMessage(&msg);
  430.         DispatchMessage(&msg);
  431.     }
  432.  
  433.     m_dwMsgLoopThreadID = 0;
  434.  
  435.     uResult = msg.wParam;
  436.  
  437.     return(uResult);
  438. }
  439.  
  440.  
  441. BOOL CallTracer::QuitMessageLoop(UINT uResult)
  442. {
  443.     return(PostThreadMessage(m_dwMsgLoopThreadID, WM_QUIT, uResult, 0));
  444. }
  445.  
  446.  
  447. HRESULT CallTracer::DebugProcess(PCSTR pcszDebuggeeCmdLine)
  448. {
  449.     HRESULT hr = E_FAIL;
  450.     STARTUPINFO si;
  451.     PROCESS_INFORMATION pi;
  452.  
  453.     ZeroMemory(&si, sizeof(si));
  454.     si.cb = sizeof(si);
  455.  
  456.     if (CreateProcess(NULL, (PSTR)pcszDebuggeeCmdLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
  457.     {
  458.         hr = m_pirdm->RequestCreateEvent(L"", pi.dwProcessId);
  459.  
  460.         if (SUCCEEDED(hr))
  461.         {
  462.             if (ResumeThread(pi.hThread) == 0xffffffff)
  463.                 hr = E_FAIL;
  464.         }
  465.  
  466.         CloseHandle(pi.hProcess);
  467.         CloseHandle(pi.hThread);
  468.  
  469.         RunMessageLoop();
  470.     }
  471.  
  472.     return(hr);
  473. }
  474.  
  475.  
  476. HRESULT CallTracer::Run(PCSTR pcszDebuggeeCmdLine)
  477. {
  478.     HRESULT hr;
  479.  
  480.     if (CreateDebugKey())
  481.     {
  482.         hr = DebugProcess(pcszDebuggeeCmdLine);
  483.  
  484.         DeleteDebugKey();
  485.     }
  486.     else
  487.         hr = LAST_WIN32_ERROR_TO_HRESULT();
  488.  
  489.     return(hr);
  490. }
  491.  
  492.  
  493. // static
  494. PCSTR CallTracer::GetFRAMEKINDString(FRAMEKIND fk)
  495. {
  496.     PCSTR pcsz;
  497.  
  498.     switch (fk)
  499.     {
  500.         case FRAME_KIND_JIT_COMPILED:
  501.             pcsz = "JIT";
  502.             break;
  503.  
  504.         case FRAME_KIND_NATIVE:
  505.             pcsz = "native";
  506.             break;
  507.  
  508.         case FRAME_KIND_COM:
  509.             pcsz = "COM";
  510.             break;
  511.  
  512.         case FRAME_KIND_INTERPRETED:
  513.             pcsz = "interpreted";
  514.             break;
  515.  
  516.         case FRAME_KIND_FAST_INTERPRETED:
  517.             pcsz = "fast interpreted";
  518.             break;
  519.  
  520.         case FRAME_KIND_INVALID:
  521.             pcsz = "INVALID";
  522.             break;
  523.  
  524.         default:
  525.             pcsz = "UNRECOGNIZED FRAMEKIND";
  526.             break;
  527.     }
  528.  
  529.     return(pcsz);
  530. }
  531.  
  532.  
  533. // static
  534. ULONG CallTracer::CountParentFrames(PIRemoteStackFrame pirsf)
  535. {
  536.     ULONG ulcFrames = 0;
  537.  
  538.     if (pirsf)
  539.     {
  540.         pirsf->AddRef();
  541.  
  542.         do
  543.         {
  544.             HRESULT hr;
  545.             PIRemoteStackFrame pirsfParent;
  546.  
  547.             hr = pirsf->GetCallingFrame(&pirsfParent);
  548.             pirsf->Release();
  549.  
  550.             if (hr == S_OK &&
  551.                 pirsfParent)
  552.             {
  553.                 ulcFrames++;
  554.                 pirsf = pirsfParent;
  555.             }
  556.             else
  557.                 break;
  558.  
  559.         } while (pirsf);
  560.     }
  561.  
  562.     return(ulcFrames);
  563. }
  564.  
  565.  
  566. // static
  567. HRESULT CallTracer::DumpContext(PIRemoteThread pirth)
  568. {
  569.     HRESULT hr;
  570.     PIRemoteThreadEx pirthex;
  571.  
  572.     hr = pirth->QueryInterface(IID_IRemoteThreadEx, (PVOID *)&pirthex);
  573.  
  574.     if (hr == S_OK)
  575.     {
  576.         ULONG ulThreadID;
  577.  
  578.         hr = pirthex->GetThreadId(&ulThreadID);
  579.  
  580.         if (hr == S_OK)
  581.         {
  582.             PIRemoteStackFrame pirsf;
  583.  
  584.             hr = pirthex->GetCurrentFrame(&pirsf);
  585.  
  586.             if (hr == S_OK)
  587.             {
  588.                 FRAMEKIND fk;
  589.  
  590.                 hr = pirsf->GetKind(&fk);
  591.  
  592.                 if (hr == S_OK)
  593.                 {
  594.                     PIRemoteContainerObject pirco;
  595.  
  596.                     hr = pirsf->GetMethodObject(&pirco);
  597.  
  598.                     if (hr == S_OK)
  599.                     {
  600.                         PIRemoteField pirf;
  601.  
  602.                         hr = pirco->GetType(&pirf);
  603.  
  604.                         if (hr == S_OK)
  605.                         {
  606.                             PIRemoteMethodField pirmf;
  607.  
  608.                             hr = pirf->QueryInterface(IID_IRemoteMethodField, (PVOID *)&pirmf);
  609.  
  610.                             if (hr == S_OK)
  611.                             {
  612.                                 POLESTR pwszMethodName;
  613.  
  614.                                 hr = pirmf->GetName(&pwszMethodName);
  615.  
  616.                                 if (hr == S_OK)
  617.                                 {
  618.                                     PIRemoteContainerField pircf;
  619.  
  620.                                     hr = pirmf->GetContainer(&pircf);
  621.  
  622.                                     if (hr == S_OK)
  623.                                     {
  624.                                         POLESTR pwszClassName;
  625.  
  626.                                         hr = pircf->GetName(&pwszClassName);
  627.  
  628.                                         if (hr == S_OK)
  629.                                         {
  630.                                             ULONG ulcDepth = CountParentFrames(pirsf);
  631.                                             ULONG uli;
  632.  
  633.                                             for (uli = 0; uli < ulcDepth; uli++)
  634.                                                 printf(" ");
  635.  
  636.                                             printf("%lxh [%s] %ls.%ls()\n",
  637.                                                    ulThreadID,
  638.                                                    GetFRAMEKINDString(fk),
  639.                                                    pwszClassName,
  640.                                                    pwszMethodName);
  641.  
  642.                                             CoTaskMemFree(pwszClassName);
  643.                                             pwszClassName = NULL;
  644.                                         }
  645.  
  646.                                         pircf->Release();
  647.                                         pircf = NULL;
  648.                                     }
  649.  
  650.                                     CoTaskMemFree(pwszMethodName);
  651.                                     pwszMethodName = NULL;
  652.                                 }
  653.  
  654.                                 pirmf->Release();
  655.                                 pirmf = NULL;
  656.                             }
  657.  
  658.                             pirf->Release();
  659.                             pirf = NULL;
  660.                         }
  661.  
  662.                         pirco->Release();
  663.                         pirco = NULL;
  664.                     }
  665.                 }
  666.  
  667.                 pirsf->Release();
  668.                 pirsf = NULL;
  669.             }
  670.         }
  671.  
  672.         pirthex->Release();
  673.         pirthex = NULL;
  674.     }
  675.  
  676.     return(hr);
  677. }
  678.  
  679.  
  680. // IUnknown methods
  681.  
  682. STDMETHODIMP CallTracer::QueryInterface(REFIID riid, PVOID *ppvObject)
  683. {
  684.     HRESULT hr = S_OK;
  685.  
  686.     if (riid == IID_IRemoteDebugManagerCallback)
  687.         *ppvObject = SAFE_CAST(PIRemoteDebugManagerCallback, this);
  688.     else if (riid == IID_IUnknown ||
  689.              riid == IID_IRemoteProcessCallback)
  690.         *ppvObject = SAFE_CAST(PIRemoteProcessCallback, this);
  691.     else
  692.     {
  693.         *ppvObject = NULL;
  694.         hr = E_NOINTERFACE;
  695.     }
  696.  
  697.     if (hr == S_OK)
  698.         AddRef();
  699.  
  700.     return(hr);
  701. }
  702.  
  703.  
  704. // IRemoteDebugManagerCallback methods
  705.  
  706. #pragma warning(disable:4100)   // "unreferenced formal parameter" warning
  707.  
  708. STDMETHODIMP CallTracer::ProcessCreateEvent(PIRemoteProcess pirpNew, PIRemoteProcess pirpParent)
  709. {
  710.     if (pirpNew->RegisterCallback(this) == S_OK)
  711.     {
  712.         m_pirp = pirpNew;
  713.         m_pirp->AddRef();
  714.  
  715.         m_pirp->TraceMethods(TRUE);
  716.     }
  717.  
  718.     DeleteDebugKey();
  719.  
  720.     return(S_FALSE);
  721. }
  722.  
  723.  
  724. // IRemoteProcessCallback methods
  725.  
  726. STDMETHODIMP CallTracer::ProcessDestroyEvent(PIRemoteThread pirth)
  727. {
  728.     m_pirp->Detach();
  729.     m_pirp->Release();
  730.     m_pirp = NULL;
  731.  
  732.     QuitMessageLoop(0);
  733.  
  734.     return(S_FALSE);
  735. }
  736.  
  737.  
  738. STDMETHODIMP CallTracer::TraceEvent(PIRemoteThread pirth)
  739. {
  740.     DumpContext(pirth);
  741.  
  742.     return(S_FALSE);
  743. }
  744.  
  745.  
  746. STDMETHODIMP CallTracer::DebugStringEvent(PIRemoteThread pirth, PCOLESTR pcwszDebugMsg)
  747. {
  748.     return(S_FALSE);
  749. }
  750.  
  751.  
  752. STDMETHODIMP CallTracer::CodeBreakpointEvent(PIRemoteThread pirth)
  753. {
  754.     return(S_FALSE);
  755. }
  756.  
  757.  
  758. STDMETHODIMP CallTracer::DataBreakpointEvent(PIRemoteThread pirth, PIRemoteObject piro)
  759. {
  760.     return(S_FALSE);
  761. }
  762.  
  763.  
  764. STDMETHODIMP CallTracer::ExceptionEvent(PIRemoteThread pirth, PIRemoteClassField pircfException, EXCEPTIONKIND exk)
  765. {
  766.     return(S_FALSE);
  767. }
  768.  
  769.  
  770. STDMETHODIMP CallTracer::StepEvent(PIRemoteThread pirth)
  771. {
  772.     return(S_FALSE);
  773. }
  774.  
  775.  
  776. STDMETHODIMP CallTracer::CanStopEvent(PIRemoteThread pirth)
  777. {
  778.     return(S_FALSE);
  779. }
  780.  
  781.  
  782. STDMETHODIMP CallTracer::BreakEvent(PIRemoteThread pirth)
  783. {
  784.     return(S_FALSE);
  785. }
  786.  
  787.  
  788. STDMETHODIMP CallTracer::ThreadCreateEvent(PIRemoteThread pirth)
  789. {
  790.     return(S_FALSE);
  791. }
  792.  
  793.  
  794. STDMETHODIMP CallTracer::ThreadDestroyEvent(PIRemoteThread pirth)
  795. {
  796.     return(S_FALSE);
  797. }
  798.  
  799.  
  800. STDMETHODIMP CallTracer::ThreadGroupCreateEvent(PIRemoteThread pirth, PIRemoteThreadGroup pirthg)
  801. {
  802.     return(S_FALSE);
  803. }
  804.  
  805.  
  806. STDMETHODIMP CallTracer::ThreadGroupDestroyEvent(PIRemoteThread pirth, PIRemoteThreadGroup pirthg)
  807. {
  808.     return(S_FALSE);
  809. }
  810.  
  811.  
  812. STDMETHODIMP CallTracer::ClassLoadEvent(PIRemoteThread pirth, PIRemoteClassField pircfClass)
  813. {
  814.     return(S_FALSE);
  815. }
  816.  
  817.  
  818. STDMETHODIMP CallTracer::ClassUnloadEvent(PIRemoteThread pirth, PIRemoteClassField pircfClass)
  819. {
  820.     return(S_FALSE);
  821. }
  822.  
  823.  
  824. STDMETHODIMP CallTracer::LoadCompleteEvent(PIRemoteThread pirth)
  825. {
  826.     return(S_FALSE);
  827. }
  828.  
  829. #pragma warning(default:4100)   // "unreferenced formal parameter" warning
  830.  
  831.