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.

702 lines
22 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. tracelog.c
  5. Abstract:
  6. Sample trace control program. Allows user to start, update, query, stop
  7. event tracing, etc.
  8. --*/
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <windows.h>
  12. #include <shellapi.h>
  13. #include <tchar.h>
  14. #include <wmistr.h>
  15. #include <initguid.h>
  16. #include <guiddef.h>
  17. #include <evntrace.h>
  18. #define MAXSTR 1024
  19. // Default trace file name.
  20. #define DEFAULT_LOGFILE_NAME _T("C:\\LogFile.Etl")
  21. // On Windows 2000, we support up to 32 loggers at once.
  22. // On Windows XP and .NET server, we support up to 64 loggers.
  23. #define MAXIMUM_LOGGERS 32
  24. // In this sample, we support the following actions.
  25. // Additional actions that we do not use in this sample include
  26. // Flush and Enumerate Guids functionalities. They are supported
  27. // only on XP or higher version.
  28. #define ACTION_QUERY 0
  29. #define ACTION_START 1
  30. #define ACTION_STOP 2
  31. #define ACTION_UPDATE 3
  32. #define ACTION_LIST 4
  33. #define ACTION_ENABLE 5
  34. #define ACTION_HELP 6
  35. #define ACTION_UNDEFINED 10
  36. void
  37. PrintLoggerStatus(
  38. IN PEVENT_TRACE_PROPERTIES LoggerInfo,
  39. IN ULONG Status
  40. );
  41. ULONG
  42. ahextoi(
  43. IN TCHAR *s
  44. );
  45. void
  46. StringToGuid(
  47. IN TCHAR *str,
  48. OUT LPGUID guid
  49. );
  50. void
  51. PrintHelpMessage();
  52. //
  53. // main function
  54. //
  55. __cdecl main(argc, argv)
  56. int argc;
  57. char **argv;
  58. /*++
  59. Routine Description:
  60. It is the main function.
  61. Arguments:
  62. Return Value:
  63. Error Code defined in winerror.h : If the function succeeds,
  64. it returns ERROR_SUCCESS (== 0).
  65. --*/{
  66. ULONG i, j;
  67. ULONG Status = ERROR_SUCCESS;
  68. LPTSTR *targv, *utargv = NULL;
  69. // Action to be taken
  70. USHORT Action = ACTION_UNDEFINED;
  71. LPTSTR LoggerName;
  72. LPTSTR LogFileName;
  73. PEVENT_TRACE_PROPERTIES pLoggerInfo;
  74. TRACEHANDLE LoggerHandle = 0;
  75. // Target GUID, level and flags for enable/disable
  76. GUID TargetGuid;
  77. ULONG bEnable = TRUE;
  78. ULONG SizeNeeded = 0;
  79. // We will enable Process, Thread, Disk, and Network events
  80. // if the Kernel Logger is requested.
  81. BOOL bKernelLogger = FALSE;
  82. // Allocate and initialize EVENT_TRACE_PROPERTIES structure first
  83. SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) + 2 * MAXSTR * sizeof(TCHAR);
  84. pLoggerInfo = (PEVENT_TRACE_PROPERTIES) malloc(SizeNeeded);
  85. if (pLoggerInfo == NULL) {
  86. return (ERROR_OUTOFMEMORY);
  87. }
  88. RtlZeroMemory(pLoggerInfo, SizeNeeded);
  89. pLoggerInfo->Wnode.BufferSize = SizeNeeded;
  90. pLoggerInfo->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  91. pLoggerInfo->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  92. pLoggerInfo->LogFileNameOffset = pLoggerInfo->LoggerNameOffset + MAXSTR * sizeof(TCHAR);
  93. LoggerName = (LPTSTR)((char*)pLoggerInfo + pLoggerInfo->LoggerNameOffset);
  94. LogFileName = (LPTSTR)((char*)pLoggerInfo + pLoggerInfo->LogFileNameOffset);
  95. // If the logger name is not given, we will assume the kernel logger.
  96. _tcscpy(LoggerName, KERNEL_LOGGER_NAME);
  97. #ifdef UNICODE
  98. if ((targv = CommandLineToArgvW(
  99. GetCommandLineW(), // pointer to a command-line string
  100. &argc // receives the argument count
  101. )) == NULL) {
  102. free(pLoggerInfo);
  103. return (GetLastError());
  104. };
  105. utargv = targv;
  106. #else
  107. targv = argv;
  108. #endif
  109. //
  110. // Parse the command line options to determine actions and parameters.
  111. //
  112. while (--argc > 0) {
  113. ++targv;
  114. if (**targv == '-' || **targv == '/') { // argument found
  115. if (targv[0][0] == '/' ) {
  116. targv[0][0] = '-';
  117. }
  118. // Deterine actions.
  119. if (!_tcsicmp(targv[0], _T("-start"))) {
  120. Action = ACTION_START;
  121. if (argc > 1) {
  122. if (targv[1][0] != '-' && targv[1][0] != '/') {
  123. ++targv; --argc;
  124. _tcscpy(LoggerName, targv[0]);
  125. }
  126. }
  127. }
  128. else if (!_tcsicmp(targv[0], _T("-enable"))) {
  129. Action = ACTION_ENABLE;
  130. if (argc > 1) {
  131. if (targv[1][0] != '-' && targv[1][0] != '/') {
  132. ++targv; --argc;
  133. _tcscpy(LoggerName, targv[0]);
  134. }
  135. }
  136. }
  137. else if (!_tcsicmp(targv[0], _T("-disable"))) {
  138. Action = ACTION_ENABLE;
  139. bEnable = FALSE;
  140. if (argc > 1) {
  141. if (targv[1][0] != '-' && targv[1][0] != '/') {
  142. ++targv; --argc;
  143. _tcscpy(LoggerName, targv[0]);
  144. }
  145. }
  146. }
  147. else if (!_tcsicmp(targv[0], _T("-stop"))) {
  148. Action = ACTION_STOP;
  149. if (argc > 1) {
  150. if (targv[1][0] != '-' && targv[1][0] != '/') {
  151. ++targv; --argc;
  152. _tcscpy(LoggerName, targv[0]);
  153. }
  154. }
  155. }
  156. else if (!_tcsicmp(targv[0], _T("-update"))) {
  157. Action = ACTION_UPDATE;
  158. if (argc > 1) {
  159. if (targv[1][0] != '-' && targv[1][0] != '/') {
  160. ++targv; --argc;
  161. _tcscpy(LoggerName, targv[0]);
  162. }
  163. }
  164. }
  165. else if (!_tcsicmp(targv[0], _T("-query"))) {
  166. Action = ACTION_QUERY;
  167. if (argc > 1) {
  168. if (targv[1][0] != '-' && targv[1][0] != '/') {
  169. ++targv; --argc;
  170. _tcscpy(LoggerName, targv[0]);
  171. }
  172. }
  173. }
  174. else if (!_tcsicmp(targv[0], _T("-list"))) {
  175. Action = ACTION_LIST;
  176. }
  177. // Get other parameters.
  178. // Users can customize logger settings further by adding/changing
  179. // values to pLoggerInfo. Refer to EVENT_TRACE_PROPERTIES documentation
  180. // for available options.
  181. // In this sample, we allow changing maximum number of buffers and
  182. // specifying user mode (private) logger.
  183. // We also take trace file name and guid for enable/disable.
  184. else if (!_tcsicmp(targv[0], _T("-f"))) {
  185. if (argc > 1) {
  186. _tfullpath(LogFileName, targv[1], MAXSTR);
  187. ++targv; --argc;
  188. }
  189. }
  190. else if (!_tcsicmp(targv[0], _T("-guid"))) {
  191. if (argc > 1) {
  192. // -guid #00000000-0000-0000-0000-000000000000
  193. if (targv[1][0] == _T('#')) {
  194. StringToGuid(&targv[1][1], &TargetGuid);
  195. ++targv; --argc;
  196. }
  197. }
  198. }
  199. else if (!_tcsicmp(targv[0], _T("-max"))) {
  200. if (argc > 1) {
  201. pLoggerInfo->MaximumBuffers = _ttoi(targv[1]);
  202. ++targv; --argc;
  203. }
  204. }
  205. else if (!_tcsicmp(targv[0], _T("-um"))) {
  206. pLoggerInfo->LogFileMode |= EVENT_TRACE_PRIVATE_LOGGER_MODE;
  207. }
  208. else if ( targv[0][1] == 'h' || targv[0][1] == 'H' || targv[0][1] == '?'){
  209. Action = ACTION_HELP;
  210. PrintHelpMessage();
  211. if (utargv != NULL) {
  212. GlobalFree(utargv);
  213. }
  214. free(pLoggerInfo);
  215. return (ERROR_SUCCESS);
  216. }
  217. else Action = ACTION_UNDEFINED;
  218. }
  219. else {
  220. _tprintf(_T("Invalid option given: %s\n"), targv[0]);
  221. Status = ERROR_INVALID_PARAMETER;
  222. SetLastError(Status);
  223. if (utargv != NULL) {
  224. GlobalFree(utargv);
  225. }
  226. free(pLoggerInfo);
  227. return (Status);
  228. }
  229. }
  230. // Set the kernel logger parameters.
  231. if (!_tcscmp(LoggerName, KERNEL_LOGGER_NAME)) {
  232. // Set enable flags. Users can add options to add additional kernel events
  233. // or remove some of these events.
  234. pLoggerInfo->EnableFlags |= EVENT_TRACE_FLAG_PROCESS;
  235. pLoggerInfo->EnableFlags |= EVENT_TRACE_FLAG_THREAD;
  236. pLoggerInfo->EnableFlags |= EVENT_TRACE_FLAG_DISK_IO;
  237. pLoggerInfo->EnableFlags |= EVENT_TRACE_FLAG_NETWORK_TCPIP;
  238. pLoggerInfo->Wnode.Guid = SystemTraceControlGuid;
  239. bKernelLogger = TRUE;
  240. }
  241. else if (pLoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
  242. // We must provide a control GUID for a private logger.
  243. pLoggerInfo->Wnode.Guid = TargetGuid;
  244. }
  245. // Process the request.
  246. switch (Action) {
  247. case ACTION_START:
  248. {
  249. // Use default file name if not given
  250. if (_tcslen(LogFileName) == 0) {
  251. _tcscpy(LogFileName, DEFAULT_LOGFILE_NAME);
  252. }
  253. Status = StartTrace(&LoggerHandle, LoggerName, pLoggerInfo);
  254. if (Status != ERROR_SUCCESS) {
  255. _tprintf(_T("Could not start logger: %s\n")
  256. _T("Operation Status: %uL\n"),
  257. LoggerName,
  258. Status);
  259. break;
  260. }
  261. _tprintf(_T("Logger Started...\n"));
  262. }
  263. case ACTION_ENABLE:
  264. {
  265. // We can allow enabling a GUID during START operation (Note no break in case ACTION_START).
  266. // In that case, we do not need to get LoggerHandle separately.
  267. if (Action == ACTION_ENABLE ){
  268. // Get Logger Handle though Query.
  269. Status = ControlTrace((TRACEHANDLE) 0, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_QUERY);
  270. if( Status != ERROR_SUCCESS ){
  271. _tprintf( _T("ERROR: Logger not started\n")
  272. _T("Operation Status: %uL\n"),
  273. Status);
  274. break;
  275. }
  276. LoggerHandle = pLoggerInfo->Wnode.HistoricalContext;
  277. }
  278. // We do not allow EnableTrace on the Kernel Logger in this sample,
  279. // users can use EnableFlags to enable/disable certain kernel events.
  280. if (!bKernelLogger) {
  281. _tprintf(_T("Enabling trace to logger %d\n"), LoggerHandle);
  282. // In this sample, we use EnableFlag = EnableLebel = 0
  283. Status = EnableTrace (
  284. bEnable,
  285. 0,
  286. 0,
  287. &TargetGuid,
  288. LoggerHandle);
  289. if (Status != ERROR_SUCCESS) {
  290. _tprintf(_T("ERROR: Failed to enable Guid...\n"));
  291. _tprintf(_T("Operation Status: %uL\n"), Status);
  292. break;
  293. }
  294. }
  295. break;
  296. }
  297. case ACTION_STOP :
  298. {
  299. LoggerHandle = (TRACEHANDLE) 0;
  300. Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_STOP);
  301. break;
  302. }
  303. case ACTION_LIST :
  304. {
  305. ULONG returnCount;
  306. PEVENT_TRACE_PROPERTIES pLoggerInfo[MAXIMUM_LOGGERS];
  307. PEVENT_TRACE_PROPERTIES pStorage, pTempStorage;
  308. ULONG SizeForOneProperty = sizeof(EVENT_TRACE_PROPERTIES) +
  309. 2 * MAXSTR * sizeof(TCHAR);
  310. // We need to prepare space to receieve the inforamtion on loggers.
  311. SizeNeeded = MAXIMUM_LOGGERS * SizeForOneProperty;
  312. pStorage = (PEVENT_TRACE_PROPERTIES)malloc(SizeNeeded);
  313. if (pStorage == NULL) {
  314. Status = ERROR_OUTOFMEMORY;
  315. break;
  316. }
  317. RtlZeroMemory(pStorage, SizeNeeded);
  318. // Save the pointer for free() later.
  319. pTempStorage = pStorage;
  320. for (i = 0; i < MAXIMUM_LOGGERS; i++) {
  321. pStorage->Wnode.BufferSize = SizeForOneProperty;
  322. pStorage->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  323. pStorage->LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES)
  324. + MAXSTR * sizeof(TCHAR);
  325. pLoggerInfo[i] = pStorage;
  326. pStorage = (PEVENT_TRACE_PROPERTIES) (
  327. (PUCHAR)pStorage +
  328. pStorage->Wnode.BufferSize);
  329. }
  330. Status = QueryAllTraces(pLoggerInfo,
  331. MAXIMUM_LOGGERS,
  332. &returnCount);
  333. if (Status == ERROR_SUCCESS)
  334. {
  335. for (j= 0; j < returnCount; j++)
  336. {
  337. PrintLoggerStatus(pLoggerInfo[j],
  338. Status);
  339. _tprintf(_T("\n"));
  340. }
  341. }
  342. free(pTempStorage);
  343. break;
  344. }
  345. case ACTION_UPDATE :
  346. {
  347. // In this sample, users can only update MaximumBuffers and log file name.
  348. // User can add more options for other parameters as needed.
  349. Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_UPDATE);
  350. break;
  351. }
  352. case ACTION_QUERY :
  353. {
  354. Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_QUERY);
  355. break;
  356. }
  357. case ACTION_HELP:
  358. {
  359. PrintHelpMessage();
  360. break;
  361. }
  362. default :
  363. {
  364. _tprintf(_T("Error: no action specified\n"));
  365. PrintHelpMessage();
  366. break;
  367. }
  368. }
  369. if ((Action != ACTION_HELP) &&
  370. (Action != ACTION_UNDEFINED) &&
  371. (Action != ACTION_LIST)) {
  372. PrintLoggerStatus(pLoggerInfo,
  373. Status);
  374. }
  375. if (Status != ERROR_SUCCESS) {
  376. SetLastError(Status);
  377. }
  378. if (utargv != NULL) {
  379. GlobalFree(utargv);
  380. }
  381. free(pLoggerInfo);
  382. return (Status);
  383. }
  384. void
  385. PrintLoggerStatus(
  386. IN PEVENT_TRACE_PROPERTIES LoggerInfo,
  387. IN ULONG Status
  388. )
  389. /*++
  390. Routine Description:
  391. Prints out the status of the specified logger.
  392. Arguments:
  393. LoggerInfo - The pointer to the resident EVENT_TRACE_PROPERTIES that has
  394. the information about the current logger.
  395. Status - The operation status of the current logger.
  396. Return Value:
  397. None
  398. --*/
  399. {
  400. LPTSTR LoggerName, LogFileName;
  401. if ((LoggerInfo->LoggerNameOffset > 0) &&
  402. (LoggerInfo->LoggerNameOffset < LoggerInfo->Wnode.BufferSize)) {
  403. LoggerName = (LPTSTR) ((PUCHAR)LoggerInfo +
  404. LoggerInfo->LoggerNameOffset);
  405. }
  406. else LoggerName = NULL;
  407. if ((LoggerInfo->LogFileNameOffset > 0) &&
  408. (LoggerInfo->LogFileNameOffset < LoggerInfo->Wnode.BufferSize)) {
  409. LogFileName = (LPTSTR) ((PUCHAR)LoggerInfo +
  410. LoggerInfo->LogFileNameOffset);
  411. }
  412. else LogFileName = NULL;
  413. _tprintf(_T("Operation Status: %uL\n"), Status);
  414. _tprintf(_T("Logger Name: %s\n"),
  415. (LoggerName == NULL) ?
  416. _T(" ") : LoggerName);
  417. _tprintf(_T("Logger Id: %I64x\n"), LoggerInfo->Wnode.HistoricalContext);
  418. _tprintf(_T("Logger Thread Id: %d\n"), LoggerInfo->LoggerThreadId);
  419. if (Status != 0)
  420. return;
  421. _tprintf(_T("Buffer Size: %d Kb"), LoggerInfo->BufferSize);
  422. if (LoggerInfo->LogFileMode & EVENT_TRACE_USE_PAGED_MEMORY) {
  423. _tprintf(_T(" using paged memory\n"));
  424. }
  425. else {
  426. _tprintf(_T("\n"));
  427. }
  428. _tprintf(_T("Maximum Buffers: %d\n"), LoggerInfo->MaximumBuffers);
  429. _tprintf(_T("Minimum Buffers: %d\n"), LoggerInfo->MinimumBuffers);
  430. _tprintf(_T("Number of Buffers: %d\n"), LoggerInfo->NumberOfBuffers);
  431. _tprintf(_T("Free Buffers: %d\n"), LoggerInfo->FreeBuffers);
  432. _tprintf(_T("Buffers Written: %d\n"), LoggerInfo->BuffersWritten);
  433. _tprintf(_T("Events Lost: %d\n"), LoggerInfo->EventsLost);
  434. _tprintf(_T("Log Buffers Lost: %d\n"), LoggerInfo->LogBuffersLost);
  435. _tprintf(_T("Real Time Buffers Lost: %d\n"), LoggerInfo->RealTimeBuffersLost);
  436. _tprintf(_T("AgeLimit: %d\n"), LoggerInfo->AgeLimit);
  437. if (LogFileName == NULL) {
  438. _tprintf(_T("Buffering Mode: "));
  439. }
  440. else {
  441. _tprintf(_T("Log File Mode: "));
  442. }
  443. if (LoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_APPEND) {
  444. _tprintf(_T("Append "));
  445. }
  446. if (LoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) {
  447. _tprintf(_T("Circular\n"));
  448. }
  449. else if (LoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_SEQUENTIAL) {
  450. _tprintf(_T("Sequential\n"));
  451. }
  452. else {
  453. _tprintf(_T("Sequential\n"));
  454. }
  455. if (LoggerInfo->LogFileMode & EVENT_TRACE_REAL_TIME_MODE) {
  456. _tprintf(_T("Real Time mode enabled"));
  457. _tprintf(_T("\n"));
  458. }
  459. if (LoggerInfo->MaximumFileSize > 0)
  460. _tprintf(_T("Maximum File Size: %d Mb\n"), LoggerInfo->MaximumFileSize);
  461. if (LoggerInfo->FlushTimer > 0)
  462. _tprintf(_T("Buffer Flush Timer: %d secs\n"), LoggerInfo->FlushTimer);
  463. if (LoggerInfo->EnableFlags != 0) {
  464. _tprintf(_T("Enabled tracing: "));
  465. if ((LoggerName != NULL) && (!_tcscmp(LoggerName, KERNEL_LOGGER_NAME))) {
  466. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_PROCESS)
  467. _tprintf(_T("Process "));
  468. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_THREAD)
  469. _tprintf(_T("Thread "));
  470. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_DISK_IO)
  471. _tprintf(_T("Disk "));
  472. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_DISK_FILE_IO)
  473. _tprintf(_T("File "));
  474. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_MEMORY_PAGE_FAULTS)
  475. _tprintf(_T("PageFaults "));
  476. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_MEMORY_HARD_FAULTS)
  477. _tprintf(_T("HardFaults "));
  478. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_IMAGE_LOAD)
  479. _tprintf(_T("ImageLoad "));
  480. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_NETWORK_TCPIP)
  481. _tprintf(_T("TcpIp "));
  482. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_REGISTRY)
  483. _tprintf(_T("Registry "));
  484. }else{
  485. _tprintf(_T("0x%08x"), LoggerInfo->EnableFlags );
  486. }
  487. _tprintf(_T("\n"));
  488. }
  489. if (LogFileName != NULL) {
  490. _tprintf(_T("Log Filename: %s\n"), LogFileName);
  491. }
  492. }
  493. ULONG
  494. ahextoi(
  495. IN TCHAR *s
  496. )
  497. /*++
  498. Routine Description:
  499. Converts a hex string into a number.
  500. Arguments:
  501. s - A hex string in TCHAR.
  502. Return Value:
  503. ULONG - The number in the string.
  504. --*/
  505. {
  506. int len;
  507. ULONG num, base, hex;
  508. len = _tcslen(s);
  509. hex = 0; base = 1; num = 0;
  510. while (--len >= 0) {
  511. if ( (s[len] == 'x' || s[len] == 'X') &&
  512. (s[len-1] == '0') )
  513. break;
  514. if (s[len] >= '0' && s[len] <= '9')
  515. num = s[len] - '0';
  516. else if (s[len] >= 'a' && s[len] <= 'f')
  517. num = (s[len] - 'a') + 10;
  518. else if (s[len] >= 'A' && s[len] <= 'F')
  519. num = (s[len] - 'A') + 10;
  520. else
  521. continue;
  522. hex += num * base;
  523. base = base * 16;
  524. }
  525. return hex;
  526. }
  527. void
  528. StringToGuid(
  529. IN TCHAR *str,
  530. IN OUT LPGUID guid
  531. )
  532. /*++
  533. Routine Description:
  534. Converts a string into a GUID.
  535. Arguments:
  536. str - A string in TCHAR.
  537. guid - The pointer to a GUID that will have the converted GUID.
  538. Return Value:
  539. None.
  540. --*/
  541. {
  542. TCHAR temp[10];
  543. int i;
  544. _tcsncpy(temp, str, 8);
  545. temp[8] = 0;
  546. guid->Data1 = ahextoi(temp);
  547. _tcsncpy(temp, &str[9], 4);
  548. temp[4] = 0;
  549. guid->Data2 = (USHORT) ahextoi(temp);
  550. _tcsncpy(temp, &str[14], 4);
  551. temp[4] = 0;
  552. guid->Data3 = (USHORT) ahextoi(temp);
  553. for (i=0; i<2; i++) {
  554. _tcsncpy(temp, &str[19 + (i*2)], 2);
  555. temp[2] = 0;
  556. guid->Data4[i] = (UCHAR) ahextoi(temp);
  557. }
  558. for (i=2; i<8; i++) {
  559. _tcsncpy(temp, &str[20 + (i*2)], 2);
  560. temp[2] = 0;
  561. guid->Data4[i] = (UCHAR) ahextoi(temp);
  562. }
  563. }
  564. void PrintHelpMessage()
  565. /*++
  566. Routine Description:
  567. prints out a help message.
  568. Arguments:
  569. None.
  570. Return Value:
  571. None.
  572. --*/
  573. {
  574. _tprintf(_T("Usage: tracelog [actions] [options] | [-h | -help | -?]\n"));
  575. _tprintf(_T("\n actions:\n"));
  576. _tprintf(_T("\t-start [LoggerName] Starts up the [LoggerName] trace session\n"));
  577. _tprintf(_T("\t-stop [LoggerName] Stops the [LoggerName] trace session\n"));
  578. _tprintf(_T("\t-update [LoggerName] Updates the [LoggerName] trace session\n"));
  579. _tprintf(_T("\t-enable [LoggerName] Enables providers for the [LoggerName] session\n"));
  580. _tprintf(_T("\t-disable [LoggerName] Disables providers for the [LoggerName] session\n"));
  581. _tprintf(_T("\t-query [LoggerName] Query status of [LoggerName] trace session\n"));
  582. _tprintf(_T("\t-list List all trace sessions\n"));
  583. _tprintf(_T("\n options:\n"));
  584. _tprintf(_T("\t-um Use Process Private tracing\n"));
  585. _tprintf(_T("\t-max <n> Sets maximum buffers\n"));
  586. _tprintf(_T("\t-f <name> Log to file <name>\n"));
  587. _tprintf(_T("\t-guid #<guid> Provider GUID to enable/disable\n"));
  588. _tprintf(_T("\n"));
  589. _tprintf(_T("\t-h\n"));
  590. _tprintf(_T("\t-help\n"));
  591. _tprintf(_T("\t-? Display usage information\n"));
  592. }