Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3806 lines
110 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) 2002 Microsoft Corporation. All rights reserved.
  3. // Copyright (c) 2002 OSR Open Systems Resources, Inc.
  4. //
  5. // DisplayDlg.cpp : implementation file
  6. //////////////////////////////////////////////////////////////////////////////
  7. #include "stdafx.h"
  8. #include <tchar.h>
  9. #include <wmistr.h>
  10. #include <initguid.h>
  11. #include <ks.h>
  12. extern "C" {
  13. #include <evntrace.h>
  14. }
  15. #include <traceprt.h>
  16. #include "TraceView.h"
  17. #include "logsession.h"
  18. #include "DockDialogBar.h"
  19. #include "DisplayDlg.h"
  20. #include "utils.h"
  21. // GLOBALS
  22. //
  23. // global event callbacks
  24. // We need these because there is no context we can
  25. // pass into the trace event callback routines, thus
  26. // we must have a unique callback for each instance
  27. // of this class. We can't use a global hash like
  28. // we are doing for the buffer callbacks, as we don't
  29. // get any information in the EVENT_TRACE struct that
  30. // allows us to lookup a value. This struct is filled
  31. // in by the call to FormatTraceEvents, and we are
  32. // supposed to treat this struct as opaque. We must
  33. // have a unique EventListHead for the call to
  34. // FormatTraceEvents, so we need these separate callbacks.
  35. // Yuck!
  36. //
  37. PEVENT_CALLBACK g_pDumpEvent[MAX_LOG_SESSIONS];
  38. //
  39. // Global hash table used in the event callbacks
  40. // to get the proper CDisplayDlg instance.
  41. //
  42. CMapWordToPtr g_displayIDToDisplayDlgHash(16);
  43. //
  44. // Global hash table used in the buffer callback
  45. // to get the proper CDisplayDlg instance.
  46. //
  47. CMapStringToPtr g_loggerNameToDisplayDlgHash(16);
  48. //
  49. // Yet another global hash table, this one is used
  50. // to prevent multiple sessions from starting using
  51. // the same format GUIDs. Format info as it turns out
  52. // is stored in a global hash table in traceprt.dll.
  53. // If multiple sessions in the same process attempt
  54. // to use the same format GUID, only one entry is
  55. // entered into the traceprt hash as expected. But,
  56. // the hash entries are removed when a session ends.
  57. // So, if multiple sessions in the same process were
  58. // use the same format GUID, as soon as one of those
  59. // sessions ended, the other sessions will lose their
  60. // hash entries.
  61. //
  62. CMapStringToPtr g_formatInfoHash(16);
  63. //
  64. // Synchronization event for GetTraceGuids, FormatTraceEvent,
  65. // and CleanupEventListHead in traceprt.dll. These are not
  66. // inherently thread safe.
  67. //
  68. HANDLE g_hGetTraceEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
  69. //
  70. // Buffer callback prototype
  71. //
  72. ULONG WINAPI BufferCallback(PEVENT_TRACE_LOGFILE Buffer);
  73. //
  74. // Memory Tracking
  75. //
  76. BOOLEAN RecoveringMemory = FALSE;
  77. LONG MaxTraceEntries = 50000;
  78. // CDisplayDlg dialog
  79. IMPLEMENT_DYNAMIC(CDisplayDlg, CDialog)
  80. CDisplayDlg::CDisplayDlg(CWnd* pParent, LONG DisplayID)
  81. : CDialog(CDisplayDlg::IDD, pParent)
  82. {
  83. ASSERT(DisplayID < MAX_LOG_SESSIONS);
  84. //
  85. // Get a handle to the main frame
  86. //
  87. m_hMainWnd = pParent->GetSafeHwnd();
  88. //
  89. // Save the ID for this DisplayDlg
  90. //
  91. m_displayID = DisplayID;
  92. //
  93. // Setup the default flags and names for the listing and summary files
  94. //
  95. m_bWriteListingFile = FALSE;
  96. m_bWriteSummaryFile = FALSE;
  97. m_listingFileName.Format(_T("Output%d.out"), m_displayID);
  98. m_summaryFileName.Format(_T("Summary%d.sum"), m_displayID);
  99. //
  100. // initialize the column names
  101. //
  102. m_columnName.Add("Name");
  103. m_columnName.Add("File Name");
  104. m_columnName.Add("Line#");
  105. m_columnName.Add("Func Name");
  106. m_columnName.Add("Process ID");
  107. m_columnName.Add("Thread ID");
  108. m_columnName.Add("CPU#");
  109. m_columnName.Add("Sequence#");
  110. m_columnName.Add("System Time");
  111. m_columnName.Add("Kernel Time");
  112. m_columnName.Add("User Time");
  113. m_columnName.Add("Indent");
  114. m_columnName.Add("Flags Name");
  115. m_columnName.Add("Level Name");
  116. m_columnName.Add("Component Name");
  117. m_columnName.Add("SubComponent Name");
  118. m_columnName.Add("Message");
  119. //
  120. // Set the initial column widths
  121. //
  122. for(LONG ii = 0; ii < MaxTraceSessionOptions; ii++) {
  123. m_columnWidth[ii] = 100;
  124. }
  125. //
  126. // Set the default display flags
  127. //
  128. m_displayFlags = TRACEOUTPUT_DISPLAY_PROVIDERNAME |
  129. TRACEOUTPUT_DISPLAY_MESSAGE |
  130. TRACEOUTPUT_DISPLAY_FILENAME |
  131. TRACEOUTPUT_DISPLAY_LINENUMBER |
  132. TRACEOUTPUT_DISPLAY_FUNCTIONNAME |
  133. TRACEOUTPUT_DISPLAY_PROCESSID |
  134. TRACEOUTPUT_DISPLAY_THREADID |
  135. TRACEOUTPUT_DISPLAY_CPUNUMBER |
  136. TRACEOUTPUT_DISPLAY_SEQNUMBER |
  137. TRACEOUTPUT_DISPLAY_SYSTEMTIME;
  138. //
  139. // setup the lookup tables for the column positions
  140. //
  141. for(LONG ii = 0; ii < MaxTraceSessionOptions; ii++) {
  142. //
  143. // This lookup table allows a retrieval of the current
  144. // position of a given column like m_retrievalArray[Flags]
  145. // will return the correct column value for the Flags
  146. // column
  147. //
  148. m_retrievalArray[ii] = ii;
  149. //
  150. // This lookup table allows correct placement of
  151. // a column being added. So, if the Flags column
  152. // needed to be inserted, then m_insertionArray[Flags]
  153. // would give the correct insertion column value
  154. //
  155. m_insertionArray[ii] = ii;
  156. }
  157. //
  158. // initialize the dock dialog bar pointer
  159. //
  160. m_pDockDialogBar = NULL;
  161. //
  162. // Show latest event trace entry
  163. //
  164. m_bShowLatest = TRUE;
  165. //
  166. // Setup the sort related compare function table
  167. // There are two functions for each column, an
  168. // ascending compare and a descending compare.
  169. //
  170. m_traceSortRoutine[ProviderName] = CompareOnName;
  171. m_traceSortRoutine[Message] = CompareOnMessage;
  172. m_traceSortRoutine[FileName] = CompareOnFileName;
  173. m_traceSortRoutine[LineNumber] = CompareOnLineNumber;
  174. m_traceSortRoutine[FunctionName] = CompareOnFunctionName;
  175. m_traceSortRoutine[ProcessId] = CompareOnProcessId;
  176. m_traceSortRoutine[ThreadId] = CompareOnThreadId;
  177. m_traceSortRoutine[CpuNumber] = CompareOnCpuNumber;
  178. m_traceSortRoutine[SeqNumber] = CompareOnSeqNumber;
  179. m_traceSortRoutine[SystemTime] = CompareOnSystemTime;
  180. m_traceSortRoutine[KernelTime] = CompareOnKernelTime;
  181. m_traceSortRoutine[UserTime] = CompareOnUserTime;
  182. m_traceSortRoutine[Indent] = CompareOnIndent;
  183. m_traceSortRoutine[FlagsName] = CompareOnFlagsName;
  184. m_traceSortRoutine[LevelName] = CompareOnLevelName;
  185. m_traceSortRoutine[ComponentName] = CompareOnComponentName;
  186. m_traceSortRoutine[SubComponentName]= CompareOnSubComponentName;
  187. m_traceReverseSortRoutine[ProviderName] = ReverseCompareOnName;
  188. m_traceReverseSortRoutine[Message] = ReverseCompareOnMessage;
  189. m_traceReverseSortRoutine[FileName] = ReverseCompareOnFileName;
  190. m_traceReverseSortRoutine[LineNumber] = ReverseCompareOnLineNumber;
  191. m_traceReverseSortRoutine[FunctionName] = ReverseCompareOnFunctionName;
  192. m_traceReverseSortRoutine[ProcessId] = ReverseCompareOnProcessId;
  193. m_traceReverseSortRoutine[ThreadId] = ReverseCompareOnThreadId;
  194. m_traceReverseSortRoutine[CpuNumber] = ReverseCompareOnCpuNumber;
  195. m_traceReverseSortRoutine[SeqNumber] = ReverseCompareOnSeqNumber;
  196. m_traceReverseSortRoutine[SystemTime] = ReverseCompareOnSystemTime;
  197. m_traceReverseSortRoutine[KernelTime] = ReverseCompareOnKernelTime;
  198. m_traceReverseSortRoutine[UserTime] = ReverseCompareOnUserTime;
  199. m_traceReverseSortRoutine[Indent] = ReverseCompareOnIndent;
  200. m_traceReverseSortRoutine[FlagsName] = ReverseCompareOnFlagsName;
  201. m_traceReverseSortRoutine[LevelName] = ReverseCompareOnLevelName;
  202. m_traceReverseSortRoutine[ComponentName] = ReverseCompareOnComponentName;
  203. m_traceReverseSortRoutine[SubComponentName]= ReverseCompareOnSubComponentName;
  204. //
  205. // Zero our column array buffer
  206. //
  207. memset(m_columnArray, 0, sizeof(int) * MaxTraceSessionOptions);
  208. //
  209. // Setup the array of event handler pointers
  210. //
  211. g_pDumpEvent[0] = DumpEvent0;
  212. g_pDumpEvent[1] = DumpEvent1;
  213. g_pDumpEvent[2] = DumpEvent2;
  214. g_pDumpEvent[3] = DumpEvent3;
  215. g_pDumpEvent[4] = DumpEvent4;
  216. g_pDumpEvent[5] = DumpEvent5;
  217. g_pDumpEvent[6] = DumpEvent6;
  218. g_pDumpEvent[7] = DumpEvent7;
  219. g_pDumpEvent[8] = DumpEvent8;
  220. g_pDumpEvent[9] = DumpEvent9;
  221. g_pDumpEvent[10] = DumpEvent10;
  222. g_pDumpEvent[11] = DumpEvent11;
  223. g_pDumpEvent[12] = DumpEvent12;
  224. g_pDumpEvent[13] = DumpEvent13;
  225. g_pDumpEvent[14] = DumpEvent14;
  226. g_pDumpEvent[15] = DumpEvent15;
  227. g_pDumpEvent[16] = DumpEvent16;
  228. g_pDumpEvent[17] = DumpEvent17;
  229. g_pDumpEvent[18] = DumpEvent18;
  230. g_pDumpEvent[19] = DumpEvent19;
  231. g_pDumpEvent[20] = DumpEvent20;
  232. g_pDumpEvent[21] = DumpEvent21;
  233. g_pDumpEvent[22] = DumpEvent22;
  234. g_pDumpEvent[23] = DumpEvent23;
  235. g_pDumpEvent[24] = DumpEvent24;
  236. g_pDumpEvent[25] = DumpEvent25;
  237. g_pDumpEvent[26] = DumpEvent26;
  238. g_pDumpEvent[27] = DumpEvent27;
  239. g_pDumpEvent[28] = DumpEvent28;
  240. g_pDumpEvent[29] = DumpEvent29;
  241. g_pDumpEvent[30] = DumpEvent30;
  242. g_pDumpEvent[31] = DumpEvent31;
  243. g_pDumpEvent[32] = DumpEvent32;
  244. g_pDumpEvent[33] = DumpEvent33;
  245. g_pDumpEvent[34] = DumpEvent34;
  246. g_pDumpEvent[35] = DumpEvent35;
  247. g_pDumpEvent[36] = DumpEvent36;
  248. g_pDumpEvent[37] = DumpEvent37;
  249. g_pDumpEvent[38] = DumpEvent38;
  250. g_pDumpEvent[39] = DumpEvent39;
  251. g_pDumpEvent[40] = DumpEvent40;
  252. g_pDumpEvent[41] = DumpEvent41;
  253. g_pDumpEvent[42] = DumpEvent42;
  254. g_pDumpEvent[43] = DumpEvent43;
  255. g_pDumpEvent[44] = DumpEvent44;
  256. g_pDumpEvent[45] = DumpEvent45;
  257. g_pDumpEvent[46] = DumpEvent46;
  258. g_pDumpEvent[47] = DumpEvent47;
  259. g_pDumpEvent[48] = DumpEvent48;
  260. g_pDumpEvent[49] = DumpEvent49;
  261. g_pDumpEvent[50] = DumpEvent50;
  262. g_pDumpEvent[51] = DumpEvent51;
  263. g_pDumpEvent[52] = DumpEvent52;
  264. g_pDumpEvent[53] = DumpEvent53;
  265. g_pDumpEvent[54] = DumpEvent54;
  266. g_pDumpEvent[55] = DumpEvent55;
  267. g_pDumpEvent[56] = DumpEvent56;
  268. g_pDumpEvent[57] = DumpEvent57;
  269. g_pDumpEvent[58] = DumpEvent58;
  270. g_pDumpEvent[59] = DumpEvent59;
  271. g_pDumpEvent[60] = DumpEvent60;
  272. g_pDumpEvent[61] = DumpEvent61;
  273. g_pDumpEvent[62] = DumpEvent62;
  274. g_pDumpEvent[63] = DumpEvent63;
  275. //
  276. // Put this session in the global hash table by display ID
  277. //
  278. g_displayIDToDisplayDlgHash.SetAt((WORD)m_displayID, this);
  279. //
  280. // Set our event callback
  281. //
  282. m_pEventCallback = g_pDumpEvent[m_displayID];
  283. //
  284. // Set our event list head to NULL
  285. //
  286. m_pEventListHead = NULL;
  287. //
  288. // initialize the group flags
  289. //
  290. m_bGroupActive = FALSE;
  291. m_bGroupInActive = FALSE;
  292. //
  293. // Initialize the end trace event
  294. //
  295. m_hEndTraceEvent = NULL;
  296. //
  297. // Initialize the last sorted column value to be
  298. // an invalid column so as to not sort, we track
  299. // the column so sorts can be reversed.
  300. //
  301. m_lastSorted = MaxTraceSessionOptions;
  302. //
  303. // Sort order for trace array, TRUE == descending, FALSE == ascending
  304. //
  305. m_bOrder = TRUE;
  306. //
  307. // Initialize handles
  308. //
  309. m_hRealTimeOutputThread = INVALID_HANDLE_VALUE;
  310. m_hRealTimeProcessingDoneEvent = NULL;
  311. m_hRealTimeProcessingStartEvent = NULL;
  312. m_hRealTimeTerminationEvent = NULL;
  313. m_hTraceEventMutex = NULL;
  314. m_hSessionArrayMutex = NULL;
  315. }
  316. CDisplayDlg::~CDisplayDlg()
  317. {
  318. ULONG exitCode = STILL_ACTIVE;
  319. CTraceViewApp *pMainWnd;
  320. //
  321. // Clear the trace log
  322. //
  323. //
  324. // Get a pointer to the app
  325. //
  326. pMainWnd = (CTraceViewApp *)AfxGetApp();
  327. //
  328. // Get our trace event array protection
  329. //
  330. WaitForSingleObject(m_hTraceEventMutex,INFINITE);
  331. //
  332. // Send all elements to be freed
  333. //
  334. int elCount;
  335. elCount = (int)m_traceArray.GetSize();
  336. while (elCount > 0 ) {
  337. delete m_traceArray.GetAt( --elCount );
  338. }
  339. //
  340. // Remove the elements from the array
  341. //
  342. m_traceArray.RemoveAll();
  343. //
  344. // Release our trace event array protection
  345. //
  346. ReleaseMutex(m_hTraceEventMutex);
  347. //
  348. // empty the list control
  349. //
  350. m_displayCtrl.DeleteAllItems();
  351. //
  352. // Reset the flag
  353. //
  354. exitCode = STILL_ACTIVE;
  355. //
  356. // Terminate the real time thread
  357. //
  358. SetEvent(m_hRealTimeTerminationEvent);
  359. //
  360. // Wait on the real time thread to exit
  361. //
  362. for(LONG ii = 0; (ii < 200) && (exitCode == STILL_ACTIVE); ii++) {
  363. if(0 == GetExitCodeThread(m_hRealTimeOutputThread, &exitCode)) {
  364. break;
  365. }
  366. Sleep(100);
  367. //
  368. // set the event again just in case
  369. //
  370. SetEvent(m_hRealTimeTerminationEvent);
  371. }
  372. //
  373. // We waited 20 seconds and the thread didn't die, so kill it
  374. //
  375. if(exitCode == STILL_ACTIVE) {
  376. TerminateThread(m_hRealTimeOutputThread, 0);
  377. }
  378. m_hRealTimeOutputThread = INVALID_HANDLE_VALUE;
  379. //
  380. // Pull this DisplayDlg out of the global hash table
  381. //
  382. g_displayIDToDisplayDlgHash.RemoveKey((WORD)m_displayID);
  383. //
  384. // The dialog bar should be deleted after this object,
  385. // but this pointer better be NULL when we are deleted
  386. //
  387. ASSERT(NULL == m_pDockDialogBar);
  388. //
  389. // Close any open handles
  390. //
  391. if(m_hRealTimeProcessingDoneEvent != NULL) {
  392. CloseHandle(m_hRealTimeProcessingDoneEvent);
  393. }
  394. if(m_hRealTimeProcessingStartEvent != NULL) {
  395. CloseHandle(m_hRealTimeProcessingStartEvent);
  396. }
  397. if(m_hRealTimeTerminationEvent != NULL) {
  398. CloseHandle(m_hRealTimeTerminationEvent);
  399. }
  400. if(m_hTraceEventMutex != NULL) {
  401. CloseHandle(m_hTraceEventMutex);
  402. }
  403. if(m_hSessionArrayMutex != NULL) {
  404. CloseHandle(m_hSessionArrayMutex);
  405. }
  406. }
  407. void CDisplayDlg::DoDataExchange(CDataExchange* pDX)
  408. {
  409. CDialog::DoDataExchange(pDX);
  410. }
  411. BEGIN_MESSAGE_MAP(CDisplayDlg, CDialog)
  412. //{{AFX_MSG_MAP(CDisplayDlg)
  413. ON_MESSAGE(WM_USER_TRACE_DONE, OnTraceDone)
  414. ON_MESSAGE(WM_USER_AUTOSIZECOLUMNS, AutoSizeColumns)
  415. ON_WM_NCCALCSIZE()
  416. ON_WM_SIZE()
  417. ON_WM_TIMER()
  418. ON_WM_INITMENUPOPUP()
  419. ON_NOTIFY(LVN_GETDISPINFO, IDC_DISPLAY_LIST, OnGetDispInfo)
  420. ON_NOTIFY(NM_CLICK, IDC_DISPLAY_LIST, OnNMClickDisplayList)
  421. ON_NOTIFY(NM_RCLICK, IDC_DISPLAY_LIST, OnNMRClickDisplayList)
  422. ON_NOTIFY(LVN_BEGINSCROLL, IDC_DISPLAY_LIST, OnLvnBeginScrollDisplayList)
  423. ON_NOTIFY(HDN_ITEMCLICK, 0, OnDoSort)
  424. ON_COMMAND(ID__AUTOSIZECOLUMNS, AutoSizeColumns)
  425. ON_COMMAND(ID__CLEARDISPLAY, OnClearDisplay)
  426. ON_COMMAND(ID__NAME, OnNameDisplayColumnCheck)
  427. ON_COMMAND(ID__MESSAGE, OnMessageDisplayColumnCheck)
  428. ON_COMMAND(ID__FILENAME, OnFileNameDisplayColumnCheck)
  429. ON_COMMAND(ID__LINENUMBER, OnLineNumberDisplayColumnCheck)
  430. ON_COMMAND(ID__FUNCTIONNAME, OnFunctionNameDisplayColumnCheck)
  431. ON_COMMAND(ID__PROCESSID, OnProcessIDDisplayColumnCheck)
  432. ON_COMMAND(ID__THREADID, OnThreadIDDisplayColumnCheck)
  433. ON_COMMAND(ID__CPUNUMBER, OnCpuNumberDisplayColumnCheck)
  434. ON_COMMAND(ID__SEQUENCENUMBER, OnSeqNumberDisplayColumnCheck)
  435. ON_COMMAND(ID__SYSTEMTIME, OnSystemTimeDisplayColumnCheck)
  436. ON_COMMAND(ID__KERNELTIME, OnKernelTimeDisplayColumnCheck)
  437. ON_COMMAND(ID__USERTIME, OnUserTimeDisplayColumnCheck)
  438. ON_COMMAND(ID__INDENT, OnIndentDisplayColumnCheck)
  439. ON_COMMAND(ID__FLAGSNAME, OnFlagsNameDisplayColumnCheck)
  440. ON_COMMAND(ID__LEVELNAME, OnLevelNameDisplayColumnCheck)
  441. ON_COMMAND(ID__COMPONENTNAME, OnComponentNameDisplayColumnCheck)
  442. ON_COMMAND(ID__SUBCOMPONENTNAME, OnSubComponentNameDisplayColumnCheck)
  443. //}}AFX_MSG_MAP
  444. END_MESSAGE_MAP()
  445. //////////////////////////////////////////////////////////////////////////
  446. // CDisplayDlg message handlers
  447. BOOL CDisplayDlg::OnInitDialog()
  448. {
  449. RECT rc;
  450. RECT parentRC;
  451. BOOL retVal;
  452. CString str;
  453. retVal = CDialog::OnInitDialog();
  454. //
  455. // Setup the protection for our trace event array
  456. //
  457. m_hTraceEventMutex = CreateMutex(NULL,TRUE,NULL);
  458. if(m_hTraceEventMutex == NULL) {
  459. DWORD error = GetLastError();
  460. str.Format(_T("CreateMutex Error %d %x"),error,error);
  461. AfxMessageBox(str);
  462. return FALSE;
  463. }
  464. ReleaseMutex(m_hTraceEventMutex);
  465. //
  466. // Setup the protection for our log session array
  467. //
  468. m_hSessionArrayMutex = CreateMutex(NULL,TRUE,NULL);
  469. if(m_hSessionArrayMutex == NULL) {
  470. DWORD error = GetLastError();
  471. str.Format(_T("CreateMutex Error %d %x"),error,error);
  472. AfxMessageBox(str);
  473. return FALSE;
  474. }
  475. ReleaseMutex(m_hSessionArrayMutex);
  476. //
  477. // Create the events for the real time thread operation
  478. //
  479. m_hRealTimeTerminationEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  480. if(NULL == m_hRealTimeTerminationEvent) {
  481. DWORD error = GetLastError();
  482. str.Format(_T("CreateEvent Error %d %x"),error,error);
  483. AfxMessageBox(str);
  484. return FALSE;
  485. }
  486. m_hRealTimeProcessingStartEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  487. if(NULL == m_hRealTimeProcessingStartEvent) {
  488. DWORD error = GetLastError();
  489. str.Format(_T("CreateEvent Error %d %x"),error,error);
  490. AfxMessageBox(str);
  491. return FALSE;
  492. }
  493. m_hRealTimeProcessingDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  494. if(NULL == m_hRealTimeProcessingDoneEvent) {
  495. DWORD error = GetLastError();
  496. str.Format(_T("CreateEvent Error %d %x"),error,error);
  497. AfxMessageBox(str);
  498. return FALSE;
  499. }
  500. //
  501. // spawn a thread to handle real time events
  502. //
  503. m_pRealTimeOutputThread = AfxBeginThread((AFX_THREADPROC)RealTimeEventThread,
  504. this,
  505. THREAD_PRIORITY_LOWEST,
  506. 0,
  507. CREATE_SUSPENDED);
  508. //
  509. // save the thread handle
  510. //
  511. DuplicateHandle(GetCurrentProcess(),
  512. m_pRealTimeOutputThread->m_hThread,
  513. GetCurrentProcess(),
  514. &m_hRealTimeOutputThread,
  515. 0,
  516. FALSE,
  517. DUPLICATE_SAME_ACCESS);
  518. //
  519. // start the thread
  520. //
  521. ResumeThread(m_pRealTimeOutputThread->m_hThread);
  522. //
  523. // get the parent dimensions
  524. //
  525. GetParent()->GetParent()->GetClientRect(&parentRC);
  526. //
  527. // get the dialog dimensions
  528. //
  529. GetWindowRect(&rc);
  530. //
  531. // adjust the list control dimensions
  532. //
  533. rc.right = parentRC.right - parentRC.left - 24;
  534. rc.bottom = rc.bottom - rc.top;
  535. rc.left = 0;
  536. rc.top = 0;
  537. //
  538. // Create the list control
  539. //
  540. if(!m_displayCtrl.Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT|LVS_OWNERDATA,
  541. rc,
  542. this,
  543. IDC_DISPLAY_LIST))
  544. {
  545. TRACE(_T("Failed to create logger list control\n"));
  546. return FALSE;
  547. }
  548. return retVal;
  549. }
  550. void CDisplayDlg::OnNcPaint()
  551. {
  552. CRect pRect;
  553. GetClientRect(&pRect);
  554. InvalidateRect(&pRect, TRUE);
  555. }
  556. VOID CDisplayDlg::SetDisplayFlags(LONG DisplayFlags)
  557. {
  558. LONG addDisplayFlags = ~m_displayFlags & DisplayFlags;
  559. LONG removeDisplayFlags = m_displayFlags & ~DisplayFlags;
  560. LONG updateDisplayFlags = m_displayFlags & DisplayFlags;
  561. BOOL bChanged = FALSE;
  562. LONG ii;
  563. LONG jj;
  564. LONG kk;
  565. LONG ll;
  566. CString str;
  567. //
  568. // Insert any new columns and remove any uneeded
  569. //
  570. for(ii = 0; ii < MaxTraceSessionOptions; ii++) {
  571. //
  572. // add the columns
  573. //
  574. if(addDisplayFlags & (1 << ii)) {
  575. //
  576. // add the column
  577. //
  578. m_displayCtrl.InsertColumn(m_insertionArray[ii],
  579. m_columnName[ii],
  580. LVCFMT_LEFT,
  581. m_columnWidth[ii]);
  582. //
  583. // update the column positions
  584. //
  585. for(kk = 0, ll = 0; kk < MaxTraceSessionOptions; kk++) {
  586. m_insertionArray[kk] = ll;
  587. if(DisplayFlags & (1 << kk)) {
  588. m_retrievalArray[ll] = kk;
  589. ll++;
  590. }
  591. }
  592. }
  593. //
  594. // remove the columns
  595. //
  596. if(removeDisplayFlags & (1 << ii)) {
  597. //
  598. // delete the column
  599. //
  600. m_displayCtrl.DeleteColumn(m_insertionArray[ii]);
  601. //
  602. // update the column positions
  603. //
  604. for(kk = 0, ll = 0; kk < MaxTraceSessionOptions; kk++) {
  605. m_insertionArray[kk] = ll;
  606. if(DisplayFlags & (1 << kk)) {
  607. m_retrievalArray[ll] = kk;
  608. ll++;
  609. }
  610. }
  611. }
  612. }
  613. //
  614. // Save the new display flags
  615. //
  616. m_displayFlags = DisplayFlags;
  617. //
  618. // Save the new column order array
  619. //
  620. memset(m_columnArray, 0, sizeof(int) * MaxTraceSessionOptions);
  621. m_displayCtrl.GetColumnOrderArray(m_columnArray);
  622. }
  623. VOID CDisplayDlg::AddSession(CLogSession *pLogSession)
  624. {
  625. ULONG flags;
  626. //
  627. // Get the array protection
  628. //
  629. WaitForSingleObject(m_hSessionArrayMutex, INFINITE);
  630. //
  631. // Add the log session to the list
  632. //
  633. m_sessionArray.Add(pLogSession);
  634. //
  635. // Is this the first session?
  636. //
  637. if(m_sessionArray.GetSize() == 1) {
  638. //
  639. // Force the columns to get updated for first time
  640. //
  641. flags = GetDisplayFlags();
  642. m_displayFlags = 0;
  643. SetDisplayFlags(flags);
  644. //
  645. // Fix the widths of the columns
  646. //
  647. AutoSizeColumns();
  648. }
  649. //
  650. // Release the array protection
  651. //
  652. ReleaseMutex(m_hSessionArrayMutex);
  653. }
  654. VOID CDisplayDlg::RemoveSession(CLogSession *pLogSession)
  655. {
  656. LONG traceDisplayFlags;
  657. PVOID pHashEntry;
  658. CString hashEntryKey;
  659. POSITION pos;
  660. //
  661. // Get the array protection
  662. //
  663. WaitForSingleObject(m_hSessionArrayMutex, INFINITE);
  664. for(LONG ii = (LONG)m_sessionArray.GetSize() - 1; ii >= 0; ii--) {
  665. if(pLogSession == (CLogSession *)m_sessionArray[ii]) {
  666. m_sessionArray.RemoveAt(ii);
  667. break;
  668. }
  669. }
  670. //
  671. // Release the array protection
  672. //
  673. ReleaseMutex(m_hSessionArrayMutex);
  674. //
  675. // Remove TMF info from our global hash, if any.
  676. //
  677. for(pos = g_formatInfoHash.GetStartPosition(); pos != NULL; )
  678. {
  679. g_formatInfoHash.GetNextAssoc(pos, hashEntryKey, pHashEntry);
  680. if(pHashEntry == (PVOID)pLogSession) {
  681. g_formatInfoHash.RemoveKey(hashEntryKey);
  682. }
  683. }
  684. //
  685. // Force an update of the displayed columns
  686. //
  687. traceDisplayFlags = GetDisplayFlags();
  688. //
  689. // Update the display flags and thus the display
  690. //
  691. SetDisplayFlags(traceDisplayFlags);
  692. }
  693. void CDisplayDlg::OnSize(UINT nType, int cx,int cy)
  694. {
  695. CRect rc;
  696. if(!IsWindow(m_displayCtrl.GetSafeHwnd()))
  697. {
  698. return;
  699. }
  700. GetParent()->GetClientRect(&rc);
  701. //
  702. // reset the size of the dialog to follow the frame
  703. //
  704. SetWindowPos(NULL,
  705. 0,
  706. 0,
  707. rc.right - rc.left,
  708. rc.bottom - rc.top,
  709. SWP_NOMOVE|SWP_SHOWWINDOW|SWP_NOZORDER);
  710. GetClientRect(&rc);
  711. //
  712. // Reset the size and position of the list control in the dialog
  713. //
  714. m_displayCtrl.MoveWindow(rc);
  715. }
  716. BOOL CDisplayDlg::PreTranslateMessage(MSG* pMsg)
  717. {
  718. if(pMsg->message == WM_KEYDOWN)
  719. {
  720. //
  721. // Ignore the escape key, otherwise
  722. // the client area grays out on escape
  723. //
  724. if(pMsg->wParam == VK_ESCAPE) {
  725. // ignore the key
  726. return TRUE;
  727. }
  728. //
  729. // For the return key, we set the list control
  730. // to always scroll to the last item
  731. //
  732. if(pMsg->wParam == VK_RETURN) {
  733. //
  734. // Start showing the latest entries in the list
  735. //
  736. m_bShowLatest = TRUE;
  737. return TRUE;
  738. }
  739. //
  740. // Fix for key accelerators, otherwise they are never
  741. // processed
  742. //
  743. if (AfxGetMainWnd()->PreTranslateMessage(pMsg)) {
  744. return TRUE;
  745. }
  746. }
  747. return CDialog::PreTranslateMessage(pMsg);
  748. }
  749. void CDisplayDlg::OnNMClickDisplayList(NMHDR *pNMHDR, LRESULT *pResult)
  750. {
  751. //
  752. // Stop automatic scrolling to latest list control entry
  753. // Hit enter to start auto scrolling again
  754. //
  755. m_bShowLatest = FALSE;
  756. *pResult = 0;
  757. }
  758. void CDisplayDlg::OnNMRClickDisplayList(NMHDR *pNMHDR, LRESULT *pResult)
  759. {
  760. CString str;
  761. DWORD position;
  762. int listIndex;
  763. LVHITTESTINFO lvhti;
  764. //
  765. // Get the position of the mouse when this
  766. // message posted
  767. //
  768. position = ::GetMessagePos();
  769. //
  770. // Get the position in an easy to use format
  771. //
  772. CPoint point((int) LOWORD (position), (int)HIWORD(position));
  773. //
  774. // Convert to screen coordinates
  775. //
  776. CPoint screenPoint(point);
  777. //
  778. // If there are entries in the event array, then pop-up
  779. // the menu to allow autosize columns and clear display
  780. //
  781. CMenu menu;
  782. menu.LoadMenu(IDR_TRACE_SESSION_POPUP_MENU);
  783. CMenu* pPopup = menu.GetSubMenu(0);
  784. ASSERT(pPopup != NULL);
  785. pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, screenPoint.x, screenPoint.y, this);
  786. *pResult = 0;
  787. }
  788. void CDisplayDlg::OnLvnBeginScrollDisplayList(NMHDR *pNMHDR, LRESULT *pResult)
  789. {
  790. //
  791. // This feature requires Internet Explorer 5.5 or greater.
  792. // The symbol _WIN32_IE must be >= 0x0560.
  793. //
  794. LPNMLVSCROLL pStateChanged = reinterpret_cast<LPNMLVSCROLL>(pNMHDR);
  795. //
  796. // If someone grabs the scroll handle,
  797. // stop the list control from scrolling
  798. //
  799. m_bShowLatest = FALSE;
  800. *pResult = 0;
  801. }
  802. void CDisplayDlg::OnGetDispInfo(NMHDR *pNMHDR, LRESULT *pResult)
  803. {
  804. CString str;
  805. LV_DISPINFO *pDispInfo = (LV_DISPINFO*)pNMHDR;
  806. LV_ITEM *pItem;
  807. int index;
  808. int item = 0;
  809. int subItem = 0;
  810. LPWSTR outStr;
  811. CString tempString;
  812. CString tempString2;
  813. CTraceMessage *pTraceMessage;
  814. if(pDispInfo == NULL) {
  815. return;
  816. }
  817. //
  818. // list control cell information
  819. //
  820. pItem = &pDispInfo->item;
  821. //
  822. // Get the cell item and subitem locators
  823. //
  824. item = pItem->iItem;
  825. subItem = pItem->iSubItem;
  826. //
  827. // Get the string pointer we need to fill in
  828. //
  829. outStr = pItem->pszText;
  830. //
  831. // Check that this is a text buffer request
  832. //
  833. if(!(pItem->mask & LVIF_TEXT)) {
  834. return;
  835. }
  836. //
  837. // Make sure the text requested is text we have
  838. //
  839. if((m_traceArray.GetSize() == 0) ||
  840. (item >= m_traceArray.GetSize()) ||
  841. (item < 0)) {
  842. _tcscpy(outStr,_T(""));
  843. return;
  844. }
  845. //
  846. // Get our trace event array protection
  847. //
  848. WaitForSingleObject(m_hTraceEventMutex,INFINITE);
  849. //
  850. // Get the message from the array
  851. //
  852. pTraceMessage = m_traceArray[item];
  853. //
  854. // Release our trace event array protection
  855. //
  856. ReleaseMutex(m_hTraceEventMutex);
  857. if(NULL == pTraceMessage) {
  858. _tcscpy(outStr,_T(""));
  859. return;
  860. }
  861. CTime kernelTime(pTraceMessage->m_KernelTime);
  862. CTime userTime(pTraceMessage->m_UserTime);
  863. // if( (pTraceMessage->m_UserTime.dwLowDateTime != 0) && (pTraceMessage->m_UserTime.dwHighDateTime != 0) ) {
  864. // CTime userTime1(pTraceMessage->m_UserTime);
  865. // userTime = userTime1;
  866. // }
  867. //
  868. // Copy the proper portion of the message to the out string
  869. //
  870. switch(m_retrievalArray[subItem]) {
  871. case ProviderName:
  872. _tcscpy(outStr, pTraceMessage->m_GuidName);
  873. break;
  874. case Message: {
  875. _tcsncpy(outStr, pTraceMessage->m_Message, pItem->cchTextMax-4);
  876. outStr[pItem->cchTextMax-4] = 0x00;
  877. if( (pItem->cchTextMax-4) <=
  878. (int)_tcslen(pTraceMessage->m_Message) ) {
  879. _tcscat(outStr, _T("..."));
  880. }
  881. break;
  882. }
  883. case FileName:
  884. //
  885. // Filename and line number are combined in a single string
  886. // so we have to parse them out. The format is generally
  887. // something like this:
  888. //
  889. // myfile_c389
  890. //
  891. // Where myfile.c is where the event occurred and on line 389.
  892. // This field can also signify a type of message, as in the
  893. // Kernel Logger case, for example, so if there is no underscore
  894. // we assume this is the case and we just print out the whole
  895. // field.
  896. //
  897. if(pTraceMessage->m_GuidTypeName.Find('_') > 0) {
  898. tempString = (LPCTSTR)pTraceMessage->m_GuidTypeName.Left(pTraceMessage->m_GuidTypeName.Find('_'));
  899. if(tempString.IsEmpty()) {
  900. //
  901. // Copy the string back to the list control
  902. //
  903. _tcscpy(outStr, tempString);
  904. return;
  905. }
  906. //
  907. // Get the extension
  908. //
  909. tempString += ".";
  910. tempString2 = (LPCTSTR)pTraceMessage->m_GuidTypeName.Right(pTraceMessage->m_GuidTypeName.GetLength() - pTraceMessage->m_GuidTypeName.Find('_') - 1);
  911. tempString += (LPCTSTR)tempString2.Left(tempString2.FindOneOf(_T("0123456789")));
  912. } else {
  913. tempString = (LPCTSTR)pTraceMessage->m_GuidTypeName;
  914. }
  915. _tcscpy(outStr, tempString);
  916. break;
  917. case LineNumber:
  918. //
  919. // Filename and line number are combined in a single string
  920. // so we have to parse them out. The format is generally
  921. // something like this:
  922. //
  923. // myfile_c389
  924. //
  925. // Where myfile.c is where the event occurred and on line 389.
  926. // This field can also signify a type of message, as in the
  927. // Kernel Logger case, for example, so if there is no underscore
  928. // we assume this is the case and we print nothing for the line
  929. // number.
  930. //
  931. if(pTraceMessage->m_GuidTypeName.Find('_') > 0) {
  932. tempString2 =
  933. pTraceMessage->m_GuidTypeName.Right(pTraceMessage->m_GuidTypeName.GetLength() -
  934. pTraceMessage->m_GuidTypeName.Find('_') - 1);
  935. tempString2 =
  936. tempString2.Right(tempString2.GetLength() -
  937. tempString2.FindOneOf(_T("0123456789")));
  938. } else {
  939. tempString2.Empty();
  940. }
  941. _tcscpy(outStr, tempString2);
  942. break;
  943. case FunctionName:
  944. _tcscpy(outStr, pTraceMessage->m_FunctionName);
  945. break;
  946. case ProcessId:
  947. if((LONG)pTraceMessage->m_ProcessId >= 0) {
  948. tempString.Format(_T("%d"), pTraceMessage->m_ProcessId);
  949. } else {
  950. tempString.Empty();
  951. }
  952. _tcscpy(outStr, tempString);
  953. break;
  954. case ThreadId:
  955. if((LONG)pTraceMessage->m_ThreadId >= 0) {
  956. tempString.Format(_T("%d"), pTraceMessage->m_ThreadId);
  957. } else {
  958. tempString.Empty();
  959. }
  960. _tcscpy(outStr, tempString);
  961. break;
  962. case CpuNumber:
  963. if((LONG)pTraceMessage->m_CpuNumber >= 0) {
  964. tempString.Format(_T("%d"), pTraceMessage->m_CpuNumber);
  965. } else {
  966. tempString.Empty();
  967. }
  968. _tcscpy(outStr, tempString);
  969. break;
  970. case SeqNumber:
  971. if((LONG)pTraceMessage->m_SequenceNum >= 0) {
  972. tempString.Format(_T("%d"), pTraceMessage->m_SequenceNum);
  973. } else {
  974. tempString.Empty();
  975. }
  976. _tcscpy(outStr, tempString);
  977. break;
  978. case SystemTime:
  979. tempString.Format(_T("%02d\\%02d\\%4d-%02d:%02d:%02d:%02d"),
  980. pTraceMessage->m_SystemTime.wMonth,
  981. pTraceMessage->m_SystemTime.wDay,
  982. pTraceMessage->m_SystemTime.wYear,
  983. pTraceMessage->m_SystemTime.wHour,
  984. pTraceMessage->m_SystemTime.wMinute,
  985. pTraceMessage->m_SystemTime.wSecond,
  986. pTraceMessage->m_SystemTime.wMilliseconds);
  987. _tcscpy(outStr, tempString);
  988. break;
  989. case KernelTime:
  990. //
  991. // We have to do an ugly conversion here. If the year is 1969,
  992. // then the time was blank.
  993. //
  994. if( (kernelTime == -1) || (kernelTime.GetYear() == 1969)) {
  995. tempString.Format(_T(""));
  996. } else {
  997. tempString.Format(_T("%s-%02d:%02d:%02d"),
  998. kernelTime.Format("%m\\%d\\%Y"),
  999. kernelTime.GetHour() + 5,
  1000. kernelTime.GetMinute(),
  1001. kernelTime.GetSecond());
  1002. }
  1003. _tcscpy(outStr, tempString);
  1004. break;
  1005. case UserTime:
  1006. //
  1007. // We have to do an ugly conversion here. If the year is 1969 or
  1008. // 1970 then the time was blank.
  1009. //
  1010. if( (userTime == -1) || (userTime.GetYear() == 1969) || (userTime.GetYear() == 1970) ) {
  1011. tempString.Format(_T(""));
  1012. } else {
  1013. tempString.Format(_T("%s-%02d:%02d:%02d"),
  1014. userTime.Format("%m\\%d\\%Y"),
  1015. userTime.GetHour() + 5,
  1016. userTime.GetMinute(),
  1017. userTime.GetSecond());
  1018. }
  1019. _tcscpy(outStr, tempString);
  1020. break;
  1021. case Indent:
  1022. tempString.Format(_T("%d"), pTraceMessage->m_Indent);
  1023. _tcscpy(outStr, tempString);
  1024. break;
  1025. case FlagsName:
  1026. _tcscpy(outStr, pTraceMessage->m_FlagsName);
  1027. break;
  1028. case LevelName:
  1029. _tcscpy(outStr, pTraceMessage->m_LevelName);
  1030. break;
  1031. case ComponentName:
  1032. _tcscpy(outStr, pTraceMessage->m_ComponentName);
  1033. break;
  1034. case SubComponentName:
  1035. _tcscpy(outStr, pTraceMessage->m_SubComponentName);
  1036. break;
  1037. default:
  1038. //
  1039. // Default to empty string
  1040. //
  1041. _tcscpy(outStr,_T(""));
  1042. break;
  1043. }
  1044. }
  1045. void CDisplayDlg::OnClearDisplay()
  1046. {
  1047. CTraceMessage *pTraceMessage;
  1048. CTraceViewApp *pMainWnd;
  1049. //
  1050. // Clear the trace log
  1051. //
  1052. //
  1053. // Get a pointer to the main frame
  1054. //
  1055. pMainWnd = (CTraceViewApp *)AfxGetApp();
  1056. //
  1057. // Get our trace event array protection
  1058. //
  1059. WaitForSingleObject(m_hTraceEventMutex,INFINITE);
  1060. int elCount;
  1061. elCount = (int)m_traceArray.GetSize();
  1062. while (elCount > 0 ) {
  1063. delete m_traceArray.GetAt( --elCount );
  1064. }
  1065. //
  1066. // Remove the elements from the array
  1067. //
  1068. m_traceArray.RemoveAll();
  1069. //
  1070. // Release our trace event array protection
  1071. //
  1072. ReleaseMutex(m_hTraceEventMutex);
  1073. //
  1074. // Clear the list control
  1075. //
  1076. m_displayCtrl.DeleteAllItems();
  1077. //
  1078. // Reset the output to always show latest
  1079. //
  1080. m_bShowLatest = TRUE;
  1081. }
  1082. void CDisplayDlg::AutoSizeColumns()
  1083. {
  1084. LONG colWidth1;
  1085. LONG colWidth2;
  1086. LONG columnCount;
  1087. CHeaderCtrl *pHeaderCtrl;
  1088. //
  1089. // Get the list control header
  1090. //
  1091. pHeaderCtrl = m_displayCtrl.GetHeaderCtrl();
  1092. if (pHeaderCtrl != NULL)
  1093. {
  1094. //
  1095. // Get number of columns
  1096. //
  1097. columnCount = pHeaderCtrl->GetItemCount();
  1098. for(LONG ii = 0; ii < (columnCount - 1); ii++) {
  1099. //
  1100. // Get the max width of the column entries
  1101. //
  1102. m_displayCtrl.SetColumnWidth(ii, LVSCW_AUTOSIZE);
  1103. colWidth1 = m_displayCtrl.GetColumnWidth(ii);
  1104. //
  1105. // Get the width of the column header
  1106. //
  1107. m_displayCtrl.SetColumnWidth(ii, LVSCW_AUTOSIZE_USEHEADER);
  1108. colWidth2 = m_displayCtrl.GetColumnWidth(ii);
  1109. //
  1110. // Set the column width to the max of the two
  1111. // Special case the first column?? Seems to be off
  1112. // a couple of pixels
  1113. //
  1114. if(0 == ii) {
  1115. m_displayCtrl.SetColumnWidth(ii, max(colWidth1,colWidth2) + 2);
  1116. } else {
  1117. m_displayCtrl.SetColumnWidth(ii, max(colWidth1,colWidth2));
  1118. }
  1119. //
  1120. // Save the column width
  1121. //
  1122. m_columnWidth[m_retrievalArray[ii]] = m_displayCtrl.GetColumnWidth(ii);
  1123. }
  1124. //
  1125. // Special case the message column. The last column is usually
  1126. // limited to only be as wide as needed. But, if the message
  1127. // column is the last column, then use up all available space.
  1128. //
  1129. if(m_retrievalArray[columnCount - 1] != Message) {
  1130. //
  1131. // Get the column width of the last column
  1132. //
  1133. colWidth2 = m_displayCtrl.GetColumnWidth(columnCount - 1);
  1134. //
  1135. // Get the max width of the column entries for the last column
  1136. //
  1137. m_displayCtrl.SetColumnWidth(columnCount - 1, LVSCW_AUTOSIZE);
  1138. colWidth1 = m_displayCtrl.GetColumnWidth(columnCount - 1);
  1139. //
  1140. // Set the last column width to the max of the two
  1141. //
  1142. m_displayCtrl.SetColumnWidth(columnCount - 1, max(colWidth1,colWidth2));
  1143. //
  1144. // Save the column width
  1145. //
  1146. m_columnWidth[m_retrievalArray[columnCount - 1]] = m_displayCtrl.GetColumnWidth(columnCount - 1);
  1147. } else {
  1148. //
  1149. // Set the width of the column to use the remaining space
  1150. //
  1151. m_displayCtrl.SetColumnWidth(columnCount - 1,
  1152. LVSCW_AUTOSIZE_USEHEADER);
  1153. //
  1154. // Save the column width
  1155. //
  1156. m_columnWidth[m_retrievalArray[columnCount - 1]] =
  1157. m_displayCtrl.GetColumnWidth(columnCount - 1);
  1158. }
  1159. }
  1160. }
  1161. void CDisplayDlg::OnNameDisplayColumnCheck()
  1162. {
  1163. LONG flags;
  1164. //
  1165. // Get the current flag values
  1166. //
  1167. flags = GetDisplayFlags();
  1168. //
  1169. // Toggle the Name flag value
  1170. //
  1171. if(flags & TRACEOUTPUT_DISPLAY_PROVIDERNAME) {
  1172. flags &= ~TRACEOUTPUT_DISPLAY_PROVIDERNAME;
  1173. } else {
  1174. flags |= TRACEOUTPUT_DISPLAY_PROVIDERNAME;
  1175. }
  1176. //
  1177. // Update the flag values and thus the display
  1178. //
  1179. SetDisplayFlags(flags);
  1180. }
  1181. void CDisplayDlg::OnMessageDisplayColumnCheck()
  1182. {
  1183. LONG flags;
  1184. //
  1185. // Get the current flag values
  1186. //
  1187. flags = GetDisplayFlags();
  1188. //
  1189. // Toggle the Message flag value
  1190. //
  1191. if(flags & TRACEOUTPUT_DISPLAY_MESSAGE) {
  1192. flags &= ~TRACEOUTPUT_DISPLAY_MESSAGE;
  1193. } else {
  1194. flags |= TRACEOUTPUT_DISPLAY_MESSAGE;
  1195. }
  1196. //
  1197. // Update the flag values and thus the display
  1198. //
  1199. SetDisplayFlags(flags);
  1200. }
  1201. void CDisplayDlg::OnFileNameDisplayColumnCheck()
  1202. {
  1203. LONG flags;
  1204. //
  1205. // Get the current flag values
  1206. //
  1207. flags = GetDisplayFlags();
  1208. //
  1209. // Toggle the FileName flag value
  1210. //
  1211. if(flags & TRACEOUTPUT_DISPLAY_FILENAME) {
  1212. flags &= ~TRACEOUTPUT_DISPLAY_FILENAME;
  1213. } else {
  1214. flags |= TRACEOUTPUT_DISPLAY_FILENAME;
  1215. }
  1216. //
  1217. // Update the flag values and thus the display
  1218. //
  1219. SetDisplayFlags(flags);
  1220. }
  1221. void CDisplayDlg::OnLineNumberDisplayColumnCheck()
  1222. {
  1223. LONG flags;
  1224. //
  1225. // Get the current flag values
  1226. //
  1227. flags = GetDisplayFlags();
  1228. //
  1229. // Toggle the LineNumber flag value
  1230. //
  1231. if(flags & TRACEOUTPUT_DISPLAY_LINENUMBER) {
  1232. flags &= ~TRACEOUTPUT_DISPLAY_LINENUMBER;
  1233. } else {
  1234. flags |= TRACEOUTPUT_DISPLAY_LINENUMBER;
  1235. }
  1236. //
  1237. // Update the flag values and thus the display
  1238. //
  1239. SetDisplayFlags(flags);
  1240. }
  1241. void CDisplayDlg::OnFunctionNameDisplayColumnCheck()
  1242. {
  1243. LONG flags;
  1244. //
  1245. // Get the current flag values
  1246. //
  1247. flags = GetDisplayFlags();
  1248. //
  1249. // Toggle the FunctionName flag value
  1250. //
  1251. if(flags & TRACEOUTPUT_DISPLAY_FUNCTIONNAME) {
  1252. flags &= ~TRACEOUTPUT_DISPLAY_FUNCTIONNAME;
  1253. } else {
  1254. flags |= TRACEOUTPUT_DISPLAY_FUNCTIONNAME;
  1255. }
  1256. //
  1257. // Update the flag values and thus the display
  1258. //
  1259. SetDisplayFlags(flags);
  1260. }
  1261. void CDisplayDlg::OnProcessIDDisplayColumnCheck()
  1262. {
  1263. LONG flags;
  1264. //
  1265. // Get the current flag values
  1266. //
  1267. flags = GetDisplayFlags();
  1268. //
  1269. // Toggle the ProcessID flag value
  1270. //
  1271. if(flags & TRACEOUTPUT_DISPLAY_PROCESSID) {
  1272. flags &= ~TRACEOUTPUT_DISPLAY_PROCESSID;
  1273. } else {
  1274. flags |= TRACEOUTPUT_DISPLAY_PROCESSID;
  1275. }
  1276. //
  1277. // Update the flag values and thus the display
  1278. //
  1279. SetDisplayFlags(flags);
  1280. }
  1281. void CDisplayDlg::OnThreadIDDisplayColumnCheck()
  1282. {
  1283. LONG flags;
  1284. //
  1285. // Get the current flag values
  1286. //
  1287. flags = GetDisplayFlags();
  1288. //
  1289. // Toggle the Thread ID flag value
  1290. //
  1291. if(flags & TRACEOUTPUT_DISPLAY_THREADID) {
  1292. flags &= ~TRACEOUTPUT_DISPLAY_THREADID;
  1293. } else {
  1294. flags |= TRACEOUTPUT_DISPLAY_THREADID;
  1295. }
  1296. //
  1297. // Update the flag values and thus the display
  1298. //
  1299. SetDisplayFlags(flags);
  1300. }
  1301. void CDisplayDlg::OnCpuNumberDisplayColumnCheck()
  1302. {
  1303. LONG flags;
  1304. //
  1305. // Get the current flag values
  1306. //
  1307. flags = GetDisplayFlags();
  1308. //
  1309. // Toggle the CPU Number flag value
  1310. //
  1311. if(flags & TRACEOUTPUT_DISPLAY_CPUNUMBER) {
  1312. flags &= ~TRACEOUTPUT_DISPLAY_CPUNUMBER;
  1313. } else {
  1314. flags |= TRACEOUTPUT_DISPLAY_CPUNUMBER;
  1315. }
  1316. //
  1317. // Update the flag values and thus the display
  1318. //
  1319. SetDisplayFlags(flags);
  1320. }
  1321. void CDisplayDlg::OnSeqNumberDisplayColumnCheck()
  1322. {
  1323. LONG flags;
  1324. //
  1325. // Get the current flag values
  1326. //
  1327. flags = GetDisplayFlags();
  1328. //
  1329. // Toggle the Sequence Number flag value
  1330. //
  1331. if(flags & TRACEOUTPUT_DISPLAY_SEQNUMBER) {
  1332. flags &= ~TRACEOUTPUT_DISPLAY_SEQNUMBER;
  1333. } else {
  1334. flags |= TRACEOUTPUT_DISPLAY_SEQNUMBER;
  1335. }
  1336. //
  1337. // Update the flag values and thus the display
  1338. //
  1339. SetDisplayFlags(flags);
  1340. }
  1341. void CDisplayDlg::OnSystemTimeDisplayColumnCheck()
  1342. {
  1343. LONG flags;
  1344. //
  1345. // Get the current flag values
  1346. //
  1347. flags = GetDisplayFlags();
  1348. //
  1349. // Toggle the SystemTime flag value
  1350. //
  1351. if(flags & TRACEOUTPUT_DISPLAY_SYSTEMTIME) {
  1352. flags &= ~TRACEOUTPUT_DISPLAY_SYSTEMTIME;
  1353. } else {
  1354. flags |= TRACEOUTPUT_DISPLAY_SYSTEMTIME;
  1355. }
  1356. //
  1357. // Update the flag values and thus the display
  1358. //
  1359. SetDisplayFlags(flags);
  1360. }
  1361. void CDisplayDlg::OnKernelTimeDisplayColumnCheck()
  1362. {
  1363. LONG flags;
  1364. //
  1365. // Get the current flag values
  1366. //
  1367. flags = GetDisplayFlags();
  1368. //
  1369. // Toggle the KernelTime flag value
  1370. //
  1371. if(flags & TRACEOUTPUT_DISPLAY_KERNELTIME) {
  1372. flags &= ~TRACEOUTPUT_DISPLAY_KERNELTIME;
  1373. } else {
  1374. flags |= TRACEOUTPUT_DISPLAY_KERNELTIME;
  1375. }
  1376. //
  1377. // Update the flag values and thus the display
  1378. //
  1379. SetDisplayFlags(flags);
  1380. }
  1381. void CDisplayDlg::OnUserTimeDisplayColumnCheck()
  1382. {
  1383. LONG flags;
  1384. //
  1385. // Get the current flag values
  1386. //
  1387. flags = GetDisplayFlags();
  1388. //
  1389. // Toggle the UserTime flag value
  1390. //
  1391. if(flags & TRACEOUTPUT_DISPLAY_USERTIME) {
  1392. flags &= ~TRACEOUTPUT_DISPLAY_USERTIME;
  1393. } else {
  1394. flags |= TRACEOUTPUT_DISPLAY_USERTIME;
  1395. }
  1396. //
  1397. // Update the flag values and thus the display
  1398. //
  1399. SetDisplayFlags(flags);
  1400. }
  1401. void CDisplayDlg::OnIndentDisplayColumnCheck()
  1402. {
  1403. LONG flags;
  1404. //
  1405. // Get the current flag values
  1406. //
  1407. flags = GetDisplayFlags();
  1408. //
  1409. // Toggle the Indent flag value
  1410. //
  1411. if(flags & TRACEOUTPUT_DISPLAY_INDENT) {
  1412. flags &= ~TRACEOUTPUT_DISPLAY_INDENT;
  1413. } else {
  1414. flags |= TRACEOUTPUT_DISPLAY_INDENT;
  1415. }
  1416. //
  1417. // Update the flag values and thus the display
  1418. //
  1419. SetDisplayFlags(flags);
  1420. }
  1421. void CDisplayDlg::OnFlagsNameDisplayColumnCheck()
  1422. {
  1423. LONG flags;
  1424. //
  1425. // Get the current flag values
  1426. //
  1427. flags = GetDisplayFlags();
  1428. //
  1429. // Toggle the FlagsName flag value
  1430. //
  1431. if(flags & TRACEOUTPUT_DISPLAY_FLAGSNAME) {
  1432. flags &= ~TRACEOUTPUT_DISPLAY_FLAGSNAME;
  1433. } else {
  1434. flags |= TRACEOUTPUT_DISPLAY_FLAGSNAME;
  1435. }
  1436. //
  1437. // Update the flag values and thus the display
  1438. //
  1439. SetDisplayFlags(flags);
  1440. }
  1441. void CDisplayDlg::OnLevelNameDisplayColumnCheck()
  1442. {
  1443. LONG flags;
  1444. //
  1445. // Get the current flag values
  1446. //
  1447. flags = GetDisplayFlags();
  1448. //
  1449. // Toggle the LevelName flag value
  1450. //
  1451. if(flags & TRACEOUTPUT_DISPLAY_LEVELNAME) {
  1452. flags &= ~TRACEOUTPUT_DISPLAY_LEVELNAME;
  1453. } else {
  1454. flags |= TRACEOUTPUT_DISPLAY_LEVELNAME;
  1455. }
  1456. //
  1457. // Update the flag values and thus the display
  1458. //
  1459. SetDisplayFlags(flags);
  1460. }
  1461. void CDisplayDlg::OnComponentNameDisplayColumnCheck()
  1462. {
  1463. LONG flags;
  1464. //
  1465. // Get the current flag values
  1466. //
  1467. flags = GetDisplayFlags();
  1468. //
  1469. // Toggle the ComponentName flag value
  1470. //
  1471. if(flags & TRACEOUTPUT_DISPLAY_COMPNAME) {
  1472. flags &= ~TRACEOUTPUT_DISPLAY_COMPNAME;
  1473. } else {
  1474. flags |= TRACEOUTPUT_DISPLAY_COMPNAME;
  1475. }
  1476. //
  1477. // Update the flag values and thus the display
  1478. //
  1479. SetDisplayFlags(flags);
  1480. }
  1481. void CDisplayDlg::OnSubComponentNameDisplayColumnCheck()
  1482. {
  1483. LONG flags;
  1484. //
  1485. // Get the current flag values
  1486. //
  1487. flags = GetDisplayFlags();
  1488. //
  1489. // Toggle the SubComponentName flag value
  1490. //
  1491. if(flags & TRACEOUTPUT_DISPLAY_SUBCOMPNAME) {
  1492. flags &= ~TRACEOUTPUT_DISPLAY_SUBCOMPNAME;
  1493. } else {
  1494. flags |= TRACEOUTPUT_DISPLAY_SUBCOMPNAME;
  1495. }
  1496. //
  1497. // Update the flag values and thus the display
  1498. //
  1499. SetDisplayFlags(flags);
  1500. }
  1501. BOOL CDisplayDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
  1502. {
  1503. HD_NOTIFY *pHDN = (HD_NOTIFY*)lParam;
  1504. LPNMHDR pNH = (LPNMHDR) lParam;
  1505. //
  1506. // wParam is zero for Header ctrl
  1507. //
  1508. if(wParam == 0 && pNH->code == NM_RCLICK) {
  1509. //
  1510. // Right button was clicked on header
  1511. //
  1512. //
  1513. // Determine where the right click occurred and pop-up
  1514. // a menu there
  1515. //
  1516. CPoint pt(GetMessagePos());
  1517. CHeaderCtrl *pHeader = m_displayCtrl.GetHeaderCtrl();
  1518. pHeader->ScreenToClient(&pt);
  1519. CPoint screenPoint(GetMessagePos());
  1520. CMenu menu;
  1521. menu.LoadMenu(IDR_TRACE_DISPLAY_OPTION_POPUP_MENU);
  1522. CMenu* pPopup = menu.GetSubMenu(0);
  1523. ASSERT(pPopup != NULL);
  1524. pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  1525. screenPoint.x,
  1526. screenPoint.y,
  1527. this);
  1528. return TRUE;
  1529. } else if(wParam == 0 && pNH->code == NM_RELEASEDCAPTURE) {
  1530. //
  1531. // Column header was pressed and now released
  1532. //
  1533. POINT Point;
  1534. CHeaderCtrl *pHeader = m_displayCtrl.GetHeaderCtrl();
  1535. int columnArray[MaxTraceSessionOptions];
  1536. GetCursorPos (&Point);
  1537. ScreenToClient(&Point);
  1538. HDHITTESTINFO HitTest;
  1539. //
  1540. //Offset of right scrolling
  1541. //
  1542. HitTest.pt.x = Point.x + GetScrollPos(SB_HORZ);
  1543. HitTest.pt.y = Point.y;
  1544. //
  1545. //Send the hit test message
  1546. //
  1547. pHeader->SendMessage(HDM_HITTEST,0,(LPARAM)&HitTest);
  1548. //
  1549. // We check here if the column order changed. If so, then
  1550. // we don't want to cause a sort of the column items, the user
  1551. // had to press the column header to drag the column around.
  1552. //
  1553. memset(columnArray, 0, sizeof(int) * MaxTraceSessionOptions);
  1554. m_displayCtrl.GetColumnOrderArray(columnArray);
  1555. if(memcmp(m_columnArray, columnArray, sizeof(int) * MaxTraceSessionOptions)) {
  1556. //
  1557. // Column order changed, save the new order
  1558. //
  1559. memcpy(m_columnArray, columnArray, sizeof(int) * MaxTraceSessionOptions);
  1560. //
  1561. // Now call the default handler and return
  1562. //
  1563. return CDialog::OnNotify(wParam, lParam, pResult);
  1564. }
  1565. if(HitTest.iItem >= 0) {
  1566. //
  1567. // Now check for column resize
  1568. //
  1569. if(m_displayCtrl.GetColumnWidth(HitTest.iItem) != m_columnWidth[m_retrievalArray[HitTest.iItem]]) {
  1570. //
  1571. // Save off the new column width and don't sort the column
  1572. //
  1573. m_columnWidth[m_retrievalArray[HitTest.iItem]] = m_displayCtrl.GetColumnWidth(HitTest.iItem);
  1574. //
  1575. // Now call the default handler and return
  1576. //
  1577. return CDialog::OnNotify(wParam, lParam, pResult);
  1578. }
  1579. // //
  1580. // // Sort the table by this column's data
  1581. // //
  1582. // SortTable(HitTest.iItem);
  1583. //
  1584. // //
  1585. // // Force a redraw of the data
  1586. // //
  1587. // m_displayCtrl.RedrawItems(m_displayCtrl.GetTopIndex(),
  1588. // m_displayCtrl.GetTopIndex() + m_displayCtrl.GetCountPerPage());
  1589. //
  1590. // m_displayCtrl.UpdateWindow();
  1591. }
  1592. }
  1593. //
  1594. // Now call the default handler and return
  1595. //
  1596. return CDialog::OnNotify(wParam, lParam, pResult);
  1597. }
  1598. void CDisplayDlg::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
  1599. {
  1600. //
  1601. // Call the default handler
  1602. //
  1603. CDialog::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
  1604. //
  1605. // As CDisplayDlg corresponds to a non-CFrameWnd window, OF COURSE
  1606. // you have to overload this handler and explicitly set the check
  1607. // state of each item in the popup menu. It is utterly,
  1608. // absolutely, and intuitively obvious as to why this is
  1609. // necessary, thus it won't be explained here
  1610. //
  1611. //
  1612. // Trace session pop-up menu
  1613. //
  1614. //
  1615. // Disable the clear display option, if there are no
  1616. // traces displayed
  1617. //
  1618. if(m_traceArray.GetSize() == 0) {
  1619. pPopupMenu->EnableMenuItem(ID__CLEARDISPLAY, MF_GRAYED);
  1620. }
  1621. //
  1622. // Trace display option pop-up menu
  1623. //
  1624. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_PROVIDERNAME) {
  1625. pPopupMenu->CheckMenuItem(ID__NAME, MF_CHECKED);
  1626. }
  1627. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_MESSAGE) {
  1628. pPopupMenu->CheckMenuItem(ID__MESSAGE, MF_CHECKED);
  1629. }
  1630. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_FILENAME) {
  1631. pPopupMenu->CheckMenuItem(ID__FILENAME, MF_CHECKED);
  1632. }
  1633. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_LINENUMBER) {
  1634. pPopupMenu->CheckMenuItem(ID__LINENUMBER, MF_CHECKED);
  1635. }
  1636. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_FUNCTIONNAME) {
  1637. pPopupMenu->CheckMenuItem(ID__FUNCTIONNAME, MF_CHECKED);
  1638. }
  1639. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_PROCESSID) {
  1640. pPopupMenu->CheckMenuItem(ID__PROCESSID, MF_CHECKED);
  1641. }
  1642. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_THREADID) {
  1643. pPopupMenu->CheckMenuItem(ID__THREADID, MF_CHECKED);
  1644. }
  1645. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_CPUNUMBER) {
  1646. pPopupMenu->CheckMenuItem(ID__CPUNUMBER, MF_CHECKED);
  1647. }
  1648. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_SEQNUMBER) {
  1649. pPopupMenu->CheckMenuItem(ID__SEQUENCENUMBER, MF_CHECKED);
  1650. }
  1651. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_SYSTEMTIME) {
  1652. pPopupMenu->CheckMenuItem(ID__SYSTEMTIME, MF_CHECKED);
  1653. }
  1654. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_KERNELTIME) {
  1655. pPopupMenu->CheckMenuItem(ID__KERNELTIME, MF_CHECKED);
  1656. }
  1657. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_USERTIME) {
  1658. pPopupMenu->CheckMenuItem(ID__USERTIME, MF_CHECKED);
  1659. }
  1660. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_INDENT) {
  1661. pPopupMenu->CheckMenuItem(ID__INDENT, MF_CHECKED);
  1662. }
  1663. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_FLAGSNAME) {
  1664. pPopupMenu->CheckMenuItem(ID__FLAGSNAME, MF_CHECKED);
  1665. }
  1666. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_LEVELNAME) {
  1667. pPopupMenu->CheckMenuItem(ID__LEVELNAME, MF_CHECKED);
  1668. }
  1669. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_COMPNAME) {
  1670. pPopupMenu->CheckMenuItem(ID__COMPONENTNAME, MF_CHECKED);
  1671. }
  1672. if(GetDisplayFlags() & TRACEOUTPUT_DISPLAY_SUBCOMPNAME) {
  1673. pPopupMenu->CheckMenuItem(ID__SUBCOMPONENTNAME, MF_CHECKED);
  1674. }
  1675. }
  1676. void CDisplayDlg::SortTable(int Column)
  1677. {
  1678. CString str;
  1679. //
  1680. // Use qsort with the proper compare routine. We use qsort
  1681. // versus the list control's own sort functionality as its
  1682. // actually more flexible for this case. We don't have to
  1683. // parse the item data during the sorts this way. The native
  1684. // sort wouldn't buy us anything.
  1685. //
  1686. //
  1687. // Get our trace event array protection
  1688. //
  1689. WaitForSingleObject(m_hTraceEventMutex,INFINITE);
  1690. //
  1691. // Check the column to see if its in range, if not just sort
  1692. // by the last selected column
  1693. //
  1694. if(Column < MaxLogSessionOptions) {
  1695. if(m_lastSorted != m_retrievalArray[Column]) {
  1696. //
  1697. // If this column has not been used to sort the trace event
  1698. // data before, then sort ascending
  1699. //
  1700. m_bOrder = TRUE;
  1701. } else {
  1702. //
  1703. // If this column has been used before, then reverse the order
  1704. // of the sort (column header was selected again)
  1705. //
  1706. m_bOrder = (m_bOrder == TRUE ? FALSE : TRUE);
  1707. }
  1708. //
  1709. // Save the column
  1710. //
  1711. m_lastSorted = m_retrievalArray[Column];
  1712. } else if(m_lastSorted >= MaxLogSessionOptions) {
  1713. //
  1714. // Release our trace event array protection
  1715. //
  1716. ReleaseMutex(m_hTraceEventMutex);
  1717. str.Format(_T("m_lastSorted = %d"), m_lastSorted);
  1718. return;
  1719. }
  1720. //
  1721. // Determine whether to sort ascending or descending and call
  1722. // qsort with the proper callback
  1723. //
  1724. if(m_bOrder) {
  1725. qsort((PVOID)&m_traceArray[0], m_traceArray.GetSize(), sizeof(CTraceMessage *), m_traceSortRoutine[m_lastSorted]);
  1726. } else {
  1727. qsort((PVOID)&m_traceArray[0], m_traceArray.GetSize(), sizeof(CTraceMessage *), m_traceReverseSortRoutine[m_lastSorted]);
  1728. }
  1729. //
  1730. // Release our trace event array protection
  1731. //
  1732. ReleaseMutex(m_hTraceEventMutex);
  1733. }
  1734. int CDisplayDlg::CompareOnName(const void *pMessage1, const void *pMessage2)
  1735. {
  1736. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1737. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1738. return(pTraceMessage1->m_GuidName.Compare(pTraceMessage2->m_GuidName));
  1739. }
  1740. int CDisplayDlg::CompareOnMessage(const void *pMessage1, const void *pMessage2)
  1741. {
  1742. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1743. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1744. return(pTraceMessage1->m_Message.Compare(pTraceMessage2->m_Message));
  1745. }
  1746. int CDisplayDlg::CompareOnFileName(const void *pMessage1, const void *pMessage2)
  1747. {
  1748. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1749. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1750. return(pTraceMessage1->m_GuidTypeName.Compare(pTraceMessage2->m_GuidTypeName));
  1751. }
  1752. int CDisplayDlg::CompareOnLineNumber(const void *pMessage1, const void *pMessage2)
  1753. {
  1754. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1755. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1756. CString string1;
  1757. CString string2;
  1758. DWORD val1, val2;
  1759. //
  1760. // Get Line number string for the first element
  1761. //
  1762. string1 =
  1763. pTraceMessage1->m_GuidTypeName.Right(pTraceMessage1->m_GuidTypeName.GetLength() -
  1764. pTraceMessage1->m_GuidTypeName.Find('_') - 1);
  1765. string1 =
  1766. string1.Right(string1.GetLength() -
  1767. string1.FindOneOf(_T("0123456789")));
  1768. string2 =
  1769. pTraceMessage2->m_GuidTypeName.Right(pTraceMessage2->m_GuidTypeName.GetLength() -
  1770. pTraceMessage2->m_GuidTypeName.Find('_') - 1);
  1771. //
  1772. // Get the line number string for the second element
  1773. //
  1774. string2 =
  1775. string2.Right(string2.GetLength() -
  1776. string2.FindOneOf(_T("0123456789")));
  1777. TCHAR * end;
  1778. val1 = _tcstoul(string1, &end, 10);
  1779. val2 = _tcstoul(string2, &end,10);
  1780. if(val1 == val2) {
  1781. return(0);
  1782. }
  1783. if(val1 < val2) {
  1784. return(-1);
  1785. }
  1786. return(1);
  1787. }
  1788. int CDisplayDlg::CompareOnFunctionName(const void *pMessage1, const void *pMessage2)
  1789. {
  1790. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1791. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1792. return(pTraceMessage1->m_FunctionName.Compare(pTraceMessage2->m_FunctionName));
  1793. }
  1794. int CDisplayDlg::CompareOnProcessId(const void *pMessage1, const void *pMessage2)
  1795. {
  1796. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1797. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1798. return((LONG)pTraceMessage1->m_ProcessId - (LONG)pTraceMessage2->m_ProcessId);
  1799. }
  1800. int CDisplayDlg::CompareOnThreadId(const void *pMessage1, const void *pMessage2)
  1801. {
  1802. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1803. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1804. return((LONG)pTraceMessage1->m_ThreadId - (LONG)pTraceMessage2->m_ThreadId);
  1805. }
  1806. int CDisplayDlg::CompareOnCpuNumber(const void *pMessage1, const void *pMessage2)
  1807. {
  1808. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1809. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1810. return((LONG)pTraceMessage1->m_CpuNumber - (LONG)pTraceMessage2->m_CpuNumber);
  1811. }
  1812. int CDisplayDlg::CompareOnSeqNumber(const void *pMessage1, const void *pMessage2)
  1813. {
  1814. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1815. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1816. return((LONG)pTraceMessage1->m_SequenceNum - (LONG)pTraceMessage2->m_SequenceNum);
  1817. }
  1818. int CDisplayDlg::CompareOnSystemTime(const void *pMessage1, const void *pMessage2)
  1819. {
  1820. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1821. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1822. FILETIME timea, timeb;
  1823. BOOL res;
  1824. res = SystemTimeToFileTime(&pTraceMessage1->m_SystemTime, &timea);
  1825. res = SystemTimeToFileTime(&pTraceMessage2->m_SystemTime, &timeb);
  1826. return(CompareFileTime(&timea, &timeb));
  1827. }
  1828. int CDisplayDlg::CompareOnKernelTime(const void *pMessage1, const void *pMessage2)
  1829. {
  1830. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1831. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1832. return(pTraceMessage1->m_KernelTime - pTraceMessage2->m_KernelTime);
  1833. // return (pTraceMessage1->m_KernelTime.dwHighDateTime - pTraceMessage2->m_KernelTime.dwHighDateTime) ?
  1834. // (pTraceMessage1->m_KernelTime.dwHighDateTime - pTraceMessage2->m_KernelTime.dwHighDateTime) :
  1835. // (pTraceMessage1->m_KernelTime.dwLowDateTime - pTraceMessage2->m_KernelTime.dwLowDateTime);
  1836. }
  1837. int CDisplayDlg::CompareOnUserTime(const void *pMessage1, const void *pMessage2)
  1838. {
  1839. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1840. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1841. return(pTraceMessage1->m_UserTime - pTraceMessage2->m_UserTime);
  1842. // return (pTraceMessage1->m_UserTime.dwHighDateTime - pTraceMessage2->m_UserTime.dwHighDateTime) ?
  1843. // (pTraceMessage1->m_UserTime.dwHighDateTime - pTraceMessage2->m_UserTime.dwHighDateTime) :
  1844. // (pTraceMessage1->m_UserTime.dwLowDateTime - pTraceMessage2->m_UserTime.dwLowDateTime);
  1845. }
  1846. int CDisplayDlg::CompareOnIndent(const void *pMessage1, const void *pMessage2)
  1847. {
  1848. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1849. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1850. return((LONG)pTraceMessage1->m_Indent - (LONG)pTraceMessage2->m_Indent);
  1851. }
  1852. int CDisplayDlg::CompareOnFlagsName(const void *pMessage1, const void *pMessage2)
  1853. {
  1854. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1855. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1856. return(pTraceMessage1->m_FlagsName.Compare(pTraceMessage2->m_FlagsName));
  1857. }
  1858. int CDisplayDlg::CompareOnLevelName(const void *pMessage1, const void *pMessage2)
  1859. {
  1860. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1861. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1862. return(pTraceMessage1->m_LevelName.Compare(pTraceMessage2->m_LevelName));
  1863. }
  1864. int CDisplayDlg::CompareOnComponentName(const void *pMessage1, const void *pMessage2)
  1865. {
  1866. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1867. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1868. return(pTraceMessage1->m_ComponentName.Compare(pTraceMessage2->m_ComponentName));
  1869. }
  1870. int CDisplayDlg::CompareOnSubComponentName(const void *pMessage1, const void *pMessage2)
  1871. {
  1872. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1873. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1874. return(pTraceMessage1->m_SubComponentName.Compare(pTraceMessage2->m_SubComponentName));
  1875. }
  1876. int CDisplayDlg::ReverseCompareOnName(const void *pMessage1, const void *pMessage2)
  1877. {
  1878. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1879. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1880. return(pTraceMessage2->m_GuidName.Compare(pTraceMessage1->m_GuidName));
  1881. }
  1882. int CDisplayDlg::ReverseCompareOnMessage(const void *pMessage1, const void *pMessage2)
  1883. {
  1884. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1885. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1886. return(pTraceMessage2->m_Message.Compare(pTraceMessage1->m_Message));
  1887. }
  1888. int CDisplayDlg::ReverseCompareOnFileName(const void *pMessage1, const void *pMessage2)
  1889. {
  1890. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1891. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1892. return(pTraceMessage2->m_GuidTypeName.Compare(pTraceMessage1->m_GuidTypeName));
  1893. }
  1894. int CDisplayDlg::ReverseCompareOnLineNumber(const void *pMessage1, const void *pMessage2)
  1895. {
  1896. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1897. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1898. CString string1;
  1899. CString string2;
  1900. DWORD val1, val2;
  1901. //
  1902. // Get Line number string for the first element
  1903. //
  1904. string1 =
  1905. pTraceMessage1->m_GuidTypeName.Right(pTraceMessage1->m_GuidTypeName.GetLength() -
  1906. pTraceMessage1->m_GuidTypeName.Find('_') - 1);
  1907. string1 =
  1908. string1.Right(string1.GetLength() -
  1909. string1.FindOneOf(_T("0123456789")));
  1910. string2 =
  1911. pTraceMessage2->m_GuidTypeName.Right(pTraceMessage2->m_GuidTypeName.GetLength() -
  1912. pTraceMessage2->m_GuidTypeName.Find('_') - 1);
  1913. //
  1914. // Get the line number string for the second element
  1915. //
  1916. string2 =
  1917. string2.Right(string2.GetLength() -
  1918. string2.FindOneOf(_T("0123456789")));
  1919. TCHAR * end;
  1920. val1 = _tcstoul(string1, &end, 10);
  1921. val2 = _tcstoul(string2, &end,10);
  1922. if(val1 == val2) {
  1923. return(0);
  1924. }
  1925. if(val1 > val2) {
  1926. return(-1);
  1927. }
  1928. return(1);
  1929. }
  1930. int CDisplayDlg::ReverseCompareOnFunctionName(const void *pMessage1, const void *pMessage2)
  1931. {
  1932. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1933. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1934. return(pTraceMessage2->m_FunctionName.Compare(pTraceMessage1->m_FunctionName));
  1935. }
  1936. int CDisplayDlg::ReverseCompareOnProcessId(const void *pMessage1, const void *pMessage2)
  1937. {
  1938. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1939. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1940. return((LONG)pTraceMessage2->m_ProcessId - (LONG)pTraceMessage1->m_ProcessId);
  1941. }
  1942. int CDisplayDlg::ReverseCompareOnThreadId(const void *pMessage1, const void *pMessage2)
  1943. {
  1944. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1945. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1946. return((LONG)pTraceMessage2->m_ThreadId - (LONG)pTraceMessage1->m_ThreadId);
  1947. }
  1948. int CDisplayDlg::ReverseCompareOnCpuNumber(const void *pMessage1, const void *pMessage2)
  1949. {
  1950. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1951. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1952. return((LONG)pTraceMessage2->m_CpuNumber - (LONG)pTraceMessage1->m_CpuNumber);
  1953. }
  1954. int CDisplayDlg::ReverseCompareOnSeqNumber(const void *pMessage1, const void *pMessage2)
  1955. {
  1956. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1957. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1958. return((LONG)pTraceMessage2->m_SequenceNum - (LONG)pTraceMessage1->m_SequenceNum);
  1959. }
  1960. int CDisplayDlg::ReverseCompareOnSystemTime(const void *pMessage1, const void *pMessage2)
  1961. {
  1962. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1963. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1964. FILETIME timea, timeb;
  1965. BOOL res;
  1966. res = SystemTimeToFileTime(&pTraceMessage1->m_SystemTime, &timea);
  1967. res = SystemTimeToFileTime(&pTraceMessage2->m_SystemTime, &timeb);
  1968. return(CompareFileTime(&timeb, &timea));
  1969. }
  1970. int CDisplayDlg::ReverseCompareOnKernelTime(const void *pMessage1, const void *pMessage2)
  1971. {
  1972. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1973. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1974. return(pTraceMessage2->m_KernelTime - pTraceMessage1->m_KernelTime);
  1975. // return (pTraceMessage2->m_KernelTime.dwHighDateTime - pTraceMessage1->m_KernelTime.dwHighDateTime) ?
  1976. // (pTraceMessage2->m_KernelTime.dwHighDateTime - pTraceMessage1->m_KernelTime.dwHighDateTime) :
  1977. // (pTraceMessage2->m_KernelTime.dwLowDateTime - pTraceMessage1->m_KernelTime.dwLowDateTime);
  1978. }
  1979. int CDisplayDlg::ReverseCompareOnUserTime(const void *pMessage1, const void *pMessage2)
  1980. {
  1981. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1982. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1983. return(pTraceMessage2->m_UserTime - pTraceMessage1->m_UserTime);
  1984. // return (pTraceMessage2->m_UserTime.dwHighDateTime - pTraceMessage1->m_UserTime.dwHighDateTime) ?
  1985. // (pTraceMessage2->m_UserTime.dwHighDateTime - pTraceMessage1->m_UserTime.dwHighDateTime) :
  1986. // (pTraceMessage2->m_UserTime.dwLowDateTime - pTraceMessage1->m_UserTime.dwLowDateTime);
  1987. }
  1988. int CDisplayDlg::ReverseCompareOnIndent(const void *pMessage1, const void *pMessage2)
  1989. {
  1990. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1991. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1992. return((LONG)pTraceMessage2->m_Indent - (LONG)pTraceMessage1->m_Indent);
  1993. }
  1994. int CDisplayDlg::ReverseCompareOnFlagsName(const void *pMessage1, const void *pMessage2)
  1995. {
  1996. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  1997. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  1998. return(pTraceMessage2->m_FlagsName.Compare(pTraceMessage1->m_FlagsName));
  1999. }
  2000. int CDisplayDlg::ReverseCompareOnLevelName(const void *pMessage1, const void *pMessage2)
  2001. {
  2002. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  2003. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  2004. return(pTraceMessage2->m_LevelName.Compare(pTraceMessage1->m_LevelName));
  2005. }
  2006. int CDisplayDlg::ReverseCompareOnComponentName(const void *pMessage1, const void *pMessage2)
  2007. {
  2008. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  2009. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  2010. return(pTraceMessage2->m_ComponentName.Compare(pTraceMessage1->m_ComponentName));
  2011. }
  2012. int CDisplayDlg::ReverseCompareOnSubComponentName(const void *pMessage1, const void *pMessage2)
  2013. {
  2014. CTraceMessage *pTraceMessage1 = *(CTraceMessage **)pMessage1;
  2015. CTraceMessage *pTraceMessage2 = *(CTraceMessage **)pMessage2;
  2016. return(pTraceMessage2->m_SubComponentName.Compare(pTraceMessage1->m_SubComponentName));
  2017. }
  2018. BOOL CDisplayDlg::BeginTrace(BOOL bUseExisting)
  2019. {
  2020. CTraceSession *pTraceSession;
  2021. CLogSession *pLogSession;
  2022. LONG ii;
  2023. LONG jj;
  2024. CString str;
  2025. BOOL bGroupActive = FALSE;
  2026. //
  2027. // If the group is already started or being started, just return
  2028. // false
  2029. //
  2030. if(TRUE == SetGroupActive(TRUE)) {
  2031. return FALSE;
  2032. }
  2033. //
  2034. // The list head should always be NULL here
  2035. //
  2036. ASSERT(m_pEventListHead == NULL);
  2037. //
  2038. // Setup the event timer
  2039. //
  2040. m_eventTimer = SetTimer(1, EVENT_TIME_LIMIT, 0);
  2041. //
  2042. // zero our counts
  2043. //
  2044. m_totalBuffersRead = 0;
  2045. m_totalEventsLost = 0;
  2046. m_totalEventCount = 0;
  2047. //
  2048. // We set to use the StructuredFormat method in traceprt.dll
  2049. // and we use no prefix on the message. We have to specify no
  2050. // prefix as we cannot otherwise predictably setup the data we
  2051. // get in our event callback.
  2052. //
  2053. SetTraceFormatParameter(ParameterStructuredFormat,UlongToPtr(1));
  2054. SetTraceFormatParameter(ParameterUsePrefix,UlongToPtr(0));
  2055. //
  2056. // open the output file if writing output
  2057. //
  2058. if(m_bWriteListingFile) {
  2059. m_bListingFileOpen = FALSE;
  2060. if(!m_listingFile.Open(
  2061. m_listingFileName,
  2062. CFile::modeCreate | CFile::modeReadWrite)) {
  2063. AfxMessageBox(_T("Unable To Create Listing File"));
  2064. } else {
  2065. m_bListingFileOpen = TRUE;
  2066. }
  2067. }
  2068. //
  2069. // Get the array protection
  2070. //
  2071. WaitForSingleObject(m_hSessionArrayMutex, INFINITE);
  2072. //
  2073. // Setup the log sessions
  2074. //
  2075. for(ii = 0; ii < m_sessionArray.GetSize(); ii++) {
  2076. //
  2077. // Get the next CLogSession pointer
  2078. //
  2079. pLogSession = (CLogSession *)m_sessionArray[ii];
  2080. if(NULL == pLogSession) {
  2081. continue;
  2082. }
  2083. if(!pLogSession->BeginTrace(bUseExisting)) {
  2084. if(pLogSession->m_bTraceActive) {
  2085. //BUGBUG -- should we be doing this??
  2086. pLogSession->EndTrace();
  2087. }
  2088. continue;
  2089. }
  2090. bGroupActive = TRUE;
  2091. }
  2092. //
  2093. // Release the array protection
  2094. //
  2095. ReleaseMutex(m_hSessionArrayMutex);
  2096. //
  2097. // Show the sessions running
  2098. //
  2099. ::PostMessage(m_hMainWnd, WM_USER_UPDATE_LOGSESSION_LIST, 0, 0);
  2100. //
  2101. // If none of the log sessions started successfully,
  2102. // then return FALSE
  2103. //
  2104. //BUGBUG -- maybe we want to fail if ANY of the sessions didn't start?
  2105. // Also, might need a pop-up here?
  2106. if(!bGroupActive) {
  2107. SetGroupActive(FALSE);
  2108. SetState(Stopped);
  2109. return FALSE;
  2110. }
  2111. //
  2112. // Prepare the format GUIDs and such
  2113. //
  2114. if(!SetupTraceSessions()) {
  2115. AfxMessageBox(_T("Failed To Open Handles For Any Log Sessions In Group"));
  2116. SetGroupActive(FALSE);
  2117. SetState(Stopped);
  2118. return FALSE;
  2119. }
  2120. return TRUE;
  2121. }
  2122. UINT CDisplayDlg::RealTimeEventThread(LPVOID pParam)
  2123. {
  2124. CString str;
  2125. CDisplayDlg *pDisplayDlg = (CDisplayDlg *)pParam;
  2126. CLogSession *pLogSession;
  2127. LONG status;
  2128. CTraceSession *pTraceSession;
  2129. DWORD handleIndex;
  2130. HANDLE handleArray[2];
  2131. //
  2132. // Setup the handle array, the termination event
  2133. // must always be element zero, so that it's index
  2134. // will be the index returned in case multiple
  2135. // events are set
  2136. //
  2137. handleArray[0] = pDisplayDlg->m_hRealTimeTerminationEvent;
  2138. handleArray[1] = pDisplayDlg->m_hRealTimeProcessingStartEvent;
  2139. //
  2140. // Our master control loop, loop until we get a termination event
  2141. // signal. The start event signals the loop to call ProcessTrace,
  2142. // the done event is signalled and the WM_USER_TRACE_DONE message
  2143. // posted to signal that CloseTrace was called
  2144. //
  2145. while(1) {
  2146. //
  2147. // Wait on start or termination event
  2148. //
  2149. handleIndex = WaitForMultipleObjects(2,
  2150. handleArray,
  2151. FALSE,
  2152. INFINITE) - WAIT_OBJECT_0;
  2153. //
  2154. // Did we get killed?
  2155. //
  2156. if(0 == handleIndex) {
  2157. //
  2158. // Signal that we are done.
  2159. //
  2160. ::PostMessage(pDisplayDlg->GetSafeHwnd(), WM_USER_TRACE_DONE, 0, 0);
  2161. //
  2162. // Free our string buffer (threads seem to leak if this isn't done??)
  2163. //
  2164. str.Empty();
  2165. return 0;
  2166. }
  2167. //
  2168. // Reset done event for UpdateSession
  2169. //
  2170. ResetEvent(pDisplayDlg->m_hRealTimeProcessingDoneEvent);
  2171. //
  2172. // Process the trace events
  2173. //
  2174. status = ProcessTrace(pDisplayDlg->m_traceHandleArray,
  2175. pDisplayDlg->m_traceHandleCount,
  2176. NULL,
  2177. NULL);
  2178. if(ERROR_SUCCESS != status){
  2179. str.Format(_T("ProcessTrace returned error %d, GetLastError() = %d\n"), status, GetLastError());
  2180. AfxMessageBox(str);
  2181. }
  2182. //
  2183. // We are done, close the trace sessions
  2184. //
  2185. for(LONG ii = 0; ii < pDisplayDlg->m_traceHandleCount; ii++) {
  2186. status = CloseTrace(pDisplayDlg->m_traceHandleArray[ii]);
  2187. if(ERROR_SUCCESS != status){
  2188. str.Format(_T("CloseTrace returned error %d\n"), status);
  2189. AfxMessageBox(str);
  2190. }
  2191. }
  2192. //
  2193. // Set done event for UpdateSession
  2194. //
  2195. SetEvent(pDisplayDlg->m_hRealTimeProcessingDoneEvent);
  2196. //
  2197. // Indicate that we are done.
  2198. //
  2199. ::PostMessage(pDisplayDlg->GetSafeHwnd(), WM_USER_TRACE_DONE, 0, 0);
  2200. }
  2201. return 0;
  2202. }
  2203. BOOL CDisplayDlg::EndTrace(HANDLE DoneEvent)
  2204. {
  2205. CString str;
  2206. CLogSession *pLogSession;
  2207. LONG ii;
  2208. BOOL bWasActive = FALSE;
  2209. BOOL bWasRealTime = FALSE;
  2210. //
  2211. // If the group is already stopped, or is stopping, just
  2212. // return FALSE.
  2213. //
  2214. if(TRUE == SetGroupInActive(TRUE)) {
  2215. return FALSE;
  2216. }
  2217. //
  2218. // Save the caller's event to be set when stopped
  2219. //
  2220. m_hEndTraceEvent = DoneEvent;
  2221. //
  2222. // Get the array protection
  2223. //
  2224. WaitForSingleObject(m_hSessionArrayMutex, INFINITE);
  2225. for(ii = 0; ii < m_sessionArray.GetSize(); ii++) {
  2226. pLogSession = (CLogSession *)m_sessionArray[ii];
  2227. if(NULL == pLogSession) {
  2228. continue;
  2229. }
  2230. //
  2231. // If the session is active, stop it
  2232. //
  2233. if(pLogSession->m_bTraceActive) {
  2234. pLogSession->EndTrace();
  2235. bWasActive = TRUE;
  2236. if(pLogSession->m_bRealTime) {
  2237. bWasRealTime = TRUE;
  2238. }
  2239. }
  2240. }
  2241. //
  2242. // Release the array protection
  2243. //
  2244. ReleaseMutex(m_hSessionArrayMutex);
  2245. if(bWasActive) {
  2246. //
  2247. // Update the log session state
  2248. //
  2249. ::PostMessage(m_hMainWnd, WM_USER_UPDATE_LOGSESSION_LIST, 0, 0);
  2250. if(!bWasRealTime) {
  2251. //
  2252. // We need to explicitly call OnTraceDone here
  2253. //
  2254. OnTraceDone(NULL, NULL);
  2255. }
  2256. return TRUE;
  2257. }
  2258. return FALSE;
  2259. }
  2260. void CDisplayDlg::OnTraceDone(WPARAM wParam, LPARAM lParam)
  2261. {
  2262. CString str;
  2263. CLogSession *pLogSession = NULL;
  2264. //
  2265. // Set the group state
  2266. //
  2267. SetState(Stopping);
  2268. //
  2269. // Write the summary file if requested
  2270. //
  2271. if(m_bWriteSummaryFile) {
  2272. WriteSummaryFile();
  2273. }
  2274. //
  2275. // close the output file if opened
  2276. //
  2277. if(m_bWriteListingFile && m_bListingFileOpen) {
  2278. m_listingFile.Close();
  2279. m_bListingFileOpen = FALSE;
  2280. }
  2281. //
  2282. // Cleanup the event list
  2283. //
  2284. WaitForSingleObject(g_hGetTraceEvent, INFINITE);
  2285. //
  2286. // The event list head
  2287. //
  2288. CleanupTraceEventList(m_pEventListHead);
  2289. SetEvent(g_hGetTraceEvent);
  2290. m_pEventListHead = NULL;
  2291. //
  2292. // Remove the keys from the hash table
  2293. //
  2294. for(LONG ii = 0; ii < m_sessionArray.GetSize(); ii++) {
  2295. pLogSession = (CLogSession *)m_sessionArray[ii];
  2296. if(NULL == pLogSession) {
  2297. continue;
  2298. }
  2299. g_loggerNameToDisplayDlgHash.RemoveKey(pLogSession->GetDisplayName());
  2300. }
  2301. //
  2302. // Kill the event timer
  2303. //
  2304. KillTimer(m_eventTimer);
  2305. //
  2306. // Force one last update of the event display
  2307. //
  2308. OnTimer(1);
  2309. //
  2310. // Set the group as not active
  2311. //
  2312. SetGroupActive(FALSE);
  2313. SetGroupInActive(FALSE);
  2314. //
  2315. // Set the group state
  2316. //
  2317. SetState(Stopped);
  2318. if(m_hEndTraceEvent != NULL) {
  2319. SetEvent(m_hEndTraceEvent);
  2320. m_hEndTraceEvent = NULL;
  2321. }
  2322. return;
  2323. }
  2324. //
  2325. // Updates an active tracing session. Real-Time mode, log file name,
  2326. // flush-time, flags, and maximum buffers can be updated for active
  2327. // sessions.
  2328. //
  2329. BOOL CDisplayDlg::UpdateSession(CLogSession *pLogSession)
  2330. {
  2331. CLogSession *pLog;
  2332. PEVENT_TRACE_PROPERTIES pQueryProperties;
  2333. ULONG sizeNeeded;
  2334. LPTSTR pLoggerName;
  2335. LPTSTR pCurrentLogFileName;
  2336. LPTSTR pLogFileName;
  2337. ULONG flags;
  2338. ULONG level;
  2339. ULONG status;
  2340. CString logFileName;
  2341. CString str;
  2342. //
  2343. // setup our buffer size for the properties struct for our query
  2344. //
  2345. sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 1024 * sizeof(TCHAR));
  2346. //
  2347. // allocate our memory
  2348. //
  2349. pQueryProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded];
  2350. if(NULL == pQueryProperties) {
  2351. return FALSE;
  2352. }
  2353. //
  2354. // zero our structures
  2355. //
  2356. memset(pQueryProperties, 0, sizeNeeded);
  2357. //
  2358. // Set the size
  2359. //
  2360. pQueryProperties->Wnode.BufferSize = sizeNeeded;
  2361. //
  2362. // Set the GUID
  2363. //
  2364. pQueryProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  2365. //
  2366. // Set the logger name offset
  2367. //
  2368. pQueryProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  2369. //
  2370. // Set the logger name for the query
  2371. //
  2372. pLoggerName = (LPTSTR)((char*)pQueryProperties + pQueryProperties->LoggerNameOffset);
  2373. _tcscpy(pLoggerName, pLogSession->GetDisplayName());
  2374. //
  2375. // Set the log file name offset
  2376. //
  2377. pQueryProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR));
  2378. //
  2379. // Get the log file name pointers
  2380. //
  2381. pCurrentLogFileName = (LPTSTR)((char*)pQueryProperties + pQueryProperties->LogFileNameOffset);
  2382. //
  2383. // Query the log session
  2384. //
  2385. status = ControlTrace(0,
  2386. pLogSession->GetDisplayName(),
  2387. pQueryProperties,
  2388. EVENT_TRACE_CONTROL_QUERY);
  2389. if(ERROR_SUCCESS != status) {
  2390. str.Format(_T("Query Failed For Log Session, %d\nSession Not Updated"), status);
  2391. AfxMessageBox(str);
  2392. }
  2393. //
  2394. // Call the log session's UpdateSession function
  2395. //
  2396. if(!pLogSession->UpdateSession(pQueryProperties)) {
  2397. delete [] pQueryProperties;
  2398. return FALSE;
  2399. }
  2400. //
  2401. // Get the array protection
  2402. //
  2403. WaitForSingleObject(m_hSessionArrayMutex, INFINITE);
  2404. for(LONG ii = 0; ii < m_sessionArray.GetSize(); ii++) {
  2405. pLog = (CLogSession *)m_sessionArray[ii];
  2406. if(pLog == pLogSession) {
  2407. continue;
  2408. }
  2409. //
  2410. // In our real-time thread we call ProcessTrace. If all sessions
  2411. // related to that call update to be non-real-time sessions, then
  2412. // ProcessTrace will exit and CloseTrace will get called. We have
  2413. // to track this and restart the real-time processing if a log session
  2414. // subsequently updates to be real-time again. So, we check here if
  2415. // any other attached sessions are real-time, and if so, we don't
  2416. // have to bother with waiting on or setting the events below.
  2417. //
  2418. if(pLog->m_bRealTime) {
  2419. delete [] pQueryProperties;
  2420. return TRUE;
  2421. }
  2422. }
  2423. //
  2424. // Release the array protection
  2425. //
  2426. ReleaseMutex(m_hSessionArrayMutex);
  2427. //
  2428. // If real-time is specified and the session was not real-time before,
  2429. // then we need to set the start event.
  2430. //
  2431. if(pLogSession->m_bRealTime &&
  2432. !(pQueryProperties->LogFileMode & EVENT_TRACE_REAL_TIME_MODE)) {
  2433. //
  2434. // We have updated a session to be real-time and it is the only session in
  2435. // its group to be real-time. We need to restart the trace in this case
  2436. //
  2437. //
  2438. // Start the real-time thread processing again
  2439. //
  2440. BeginTrace(TRUE);
  2441. }
  2442. //
  2443. // If real-time is not set and it was before, then we need to wait on
  2444. // the real-time thread to catch the fact that the session is no longer
  2445. // tracing real time. This will cause the ProcessTrace call to
  2446. // return in the real-time thread.
  2447. //
  2448. if(!pLogSession->m_bRealTime &&
  2449. (pQueryProperties->LogFileMode & EVENT_TRACE_REAL_TIME_MODE)) {
  2450. //
  2451. // Make sure our thread catches the stop
  2452. //
  2453. WaitForSingleObject(m_hRealTimeProcessingDoneEvent, INFINITE);
  2454. }
  2455. delete [] pQueryProperties;
  2456. return TRUE;
  2457. }
  2458. BOOL CDisplayDlg::SetupTraceSessions()
  2459. {
  2460. CTraceSession *pTraceSession;
  2461. CLogSession *pLogSession;
  2462. LONG jj;
  2463. CString str;
  2464. LPTSTR tmfFile;
  2465. PVOID pHashEntry;
  2466. //
  2467. // Initialize our handle count
  2468. //
  2469. m_traceHandleCount = 0;
  2470. //
  2471. // Get the array protection
  2472. //
  2473. WaitForSingleObject(m_hSessionArrayMutex, INFINITE);
  2474. //
  2475. // Setup the log sessions
  2476. //
  2477. for(LONG ii = 0; ii < m_sessionArray.GetSize(); ii++) {
  2478. //
  2479. // Get the next CLogSession pointer
  2480. //
  2481. pLogSession = (CLogSession *)m_sessionArray[ii];
  2482. if(NULL == pLogSession) {
  2483. continue;
  2484. }
  2485. //
  2486. // If the log session is not real-time and we are not dumping an existing
  2487. // logfile, then no need to call OpenTrace
  2488. //
  2489. if((!pLogSession->m_bRealTime) && (!pLogSession->m_bDisplayExistingLogFileOnly)) {
  2490. continue;
  2491. }
  2492. //
  2493. // zero the EVENT_TRACE_LOGFILE buffer
  2494. //
  2495. memset(&pLogSession->m_evmFile, 0, sizeof(EVENT_TRACE_LOGFILE));
  2496. //
  2497. // setup the trace parameters
  2498. //
  2499. //
  2500. // For real-time we set the logger name only, for existing logfiles we
  2501. // also set the logfile name.
  2502. //
  2503. if(pLogSession->m_bDisplayExistingLogFileOnly) {
  2504. pLogSession->m_evmFile.LogFileName = (LPTSTR)(LPCTSTR)pLogSession->m_logFileName;
  2505. pLogSession->m_evmFile.LoggerName = (LPTSTR)(LPCTSTR)pLogSession->GetDisplayName();
  2506. } else {
  2507. pLogSession->m_evmFile.LoggerName = (LPTSTR)(LPCTSTR)pLogSession->GetDisplayName();
  2508. }
  2509. pLogSession->m_evmFile.Context = NULL;
  2510. pLogSession->m_evmFile.BufferCallback = (PEVENT_TRACE_BUFFER_CALLBACK)BufferCallback;
  2511. pLogSession->m_evmFile.BuffersRead = 0;
  2512. pLogSession->m_evmFile.CurrentTime = 0;
  2513. pLogSession->m_evmFile.EventCallback = m_pEventCallback;
  2514. if(pLogSession->m_bDisplayExistingLogFileOnly) {
  2515. pLogSession->m_evmFile.LogFileMode = EVENT_TRACE_FILE_MODE_SEQUENTIAL;
  2516. } else {
  2517. pLogSession->m_evmFile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  2518. }
  2519. //
  2520. // We call GetTraceGuids for each TMF file specified, or once if
  2521. // a TMF path is used.
  2522. //
  2523. for(jj = 0; jj < pLogSession->m_traceSessionArray.GetSize(); jj++) {
  2524. pTraceSession = (CTraceSession *)pLogSession->m_traceSessionArray[jj];
  2525. if((NULL != pTraceSession) && (0 != pTraceSession->m_tmfFile.GetSize())) {
  2526. //
  2527. // TMFs were selected get the format info from each one.
  2528. //
  2529. for(LONG kk = 0; kk < pTraceSession->m_tmfFile.GetSize(); kk++) {
  2530. //
  2531. // Make sure the format info isn't already in use
  2532. // This actually isn't foolproof, as it counts on
  2533. // no one changing the TMF filename and thus two TMFs
  2534. // with different names having the same format GUID.
  2535. //
  2536. if(g_formatInfoHash.Lookup(pTraceSession->m_tmfFile[kk].Right(40), pHashEntry)) {
  2537. //
  2538. // Need to clean out any unique entries from the hash that
  2539. // were added by this session
  2540. //
  2541. for(; kk > 0; kk--) {
  2542. g_formatInfoHash.RemoveKey(pTraceSession->m_tmfFile[kk - 1].Right(40));
  2543. }
  2544. return FALSE;
  2545. }
  2546. //
  2547. // Not there, so add it to the hash
  2548. //
  2549. g_formatInfoHash.SetAt(pTraceSession->m_tmfFile[kk].Right(40), pLogSession);
  2550. //
  2551. // get the protection
  2552. //
  2553. WaitForSingleObject(g_hGetTraceEvent, INFINITE);
  2554. //
  2555. // Get the format GUIDs from the TMF file(s)
  2556. //
  2557. if(0 == GetTraceGuids((LPTSTR)(LPCTSTR)pTraceSession->m_tmfFile[kk],
  2558. (PLIST_ENTRY *)&m_pEventListHead)) {
  2559. str.Format(_T("Failed To Get Format Information For Logger %ls"), pLogSession->m_evmFile.LoggerName);
  2560. AfxMessageBox(str);
  2561. }
  2562. //
  2563. // Release the protection
  2564. //
  2565. SetEvent(g_hGetTraceEvent);
  2566. }
  2567. } else {
  2568. CString defaultPath;
  2569. if((GetModuleFileName(NULL, defaultPath.GetBuffer(500), 500)) == 0) {
  2570. defaultPath.Empty();
  2571. } else {
  2572. defaultPath = (LPCTSTR)defaultPath.Left(defaultPath.ReverseFind('\\') + 1);
  2573. }
  2574. defaultPath +=_T("default.tmf");
  2575. //
  2576. // If path is empty, the TMF path environment variable will
  2577. // be used as-is by default.
  2578. //
  2579. if(!pTraceSession->m_tmfPath.IsEmpty()){
  2580. //
  2581. // If the path is set we set the TMF path
  2582. // environment variable
  2583. //
  2584. SetTraceFormatParameter(ParameterTraceFormatSearchPath, (PVOID)(LPCTSTR)pTraceSession->m_tmfPath);
  2585. }
  2586. //
  2587. // Still have to call GetTraceGuids
  2588. //
  2589. WaitForSingleObject(g_hGetTraceEvent, INFINITE);
  2590. //
  2591. // Get the format info
  2592. //
  2593. GetTraceGuids((LPTSTR)(LPCTSTR)defaultPath,
  2594. (PLIST_ENTRY *)&m_pEventListHead);
  2595. //
  2596. // Release the protection
  2597. //
  2598. SetEvent(g_hGetTraceEvent);
  2599. }
  2600. }
  2601. //
  2602. // Open and get a handle to the trace session
  2603. //
  2604. pLogSession->m_traceHandle = OpenTrace(&pLogSession->m_evmFile);
  2605. if(INVALID_HANDLE_VALUE == (HANDLE)pLogSession->m_traceHandle) {
  2606. str.Format(_T("OpenTrace failed for logger %ls\nError returned: %d"),
  2607. pLogSession->GetDisplayName(),
  2608. GetLastError());
  2609. AfxMessageBox(str);
  2610. continue;
  2611. }
  2612. //
  2613. // Save the handle in our array for OpenTrace
  2614. //
  2615. m_traceHandleArray[m_traceHandleCount++] = pLogSession->m_traceHandle;
  2616. //
  2617. // Add this displayDlg to the global hash table keyed
  2618. // by log session name
  2619. //
  2620. g_loggerNameToDisplayDlgHash.SetAt(pLogSession->GetDisplayName(), this);
  2621. }
  2622. //
  2623. // Release the array protection
  2624. //
  2625. ReleaseMutex(m_hSessionArrayMutex);
  2626. //
  2627. // If we have at least one valid handle start
  2628. // our real-time thread processing events
  2629. //
  2630. if(m_traceHandleCount != 0) {
  2631. //
  2632. // Set the real-time processing start event and thus kick
  2633. // the real-time thread into processing events
  2634. //
  2635. SetEvent(m_hRealTimeProcessingStartEvent);
  2636. }
  2637. return TRUE;
  2638. }
  2639. //
  2640. // This function handles writing the summary file. Heavily borrowed code
  2641. // from TraceFmt here.
  2642. //
  2643. VOID CDisplayDlg::WriteSummaryFile()
  2644. {
  2645. CLogSession *pLogSession;
  2646. CString str;
  2647. CStdioFile summaryFile;
  2648. TCHAR *pSummaryBlock;
  2649. __int64 elapsedTime;
  2650. LONG ii;
  2651. //
  2652. // Attempt to open the summary file
  2653. //
  2654. if(!summaryFile.Open(m_summaryFileName, CFile::modeCreate |
  2655. CFile::modeReadWrite)) {
  2656. AfxMessageBox(_T("Unable To Create Summary File"));
  2657. return;
  2658. }
  2659. //
  2660. // allocate some memory
  2661. //
  2662. pSummaryBlock = new TCHAR[SIZESUMMARYBLOCK];
  2663. if(NULL == pSummaryBlock) {
  2664. AfxMessageBox(_T("Unable To Create Summary File"));
  2665. return;
  2666. }
  2667. //
  2668. // Write the header
  2669. //
  2670. str.Format(_T("Files Processed:\n"));
  2671. summaryFile.WriteString(str);
  2672. //
  2673. // Get the array protection
  2674. //
  2675. WaitForSingleObject(m_hSessionArrayMutex, INFINITE);
  2676. for(ii = 0; ii < m_sessionArray.GetSize(); ii++) {
  2677. pLogSession = (CLogSession *)m_sessionArray[ii];
  2678. if(NULL == pLogSession) {
  2679. continue;
  2680. }
  2681. str.Format(_T("\t%s\n"),pLogSession->m_logFileName);
  2682. summaryFile.WriteString(str);
  2683. }
  2684. //
  2685. // Release the array protection
  2686. //
  2687. ReleaseMutex(m_hSessionArrayMutex);
  2688. //
  2689. // Get the duration of the session
  2690. //
  2691. GetTraceElapseTime(&elapsedTime);
  2692. //
  2693. // Write out the counts
  2694. //
  2695. str.Format(
  2696. _T("Total Buffers Processed %d\n")
  2697. _T("Total Events Processed %d\n")
  2698. _T("Total Events Lost %d\n")
  2699. _T("Elapsed Time %I64d sec\n"),
  2700. m_totalBuffersRead,
  2701. m_totalEventCount,
  2702. m_totalEventsLost,
  2703. (elapsedTime / 10000000) );
  2704. summaryFile.WriteString(str);
  2705. str.Format(
  2706. _T("+--------------------------------------------------------------------------------------+\n")
  2707. _T("|%10s %-20s %-10s %-36s|\n")
  2708. _T("+--------------------------------------------------------------------------------------+\n"),
  2709. _T("EventCount"),
  2710. _T("EventName"),
  2711. _T("EventType"),
  2712. _T("Guid"));
  2713. summaryFile.WriteString(str);
  2714. //
  2715. // Write out the summary block
  2716. //
  2717. SummaryTraceEventList(pSummaryBlock, SIZESUMMARYBLOCK, m_pEventListHead);
  2718. str.Format(_T("%s+--------------------------------------------------------------------------------------+\n"),
  2719. pSummaryBlock);
  2720. summaryFile.WriteString(str);
  2721. //
  2722. // Close the file
  2723. //
  2724. summaryFile.Close();
  2725. //
  2726. // Free our memory
  2727. //
  2728. delete [] pSummaryBlock;
  2729. }
  2730. ULONG WINAPI BufferCallback(PEVENT_TRACE_LOGFILE pLog)
  2731. {
  2732. CDisplayDlg *pDisplayDlg;
  2733. CString str;
  2734. //
  2735. // Get the logger name from the passed in struct
  2736. //
  2737. str.Format(_T("%s"), pLog->LoggerName);
  2738. //
  2739. // Get our logsession from the global hash table using the logger name
  2740. //
  2741. g_loggerNameToDisplayDlgHash.Lookup(str, (void*&)pDisplayDlg);
  2742. //
  2743. // If we got our displayDlg, update the counts
  2744. //
  2745. if(NULL != pDisplayDlg) {
  2746. pDisplayDlg->m_totalBuffersRead++;
  2747. pDisplayDlg->m_totalEventsLost += pLog->EventsLost;
  2748. ::PostMessage(pDisplayDlg->m_hMainWnd, WM_USER_UPDATE_LOGSESSION_LIST, 0, 0);
  2749. }
  2750. return TRUE;
  2751. }
  2752. //
  2753. // Sort handler
  2754. VOID CDisplayDlg::OnDoSort(NMHDR * pNmhdr, LRESULT * pResult)
  2755. {
  2756. NMLISTVIEW *pLV = (NMLISTVIEW *)pNmhdr;
  2757. //
  2758. // Sort the table by the selected column's data
  2759. //
  2760. SortTable(pLV->iItem);
  2761. //
  2762. // Force a redraw of the data
  2763. //
  2764. m_displayCtrl.RedrawItems(m_displayCtrl.GetTopIndex(),
  2765. m_displayCtrl.GetTopIndex() + m_displayCtrl.GetCountPerPage());
  2766. m_displayCtrl.UpdateWindow();
  2767. }
  2768. //
  2769. // EventHandler() is only a wrapper, it calls FormatTraceEvent() in TracePrt.
  2770. //
  2771. VOID CDisplayDlg::EventHandler(PEVENT_TRACE pEvent)
  2772. {
  2773. CString str;
  2774. CString tempString;
  2775. GUID guidValue;
  2776. CString guidString;
  2777. PSTRUCTUREDMESSAGE pStructuredMessage;
  2778. CTraceMessage *pTraceMessage;
  2779. DWORD itemCount;
  2780. DWORD time;
  2781. CTraceViewApp *pMainWnd;
  2782. //
  2783. // Make sure we got an event
  2784. //
  2785. if (NULL == pEvent) {
  2786. return;
  2787. }
  2788. //
  2789. // Get traceprt protection
  2790. //
  2791. WaitForSingleObject(g_hGetTraceEvent, INFINITE);
  2792. //
  2793. // FormatTraceEvent fills in our event buffer and updates some
  2794. // info in the event list for the summary file
  2795. //
  2796. if(FormatTraceEvent(m_pEventListHead,
  2797. pEvent,
  2798. m_pEventBuf,
  2799. EVENT_BUFFER_SIZE,
  2800. NULL) <= 0) {
  2801. //
  2802. // Release traceprt protection
  2803. //
  2804. SetEvent(g_hGetTraceEvent);
  2805. return;
  2806. }
  2807. //
  2808. // Release traceprt protection
  2809. //
  2810. SetEvent(g_hGetTraceEvent);
  2811. //
  2812. // Get the structured message struct from the event buffer
  2813. //
  2814. pStructuredMessage = (PSTRUCTUREDMESSAGE)&m_pEventBuf[0];
  2815. //
  2816. // Get a pointer to the main wnd
  2817. //
  2818. pMainWnd = (CTraceViewApp *)AfxGetApp();
  2819. if(NULL == pMainWnd) {
  2820. return;
  2821. }
  2822. //
  2823. // Allocate a message struct from the main frame
  2824. //
  2825. pTraceMessage = pMainWnd->AllocateTraceEventBlock();
  2826. if(NULL == pTraceMessage) {
  2827. return;
  2828. }
  2829. //
  2830. // Get the message from the event buffer
  2831. //
  2832. memcpy(&pTraceMessage->m_TraceGuid,
  2833. &pStructuredMessage->TraceGuid,
  2834. sizeof(GUID));
  2835. //
  2836. // Copy the message struct to our own struct
  2837. //
  2838. pTraceMessage->m_GuidName =
  2839. (pStructuredMessage->GuidName ? &m_pEventBuf[pStructuredMessage->GuidName/sizeof(TCHAR)] :_T(""));
  2840. pTraceMessage->m_GuidTypeName.Format(_T("%s"),
  2841. (pStructuredMessage->GuidTypeName ? &m_pEventBuf[pStructuredMessage->GuidTypeName/sizeof(TCHAR)] :_T("")));
  2842. pTraceMessage->m_ThreadId = pStructuredMessage->ThreadId;
  2843. memcpy(&pTraceMessage->m_SystemTime,
  2844. &pStructuredMessage->SystemTime,
  2845. sizeof(SYSTEMTIME));
  2846. memcpy(&pTraceMessage->m_UserTime,
  2847. &pStructuredMessage->UserTime,
  2848. sizeof(ULONG));
  2849. memcpy(&pTraceMessage->m_KernelTime,
  2850. &pStructuredMessage->KernelTime,
  2851. sizeof(ULONG));
  2852. pTraceMessage->m_SequenceNum = pStructuredMessage->SequenceNum;
  2853. pTraceMessage->m_ProcessId = pStructuredMessage->ProcessId;
  2854. pTraceMessage->m_CpuNumber = pStructuredMessage->CpuNumber;
  2855. pTraceMessage->m_Indent = pStructuredMessage->Indent;
  2856. pTraceMessage->m_FlagsName.Format(_T("%s"),
  2857. (pStructuredMessage->FlagsName ? &m_pEventBuf[pStructuredMessage->FlagsName/sizeof(TCHAR)] :_T("")));
  2858. pTraceMessage->m_LevelName.Format(_T("%s"),
  2859. (pStructuredMessage->LevelName ? &m_pEventBuf[pStructuredMessage->LevelName/sizeof(TCHAR)] :_T("")));
  2860. pTraceMessage->m_FunctionName.Format(_T("%s"),
  2861. (pStructuredMessage->FunctionName ? &m_pEventBuf[pStructuredMessage->FunctionName/sizeof(TCHAR)] :_T("")));
  2862. pTraceMessage->m_ComponentName.Format(_T("%s"),
  2863. (pStructuredMessage->ComponentName ? &m_pEventBuf[pStructuredMessage->ComponentName/sizeof(TCHAR)] :_T("")));
  2864. pTraceMessage->m_SubComponentName.Format(_T("%s"),
  2865. (pStructuredMessage->SubComponentName ? &m_pEventBuf[pStructuredMessage->SubComponentName/sizeof(TCHAR)] :_T("")));
  2866. pTraceMessage->m_Message.Format(_T("%s"),
  2867. (pStructuredMessage->FormattedString ? &m_pEventBuf[pStructuredMessage->FormattedString/sizeof(TCHAR)] :_T("")));
  2868. //
  2869. // Get our trace event array protection
  2870. //
  2871. WaitForSingleObject(m_hTraceEventMutex,INFINITE);
  2872. //
  2873. // If we're in a low memory situation, drop one entry for every one we add
  2874. //
  2875. if( m_traceArray.GetSize() > MaxTraceEntries) {
  2876. delete m_traceArray.GetAt(0);
  2877. //
  2878. // Slide 'em all down...
  2879. //
  2880. m_traceArray.RemoveAt(0);
  2881. }
  2882. //
  2883. // Add the event to the array
  2884. //
  2885. m_traceArray.Add(pTraceMessage);
  2886. //
  2887. // Update the item count for the list control so that
  2888. // the display gets updated
  2889. //
  2890. itemCount = (LONG)m_traceArray.GetSize();
  2891. //
  2892. // Release our trace event array protection
  2893. //
  2894. ReleaseMutex(m_hTraceEventMutex);
  2895. //
  2896. // dump the event to the output file if any
  2897. //
  2898. if(m_bWriteListingFile &&
  2899. m_bListingFileOpen) {
  2900. //
  2901. // Glorious hack to get FILETIME back into string format
  2902. // Not sure this works for different time zones or daylight savings
  2903. //
  2904. CTime kernelTime(pStructuredMessage->KernelTime);
  2905. CTime userTime(pStructuredMessage->UserTime);
  2906. CString system;
  2907. CString kernel;
  2908. CString user;
  2909. system.Format(_T("%02d\\%02d\\%4d-%02d:%02d:%02d"),
  2910. pStructuredMessage->SystemTime.wMonth,
  2911. pStructuredMessage->SystemTime.wDay,
  2912. pStructuredMessage->SystemTime.wYear,
  2913. pStructuredMessage->SystemTime.wHour,
  2914. pStructuredMessage->SystemTime.wMinute,
  2915. pStructuredMessage->SystemTime.wSecond,
  2916. pStructuredMessage->SystemTime.wMilliseconds);
  2917. if(kernelTime.GetYear() == 1969) {
  2918. kernel.Format(_T(" "));
  2919. } else {
  2920. kernel.Format(_T("%s-%02d:%02d:%02d"),
  2921. kernelTime.Format("%m\\%d\\%Y"),
  2922. kernelTime.GetHour() + 5,
  2923. kernelTime.GetMinute(),
  2924. kernelTime.GetSecond());
  2925. }
  2926. if(userTime.GetYear() == 1969) {
  2927. user.Format(_T(" "));
  2928. } else {
  2929. user.Format(_T("%s-%02d:%02d:%02d"),
  2930. userTime.Format("%m\\%d\\%Y"),
  2931. userTime.GetHour() + 5,
  2932. userTime.GetMinute(),
  2933. userTime.GetSecond());
  2934. }
  2935. //
  2936. // Need to reformat with good timestamps for the output file.
  2937. // Output Order --> Name FileName_Line# FunctionName ProcessID ThreadID
  2938. // CPU# Seq# SystemTime KernelTime UserTime Indent
  2939. // FlagsName LevelName ComponentName SubComponentName
  2940. // Message at end
  2941. //
  2942. str.Format(_T("%s %s %s %X %X %d %u %s %s %s %s %s %s %s %s %s"),
  2943. (pStructuredMessage->GuidName ? &m_pEventBuf[pStructuredMessage->GuidName/sizeof(TCHAR)] :_T("")),
  2944. (pStructuredMessage->GuidTypeName ? &m_pEventBuf[pStructuredMessage->GuidTypeName/sizeof(TCHAR)] :_T("")),
  2945. (pStructuredMessage->FunctionName ? &m_pEventBuf[pStructuredMessage->FunctionName/sizeof(TCHAR)] :_T("")),
  2946. pStructuredMessage->ProcessId,
  2947. pStructuredMessage->ThreadId,
  2948. pStructuredMessage->CpuNumber,
  2949. pStructuredMessage->SequenceNum,
  2950. system,
  2951. kernel,
  2952. user,
  2953. (pStructuredMessage->Indent ? &m_pEventBuf[pStructuredMessage->Indent/sizeof(TCHAR)] :_T("")),
  2954. (pStructuredMessage->FlagsName ? &m_pEventBuf[pStructuredMessage->FlagsName/sizeof(TCHAR)] :_T("")),
  2955. (pStructuredMessage->LevelName ? &m_pEventBuf[pStructuredMessage->LevelName/sizeof(TCHAR)] :_T("")),
  2956. (pStructuredMessage->ComponentName ? &m_pEventBuf[pStructuredMessage->ComponentName/sizeof(TCHAR)] :_T("")),
  2957. (pStructuredMessage->SubComponentName ? &m_pEventBuf[pStructuredMessage->SubComponentName/sizeof(TCHAR)] :_T("")),
  2958. (pStructuredMessage->FormattedString ? &m_pEventBuf[pStructuredMessage->FormattedString/sizeof(TCHAR)] :_T("")));
  2959. str +=_T("\n");
  2960. m_listingFile.WriteString(str);
  2961. }
  2962. //
  2963. // Update the event count for the summary file
  2964. //
  2965. m_totalEventCount++;
  2966. //
  2967. // Empty the string buffer (not strictly necessary)
  2968. //
  2969. str.Empty();
  2970. }
  2971. VOID CDisplayDlg::OnTimer(UINT nIDEvent)
  2972. {
  2973. int itemCount;
  2974. static int previousCount = 0;
  2975. static BOOL bAutoSizeOnce = TRUE;
  2976. static CTraceMessage * msgLastSeen=0;
  2977. //
  2978. // This is a really bad hack.
  2979. // Couldn't figure out anyway to get notified when
  2980. // the DisplayDlg window has actually been displayed.
  2981. // Until it is displayed, then AutoSizeColumns won't
  2982. // work correctly for the last column. Calling it here
  2983. // seems to fix the problem. There has to be a better way.
  2984. //
  2985. if(bAutoSizeOnce) {
  2986. AutoSizeColumns();
  2987. bAutoSizeOnce = FALSE;
  2988. }
  2989. //
  2990. // Get our trace event array protection
  2991. //
  2992. WaitForSingleObject(m_hTraceEventMutex,INFINITE);
  2993. //
  2994. // Update the item count for the list control so that
  2995. // the display gets updated
  2996. //
  2997. itemCount = (LONG)m_traceArray.GetSize();
  2998. //
  2999. // Release our trace event array protection
  3000. //
  3001. ReleaseMutex(m_hTraceEventMutex);
  3002. if(itemCount == 0) {
  3003. msgLastSeen = NULL;
  3004. return;
  3005. }
  3006. if( itemCount <= MaxTraceEntries) {
  3007. if( itemCount == previousCount ) {
  3008. return;
  3009. }
  3010. } else {
  3011. if(m_traceArray.GetAt(0) == msgLastSeen) {
  3012. return;
  3013. }
  3014. msgLastSeen = m_traceArray.GetAt(0);
  3015. }
  3016. previousCount = itemCount;
  3017. //
  3018. // Sort the table of event messages
  3019. //
  3020. SortTable();
  3021. //
  3022. // Adjust the trace display item count
  3023. //
  3024. m_displayCtrl.SetItemCountEx(itemCount,
  3025. LVSICF_NOINVALIDATEALL|LVSICF_NOSCROLL);
  3026. m_displayCtrl.RedrawItems(m_displayCtrl.GetTopIndex(),
  3027. m_displayCtrl.GetTopIndex() + m_displayCtrl.GetCountPerPage());
  3028. m_displayCtrl.UpdateWindow();
  3029. //
  3030. // Ensure that the last item is visible if requested.
  3031. //
  3032. if(m_bShowLatest) {
  3033. m_displayCtrl.EnsureVisible(itemCount - 1,
  3034. FALSE);
  3035. }
  3036. //
  3037. // Force an update of the event count in the display
  3038. //
  3039. ::PostMessage(m_hMainWnd, WM_USER_UPDATE_LOGSESSION_LIST, 0, 0);
  3040. }
  3041. VOID CDisplayDlg::SetState(LOG_SESSION_STATE StateValue)
  3042. {
  3043. CLogSession *pLogSession = NULL;
  3044. //
  3045. // Get the array protection
  3046. //
  3047. WaitForSingleObject(m_hSessionArrayMutex, INFINITE);
  3048. for(LONG ii = 0; ii < m_sessionArray.GetSize(); ii++) {
  3049. pLogSession = (CLogSession *)m_sessionArray[ii];
  3050. if(NULL == pLogSession) {
  3051. continue;
  3052. }
  3053. //
  3054. // Set the log session's state
  3055. //
  3056. pLogSession->SetState(StateValue);
  3057. }
  3058. //
  3059. // Release the array protection
  3060. //
  3061. ReleaseMutex(m_hSessionArrayMutex);
  3062. ::PostMessage(m_hMainWnd, WM_USER_UPDATE_LOGSESSION_LIST, 0, 0);
  3063. }
  3064. //
  3065. // Macro to create our event callback functions. This is only
  3066. // necessary as there is no context we can pass into our event
  3067. // callback function. So, we setup a unique event callback for
  3068. // each log session. We have 64 here, but the number will have
  3069. // to increase to match the total number of possible loggers
  3070. //
  3071. #define MAKE_EVENT_CALLBACK(n) \
  3072. VOID WINAPI DumpEvent##n(PEVENT_TRACE pEvent) \
  3073. { \
  3074. CDisplayDlg *pDisplayDlg; \
  3075. g_displayIDToDisplayDlgHash.Lookup(n, (void *&)pDisplayDlg);\
  3076. if(NULL != pDisplayDlg) { \
  3077. pDisplayDlg->EventHandler(pEvent); \
  3078. } \
  3079. }
  3080. //
  3081. // Make 64 of them initially
  3082. //
  3083. MAKE_EVENT_CALLBACK(0);
  3084. MAKE_EVENT_CALLBACK(1);
  3085. MAKE_EVENT_CALLBACK(2);
  3086. MAKE_EVENT_CALLBACK(3);
  3087. MAKE_EVENT_CALLBACK(4);
  3088. MAKE_EVENT_CALLBACK(5);
  3089. MAKE_EVENT_CALLBACK(6);
  3090. MAKE_EVENT_CALLBACK(7);
  3091. MAKE_EVENT_CALLBACK(8);
  3092. MAKE_EVENT_CALLBACK(9);
  3093. MAKE_EVENT_CALLBACK(10);
  3094. MAKE_EVENT_CALLBACK(11);
  3095. MAKE_EVENT_CALLBACK(12);
  3096. MAKE_EVENT_CALLBACK(13);
  3097. MAKE_EVENT_CALLBACK(14);
  3098. MAKE_EVENT_CALLBACK(15);
  3099. MAKE_EVENT_CALLBACK(16);
  3100. MAKE_EVENT_CALLBACK(17);
  3101. MAKE_EVENT_CALLBACK(18);
  3102. MAKE_EVENT_CALLBACK(19);
  3103. MAKE_EVENT_CALLBACK(20);
  3104. MAKE_EVENT_CALLBACK(21);
  3105. MAKE_EVENT_CALLBACK(22);
  3106. MAKE_EVENT_CALLBACK(23);
  3107. MAKE_EVENT_CALLBACK(24);
  3108. MAKE_EVENT_CALLBACK(25);
  3109. MAKE_EVENT_CALLBACK(26);
  3110. MAKE_EVENT_CALLBACK(27);
  3111. MAKE_EVENT_CALLBACK(28);
  3112. MAKE_EVENT_CALLBACK(29);
  3113. MAKE_EVENT_CALLBACK(30);
  3114. MAKE_EVENT_CALLBACK(31);
  3115. MAKE_EVENT_CALLBACK(32);
  3116. MAKE_EVENT_CALLBACK(33);
  3117. MAKE_EVENT_CALLBACK(34);
  3118. MAKE_EVENT_CALLBACK(35);
  3119. MAKE_EVENT_CALLBACK(36);
  3120. MAKE_EVENT_CALLBACK(37);
  3121. MAKE_EVENT_CALLBACK(38);
  3122. MAKE_EVENT_CALLBACK(39);
  3123. MAKE_EVENT_CALLBACK(40);
  3124. MAKE_EVENT_CALLBACK(41);
  3125. MAKE_EVENT_CALLBACK(42);
  3126. MAKE_EVENT_CALLBACK(43);
  3127. MAKE_EVENT_CALLBACK(44);
  3128. MAKE_EVENT_CALLBACK(45);
  3129. MAKE_EVENT_CALLBACK(46);
  3130. MAKE_EVENT_CALLBACK(47);
  3131. MAKE_EVENT_CALLBACK(48);
  3132. MAKE_EVENT_CALLBACK(49);
  3133. MAKE_EVENT_CALLBACK(50);
  3134. MAKE_EVENT_CALLBACK(51);
  3135. MAKE_EVENT_CALLBACK(52);
  3136. MAKE_EVENT_CALLBACK(53);
  3137. MAKE_EVENT_CALLBACK(54);
  3138. MAKE_EVENT_CALLBACK(55);
  3139. MAKE_EVENT_CALLBACK(56);
  3140. MAKE_EVENT_CALLBACK(57);
  3141. MAKE_EVENT_CALLBACK(58);
  3142. MAKE_EVENT_CALLBACK(59);
  3143. MAKE_EVENT_CALLBACK(60);
  3144. MAKE_EVENT_CALLBACK(61);
  3145. MAKE_EVENT_CALLBACK(62);
  3146. MAKE_EVENT_CALLBACK(63);