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.

1608 lines
52 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. tracesup.c
  5. Abstract:
  6. Data Consumer Processing for version 1.2 and above
  7. Author:
  8. 07-May-2002 Melur Raghuraman
  9. Revision History:
  10. --*/
  11. #include "tracep.h"
  12. #define TIME_IN_RANGE(x, a, b) ((a == 0) || (x >= a)) && ((b == 0) || (x <= b))
  13. ULONG WmipTraceDebugLevel=0;
  14. // 0 No Debugging. Default
  15. // 1 Errors only
  16. // 2 API Level Messages
  17. // 4 Buffer Level Messages
  18. // 8 Event Level Messages
  19. // 16 All messages. Maximum
  20. //
  21. ULONG
  22. EtwpProcessTraceLogEx(
  23. PTRACEHANDLE HandleArray,
  24. PEVENT_TRACE_LOGFILEW *Logfiles,
  25. ULONG LogfileCount,
  26. LONGLONG StartTime,
  27. LONGLONG EndTime,
  28. ULONG Unicode
  29. )
  30. /*++
  31. Routine Description:
  32. This routine processes an array of traces from file. It goes through each
  33. event till the end of file, firing event callbacks (if any) along the way.
  34. It handles circular logfiles and windowing of data (with the given start
  35. and end times) correctly. When more than one trace it provides the callback
  36. in chronological order.
  37. Arguments:
  38. Logfiles Array of traces
  39. LogfileCount Number of traces
  40. StartTime Starting Time of the window of analysis
  41. EndTime Ending Time of the window of analysis
  42. Unicode Unicode Flag.
  43. Returned Value:
  44. Status Code.
  45. --*/
  46. {
  47. PTRACELOG_CONTEXT pContext;
  48. ULONG i;
  49. ULONG Status;
  50. LONGLONG CurrentTime = StartTime;
  51. LONGLONG PreviousTime = 0;
  52. LIST_ENTRY StreamListHead;
  53. //
  54. // This temporary list is a sorted list of streams. They are in
  55. // ascending order of TimeStamp. When each stream events are
  56. // exhausted they are dropped from this list. When this list is
  57. // empty, we are done.
  58. //
  59. InitializeListHead(&StreamListHead);
  60. Status = EtwpSetupLogFileStreams( &StreamListHead,
  61. HandleArray,
  62. Logfiles,
  63. LogfileCount,
  64. StartTime,
  65. EndTime,
  66. Unicode
  67. );
  68. if (Status != ERROR_SUCCESS) {
  69. goto Cleanup;
  70. }
  71. //
  72. // At this point, we have the local StreamList in sorted order for
  73. // the first event.
  74. //
  75. while (!IsListEmpty(&StreamListHead) ) {
  76. PLIST_ENTRY Next;
  77. PTRACE_STREAM_CONTEXT pStream;
  78. BOOLEAN EventInRange;
  79. Next = RemoveHeadList( &StreamListHead );
  80. pStream = CONTAINING_RECORD(Next, TRACE_STREAM_CONTEXT, Entry);
  81. CurrentTime = pStream->CurrentEvent.Header.TimeStamp.QuadPart;
  82. //
  83. // Check to see if TimeStamp is forward moving...
  84. //
  85. if (ETW_LOG_MAX()) {
  86. if (CurrentTime < PreviousTime) {
  87. DbgPrint("ETW: TimeStamp error. Current %I64u Previous %I64u\n",
  88. CurrentTime, PreviousTime);
  89. }
  90. PreviousTime = CurrentTime;
  91. }
  92. //
  93. // Make The Callback for the Current Event
  94. //
  95. if ( TIME_IN_RANGE(CurrentTime, StartTime, EndTime) ) {
  96. pStream->CbCount++;
  97. Status = EtwpDoEventCallbacks( &pStream->pContext->Logfile,
  98. &pStream->CurrentEvent
  99. );
  100. pStream->pContext->LastTimeStamp = CurrentTime;
  101. }
  102. else {
  103. if (ETW_LOG_MAX()) {
  104. DbgPrint("ETW: EventTime %I64u not in Range %I64u-%I64u\n",
  105. CurrentTime, StartTime, EndTime);
  106. }
  107. }
  108. //
  109. // Advance to next event for the stream
  110. //
  111. Status = EtwpAdvanceToNewEventEx(&StreamListHead, pStream);
  112. //
  113. // If the caller indicates to quit via the buffer callback, quit
  114. //
  115. if (Status == ERROR_CANCELLED)
  116. {
  117. if (ETW_LOG_API()) {
  118. DbgPrint("ETW: Processing Cancelled \n");
  119. }
  120. break;
  121. }
  122. }
  123. Cleanup:
  124. for (i=0; i < LogfileCount; i++) {
  125. pContext = (PTRACELOG_CONTEXT)Logfiles[i]->Context;
  126. if (pContext != NULL) {
  127. if ((Status == ERROR_SUCCESS) &&
  128. (pContext->ConversionFlags & EVENT_TRACE_READ_BEHIND) ) {
  129. EtwpCleanupTraceLog(pContext, TRUE);
  130. }
  131. else {
  132. EtwpCleanupTraceLog(pContext, FALSE);
  133. }
  134. }
  135. }
  136. return Status;
  137. }
  138. //
  139. // EtwpSetupLogFileStreams will set up the stream for each logfile.
  140. //
  141. ULONG
  142. EtwpSetupLogFileStreams(
  143. PLIST_ENTRY pStreamListHead,
  144. PTRACEHANDLE HandleArray,
  145. PEVENT_TRACE_LOGFILEW *Logfiles,
  146. ULONG LogfileCount,
  147. LONGLONG StartTime,
  148. LONGLONG EndTime,
  149. ULONG Unicode
  150. )
  151. {
  152. ULONG Status = ERROR_SUCCESS;
  153. long NumProc;
  154. PTRACELOG_CONTEXT pContext;
  155. long i, j;
  156. //
  157. // Breakdown each logfile into streams
  158. //
  159. for (i=0; i<(long)LogfileCount; i++) {
  160. NumProc = Logfiles[i]->LogfileHeader.NumberOfProcessors;
  161. pContext = Logfiles[i]->Context;
  162. if (NumProc == 0) NumProc = 1;
  163. //
  164. // Before Setting up the streams find the last buffer range
  165. //
  166. EtwpGetLastBufferWithMarker( pContext );
  167. //
  168. // Set up the Generic Streams
  169. //
  170. for (j = 0; j < NumProc; j++) {
  171. Status = EtwpAddTraceStream( pStreamListHead,
  172. pContext,
  173. WMI_BUFFER_TYPE_GENERIC,
  174. StartTime,
  175. EndTime,
  176. j
  177. );
  178. //
  179. // The LogFileHeader is logged as a RunDown buffer.
  180. //
  181. Status = EtwpAddTraceStream( pStreamListHead,
  182. pContext,
  183. WMI_BUFFER_TYPE_RUNDOWN,
  184. StartTime,
  185. EndTime,
  186. j
  187. );
  188. if (Logfiles[i]->IsKernelTrace) {
  189. if ( PerfIsGroupOnInGroupMask(PERF_CONTEXT_SWITCH, &pContext->PerfGroupMask) ) {
  190. Status = EtwpAddTraceStream( pStreamListHead,
  191. pContext,
  192. WMI_BUFFER_TYPE_CTX_SWAP,
  193. StartTime, EndTime,
  194. j
  195. );
  196. }
  197. }
  198. }
  199. }
  200. return Status;
  201. }
  202. //
  203. // This routine will find the last buffer in the logfile with
  204. // WMI_BUFFER_FLAG_FLUSH_MARKER set. We can only process upto
  205. // this point.
  206. //
  207. ULONG
  208. EtwpGetLastBufferWithMarker(
  209. PTRACELOG_CONTEXT pContext
  210. )
  211. {
  212. ULONGLONG ReadPosition;
  213. PVOID pTmpBuffer;
  214. ULONG BufferSize;
  215. ULONG nBytesRead=0;
  216. PWMI_BUFFER_HEADER pHeader;
  217. ULONG Status;
  218. EtwpAssert(pContext != NULL);
  219. pContext->MaxReadPosition = 0;
  220. BufferSize = pContext->BufferSize;
  221. if (ETW_LOG_MAX()) {
  222. ReadPosition = 0;
  223. pTmpBuffer = EtwpAlloc(BufferSize);
  224. if (pTmpBuffer == NULL) {
  225. return ERROR_OUTOFMEMORY;
  226. }
  227. dumpmore:
  228. pContext->AsynchRead.Offset = (DWORD)(ReadPosition & 0xFFFFFFFF);
  229. pContext->AsynchRead.OffsetHigh = (DWORD)(ReadPosition >> 32);
  230. Status = EtwpSynchReadFile(pContext->Handle,
  231. pTmpBuffer,
  232. BufferSize,
  233. &nBytesRead,
  234. &pContext->AsynchRead);
  235. if (nBytesRead == 0) {
  236. DbgPrint("End OF File reached\n");
  237. EtwpFree(pTmpBuffer);
  238. }
  239. else {
  240. PWMI_BUFFER_HEADER pHeader = (PWMI_BUFFER_HEADER) pTmpBuffer;
  241. PWMI_CLIENT_CONTEXT ClientContext = (PWMI_CLIENT_CONTEXT)&pHeader->Wnode.ClientContext;
  242. DbgPrint("ReadPos: %I64u BufferType %d BufferFlag %d Proc %d \n",
  243. ReadPosition, pHeader->BufferType, pHeader->BufferFlag, ClientContext->ProcessorNumber);
  244. ReadPosition += BufferSize;
  245. goto dumpmore;
  246. }
  247. }
  248. if (pContext->Logfile.LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) {
  249. pContext->MaxReadPosition = pContext->Logfile.LogfileHeader.MaximumFileSize * 1024 * 1024;
  250. return ERROR_SUCCESS;
  251. }
  252. ReadPosition = pContext->BufferCount * pContext->BufferSize;
  253. if ( (pContext->ConversionFlags & EVENT_TRACE_READ_BEHIND) !=
  254. EVENT_TRACE_READ_BEHIND) {
  255. pContext->MaxReadPosition = ReadPosition;
  256. return ERROR_SUCCESS;
  257. }
  258. if (ReadPosition < BufferSize) {
  259. if (ETW_LOG_ERROR()) {
  260. DbgPrint("ETW: ReadPosition %I64u is less than BufferSize %d \n",
  261. ReadPosition, BufferSize);
  262. }
  263. return ERROR_SUCCESS;
  264. }
  265. //
  266. // Set the ReadPosition to the start of last buffer
  267. //
  268. ReadPosition -= BufferSize;
  269. pTmpBuffer = EtwpAlloc(BufferSize);
  270. if (pTmpBuffer == NULL) {
  271. if (ETW_LOG_ERROR()) {
  272. DbgPrint("ETW: Allocation Failed %d Bytes, Line %d\n",
  273. BufferSize, __LINE__);
  274. }
  275. return ERROR_OUTOFMEMORY;
  276. }
  277. Retry:
  278. pContext->AsynchRead.Offset = (DWORD)(ReadPosition & 0xFFFFFFFF);
  279. pContext->AsynchRead.OffsetHigh = (DWORD)(ReadPosition >> 32);
  280. Status = EtwpSynchReadFile(pContext->Handle,
  281. pTmpBuffer,
  282. BufferSize,
  283. &nBytesRead,
  284. &pContext->AsynchRead);
  285. if (nBytesRead == 0) {
  286. EtwpDebugPrint(("ETW Error: No data in file. \n"));
  287. pContext->MaxReadPosition = 0;
  288. EtwpFree(pTmpBuffer);
  289. return ERROR_SUCCESS;
  290. }
  291. pHeader = (PWMI_BUFFER_HEADER) pTmpBuffer;
  292. if (pHeader->BufferFlag & WMI_BUFFER_FLAG_FLUSH_MARKER) {
  293. //
  294. // Found the Marker. It is safe to process events upto this point.
  295. //
  296. if (ETW_LOG_BUFFER()) {
  297. DbgPrint("ETW: Found Flush Marker at %I64u\n", ReadPosition);
  298. }
  299. pContext->MaxReadPosition = ReadPosition;
  300. EtwpFree(pTmpBuffer);
  301. return ERROR_SUCCESS;
  302. }
  303. if (ReadPosition < BufferSize) {
  304. EtwpAssert(ReadPosition == 0);
  305. pContext->MaxReadPosition = 0;
  306. EtwpFree(pTmpBuffer);
  307. return ERROR_SUCCESS;
  308. }
  309. else {
  310. ReadPosition -= BufferSize;
  311. goto Retry;
  312. }
  313. if (ETW_LOG_ERROR()) {
  314. DbgPrint("ETW: Could not find Last Marker. Corrupt File!\n");
  315. }
  316. EtwpAssert(FALSE);
  317. EtwpFree(pTmpBuffer);
  318. return ERROR_SUCCESS;
  319. }
  320. ULONG
  321. EtwpAddTraceStream(
  322. PLIST_ENTRY pStreamListHead,
  323. PTRACELOG_CONTEXT pContext,
  324. USHORT StreamType,
  325. LONGLONG StartTime,
  326. LONGLONG EndTime,
  327. ULONG ProcessorNumber
  328. )
  329. {
  330. ULONG Status = ERROR_SUCCESS;
  331. PTRACE_STREAM_CONTEXT pStream;
  332. pStream = (PTRACE_STREAM_CONTEXT) EtwpAlloc( sizeof(TRACE_STREAM_CONTEXT) );
  333. if (pStream == NULL) {
  334. if (ETW_LOG_ERROR()) {
  335. DbgPrint("ETW: Allocation Failed %d Bytes, Line %d\n",
  336. sizeof(TRACE_STREAM_CONTEXT), __LINE__);
  337. }
  338. return ERROR_OUTOFMEMORY;
  339. }
  340. RtlZeroMemory(pStream, sizeof(TRACE_STREAM_CONTEXT) );
  341. pStream->Type = StreamType;
  342. pStream->ProcessorNumber = ProcessorNumber;
  343. pStream->pContext = pContext;
  344. EtwpAssert( pContext != NULL );
  345. EtwpAssert(pContext->BufferSize != 0);
  346. pStream->StreamBuffer = EtwpAlloc(pContext->BufferSize);
  347. if (pStream->StreamBuffer == NULL) {
  348. if (ETW_LOG_ERROR()) {
  349. DbgPrint("ETW: Allocation Failed %d Bytes, Line %d\n",
  350. pContext->BufferSize, __LINE__);
  351. }
  352. EtwpFree(pStream);
  353. return ERROR_OUTOFMEMORY;
  354. }
  355. //
  356. // For Circular, Jump off to First Buffer
  357. // For Non-circular with StartTime specified, try to use the cached offset
  358. //
  359. if (pContext->Logfile.LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) {
  360. if (StreamType != WMI_BUFFER_TYPE_RUNDOWN) {
  361. pStream->ReadPosition = pContext->FirstBuffer *
  362. pContext->BufferSize;
  363. }
  364. else {
  365. pStream->ReadPosition = 0;
  366. }
  367. }
  368. else {
  369. if ( (StartTime > 0) && (StartTime >= pContext->LastTimeStamp) ) {
  370. pStream->ReadPosition = pContext->OldMaxReadPosition +
  371. pContext->BufferSize;
  372. if (pStream->ReadPosition > pContext->MaxReadPosition) {
  373. EtwpFree(pStream->StreamBuffer);
  374. EtwpFree(pStream);
  375. return Status;
  376. }
  377. }
  378. }
  379. Status = EtwpGetNextBuffer(pStream);
  380. //
  381. // If Read failed, it is not fatal. There are no
  382. // events in this stream. Set the stream to not active and
  383. // continue.
  384. if (pStream->bActive) {
  385. if (ETW_LOG_BUFFER()) {
  386. DbgPrint("ETW: Added Stream %d Proc %d ReadPosition %I64u\n",
  387. pStream->Type, pStream->ProcessorNumber, pStream->ReadPosition);
  388. }
  389. EtwpAdvanceToNewEventEx(pStreamListHead, pStream);
  390. InsertTailList(&pContext->StreamListHead, &pStream->AllocEntry);
  391. }
  392. else {
  393. EtwpFree(pStream->StreamBuffer);
  394. EtwpFree(pStream);
  395. }
  396. return Status;
  397. }
  398. ULONG
  399. EtwpGetNextBuffer(
  400. PTRACE_STREAM_CONTEXT pStream
  401. )
  402. {
  403. PEVENT_TRACE_LOGFILE LogFile;
  404. PTRACELOG_CONTEXT pContext;
  405. HANDLE hFile;
  406. NTSTATUS NtStatus;
  407. ULONG BufferSize;
  408. ULONGLONG ReadPosition;
  409. PWMI_CLIENT_CONTEXT ClientContext;
  410. ULONG nBytesRead=0;
  411. PWMI_BUFFER_HEADER pHeader;
  412. ULONG Status;
  413. ULONGLONG FirstOffset, LastOffset, StartOffset;
  414. ULONG ProcessorNumber = pStream->ProcessorNumber;
  415. pContext = pStream->pContext;
  416. LogFile = &pContext->Logfile;
  417. hFile = pContext->Handle;
  418. BufferSize = pContext->BufferSize;
  419. pStream->EventCount = 0;
  420. FirstOffset = pContext->FirstBuffer * BufferSize;
  421. LastOffset = pContext->LastBuffer * BufferSize;
  422. StartOffset = pContext->StartBuffer * BufferSize;
  423. //
  424. // Need to handle FileType properly here.
  425. //
  426. retry:
  427. ReadPosition = pStream->ReadPosition;
  428. if (ReadPosition > pContext->MaxReadPosition) {
  429. //
  430. // Only Valid for Sequential. For read behind mode, we do not
  431. // process past the MaxReadPosition.
  432. //
  433. if (pContext->ConversionFlags & EVENT_TRACE_READ_BEHIND) {
  434. if (ETW_LOG_BUFFER()) {
  435. DbgPrint("ETW: Reached MaxReadPosition for Stream %d Proc %d\n", pStream->Type, pStream->ProcessorNumber);
  436. }
  437. pStream->bActive = FALSE;
  438. return ERROR_SUCCESS;
  439. }
  440. }
  441. if (pContext->Logfile.LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) {
  442. //
  443. // If we have scanned once and reached FirstBuffer, then we are done.
  444. //
  445. if ( (ReadPosition >= FirstOffset) && pStream->ScanDone) {
  446. if (ETW_LOG_BUFFER()) {
  447. DbgPrint("ETW: Stream %d Proc %d Circular Mode Done.\n",
  448. pStream->Type, pStream->ProcessorNumber);
  449. }
  450. pStream->bActive = FALSE;
  451. return ERROR_SUCCESS;
  452. }
  453. }
  454. pContext->AsynchRead.Offset = (DWORD)(ReadPosition & 0xFFFFFFFF);
  455. pContext->AsynchRead.OffsetHigh = (DWORD)(ReadPosition >> 32);
  456. Status = EtwpSynchReadFile(pContext->Handle,
  457. (LPVOID)pStream->StreamBuffer,
  458. BufferSize,
  459. &nBytesRead,
  460. &pContext->AsynchRead);
  461. if (nBytesRead == 0) {
  462. if (pContext->Logfile.LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) {
  463. if (ReadPosition >= LastOffset && !pStream->ScanDone) {
  464. //
  465. // Rundown stream ends when we reach EOF
  466. //
  467. if (pStream->Type == WMI_BUFFER_TYPE_RUNDOWN) {
  468. pStream->ScanDone = TRUE;
  469. pStream->bActive = FALSE;
  470. return ERROR_SUCCESS;
  471. }
  472. pStream->ReadPosition = StartOffset;
  473. pStream->ScanDone = TRUE;
  474. goto retry;
  475. }
  476. else {
  477. pStream->bActive = FALSE;
  478. }
  479. }
  480. else {
  481. pStream->bActive = FALSE;
  482. }
  483. return ERROR_SUCCESS;
  484. }
  485. pStream->ReadPosition += BufferSize;
  486. pHeader = (PWMI_BUFFER_HEADER) pStream->StreamBuffer;
  487. ClientContext = (PWMI_CLIENT_CONTEXT)&pHeader->Wnode.ClientContext;
  488. if ( ClientContext->ProcessorNumber
  489. >= LogFile->LogfileHeader.NumberOfProcessors) {
  490. ClientContext->ProcessorNumber = (UCHAR) 0;
  491. }
  492. if ( (pStream->Type != pHeader->BufferType) ||
  493. (ClientContext->ProcessorNumber != ProcessorNumber) ) {
  494. goto retry;
  495. }
  496. //
  497. // If we got here, then we have the right buffer. Set the first
  498. // offset so that events can parsed.
  499. //
  500. pStream->CurrentOffset = sizeof(WMI_BUFFER_HEADER);
  501. pStream->bActive = TRUE;
  502. return ERROR_SUCCESS;
  503. }
  504. ULONG
  505. EtwpAdvanceToNewEventEx(
  506. PLIST_ENTRY pStreamListHead,
  507. PTRACE_STREAM_CONTEXT pStream
  508. )
  509. {
  510. ULONG Size=0;
  511. WMI_HEADER_TYPE HdrType = WMIHT_NONE;
  512. PVOID pBuffer;
  513. ULONG Offset;
  514. PTRACELOG_CONTEXT pContext;
  515. PEVENT_TRACE pEvent;
  516. ULONG Status;
  517. PEVENT_TRACE_LOGFILEW logfile;
  518. //
  519. // This routine advances to next event for this stream
  520. //
  521. Retry:
  522. pBuffer = pStream->StreamBuffer;
  523. Offset = pStream->CurrentOffset;
  524. pContext = pStream->pContext;
  525. EtwpAssert(pBuffer != NULL);
  526. EtwpAssert(pContext != NULL);
  527. pEvent = &pStream->CurrentEvent;
  528. if ((HdrType = WmiGetTraceHeader(pBuffer, Offset, &Size)) != WMIHT_NONE) {
  529. if (Size > 0) {
  530. LONGLONG TimeStamp, NextTimeStamp;
  531. PLIST_ENTRY Head, Next;
  532. PTRACE_STREAM_CONTEXT CurrentStream;
  533. EtwpParseTraceEvent( pContext,
  534. pBuffer,
  535. Offset,
  536. HdrType,
  537. pEvent,
  538. sizeof(EVENT_TRACE)
  539. );
  540. pStream->CurrentOffset += Size;
  541. pStream->EventCount++;
  542. Head = pStreamListHead;
  543. Next = Head->Flink;
  544. TimeStamp = pStream->CurrentEvent.Header.TimeStamp.QuadPart;
  545. while (Head != Next) {
  546. CurrentStream = CONTAINING_RECORD(Next, TRACE_STREAM_CONTEXT, Entry);
  547. NextTimeStamp = CurrentStream->CurrentEvent.Header.TimeStamp.QuadPart;
  548. if (TimeStamp < NextTimeStamp) {
  549. InsertHeadList(Next->Blink, &pStream->Entry);
  550. break;
  551. }
  552. //
  553. // In case of a Tie in TimeStamps, we try to order the events
  554. // using Sequence numbers, if available. FieldTypeFlags in the
  555. // header indicates if this event has a sequence number.
  556. //
  557. else if (TimeStamp == NextTimeStamp) {
  558. USHORT pFlags = pStream->CurrentEvent.Header.FieldTypeFlags;
  559. USHORT cFlags = CurrentStream->CurrentEvent.Header.FieldTypeFlags;
  560. if (pFlags & EVENT_TRACE_USE_SEQUENCE) {
  561. if ( (cFlags & EVENT_TRACE_USE_SEQUENCE) &&
  562. (pStream->CurrentEvent.InstanceId <
  563. CurrentStream->CurrentEvent.InstanceId)) {
  564. InsertHeadList(Next->Blink, &pStream->Entry);
  565. break;
  566. }
  567. }
  568. else {
  569. InsertHeadList(Next->Blink, &pStream->Entry);
  570. break;
  571. }
  572. }
  573. Next = Next->Flink;
  574. }
  575. if (Next == Head) {
  576. InsertTailList(Head, &pStream->Entry);
  577. }
  578. }
  579. return ERROR_SUCCESS;
  580. }
  581. //
  582. // No more events in this buffer. Advance to next buffer and retry.
  583. //
  584. logfile = &pContext->Logfile;
  585. if (logfile->BufferCallback) {
  586. ULONG bRetVal;
  587. PWMI_BUFFER_HEADER pHeader = (PWMI_BUFFER_HEADER)pBuffer;
  588. logfile->Filled = (ULONG)pHeader->Offset;
  589. logfile->BuffersRead++;
  590. try {
  591. bRetVal = (*logfile->BufferCallback) (logfile);
  592. if (!bRetVal) {
  593. return ERROR_CANCELLED;
  594. }
  595. } except (EXCEPTION_EXECUTE_HANDLER) {
  596. Status = GetExceptionCode();
  597. EtwpDebugPrint(("TRACE: BufferCallback threw exception %X\n",
  598. Status));
  599. EtwpSetDosError(EtwpNtStatusToDosError(Status));
  600. return ERROR_CANCELLED; // so that realtime also cleans up.
  601. }
  602. }
  603. if (ETW_LOG_BUFFER()) {
  604. PWMI_BUFFER_HEADER pHeader = (PWMI_BUFFER_HEADER)pBuffer;
  605. DbgPrint("ETW: %d Type %d Flag %d Proc %d Events %d Filled %d Offset %d ReadPos %I64u TimeStamp %I64u\n",
  606. logfile->BuffersRead, pStream->Type, pHeader->BufferFlag, pStream->ProcessorNumber, pStream->EventCount, logfile->Filled,
  607. pStream->CurrentOffset, pStream->ReadPosition, pContext->LastTimeStamp);
  608. }
  609. Status = EtwpGetNextBuffer(pStream);
  610. if (pStream->bActive) {
  611. goto Retry;
  612. }
  613. return ERROR_SUCCESS;
  614. }
  615. WMI_HEADER_TYPE
  616. WMIAPI
  617. WmiGetTraceHeader(
  618. IN PVOID LogBuffer,
  619. IN ULONG Offset,
  620. OUT ULONG *Size
  621. )
  622. {
  623. ULONG Status = ERROR_SUCCESS;
  624. ULONG TraceType;
  625. try {
  626. TraceType = EtwpGetNextEventOffsetType(
  627. (PUCHAR)LogBuffer,
  628. Offset,
  629. Size
  630. );
  631. return EtwpConvertTraceTypeToEnum(TraceType);
  632. } except (EXCEPTION_EXECUTE_HANDLER) {
  633. Status = GetExceptionCode();
  634. EtwpDebugPrint(("TRACE: WmiGetTraceHeader threw exception %X\n",
  635. Status));
  636. Status = EtwpSetDosError(EtwpNtStatusToDosError(Status));
  637. }
  638. return 0;
  639. }
  640. ULONG
  641. EtwpGetNextEventOffsetType(
  642. PUCHAR pBuffer,
  643. ULONG Offset,
  644. PULONG RetSize
  645. )
  646. {
  647. ULONG nSize;
  648. ULONG TraceMarker;
  649. ULONG TraceType = 0;
  650. PWMI_BUFFER_HEADER Header;
  651. ULONG Alignment;
  652. ULONG BufferSize;
  653. if (RetSize != NULL) {
  654. *RetSize = 0;
  655. }
  656. if (pBuffer == NULL) {
  657. return 0;
  658. }
  659. Header = (PWMI_BUFFER_HEADER)pBuffer;
  660. Alignment = Header->ClientContext.Alignment;
  661. BufferSize = Header->Wnode.BufferSize;
  662. //
  663. // Check for end of buffer (w/o End of Buffer Marker case...)
  664. //
  665. if ( Offset >= (BufferSize - sizeof(long)) ){
  666. return 0;
  667. }
  668. TraceMarker = *((PULONG)(pBuffer + Offset));
  669. if (TraceMarker == 0xFFFFFFFF) {
  670. return 0;
  671. }
  672. if (TraceMarker & TRACE_HEADER_FLAG) {
  673. //
  674. // If the first bit is set, then it is either TRACE or PERF record.
  675. //
  676. if (TraceMarker & TRACE_HEADER_EVENT_TRACE) { // One of Ours.
  677. TraceType = (TraceMarker & TRACE_HEADER_ENUM_MASK) >> 16;
  678. switch(TraceType) {
  679. //
  680. // ISSUE: Need to split the two so we can process cross platform
  681. // shsiao 03/22/2000
  682. //
  683. case TRACE_HEADER_TYPE_PERFINFO32:
  684. case TRACE_HEADER_TYPE_PERFINFO64:
  685. {
  686. PUSHORT Size;
  687. Size = (PUSHORT) (pBuffer + Offset + sizeof(ULONG));
  688. nSize = *Size;
  689. break;
  690. }
  691. case TRACE_HEADER_TYPE_SYSTEM32:
  692. case TRACE_HEADER_TYPE_SYSTEM64:
  693. {
  694. PUSHORT Size;
  695. Size = (PUSHORT) (pBuffer + Offset + sizeof(ULONG));
  696. nSize = *Size;
  697. break;
  698. }
  699. case TRACE_HEADER_TYPE_FULL_HEADER:
  700. case TRACE_HEADER_TYPE_INSTANCE:
  701. {
  702. PUSHORT Size;
  703. Size = (PUSHORT)(pBuffer + Offset);
  704. nSize = *Size;
  705. break;
  706. }
  707. default:
  708. {
  709. return 0;
  710. }
  711. }
  712. }
  713. else if ((TraceMarker & TRACE_HEADER_ULONG32_TIME) ==
  714. TRACE_HEADER_ULONG32_TIME) {
  715. PUSHORT Size;
  716. Size = (PUSHORT) (pBuffer + Offset);
  717. nSize = *Size;
  718. TraceType = TRACE_HEADER_TYPE_TIMED;
  719. }
  720. else if ((TraceMarker & TRACE_HEADER_ULONG32) ==
  721. TRACE_HEADER_ULONG32) {
  722. PUSHORT Size;
  723. Size = (PUSHORT) (pBuffer + Offset);
  724. nSize = *Size;
  725. TraceType = TRACE_HEADER_TYPE_ULONG32;
  726. }
  727. else if ((TraceMarker & TRACE_MESSAGE) ==
  728. TRACE_MESSAGE) {
  729. PUSHORT Size;
  730. Size = (PUSHORT) (pBuffer + Offset) ;
  731. nSize = *Size;
  732. TraceType = TRACE_HEADER_TYPE_MESSAGE;
  733. }
  734. else {
  735. return 0;
  736. }
  737. }
  738. else { // Must be WNODE_HEADER
  739. PUSHORT Size;
  740. Size = (PUSHORT) (pBuffer + Offset);
  741. nSize = *Size;
  742. TraceType = TRACE_HEADER_TYPE_WNODE_HEADER;
  743. }
  744. //
  745. // Check for End Of Buffer Marker
  746. //
  747. if (nSize == 0xFFFFFFFF) {
  748. return 0;
  749. }
  750. if (Alignment != 0) {
  751. nSize = (ULONG) ALIGN_TO_POWER2(nSize, Alignment);
  752. }
  753. //
  754. // Check for larger than BufferSize
  755. //
  756. if (nSize >= BufferSize) {
  757. return 0;
  758. }
  759. if (RetSize != NULL) {
  760. *RetSize = nSize;
  761. }
  762. return TraceType;
  763. }
  764. ULONG
  765. EtwpParseTraceEvent(
  766. IN PTRACELOG_CONTEXT pContext,
  767. IN PVOID LogBuffer,
  768. IN ULONG Offset,
  769. IN WMI_HEADER_TYPE HeaderType,
  770. IN OUT PVOID EventInfo,
  771. IN ULONG EventInfoSize
  772. )
  773. {
  774. PWMI_BUFFER_HEADER Header = (PWMI_BUFFER_HEADER)LogBuffer;
  775. ULONG Status = ERROR_SUCCESS;
  776. PVOID pEvent;
  777. if ( (LogBuffer == NULL) ||
  778. (EventInfo == NULL) ||
  779. (EventInfoSize < sizeof(EVENT_TRACE_HEADER)) )
  780. {
  781. return (ERROR_INVALID_PARAMETER);
  782. }
  783. Status = EtwpCreateGuidMapping();
  784. if (Status != ERROR_SUCCESS) {
  785. return Status;
  786. }
  787. try {
  788. RtlZeroMemory(EventInfo, sizeof(EVENT_TRACE));
  789. pEvent = (void*) ((PUCHAR)LogBuffer + Offset);
  790. EtwpCopyCurrentEvent(pContext,
  791. pEvent,
  792. EventInfo,
  793. EtwpConvertEnumToTraceType(HeaderType),
  794. (PWMI_BUFFER_HEADER)LogBuffer
  795. );
  796. ( (PEVENT_TRACE)EventInfo)->ClientContext = Header->Wnode.ClientContext;
  797. } except (EXCEPTION_EXECUTE_HANDLER) {
  798. Status = GetExceptionCode();
  799. EtwpDebugPrint(("TRACE: EtwpParseTraceEvent threw exception %X\n",
  800. Status));
  801. Status = EtwpSetDosError(EtwpNtStatusToDosError(Status));
  802. }
  803. return Status;
  804. }
  805. ULONG
  806. EtwpCopyCurrentEvent(
  807. PTRACELOG_CONTEXT pContext,
  808. PVOID pHeader,
  809. PEVENT_TRACE pEvent,
  810. ULONG TraceType,
  811. PWMI_BUFFER_HEADER LogBuffer
  812. )
  813. /*++
  814. Routine Description:
  815. This routine copies the Current Event from the logfile buffer stream to
  816. the CurrentEvent structure provided by the caller. The routine takes
  817. care of the differences between kernel event and user events by mapping
  818. all events uniformly to the EVENT_TRACE_HEADER structure.
  819. Arguments:
  820. pHeader Pointer to the datablock in the input stream (logfile).
  821. pEvent Current Event to which the data is copied.
  822. TraceType Enum indicating the header type.
  823. LogBuffer The buffer
  824. Returned Value:
  825. Status indicating success or failure.
  826. --*/
  827. {
  828. PEVENT_TRACE_HEADER pWnode;
  829. PEVENT_TRACE_HEADER pWnodeHeader;
  830. ULONG nGroupType;
  831. LPGUID pGuid;
  832. ULONG UsePerfClock = 0;
  833. ULONG UseBasePtr = 0;
  834. ULONG PrivateLogger=0;
  835. if (pHeader == NULL || pEvent == NULL)
  836. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  837. if (pContext != NULL) {
  838. UsePerfClock = pContext->UsePerfClock;
  839. UseBasePtr = pContext->ConversionFlags & EVENT_TRACE_GET_RAWEVENT;
  840. PrivateLogger = (pContext->Logfile.LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE);
  841. }
  842. switch(TraceType) {
  843. //
  844. // ISSUE: Need to split the two so we can process cross platform.
  845. // shsiao 03/22/2000
  846. //
  847. case TRACE_HEADER_TYPE_PERFINFO32:
  848. case TRACE_HEADER_TYPE_PERFINFO64:
  849. {
  850. PPERFINFO_TRACE_HEADER pPerfHeader;
  851. pPerfHeader = (PPERFINFO_TRACE_HEADER) pHeader;
  852. nGroupType = pPerfHeader->Packet.Group << 8;
  853. if ((nGroupType == EVENT_TRACE_GROUP_PROCESS) &&
  854. (pPerfHeader->Packet.Type == EVENT_TRACE_TYPE_LOAD)) {
  855. nGroupType += pPerfHeader->Packet.Type;
  856. }
  857. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  858. pWnode = (PEVENT_TRACE_HEADER) &pEvent->Header;
  859. pGuid = EtwpGroupTypeToGuid(nGroupType);
  860. if (pGuid != NULL)
  861. RtlCopyMemory(&pWnode->Guid, pGuid, sizeof(GUID));
  862. pWnode->Size = pPerfHeader->Packet.Size;
  863. pWnode->Class.Type = pPerfHeader->Packet.Type;
  864. pWnode->Class.Version = pPerfHeader->Version;
  865. EtwpCalculateCurrentTime( &pWnode->TimeStamp,
  866. &pPerfHeader->SystemTime,
  867. pContext );
  868. //
  869. // PERFINFO headers does not have ThreadId or CPU Times
  870. //
  871. if( LogBuffer->Flags & WNODE_FLAG_THREAD_BUFFER ){
  872. pWnode->ThreadId = LogBuffer->CurrentOffset;
  873. } else {
  874. pWnode->ProcessId = -1;
  875. pWnode->ThreadId = -1;
  876. }
  877. if (UseBasePtr) {
  878. pEvent->MofData = (PVOID) pHeader;
  879. pEvent->MofLength = pWnode->Size;
  880. //
  881. // Override the Timestamp with SystemTime from PERFCounter.
  882. // If rdtsc is used no conversion is done.
  883. //
  884. if (UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  885. pPerfHeader->SystemTime = pWnode->TimeStamp;
  886. }
  887. }
  888. else if (pWnode->Size > FIELD_OFFSET(PERFINFO_TRACE_HEADER, Data)) {
  889. pEvent->MofData = (PVOID) ((char*) pHeader +
  890. FIELD_OFFSET(PERFINFO_TRACE_HEADER, Data));
  891. pEvent->MofLength = pWnode->Size -
  892. FIELD_OFFSET(PERFINFO_TRACE_HEADER, Data);
  893. }
  894. pEvent->Header.FieldTypeFlags = EVENT_TRACE_USE_NOCPUTIME;
  895. break;
  896. }
  897. case TRACE_HEADER_TYPE_SYSTEM32:
  898. {
  899. PSYSTEM_TRACE_HEADER pSystemHeader32;
  900. pSystemHeader32 = (PSYSTEM_TRACE_HEADER) pHeader;
  901. nGroupType = pSystemHeader32->Packet.Group << 8;
  902. if ((nGroupType == EVENT_TRACE_GROUP_PROCESS) &&
  903. (pSystemHeader32->Packet.Type == EVENT_TRACE_TYPE_LOAD)) {
  904. nGroupType += pSystemHeader32->Packet.Type;
  905. }
  906. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  907. pWnode = (PEVENT_TRACE_HEADER) &pEvent->Header;
  908. pGuid = EtwpGroupTypeToGuid(nGroupType);
  909. if (pGuid != NULL)
  910. RtlCopyMemory(&pWnode->Guid, pGuid, sizeof(GUID));
  911. pWnode->Size = pSystemHeader32->Packet.Size;
  912. pWnode->ThreadId = pSystemHeader32->ThreadId;
  913. pWnode->ProcessId = pSystemHeader32->ProcessId;
  914. pWnode->KernelTime = pSystemHeader32->KernelTime;
  915. pWnode->UserTime = pSystemHeader32->UserTime;
  916. pWnode->Class.Type = pSystemHeader32->Packet.Type;
  917. pWnode->Class.Version = pSystemHeader32->Version;
  918. EtwpCalculateCurrentTime( &pWnode->TimeStamp,
  919. &pSystemHeader32->SystemTime,
  920. pContext );
  921. if (UseBasePtr) {
  922. pEvent->MofData = (PVOID) pHeader;
  923. pEvent->MofLength = pWnode->Size;
  924. if (UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  925. pSystemHeader32->SystemTime = pWnode->TimeStamp;
  926. }
  927. }
  928. else {
  929. pWnode->FieldTypeFlags = 0;
  930. if (pWnode->Size > sizeof(SYSTEM_TRACE_HEADER)) {
  931. pEvent->MofData = (PVOID) ((char*) pHeader +
  932. sizeof(SYSTEM_TRACE_HEADER));
  933. pEvent->MofLength = pWnode->Size - sizeof(SYSTEM_TRACE_HEADER);
  934. }
  935. }
  936. break;
  937. }
  938. case TRACE_HEADER_TYPE_SYSTEM64:
  939. {
  940. PSYSTEM_TRACE_HEADER pSystemHeader64;
  941. pSystemHeader64 = (PSYSTEM_TRACE_HEADER) pHeader;
  942. nGroupType = pSystemHeader64->Packet.Group << 8;
  943. if ((nGroupType == EVENT_TRACE_GROUP_PROCESS) &&
  944. (pSystemHeader64->Packet.Type == EVENT_TRACE_TYPE_LOAD)) {
  945. nGroupType += pSystemHeader64->Packet.Type;
  946. }
  947. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  948. pWnode = (PEVENT_TRACE_HEADER) &pEvent->Header;
  949. pGuid = EtwpGroupTypeToGuid(nGroupType);
  950. if (pGuid != NULL)
  951. RtlCopyMemory(&pWnode->Guid, pGuid, sizeof(GUID));
  952. pWnode->Size = pSystemHeader64->Packet.Size;
  953. pWnode->ThreadId = pSystemHeader64->ThreadId;
  954. pWnode->ProcessId = pSystemHeader64->ProcessId;
  955. pWnode->KernelTime = pSystemHeader64->KernelTime;
  956. pWnode->UserTime = pSystemHeader64->UserTime;
  957. pWnode->Class.Type = pSystemHeader64->Packet.Type;
  958. pWnode->Class.Version = pSystemHeader64->Version;
  959. EtwpCalculateCurrentTime( &pWnode->TimeStamp,
  960. &pSystemHeader64->SystemTime,
  961. pContext );
  962. if (UseBasePtr) {
  963. pEvent->MofData = (PVOID) pHeader;
  964. pEvent->MofLength = pWnode->Size;
  965. if (UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  966. pSystemHeader64->SystemTime = pWnode->TimeStamp;
  967. }
  968. }
  969. else {
  970. pWnode->FieldTypeFlags = 0;
  971. if (pWnode->Size > sizeof(SYSTEM_TRACE_HEADER)) {
  972. pEvent->MofData = (PVOID) ((char*) pHeader +
  973. sizeof(SYSTEM_TRACE_HEADER));
  974. pEvent->MofLength = pWnode->Size - sizeof(SYSTEM_TRACE_HEADER);
  975. }
  976. }
  977. break;
  978. }
  979. case TRACE_HEADER_TYPE_FULL_HEADER:
  980. {
  981. pWnodeHeader = (PEVENT_TRACE_HEADER) pHeader;
  982. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  983. pWnode = (PEVENT_TRACE_HEADER) &pEvent->Header;
  984. RtlCopyMemory(pWnode,
  985. pWnodeHeader,
  986. sizeof(EVENT_TRACE_HEADER)
  987. );
  988. EtwpCalculateCurrentTime( &pWnode->TimeStamp,
  989. &pWnodeHeader->TimeStamp,
  990. pContext );
  991. if (UseBasePtr) {
  992. pEvent->Header.Size = pWnodeHeader->Size;
  993. pEvent->MofData = (PVOID)pHeader;
  994. pEvent->MofLength = pWnodeHeader->Size;
  995. if (UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  996. pWnodeHeader->TimeStamp = pWnode->TimeStamp;
  997. }
  998. }
  999. else {
  1000. //
  1001. // If the data came from Process Private Logger, then
  1002. // mark the ProcessorTime field as valid
  1003. //
  1004. pEvent->Header.FieldTypeFlags = (PrivateLogger) ? EVENT_TRACE_USE_PROCTIME : 0;
  1005. if (pWnodeHeader->Size > sizeof(EVENT_TRACE_HEADER)) {
  1006. pEvent->MofData = (PVOID) ((char*)pWnodeHeader +
  1007. sizeof(EVENT_TRACE_HEADER));
  1008. pEvent->MofLength = pWnodeHeader->Size -
  1009. sizeof(EVENT_TRACE_HEADER);
  1010. }
  1011. }
  1012. break;
  1013. }
  1014. case TRACE_HEADER_TYPE_INSTANCE:
  1015. {
  1016. // new scheme using EVENT_INSTANCE_GUID_HEADER
  1017. if (((pContext->Logfile.LogfileHeader.VersionDetail.SubVersion >= 1) &&
  1018. (pContext->Logfile.LogfileHeader.VersionDetail.SubMinorVersion >= 1)) ||
  1019. pContext->Logfile.LogFileMode & EVENT_TRACE_REAL_TIME_MODE) {
  1020. PEVENT_INSTANCE_GUID_HEADER pInstanceHeader;
  1021. pInstanceHeader = (PEVENT_INSTANCE_GUID_HEADER) pHeader;
  1022. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  1023. pWnode = (PEVENT_TRACE_HEADER) &pEvent->Header;
  1024. // EVENT_INSTANCE_GUID_HEADER is the same as the first part of the EVENT_TRACE.
  1025. // No need to copy IIDs and parent GUID
  1026. RtlCopyMemory(pWnode,
  1027. pInstanceHeader,
  1028. sizeof(EVENT_INSTANCE_GUID_HEADER)
  1029. );
  1030. EtwpCalculateCurrentTime( &pWnode->TimeStamp,
  1031. &pInstanceHeader->TimeStamp,
  1032. pContext );
  1033. if (UseBasePtr) {
  1034. pEvent->Header.Size = pInstanceHeader->Size;
  1035. pEvent->MofData = (PVOID)pHeader;
  1036. pEvent->MofLength = pInstanceHeader->Size;
  1037. if (UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  1038. pInstanceHeader->TimeStamp = pWnode->TimeStamp;
  1039. }
  1040. }
  1041. else {
  1042. pEvent->Header.FieldTypeFlags = (PrivateLogger) ? EVENT_TRACE_USE_PROCTIME : 0;
  1043. if (pInstanceHeader->Size > sizeof(EVENT_INSTANCE_GUID_HEADER)) {
  1044. pEvent->MofData = (PVOID) ((char*)pInstanceHeader +
  1045. sizeof(EVENT_INSTANCE_GUID_HEADER));
  1046. pEvent->MofLength = pInstanceHeader->Size -
  1047. sizeof(EVENT_INSTANCE_GUID_HEADER);
  1048. }
  1049. }
  1050. }
  1051. else {
  1052. PEVENT_INSTANCE_HEADER pInstanceHeader;
  1053. pInstanceHeader = (PEVENT_INSTANCE_HEADER) pHeader;
  1054. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  1055. pWnode = (PEVENT_TRACE_HEADER) &pEvent->Header;
  1056. RtlCopyMemory(pWnode,
  1057. pInstanceHeader,
  1058. sizeof(EVENT_INSTANCE_HEADER)
  1059. );
  1060. EtwpCalculateCurrentTime( &pWnode->TimeStamp,
  1061. &pInstanceHeader->TimeStamp,
  1062. pContext );
  1063. pEvent->InstanceId = pInstanceHeader->InstanceId;
  1064. pEvent->ParentInstanceId = pInstanceHeader->ParentInstanceId;
  1065. pGuid = EtwpGuidMapHandleToGuid(&pContext->GuidMapListHead, pInstanceHeader->RegHandle);
  1066. if (pGuid != NULL) {
  1067. pEvent->Header.Guid = *pGuid;
  1068. }
  1069. else {
  1070. RtlZeroMemory(&pEvent->Header.Guid, sizeof(GUID));
  1071. }
  1072. if (pInstanceHeader->ParentRegHandle != (ULONGLONG)0) {
  1073. pGuid = EtwpGuidMapHandleToGuid(
  1074. &pContext->GuidMapListHead,
  1075. pInstanceHeader->ParentRegHandle);
  1076. if (pGuid != NULL) {
  1077. pEvent->ParentGuid = *pGuid;
  1078. }
  1079. #ifdef DBG
  1080. else {
  1081. EtwpAssert(pGuid != NULL);
  1082. }
  1083. #endif
  1084. }
  1085. if (UseBasePtr) {
  1086. pEvent->Header.Size = pInstanceHeader->Size;
  1087. pEvent->MofData = (PVOID)pHeader;
  1088. pEvent->MofLength = pInstanceHeader->Size;
  1089. if (UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  1090. pInstanceHeader->TimeStamp = pWnode->TimeStamp;
  1091. }
  1092. }
  1093. else {
  1094. pEvent->Header.FieldTypeFlags = (PrivateLogger) ? EVENT_TRACE_USE_PROCTIME : 0;
  1095. if (pInstanceHeader->Size > sizeof(EVENT_INSTANCE_HEADER)) {
  1096. pEvent->MofData = (PVOID) ((char*)pInstanceHeader +
  1097. sizeof(EVENT_INSTANCE_HEADER));
  1098. pEvent->MofLength = pInstanceHeader->Size -
  1099. sizeof(EVENT_INSTANCE_HEADER);
  1100. }
  1101. }
  1102. }
  1103. break;
  1104. }
  1105. case TRACE_HEADER_TYPE_TIMED:
  1106. {
  1107. PTIMED_TRACE_HEADER pTimedHeader;
  1108. pTimedHeader = (PTIMED_TRACE_HEADER) pHeader;
  1109. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  1110. pWnode = (PEVENT_TRACE_HEADER) &pEvent->Header;
  1111. pWnode->Size = pTimedHeader->Size;
  1112. pWnode->Version = pTimedHeader->EventId;
  1113. EtwpCalculateCurrentTime( &pWnode->TimeStamp,
  1114. &pTimedHeader->TimeStamp,
  1115. pContext );
  1116. pWnode->ThreadId = -1;
  1117. pWnode->ProcessId = -1;
  1118. if (UseBasePtr) {
  1119. pEvent->MofData = (PVOID)pHeader;
  1120. pEvent->MofLength = pTimedHeader->Size;
  1121. if (UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  1122. pTimedHeader->TimeStamp = pWnode->TimeStamp;
  1123. }
  1124. }
  1125. else if (pWnode->Size > sizeof(TIMED_TRACE_HEADER)) {
  1126. pEvent->MofData = (PVOID) ((char*) pHeader +
  1127. sizeof(TIMED_TRACE_HEADER));
  1128. pEvent->MofLength = pWnode->Size - sizeof(TIMED_TRACE_HEADER);
  1129. }
  1130. pEvent->Header.FieldTypeFlags = EVENT_TRACE_USE_NOCPUTIME;
  1131. break;
  1132. }
  1133. case TRACE_HEADER_TYPE_WNODE_HEADER:
  1134. {
  1135. PWNODE_HEADER pTmpWnode = (PWNODE_HEADER) pHeader;
  1136. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  1137. RtlCopyMemory(&pEvent->Header, pTmpWnode, sizeof(WNODE_HEADER));
  1138. pEvent->MofData = (PVOID) pTmpWnode;
  1139. pEvent->MofLength = pTmpWnode->BufferSize;
  1140. break;
  1141. }
  1142. case TRACE_HEADER_TYPE_MESSAGE:
  1143. {
  1144. PMESSAGE_TRACE pMsg = (PMESSAGE_TRACE) pHeader;
  1145. USHORT MessageFlags = 0;
  1146. UCHAR * pMessageData;
  1147. ULONG MessageLength;
  1148. RtlZeroMemory(pEvent, sizeof(EVENT_TRACE));
  1149. RtlCopyMemory(&pEvent->Header, pMsg, sizeof(MESSAGE_TRACE_HEADER));
  1150. //
  1151. // Now Process the Trace Message header options
  1152. //
  1153. pMessageData = (char *)pMsg + sizeof(MESSAGE_TRACE_HEADER);
  1154. MessageLength = pMsg->MessageHeader.Size;
  1155. MessageFlags = ((PMESSAGE_TRACE_HEADER)pEvent)->Packet.OptionFlags;
  1156. // Note that the order in which these are added is critical New
  1157. // entries must be added at the end!
  1158. //
  1159. // [First Entry] Sequence Number
  1160. if (MessageFlags&TRACE_MESSAGE_SEQUENCE) {
  1161. if (MessageLength >= sizeof(ULONG)) {
  1162. RtlCopyMemory(&pEvent->InstanceId, pMessageData, sizeof(ULONG));
  1163. pMessageData += sizeof(ULONG);
  1164. MessageLength -= sizeof(ULONG);
  1165. //
  1166. // Software tracing tools look at this (overlapped) field, so
  1167. // we should not overwrite it.
  1168. //
  1169. pEvent->Header.FieldTypeFlags |= EVENT_TRACE_USE_SEQUENCE;
  1170. } else {
  1171. goto TraceMessageShort;
  1172. }
  1173. }
  1174. // [Second Entry] GUID ? or CompnentID ?
  1175. if (MessageFlags&TRACE_MESSAGE_COMPONENTID) {
  1176. if (MessageLength >= sizeof(ULONG)) {
  1177. RtlCopyMemory(&pEvent->Header.Guid,pMessageData,sizeof(ULONG)) ;
  1178. pMessageData += sizeof(ULONG);
  1179. MessageLength -= sizeof(ULONG);
  1180. } else {
  1181. goto TraceMessageShort;
  1182. }
  1183. } else if (MessageFlags&TRACE_MESSAGE_GUID) { // Can't have both
  1184. if (MessageLength >= sizeof(GUID)) {
  1185. RtlCopyMemory(&pEvent->Header.Guid,pMessageData, sizeof(GUID));
  1186. pMessageData += sizeof(GUID);
  1187. MessageLength -= sizeof(GUID);
  1188. } else {
  1189. goto TraceMessageShort;
  1190. }
  1191. }
  1192. // [Third Entry] Timestamp?
  1193. if (MessageFlags&TRACE_MESSAGE_TIMESTAMP) {
  1194. LARGE_INTEGER TimeStamp;
  1195. if (MessageLength >= sizeof(LARGE_INTEGER)) {
  1196. RtlCopyMemory(&TimeStamp,pMessageData,sizeof(LARGE_INTEGER));
  1197. pMessageData += sizeof(LARGE_INTEGER);
  1198. MessageLength -= sizeof(LARGE_INTEGER);
  1199. EtwpCalculateCurrentTime( &pEvent->Header.TimeStamp,
  1200. &TimeStamp,
  1201. pContext );
  1202. } else {
  1203. goto TraceMessageShort;
  1204. }
  1205. }
  1206. // [Fourth Entry] System Information?
  1207. if (MessageFlags&TRACE_MESSAGE_SYSTEMINFO) {
  1208. if (MessageLength >= 2 * sizeof(ULONG)) {
  1209. RtlCopyMemory(&pEvent->Header.ThreadId, pMessageData, sizeof(ULONG)) ;
  1210. pMessageData += sizeof(ULONG);
  1211. MessageLength -=sizeof(ULONG);
  1212. RtlCopyMemory(&pEvent->Header.ProcessId,pMessageData, sizeof(ULONG)) ;
  1213. pMessageData += sizeof(ULONG);
  1214. MessageLength -=sizeof(ULONG);
  1215. } else {
  1216. goto TraceMessageShort;
  1217. }
  1218. }
  1219. //
  1220. // Add New Header Entries immediately before this comment!
  1221. //
  1222. TraceMessageShort:
  1223. if (UseBasePtr) {
  1224. pEvent->MofData = (PVOID)pHeader;
  1225. pEvent->MofLength = pMsg->MessageHeader.Size;
  1226. }
  1227. else {
  1228. pEvent->MofData = (PVOID)&(pMsg->Data) ;
  1229. if (pMsg->MessageHeader.Size >= sizeof(MESSAGE_TRACE_HEADER) ) {
  1230. pEvent->MofLength = pMsg->MessageHeader.Size - sizeof(MESSAGE_TRACE_HEADER);
  1231. } else {
  1232. pEvent->MofLength = 0;
  1233. }
  1234. }
  1235. break;
  1236. }
  1237. default: // Assumed to be REAL WNODE
  1238. break;
  1239. }
  1240. return EtwpSetDosError(ERROR_SUCCESS);
  1241. }
  1242. LPGUID
  1243. EtwpGroupTypeToGuid(
  1244. ULONG GroupType
  1245. )
  1246. /*++
  1247. Routine Description:
  1248. This routine returns the GUID corresponding to a given GroupType.
  1249. The mapping is static and is defined by the kernel provider.
  1250. This routine assumes that the EventMapList is available for use.
  1251. It is allocated once via ProcessTrace and never deleted.
  1252. Arguments:
  1253. GroupType The GroupType of the kernel event.
  1254. Returned Value:
  1255. Pointer to the GUID representing the given GroupType.
  1256. --*/
  1257. {
  1258. ULONG i;
  1259. for (i = 0; i < MAX_KERNEL_TRACE_EVENTS; i++) {
  1260. if (EventMapList[i].GroupType == GroupType)
  1261. return (&EventMapList[i].Guid);
  1262. }
  1263. return NULL;
  1264. }
  1265. VOID
  1266. EtwpCalculateCurrentTime (
  1267. OUT PLARGE_INTEGER DestTime,
  1268. IN PLARGE_INTEGER TimeValue,
  1269. IN PTRACELOG_CONTEXT pContext
  1270. )
  1271. {
  1272. ULONG64 StartPerfClock;
  1273. ULONG64 CurrentTime, TimeStamp;
  1274. ULONG64 Delta;
  1275. double dDelta;
  1276. if (pContext == NULL) {
  1277. Move64(TimeValue, DestTime);
  1278. return;
  1279. }
  1280. if (pContext->ConversionFlags & EVENT_TRACE_GET_RAWEVENT) {
  1281. Move64(TimeValue, DestTime);
  1282. return;
  1283. }
  1284. Move64(TimeValue, (PLARGE_INTEGER) &TimeStamp);
  1285. if ((pContext->UsePerfClock == EVENT_TRACE_CLOCK_SYSTEMTIME) ||
  1286. (pContext->UsePerfClock == EVENT_TRACE_CLOCK_RAW)) {
  1287. //
  1288. // System time, just return the time stamp.
  1289. //
  1290. Move64(TimeValue, DestTime);
  1291. return;
  1292. }
  1293. else if (pContext->UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  1294. if (pContext->PerfFreq.QuadPart == 0) {
  1295. Move64(TimeValue, DestTime);
  1296. return;
  1297. }
  1298. StartPerfClock = pContext->StartPerfClock.QuadPart;
  1299. if (TimeStamp > StartPerfClock) {
  1300. Delta = (TimeStamp - StartPerfClock);
  1301. dDelta = ((double) Delta) * (10000000.0 / (double)pContext->PerfFreq.QuadPart);
  1302. Delta = (ULONG64)dDelta;
  1303. CurrentTime = pContext->StartTime.QuadPart + Delta;
  1304. }
  1305. else {
  1306. Delta = StartPerfClock - TimeStamp;
  1307. dDelta = ((double) Delta) * (10000000.0 / (double)pContext->PerfFreq.QuadPart);
  1308. Delta = (ULONG64)dDelta;
  1309. CurrentTime = pContext->StartTime.QuadPart - Delta;
  1310. }
  1311. Move64((PLARGE_INTEGER) &CurrentTime, DestTime);
  1312. return;
  1313. }
  1314. else {
  1315. if (pContext->CpuSpeedInMHz == 0) {
  1316. Move64(TimeValue, DestTime);
  1317. return;
  1318. }
  1319. StartPerfClock = pContext->StartPerfClock.QuadPart;
  1320. if (TimeStamp > StartPerfClock) {
  1321. Delta = (TimeStamp - StartPerfClock);
  1322. dDelta = ((double) Delta) * (10.0 / (double)pContext->CpuSpeedInMHz);
  1323. Delta = (ULONG64)dDelta;
  1324. CurrentTime = pContext->StartTime.QuadPart + Delta;
  1325. }
  1326. else {
  1327. Delta = StartPerfClock - TimeStamp;
  1328. dDelta = ((double) Delta) * (10.0 / (double)pContext->CpuSpeedInMHz);
  1329. Delta = (ULONG64)dDelta;
  1330. CurrentTime = pContext->StartTime.QuadPart - Delta;
  1331. }
  1332. Move64((PLARGE_INTEGER) &CurrentTime, DestTime);
  1333. return;
  1334. }
  1335. }