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.

1048 lines
32 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. // Copyright (c) 2002 Microsoft Corporation. All rights reserved.
  3. // Copyright (c) 2002 OSR Open Systems Resources, Inc.
  4. //
  5. // LogSession.cpp : implementation of the CLogSession class
  6. //////////////////////////////////////////////////////////////////////////////
  7. #include "stdafx.h"
  8. #include <afxtempl.h>
  9. #include "DockDialogBar.h"
  10. #include <tchar.h>
  11. #include <wmistr.h>
  12. #include <initguid.h>
  13. #include <guiddef.h>
  14. extern "C" {
  15. #include <evntrace.h>
  16. #include "wppfmtstub.h"
  17. }
  18. #include <traceprt.h>
  19. #include "TraceView.h"
  20. #include "utils.h"
  21. #include "LogSession.h"
  22. #include "ListCtrlEx.h"
  23. #include "LogSessionDlg.h"
  24. #include "DisplayDlg.h"
  25. CTraceSession::CTraceSession(ULONG TraceSessionID)
  26. {
  27. m_traceSessionID = TraceSessionID;
  28. //
  29. // Initialize the temp directory
  30. //
  31. m_tempDirectory.Empty();
  32. //
  33. // Not using kernel logger unless selected by user
  34. //
  35. m_bKernelLogger = FALSE;
  36. }
  37. CTraceSession::~CTraceSession()
  38. {
  39. //
  40. // remove our working directory
  41. //
  42. ClearDirectory(m_tempDirectory);
  43. //
  44. // Now remove it
  45. //
  46. RemoveDirectory(m_tempDirectory);
  47. }
  48. BOOL CTraceSession::ProcessPdb()
  49. {
  50. CString traceDirectory;
  51. CString tempPath;
  52. CString tmfPath;
  53. CString tmcPath;
  54. CString providerName;
  55. CString temp;
  56. GUID directoryGuid;
  57. CFileFind fileFind;
  58. if(m_pdbFile.IsEmpty()) {
  59. return FALSE;
  60. }
  61. if(m_tempDirectory.IsEmpty()) {
  62. //
  63. // setup a special directory in which to create our files
  64. //
  65. traceDirectory = (LPCTSTR)((CTraceViewApp *)AfxGetApp())->m_traceDirectory;
  66. //
  67. // create our own unique directory under the temp directory
  68. //
  69. if(S_OK != CoCreateGuid(&directoryGuid)) {
  70. AfxMessageBox(_T("Failed To Create Temp Directory\nApplication Will Exit"));
  71. return FALSE;
  72. }
  73. GuidToString(directoryGuid, temp);
  74. traceDirectory += (LPCTSTR)temp;
  75. traceDirectory += (LPCTSTR)_T("\\");
  76. if(!CreateDirectory(traceDirectory, NULL)) {
  77. AfxMessageBox(_T("Failed To Create Temporary Directory For Trace Session"));
  78. return FALSE;
  79. }
  80. //
  81. // save the directory
  82. //
  83. m_tempDirectory = traceDirectory;
  84. }
  85. //
  86. // Clear the directory in case it already existed
  87. //
  88. ClearDirectory(m_tempDirectory);
  89. //
  90. // Now create the TMF and TMC files
  91. //
  92. if(!ParsePdb(m_pdbFile, m_tempDirectory)) {
  93. AfxMessageBox(_T("Failed To Parse PDB File"));
  94. return FALSE;
  95. }
  96. //
  97. // Get the control GUID for this provider
  98. //
  99. tmfPath = (LPCTSTR)m_tempDirectory;
  100. tmcPath = (LPCTSTR)m_tempDirectory;
  101. tmcPath +=_T("\\*.tmc");
  102. if(!fileFind.FindFile(tmcPath)) {
  103. AfxMessageBox(_T("Failed To Get Control GUID From PDB"));
  104. return FALSE;
  105. } else {
  106. while(fileFind.FindNextFile()) {
  107. tmcPath = fileFind.GetFileName();
  108. m_tmcFile.Add(tmcPath);
  109. }
  110. tmcPath = fileFind.GetFileName();
  111. m_tmcFile.Add(tmcPath);
  112. }
  113. if(m_tmcFile.GetSize() == 0) {
  114. AfxMessageBox(_T("No Control GUIDs Obtained From PDB"));
  115. return FALSE;
  116. }
  117. //
  118. // Pull the control GUID(s) from the name(s) of the TMC file(s),
  119. // this is a very backwards way of getting a GUID from a PDB
  120. // but its what we got
  121. //
  122. for(LONG ii = 0; ii < m_tmcFile.GetSize(); ii++) {
  123. m_controlGuid.Add(
  124. (LPCTSTR)m_tmcFile[ii].Left(m_tmcFile[ii].Find('.')));
  125. m_controlGuidFriendlyName.Add(m_pdbFile);
  126. }
  127. //
  128. // Now get the full path and name of the TMF file
  129. //
  130. tmfPath +=_T("\\*.tmf");
  131. if(!fileFind.FindFile(tmfPath)) {
  132. AfxMessageBox(_T("Failed To Get Format Information From PDB\nEvent Data Will Not Be Formatted"));
  133. } else {
  134. while(fileFind.FindNextFile()) {
  135. //
  136. // Get the trace event identifier GUID
  137. //
  138. tmfPath = (LPCTSTR)fileFind.GetFileName();
  139. if(!tmfPath.IsEmpty()) {
  140. //
  141. // Add format GUID
  142. //
  143. m_formatGuid.Add((LPCTSTR)tmfPath.Left(tmfPath.Find('.')));
  144. //
  145. // Add the TMF filename to the TMF path
  146. //
  147. tmfPath = (LPCTSTR)m_tempDirectory;
  148. tmfPath +=_T("\\");
  149. tmfPath += (LPCTSTR)fileFind.GetFileName();
  150. //
  151. // Store the TMF path
  152. //
  153. m_tmfFile.Add(tmfPath);
  154. }
  155. }
  156. //
  157. // Get the trace event identifier GUID
  158. //
  159. tmfPath = (LPCTSTR)fileFind.GetFileName();
  160. if(!tmfPath.IsEmpty()) {
  161. //
  162. // Add format GUID
  163. //
  164. m_formatGuid.Add((LPCTSTR)tmfPath.Left(tmfPath.Find('.')));
  165. //
  166. // Add the TMF filename to the TMF path
  167. //
  168. tmfPath = (LPCTSTR)m_tempDirectory;
  169. tmfPath +=_T("\\");
  170. tmfPath += (LPCTSTR)fileFind.GetFileName();
  171. //
  172. // Store the TMF path
  173. //
  174. m_tmfFile.Add(tmfPath);
  175. }
  176. }
  177. if(m_tmfFile.GetSize() == 0) {
  178. AfxMessageBox(_T("Failed To Get Format Information From PDB\nEvent Data Will Not Be Formatted"));
  179. }
  180. return TRUE;
  181. }
  182. CLogSession::CLogSession(ULONG LogSessionID, CLogSessionDlg *pLogSessionDlg)
  183. {
  184. //
  185. // Save the log session ID
  186. //
  187. m_logSessionID = LogSessionID;
  188. //
  189. // save the log session dialog pointer
  190. //
  191. m_pLogSessionDlg = pLogSessionDlg;
  192. CString str;
  193. str.Format(_T("m_pLogSession = %p"), this);
  194. //
  195. // initialize class members
  196. //
  197. m_pDisplayDialog = NULL;
  198. m_groupID = -1;
  199. m_bAppend = FALSE;
  200. m_bRealTime = TRUE;
  201. m_logFileName.Format(_T("LogSession%d.etl"), m_logSessionID);
  202. m_displayName.Format(_T("LogSession%d"), m_logSessionID);
  203. m_sessionHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE;
  204. m_bTraceActive = FALSE;
  205. m_bSessionActive = FALSE;
  206. m_bStoppingTrace = FALSE;
  207. m_bDisplayExistingLogFileOnly = FALSE;
  208. //
  209. // Initialize default log session parameter values
  210. //
  211. m_logSessionValues.Add("STOPPED"); // State
  212. m_logSessionValues.Add("0"); // Event Count
  213. m_logSessionValues.Add("0"); // Lost Event Count
  214. m_logSessionValues.Add("0"); // Event Buffers Read Count
  215. m_logSessionValues.Add("0xFFFF"); // Flags
  216. m_logSessionValues.Add("1"); // Flush time in seconds
  217. m_logSessionValues.Add("21"); // Maximum buffers
  218. m_logSessionValues.Add("4"); // Minimum buffers
  219. m_logSessionValues.Add("200"); // Buffer size in KB
  220. m_logSessionValues.Add("20"); // Decay value in minutes
  221. m_logSessionValues.Add(""); // Circular file size in MB
  222. m_logSessionValues.Add("200"); // Sequential file size in MB
  223. m_logSessionValues.Add(""); // New file after size in MB
  224. m_logSessionValues.Add("FALSE"); // Use global sequence numbers
  225. m_logSessionValues.Add("TRUE"); // Use local sequence numbers
  226. m_logSessionValues.Add("0"); // Level
  227. //
  228. // Set the default log session name color
  229. //
  230. m_titleTextColor = RGB(0,0,0);
  231. m_titleBackgroundColor = RGB(255,255,255);
  232. //
  233. // Default to writing no log file
  234. //
  235. m_bWriteLogFile = FALSE;
  236. }
  237. CLogSession::~CLogSession()
  238. {
  239. CTraceSession *pTraceSession;
  240. //
  241. // free the trace sessions
  242. //
  243. while(m_traceSessionArray.GetSize() > 0) {
  244. pTraceSession = (CTraceSession *)m_traceSessionArray[0];
  245. m_traceSessionArray.RemoveAt(0);
  246. if(NULL != pTraceSession) {
  247. delete pTraceSession;
  248. }
  249. }
  250. }
  251. VOID CLogSession::SetState(LOG_SESSION_STATE StateValue)
  252. {
  253. LONG index;
  254. CString stateText;
  255. switch(StateValue) {
  256. case Grouping:
  257. //
  258. // set the display text
  259. //
  260. stateText =_T("GROUPING");
  261. m_bGroupingTrace = TRUE;
  262. break;
  263. case UnGrouping:
  264. //
  265. // set the display text
  266. //
  267. stateText =_T("UNGROUPING");
  268. m_bGroupingTrace = TRUE;
  269. break;
  270. case Existing:
  271. //
  272. // set the display text
  273. //
  274. stateText =_T("EXISTING");
  275. //
  276. // Set our state to show a session is in progress
  277. //
  278. m_bTraceActive = TRUE;
  279. m_bGroupingTrace = FALSE;
  280. break;
  281. case Running:
  282. //
  283. // set the display text
  284. //
  285. stateText =_T("RUNNING");
  286. //
  287. // Set our state to show a session is in progress
  288. //
  289. m_bTraceActive = TRUE;
  290. m_bGroupingTrace = FALSE;
  291. break;
  292. case Stopping:
  293. if(m_logSessionValues[State].Compare(_T("GROUPING"))) {
  294. if(m_logSessionValues[State].Compare(_T("UNGROUPING"))) {
  295. if(!m_bDisplayExistingLogFileOnly) {
  296. //
  297. // set the display text
  298. //
  299. stateText =_T("STOPPING");
  300. }
  301. }
  302. }
  303. //
  304. // Indicate we are done stopping the trace
  305. //
  306. m_bStoppingTrace = TRUE;
  307. break;
  308. case Stopped:
  309. default:
  310. if(m_logSessionValues[State].Compare(_T("GROUPING"))) {
  311. if(m_logSessionValues[State].Compare(_T("UNGROUPING"))) {
  312. if(!m_bDisplayExistingLogFileOnly) {
  313. //
  314. // set the display text
  315. //
  316. stateText =_T("STOPPED");
  317. }
  318. }
  319. }
  320. //
  321. // Indicate we are done stopping the trace
  322. //
  323. m_bStoppingTrace = FALSE;
  324. //
  325. // Set our state to show a session is not in progress
  326. //
  327. m_bTraceActive = FALSE;
  328. break;
  329. }
  330. //
  331. // Save the state value
  332. //
  333. if(!stateText.IsEmpty()) {
  334. m_logSessionValues[State] = stateText;
  335. }
  336. }
  337. BOOL CLogSession::BeginTrace(BOOL bUseExisting)
  338. {
  339. ULONG ret;
  340. PEVENT_TRACE_PROPERTIES pProperties;
  341. PEVENT_TRACE_PROPERTIES pQueryProperties;
  342. TRACEHANDLE hSessionHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE;
  343. CString str;
  344. ULONG sizeNeeded;
  345. LPTSTR pLoggerName;
  346. LPTSTR pLogFileName;
  347. ULONG flags = 0;
  348. ULONG level;
  349. GUID controlGuid;
  350. LONG status;
  351. CTraceSession *pTraceSession;
  352. //
  353. // If we are just displaying an existing log file, then just set
  354. // the state and return
  355. //
  356. if(m_bDisplayExistingLogFileOnly) {
  357. SetState(Existing);
  358. return TRUE;
  359. }
  360. //
  361. // setup our buffer size for the properties struct
  362. //
  363. sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 500 * sizeof(TCHAR));
  364. pProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded];
  365. if(NULL == pProperties) {
  366. AfxMessageBox(_T("Failed To Start Trace, Out Of Resources"));
  367. return FALSE;
  368. }
  369. //
  370. // zero our structure
  371. //
  372. memset(pProperties, 0, sizeNeeded);
  373. pProperties->Wnode.BufferSize = sizeNeeded;
  374. pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  375. pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  376. pLoggerName = (LPTSTR)((char*)pProperties + pProperties->LoggerNameOffset);
  377. _tcscpy(pLoggerName, GetDisplayName());
  378. //
  379. // If using a log file, then set the parameters for it
  380. //
  381. if(m_bWriteLogFile) {
  382. pProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR));
  383. pLogFileName = (LPTSTR)((char*)pProperties + pProperties->LogFileNameOffset);
  384. _tcscpy(pLogFileName, (LPCTSTR)m_logFileName);
  385. //BUGBUG
  386. //
  387. // Can't have circular and sequential, so we favor circular
  388. // this probably needs to change in that we should limit the
  389. // user to only be able to pick one or the other.
  390. //
  391. if(!m_logSessionValues[Circular].IsEmpty()) {
  392. //
  393. // Deliver events to a circular log file.
  394. //
  395. pProperties->LogFileMode |= EVENT_TRACE_FILE_MODE_CIRCULAR;
  396. //
  397. // Circular log files should have a maximum size.
  398. //
  399. pProperties->MaximumFileSize = ConvertStringToNum(m_logSessionValues[Circular]);
  400. } else {
  401. //
  402. // Deliver events to a sequential log file.
  403. //
  404. pProperties->LogFileMode |= EVENT_TRACE_FILE_MODE_SEQUENTIAL;
  405. //
  406. // Sequential log files can have a maximum size.
  407. //
  408. pProperties->MaximumFileSize = ConvertStringToNum(m_logSessionValues[Sequential]);
  409. }
  410. //
  411. // Append to a current logfile.
  412. //
  413. if(m_bAppend) {
  414. pProperties->LogFileMode |= EVENT_TRACE_FILE_MODE_APPEND;
  415. }
  416. if(!m_logSessionValues[NewFile].IsEmpty()) {
  417. //
  418. // Use a new log file when the requested size of data is
  419. // received.
  420. //
  421. pProperties->LogFileMode |= EVENT_TRACE_FILE_MODE_NEWFILE;
  422. //
  423. // Data size.
  424. //
  425. pProperties->MaximumFileSize = ConvertStringToNum(m_logSessionValues[NewFile]);
  426. }
  427. }
  428. //
  429. // Set the session to generate real-time events
  430. //
  431. if(m_bRealTime) {
  432. pProperties->LogFileMode |= EVENT_TRACE_REAL_TIME_MODE;
  433. }
  434. //BUGBUG
  435. //
  436. // Again we should limit the user to select one or the other.
  437. // a session can only use global or local sequence numbers so
  438. // we favor global for now.
  439. //
  440. if(m_logSessionValues[GlobalSequence] == "TRUE") {
  441. //
  442. // Use global sequence numbers.
  443. //
  444. pProperties->LogFileMode |= EVENT_TRACE_USE_GLOBAL_SEQUENCE;
  445. } else if(m_logSessionValues[LocalSequence] == "TRUE") {
  446. //
  447. // Use local sequence numbers.
  448. //
  449. pProperties->LogFileMode |= EVENT_TRACE_USE_LOCAL_SEQUENCE;
  450. }
  451. //
  452. // Set the buffer settings.
  453. //
  454. pProperties->BufferSize = ConvertStringToNum(m_logSessionValues[BufferSize]);
  455. pProperties->MinimumBuffers = ConvertStringToNum(m_logSessionValues[MinimumBuffers]);
  456. pProperties->MaximumBuffers = ConvertStringToNum(m_logSessionValues[MaximumBuffers]);
  457. pProperties->FlushTimer = ConvertStringToNum(m_logSessionValues[FlushTime]);
  458. level = ConvertStringToNum(m_logSessionValues[Level]);
  459. pProperties->AgeLimit = ConvertStringToNum(m_logSessionValues[DecayTime]);
  460. //
  461. // get the trace enable flags
  462. //
  463. flags = ConvertStringToNum(m_logSessionValues[Flags]);
  464. pProperties->EnableFlags = flags;
  465. //
  466. // Start the session.
  467. //
  468. while(ERROR_SUCCESS != (ret = StartTrace(&hSessionHandle,
  469. GetDisplayName(),
  470. pProperties))) {
  471. if(ret != ERROR_ALREADY_EXISTS)
  472. {
  473. str.Format(_T("StartTrace failed: %d\n"), ret);
  474. AfxMessageBox(str);
  475. delete [] pProperties;
  476. //
  477. // Reset the session handle
  478. //
  479. SetSessionHandle((TRACEHANDLE)INVALID_HANDLE_VALUE);
  480. return FALSE;
  481. }
  482. if(bUseExisting) {
  483. SetState(Running);
  484. delete [] pProperties;
  485. return TRUE;
  486. }
  487. //
  488. // If the session is already active give the user a chance to kill
  489. // it and restart. (this will happen if the app dies while a log
  490. // session is active)
  491. //
  492. str.Format(_T("Warning: LogSession Already In Progress\n\nSelect Action:\n\n\tYes - Stop And Restart The Log Session\n\n\tNo - Join The Log Session Without Stopping\n\t (Session Will Be Unremovable/Unstoppable Without Restarting TraceView)\n\n\tCancel - Abort Start Operation"));
  493. ret = AfxMessageBox(str, MB_YESNOCANCEL);
  494. //
  495. // If joining an in progress session, we need to query and
  496. // get the correct values for the session
  497. //
  498. if(IDNO == ret) {
  499. //
  500. // setup our buffer size for the properties struct for our query
  501. //
  502. sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 1024 * sizeof(TCHAR));
  503. //
  504. // allocate our memory
  505. //
  506. pQueryProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded];
  507. if(NULL == pQueryProperties) {
  508. return FALSE;
  509. }
  510. //
  511. // zero our structures
  512. //
  513. memset(pQueryProperties, 0, sizeNeeded);
  514. //
  515. // Set the size
  516. //
  517. pQueryProperties->Wnode.BufferSize = sizeNeeded;
  518. //
  519. // Set the GUID
  520. //
  521. pQueryProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  522. //
  523. // Set the logger name offset
  524. //
  525. pQueryProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  526. //
  527. // Set the logger name for the query
  528. //
  529. pLoggerName = (LPTSTR)((char*)pQueryProperties + pQueryProperties->LoggerNameOffset);
  530. _tcscpy(pLoggerName, GetDisplayName());
  531. //
  532. // Set the log file name offset
  533. //
  534. pQueryProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR));
  535. //
  536. // Query the log session
  537. //
  538. status = ControlTrace(0,
  539. GetDisplayName(),
  540. pQueryProperties,
  541. EVENT_TRACE_CONTROL_QUERY);
  542. if(ERROR_SUCCESS == status) {
  543. if(pQueryProperties->LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) {
  544. m_logSessionValues[Circular].Format(_T("%d"), pQueryProperties->MaximumFileSize);
  545. m_logSessionValues[Sequential].Empty();
  546. m_logSessionValues[NewFile].Empty();
  547. }
  548. if(pQueryProperties->LogFileMode & EVENT_TRACE_FILE_MODE_SEQUENTIAL) {
  549. m_logSessionValues[Sequential].Format(_T("%d"), pQueryProperties->MaximumFileSize);
  550. m_logSessionValues[Circular].Empty();
  551. m_logSessionValues[NewFile].Empty();
  552. }
  553. if(pQueryProperties->LogFileMode & EVENT_TRACE_FILE_MODE_NEWFILE) {
  554. m_logSessionValues[NewFile].Format(_T("%d"), pQueryProperties->MaximumFileSize);
  555. m_logSessionValues[Circular].Empty();
  556. m_logSessionValues[Sequential].Empty();
  557. }
  558. if(pQueryProperties->LogFileMode & EVENT_TRACE_USE_GLOBAL_SEQUENCE) {
  559. m_logSessionValues[GlobalSequence].Format(_T("TRUE"));
  560. m_logSessionValues[LocalSequence].Format(_T("FALSE"));
  561. }
  562. if(pQueryProperties->LogFileMode & EVENT_TRACE_USE_LOCAL_SEQUENCE) {
  563. m_logSessionValues[GlobalSequence].Format(_T("FALSE"));
  564. m_logSessionValues[LocalSequence].Format(_T("TRUE"));
  565. }
  566. m_logSessionValues[BufferSize].Format(_T("%d"), pQueryProperties->BufferSize);
  567. m_logSessionValues[MinimumBuffers].Format(_T("%d"), pQueryProperties->MinimumBuffers);
  568. m_logSessionValues[MaximumBuffers].Format(_T("%d"), pQueryProperties->MaximumBuffers);
  569. m_logSessionValues[FlushTime].Format(_T("%d"), pQueryProperties->FlushTimer);
  570. m_logSessionValues[Level].Format(_T("%d"), pQueryProperties->Wnode.HistoricalContext);
  571. m_logSessionValues[DecayTime].Format(_T("%d"), pQueryProperties->AgeLimit);
  572. m_logSessionValues[Flags].Format(_T("0x%X"), pQueryProperties->EnableFlags);
  573. //
  574. // Now write the values out
  575. //
  576. //::PostMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_USER_UPDATE_LOGSESSION_DATA, (WPARAM)this, NULL);
  577. }
  578. hSessionHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE;
  579. break;
  580. }
  581. if(IDCANCEL == ret) {
  582. this->SetSessionHandle((TRACEHANDLE)INVALID_HANDLE_VALUE);
  583. return FALSE;
  584. }
  585. //
  586. // Stop the session, so it can be restarted.
  587. //
  588. ret = ControlTrace(hSessionHandle,
  589. GetDisplayName(),
  590. pProperties,
  591. EVENT_TRACE_CONTROL_STOP);
  592. }
  593. delete [] pProperties;
  594. //
  595. // Set the session state flag
  596. //
  597. m_bSessionActive = TRUE;
  598. //
  599. // Save the new session handle
  600. //
  601. SetSessionHandle(hSessionHandle);
  602. //
  603. // If the session handle is invalid, we are hooking up to
  604. // an already running session
  605. //
  606. if((TRACEHANDLE)INVALID_HANDLE_VALUE == (TRACEHANDLE)hSessionHandle) {
  607. SetState(Running);
  608. return TRUE;
  609. }
  610. //
  611. // Enable the trace(s)
  612. //
  613. for(LONG ii = 0; ii < m_traceSessionArray.GetSize(); ii++) {
  614. pTraceSession = (CTraceSession *)m_traceSessionArray[ii];
  615. if(pTraceSession == NULL) {
  616. continue;
  617. }
  618. //
  619. // Enable all trace providers for this log session
  620. //
  621. for(LONG jj = 0; jj < pTraceSession->m_controlGuid.GetSize(); jj++) {
  622. //
  623. // We don't have to enable the kernel logger, so check for it
  624. //
  625. if(!pTraceSession->m_bKernelLogger) {
  626. StringToGuid((LPTSTR)(LPCTSTR)pTraceSession->m_controlGuid[jj], &controlGuid);
  627. ret = EnableTrace(TRUE,
  628. flags,
  629. level,
  630. &controlGuid,
  631. hSessionHandle);
  632. if (ret != ERROR_SUCCESS)
  633. {
  634. if(ret == ERROR_INVALID_FUNCTION) {
  635. str.Format(_T("Failed To Enable Trace For Control GUID:\n%ls\n\nEnableTrace Returned %d\n\nThis Error Is Commonly Caused By Multiple Log Sessions\nAttempting To Solicit Events From A Single Provider"), pTraceSession->m_controlGuid[jj], ret);
  636. } else {
  637. str.Format(_T("Failed To Enable Trace For Control GUID:\n%ls\n\nEnableTrace Returned %d\n"), pTraceSession->m_controlGuid[jj], ret);
  638. }
  639. AfxMessageBox(str);
  640. }
  641. }
  642. }
  643. }
  644. SetState(Running);
  645. return TRUE;
  646. }
  647. //
  648. // Updates an active tracing session. Real-Time mode, log file name,
  649. // flush-time, flags, and maximum buffers can be updated.
  650. //
  651. BOOL CLogSession::UpdateSession(PEVENT_TRACE_PROPERTIES pQueryProperties)
  652. {
  653. PEVENT_TRACE_PROPERTIES pProperties;
  654. ULONG sizeNeeded;
  655. LPTSTR pLoggerName;
  656. LPTSTR pCurrentLogFileName;
  657. LPTSTR pLogFileName;
  658. ULONG flags;
  659. ULONG level;
  660. ULONG status;
  661. CString logFileName;
  662. CString str;
  663. //
  664. // setup our buffer size for the properties struct
  665. //
  666. sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 1024 * sizeof(TCHAR));
  667. //
  668. // allocate our memory
  669. //
  670. pProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded];
  671. if(NULL == pProperties) {
  672. return FALSE;
  673. }
  674. //
  675. // zero our structures
  676. //
  677. memset(pProperties, 0, sizeNeeded);
  678. //
  679. // Set the size
  680. //
  681. pProperties->Wnode.BufferSize = sizeNeeded;
  682. //
  683. // Set the GUID
  684. //
  685. pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  686. //
  687. // Set the logger name offset
  688. //
  689. pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  690. //
  691. // Set the log file name offset
  692. //
  693. pProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR));
  694. //
  695. // Get the log file name pointers
  696. //
  697. pLogFileName = (LPTSTR)((char*)pProperties + pProperties->LogFileNameOffset);
  698. //
  699. // Set the log file name
  700. //
  701. if(m_bWriteLogFile) {
  702. //
  703. // See if the logfile name is already specified and hasn't changed
  704. // ControlTrace will fail if you specify the same logfile name as it
  705. // is already using
  706. //
  707. if((NULL == pQueryProperties) ||
  708. (NULL == _tcsstr((LPTSTR)((char*)pQueryProperties + pQueryProperties->LogFileNameOffset), m_logFileName)) ||
  709. (NULL == (LPTSTR)((char*)pQueryProperties + pQueryProperties->LogFileNameOffset))) {
  710. _tcscpy(pLogFileName, (LPCTSTR)m_logFileName);
  711. }
  712. }
  713. //
  714. // Set the real-time setting.
  715. //
  716. if(m_bRealTime) {
  717. pProperties->LogFileMode |= EVENT_TRACE_REAL_TIME_MODE;
  718. }
  719. //
  720. // Set the max buffers setting.
  721. //
  722. pProperties->MaximumBuffers = ConvertStringToNum(m_logSessionValues[MaximumBuffers]);
  723. //
  724. // Set the enable flags setting.
  725. //
  726. flags = ConvertStringToNum(m_logSessionValues[Flags]);
  727. pProperties->EnableFlags = flags;
  728. //
  729. // Set the flush time setting.
  730. //
  731. pProperties->FlushTimer = ConvertStringToNum(m_logSessionValues[FlushTime]);
  732. //
  733. // Attempt to update the session
  734. //
  735. status = ControlTrace(0,
  736. GetDisplayName(),
  737. pProperties,
  738. EVENT_TRACE_CONTROL_UPDATE);
  739. if(ERROR_BAD_PATHNAME == status) {
  740. _tcscpy(pLogFileName,_T(""));
  741. //
  742. // If we get an ERROR_BAD_PATHNAME it means we specified the same
  743. // logfile name as the one we were already using. It seems the
  744. // tool should handle this, but it doesn't, so we just try again
  745. // with a blank logfilename. There is no way to clear a logfile
  746. // name from a session, so this seems to work.
  747. //
  748. status = ControlTrace(0,
  749. GetDisplayName(),
  750. pProperties,
  751. EVENT_TRACE_CONTROL_UPDATE);
  752. }
  753. if(ERROR_SUCCESS != status) {
  754. CString str;
  755. str.Format(_T("Failed To Update Session\nControlTrace failed with status %d"), status);
  756. AfxMessageBox(str);
  757. delete [] pProperties;
  758. return FALSE;
  759. }
  760. delete [] pProperties;
  761. return TRUE;
  762. }
  763. LONG CLogSession::EndTrace()
  764. {
  765. ULONG ret;
  766. PEVENT_TRACE_PROPERTIES pProperties;
  767. CString str;
  768. ULONG sizeNeeded;
  769. LPTSTR pLoggerName;
  770. LPTSTR pLogFileName;
  771. ULONG exitCode = STILL_ACTIVE;
  772. LONG startTime;
  773. TRACEHANDLE hSessionHandle = (TRACEHANDLE)INVALID_HANDLE_VALUE;
  774. LONG status;
  775. CTraceSession *pTraceSession;
  776. GUID controlGuid;
  777. //
  778. // If an attempt to stop this session has already been made, just return
  779. //
  780. if(m_bStoppingTrace || !m_bTraceActive) {
  781. return TRUE;
  782. }
  783. SetState(Stopping);
  784. //
  785. // If dealing with an existing log file we terminate the tracing later
  786. //
  787. if(m_bDisplayExistingLogFileOnly) {
  788. return TRUE;
  789. }
  790. //
  791. // Get our session handle
  792. //
  793. hSessionHandle = GetSessionHandle();
  794. //
  795. // If the session handle is invalid, we hooked up to
  796. // an already running session, so we can't stop the traces
  797. //
  798. if((TRACEHANDLE)INVALID_HANDLE_VALUE != hSessionHandle) {
  799. //
  800. // Disable the trace(s)
  801. //
  802. for(LONG ii = 0; ii < m_traceSessionArray.GetSize(); ii++) {
  803. pTraceSession = (CTraceSession *)m_traceSessionArray[ii];
  804. if(pTraceSession == NULL) {
  805. continue;
  806. }
  807. //
  808. // Disable all trace providers for this log session
  809. //
  810. for(LONG jj = 0; jj < pTraceSession->m_controlGuid.GetSize(); jj++) {
  811. StringToGuid((LPTSTR)(LPCTSTR)pTraceSession->m_controlGuid[jj], &controlGuid);
  812. ret = EnableTrace(FALSE,
  813. 0,
  814. 0,
  815. &controlGuid,
  816. hSessionHandle);
  817. if (ret != ERROR_SUCCESS)
  818. {
  819. if(ret == ERROR_INVALID_FUNCTION) {
  820. str.Format(_T("Failed To Disable Trace For Control GUID:\n%ls\n\nEnableTrace Returned %d"), pTraceSession->m_controlGuid[jj], ret);
  821. } else {
  822. str.Format(_T("Failed To Disable Trace For Control GUID:\n%ls\n\nEnableTrace Returned %d\n"), pTraceSession->m_controlGuid[jj], ret);
  823. }
  824. AfxMessageBox(str);
  825. }
  826. }
  827. }
  828. //
  829. // Calculate the size needed to store the properties,
  830. // a LogFileName string, and LoggerName string.
  831. //
  832. sizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + (2 * 500 * sizeof(TCHAR));
  833. pProperties = (PEVENT_TRACE_PROPERTIES) new char[sizeNeeded];
  834. if(NULL == pProperties) {
  835. AfxMessageBox(_T("Failed To Stop Trace, Out Of Resources"));
  836. return ERROR_OUTOFMEMORY;
  837. }
  838. //
  839. // zero our structure
  840. //
  841. memset(pProperties, 0, sizeNeeded);
  842. //
  843. // setup the struct
  844. //
  845. pProperties->Wnode.BufferSize = sizeNeeded;
  846. pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  847. pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  848. pLoggerName = (LPTSTR)((char*)pProperties + pProperties->LoggerNameOffset);
  849. _tcscpy(pLoggerName, GetDisplayName());
  850. if(m_bWriteLogFile) {
  851. pProperties->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + (500 * sizeof(TCHAR));
  852. pLogFileName = (LPTSTR)((char*)pProperties + pProperties->LogFileNameOffset);
  853. _tcscpy(pLogFileName, (LPCTSTR)m_logFileName);
  854. }
  855. //
  856. // The WNODE_HEADER is being used.
  857. //
  858. pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  859. //
  860. // end the trace session
  861. //
  862. ret = ControlTrace(hSessionHandle,
  863. (LPCTSTR)GetDisplayName(),
  864. pProperties,
  865. EVENT_TRACE_CONTROL_STOP);
  866. if(ERROR_SUCCESS != ret) {
  867. str.Format(_T("Failed To Stop Trace: %d, Session Handle = 0x%X"), ret, hSessionHandle);
  868. AfxMessageBox(str);
  869. }
  870. delete [] pProperties;
  871. }
  872. //
  873. // Set the session state flag
  874. //
  875. m_bSessionActive = FALSE;
  876. //
  877. // reset the session handle
  878. //
  879. SetSessionHandle((TRACEHANDLE)INVALID_HANDLE_VALUE);
  880. return ret;
  881. }