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.

745 lines
23 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. mergetl.c
  5. Abstract:
  6. Converts multiple ETL files into a single ordered ETL files.
  7. Author:
  8. Melur Raghuraman (Mraghu) 9-Dec-2000
  9. Revision History:
  10. --*/
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <windows.h>
  17. #include <shellapi.h>
  18. #include <wmistr.h>
  19. #include <objbase.h>
  20. #include <initguid.h>
  21. #include <wmium.h>
  22. #include <ntwmi.h>
  23. #include <wmiumkm.h>
  24. #include <evntrace.h>
  25. #include "cpdata.h"
  26. #include "tracectr.h"
  27. #define MAXSTR 1024
  28. #define LOGGER_NAME L"{28ad2447-105b-4fe2-9599-e59b2aa9a634}"
  29. #define LOGGER_NAME_SIZE 38
  30. #define MAX_RETRY_COUNT 10
  31. #define ETW_PROC_MISMATCH 0x00000001
  32. #define ETW_MACHINE_MISMATCH 0x00000002
  33. #define ETW_CLOCK_MISMATCH 0x00000004
  34. #define ETW_BOOTTIME_MISMATCH 0x00000008
  35. #define ETW_VERSION_MISMATCH 0x00000010
  36. #define ETW_POINTER_MISMATCH 0x00000020
  37. TRACEHANDLE LoggerHandle;
  38. ULONG TotalRelogBuffersRead = 0;
  39. ULONG TotalRelogEventsRead = 0;
  40. ULONG FailedEvents=0;
  41. ULONG NumHdrProcessed = 0;
  42. GUID TransactionGuid =
  43. {0xab8bb8a1, 0x3d98, 0x430c, 0x92, 0xb0, 0x78, 0x8f, 0x1d, 0x3f, 0x6e, 0x94};
  44. GUID ControlGuid[2] =
  45. {
  46. {0x42ae6427, 0xb741, 0x4e69, 0xb3, 0x95, 0x38, 0x33, 0x9b, 0xb9, 0x91, 0x80},
  47. {0xb9e2c2d6, 0x95fb, 0x4841, 0xa3, 0x73, 0xad, 0x67, 0x2b, 0x67, 0xb6, 0xc1}
  48. };
  49. typedef struct _USER_MOF_EVENT {
  50. EVENT_TRACE_HEADER Header;
  51. MOF_FIELD mofData;
  52. } USER_MOF_EVENT, *PUSER_MOF_EVENT;
  53. PSYSTEM_TRACE_HEADER MergedSystemTraceHeader;
  54. PTRACE_LOGFILE_HEADER MergedLogFileHeader;
  55. ULONG HeaderMisMatch = 0;
  56. TRACE_GUID_REGISTRATION TraceGuidReg[] =
  57. {
  58. { (LPGUID)&TransactionGuid,
  59. NULL
  60. }
  61. };
  62. TRACEHANDLE RegistrationHandle[2];
  63. ULONG InitializeTrace();
  64. ULONG
  65. ControlCallback(
  66. IN WMIDPREQUESTCODE RequestCode,
  67. IN PVOID Context,
  68. IN OUT ULONG *InOutBufferSize,
  69. IN OUT PVOID Buffer
  70. );
  71. void
  72. WINAPI
  73. EtwDumpEvent(
  74. PEVENT_TRACE pEvent
  75. );
  76. void
  77. WINAPI
  78. EtwProcessLogHeader(
  79. PEVENT_TRACE pEvent
  80. );
  81. ULONG
  82. WINAPI
  83. TerminateOnBufferCallback(
  84. PEVENT_TRACE_LOGFILE pLog
  85. );
  86. ULONG
  87. WINAPI
  88. BufferCallback(
  89. PEVENT_TRACE_LOGFILE pLog
  90. );
  91. USER_MOF_EVENT UserMofEvent;
  92. BOOLEAN bLoggerStarted = FALSE;
  93. PEVENT_TRACE_LOGFILE pLogFile=NULL;
  94. PEVENT_TRACE_LOGFILE EvmFile[MAXLOGGERS];
  95. ULONG LogFileCount = 0;
  96. PEVENT_TRACE_PROPERTIES pLoggerInfo = NULL;
  97. ULONG LoggerInfoSize = 0;
  98. ULONG DifferentPointer = FALSE;
  99. int EtwRelogEtl(
  100. IN OUT PTRACE_CONTEXT_BLOCK TraceContext,
  101. OUT PULONG pMergedEventsLost
  102. )
  103. {
  104. ULONG Status=ERROR_SUCCESS;
  105. ULONG i, j;
  106. TRACEHANDLE HandleArray[MAXLOGGERS];
  107. ULONG SizeNeeded = 0;
  108. LPTSTR LoggerName;
  109. LPTSTR LogFileName;
  110. //
  111. // Allocate Storage for the MergedSystemTraceHeader
  112. //
  113. LoggerInfoSize = sizeof(SYSTEM_TRACE_HEADER) +
  114. sizeof(TRACE_LOGFILE_HEADER) +
  115. MAXSTR * sizeof(WCHAR) +
  116. (LOGGER_NAME_SIZE + 1) * sizeof(WCHAR);
  117. SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) +
  118. 2 * MAXSTR * sizeof(WCHAR) +
  119. LoggerInfoSize;
  120. // Need to allocate more to consider different pointer size case
  121. pLoggerInfo = (PEVENT_TRACE_PROPERTIES) malloc(SizeNeeded + 8);
  122. if (pLoggerInfo == NULL) {
  123. Status = ERROR_OUTOFMEMORY;
  124. goto cleanup;
  125. }
  126. RtlZeroMemory(pLoggerInfo, SizeNeeded + 8);
  127. pLoggerInfo->Wnode.BufferSize = SizeNeeded;
  128. pLoggerInfo->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  129. //
  130. // The relogged file contains a standard time stamp format.
  131. //
  132. pLoggerInfo->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES) + LoggerInfoSize;
  133. pLoggerInfo->LogFileNameOffset = pLoggerInfo->LoggerNameOffset + MAXSTR * sizeof(WCHAR);
  134. pLoggerInfo->LogFileMode = (EVENT_TRACE_PRIVATE_LOGGER_MODE |
  135. EVENT_TRACE_RELOG_MODE |
  136. EVENT_TRACE_FILE_MODE_SEQUENTIAL
  137. );
  138. pLoggerInfo->MinimumBuffers = 2;
  139. pLoggerInfo->MaximumBuffers = 50;
  140. LoggerName = (LPTSTR)((char*)pLoggerInfo + pLoggerInfo->LoggerNameOffset);
  141. LogFileName = (LPTSTR)((char*)pLoggerInfo + pLoggerInfo->LogFileNameOffset);
  142. StringCchCopyW(LoggerName, MAXSTR, LOGGER_NAME);
  143. Status = UuidCreate(&ControlGuid[0]);
  144. if (Status != ERROR_SUCCESS) {
  145. goto cleanup;
  146. }
  147. pLoggerInfo->Wnode.Guid = ControlGuid[0];
  148. if ( wcslen(TraceContext->MergeFileName) > 0 ) {
  149. StringCchCopyW(LogFileName, MAXSTR, TraceContext->MergeFileName);
  150. }
  151. MergedSystemTraceHeader = (PSYSTEM_TRACE_HEADER) ((PUCHAR) pLoggerInfo +
  152. sizeof(EVENT_TRACE_PROPERTIES));
  153. MergedLogFileHeader = (PTRACE_LOGFILE_HEADER) (
  154. (PUCHAR)MergedSystemTraceHeader +
  155. sizeof(SYSTEM_TRACE_HEADER));
  156. LogFileCount = 0;
  157. for (i = 0; i < TraceContext->LogFileCount; i++) {
  158. pLogFile = malloc(sizeof(EVENT_TRACE_LOGFILE));
  159. if (pLogFile == NULL) {
  160. Status = ERROR_OUTOFMEMORY;
  161. goto cleanup;
  162. }
  163. RtlZeroMemory(pLogFile, sizeof(EVENT_TRACE_LOGFILE));
  164. EvmFile[i] = pLogFile;
  165. pLogFile->LogFileName = TraceContext->LogFileName[i];
  166. EvmFile[i]->EventCallback = (PEVENT_CALLBACK) &EtwProcessLogHeader;
  167. EvmFile[i]->BufferCallback = TerminateOnBufferCallback;
  168. LogFileCount++;
  169. }
  170. if (LogFileCount == 0) {
  171. Status = ERROR_INVALID_PARAMETER;
  172. goto cleanup;
  173. }
  174. //
  175. // Initialize Trace
  176. //
  177. Status = InitializeTrace();
  178. if (Status != ERROR_SUCCESS) {
  179. goto cleanup;
  180. }
  181. //
  182. // Set up the Relog Event
  183. //
  184. RtlZeroMemory(&UserMofEvent, sizeof(UserMofEvent));
  185. UserMofEvent.Header.Size = sizeof(UserMofEvent);
  186. UserMofEvent.Header.Flags = WNODE_FLAG_TRACED_GUID | WNODE_FLAG_USE_MOF_PTR;
  187. for (i = 0; i < LogFileCount; i++) {
  188. TRACEHANDLE x;
  189. EvmFile[i]->LogfileHeader.ReservedFlags |= EVENT_TRACE_GET_RAWEVENT;
  190. x = OpenTrace(EvmFile[i]);
  191. HandleArray[i] = x;
  192. if (HandleArray[i] == (TRACEHANDLE)INVALID_HANDLE_VALUE) {
  193. Status = GetLastError();
  194. for (j = 0; j < i; j++)
  195. CloseTrace(HandleArray[j]);
  196. goto cleanup;
  197. }
  198. Status = ProcessTrace(&x, 1, NULL, NULL);
  199. }
  200. for (j = 0; j < LogFileCount; j++){
  201. Status = CloseTrace(HandleArray[j]);
  202. }
  203. if (HeaderMisMatch) {
  204. if (HeaderMisMatch & ETW_CLOCK_MISMATCH) {
  205. Status = ERROR_INVALID_TIME;
  206. }
  207. else if (HeaderMisMatch & ETW_PROC_MISMATCH || HeaderMisMatch & ETW_POINTER_MISMATCH)
  208. Status = ERROR_INVALID_DATA;
  209. goto cleanup;
  210. }
  211. if ( (MergedLogFileHeader->BufferSize == 0) ||
  212. (MergedLogFileHeader->NumberOfProcessors == 0) ) {
  213. goto cleanup;
  214. }
  215. //
  216. // We are past the Error checks. Go ahead and Allocate
  217. // Storage to Start a logger
  218. //
  219. pLoggerInfo->Wnode.ClientContext = MergedLogFileHeader->ReservedFlags;
  220. pLoggerInfo->Wnode.ProviderId = MergedLogFileHeader->NumberOfProcessors;
  221. pLoggerInfo->BufferSize = MergedLogFileHeader->BufferSize / 1024;
  222. //
  223. // We are Past the Error Checks. Go ahead and redo ProcessTrace
  224. //
  225. for (i = 0; i < TraceContext->LogFileCount; i++) {
  226. TRACEHANDLE x;
  227. EvmFile[i]->EventCallback = (PEVENT_CALLBACK) &EtwDumpEvent;
  228. EvmFile[i]->BufferCallback = BufferCallback;
  229. EvmFile[i]->LogfileHeader.ReservedFlags |= EVENT_TRACE_GET_RAWEVENT;
  230. x = OpenTrace(EvmFile[i]);
  231. HandleArray[i] = x;
  232. if (HandleArray[i] == 0) {
  233. Status = GetLastError();
  234. for (j = 0; j < i; j++)
  235. CloseTrace(HandleArray[j]);
  236. goto cleanup;
  237. }
  238. }
  239. Status = ProcessTrace(
  240. HandleArray,
  241. LogFileCount,
  242. NULL,
  243. NULL
  244. );
  245. for (j = 0; j < LogFileCount; j++){
  246. Status = CloseTrace(HandleArray[j]);
  247. }
  248. //
  249. // Need to Stop Trace
  250. //
  251. if (bLoggerStarted) {
  252. RtlZeroMemory(pLoggerInfo, SizeNeeded);
  253. pLoggerInfo->Wnode.BufferSize = sizeof(EVENT_TRACE_PROPERTIES) + 2 * MAXSTR * sizeof(WCHAR);
  254. pLoggerInfo->Wnode.Guid = ControlGuid[0];
  255. pLoggerInfo->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  256. pLoggerInfo->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  257. pLoggerInfo->LogFileNameOffset = pLoggerInfo->LoggerNameOffset + MAXSTR * sizeof(WCHAR);
  258. pLoggerInfo->LogFileMode = (EVENT_TRACE_PRIVATE_LOGGER_MODE |
  259. EVENT_TRACE_RELOG_MODE |
  260. EVENT_TRACE_FILE_MODE_SEQUENTIAL
  261. );
  262. Status = ControlTrace(LoggerHandle, LoggerName, pLoggerInfo, EVENT_TRACE_CONTROL_STOP);
  263. }
  264. //
  265. // We need to cleanup and reset properly to allow this library
  266. // to be used by perf tools
  267. //
  268. bLoggerStarted = FALSE;
  269. Status = UnregisterTraceGuids(RegistrationHandle[0]);
  270. cleanup:
  271. if (NULL != pMergedEventsLost) {
  272. *pMergedEventsLost = FailedEvents;
  273. }
  274. for (i = 0; i < LogFileCount; i ++){
  275. if (EvmFile[i] != NULL)
  276. free(EvmFile[i]);
  277. }
  278. if (pLoggerInfo != NULL)
  279. free (pLoggerInfo);
  280. return Status;
  281. }
  282. void
  283. WINAPI
  284. EtwProcessLogHeader(
  285. PEVENT_TRACE pEvent
  286. )
  287. /*++
  288. Routine Description:
  289. This routine checks to see if the pEvent is a LOGFILE_HEADER
  290. and if so captures the information on the logfile for validation.
  291. The following checks are performed.
  292. 1. Files must be from the same machine. (Verified using machine name)
  293. 2. If different buffersizes are used, largest buffer size is
  294. selected for relogging.
  295. 3. The StartTime and StopTime are the outer most from the files.
  296. 4. The CPUClock type must be the same for all files. If different
  297. clock types are used, then the files will be rejected.
  298. The routine assumes that the first Event Callback from each file is the
  299. LogFileHeader callback.
  300. Other Issues that could result in a not so useful merged logfile are:
  301. 1. Multiple RunDown records when kernel logfiles are merged.
  302. 2. Multiple SystemConfig records when kernel logfiles are merged
  303. 3. Multiple and conflicting GUidMap records when Application logfiles are merged.
  304. 4. ReLogging 32 bit data in 64 bit system
  305. Arguments:
  306. Return Value:
  307. None.
  308. --*/
  309. {
  310. ULONG NumProc;
  311. if( IsEqualGUID(&pEvent->Header.Guid, &EventTraceGuid) &&
  312. pEvent->Header.Class.Type == EVENT_TRACE_TYPE_INFO ) {
  313. PSYSTEM_TRACE_HEADER pSysHeader;
  314. PTRACE_LOGFILE_HEADER head = (PTRACE_LOGFILE_HEADER)((PUCHAR)pEvent->MofData + sizeof(SYSTEM_TRACE_HEADER) );
  315. ULONG BufferSize = head->BufferSize;
  316. pSysHeader = (PSYSTEM_TRACE_HEADER) pEvent->MofData;
  317. if (MergedSystemTraceHeader->Packet.Size == 0) {
  318. ULONG HeaderSize;
  319. LPTSTR LoggerName;
  320. ULONG SizeToCopy = sizeof(SYSTEM_TRACE_HEADER) +
  321. sizeof(TRACE_LOGFILE_HEADER);
  322. if (4 == head->PointerSize && 8 == sizeof(PVOID) ||
  323. 8 == head->PointerSize && 4 == sizeof(PVOID)) {
  324. DifferentPointer = TRUE;
  325. if (4 == sizeof(PVOID)) {
  326. SizeToCopy += 8;
  327. pLoggerInfo->Wnode.BufferSize += 8;
  328. }
  329. else if (8 == sizeof(PVOID)) {
  330. SizeToCopy -= 8;
  331. pLoggerInfo->Wnode.BufferSize -= 8;
  332. }
  333. }
  334. RtlCopyMemory(MergedSystemTraceHeader, pSysHeader, SizeToCopy);
  335. HeaderSize = SizeToCopy +
  336. MAXSTR * sizeof(WCHAR) +
  337. (LOGGER_NAME_SIZE + 1) * sizeof(WCHAR);
  338. MergedSystemTraceHeader->Packet.Size = (USHORT)HeaderSize;
  339. //
  340. // Copy the LoggerName and the LogFileName
  341. //
  342. LoggerName = (PWCHAR)((PUCHAR)MergedSystemTraceHeader + SizeToCopy);
  343. StringCchCopyW(LoggerName, (LOGGER_NAME_SIZE + 1), LOGGER_NAME);
  344. }
  345. else {
  346. //
  347. // Sum up Events Lost from each file
  348. //
  349. MergedLogFileHeader->EventsLost += head->EventsLost;
  350. if (DifferentPointer && 4 == sizeof(PVOID)) {
  351. ULONG CurrentBuffersLost, MoreBuffersLost;
  352. RtlCopyMemory(&CurrentBuffersLost,
  353. (PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, BuffersLost) + 8,
  354. sizeof(ULONG));
  355. RtlCopyMemory(&MoreBuffersLost,
  356. (PUCHAR)head + FIELD_OFFSET(TRACE_LOGFILE_HEADER, BuffersLost) + 8,
  357. sizeof(ULONG));
  358. CurrentBuffersLost += MoreBuffersLost;
  359. RtlCopyMemory((PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, BuffersLost) + 8,
  360. &CurrentBuffersLost,
  361. sizeof(ULONG));
  362. }
  363. else if (DifferentPointer && 8 == sizeof(PVOID)) {
  364. ULONG CurrentBuffersLost, MoreBuffersLost;
  365. RtlCopyMemory(&CurrentBuffersLost,
  366. (PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, BuffersLost) - 8,
  367. sizeof(ULONG));
  368. RtlCopyMemory(&MoreBuffersLost,
  369. (PUCHAR)head + FIELD_OFFSET(TRACE_LOGFILE_HEADER, BuffersLost) - 8,
  370. sizeof(ULONG));
  371. CurrentBuffersLost += MoreBuffersLost;
  372. RtlCopyMemory((PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, BuffersLost) - 8,
  373. &CurrentBuffersLost,
  374. sizeof(ULONG));
  375. }
  376. else {
  377. MergedLogFileHeader->BuffersLost += head->BuffersLost;
  378. }
  379. }
  380. //
  381. // Pick up the Largest BufferSize
  382. //
  383. if (BufferSize > MergedLogFileHeader->BufferSize) {
  384. MergedLogFileHeader->BufferSize = BufferSize;
  385. }
  386. //
  387. // Verify the NumberOfProcessors
  388. //
  389. NumProc = head->NumberOfProcessors;
  390. if ( MergedLogFileHeader->NumberOfProcessors != NumProc) {
  391. HeaderMisMatch |= ETW_PROC_MISMATCH;
  392. }
  393. //
  394. // Pick up the Earliest StartTime (always in SystemTime)
  395. //
  396. if (DifferentPointer && 4 == sizeof(PVOID)) {
  397. LARGE_INTEGER CurrentStartTime, NewStartTime;
  398. RtlCopyMemory(&CurrentStartTime,
  399. (PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, StartTime) + 8,
  400. sizeof(LARGE_INTEGER));
  401. RtlCopyMemory(&NewStartTime,
  402. (PUCHAR)head+ FIELD_OFFSET(TRACE_LOGFILE_HEADER, StartTime) + 8,
  403. sizeof(LARGE_INTEGER));
  404. if (CurrentStartTime.QuadPart > NewStartTime.QuadPart) {
  405. RtlCopyMemory((PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, StartTime) + 8,
  406. &NewStartTime,
  407. sizeof(LARGE_INTEGER));
  408. }
  409. }
  410. else if (DifferentPointer && 8 == sizeof(PVOID)) {
  411. LARGE_INTEGER CurrentStartTime, NewStartTime;
  412. RtlCopyMemory(&CurrentStartTime,
  413. (PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, StartTime) - 8,
  414. sizeof(LARGE_INTEGER));
  415. RtlCopyMemory(&NewStartTime,
  416. (PUCHAR)head+ FIELD_OFFSET(TRACE_LOGFILE_HEADER, StartTime) - 8,
  417. sizeof(LARGE_INTEGER));
  418. if (CurrentStartTime.QuadPart > NewStartTime.QuadPart) {
  419. RtlCopyMemory((PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, StartTime) - 8,
  420. &NewStartTime,
  421. sizeof(LARGE_INTEGER));
  422. }
  423. }
  424. else {
  425. if (MergedLogFileHeader->StartTime.QuadPart > head->StartTime.QuadPart) {
  426. MergedLogFileHeader->StartTime.QuadPart = head->StartTime.QuadPart;
  427. }
  428. }
  429. //
  430. // Pick up the latest EndTime
  431. //
  432. if (MergedLogFileHeader->EndTime.QuadPart < head->EndTime.QuadPart) {
  433. MergedLogFileHeader->EndTime.QuadPart = head->EndTime.QuadPart;
  434. }
  435. //
  436. // This StartPerfClock is in the ClockType used.
  437. //
  438. if (pSysHeader->SystemTime.QuadPart < MergedSystemTraceHeader->SystemTime.QuadPart) {
  439. MergedSystemTraceHeader->SystemTime = pSysHeader->SystemTime;
  440. }
  441. //
  442. // Verify the pointer size
  443. //
  444. if (MergedLogFileHeader->PointerSize != head->PointerSize) {
  445. HeaderMisMatch |= ETW_POINTER_MISMATCH;
  446. }
  447. //
  448. // Verify the Clock Type
  449. //
  450. if (DifferentPointer && 4 == sizeof(PVOID)) {
  451. if (RtlCompareMemory((PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, ReservedFlags) + 8,
  452. (PUCHAR)head + FIELD_OFFSET(TRACE_LOGFILE_HEADER, ReservedFlags) + 8,
  453. sizeof(ULONG)) != sizeof(ULONG)) {
  454. HeaderMisMatch |= ETW_CLOCK_MISMATCH;
  455. }
  456. if (RtlCompareMemory((PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, PerfFreq) + 8,
  457. (PUCHAR)head + FIELD_OFFSET(TRACE_LOGFILE_HEADER, PerfFreq) + 8,
  458. sizeof(LARGE_INTEGER)) != sizeof(LARGE_INTEGER)) {
  459. HeaderMisMatch |= ETW_MACHINE_MISMATCH;
  460. }
  461. }
  462. else if (DifferentPointer && 8 == sizeof(PVOID)) {
  463. if (RtlCompareMemory((PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, ReservedFlags) - 8,
  464. (PUCHAR)head + FIELD_OFFSET(TRACE_LOGFILE_HEADER, ReservedFlags) - 8,
  465. sizeof(ULONG)) != sizeof(ULONG)) {
  466. HeaderMisMatch |= ETW_CLOCK_MISMATCH;
  467. }
  468. if (RtlCompareMemory((PUCHAR)MergedLogFileHeader + FIELD_OFFSET(TRACE_LOGFILE_HEADER, PerfFreq) - 8,
  469. (PUCHAR)head + FIELD_OFFSET(TRACE_LOGFILE_HEADER, PerfFreq) - 8,
  470. sizeof(LARGE_INTEGER)) != sizeof(LARGE_INTEGER)) {
  471. HeaderMisMatch |= ETW_MACHINE_MISMATCH;
  472. }
  473. }
  474. else {
  475. if (head->ReservedFlags != MergedLogFileHeader->ReservedFlags) {
  476. HeaderMisMatch |= ETW_CLOCK_MISMATCH;
  477. }
  478. if (head->PerfFreq.QuadPart != MergedLogFileHeader->PerfFreq.QuadPart) {
  479. HeaderMisMatch |= ETW_MACHINE_MISMATCH;
  480. }
  481. }
  482. //
  483. // Verify Machine Name
  484. //
  485. // CPU Name is in the CPU Configuration record
  486. // which can be version dependent and found only on Kernel Logger
  487. //
  488. // Verify Build Number
  489. //
  490. // if (head->ProviderVersion != MergedLogFileHeader->ProviderVersion) {
  491. // HeaderMisMatch |= ETW_VERSION_MISMATCH;
  492. // }
  493. //
  494. // Boot Time Verification?
  495. //
  496. // if (head->BootTime.QuadPart != MergedLogFileHeader->BootTime.QuadPart) {
  497. // HeaderMisMatch |= ETW_BOOTTIME_MISMATCH;
  498. // }
  499. //
  500. // Sum up Events Lost from each file
  501. //
  502. NumHdrProcessed++;
  503. }
  504. }
  505. void
  506. WINAPI
  507. EtwDumpEvent(
  508. PEVENT_TRACE pEvent
  509. )
  510. {
  511. PEVENT_TRACE_HEADER pHeader;
  512. ULONG Status = ERROR_SUCCESS;
  513. ULONG CachedFlags;
  514. USHORT CachedSize;
  515. ULONG RetryCount = 0;
  516. if (pEvent == NULL) {
  517. return;
  518. }
  519. TotalRelogEventsRead++;
  520. if (!bLoggerStarted) {
  521. Status = StartTraceW(&LoggerHandle, LOGGER_NAME, pLoggerInfo);
  522. if (Status != ERROR_SUCCESS) {
  523. return;
  524. }
  525. bLoggerStarted = TRUE;
  526. }
  527. pHeader = (PEVENT_TRACE_HEADER)pEvent->MofData;
  528. //
  529. // Ignore LogFileHeader Events
  530. //
  531. if( IsEqualGUID(&pEvent->Header.Guid, &EventTraceGuid) &&
  532. pEvent->Header.Class.Type == EVENT_TRACE_TYPE_INFO ) {
  533. return;
  534. }
  535. CachedSize = pEvent->Header.Size;
  536. CachedFlags = pEvent->Header.Flags;
  537. pEvent->Header.Size = sizeof(EVENT_TRACE);
  538. pEvent->Header.Flags |= (WNODE_FLAG_TRACED_GUID | WNODE_FLAG_NO_HEADER);
  539. do {
  540. Status = TraceEvent(LoggerHandle, (PEVENT_TRACE_HEADER)pEvent );
  541. if ((Status == ERROR_NOT_ENOUGH_MEMORY || Status == ERROR_OUTOFMEMORY) &&
  542. (RetryCount++ < MAX_RETRY_COUNT)) {
  543. _sleep(500); // Sleep for half a second.
  544. }
  545. else {
  546. break;
  547. }
  548. } while (TRUE);
  549. if (Status != ERROR_SUCCESS) {
  550. FailedEvents++;
  551. }
  552. //
  553. // Restore Cached values
  554. //
  555. pEvent->Header.Size = CachedSize;
  556. pEvent->Header.Flags = CachedFlags;
  557. }
  558. ULONG InitializeTrace(
  559. )
  560. {
  561. ULONG Status;
  562. Status = RegisterTraceGuids(
  563. (WMIDPREQUEST)ControlCallback,
  564. NULL,
  565. (LPCGUID)&ControlGuid[0],
  566. 1,
  567. &TraceGuidReg[0],
  568. NULL,
  569. NULL,
  570. &RegistrationHandle[0]
  571. );
  572. return(Status);
  573. }
  574. ULONG
  575. ControlCallback(
  576. IN WMIDPREQUESTCODE RequestCode,
  577. IN PVOID Context,
  578. IN OUT ULONG *InOutBufferSize,
  579. IN OUT PVOID Buffer
  580. )
  581. {
  582. return ERROR_SUCCESS;
  583. }
  584. ULONG
  585. WINAPI
  586. TerminateOnBufferCallback(
  587. PEVENT_TRACE_LOGFILE pLog
  588. )
  589. {
  590. if (LogFileCount == NumHdrProcessed)
  591. return (FALSE); // Terminate ProcessTrace on First BufferCallback
  592. else
  593. return (TRUE);
  594. }
  595. ULONG
  596. WINAPI
  597. BufferCallback(
  598. PEVENT_TRACE_LOGFILE pLog
  599. )
  600. {
  601. TotalRelogBuffersRead++;
  602. return (TRUE);
  603. }