Source code of Windows XP (NT5)
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.

2862 lines
87 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. tracedmp.c
  5. Abstract:
  6. Sample trace consumer program. Converts binary
  7. Event Trace Log (ETL) to CSV format
  8. --*/
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <windows.h>
  12. #include <wbemidl.h>
  13. #include <shellapi.h>
  14. #include <tchar.h>
  15. #include <wmistr.h>
  16. #include <objbase.h>
  17. #include <initguid.h>
  18. #include <evntrace.h>
  19. #include <objidl.h>
  20. #define MAXLOGFILES 16
  21. #define MAXSTR 1024
  22. #define MOFWSTR 16360
  23. #define MOFSTR 32720
  24. #define MAXTYPE 256
  25. #define UC(x) ( (UINT)((x) & 0xFF) )
  26. #define NTOHS(x) ( (UC(x) * 256) + UC((x) >> 8) )
  27. // Maximum number of properties per WBEM class object: may need to be changed
  28. #define MAXPROPS 256
  29. #define DUMP_FILE_NAME _T("DumpFile.csv")
  30. #define SUMMARY_FILE_NAME _T("Summary.txt")
  31. #define DEFAULT_LOGFILE_NAME _T("C:\\Logfile.Etl")
  32. #define KERNEL_LOGGER_NAME _T("NT Kernel Logger")
  33. #define DEFAULT_NAMESPACE _T("root\\wmi")
  34. #define IsEqualGUID(rguid1, rguid2) (!memcmp(rguid1, rguid2, sizeof(GUID)))
  35. #define CHECK_WBEM_HR( hr ) if( WBEM_NO_ERROR != hr ){ WbemError(hr); goto cleanup; }
  36. #define InitializeListHead(ListHead) (\
  37. (ListHead)->Flink = (ListHead)->Blink = (ListHead))
  38. #define InsertTailList(ListHead,Entry) {\
  39. PLIST_ENTRY _EX_Blink;\
  40. PLIST_ENTRY _EX_ListHead;\
  41. _EX_ListHead = (ListHead);\
  42. _EX_Blink = _EX_ListHead->Blink;\
  43. (Entry)->Flink = _EX_ListHead;\
  44. (Entry)->Blink = _EX_Blink;\
  45. _EX_Blink->Flink = (Entry);\
  46. _EX_ListHead->Blink = (Entry);\
  47. }
  48. #define RemoveEntryList(Entry) {\
  49. PLIST_ENTRY _EX_Blink;\
  50. PLIST_ENTRY _EX_Flink;\
  51. _EX_Flink = (Entry)->Flink;\
  52. _EX_Blink = (Entry)->Blink;\
  53. _EX_Blink->Flink = _EX_Flink;\
  54. _EX_Flink->Blink = _EX_Blink;\
  55. }
  56. #define GUID_TYPE_EVENTTRACE _T("EventTrace")
  57. #define GUID_TYPE_HEADER _T("Header")
  58. #define GUID_TYPE_UNKNOWN _T("Unknown")
  59. #define GUID_TYPE_DEFAULT _T("Default")
  60. #define EVENT_TYPE_DEFAULT (-1)
  61. #define EVENT_LEVEL_DEFAULT (-1)
  62. #define EVENT_VERSION_DEFAULT (-1)
  63. #define STR_ItemChar _T("ItemChar")
  64. #define STR_ItemWChar _T("ItemWChar")
  65. #define STR_ItemUChar _T("ItemUChar")
  66. #define STR_ItemCharShort _T("ItemCharShort")
  67. #define STR_ItemShort _T("ItemShort")
  68. #define STR_ItemUShort _T("ItemUShort")
  69. #define STR_ItemLong _T("ItemLong")
  70. #define STR_ItemULong _T("ItemULong")
  71. #define STR_ItemULongX _T("ItemULongX")
  72. #define STR_ItemLongLong _T("ItemLongLong")
  73. #define STR_ItemULongLong _T("ItemULongLong")
  74. #define STR_ItemFloat _T("ItemFloat");
  75. #define STR_ItemDouble _T("ItemDouble");
  76. #define STR_ItemString _T("ItemString")
  77. #define STR_ItemWString _T("ItemWString")
  78. #define STR_ItemPString _T("ItemPString")
  79. #define STR_ItemPWString _T("ItemPWString")
  80. #define STR_ItemDSString _T("ItemDSString")
  81. #define STR_ItemDSWString _T("ItemDSWString")
  82. #define STR_ItemMLString _T("ItemMLString")
  83. #define STR_ItemSid _T("ItemSid")
  84. #define STR_ItemIPAddr _T("ItemIPAddr")
  85. #define STR_ItemPort _T("ItemPort")
  86. #define STR_ItemNWString _T("ItemNWString")
  87. #define STR_ItemPtr _T("ItemPtr")
  88. #define STR_ItemGuid _T("ItemGuid")
  89. #define STR_ItemBool _T("ItemBool")
  90. // Data types supported in this consumer.
  91. typedef enum _ITEM_TYPE {
  92. ItemChar,
  93. ItemWChar,
  94. ItemUChar,
  95. ItemCharShort,
  96. ItemShort,
  97. ItemUShort,
  98. ItemLong,
  99. ItemULong,
  100. ItemULongX,
  101. ItemLongLong,
  102. ItemULongLong,
  103. ItemFloat,
  104. ItemDouble,
  105. ItemString,
  106. ItemWString,
  107. ItemPString,
  108. ItemPWString,
  109. ItemDSString,
  110. ItemDSWString,
  111. ItemSid,
  112. ItemIPAddr,
  113. ItemPort,
  114. ItemMLString,
  115. ItemNWString, // Non-null terminated Wide Char String
  116. ItemPtr,
  117. ItemGuid,
  118. ItemBool,
  119. ItemUnknown
  120. } ITEM_TYPE;
  121. // Construct that represents an event layout
  122. typedef struct _MOF_INFO {
  123. LIST_ENTRY Entry;
  124. LPTSTR strDescription; // Class Name
  125. ULONG EventCount;
  126. GUID Guid;
  127. PLIST_ENTRY ItemHeader;
  128. LPTSTR strType; // Type Name
  129. SHORT TypeIndex;
  130. SHORT Version;
  131. CHAR Level;
  132. } MOF_INFO, *PMOF_INFO;
  133. typedef struct _ITEM_DESC *PITEM_DESC;
  134. // Construct that represents one data item
  135. typedef struct _ITEM_DESC {
  136. LIST_ENTRY Entry;
  137. LPTSTR strDescription;
  138. ULONG DataSize;
  139. ITEM_TYPE ItemType;
  140. UINT ArraySize;
  141. } ITEM_DESC;
  142. void
  143. PrintHelpMessage();
  144. PMOF_INFO
  145. GetNewMofInfo(
  146. GUID guid,
  147. SHORT nType,
  148. SHORT nVersion,
  149. CHAR nLevel
  150. );
  151. void
  152. AddMofInfo(
  153. PLIST_ENTRY List,
  154. LPTSTR strType,
  155. ITEM_TYPE nType,
  156. UINT ArraySize
  157. );
  158. HRESULT
  159. WbemConnect(
  160. IWbemServices** pWbemServices
  161. );
  162. ULONG GetArraySize(
  163. IN IWbemQualifierSet *pQualSet
  164. );
  165. ITEM_TYPE
  166. GetItemType(
  167. IN CIMTYPE_ENUMERATION CimType,
  168. IN IWbemQualifierSet *pQualSet
  169. );
  170. PMOF_INFO
  171. GetPropertiesFromWBEM(
  172. IWbemClassObject *pTraceSubClasses,
  173. GUID Guid,
  174. SHORT nVersion,
  175. CHAR nLevel,
  176. SHORT nType
  177. );
  178. PMOF_INFO
  179. GetGuids(
  180. GUID Guid,
  181. SHORT nVersion,
  182. CHAR nLevel,
  183. SHORT nType
  184. );
  185. ULONG
  186. ahextoi(
  187. TCHAR *s
  188. );
  189. PMOF_INFO
  190. GetMofInfoHead(
  191. GUID Guid,
  192. SHORT nType,
  193. SHORT nVersion,
  194. CHAR nLevel
  195. );
  196. ULONG
  197. CheckFile(
  198. LPTSTR fileName
  199. );
  200. void
  201. CleanupEventList(
  202. VOID
  203. );
  204. ULONG
  205. WINAPI
  206. BufferCallback(
  207. PEVENT_TRACE_LOGFILE pLog
  208. );
  209. void
  210. WINAPI
  211. DumpEvent(
  212. PEVENT_TRACE pEvent
  213. );
  214. void
  215. RemoveMofInfo(
  216. PLIST_ENTRY pMofInfo
  217. );
  218. void
  219. GuidToString(
  220. PTCHAR s,
  221. LPGUID piid
  222. );
  223. HRESULT
  224. ParseTime(
  225. LPTSTR strTime,
  226. SYSTEMTIME* pstTime
  227. );
  228. // output files
  229. FILE* DumpFile = NULL;
  230. FILE* SummaryFile = NULL;
  231. static ULONG TotalBuffersRead = 0;
  232. static ULONG TotalEventsLost = 0;
  233. static ULONG TotalEventCount = 0;
  234. static ULONG TimerResolution = 10;
  235. static ULONGLONG StartTime = 0;
  236. static ULONGLONG EndTime = 0;
  237. static BOOL fNoEndTime = FALSE;
  238. static __int64 ElapseTime;
  239. PCHAR MofData = NULL;
  240. size_t MofLength = 0;
  241. BOOLEAN fSummaryOnly = FALSE;
  242. BOOLEAN fDebugDisplay = FALSE;
  243. BOOLEAN fRealTimeCircular = FALSE;
  244. ULONG PointerSize = sizeof(PVOID) * 8;
  245. // Global head for event layout linked list
  246. PLIST_ENTRY EventListHead = NULL;
  247. // log files
  248. PEVENT_TRACE_LOGFILE EvmFile[MAXLOGFILES];
  249. ULONG LogFileCount = 0;
  250. BOOL g_bUserMode = FALSE;
  251. // cached Wbem pointer
  252. IWbemServices *pWbemServices = NULL;
  253. int __cdecl main (int argc, LPTSTR* argv)
  254. /*++
  255. Routine Description:
  256. It is the main function.
  257. Arguments:
  258. Usage: tracedmp [options] <EtlFile1 EtlFile2 ...>| [-h | -? | -help]
  259. -o <file> Output CSV file
  260. -rt [LoggerName] Realtime tracedmp from the logger [LoggerName]
  261. -summary Summary.txt only
  262. -begin HH:MM DD/MM/YY
  263. -end HH:MM DD/MM/YY
  264. -h
  265. -help
  266. -? Display usage information
  267. Return Value:
  268. Error Code defined in winerror.h : If the function succeeds,
  269. it returns ERROR_SUCCESS (== 0).
  270. --*/
  271. {
  272. TCHAR DumpFileName[MAXSTR];
  273. TCHAR SummaryFileName[MAXSTR];
  274. LPTSTR *targv;
  275. FILETIME ftStart;
  276. FILETIME ftEnd;
  277. SYSTEMTIME st;
  278. #ifdef UNICODE
  279. LPTSTR *cmdargv;
  280. #endif
  281. PEVENT_TRACE_LOGFILE pLogFile;
  282. ULONG Status = ERROR_SUCCESS;
  283. ULONG i, j;
  284. TRACEHANDLE HandleArray[MAXLOGFILES];
  285. #ifdef UNICODE
  286. if ((cmdargv = CommandLineToArgvW(
  287. GetCommandLineW(), // pointer to a command-line string
  288. &argc // receives the argument count
  289. )) == NULL)
  290. {
  291. return(GetLastError());
  292. };
  293. targv = cmdargv ;
  294. #else
  295. targv = argv;
  296. #endif
  297. RtlZeroMemory( &ftStart, sizeof(FILETIME) );
  298. RtlZeroMemory( &ftEnd, sizeof(FILETIME) );
  299. _tcscpy(DumpFileName, DUMP_FILE_NAME);
  300. _tcscpy(SummaryFileName, SUMMARY_FILE_NAME);
  301. while (--argc > 0) {
  302. ++targv;
  303. if (**targv == '-' || **targv == '/') { // argument found
  304. if( **targv == '/' ){
  305. **targv = '-';
  306. }
  307. if ( !_tcsicmp(targv[0], _T("-begin") )) {
  308. if (argc > 1) {
  309. if (targv[1][0] != '-' && targv[1][0] != '/') {
  310. TCHAR buffer[MAXSTR];
  311. _tcscpy( buffer, targv[1] );
  312. _tcscat( buffer, _T(" ") );
  313. ++targv; --argc;
  314. if (targv[1][0] != '-' && targv[1][0] != '/'){
  315. _tcscat( buffer, targv[1] );
  316. ParseTime( buffer, &st );
  317. SystemTimeToFileTime( &st, &ftStart );
  318. ++targv; --argc;
  319. }
  320. }
  321. }
  322. }
  323. else if ( !_tcsicmp(targv[0], _T("-end")) ) {
  324. if (argc > 1) {
  325. if (targv[1][0] != '-' && targv[1][0] != '/') {
  326. TCHAR buffer[MAXSTR];
  327. _tcscpy( buffer, targv[1] );
  328. _tcscat( buffer, _T(" ") );
  329. ++targv; --argc;
  330. if (targv[1][0] != '-' && targv[1][0] != '/'){
  331. _tcscat( buffer, targv[1] );
  332. ParseTime( buffer, &st );
  333. SystemTimeToFileTime( &st, &ftEnd );
  334. ++targv; --argc;
  335. }
  336. }
  337. }
  338. }
  339. else if ( !_tcsicmp(targv[0], _T("-summary")) ) {
  340. fSummaryOnly = TRUE;
  341. }
  342. else if ( !_tcsicmp(targv[0], _T("-debug")) ) {
  343. fDebugDisplay = TRUE;
  344. }
  345. else if ( !_tcsicmp(targv[0], _T("-RealTimeCircular")) ) {
  346. fRealTimeCircular = TRUE;
  347. }
  348. else if (targv[0][1] == 'h' || targv[0][1] == 'H'
  349. || targv[0][1] == '?')
  350. {
  351. PrintHelpMessage();
  352. return 0;
  353. }
  354. else if ( !_tcsicmp(targv[0], _T("-rt")) ) {
  355. TCHAR LoggerName[MAXSTR];
  356. _tcscpy(LoggerName, KERNEL_LOGGER_NAME);
  357. if (argc > 1) {
  358. if (targv[1][0] != '-' && targv[1][0] != '/') {
  359. ++targv; --argc;
  360. _tcscpy(LoggerName, targv[0]);
  361. }
  362. }
  363. pLogFile = (PEVENT_TRACE_LOGFILE) malloc(sizeof(EVENT_TRACE_LOGFILE));
  364. if (pLogFile == NULL){
  365. _tprintf(_T("Allocation Failure\n"));
  366. Status = ERROR_OUTOFMEMORY;
  367. goto cleanup;
  368. }
  369. RtlZeroMemory(pLogFile, sizeof(EVENT_TRACE_LOGFILE));
  370. EvmFile[LogFileCount] = pLogFile;
  371. EvmFile[LogFileCount]->LogFileName = NULL;
  372. EvmFile[LogFileCount]->LoggerName =
  373. (LPTSTR) malloc(MAXSTR*sizeof(TCHAR));
  374. if ( EvmFile[LogFileCount]->LoggerName == NULL ) {
  375. _tprintf(_T("Allocation Failure\n"));
  376. Status = ERROR_OUTOFMEMORY;
  377. goto cleanup;
  378. }
  379. _tcscpy(EvmFile[LogFileCount]->LoggerName, LoggerName);
  380. _tprintf(_T("Setting RealTime mode for %s\n"),
  381. EvmFile[LogFileCount]->LoggerName);
  382. EvmFile[LogFileCount]->Context = NULL;
  383. EvmFile[LogFileCount]->BufferCallback = BufferCallback;
  384. EvmFile[LogFileCount]->BuffersRead = 0;
  385. EvmFile[LogFileCount]->CurrentTime = 0;
  386. EvmFile[LogFileCount]->EventCallback = &DumpEvent;
  387. EvmFile[LogFileCount]->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
  388. LogFileCount++;
  389. }
  390. else if ( !_tcsicmp(targv[0], _T("-o")) ) {
  391. if (argc > 1) {
  392. if (targv[1][0] != '-' && targv[1][0] != '/') {
  393. TCHAR drive[10];
  394. TCHAR path[MAXSTR];
  395. TCHAR file[MAXSTR];
  396. TCHAR ext[MAXSTR];
  397. ++targv; --argc;
  398. _tfullpath(DumpFileName, targv[0], MAXSTR);
  399. _tsplitpath( DumpFileName, drive, path, file, ext );
  400. _tcscpy(ext,_T("csv"));
  401. _tmakepath( DumpFileName, drive, path, file, ext );
  402. _tcscpy(ext,_T("txt"));
  403. _tmakepath( SummaryFileName, drive, path, file, ext );
  404. }
  405. }
  406. }
  407. }
  408. else {
  409. pLogFile = (PEVENT_TRACE_LOGFILE) malloc(sizeof(EVENT_TRACE_LOGFILE));
  410. if (pLogFile == NULL){
  411. _tprintf(_T("Allocation Failure\n"));
  412. Status = ERROR_OUTOFMEMORY;
  413. goto cleanup;
  414. }
  415. RtlZeroMemory(pLogFile, sizeof(EVENT_TRACE_LOGFILE));
  416. EvmFile[LogFileCount] = pLogFile;
  417. EvmFile[LogFileCount]->LoggerName = NULL;
  418. EvmFile[LogFileCount]->LogFileName =
  419. (LPTSTR) malloc(MAXSTR*sizeof(TCHAR));
  420. if (EvmFile[LogFileCount]->LogFileName == NULL) {
  421. _tprintf(_T("Allocation Failure\n"));
  422. Status = ERROR_OUTOFMEMORY;
  423. goto cleanup;
  424. }
  425. _tfullpath(EvmFile[LogFileCount]->LogFileName, targv[0], MAXSTR);
  426. _tprintf(_T("Setting log file to: %s\n"),
  427. EvmFile[LogFileCount]->LogFileName);
  428. // If one of the log files is not readable, exit.
  429. if (!CheckFile(EvmFile[LogFileCount]->LogFileName)) {
  430. _tprintf(_T("Cannot open logfile for reading\n"));
  431. Status = ERROR_INVALID_PARAMETER;
  432. goto cleanup;
  433. }
  434. EvmFile[LogFileCount]->Context = NULL;
  435. EvmFile[LogFileCount]->BufferCallback = BufferCallback;
  436. EvmFile[LogFileCount]->BuffersRead = 0;
  437. EvmFile[LogFileCount]->CurrentTime = 0;
  438. EvmFile[LogFileCount]->EventCallback = &DumpEvent;
  439. LogFileCount++;
  440. }
  441. }
  442. if (LogFileCount <= 0) {
  443. PrintHelpMessage();
  444. return Status;
  445. }
  446. for (i = 0; i < LogFileCount; i++) {
  447. TRACEHANDLE x;
  448. if (fRealTimeCircular)
  449. EvmFile[i]->LogfileHeader.ReservedFlags |= 0x00000004;
  450. x = OpenTrace(EvmFile[i]);
  451. HandleArray[i] = x;
  452. if (HandleArray[i] == 0) {
  453. Status = GetLastError();
  454. _tprintf(_T("Error Opening Trace %d with status=%d\n"),
  455. i, Status);
  456. for (j = 0; j < i; j++)
  457. CloseTrace(HandleArray[j]);
  458. goto cleanup;
  459. }
  460. }
  461. if (!fSummaryOnly)
  462. {
  463. DumpFile = _tfopen(DumpFileName, _T("w"));
  464. if (DumpFile == NULL) {
  465. Status = ERROR_INVALID_PARAMETER;
  466. _tprintf(_T("DumpFile is NULL\n"));
  467. goto cleanup;
  468. }
  469. }
  470. SummaryFile = _tfopen(SummaryFileName, _T("w"));
  471. if (SummaryFile == NULL) {
  472. Status = ERROR_INVALID_PARAMETER;
  473. _tprintf(_T("SummaryFile is NULL\n"));
  474. goto cleanup;
  475. }
  476. if (!fSummaryOnly)
  477. {
  478. _ftprintf(DumpFile,
  479. _T("%12s, %10s,%7s,%21s,%11s,%11s, User Data\n"),
  480. _T("Event Name"), _T("Type"), _T("TID"), _T("Clock-Time"),
  481. _T("Kernel(ms)"), _T("User(ms)")
  482. );
  483. }
  484. Status = ProcessTrace(
  485. HandleArray,
  486. LogFileCount,
  487. &ftStart,
  488. &ftEnd
  489. );
  490. if (Status != ERROR_SUCCESS) {
  491. _tprintf(_T("Error processing with status=%dL (GetLastError=0x%x)\n"),
  492. Status, GetLastError());
  493. }
  494. for (j = 0; j < LogFileCount; j++){
  495. Status = CloseTrace(HandleArray[j]);
  496. if (Status != ERROR_SUCCESS) {
  497. _tprintf(_T("Error Closing Trace %d with status=%d\n"), j, Status);
  498. }
  499. }
  500. _ftprintf(SummaryFile,_T("Files Processed:\n"));
  501. for (i=0; i<LogFileCount; i++) {
  502. _ftprintf(SummaryFile,_T("\t%s\n"),EvmFile[i]->LogFileName);
  503. }
  504. ElapseTime = EndTime - StartTime;
  505. _ftprintf(SummaryFile,
  506. _T("Total Buffers Processed %d\n")
  507. _T("Total Events Processed %d\n")
  508. _T("Total Events Lost %d\n")
  509. _T("Start Time 0x%016I64X\n")
  510. _T("End Time 0x%016I64X\n")
  511. _T("Elapsed Time %I64d sec\n"),
  512. TotalBuffersRead,
  513. TotalEventCount,
  514. TotalEventsLost,
  515. StartTime,
  516. EndTime,
  517. (ElapseTime / 10000000) );
  518. _ftprintf(SummaryFile,
  519. _T("+-------------------------------------------------------------------------------------+\n")
  520. _T("|%10s %-20s %-10s %-36s |\n")
  521. _T("+-------------------------------------------------------------------------------------+\n"),
  522. _T("EventCount"),
  523. _T("EventName"),
  524. _T("EventType"),
  525. _T("Guid")
  526. );
  527. CleanupEventList();
  528. _ftprintf(SummaryFile,
  529. _T("+-------------------------------------------------------------------------------------+\n")
  530. );
  531. cleanup:
  532. if (!fSummaryOnly && DumpFile != NULL) {
  533. _tprintf(_T("Event traces dumped to %s\n"), DumpFileName);
  534. fclose(DumpFile);
  535. }
  536. if(SummaryFile != NULL){
  537. _tprintf(_T("Event Summary dumped to %s\n"), SummaryFileName);
  538. fclose(SummaryFile);
  539. }
  540. for (i = 0; i < LogFileCount; i ++)
  541. {
  542. if (EvmFile[i]->LoggerName != NULL)
  543. {
  544. free(EvmFile[i]->LoggerName);
  545. EvmFile[i]->LoggerName = NULL;
  546. }
  547. if (EvmFile[i]->LogFileName != NULL)
  548. {
  549. free(EvmFile[i]->LogFileName);
  550. EvmFile[i]->LogFileName = NULL;
  551. }
  552. free(EvmFile[i]);
  553. }
  554. #ifdef UNICODE
  555. GlobalFree(cmdargv);
  556. #endif
  557. SetLastError(Status);
  558. if(Status != ERROR_SUCCESS ){
  559. _tprintf(_T("Exit Status: %d\n"), Status);
  560. }
  561. if (MofData != NULL)
  562. free(MofData);
  563. return Status;
  564. }
  565. HRESULT
  566. ParseTime(
  567. LPTSTR strTime,
  568. SYSTEMTIME* pstTime
  569. )
  570. /*++
  571. Routine Description:
  572. Parse time given in a string into SYSTEMTIME.
  573. Arguments:
  574. strTime - String that shows time.
  575. pstTime - Struct to contain the parsed time information.
  576. Return Value:
  577. Error Code defined in winerror.h : If the function succeeds,
  578. it returns ERROR_SUCCESS (== 0).
  579. --*/
  580. {
  581. TCHAR buffer[MAXSTR];
  582. LPTSTR str, str2;
  583. ZeroMemory( pstTime, sizeof( SYSTEMTIME ) );
  584. if( pstTime == NULL ){
  585. return ERROR_BAD_ARGUMENTS;
  586. }
  587. _tcscpy( buffer, strTime );
  588. str = _tcstok( buffer, _T(" \n\t") );
  589. str2 = _tcstok( NULL, _T(" \n\t") );
  590. while( str ){
  591. if( _tcsstr( str, _T(":") ) ){
  592. LPTSTR strHour = _tcstok( str, _T(":") );
  593. LPTSTR strMinute = _tcstok( NULL, _T(":") );
  594. if( NULL != strHour ){
  595. pstTime->wHour = (USHORT)_ttoi( strHour );
  596. }
  597. if( NULL != strMinute ){
  598. pstTime->wMinute = (USHORT)_ttoi( strMinute );
  599. }
  600. }
  601. if( _tcsstr( str, _T("/") ) || _tcsstr( str, _T("\\") ) ){
  602. LPTSTR strMonth = _tcstok( str, _T("/\\") );
  603. LPTSTR strDay = _tcstok( NULL, _T("/\\") );
  604. LPTSTR strYear = _tcstok( NULL, _T("/\\") );
  605. if( NULL != strMonth ){
  606. pstTime->wMonth = (USHORT)_ttoi( strMonth );
  607. }
  608. if( NULL != strDay ){
  609. pstTime->wDay = (USHORT)_ttoi( strDay );
  610. }
  611. if( NULL != strYear ){
  612. pstTime->wYear = (USHORT)_ttoi( strYear );
  613. }
  614. }
  615. str = str2;
  616. str2 = NULL;
  617. }
  618. return ERROR_SUCCESS;
  619. }
  620. ULONG
  621. WINAPI
  622. BufferCallback(
  623. PEVENT_TRACE_LOGFILE pLog
  624. )
  625. /*++
  626. Routine Description:
  627. Callback method for processing a buffer. Does not do anything but
  628. updating global counters.
  629. Arguments:
  630. pLog - Pointer to a log file.
  631. Return Value:
  632. Always TRUE.
  633. --*/
  634. {
  635. TotalBuffersRead++;
  636. TotalEventsLost += pLog->EventsLost;
  637. return (TRUE);
  638. }
  639. void
  640. WINAPI
  641. DumpEvent(
  642. PEVENT_TRACE pEvent
  643. )
  644. /*++
  645. Routine Description:
  646. Callback method for processing an event. It obtains the layout
  647. information by calling GetMofInfoHead(), which returns the pointer
  648. to the PMOF_INFO corresponding to the event type. Then it writes
  649. to the output file.
  650. NOTE: Only character arrays are supported in this program.
  651. Arguments:
  652. pEvent - Pointer to an event.
  653. Return Value:
  654. None.
  655. --*/
  656. {
  657. PEVENT_TRACE_HEADER pHeader;
  658. ULONG i;
  659. PITEM_DESC pItem;
  660. char str[MOFSTR];
  661. WCHAR wstr[MOFWSTR];
  662. PCHAR ptr;
  663. ULONG ulongword;
  664. LONG longword;
  665. USHORT ushortword;
  666. SHORT shortword;
  667. PMOF_INFO pMofInfo;
  668. PLIST_ENTRY Head, Next;
  669. char iChar;
  670. WCHAR iwChar;
  671. ULONG MofDataUsed;
  672. TotalEventCount++;
  673. if (pEvent == NULL) {
  674. _tprintf(_T("Warning: Null Event\n"));
  675. return;
  676. }
  677. pHeader = (PEVENT_TRACE_HEADER) &pEvent->Header;
  678. if( IsEqualGUID(&(pEvent->Header.Guid), &EventTraceGuid) &&
  679. pEvent->Header.Class.Type == EVENT_TRACE_TYPE_INFO ) {
  680. PTRACE_LOGFILE_HEADER head = (PTRACE_LOGFILE_HEADER)pEvent->MofData;
  681. if( NULL != head ){
  682. g_bUserMode = (head->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE);
  683. if(head->TimerResolution > 0){
  684. TimerResolution = head->TimerResolution / 10000;
  685. }
  686. StartTime = head->StartTime.QuadPart;
  687. EndTime = head->EndTime.QuadPart;
  688. fNoEndTime = (EndTime == 0);
  689. PointerSize = head->PointerSize * 8;
  690. // Set pointer size
  691. if (PointerSize < 16){ // minimum is 16 bits
  692. PointerSize = 32; // default is 32 bits
  693. }
  694. }
  695. }
  696. if (fNoEndTime && EndTime < (ULONGLONG) pHeader->TimeStamp.QuadPart) {
  697. EndTime = pHeader->TimeStamp.QuadPart;
  698. }
  699. if (MofData == NULL) {
  700. MofLength = pEvent->MofLength + sizeof(UNICODE_NULL);
  701. MofData = (PCHAR) malloc(MofLength);
  702. }
  703. else if ((pEvent->MofLength + sizeof(UNICODE_NULL)) > MofLength) {
  704. MofLength = pEvent->MofLength + sizeof(UNICODE_NULL);
  705. MofData = (PCHAR) realloc(MofData, MofLength);
  706. }
  707. if (MofData == NULL) {
  708. _tprintf(_T("Allocation Failure\n"));
  709. return;
  710. }
  711. if (NULL == pEvent->MofData && pEvent->MofLength != 0) {
  712. _tprintf(_T("Incorrect MOF size\n"));
  713. return;
  714. }
  715. if (NULL != (pEvent->MofData)) {
  716. memcpy(MofData, pEvent->MofData, pEvent->MofLength);
  717. }
  718. MofData[pEvent->MofLength] = 0;
  719. MofData[pEvent->MofLength+1] = 0;
  720. ptr = MofData;
  721. MofDataUsed = 0;
  722. // Find the MOF information for this event
  723. pMofInfo = GetMofInfoHead (
  724. pEvent->Header.Guid,
  725. pEvent->Header.Class.Type,
  726. pEvent->Header.Class.Version,
  727. pEvent->Header.Class.Level
  728. );
  729. if( NULL == pMofInfo ){
  730. return;
  731. }
  732. pMofInfo->EventCount++;
  733. if( fSummaryOnly == TRUE ){
  734. return;
  735. }
  736. if( pMofInfo->strDescription != NULL ){
  737. _ftprintf( DumpFile, _T("%12s, "), pMofInfo->strDescription );
  738. }else{
  739. TCHAR strGuid[MAXSTR];
  740. GuidToString( strGuid, &pMofInfo->Guid );
  741. _ftprintf( DumpFile, _T("%12s, "), strGuid );
  742. }
  743. if(pMofInfo->strType != NULL && _tcslen(pMofInfo->strType) ){
  744. _ftprintf( DumpFile, _T("%10s, "), pMofInfo->strType );
  745. }else{
  746. _ftprintf( DumpFile, _T("%10d, "), pEvent->Header.Class.Type );
  747. }
  748. // Thread ID
  749. _ftprintf( DumpFile, _T("0x%04X, "), pHeader->ThreadId );
  750. // System Time
  751. _ftprintf( DumpFile, _T("%20I64u, "), pHeader->TimeStamp.QuadPart);
  752. if( g_bUserMode == FALSE ){
  753. // Kernel Time
  754. _ftprintf(DumpFile, _T("%10lu, "), pHeader->KernelTime * TimerResolution);
  755. // User Time
  756. _ftprintf(DumpFile, _T("%10lu, "), pHeader->UserTime * TimerResolution);
  757. }else{
  758. // processor Time
  759. _ftprintf(DumpFile, _T("%I64u, "), pHeader->ProcessorTime);
  760. }
  761. Head = pMofInfo->ItemHeader;
  762. Next = Head->Flink;
  763. if ((Head == Next) && (pEvent->MofLength > 0)) {
  764. _ftprintf(DumpFile, _T("DataSize=%d, "), pEvent->MofLength);
  765. }
  766. while (Head != Next) {
  767. pItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
  768. Next = Next->Flink;
  769. MofDataUsed = (ULONG) (ptr - MofData);
  770. if (MofDataUsed >= pEvent->MofLength){
  771. break;
  772. }
  773. switch (pItem->ItemType)
  774. {
  775. case ItemChar:
  776. case ItemUChar:
  777. for( i=0;i<pItem->ArraySize;i++){
  778. iChar = *((PCHAR) ptr);
  779. _ftprintf(DumpFile, _T("%c"), iChar);
  780. ptr += sizeof(CHAR);
  781. }
  782. _ftprintf(DumpFile, _T(", "));
  783. break;
  784. case ItemWChar:
  785. for(i=0;i<pItem->ArraySize;i++){
  786. iwChar = *((PWCHAR) ptr);
  787. _ftprintf(DumpFile, _T(",%wc"), iwChar);
  788. ptr += sizeof(WCHAR);
  789. }
  790. _ftprintf(DumpFile, _T(", "));
  791. break;
  792. case ItemCharShort:
  793. iChar = *((PCHAR) ptr);
  794. _ftprintf(DumpFile, _T("%d, "), iChar);
  795. ptr += sizeof(CHAR);
  796. break;
  797. case ItemShort:
  798. shortword = * ((PSHORT) ptr);
  799. _ftprintf(DumpFile, _T("%6d, "), shortword);
  800. ptr += sizeof (SHORT);
  801. break;
  802. case ItemUShort:
  803. ushortword = *((PUSHORT) ptr);
  804. _ftprintf(DumpFile, _T("%6u, "), ushortword);
  805. ptr += sizeof (USHORT);
  806. break;
  807. case ItemLong:
  808. longword = *((PLONG) ptr);
  809. _ftprintf(DumpFile, _T("%8d, "), longword);
  810. ptr += sizeof (LONG);
  811. break;
  812. case ItemULong:
  813. ulongword = *((PULONG) ptr);
  814. _ftprintf(DumpFile, _T("%8lu, "), ulongword);
  815. ptr += sizeof (ULONG);
  816. break;
  817. case ItemULongX:
  818. ulongword = *((PULONG) ptr);
  819. _ftprintf(DumpFile, _T("0x%08X, "), ulongword);
  820. ptr += sizeof (ULONG);
  821. break;
  822. case ItemLongLong:
  823. {
  824. LONGLONG n64;
  825. n64 = *((LONGLONG*) ptr);
  826. ptr += sizeof(LONGLONG);
  827. _ftprintf(DumpFile, _T("%16I64d, "), n64);
  828. break;
  829. }
  830. case ItemULongLong:
  831. {
  832. ULONGLONG n64;
  833. n64 = *((ULONGLONG*) ptr);
  834. ptr += sizeof(ULONGLONG);
  835. _ftprintf(DumpFile, _T("%16I64u, "), n64);
  836. break;
  837. }
  838. case ItemFloat:
  839. {
  840. float f32;
  841. f32 = *((float*) ptr);
  842. ptr += sizeof(float);
  843. _ftprintf(DumpFile, _T("%f, "), f32);
  844. break;
  845. }
  846. case ItemDouble:
  847. {
  848. double f64;
  849. f64 = *((double*) ptr);
  850. ptr += sizeof(double);
  851. _ftprintf(DumpFile, _T("%f, "), f64);
  852. break;
  853. }
  854. case ItemPtr :
  855. {
  856. unsigned __int64 pointer;
  857. if (PointerSize == 64) {
  858. pointer = *((unsigned __int64 *) ptr);
  859. _ftprintf(DumpFile, _T("0x%X, "), pointer);
  860. }
  861. else { // assumes 32 bit otherwise
  862. ulongword = *((PULONG) ptr);
  863. _ftprintf(DumpFile, _T("0x%08X, "), ulongword);
  864. }
  865. ptr += PointerSize / 8;
  866. //
  867. // If target source is Win64, then use Ptr, else use ulongword
  868. //
  869. break;
  870. }
  871. case ItemIPAddr:
  872. {
  873. ulongword = *((PULONG) ptr);
  874. // Convert it to readable form
  875. _ftprintf(DumpFile, _T("%03d.%03d.%03d.%03d, "),
  876. (ulongword >> 0) & 0xff,
  877. (ulongword >> 8) & 0xff,
  878. (ulongword >> 16) & 0xff,
  879. (ulongword >> 24) & 0xff);
  880. ptr += sizeof (ULONG);
  881. break;
  882. }
  883. case ItemPort:
  884. {
  885. _ftprintf(DumpFile, _T("%u, "), NTOHS((USHORT) *ptr));
  886. ptr += sizeof (USHORT);
  887. break;
  888. }
  889. case ItemString:
  890. {
  891. USHORT pLen = (USHORT)strlen((CHAR*) ptr);
  892. if (pLen > 0)
  893. {
  894. strcpy(str, ptr);
  895. for (i=pLen-1; i>0; i--) {
  896. if (str[i] == 0xFF)
  897. str[i] = 0;
  898. else break;
  899. }
  900. #ifdef UNICODE
  901. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  902. _ftprintf(DumpFile, _T("\"%ws\","), wstr);
  903. #else
  904. _ftprintf(DumpFile, _T("\"%s\","), str);
  905. #endif
  906. }
  907. ptr += (pLen + 1);
  908. break;
  909. }
  910. case ItemWString:
  911. {
  912. size_t pLen = 0;
  913. size_t i;
  914. if (*(WCHAR *) ptr)
  915. {
  916. pLen = ((wcslen((WCHAR*)ptr) + 1) * sizeof(WCHAR));
  917. memcpy(wstr, ptr, pLen);
  918. for (i = (pLen/2)-1; i > 0; i--)
  919. {
  920. if (((USHORT) wstr[i] == (USHORT) 0xFFFF))
  921. {
  922. wstr[i] = (USHORT) 0;
  923. }
  924. else break;
  925. }
  926. wstr[pLen / 2] = wstr[(pLen / 2) + 1]= '\0';
  927. _ftprintf(DumpFile, _T("\"%ws\","), wstr);
  928. }
  929. ptr += pLen;
  930. break;
  931. }
  932. case ItemDSString: // Counted String
  933. {
  934. USHORT pLen = (USHORT)(256 * ((USHORT) * ptr) + ((USHORT) * (ptr + 1)));
  935. ptr += sizeof(USHORT);
  936. if (pLen > (pEvent->MofLength - MofDataUsed - 1)) {
  937. pLen = (USHORT) (pEvent->MofLength - MofDataUsed - 1);
  938. }
  939. if (pLen > 0)
  940. {
  941. strcpy(str, ptr);
  942. #ifdef UNICODE
  943. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  944. fwprintf(DumpFile, _T("\"%ws\","), wstr);
  945. #else
  946. fprintf(DumpFile, _T("\"%s\","), str);
  947. #endif
  948. }
  949. ptr += (pLen + 1);
  950. break;
  951. }
  952. case ItemPString: // Counted String
  953. {
  954. USHORT pLen = * ((USHORT *) ptr);
  955. ptr += sizeof(USHORT);
  956. if (pLen > (pEvent->MofLength - MofDataUsed)) {
  957. pLen = (USHORT) (pEvent->MofLength - MofDataUsed);
  958. }
  959. if (pLen > MOFSTR * sizeof(CHAR)) {
  960. pLen = MOFSTR * sizeof(CHAR);
  961. }
  962. if (pLen > 0) {
  963. memcpy(str, ptr, pLen);
  964. str[pLen] = '\0';
  965. #ifdef UNICODE
  966. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  967. _ftprintf(DumpFile, _T("\"%ws\","), wstr);
  968. #else
  969. _ftprintf(DumpFile, _T("\"%s\","), str);
  970. #endif
  971. }
  972. ptr += pLen;
  973. break;
  974. }
  975. case ItemDSWString: // DS Counted Wide Strings
  976. case ItemPWString: // Counted Wide Strings
  977. {
  978. USHORT pLen = (USHORT)(( pItem->ItemType == ItemDSWString)
  979. ? (256 * ((USHORT) * ptr) + ((USHORT) * (ptr + 1)))
  980. : (* ((USHORT *) ptr)));
  981. ptr += sizeof(USHORT);
  982. if (pLen > (pEvent->MofLength - MofDataUsed)) {
  983. pLen = (USHORT) (pEvent->MofLength - MofDataUsed);
  984. }
  985. if (pLen > MOFWSTR * sizeof(WCHAR)) {
  986. pLen = MOFWSTR * sizeof(WCHAR);
  987. }
  988. if (pLen > 0) {
  989. memcpy(wstr, ptr, pLen);
  990. wstr[pLen / sizeof(WCHAR)] = L'\0';
  991. _ftprintf(DumpFile, _T("\"%ws\","), wstr);
  992. }
  993. ptr += pLen;
  994. break;
  995. }
  996. case ItemNWString: // Non Null Terminated String
  997. {
  998. USHORT Size;
  999. Size = (USHORT)(pEvent->MofLength - (ULONG)(ptr - MofData));
  1000. if( Size > MOFSTR )
  1001. {
  1002. Size = MOFSTR;
  1003. }
  1004. if (Size > 0)
  1005. {
  1006. memcpy(wstr, ptr, Size);
  1007. wstr[Size / 2] = '\0';
  1008. _ftprintf(DumpFile, _T("\"%ws\","), wstr);
  1009. }
  1010. ptr += Size;
  1011. break;
  1012. }
  1013. case ItemMLString: // Multi Line String
  1014. {
  1015. USHORT pLen;
  1016. char * src, * dest;
  1017. BOOL inQ = FALSE;
  1018. BOOL skip = FALSE;
  1019. UINT lineCount = 0;
  1020. ptr += sizeof(UCHAR) * 2;
  1021. pLen = (USHORT)strlen(ptr);
  1022. if (pLen > 0)
  1023. {
  1024. src = ptr;
  1025. dest = str;
  1026. while (* src != '\0'){
  1027. if (* src == '\n'){
  1028. if (!lineCount){
  1029. * dest++ = ' ';
  1030. }
  1031. lineCount++;
  1032. }else if (* src == '\"'){
  1033. if (inQ){
  1034. char strCount[32];
  1035. char * cpy;
  1036. sprintf(strCount, "{%dx}", lineCount);
  1037. cpy = & strCount[0];
  1038. while (* cpy != '\0'){
  1039. * dest ++ = * cpy ++;
  1040. }
  1041. }
  1042. inQ = !inQ;
  1043. }else if (!skip){
  1044. *dest++ = *src;
  1045. }
  1046. skip = (lineCount > 1 && inQ);
  1047. src++;
  1048. }
  1049. *dest = '\0';
  1050. #ifdef UNICODE
  1051. MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, MOFWSTR);
  1052. _ftprintf(DumpFile, _T("\"%ws\","), wstr);
  1053. #else
  1054. _ftprintf(DumpFile, _T("\"%s\","), str);
  1055. #endif
  1056. }
  1057. ptr += (pLen);
  1058. break;
  1059. }
  1060. case ItemSid:
  1061. {
  1062. TCHAR UserName[64];
  1063. TCHAR Domain[64];
  1064. TCHAR FullName[256];
  1065. ULONG asize = 0;
  1066. ULONG bsize = 0;
  1067. ULONG Sid[64];
  1068. PULONG pSid = & Sid[0];
  1069. SID_NAME_USE Se;
  1070. ULONG nSidLength;
  1071. pSid = (PULONG) ptr;
  1072. if (*pSid == 0){
  1073. ptr += 4;
  1074. _ftprintf(DumpFile, _T("%4d, "), *pSid);
  1075. }
  1076. else
  1077. {
  1078. ptr += 8; // skip the TOKEN_USER structure
  1079. nSidLength = 8 + (4*ptr[1]);
  1080. asize = 64;
  1081. bsize = 64;
  1082. if (LookupAccountSid(
  1083. NULL,
  1084. (PSID) ptr,
  1085. (LPTSTR) & UserName[0],
  1086. & asize,
  1087. (LPTSTR) & Domain[0],
  1088. & bsize,
  1089. & Se))
  1090. {
  1091. LPTSTR pFullName = &FullName[0];
  1092. _stprintf( pFullName,_T("\\\\%s\\%s"), Domain, UserName);
  1093. asize = (ULONG) _tcslen(pFullName);
  1094. if (asize > 0){
  1095. _ftprintf(DumpFile, _T("\"%s\", "), pFullName);
  1096. }
  1097. }
  1098. else
  1099. {
  1100. _ftprintf(DumpFile, _T("\"System\", "));
  1101. }
  1102. SetLastError( ERROR_SUCCESS );
  1103. ptr += nSidLength;
  1104. }
  1105. break;
  1106. }
  1107. case ItemGuid:
  1108. {
  1109. TCHAR s[64];
  1110. GuidToString(s, (LPGUID)ptr);
  1111. _ftprintf(DumpFile, _T("%s, "), s);
  1112. ptr += sizeof(GUID);
  1113. break;
  1114. }
  1115. case ItemBool:
  1116. {
  1117. BOOL Flag = (BOOL)*ptr;
  1118. _ftprintf(DumpFile, _T("%5s, "), (Flag) ? _T("TRUE") : _T("FALSE"));
  1119. ptr += sizeof(BOOL);
  1120. break;
  1121. }
  1122. default:
  1123. ptr += sizeof (int);
  1124. }
  1125. }
  1126. //Instance ID
  1127. _ftprintf(DumpFile, _T("%d,"), pEvent->InstanceId);
  1128. //Parent Instance ID
  1129. _ftprintf(DumpFile, _T("%d\n"), pEvent->ParentInstanceId);
  1130. }
  1131. ULONG
  1132. CheckFile(
  1133. LPTSTR fileName
  1134. )
  1135. /*++
  1136. Routine Description:
  1137. Checks whether a file exists and is readable.
  1138. Arguments:
  1139. fileName - File name.
  1140. Return Value:
  1141. Non-zero if the file exists and is readable. Zero otherwise.
  1142. --*/
  1143. {
  1144. HANDLE hFile;
  1145. ULONG Status;
  1146. hFile = CreateFile(
  1147. fileName,
  1148. GENERIC_READ,
  1149. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1150. NULL,
  1151. OPEN_EXISTING,
  1152. FILE_ATTRIBUTE_NORMAL,
  1153. NULL
  1154. );
  1155. Status = (hFile != INVALID_HANDLE_VALUE);
  1156. CloseHandle(hFile);
  1157. return Status;
  1158. }
  1159. PMOF_INFO
  1160. GetMofInfoHead(
  1161. GUID Guid,
  1162. SHORT nType,
  1163. SHORT nVersion,
  1164. CHAR nLevel
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. Find a matching event layout in the global linked list. If it
  1169. is not found in the list, it calls GetGuids() to examine the WBEM
  1170. namespace.
  1171. If the global list is empty, it first creates a header.
  1172. Arguments:
  1173. Guid - GUID for the event under consideration.
  1174. nType - Event Type
  1175. nVersion - Event Version
  1176. nLevel - Event Level (not supported in this program)
  1177. Return Value:
  1178. Pointer to MOF_INFO for the current event. If the layout
  1179. information is not found anywhere, GetMofInfoHead() creates
  1180. a dummy and returns it.
  1181. --*/
  1182. {
  1183. PLIST_ENTRY Head, Next;
  1184. PMOF_INFO pMofInfo;
  1185. PMOF_INFO pBestMatch = NULL;
  1186. SHORT nMatchLevel = 0;
  1187. SHORT nMatchCheck;
  1188. // Search the eventList for this Guid and find the head
  1189. if (EventListHead == NULL) {
  1190. // Initialize the MOF List and add the global header guid to it
  1191. EventListHead = (PLIST_ENTRY) malloc(sizeof(LIST_ENTRY));
  1192. if (EventListHead == NULL)
  1193. return NULL;
  1194. InitializeListHead(EventListHead);
  1195. pMofInfo = GetNewMofInfo( EventTraceGuid, EVENT_TYPE_DEFAULT, 0, 0 );
  1196. if( pMofInfo != NULL ){
  1197. InsertTailList( EventListHead, &pMofInfo->Entry );
  1198. pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(GUID_TYPE_EVENTTRACE)+1)*sizeof(TCHAR));
  1199. if( pMofInfo->strDescription != NULL ){
  1200. _tcscpy( pMofInfo->strDescription, GUID_TYPE_EVENTTRACE );
  1201. }
  1202. pMofInfo->strType = (LPTSTR)malloc((_tcslen(GUID_TYPE_HEADER)+1)*sizeof(TCHAR));
  1203. if( pMofInfo->strType != NULL ){
  1204. _tcscpy( pMofInfo->strType, GUID_TYPE_HEADER );
  1205. }
  1206. }
  1207. }
  1208. // Traverse the list and look for the Mof info head for this Guid.
  1209. Head = EventListHead;
  1210. Next = Head->Flink;
  1211. while (Head != Next) {
  1212. nMatchCheck = 0;
  1213. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1214. Next = Next->Flink;
  1215. if( IsEqualGUID(&pMofInfo->Guid, &Guid) ){
  1216. if( pMofInfo->TypeIndex == nType ){
  1217. nMatchCheck++;
  1218. }
  1219. if( pMofInfo->Version == nVersion ){
  1220. nMatchCheck++;
  1221. }
  1222. if( nMatchCheck == 2 ){ // Exact Match
  1223. return pMofInfo;
  1224. }
  1225. if( nMatchCheck > nMatchLevel ){ // Close Match
  1226. nMatchLevel = nMatchCheck;
  1227. pBestMatch = pMofInfo;
  1228. }
  1229. if( pMofInfo->TypeIndex == EVENT_TYPE_DEFAULT && // Total Guess
  1230. pBestMatch == NULL ){
  1231. pBestMatch = pMofInfo;
  1232. }
  1233. }
  1234. }
  1235. if(pBestMatch != NULL){
  1236. return pBestMatch;
  1237. }
  1238. // If one does not exist in the list, look it up in the file.
  1239. pMofInfo = GetGuids( Guid, nVersion, nLevel, nType );
  1240. // If still not found, create a unknown place holder
  1241. if( NULL == pMofInfo ){
  1242. pMofInfo = GetNewMofInfo( Guid, nType, nVersion, nLevel );
  1243. if( pMofInfo != NULL ){
  1244. pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(GUID_TYPE_UNKNOWN)+1)*sizeof(TCHAR));
  1245. if( pMofInfo->strDescription != NULL ){
  1246. _tcscpy( pMofInfo->strDescription, GUID_TYPE_UNKNOWN );
  1247. }
  1248. InsertTailList( EventListHead, &pMofInfo->Entry );
  1249. }
  1250. }
  1251. return pMofInfo;
  1252. }
  1253. void
  1254. RemoveMofInfo(
  1255. PLIST_ENTRY pMofInfo
  1256. )
  1257. /*++
  1258. Routine Description:
  1259. Removes and frees data item structs from a given list.
  1260. Arguments:
  1261. pMofInfo - Pointer to the MOF_INFO to be purged of data item structs.
  1262. Return Value:
  1263. None.
  1264. --*/
  1265. {
  1266. PLIST_ENTRY Head, Next;
  1267. PITEM_DESC pItem;
  1268. Head = pMofInfo;
  1269. Next = Head->Flink;
  1270. while (Head != Next) {
  1271. pItem = CONTAINING_RECORD(Next, ITEM_DESC, Entry);
  1272. Next = Next->Flink;
  1273. RemoveEntryList(&pItem->Entry);
  1274. free(pItem);
  1275. }
  1276. }
  1277. void
  1278. CleanupEventList(
  1279. VOID
  1280. )
  1281. /*++
  1282. Routine Description:
  1283. Cleans up a global event list.
  1284. Arguments:
  1285. Return Value:
  1286. None.
  1287. --*/
  1288. {
  1289. PLIST_ENTRY Head, Next;
  1290. PMOF_INFO pMofInfo;
  1291. TCHAR s[256];
  1292. TCHAR wstr[256];
  1293. PTCHAR str;
  1294. if (EventListHead == NULL) {
  1295. return;
  1296. }
  1297. Head = EventListHead;
  1298. Next = Head->Flink;
  1299. while (Head != Next) {
  1300. RtlZeroMemory(&wstr, 256);
  1301. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1302. if (pMofInfo->EventCount > 0) {
  1303. GuidToString(&s[0], &pMofInfo->Guid);
  1304. str = s;
  1305. if( pMofInfo->strDescription != NULL ){
  1306. _tcscpy( wstr, pMofInfo->strDescription );
  1307. }
  1308. _ftprintf(SummaryFile,_T("|%10d %-20s %-10s %36s|\n"),
  1309. pMofInfo->EventCount,
  1310. wstr,
  1311. pMofInfo->strType ? pMofInfo->strType : GUID_TYPE_DEFAULT,
  1312. str);
  1313. }
  1314. RemoveEntryList(&pMofInfo->Entry);
  1315. RemoveMofInfo(pMofInfo->ItemHeader);
  1316. free(pMofInfo->ItemHeader);
  1317. if (pMofInfo->strDescription != NULL)
  1318. free(pMofInfo->strDescription);
  1319. if (pMofInfo->strType != NULL)
  1320. free(pMofInfo->strType);
  1321. Next = Next->Flink;
  1322. free(pMofInfo);
  1323. }
  1324. free(EventListHead);
  1325. }
  1326. void
  1327. GuidToString(
  1328. PTCHAR s,
  1329. LPGUID piid
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. Converts a GUID into a string.
  1334. Arguments:
  1335. s - String that will have the converted GUID.
  1336. piid - GUID
  1337. Return Value:
  1338. None.
  1339. --*/
  1340. {
  1341. _stprintf(s, _T("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
  1342. piid->Data1, piid->Data2,
  1343. piid->Data3,
  1344. piid->Data4[0], piid->Data4[1],
  1345. piid->Data4[2], piid->Data4[3],
  1346. piid->Data4[4], piid->Data4[5],
  1347. piid->Data4[6], piid->Data4[7]);
  1348. return;
  1349. }
  1350. void
  1351. AddMofInfo(
  1352. PLIST_ENTRY List,
  1353. LPTSTR strType,
  1354. ITEM_TYPE nType,
  1355. UINT ArraySize
  1356. )
  1357. /*++
  1358. Routine Description:
  1359. Creates a data item information struct (ITEM_DESC) and appends
  1360. it to all MOF_INFOs in the given list.
  1361. GetPropertiesFromWBEM() creates a list of MOF_INFOs for multiple
  1362. types, stores them in a temporary list and calls this function for
  1363. each data item information it encounters.
  1364. Arguments:
  1365. List - List of MOF_INFOs.
  1366. strType - Item description in string.
  1367. nType - ITEM_TYPE defined at the beginning of this file.
  1368. ArraySize - Size of array of this type of items, if applicable.
  1369. Return Value:
  1370. None.
  1371. --*/
  1372. {
  1373. PITEM_DESC pItem;
  1374. PMOF_INFO pMofInfo;
  1375. PLIST_ENTRY Head = List;
  1376. PLIST_ENTRY Next = Head->Flink;
  1377. while (Head != Next) {
  1378. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1379. Next = Next->Flink;
  1380. if( NULL != pMofInfo ){
  1381. pItem = (PITEM_DESC) malloc(sizeof(ITEM_DESC));
  1382. if( NULL == pItem ){
  1383. return;
  1384. }
  1385. ZeroMemory( pItem, sizeof(ITEM_DESC) );
  1386. pItem->ItemType = nType;
  1387. pItem->ArraySize = ArraySize;
  1388. pItem->strDescription = (LPTSTR) malloc( (_tcslen(strType)+1)*sizeof(TCHAR));
  1389. if( NULL == pItem->strDescription ){
  1390. free( pItem );
  1391. return;
  1392. }
  1393. _tcscpy(pItem->strDescription, strType);
  1394. InsertTailList( (pMofInfo->ItemHeader), &pItem->Entry);
  1395. }
  1396. }
  1397. }
  1398. PMOF_INFO
  1399. GetNewMofInfo(
  1400. GUID guid,
  1401. SHORT nType,
  1402. SHORT nVersion,
  1403. CHAR nLevel
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. Creates a new MOF_INFO with given data.
  1408. Arguments:
  1409. guid - Event GUID.
  1410. nType - Event type.
  1411. nVersion - Event version.
  1412. nLevel - Event level (not supported in this program).
  1413. Return Value:
  1414. Pointer to the created MOF_INFO. NULL if malloc failed.
  1415. --*/
  1416. {
  1417. PMOF_INFO pMofInfo;
  1418. pMofInfo = (PMOF_INFO)malloc(sizeof(MOF_INFO));
  1419. if( NULL == pMofInfo ){
  1420. return NULL;
  1421. }
  1422. RtlZeroMemory(pMofInfo, sizeof(MOF_INFO));
  1423. memcpy(&pMofInfo->Guid, &guid, sizeof(GUID) );
  1424. pMofInfo->ItemHeader = (PLIST_ENTRY)malloc(sizeof(LIST_ENTRY));
  1425. if( NULL == pMofInfo->ItemHeader ){
  1426. free( pMofInfo );
  1427. return NULL;
  1428. }
  1429. InitializeListHead(pMofInfo->ItemHeader);
  1430. pMofInfo->TypeIndex = nType;
  1431. pMofInfo->Level = nLevel;
  1432. pMofInfo->Version = nVersion;
  1433. return pMofInfo;
  1434. }
  1435. void
  1436. FlushMofList(
  1437. PLIST_ENTRY ListHead
  1438. )
  1439. /*++
  1440. Routine Description:
  1441. Flushes MOF_INFOs in a temporary list into the global list.
  1442. Arguments:
  1443. ListHead - Pointer to the head of a temporary list.
  1444. Return Value:
  1445. None.
  1446. --*/
  1447. {
  1448. PMOF_INFO pMofInfo;
  1449. PLIST_ENTRY Head = ListHead;
  1450. PLIST_ENTRY Next = Head->Flink;
  1451. while( Head != Next ){
  1452. pMofInfo = CONTAINING_RECORD(Next, MOF_INFO, Entry);
  1453. Next = Next->Flink;
  1454. RemoveEntryList(&pMofInfo->Entry);
  1455. InsertTailList( EventListHead, &pMofInfo->Entry);
  1456. }
  1457. }
  1458. HRESULT
  1459. WbemConnect(
  1460. IWbemServices** pWbemServices
  1461. )
  1462. /*++
  1463. Routine Description:
  1464. Connects to WBEM and returns a pointer to WbemServices.
  1465. Arguments:
  1466. pWbemServices - Pointer to the connected WbemServices.
  1467. Return Value:
  1468. ERROR_SUCCESS if successful. Error flag otherwise.
  1469. --*/
  1470. {
  1471. IWbemLocator *pLocator = NULL;
  1472. BSTR bszNamespace = SysAllocString( L"root\\wmi" );
  1473. HRESULT hr = CoInitialize(0);
  1474. hr = CoCreateInstance(
  1475. CLSID_WbemLocator,
  1476. 0,
  1477. CLSCTX_INPROC_SERVER,
  1478. IID_IWbemLocator,
  1479. (LPVOID *) &pLocator
  1480. );
  1481. if ( ERROR_SUCCESS != hr )
  1482. goto cleanup;
  1483. hr = pLocator->ConnectServer(
  1484. bszNamespace,
  1485. NULL,
  1486. NULL,
  1487. NULL,
  1488. 0L,
  1489. NULL,
  1490. NULL,
  1491. pWbemServices
  1492. );
  1493. if ( ERROR_SUCCESS != hr )
  1494. goto cleanup;
  1495. hr = CoSetProxyBlanket(
  1496. *pWbemServices,
  1497. RPC_C_AUTHN_WINNT,
  1498. RPC_C_AUTHZ_NONE,
  1499. NULL,
  1500. RPC_C_AUTHN_LEVEL_PKT,
  1501. RPC_C_IMP_LEVEL_IMPERSONATE,
  1502. NULL,
  1503. EOAC_NONE
  1504. );
  1505. cleanup:
  1506. SysFreeString( bszNamespace );
  1507. if( pLocator ){
  1508. pLocator->Release();
  1509. pLocator = NULL;
  1510. }
  1511. return hr;
  1512. }
  1513. ULONG GetArraySize(
  1514. IN IWbemQualifierSet *pQualSet
  1515. )
  1516. /*++
  1517. Routine Description:
  1518. Examines a given qualifier set and returns the array size.
  1519. NOTE: WBEM stores the size of an array in "MAX" qualifier.
  1520. Arguments:
  1521. pQualSet - Pointer to a qualifier set.
  1522. Return Value:
  1523. The size of the array. The default is 1.
  1524. --*/
  1525. {
  1526. ULONG ArraySize = 1;
  1527. VARIANT pVal;
  1528. BSTR bszMaxLen;
  1529. HRESULT hRes;
  1530. if (pQualSet == NULL){
  1531. return ArraySize;
  1532. }
  1533. bszMaxLen = SysAllocString(L"MAX");
  1534. VariantInit(&pVal);
  1535. hRes = pQualSet->Get(bszMaxLen,
  1536. 0,
  1537. &pVal,
  1538. 0);
  1539. SysFreeString(bszMaxLen);
  1540. if (ERROR_SUCCESS == hRes && pVal.vt == VT_I4 ){
  1541. ArraySize = pVal.lVal;
  1542. }
  1543. VariantClear(&pVal);
  1544. return ArraySize;
  1545. }
  1546. ITEM_TYPE
  1547. GetItemType(
  1548. IN CIMTYPE_ENUMERATION CimType,
  1549. IN IWbemQualifierSet *pQualSet
  1550. )
  1551. /*++
  1552. Routine Description:
  1553. Examines a given qualifier set for a property and returns the type.
  1554. Arguments:
  1555. CimType - WBEM type (different from ITEM_TYPE) of a property.
  1556. pQualSet - Pointer to a qualifier set for a property under consideration.
  1557. Return Value:
  1558. The type (in ITEM_TYPE) of a property.
  1559. --*/
  1560. {
  1561. ITEM_TYPE Type;
  1562. VARIANT pVal;
  1563. HRESULT hRes;
  1564. BSTR bszQualName;
  1565. WCHAR strFormat[10];
  1566. WCHAR strTermination[30];
  1567. WCHAR strTemp[30];
  1568. BOOLEAN IsPointer = FALSE;
  1569. strFormat[0] = '\0';
  1570. strTermination[0] = '\0';
  1571. strTemp[0] = '\0';
  1572. if (pQualSet == NULL)
  1573. return ItemUnknown;
  1574. bszQualName = SysAllocString(L"format");
  1575. VariantInit(&pVal);
  1576. hRes = pQualSet->Get(bszQualName,
  1577. 0,
  1578. &pVal,
  1579. 0);
  1580. SysFreeString(bszQualName);
  1581. if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
  1582. wcscpy(strFormat, pVal.bstrVal);
  1583. bszQualName = SysAllocString(L"StringTermination");
  1584. VariantClear(&pVal);
  1585. hRes = pQualSet->Get(bszQualName,
  1586. 0,
  1587. &pVal,
  1588. 0);
  1589. SysFreeString(bszQualName);
  1590. if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
  1591. wcscpy(strTermination, pVal.bstrVal);
  1592. bszQualName = SysAllocString(L"pointer");
  1593. VariantClear(&pVal);
  1594. hRes = pQualSet->Get(bszQualName,
  1595. 0,
  1596. &pVal,
  1597. 0);
  1598. SysFreeString(bszQualName);
  1599. if (ERROR_SUCCESS == hRes)
  1600. IsPointer = TRUE;
  1601. // Major fix required to get rid of temp
  1602. bszQualName = SysAllocString(L"extension");
  1603. VariantClear(&pVal);
  1604. hRes = pQualSet->Get(bszQualName,
  1605. 0,
  1606. &pVal,
  1607. 0);
  1608. SysFreeString(bszQualName);
  1609. if (ERROR_SUCCESS == hRes && NULL != pVal.bstrVal)
  1610. wcscpy(strTemp, pVal.bstrVal);
  1611. VariantClear(&pVal);
  1612. CimType = (CIMTYPE_ENUMERATION)(CimType & (~CIM_FLAG_ARRAY));
  1613. switch (CimType) {
  1614. case CIM_EMPTY:
  1615. Type = ItemUnknown;
  1616. break;
  1617. case CIM_SINT8:
  1618. Type = ItemCharShort;
  1619. if (!_wcsicmp(strFormat, L"c")){
  1620. Type = ItemChar;
  1621. }
  1622. break;
  1623. case CIM_UINT8:
  1624. Type = ItemUChar;
  1625. break;
  1626. case CIM_SINT16:
  1627. Type = ItemShort;
  1628. break;
  1629. case CIM_UINT16:
  1630. Type = ItemUShort;
  1631. break;
  1632. case CIM_SINT32:
  1633. Type = ItemLong;
  1634. break;
  1635. case CIM_UINT32:
  1636. Type = ItemULong;
  1637. if (!_wcsicmp(strFormat, L"x")){
  1638. Type = ItemULongX;
  1639. }
  1640. break;
  1641. case CIM_SINT64:
  1642. Type = ItemLongLong;
  1643. break;
  1644. case CIM_UINT64:
  1645. Type = ItemULongLong;
  1646. break;
  1647. case CIM_REAL32:
  1648. Type = ItemFloat;
  1649. break;
  1650. case CIM_REAL64:
  1651. Type = ItemDouble;
  1652. break;
  1653. case CIM_BOOLEAN:
  1654. // ItemBool
  1655. Type = ItemBool;
  1656. break;
  1657. case CIM_STRING:
  1658. if (!_wcsicmp(strTermination, L"NullTerminated")) {
  1659. if (!_wcsicmp(strFormat, L"w"))
  1660. Type = ItemWString;
  1661. else
  1662. Type = ItemString;
  1663. }
  1664. else if (!_wcsicmp(strTermination, L"Counted")) {
  1665. if (!_wcsicmp(strFormat, L"w"))
  1666. Type = ItemPWString;
  1667. else
  1668. Type = ItemPString;
  1669. }
  1670. else if (!_wcsicmp(strTermination, L"ReverseCounted")) {
  1671. if (!_wcsicmp(strFormat, L"w"))
  1672. Type = ItemDSWString;
  1673. else
  1674. Type = ItemDSString;
  1675. }
  1676. else if (!_wcsicmp(strTermination, L"NotCounted")) {
  1677. Type = ItemNWString;
  1678. }else{
  1679. Type = ItemString;
  1680. }
  1681. break;
  1682. case CIM_CHAR16:
  1683. // ItemWChar
  1684. Type = ItemWChar;
  1685. break;
  1686. case CIM_OBJECT :
  1687. if (!_wcsicmp(strTemp, L"Port"))
  1688. Type = ItemPort;
  1689. else if (!_wcsicmp(strTemp, L"IPAddr"))
  1690. Type = ItemIPAddr;
  1691. else if (!_wcsicmp(strTemp, L"Sid"))
  1692. Type = ItemSid;
  1693. else if (!_wcsicmp(strTemp, L"Guid"))
  1694. Type = ItemGuid;
  1695. break;
  1696. case CIM_DATETIME:
  1697. case CIM_REFERENCE:
  1698. case CIM_ILLEGAL:
  1699. default:
  1700. Type = ItemUnknown;
  1701. break;
  1702. }
  1703. if (IsPointer)
  1704. Type = ItemPtr;
  1705. return Type;
  1706. }
  1707. PMOF_INFO
  1708. GetPropertiesFromWBEM(
  1709. IWbemClassObject *pTraceSubClasses,
  1710. GUID Guid,
  1711. SHORT nVersion,
  1712. CHAR nLevel,
  1713. SHORT nType
  1714. )
  1715. /*++
  1716. Routine Description:
  1717. Constructs a linked list with the information read from the WBEM
  1718. namespace, given the WBEM pointer to the version subtree. It enumerates
  1719. through all type classes in WBEM, and constructs MOF_INFOs for all of
  1720. them (for caching purpose). Meanwhile, it looks for the event layout
  1721. that mathces the passed event, and returns the pointer to the matching
  1722. MOF_INFO at the end.
  1723. Arguments:
  1724. pTraceSubClasses - WBEM pointer to the version subtree.
  1725. Guid - GUID of the passed event.
  1726. nVersion - version of the passed event.
  1727. nLevel - level of the passed event.
  1728. nType - type of the passed event.
  1729. Return Value:
  1730. Pointer to MOF_INFO corresponding to the passed event.
  1731. If the right type is not found, it returns the pointer to
  1732. the generic MOF_INFO for the event version.
  1733. --*/
  1734. {
  1735. IEnumWbemClassObject *pEnumTraceSubSubClasses = NULL;
  1736. IWbemClassObject *pTraceSubSubClasses = NULL;
  1737. IWbemQualifierSet *pQualSet = NULL;
  1738. PMOF_INFO pMofInfo = NULL, pMofLookup = NULL, pMofTemplate = NULL;
  1739. BSTR bszClassName = NULL;
  1740. BSTR bszSubClassName = NULL;
  1741. BSTR bszWmiDataId = NULL;
  1742. BSTR bszEventType = NULL;
  1743. BSTR bszEventTypeName = NULL;
  1744. BSTR bszFriendlyName = NULL;
  1745. BSTR bszPropName = NULL;
  1746. TCHAR strClassName[MAXSTR];
  1747. TCHAR strType[MAXSTR];
  1748. #ifndef UNICODE
  1749. CHAR TempString[MAXSTR];
  1750. #endif
  1751. LONG pVarType;
  1752. SHORT nEventType = EVENT_TYPE_DEFAULT;
  1753. LIST_ENTRY ListHead;
  1754. HRESULT hRes;
  1755. VARIANT pVal;
  1756. VARIANT pTypeVal;
  1757. VARIANT pTypeNameVal;
  1758. VARIANT pClassName;
  1759. ULONG lEventTypeWbem;
  1760. ULONG HUGEP *pTypeData;
  1761. BSTR HUGEP *pTypeNameData;
  1762. SAFEARRAY *PropArray = NULL;
  1763. SAFEARRAY *TypeArray = NULL;
  1764. SAFEARRAY *TypeNameArray = NULL;
  1765. long lLower, lUpper, lCount, IdIndex;
  1766. long lTypeLower, lTypeUpper;
  1767. long lTypeNameLower, lTypeNameUpper;
  1768. ULONG ArraySize;
  1769. ITEM_TYPE ItemType;
  1770. InitializeListHead(&ListHead);
  1771. VariantInit(&pVal);
  1772. VariantInit(&pTypeVal);
  1773. VariantInit(&pTypeNameVal);
  1774. VariantInit(&pClassName);
  1775. bszClassName = SysAllocString(L"__CLASS");
  1776. bszWmiDataId = SysAllocString(L"WmiDataId");
  1777. bszEventType = SysAllocString(L"EventType");
  1778. bszEventTypeName = SysAllocString(L"EventTypeName");
  1779. bszFriendlyName = SysAllocString(L"DisplayName");
  1780. hRes = pTraceSubClasses->Get(bszClassName, // property name
  1781. 0L,
  1782. &pVal, // output to this variant
  1783. NULL,
  1784. NULL);
  1785. if (ERROR_SUCCESS == hRes){
  1786. if (pQualSet) {
  1787. pQualSet->Release();
  1788. pQualSet = NULL;
  1789. }
  1790. // Get Qualifier Set to obtain the friendly name.
  1791. pTraceSubClasses->GetQualifierSet(&pQualSet);
  1792. hRes = pQualSet->Get(bszFriendlyName,
  1793. 0,
  1794. &pClassName,
  1795. 0);
  1796. if (ERROR_SUCCESS == hRes && pClassName.bstrVal != NULL) {
  1797. #ifdef UNICODE
  1798. wcscpy(strClassName, pClassName.bstrVal);
  1799. #else
  1800. WideCharToMultiByte(CP_ACP,
  1801. 0,
  1802. pClassName.bstrVal,
  1803. wcslen(pClassName.bstrVal),
  1804. TempString,
  1805. (MAXSTR * sizeof(CHAR)),
  1806. NULL,
  1807. NULL
  1808. );
  1809. strcpy(strClassName, TempString);
  1810. strClassName[wcslen(pClassName.bstrVal)] = '\0';
  1811. #endif
  1812. }
  1813. else {
  1814. #ifdef UNICODE
  1815. strClassName[0] = L'\0';
  1816. #else
  1817. strClassName[0] = '\0';
  1818. #endif
  1819. }
  1820. // Put Event Header
  1821. pMofInfo = GetNewMofInfo(Guid,
  1822. EVENT_TYPE_DEFAULT,
  1823. EVENT_VERSION_DEFAULT,
  1824. EVENT_LEVEL_DEFAULT
  1825. );
  1826. if (pMofInfo != NULL) {
  1827. pMofTemplate = pMofInfo;
  1828. pMofLookup = pMofInfo;
  1829. InsertTailList(&ListHead, &pMofInfo->Entry);
  1830. pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(strClassName) + 1) * sizeof(TCHAR));
  1831. if (NULL != pMofInfo->strDescription) {
  1832. _tcscpy(pMofInfo->strDescription, strClassName);
  1833. }
  1834. }
  1835. else{
  1836. goto cleanup;
  1837. }
  1838. // Create an enumerator to find derived classes.
  1839. bszSubClassName = SysAllocString(pVal.bstrVal);
  1840. hRes = pWbemServices->CreateClassEnum (
  1841. bszSubClassName, // class name
  1842. WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS, // shallow search
  1843. NULL,
  1844. &pEnumTraceSubSubClasses
  1845. );
  1846. SysFreeString ( bszSubClassName );
  1847. if (ERROR_SUCCESS == hRes) {
  1848. ULONG uReturnedSub = 1;
  1849. while(uReturnedSub == 1){
  1850. // For each event in the subclass
  1851. pTraceSubSubClasses = NULL;
  1852. hRes = pEnumTraceSubSubClasses->Next(5000, // timeout in five seconds
  1853. 1, // return just one instance
  1854. &pTraceSubSubClasses, // pointer to a Sub class
  1855. &uReturnedSub); // number obtained: one
  1856. if (ERROR_SUCCESS == hRes && uReturnedSub == 1) {
  1857. if (pQualSet) {
  1858. pQualSet->Release();
  1859. pQualSet = NULL;
  1860. }
  1861. // Get Qualifier Set.
  1862. pTraceSubSubClasses->GetQualifierSet(&pQualSet);
  1863. // Get Type number among Qualifiers
  1864. VariantClear(&pTypeVal);
  1865. hRes = pQualSet->Get(bszEventType,
  1866. 0,
  1867. &pTypeVal,
  1868. 0);
  1869. if (ERROR_SUCCESS == hRes) {
  1870. TypeArray = NULL;
  1871. TypeNameArray = NULL;
  1872. if (pTypeVal.vt & VT_ARRAY) { // EventType is an array
  1873. TypeArray = pTypeVal.parray;
  1874. VariantClear(&pTypeNameVal);
  1875. hRes = pQualSet->Get(bszEventTypeName,
  1876. 0,
  1877. &pTypeNameVal,
  1878. 0);
  1879. if ((ERROR_SUCCESS == hRes) && (pTypeNameVal.vt & VT_ARRAY)) {
  1880. TypeNameArray = pTypeNameVal.parray;
  1881. }
  1882. if (TypeArray != NULL) {
  1883. hRes = SafeArrayGetLBound(TypeArray, 1, &lTypeLower);
  1884. if (ERROR_SUCCESS != hRes) {
  1885. break;
  1886. }
  1887. hRes = SafeArrayGetUBound(TypeArray, 1, &lTypeUpper);
  1888. if (ERROR_SUCCESS != hRes) {
  1889. break;
  1890. }
  1891. if (lTypeUpper < 0) {
  1892. break;
  1893. }
  1894. SafeArrayAccessData(TypeArray, (void HUGEP **)&pTypeData );
  1895. if (TypeNameArray != NULL) {
  1896. hRes = SafeArrayGetLBound(TypeNameArray, 1, &lTypeNameLower);
  1897. if (ERROR_SUCCESS != hRes) {
  1898. break;
  1899. }
  1900. hRes = SafeArrayGetUBound(TypeNameArray, 1, &lTypeNameUpper);
  1901. if (ERROR_SUCCESS != hRes) {
  1902. break;
  1903. }
  1904. if (lTypeNameUpper < 0)
  1905. break;
  1906. SafeArrayAccessData(TypeNameArray, (void HUGEP **)&pTypeNameData );
  1907. }
  1908. for (lCount = lTypeLower; lCount <= lTypeUpper; lCount++) {
  1909. lEventTypeWbem = pTypeData[lCount];
  1910. nEventType = (SHORT)lEventTypeWbem;
  1911. pMofInfo = GetNewMofInfo(Guid, nEventType, nVersion, nLevel);
  1912. if (pMofInfo != NULL) {
  1913. InsertTailList(&ListHead, &pMofInfo->Entry);
  1914. if (pMofTemplate != NULL && pMofTemplate->strDescription != NULL) {
  1915. pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(pMofTemplate->strDescription) + 1) * sizeof(TCHAR));
  1916. if (pMofInfo->strDescription != NULL) {
  1917. _tcscpy(pMofInfo->strDescription, pMofTemplate->strDescription);
  1918. }
  1919. }
  1920. if (nType == nEventType) {
  1921. // Type matched
  1922. pMofLookup = pMofInfo;
  1923. }
  1924. if (TypeNameArray != NULL) {
  1925. if ((lCount >= lTypeNameLower) && (lCount <= lTypeNameUpper)) {
  1926. pMofInfo->strType = (LPTSTR)malloc((wcslen((LPWSTR)pTypeNameData[lCount]) + 1) * sizeof(TCHAR));
  1927. if (pMofInfo->strType != NULL){
  1928. #ifdef UNICODE
  1929. wcscpy(pMofInfo->strType, (LPWSTR)(pTypeNameData[lCount]));
  1930. #else
  1931. WideCharToMultiByte(CP_ACP,
  1932. 0,
  1933. (LPWSTR)(pTypeNameData[lCount]),
  1934. wcslen((LPWSTR)(pTypeNameData[lCount])),
  1935. TempString,
  1936. (MAXSTR * sizeof(CHAR)),
  1937. NULL,
  1938. NULL
  1939. );
  1940. TempString[wcslen((LPWSTR)(pTypeNameData[lCount]))] = '\0';
  1941. strcpy(pMofInfo->strType, TempString);
  1942. #endif
  1943. }
  1944. }
  1945. }
  1946. }
  1947. }
  1948. SafeArrayUnaccessData(TypeArray);
  1949. SafeArrayDestroy(TypeArray);
  1950. VariantInit(&pTypeVal);
  1951. if (TypeNameArray != NULL) {
  1952. SafeArrayUnaccessData(TypeNameArray);
  1953. SafeArrayDestroy(TypeNameArray);
  1954. VariantInit(&pTypeNameVal);
  1955. }
  1956. }
  1957. else {
  1958. // If the Types are not found, then bail
  1959. break;
  1960. }
  1961. }
  1962. else { // EventType is scalar
  1963. hRes = VariantChangeType(&pTypeVal, &pTypeVal, 0, VT_I2);
  1964. if (ERROR_SUCCESS == hRes)
  1965. nEventType = (SHORT)V_I2(&pTypeVal);
  1966. else
  1967. nEventType = (SHORT)V_I4(&pTypeVal);
  1968. VariantClear(&pTypeNameVal);
  1969. hRes = pQualSet->Get(bszEventTypeName,
  1970. 0,
  1971. &pTypeNameVal,
  1972. 0);
  1973. if (ERROR_SUCCESS == hRes) {
  1974. #ifdef UNICODE
  1975. wcscpy(strType, pTypeNameVal.bstrVal);
  1976. #else
  1977. WideCharToMultiByte(CP_ACP,
  1978. 0,
  1979. pTypeNameVal.bstrVal,
  1980. wcslen(pTypeNameVal.bstrVal),
  1981. TempString,
  1982. (MAXSTR * sizeof(CHAR)),
  1983. NULL,
  1984. NULL
  1985. );
  1986. strcpy(strType, TempString);
  1987. strType[wcslen(pTypeNameVal.bstrVal)] = '\0';
  1988. #endif
  1989. }
  1990. else{
  1991. #ifdef UNICODE
  1992. strType[0] = L'\0';
  1993. #else
  1994. strType[0] = '\0';
  1995. #endif
  1996. }
  1997. pMofInfo = GetNewMofInfo(Guid, nEventType, nVersion, nLevel);
  1998. if (pMofInfo != NULL) {
  1999. InsertTailList(&ListHead, &pMofInfo->Entry);
  2000. if (pMofTemplate != NULL && pMofTemplate->strDescription != NULL) {
  2001. pMofInfo->strDescription = (LPTSTR)malloc((_tcslen(pMofTemplate->strDescription) + 1) * sizeof(TCHAR));
  2002. if (pMofInfo->strDescription != NULL) {
  2003. _tcscpy(pMofInfo->strDescription, pMofTemplate->strDescription);
  2004. }
  2005. }
  2006. if (nType == nEventType) {
  2007. // Type matched
  2008. pMofLookup = pMofInfo;
  2009. }
  2010. pMofInfo->strType = (LPTSTR)malloc((_tcslen(strType) + 1) * sizeof(TCHAR));
  2011. if (pMofInfo->strType != NULL){
  2012. _tcscpy(pMofInfo->strType, strType);
  2013. }
  2014. }
  2015. }
  2016. // Get event layout
  2017. VariantClear(&pVal);
  2018. IdIndex = 1;
  2019. V_VT(&pVal) = VT_I4;
  2020. V_I4(&pVal) = IdIndex;
  2021. // For each property
  2022. PropArray = NULL;
  2023. while (pTraceSubSubClasses->GetNames(bszWmiDataId, // only properties with WmiDataId qualifier
  2024. WBEM_FLAG_ONLY_IF_IDENTICAL,
  2025. &pVal, // WmiDataId number starting from 1
  2026. &PropArray) == WBEM_NO_ERROR) {
  2027. hRes = SafeArrayGetLBound(PropArray, 1, &lLower);
  2028. if (ERROR_SUCCESS != hRes) {
  2029. break;
  2030. }
  2031. hRes = SafeArrayGetUBound(PropArray, 1, &lUpper);
  2032. if (ERROR_SUCCESS != hRes) {
  2033. break;
  2034. }
  2035. if (lUpper < 0)
  2036. break;
  2037. // This loop will iterate just once.
  2038. for (lCount = lLower; lCount <= lUpper; lCount++) {
  2039. hRes = SafeArrayGetElement(PropArray, &lCount, &bszPropName);
  2040. if (ERROR_SUCCESS != hRes) {
  2041. break;
  2042. }
  2043. hRes = pTraceSubSubClasses->Get(bszPropName, // Property name
  2044. 0L,
  2045. NULL,
  2046. &pVarType, // CIMTYPE of the property
  2047. NULL);
  2048. if (ERROR_SUCCESS != hRes) {
  2049. break;
  2050. }
  2051. // Get the Qualifier set for the property
  2052. if (pQualSet) {
  2053. pQualSet->Release();
  2054. pQualSet = NULL;
  2055. }
  2056. hRes = pTraceSubSubClasses->GetPropertyQualifierSet(bszPropName,
  2057. &pQualSet);
  2058. if (ERROR_SUCCESS != hRes) {
  2059. break;
  2060. }
  2061. ItemType = GetItemType((CIMTYPE_ENUMERATION)pVarType, pQualSet);
  2062. if( pVarType & CIM_FLAG_ARRAY ){
  2063. ArraySize = GetArraySize(pQualSet);
  2064. }else{
  2065. ArraySize = 1;
  2066. }
  2067. #ifdef UNICODE
  2068. AddMofInfo(&ListHead,
  2069. bszPropName,
  2070. ItemType,
  2071. ArraySize);
  2072. #else
  2073. WideCharToMultiByte(CP_ACP,
  2074. 0,
  2075. bszPropName,
  2076. wcslen(bszPropName),
  2077. TempString,
  2078. (MAXSTR * sizeof(CHAR)),
  2079. NULL,
  2080. NULL
  2081. );
  2082. TempString[wcslen(bszPropName)] = '\0';
  2083. AddMofInfo(&ListHead,
  2084. TempString,
  2085. ItemType,
  2086. ArraySize);
  2087. #endif
  2088. }
  2089. SafeArrayDestroy(PropArray);
  2090. PropArray = NULL;
  2091. V_I4(&pVal) = ++IdIndex;
  2092. } // end enumerating through WmiDataId
  2093. FlushMofList(&ListHead);
  2094. } // if getting event type was successful
  2095. } // if enumeration returned a subclass successfully
  2096. } // end enumerating subclasses
  2097. } // if enumeration was created successfully
  2098. } // if getting class name was successful
  2099. cleanup:
  2100. VariantClear(&pVal);
  2101. VariantClear(&pTypeVal);
  2102. VariantClear(&pClassName);
  2103. SysFreeString(bszClassName);
  2104. SysFreeString(bszWmiDataId);
  2105. SysFreeString(bszEventType);
  2106. SysFreeString(bszEventTypeName);
  2107. SysFreeString(bszFriendlyName);
  2108. // Should not free bszPropName becuase it is already freed by SafeArrayDestroy
  2109. FlushMofList(&ListHead);
  2110. return pMofLookup;
  2111. }
  2112. PMOF_INFO
  2113. GetGuids (GUID Guid,
  2114. SHORT nVersion,
  2115. CHAR nLevel,
  2116. SHORT nType
  2117. )
  2118. /*++
  2119. Routine Description:
  2120. Aceesses the MOF data information from WBEM, creates a linked list,
  2121. and returns a pointer that matches the passed event.
  2122. This function finds the right subtree within the WBEM namespace,
  2123. and calls GetPropertiesFromWBEM() to create the list.
  2124. Arguments:
  2125. Guid - GUID of the passed event.
  2126. nVersion - version of the passed event.
  2127. nLevel - level of the passed event.
  2128. nType - type of the passed event.
  2129. Return Value:
  2130. PMOF_INFO to MOF_INFO structure that matches the passed event.
  2131. NULL if no match is found.
  2132. --*/
  2133. {
  2134. IEnumWbemClassObject *pEnumTraceSubClasses = NULL, *pEnumTraceSubSubClasses = NULL;
  2135. IWbemClassObject *pTraceSubClasses = NULL, *pTraceSubSubClasses = NULL;
  2136. IWbemQualifierSet *pQualSet = NULL;
  2137. BSTR bszInstance = NULL;
  2138. BSTR bszPropertyName = NULL;
  2139. BSTR bszSubClassName = NULL;
  2140. BSTR bszGuid = NULL;
  2141. BSTR bszVersion = NULL;
  2142. WCHAR strGuid[MAXSTR], strTargetGuid[MAXSTR];
  2143. HRESULT hRes;
  2144. VARIANT pVal;
  2145. VARIANT pGuidVal;
  2146. VARIANT pVersionVal;
  2147. UINT nCounter=0;
  2148. BOOLEAN MatchFound;
  2149. SHORT nEventVersion = EVENT_VERSION_DEFAULT;
  2150. PMOF_INFO pMofLookup = NULL;
  2151. VariantInit(&pVal);
  2152. VariantInit(&pGuidVal);
  2153. VariantInit(&pVersionVal);
  2154. if (NULL == pWbemServices) {
  2155. hRes = WbemConnect( &pWbemServices );
  2156. if ( ERROR_SUCCESS != hRes ) {
  2157. goto cleanup;
  2158. }
  2159. }
  2160. // Convert traget GUID to string for later comparison
  2161. #ifdef UNICODE
  2162. GuidToString(strTargetGuid, &Guid);
  2163. #else
  2164. CHAR TempString[MAXSTR];
  2165. GuidToString(TempString, &Guid);
  2166. MultiByteToWideChar(CP_ACP, 0, TempString, -1, strTargetGuid, MAXSTR);
  2167. #endif
  2168. bszInstance = SysAllocString(L"EventTrace");
  2169. bszPropertyName = SysAllocString(L"__CLASS");
  2170. bszGuid = SysAllocString(L"Guid");
  2171. bszVersion = SysAllocString(L"EventVersion");
  2172. pEnumTraceSubClasses = NULL;
  2173. // Get an enumerator for all classes under "EventTace".
  2174. hRes = pWbemServices->CreateClassEnum (
  2175. bszInstance,
  2176. WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  2177. NULL,
  2178. &pEnumTraceSubClasses );
  2179. SysFreeString (bszInstance);
  2180. if (ERROR_SUCCESS == hRes) {
  2181. ULONG uReturned = 1;
  2182. MatchFound = FALSE;
  2183. while (uReturned == 1) {
  2184. pTraceSubClasses = NULL;
  2185. // Get the next ClassObject.
  2186. hRes = pEnumTraceSubClasses->Next(5000, // timeout in five seconds
  2187. 1, // return just one instance
  2188. &pTraceSubClasses, // pointer to Event Trace Sub Class
  2189. &uReturned); // number obtained: one or zero
  2190. if (ERROR_SUCCESS == hRes && (uReturned == 1)) {
  2191. // Get the class name
  2192. hRes = pTraceSubClasses->Get(bszPropertyName, // property name
  2193. 0L,
  2194. &pVal, // output to this variant
  2195. NULL,
  2196. NULL);
  2197. if (ERROR_SUCCESS == hRes){
  2198. bszSubClassName = SysAllocString(pVal.bstrVal);
  2199. // Create an enumerator to find derived classes.
  2200. hRes = pWbemServices->CreateClassEnum (
  2201. bszSubClassName,
  2202. WBEM_FLAG_SHALLOW | WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  2203. NULL,
  2204. &pEnumTraceSubSubClasses
  2205. );
  2206. SysFreeString ( bszSubClassName );
  2207. bszSubClassName = NULL;
  2208. VariantClear(&pVal);
  2209. if (ERROR_SUCCESS == hRes) {
  2210. ULONG uReturnedSub = 1;
  2211. while(uReturnedSub == 1){
  2212. pTraceSubSubClasses = NULL;
  2213. // enumerate through the resultset.
  2214. hRes = pEnumTraceSubSubClasses->Next(5000, // timeout in five seconds
  2215. 1, // return just one instance
  2216. &pTraceSubSubClasses, // pointer to a Sub class
  2217. &uReturnedSub); // number obtained: one or zero
  2218. if (ERROR_SUCCESS == hRes && uReturnedSub == 1) {
  2219. // Get the subclass name
  2220. hRes = pTraceSubSubClasses->Get(bszPropertyName, // Class name
  2221. 0L,
  2222. &pVal, // output to this variant
  2223. NULL,
  2224. NULL);
  2225. VariantClear(&pVal);
  2226. if (ERROR_SUCCESS == hRes){
  2227. // Get Qualifier Set.
  2228. if (pQualSet) {
  2229. pQualSet->Release();
  2230. pQualSet = NULL;
  2231. }
  2232. pTraceSubSubClasses->GetQualifierSet (&pQualSet );
  2233. // Get GUID among Qualifiers
  2234. hRes = pQualSet->Get(bszGuid,
  2235. 0,
  2236. &pGuidVal,
  2237. 0);
  2238. if (ERROR_SUCCESS == hRes) {
  2239. wcscpy(strGuid, (LPWSTR)V_BSTR(&pGuidVal));
  2240. VariantClear ( &pGuidVal );
  2241. if (!wcsstr(strGuid, L"{"))
  2242. swprintf(strGuid , L"{%s}", strGuid);
  2243. if (!_wcsicmp(strTargetGuid, strGuid)) {
  2244. hRes = pQualSet->Get(bszVersion,
  2245. 0,
  2246. &pVersionVal,
  2247. 0);
  2248. if (ERROR_SUCCESS == hRes) {
  2249. hRes = VariantChangeType(&pVersionVal, &pVersionVal, 0, VT_I2);
  2250. if (ERROR_SUCCESS == hRes)
  2251. nEventVersion = (SHORT)V_I2(&pVersionVal);
  2252. else
  2253. nEventVersion = (SHORT)V_I4(&pVersionVal);
  2254. VariantClear(&pVersionVal);
  2255. if (nVersion == nEventVersion) {
  2256. // Match is found.
  2257. // Now put all events in this subtree into the list
  2258. MatchFound = TRUE;
  2259. pMofLookup = GetPropertiesFromWBEM( pTraceSubSubClasses,
  2260. Guid,
  2261. nVersion,
  2262. nLevel,
  2263. nType
  2264. );
  2265. break;
  2266. }
  2267. }
  2268. else {
  2269. // if there is no version number for this event,
  2270. // the current one is the only one
  2271. // Now put all events in this subtree into the list
  2272. MatchFound = TRUE;
  2273. pMofLookup = GetPropertiesFromWBEM( pTraceSubSubClasses,
  2274. Guid,
  2275. EVENT_VERSION_DEFAULT,
  2276. nLevel,
  2277. nType
  2278. );
  2279. break;
  2280. }
  2281. }
  2282. }
  2283. }
  2284. }
  2285. } // end while enumerating sub classes
  2286. if (MatchFound) {
  2287. break;
  2288. }
  2289. if (pEnumTraceSubSubClasses) {
  2290. pEnumTraceSubSubClasses->Release();
  2291. pEnumTraceSubSubClasses = NULL;
  2292. }
  2293. } // if creating enumeration was successful
  2294. else {
  2295. pEnumTraceSubSubClasses = NULL;
  2296. }
  2297. } // if getting class name was successful
  2298. }
  2299. nCounter++;
  2300. // if match is found, break out of the top level search
  2301. if (MatchFound)
  2302. break;
  2303. } // end while enumerating top classes
  2304. if( pEnumTraceSubClasses ){
  2305. pEnumTraceSubClasses->Release();
  2306. pEnumTraceSubClasses = NULL;
  2307. }
  2308. } // if creating enumeration for top level is successful
  2309. cleanup:
  2310. VariantClear(&pGuidVal);
  2311. VariantClear(&pVersionVal);
  2312. SysFreeString(bszGuid);
  2313. SysFreeString(bszPropertyName);
  2314. SysFreeString(bszVersion);
  2315. if( pEnumTraceSubClasses ){
  2316. pEnumTraceSubClasses->Release();
  2317. pEnumTraceSubClasses = NULL;
  2318. }
  2319. if (pEnumTraceSubSubClasses){
  2320. pEnumTraceSubSubClasses->Release();
  2321. pEnumTraceSubSubClasses = NULL;
  2322. }
  2323. if (pQualSet) {
  2324. pQualSet->Release();
  2325. pQualSet = NULL;
  2326. }
  2327. return pMofLookup;
  2328. }
  2329. ULONG
  2330. ahextoi(
  2331. TCHAR *s
  2332. )
  2333. /*++
  2334. Routine Description:
  2335. Converts a hex number to an integer.
  2336. Arguments:
  2337. s - Input string containing a hex number.
  2338. Return Value:
  2339. ULONG denoted by the hex string s.
  2340. --*/
  2341. {
  2342. long len;
  2343. ULONG num, base, hex;
  2344. if (s == NULL)
  2345. return 0;
  2346. if (*s == 0)
  2347. return 0;
  2348. len = (long) _tcslen(s);
  2349. if (len == 0 || len >= MAXSTR )
  2350. return 0;
  2351. hex = 0; base = 1; num = 0;
  2352. while (--len >= 0) {
  2353. if ( (s[len] == 'x' || s[len] == 'X') &&
  2354. (s[len-1] == '0') )
  2355. break;
  2356. if (s[len] >= '0' && s[len] <= '9')
  2357. num = s[len] - '0';
  2358. else if (s[len] >= 'a' && s[len] <= 'f')
  2359. num = (s[len] - 'a') + 10;
  2360. else if (s[len] >= 'A' && s[len] <= 'F')
  2361. num = (s[len] - 'A') + 10;
  2362. else
  2363. continue;
  2364. hex += num * base;
  2365. base = base * 16;
  2366. }
  2367. return hex;
  2368. }
  2369. void
  2370. RemoveWhiteSpace(
  2371. TCHAR *s
  2372. )
  2373. /*++
  2374. Routine Description:
  2375. Removes white space (' ', '\n', and '\t') from the given string.
  2376. Arguments:
  2377. s - Input and output string.
  2378. Return Value:
  2379. None
  2380. --*/
  2381. {
  2382. UINT i = 0;
  2383. UINT j = 0;
  2384. TCHAR TempString[MAXSTR];
  2385. if (s == NULL)
  2386. return;
  2387. _tcscpy(TempString, s);
  2388. while (TempString[i] != '\0') {
  2389. if (TempString[i] != ' ' && TempString[i] != '\t' && TempString[i] != '\n')
  2390. s[j++] = TempString[i];
  2391. ++i;
  2392. }
  2393. s[j] = '\0';
  2394. }
  2395. void
  2396. PrintHelpMessage()
  2397. /*++
  2398. Routine Description:
  2399. Prints out help messages.
  2400. Arguments:
  2401. None
  2402. Return Value:
  2403. None
  2404. --*/
  2405. {
  2406. _tprintf(
  2407. _T("Usage: tracedmp [options] <EtlFile1 EtlFile2 ...>| [-h | -? | -help]\n")
  2408. _T("\t-o <file> Output CSV file\n")
  2409. _T("\t-rt [LoggerName] Realtime tracedmp from the logger [LoggerName]\n")
  2410. _T("\t-summary Summary.txt only\n")
  2411. _T("\t-begin HH:MM DD/MM/YY\n")
  2412. _T("\t-end HH:MM DD/MM/YY\n")
  2413. _T("\t-h\n")
  2414. _T("\t-help\n")
  2415. _T("\t-? Display usage information\n")
  2416. _T("\n")
  2417. _T("\tDefault Etl File is C:\\Logfile.etl\n")
  2418. _T("\tDefault output file is dumpfile.csv\n")
  2419. );
  2420. }