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.

2533 lines
81 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. logsup.c
  5. Abstract:
  6. WMI logger api set. The routines here will need to appear like they
  7. are system calls. They are necessary to do the necessary error checking
  8. and do most of the legwork that can be done outside the kernel. The
  9. kernel portion will subsequently only deal with the actual logging
  10. and tracing.
  11. Author:
  12. 28-May-1997 JeePang
  13. Revision History:
  14. --*/
  15. #ifndef MEMPHIS
  16. #include <nt.h>
  17. #include <ntrtl.h> // for ntutrl.h
  18. #include <nturtl.h> // for RTL_CRITICAL_SECTION in winbase.h/wtypes.h
  19. #include <wtypes.h> // for LPGUID in wmium.h
  20. #include "wmiump.h"
  21. #include "evntrace.h"
  22. #include "traceump.h"
  23. #include "tracelib.h"
  24. #include <math.h>
  25. #include "trcapi.h"
  26. NTSTATUS
  27. WmipProcessRunDown(
  28. IN PWMI_LOGGER_CONTEXT Logger,
  29. IN ULONG StartFlag,
  30. IN ULONG fEnableFlags
  31. );
  32. NTSTATUS
  33. WmipThreadRunDown(
  34. IN PWMI_LOGGER_CONTEXT Logger,
  35. IN PSYSTEM_PROCESS_INFORMATION pProcessInfo,
  36. IN ULONG StartFlag,
  37. IN BOOLEAN bExtended
  38. );
  39. ULONG WmiTraceAlignment = DEFAULT_TRACE_ALIGNMENT;
  40. /*
  41. ULONG
  42. WmipStartLogger(
  43. IN OUT PWMI_LOGGER_INFORMATION LoggerInfo
  44. )
  45. /*++
  46. Routine Description:
  47. This is the actual routine to communicate with the kernel to start
  48. the logger. All the required parameters must be in LoggerInfo.
  49. Arguments:
  50. LoggerInfo The actual parameters to be passed to and return from
  51. kernel.
  52. Return Value:
  53. The status of performing the action requested.
  54. --*//*
  55. {
  56. ULONG Status;
  57. ULONG BufferSize;
  58. ACCESS_MASK DesiredAccess = 0;
  59. LPGUID Guid;
  60. PVOID SavedChecksum;
  61. ULONG SavedLogFileMode;
  62. BOOLEAN IsKernelTrace = FALSE;
  63. BOOLEAN bLogFile = FALSE;
  64. BOOLEAN bRealTime = FALSE;
  65. Guid = &LoggerInfo->Wnode.Guid;
  66. if (IsEqualGUID(Guid, &SystemTraceControlGuid) ||
  67. IsEqualGUID(Guid, &WmiEventLoggerGuid)) {
  68. IsKernelTrace = TRUE;
  69. DesiredAccess |= TRACELOG_ACCESS_KERNEL_LOGGER;
  70. }
  71. if ((LoggerInfo->LogFileName.Length > 0) &&
  72. (LoggerInfo->LogFileName.Buffer != NULL)) {
  73. DesiredAccess |= TRACELOG_CREATE_ONDISK;
  74. bLogFile = TRUE;
  75. }
  76. SavedLogFileMode = LoggerInfo->LogFileMode;
  77. if (SavedLogFileMode & EVENT_TRACE_REAL_TIME_MODE) {
  78. DesiredAccess |= TRACELOG_CREATE_REALTIME;
  79. bRealTime = TRUE;
  80. }
  81. Status = WmipCheckGuidAccess( Guid, DesiredAccess );
  82. if (Status != ERROR_SUCCESS) {
  83. return Status;
  84. }
  85. //
  86. // Set the Default Clock Type
  87. //
  88. if (LoggerInfo->Wnode.ClientContext != EVENT_TRACE_CLOCK_SYSTEMTIME) {
  89. LoggerInfo->Wnode.ClientContext = EVENT_TRACE_CLOCK_PERFCOUNTER;
  90. }
  91. if (SavedLogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
  92. Status = WmipSendUmLogRequest(
  93. WmiStartLoggerCode,
  94. LoggerInfo
  95. );
  96. }
  97. else if (IsKernelTrace) {
  98. //
  99. // In order to capture the process/thread rundown accurately, we need to
  100. // start kernel logger in two steps. Start logger with delay write,
  101. // do rundown from user mode and then updatelogger with filename.
  102. //
  103. WMI_LOGGER_INFORMATION DelayLoggerInfo;
  104. ULONG EnableFlags = LoggerInfo->EnableFlags;
  105. LARGE_INTEGER Frequency;
  106. WMI_REF_CLOCK RefClock;
  107. //
  108. // If it's only realtime start logger in one step
  109. //
  110. if (bRealTime && !bLogFile) {
  111. BufferSize = LoggerInfo->BufferSize * 1024;
  112. Status = WmipSendWmiKMRequest(
  113. NULL,
  114. IOCTL_WMI_START_LOGGER,
  115. LoggerInfo,
  116. LoggerInfo->Wnode.BufferSize,
  117. LoggerInfo,
  118. LoggerInfo->Wnode.BufferSize,
  119. &BufferSize,
  120. NULL
  121. );
  122. return WmipSetDosError(Status);
  123. }
  124. if (EnableFlags & EVENT_TRACE_FLAG_EXTENSION) {
  125. PTRACE_ENABLE_FLAG_EXTENSION tFlagExt;
  126. tFlagExt = (PTRACE_ENABLE_FLAG_EXTENSION)
  127. &LoggerInfo->EnableFlags;
  128. EnableFlags = *(PULONG)((PCHAR)LoggerInfo + tFlagExt->Offset);
  129. }
  130. //
  131. // Take a reference timestamp before actually starting the logger
  132. //
  133. RefClock.StartTime.QuadPart = WmipGetSystemTime();
  134. if (LoggerInfo->Wnode.ClientContext == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  135. Status = NtQueryPerformanceCounter(&RefClock.StartPerfClock, &Frequency);
  136. }
  137. else {
  138. RefClock.StartPerfClock = RefClock.StartTime;
  139. }
  140. RtlCopyMemory(&DelayLoggerInfo, LoggerInfo, sizeof(WMI_LOGGER_INFORMATION));
  141. RtlZeroMemory(&DelayLoggerInfo.LogFileName, sizeof(UNICODE_STRING) );
  142. DelayLoggerInfo.Wnode.BufferSize = sizeof(WMI_LOGGER_INFORMATION);
  143. DelayLoggerInfo.LogFileMode |= EVENT_TRACE_DELAY_OPEN_FILE_MODE;
  144. //
  145. // Since there's no filename in step 1 of StartLogger we need to mask
  146. // the NEWFILE mode to prevent kernel trying to generate a file
  147. //
  148. DelayLoggerInfo.LogFileMode &= ~EVENT_TRACE_FILE_MODE_NEWFILE;
  149. DelayLoggerInfo.EnableFlags = (EVENT_TRACE_FLAG_PROCESS & EnableFlags);
  150. DelayLoggerInfo.EnableFlags |= (EVENT_TRACE_FLAG_THREAD & EnableFlags);
  151. DelayLoggerInfo.EnableFlags |= (EVENT_TRACE_FLAG_IMAGE_LOAD & EnableFlags);
  152. BufferSize = DelayLoggerInfo.BufferSize * 1024;
  153. Status = WmipSendWmiKMRequest(
  154. NULL,
  155. IOCTL_WMI_START_LOGGER,
  156. &DelayLoggerInfo,
  157. DelayLoggerInfo.Wnode.BufferSize,
  158. &DelayLoggerInfo,
  159. DelayLoggerInfo.Wnode.BufferSize,
  160. &BufferSize,
  161. NULL
  162. );
  163. if (Status != ERROR_SUCCESS) {
  164. return Status;
  165. }
  166. //
  167. // We need to pick up any parameter adjustment done by the kernel
  168. // here so UpdateTrace does not fail.
  169. //
  170. LoggerInfo->Wnode.HistoricalContext = DelayLoggerInfo.Wnode.HistoricalContext;
  171. LoggerInfo->MinimumBuffers = DelayLoggerInfo.MinimumBuffers;
  172. LoggerInfo->MaximumBuffers = DelayLoggerInfo.MaximumBuffers;
  173. LoggerInfo->NumberOfBuffers = DelayLoggerInfo.NumberOfBuffers;
  174. LoggerInfo->BufferSize = DelayLoggerInfo.BufferSize;
  175. LoggerInfo->AgeLimit = DelayLoggerInfo.AgeLimit;
  176. BufferSize = LoggerInfo->BufferSize * 1024;
  177. //
  178. // Add the LogHeader
  179. //
  180. LoggerInfo->Checksum = NULL;
  181. Status = WmipAddLogHeaderToLogFile(LoggerInfo, &RefClock, FALSE);
  182. if (Status == ERROR_SUCCESS) {
  183. SavedChecksum = LoggerInfo->Checksum;
  184. //
  185. // Update the logger with the filename
  186. //
  187. Status = WmipSendWmiKMRequest(
  188. NULL,
  189. IOCTL_WMI_UPDATE_LOGGER,
  190. LoggerInfo,
  191. LoggerInfo->Wnode.BufferSize,
  192. LoggerInfo,
  193. LoggerInfo->Wnode.BufferSize,
  194. &BufferSize,
  195. NULL
  196. );
  197. if (LoggerInfo->Checksum != NULL) {
  198. WmipFree(LoggerInfo->Checksum);
  199. }
  200. }
  201. if (Status != ERROR_SUCCESS) {
  202. ULONG lStatus;
  203. //
  204. // Logger must be stopped now
  205. //
  206. lStatus = WmipSendWmiKMRequest(
  207. NULL,
  208. IOCTL_WMI_STOP_LOGGER,
  209. LoggerInfo,
  210. LoggerInfo->Wnode.BufferSize,
  211. LoggerInfo,
  212. LoggerInfo->Wnode.BufferSize,
  213. &BufferSize,
  214. NULL
  215. );
  216. LoggerInfo->LogFileMode = SavedLogFileMode;
  217. return WmipSetDosError(Status);
  218. }
  219. else {
  220. if (LoggerInfo->LogFileHandle != NULL) {
  221. NtClose(LoggerInfo->LogFileHandle);
  222. LoggerInfo->LogFileHandle = NULL;
  223. }
  224. }
  225. }
  226. else {
  227. LoggerInfo->Checksum = NULL;
  228. Status = WmipAddLogHeaderToLogFile(LoggerInfo, NULL, FALSE);
  229. if (Status != ERROR_SUCCESS) {
  230. return WmipSetDosError(Status);
  231. }
  232. BufferSize = LoggerInfo->BufferSize * 1024;
  233. SavedChecksum = LoggerInfo->Checksum;
  234. Status = WmipSendWmiKMRequest( // actually start the logger here
  235. NULL,
  236. IOCTL_WMI_START_LOGGER,
  237. LoggerInfo,
  238. LoggerInfo->Wnode.BufferSize,
  239. LoggerInfo,
  240. LoggerInfo->Wnode.BufferSize,
  241. &BufferSize,
  242. NULL
  243. );
  244. if (Status == ERROR_SUCCESS) {
  245. if (LoggerInfo->LogFileHandle != NULL) {
  246. NtClose(LoggerInfo->LogFileHandle);
  247. LoggerInfo->LogFileHandle = NULL;
  248. }
  249. }
  250. if (SavedChecksum != NULL) {
  251. WmipFree(SavedChecksum);
  252. }
  253. }
  254. //
  255. // Restore the LogFileMode
  256. //
  257. LoggerInfo->LogFileMode = SavedLogFileMode;
  258. return WmipSetDosError(Status);
  259. }*/
  260. ULONG
  261. WmipFinalizeLogFileHeader(
  262. IN PWMI_LOGGER_INFORMATION LoggerInfo
  263. )
  264. {
  265. ULONG Status = ERROR_SUCCESS;
  266. ULONG ErrorCode = ERROR_SUCCESS;
  267. HANDLE LogFile = INVALID_HANDLE_VALUE;
  268. LARGE_INTEGER CurrentTime;
  269. ULONG BuffersWritten;
  270. WMI_LOGGER_CONTEXT Logger;
  271. IO_STATUS_BLOCK IoStatus;
  272. FILE_POSITION_INFORMATION FileInfo;
  273. FILE_STANDARD_INFORMATION FileSize;
  274. PWMI_BUFFER_HEADER Buffer; // need to initialize buffer first
  275. SYSTEM_BASIC_INFORMATION SystemInfo;
  276. ULONG EnableFlags;
  277. RtlZeroMemory(&Logger, sizeof(WMI_LOGGER_CONTEXT));
  278. Logger.BufferSpace = NULL;
  279. if (LoggerInfo->LogFileName.Length > 0 ) {
  280. // open the file for writing synchronously for the logger
  281. // others may want to read it as well.
  282. //
  283. LogFile = WmipCreateFileW(
  284. (LPWSTR)LoggerInfo->LogFileName.Buffer,
  285. GENERIC_READ | GENERIC_WRITE,
  286. FILE_SHARE_READ,
  287. NULL,
  288. OPEN_EXISTING,
  289. FILE_ATTRIBUTE_NORMAL,
  290. NULL
  291. );
  292. if (LogFile == INVALID_HANDLE_VALUE) {
  293. ErrorCode = WmipSetDosError(WmipGetLastError());
  294. goto cleanup;
  295. }
  296. Logger.BuffersWritten = LoggerInfo->BuffersWritten;
  297. Logger.BufferSpace = WmipAlloc(LoggerInfo->BufferSize * 1024);
  298. if (Logger.BufferSpace == NULL) {
  299. ErrorCode = WmipSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  300. goto cleanup;
  301. }
  302. Buffer = (PWMI_BUFFER_HEADER) Logger.BufferSpace;
  303. RtlZeroMemory(Buffer, LoggerInfo->BufferSize * 1024);
  304. Buffer->Wnode.BufferSize = LoggerInfo->BufferSize * 1024;
  305. Buffer->ClientContext.Alignment = (UCHAR)WmiTraceAlignment;
  306. Buffer->EventsLost = 0;
  307. Buffer->Offset = sizeof(WMI_BUFFER_HEADER);
  308. Buffer->Wnode.Guid = LoggerInfo->Wnode.Guid;
  309. Status = NtQuerySystemInformation(
  310. SystemBasicInformation,
  311. &SystemInfo, sizeof (SystemInfo), NULL);
  312. if (!NT_SUCCESS(Status)) {
  313. ErrorCode = WmipSetNtStatus(Status);
  314. goto cleanup;
  315. }
  316. Logger.TimerResolution = SystemInfo.TimerResolution;
  317. Logger.LogFileHandle = LogFile;
  318. Logger.BufferSize = LoggerInfo->BufferSize * 1024;
  319. // For Circular LogFile the process rundown data is appended at the
  320. // last buffer written and not to the end of file.
  321. //
  322. Status = NtQueryInformationFile(
  323. LogFile,
  324. &IoStatus,
  325. &FileSize,
  326. sizeof(FILE_STANDARD_INFORMATION),
  327. FileStandardInformation
  328. );
  329. if (!NT_SUCCESS(Status)) {
  330. ErrorCode = WmipSetNtStatus(Status);
  331. goto cleanup;
  332. }
  333. if (IsEqualGUID(&LoggerInfo->Wnode.Guid, &SystemTraceControlGuid)) {
  334. if (LoggerInfo->LogFileMode != EVENT_TRACE_FILE_MODE_CIRCULAR) {
  335. FileInfo.CurrentByteOffset = FileSize.EndOfFile;
  336. }
  337. else {
  338. ULONG BufferSize = LoggerInfo->BufferSize; // in KB
  339. ULONG BuffersWritten = LoggerInfo->BuffersWritten;
  340. ULONG maxBuffers = (LoggerInfo->MaximumFileSize * 1024) / BufferSize;
  341. ULONG LastBuffer;
  342. ULONG StartBuffers;
  343. FileInfo.CurrentByteOffset.QuadPart =
  344. LOGFILE_FIELD_OFFSET(StartBuffers);
  345. Status = NtSetInformationFile(
  346. LogFile,
  347. &IoStatus,
  348. &FileInfo,
  349. sizeof(FILE_POSITION_INFORMATION),
  350. FilePositionInformation
  351. );
  352. if (!NT_SUCCESS(Status)) {
  353. ErrorCode = WmipSetNtStatus(Status);
  354. goto cleanup;
  355. }
  356. Status = NtReadFile(
  357. LogFile,
  358. NULL,
  359. NULL,
  360. NULL,
  361. &IoStatus,
  362. &StartBuffers,
  363. sizeof(ULONG),
  364. NULL,
  365. NULL
  366. );
  367. if (!NT_SUCCESS(Status)) {
  368. ErrorCode = WmipSetNtStatus(Status);
  369. goto cleanup;
  370. }
  371. LastBuffer = (maxBuffers > StartBuffers) ?
  372. (StartBuffers + (BuffersWritten - StartBuffers)
  373. % (maxBuffers - StartBuffers))
  374. : 0;
  375. FileInfo.CurrentByteOffset.QuadPart = LastBuffer *
  376. BufferSize * 1024;
  377. }
  378. Status = NtSetInformationFile(
  379. LogFile,
  380. &IoStatus,
  381. &FileInfo,
  382. sizeof(FILE_POSITION_INFORMATION),
  383. FilePositionInformation
  384. );
  385. if (!NT_SUCCESS(Status)) {
  386. ErrorCode = WmipSetNtStatus(Status);
  387. goto cleanup;
  388. }
  389. EnableFlags = LoggerInfo->EnableFlags;
  390. if (EnableFlags & EVENT_TRACE_FLAG_EXTENSION) {
  391. PTRACE_ENABLE_FLAG_EXTENSION tFlagExt;
  392. tFlagExt = (PTRACE_ENABLE_FLAG_EXTENSION)
  393. &LoggerInfo->EnableFlags;
  394. if (LoggerInfo->Wnode.BufferSize >= (tFlagExt->Offset + sizeof(ULONG)) ) {
  395. EnableFlags = *(PULONG)((PCHAR)LoggerInfo + tFlagExt->Offset);
  396. }
  397. else {
  398. EnableFlags = 0; // Should not happen.
  399. }
  400. }
  401. if (LoggerInfo->Wnode.ClientContext != EVENT_TRACE_CLOCK_SYSTEMTIME) {
  402. LoggerInfo->Wnode.ClientContext = EVENT_TRACE_CLOCK_PERFCOUNTER;
  403. }
  404. Logger.UsePerfClock = LoggerInfo->Wnode.ClientContext;
  405. WmipProcessRunDown(&Logger, FALSE, EnableFlags);
  406. {
  407. PWMI_BUFFER_HEADER Buffer1 =
  408. (PWMI_BUFFER_HEADER) Logger.BufferSpace;
  409. if (Buffer1->Offset < Logger.BufferSize) {
  410. RtlFillMemory(
  411. (char *) Logger.BufferSpace + Buffer1->Offset,
  412. Logger.BufferSize - Buffer1->Offset,
  413. 0xFF);
  414. }
  415. }
  416. Status = NtWriteFile(
  417. LogFile,
  418. NULL,
  419. NULL,
  420. NULL,
  421. &IoStatus,
  422. Logger.BufferSpace,
  423. Logger.BufferSize,
  424. NULL,
  425. NULL);
  426. if (NT_SUCCESS(Status)) {
  427. NtFlushBuffersFile(Logger.LogFileHandle, &IoStatus);
  428. Logger.BuffersWritten++;
  429. }
  430. }
  431. else { // For Application Traces, need to dump the guidmaps again.
  432. // Set the FilePointer to end of file so that Rundown data may be appended.
  433. //
  434. FileInfo.CurrentByteOffset = FileSize.EndOfFile;
  435. Status = NtSetInformationFile(
  436. LogFile,
  437. &IoStatus,
  438. &FileInfo,
  439. sizeof(FILE_POSITION_INFORMATION),
  440. FilePositionInformation
  441. );
  442. if (!NT_SUCCESS(Status)) {
  443. ErrorCode = WmipSetNtStatus(Status);
  444. goto cleanup;
  445. }
  446. // Dump the Guid Maps once more at the End.
  447. //
  448. Buffer->EventsLost = 0;
  449. Buffer->Offset = sizeof(WMI_BUFFER_HEADER);
  450. BuffersWritten = Logger.BuffersWritten;
  451. if (WmipDumpGuidMaps(&Logger, NULL, FALSE) > 0) {
  452. if (Buffer->Offset < Logger.BufferSize) {
  453. RtlFillMemory(
  454. (char *) Logger.BufferSpace + Buffer->Offset,
  455. Logger.BufferSize - Buffer->Offset,
  456. 0xFF);
  457. }
  458. Status = NtWriteFile(
  459. LogFile,
  460. NULL,
  461. NULL,
  462. NULL,
  463. &IoStatus,
  464. Logger.BufferSpace,
  465. Logger.BufferSize,
  466. NULL,
  467. NULL);
  468. if (NT_SUCCESS(Status)) {
  469. NtFlushBuffersFile(Logger.LogFileHandle, &IoStatus);
  470. Logger.BuffersWritten = BuffersWritten;
  471. }
  472. }
  473. }
  474. // TODO: should use memory-mapped file
  475. // Update the EndTime stamp field in LogFile.
  476. //
  477. FileInfo.CurrentByteOffset.QuadPart =
  478. LOGFILE_FIELD_OFFSET(EndTime);
  479. Status = NtSetInformationFile(
  480. LogFile,
  481. &IoStatus,
  482. &FileInfo,
  483. sizeof(FILE_POSITION_INFORMATION),
  484. FilePositionInformation
  485. );
  486. if (!NT_SUCCESS(Status)) {
  487. ErrorCode = WmipSetNtStatus(Status);
  488. goto cleanup;
  489. }
  490. // End Time is always wallclock time.
  491. //
  492. CurrentTime.QuadPart = WmipGetSystemTime();
  493. Status = NtWriteFile(
  494. LogFile,
  495. NULL,
  496. NULL,
  497. NULL,
  498. &IoStatus,
  499. &CurrentTime,
  500. sizeof(ULONGLONG),
  501. NULL,
  502. NULL
  503. );
  504. if (NT_SUCCESS(Status)) {
  505. NtFlushBuffersFile(Logger.LogFileHandle, &IoStatus);
  506. }
  507. // Update the Number of Buffers Written field in the header
  508. //
  509. FileInfo.CurrentByteOffset.QuadPart =
  510. LOGFILE_FIELD_OFFSET(BuffersWritten);
  511. Status = NtSetInformationFile(
  512. LogFile,
  513. &IoStatus,
  514. &FileInfo,
  515. sizeof(FILE_POSITION_INFORMATION),
  516. FilePositionInformation
  517. );
  518. if (!NT_SUCCESS(Status)) {
  519. ErrorCode = WmipSetNtStatus(Status);
  520. goto cleanup;
  521. }
  522. Status = NtWriteFile(
  523. LogFile,
  524. NULL,
  525. NULL,
  526. NULL,
  527. &IoStatus,
  528. &Logger.BuffersWritten,
  529. sizeof(ULONG),
  530. NULL,
  531. NULL
  532. );
  533. if (NT_SUCCESS(Status)) {
  534. NtFlushBuffersFile(Logger.LogFileHandle, &IoStatus);
  535. }
  536. ErrorCode = RtlNtStatusToDosError(Status);
  537. LoggerInfo->BuffersWritten = Logger.BuffersWritten;
  538. //
  539. // Write the BuffersLost information into the logfile
  540. //
  541. FileInfo.CurrentByteOffset.QuadPart =
  542. LOGFILE_FIELD_OFFSET(BuffersLost);
  543. Status = NtSetInformationFile(
  544. LogFile,
  545. &IoStatus,
  546. &FileInfo,
  547. sizeof(FILE_POSITION_INFORMATION),
  548. FilePositionInformation
  549. );
  550. if (!NT_SUCCESS(Status)) {
  551. ErrorCode = WmipSetNtStatus(Status);
  552. goto cleanup;
  553. }
  554. Status = NtWriteFile(
  555. LogFile,
  556. NULL,
  557. NULL,
  558. NULL,
  559. &IoStatus,
  560. &LoggerInfo->LogBuffersLost,
  561. sizeof(ULONG),
  562. NULL,
  563. NULL
  564. );
  565. if (NT_SUCCESS(Status)) {
  566. NtFlushBuffersFile(Logger.LogFileHandle, &IoStatus);
  567. }
  568. //
  569. // Write the EventsLost information into the logfile
  570. //
  571. FileInfo.CurrentByteOffset.QuadPart =
  572. LOGFILE_FIELD_OFFSET(EventsLost);
  573. Status = NtSetInformationFile(
  574. LogFile,
  575. &IoStatus,
  576. &FileInfo,
  577. sizeof(FILE_POSITION_INFORMATION),
  578. FilePositionInformation
  579. );
  580. if (!NT_SUCCESS(Status)) {
  581. ErrorCode = WmipSetNtStatus(Status);
  582. goto cleanup;
  583. }
  584. Status = NtWriteFile(
  585. LogFile,
  586. NULL,
  587. NULL,
  588. NULL,
  589. &IoStatus,
  590. &LoggerInfo->EventsLost,
  591. sizeof(ULONG),
  592. NULL,
  593. NULL
  594. );
  595. if (NT_SUCCESS(Status)) {
  596. NtFlushBuffersFile(Logger.LogFileHandle, &IoStatus);
  597. }
  598. }
  599. cleanup:
  600. if (LogFile != INVALID_HANDLE_VALUE) {
  601. NtClose(LogFile);
  602. }
  603. if (Logger.BufferSpace != NULL) {
  604. WmipFree(Logger.BufferSpace);
  605. }
  606. return WmipSetDosError(ErrorCode);
  607. }
  608. ULONG
  609. WmipStopLogger(
  610. IN OUT PWMI_LOGGER_INFORMATION LoggerInfo
  611. )
  612. /*++
  613. Routine Description:
  614. This is the actual routine to communicate with the kernel to stop
  615. the logger. All the properties of the logger will be returned in LoggerInfo.
  616. Arguments:
  617. LoggerInfo The actual parameters to be passed to and return from
  618. kernel.
  619. Return Value:
  620. The status of performing the action requested.
  621. --*/
  622. {
  623. ULONG ErrorCode, ReturnSize;
  624. PTRACE_ENABLE_CONTEXT pContext;
  625. if (LoggerInfo == NULL)
  626. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  627. if (LoggerInfo->Wnode.BufferSize < sizeof(WMI_LOGGER_INFORMATION))
  628. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  629. if ( !(LoggerInfo->Wnode.Flags & WNODE_FLAG_TRACED_GUID) )
  630. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  631. pContext = (PTRACE_ENABLE_CONTEXT) & LoggerInfo->Wnode.HistoricalContext;
  632. if ( (pContext->InternalFlag != 0)
  633. && (pContext->InternalFlag != EVENT_TRACE_INTERNAL_FLAG_PRIVATE)) {
  634. // Currently only one possible InternalFlag value. This will filter
  635. // out some bogus LoggerHandle
  636. //
  637. return WmipSetDosError(ERROR_INVALID_HANDLE);
  638. }
  639. if (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
  640. ErrorCode = WmipSendUmLogRequest(WmiStopLoggerCode, LoggerInfo);
  641. pContext->InternalFlag |= EVENT_TRACE_INTERNAL_FLAG_PRIVATE;
  642. pContext->LoggerId = 1;
  643. }
  644. else {
  645. ErrorCode = WmipSendWmiKMRequest(
  646. NULL,
  647. IOCTL_WMI_STOP_LOGGER,
  648. LoggerInfo,
  649. LoggerInfo->Wnode.BufferSize,
  650. LoggerInfo,
  651. LoggerInfo->Wnode.BufferSize,
  652. &ReturnSize,
  653. NULL
  654. );
  655. //
  656. // if logging to a file, then update the EndTime, BuffersWritten and do
  657. // process rundown for kernel trace.
  658. //
  659. if (ErrorCode == ERROR_SUCCESS) {
  660. ErrorCode = WmipFinalizeLogFileHeader(LoggerInfo);
  661. }
  662. }
  663. return WmipSetDosError(ErrorCode);
  664. }
  665. ULONG
  666. WmipQueryLogger(
  667. IN OUT PWMI_LOGGER_INFORMATION LoggerInfo,
  668. IN ULONG Update
  669. )
  670. /*++
  671. Routine Description:
  672. This is the actual routine to communicate with the kernel to query
  673. the logger. All the properties of the logger will be returned in LoggerInfo.
  674. Arguments:
  675. LoggerInfo The actual parameters to be passed to and return from
  676. kernel.
  677. Return Value:
  678. The status of performing the action requested.
  679. --*/
  680. {
  681. ULONG Status, ReturnSize;
  682. HANDLE LogFileHandle = NULL;
  683. PTRACE_ENABLE_CONTEXT pContext;
  684. BOOLEAN bAddAppendFlag = FALSE;
  685. ULONG SavedLogFileMode;
  686. if (LoggerInfo == NULL)
  687. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  688. if (LoggerInfo->Wnode.BufferSize < sizeof(WMI_LOGGER_INFORMATION))
  689. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  690. if ( !(LoggerInfo->Wnode.Flags & WNODE_FLAG_TRACED_GUID) )
  691. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  692. LoggerInfo->Checksum = NULL;
  693. LoggerInfo->LogFileHandle = NULL;
  694. pContext = (PTRACE_ENABLE_CONTEXT) &LoggerInfo->Wnode.HistoricalContext;
  695. if ( (pContext->InternalFlag != 0)
  696. && (pContext->InternalFlag != EVENT_TRACE_INTERNAL_FLAG_PRIVATE)) {
  697. // Currently only one possible InternalFlag value. This will filter
  698. // out some bogus LoggerHandle
  699. //
  700. return WmipSetDosError(ERROR_INVALID_HANDLE);
  701. }
  702. //
  703. // If UPDATE and a new logfile is given throw in the LogFileHeader
  704. //
  705. if ( Update
  706. && LoggerInfo->LogFileName.Length > 0
  707. && !( (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE)
  708. || (pContext->InternalFlag & EVENT_TRACE_INTERNAL_FLAG_PRIVATE))) {
  709. Status = WmipAddLogHeaderToLogFile(LoggerInfo, NULL, Update);
  710. if (Status != ERROR_SUCCESS) {
  711. return WmipSetDosError(Status);
  712. }
  713. LogFileHandle = LoggerInfo->LogFileHandle;
  714. bAddAppendFlag = TRUE;
  715. //
  716. // If we are switching to a new file, make sure it is append mode
  717. //
  718. SavedLogFileMode = LoggerInfo->LogFileMode;
  719. }
  720. if (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE ||
  721. pContext->InternalFlag & EVENT_TRACE_INTERNAL_FLAG_PRIVATE) {
  722. pContext->InternalFlag |= EVENT_TRACE_INTERNAL_FLAG_PRIVATE;
  723. pContext->LoggerId = 1;
  724. Status = WmipSendUmLogRequest(
  725. (Update) ? (WmiUpdateLoggerCode) : (WmiQueryLoggerCode),
  726. LoggerInfo
  727. );
  728. }
  729. else {
  730. Status = WmipSendWmiKMRequest(
  731. NULL,
  732. (Update ? IOCTL_WMI_UPDATE_LOGGER : IOCTL_WMI_QUERY_LOGGER),
  733. LoggerInfo,
  734. LoggerInfo->Wnode.BufferSize,
  735. LoggerInfo,
  736. LoggerInfo->Wnode.BufferSize,
  737. &ReturnSize,
  738. NULL
  739. );
  740. if (LoggerInfo->Checksum != NULL) {
  741. WmipFree(LoggerInfo->Checksum);
  742. }
  743. }
  744. if (bAddAppendFlag) {
  745. LoggerInfo->LogFileMode = SavedLogFileMode;
  746. }
  747. return WmipSetDosError(Status);
  748. }
  749. PVOID
  750. WmipGetTraceBuffer(
  751. IN PWMI_LOGGER_CONTEXT Logger,
  752. IN PSYSTEM_THREAD_INFORMATION pThread,
  753. IN ULONG GroupType,
  754. IN ULONG RequiredSize
  755. )
  756. {
  757. PSYSTEM_TRACE_HEADER Header;
  758. PWMI_BUFFER_HEADER Buffer;
  759. THREAD_BASIC_INFORMATION ThreadInfo;
  760. KERNEL_USER_TIMES ThreadCpu;
  761. NTSTATUS Status;
  762. ULONG BytesUsed;
  763. PCLIENT_ID Cid;
  764. RequiredSize += sizeof (SYSTEM_TRACE_HEADER); // add in header
  765. RequiredSize = (ULONG) ALIGN_TO_POWER2(RequiredSize, WmiTraceAlignment);
  766. Buffer = (PWMI_BUFFER_HEADER) Logger->BufferSpace;
  767. if (RequiredSize > Logger->BufferSize - sizeof(WMI_BUFFER_HEADER)) {
  768. WmipSetDosError(ERROR_BUFFER_OVERFLOW);
  769. return NULL;
  770. }
  771. if (RequiredSize > (Logger->BufferSize - Buffer->Offset)) {
  772. ULONG Status;
  773. IO_STATUS_BLOCK IoStatus;
  774. if (Buffer->Offset < Logger->BufferSize) {
  775. RtlFillMemory(
  776. (char *) Buffer + Buffer->Offset,
  777. Logger->BufferSize - Buffer->Offset,
  778. 0xFF);
  779. }
  780. Status = NtWriteFile(
  781. Logger->LogFileHandle,
  782. NULL,
  783. NULL,
  784. NULL,
  785. &IoStatus,
  786. Buffer,
  787. Logger->BufferSize,
  788. NULL,
  789. NULL);
  790. Buffer->EventsLost = 0;
  791. Buffer->Offset = sizeof(WMI_BUFFER_HEADER);
  792. if (!NT_SUCCESS(Status)) {
  793. return NULL;
  794. }
  795. Logger->BuffersWritten++;
  796. }
  797. Header = (PSYSTEM_TRACE_HEADER) ((char*)Buffer + Buffer->Offset);
  798. if (Logger->UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  799. LARGE_INTEGER Frequency;
  800. ULONGLONG Counter = 0;
  801. Status = NtQueryPerformanceCounter((PLARGE_INTEGER)&Counter,
  802. &Frequency);
  803. Header->SystemTime.QuadPart = Counter;
  804. }
  805. else {
  806. Header->SystemTime.QuadPart = WmipGetSystemTime();
  807. }
  808. Header->Header = (GroupType << 16) + RequiredSize;
  809. Header->Marker = SYSTEM_TRACE_MARKER;
  810. if (pThread == NULL) {
  811. Status = NtQueryInformationThread(
  812. NtCurrentThread(),
  813. ThreadBasicInformation,
  814. &ThreadInfo,
  815. sizeof ThreadInfo, NULL);
  816. if (NT_SUCCESS(Status)) {
  817. Cid = &ThreadInfo.ClientId;
  818. Header->ThreadId = HandleToUlong(Cid->UniqueThread);
  819. Header->ProcessId = HandleToUlong(Cid->UniqueProcess);
  820. }
  821. Status = NtQueryInformationThread(
  822. NtCurrentThread(),
  823. ThreadTimes,
  824. &ThreadCpu, sizeof ThreadCpu, NULL);
  825. if (NT_SUCCESS(Status)) {
  826. Header->KernelTime = (ULONG) (ThreadCpu.KernelTime.QuadPart
  827. / Logger->TimerResolution);
  828. Header->UserTime = (ULONG) (ThreadCpu.UserTime.QuadPart
  829. / Logger->TimerResolution);
  830. }
  831. }
  832. else {
  833. Cid = &pThread->ClientId;
  834. Header->ThreadId = HandleToUlong(Cid->UniqueThread);
  835. Header->ProcessId = HandleToUlong(Cid->UniqueProcess);
  836. Header->KernelTime = (ULONG) (pThread->KernelTime.QuadPart
  837. / Logger->TimerResolution);
  838. Header->UserTime = (ULONG) (pThread->UserTime.QuadPart
  839. / Logger->TimerResolution);
  840. }
  841. Buffer->Offset += RequiredSize;
  842. // If there is room, throw in a end of buffer marker.
  843. BytesUsed = Buffer->Offset;
  844. if ( BytesUsed <= (Logger->BufferSize-sizeof(ULONG)) ) {
  845. *((long*)((char*)Buffer+Buffer->Offset)) = -1;
  846. }
  847. return (PVOID) ( (char*) Header + sizeof(SYSTEM_TRACE_HEADER) );
  848. }
  849. VOID
  850. WmipCopyPropertiesToInfo(
  851. IN PEVENT_TRACE_PROPERTIES Properties,
  852. IN PWMI_LOGGER_INFORMATION Info
  853. )
  854. {
  855. ULONG SavedBufferSize = Info->Wnode.BufferSize;
  856. RtlCopyMemory(&Info->Wnode, &Properties->Wnode, sizeof(WNODE_HEADER));
  857. Info->Wnode.BufferSize = SavedBufferSize;
  858. Info->BufferSize = Properties->BufferSize;
  859. Info->MinimumBuffers = Properties->MinimumBuffers;
  860. Info->MaximumBuffers = Properties->MaximumBuffers;
  861. Info->NumberOfBuffers = Properties->NumberOfBuffers;
  862. Info->FreeBuffers = Properties->FreeBuffers;
  863. Info->EventsLost = Properties->EventsLost;
  864. Info->BuffersWritten = Properties->BuffersWritten;
  865. Info->LoggerThreadId = Properties->LoggerThreadId;
  866. Info->MaximumFileSize = Properties->MaximumFileSize;
  867. Info->EnableFlags = Properties->EnableFlags;
  868. Info->LogFileMode = Properties->LogFileMode;
  869. Info->FlushTimer = Properties->FlushTimer;
  870. Info->LogBuffersLost = Properties->LogBuffersLost;
  871. Info->AgeLimit = Properties->AgeLimit;
  872. Info->RealTimeBuffersLost = Properties->RealTimeBuffersLost;
  873. }
  874. VOID
  875. WmipCopyInfoToProperties(
  876. IN PWMI_LOGGER_INFORMATION Info,
  877. IN PEVENT_TRACE_PROPERTIES Properties
  878. )
  879. {
  880. ULONG SavedSize = Properties->Wnode.BufferSize;
  881. RtlCopyMemory(&Properties->Wnode, &Info->Wnode, sizeof(WNODE_HEADER));
  882. Properties->Wnode.BufferSize = SavedSize;
  883. Properties->BufferSize = Info->BufferSize;
  884. Properties->MinimumBuffers = Info->MinimumBuffers;
  885. Properties->MaximumBuffers = Info->MaximumBuffers;
  886. Properties->NumberOfBuffers = Info->NumberOfBuffers;
  887. Properties->FreeBuffers = Info->FreeBuffers;
  888. Properties->EventsLost = Info->EventsLost;
  889. Properties->BuffersWritten = Info->BuffersWritten;
  890. Properties->LoggerThreadId = Info->LoggerThreadId;
  891. Properties->MaximumFileSize = Info->MaximumFileSize;
  892. Properties->EnableFlags = Info->EnableFlags;
  893. Properties->LogFileMode = Info->LogFileMode;
  894. Properties->FlushTimer = Info->FlushTimer;
  895. Properties->LogBuffersLost = Info->LogBuffersLost;
  896. Properties->AgeLimit = Info->AgeLimit;
  897. Properties->RealTimeBuffersLost = Info->RealTimeBuffersLost;
  898. }
  899. NTSTATUS
  900. WmipThreadRunDown(
  901. IN PWMI_LOGGER_CONTEXT Logger,
  902. IN PSYSTEM_PROCESS_INFORMATION pProcessInfo,
  903. IN ULONG StartFlag,
  904. IN BOOLEAN bExtended
  905. )
  906. {
  907. PSYSTEM_THREAD_INFORMATION pThreadInfo;
  908. ULONG GroupType;
  909. ULONG i;
  910. ULONG Size;
  911. ULONG SystemThreadInfoSize;
  912. PWMI_EXTENDED_THREAD_INFORMATION ThreadInfo;
  913. pThreadInfo = (PSYSTEM_THREAD_INFORMATION) (pProcessInfo+1);
  914. GroupType = EVENT_TRACE_GROUP_THREAD +
  915. ((StartFlag) ? EVENT_TRACE_TYPE_DC_START
  916. : EVENT_TRACE_TYPE_DC_END);
  917. Size = sizeof(WMI_EXTENDED_THREAD_INFORMATION);
  918. SystemThreadInfoSize = (bExtended) ? sizeof(SYSTEM_EXTENDED_THREAD_INFORMATION)
  919. : sizeof(SYSTEM_THREAD_INFORMATION);
  920. for (i=0; i < pProcessInfo->NumberOfThreads; i++) {
  921. if (pThreadInfo == NULL)
  922. break;
  923. ThreadInfo = (PWMI_EXTENDED_THREAD_INFORMATION)
  924. WmipGetTraceBuffer( Logger,
  925. pThreadInfo,
  926. GroupType,
  927. Size );
  928. if (ThreadInfo) {
  929. ThreadInfo->ProcessId =
  930. HandleToUlong(pThreadInfo->ClientId.UniqueProcess);
  931. ThreadInfo->ThreadId =
  932. HandleToUlong(pThreadInfo->ClientId.UniqueThread);
  933. if (bExtended) {
  934. PSYSTEM_EXTENDED_THREAD_INFORMATION pExtThreadInfo;
  935. pExtThreadInfo = (PSYSTEM_EXTENDED_THREAD_INFORMATION) pThreadInfo;
  936. ThreadInfo->StackBase = pExtThreadInfo->StackBase;
  937. ThreadInfo->StackLimit = pExtThreadInfo->StackLimit;
  938. ThreadInfo->StartAddr = pExtThreadInfo->ThreadInfo.StartAddress;
  939. ThreadInfo->Win32StartAddr = pExtThreadInfo->Win32StartAddress;
  940. ThreadInfo->UserStackBase = NULL;
  941. ThreadInfo->UserStackLimit = NULL;
  942. ThreadInfo->WaitMode = -1;
  943. }
  944. else {
  945. ThreadInfo->StackBase = NULL;
  946. ThreadInfo->StackLimit = NULL;
  947. ThreadInfo->StartAddr = NULL;
  948. ThreadInfo->Win32StartAddr = NULL;
  949. ThreadInfo->UserStackBase = NULL;
  950. ThreadInfo->UserStackLimit = NULL;
  951. ThreadInfo->WaitMode = -1;
  952. }
  953. }
  954. pThreadInfo = (PSYSTEM_THREAD_INFORMATION)( (char*)pThreadInfo + SystemThreadInfoSize );
  955. }
  956. return STATUS_SUCCESS;
  957. }
  958. void
  959. WmipLogImageLoadEvent(
  960. IN HANDLE ProcessID,
  961. IN PWMI_LOGGER_CONTEXT pLogger,
  962. IN PRTL_PROCESS_MODULE_INFORMATION pModuleInfo,
  963. IN PSYSTEM_THREAD_INFORMATION pThreadInfo
  964. )
  965. {
  966. UNICODE_STRING wstrModuleName;
  967. ANSI_STRING astrModuleName;
  968. ULONG sizeModuleName;
  969. ULONG sizeBuffer;
  970. PCHAR pAuxInfo;
  971. PWMI_IMAGELOAD_INFORMATION ImageLoadInfo;
  972. if ((pLogger == NULL) || (pModuleInfo == NULL) || (pThreadInfo == NULL))
  973. return;
  974. RtlInitAnsiString( & astrModuleName, pModuleInfo->FullPathName);
  975. sizeModuleName = sizeof(WCHAR) * (astrModuleName.Length);
  976. sizeBuffer = sizeModuleName + sizeof(WCHAR)
  977. + FIELD_OFFSET (WMI_IMAGELOAD_INFORMATION, FileName);
  978. ImageLoadInfo = (PWMI_IMAGELOAD_INFORMATION)
  979. WmipGetTraceBuffer(
  980. pLogger,
  981. pThreadInfo,
  982. EVENT_TRACE_GROUP_PROCESS + EVENT_TRACE_TYPE_LOAD,
  983. sizeBuffer);
  984. if (ImageLoadInfo == NULL) {
  985. return;
  986. }
  987. ImageLoadInfo->ImageBase = pModuleInfo->ImageBase;
  988. ImageLoadInfo->ImageSize = pModuleInfo->ImageSize;
  989. ImageLoadInfo->ProcessId = HandleToUlong(ProcessID);
  990. wstrModuleName.Buffer = (LPWSTR) &ImageLoadInfo->FileName[0];
  991. wstrModuleName.MaximumLength = (USHORT) sizeModuleName + sizeof(WCHAR);
  992. RtlAnsiStringToUnicodeString(& wstrModuleName, & astrModuleName, FALSE);
  993. }
  994. ULONG
  995. WmipSysModuleRunDown(
  996. IN PWMI_LOGGER_CONTEXT pLogger,
  997. IN PSYSTEM_THREAD_INFORMATION pThreadInfo
  998. )
  999. {
  1000. NTSTATUS status = STATUS_SUCCESS;
  1001. char * pLargeBuffer1;
  1002. ULONG ReturnLength;
  1003. ULONG CurrentBufferSize;
  1004. ULONG i;
  1005. PRTL_PROCESS_MODULES pModules;
  1006. PRTL_PROCESS_MODULE_INFORMATION pModuleInfo;
  1007. pLargeBuffer1 = WmipMemReserve(MAX_BUFFER_SIZE);
  1008. if (pLargeBuffer1 == NULL)
  1009. {
  1010. status = STATUS_NO_MEMORY;
  1011. goto Cleanup;
  1012. }
  1013. if (WmipMemCommit(pLargeBuffer1, BUFFER_SIZE) == NULL)
  1014. {
  1015. status = STATUS_NO_MEMORY;
  1016. goto Cleanup;
  1017. }
  1018. CurrentBufferSize = BUFFER_SIZE;
  1019. retry:
  1020. status = NtQuerySystemInformation(
  1021. SystemModuleInformation,
  1022. pLargeBuffer1,
  1023. CurrentBufferSize,
  1024. &ReturnLength);
  1025. if (status == STATUS_INFO_LENGTH_MISMATCH)
  1026. {
  1027. // Increase buffer size.
  1028. //
  1029. CurrentBufferSize += 8192;
  1030. if (WmipMemCommit(pLargeBuffer1, CurrentBufferSize) == NULL)
  1031. {
  1032. status = STATUS_NO_MEMORY;
  1033. goto Cleanup;
  1034. }
  1035. goto retry;
  1036. }
  1037. if (!NT_SUCCESS(status))
  1038. {
  1039. goto Cleanup;
  1040. }
  1041. pModules = (PRTL_PROCESS_MODULES) pLargeBuffer1;
  1042. for (i = 0, pModuleInfo = & (pModules->Modules[0]);
  1043. i < pModules->NumberOfModules;
  1044. i ++, pModuleInfo ++)
  1045. {
  1046. WmipLogImageLoadEvent(NULL, pLogger, pModuleInfo, pThreadInfo);
  1047. }
  1048. Cleanup:
  1049. if (pLargeBuffer1)
  1050. {
  1051. WmipMemFree(pLargeBuffer1);
  1052. }
  1053. return WmipSetNtStatus(status);
  1054. }
  1055. ULONG
  1056. WmipProcessModuleRunDown(
  1057. IN PWMI_LOGGER_CONTEXT pLogger,
  1058. IN HANDLE ProcessID,
  1059. IN PSYSTEM_THREAD_INFORMATION pThreadInfo)
  1060. {
  1061. NTSTATUS status = STATUS_SUCCESS;
  1062. ULONG i;
  1063. PRTL_DEBUG_INFORMATION pLargeBuffer1 = NULL;
  1064. pLargeBuffer1 = RtlCreateQueryDebugBuffer(0, FALSE);
  1065. if (pLargeBuffer1 == NULL)
  1066. {
  1067. status = STATUS_NO_MEMORY;
  1068. goto Cleanup;
  1069. }
  1070. status = RtlQueryProcessDebugInformation(
  1071. ProcessID,
  1072. RTL_QUERY_PROCESS_MODULES,
  1073. pLargeBuffer1);
  1074. if ( !NT_SUCCESS(status) || (pLargeBuffer1->Modules == NULL) )
  1075. {
  1076. goto Cleanup;
  1077. }
  1078. for (i = 0; i < pLargeBuffer1->Modules->NumberOfModules; i ++)
  1079. {
  1080. WmipLogImageLoadEvent(
  1081. ProcessID,
  1082. pLogger,
  1083. & (pLargeBuffer1->Modules->Modules[i]),
  1084. pThreadInfo);
  1085. }
  1086. Cleanup:
  1087. if (pLargeBuffer1)
  1088. {
  1089. RtlDestroyQueryDebugBuffer(pLargeBuffer1);
  1090. }
  1091. return WmipSetNtStatus(status);
  1092. }
  1093. NTSTATUS
  1094. WmipProcessRunDown(
  1095. IN PWMI_LOGGER_CONTEXT Logger,
  1096. IN ULONG StartFlag,
  1097. IN ULONG fEnableFlags
  1098. )
  1099. {
  1100. PSYSTEM_PROCESS_INFORMATION pProcessInfo;
  1101. PSYSTEM_THREAD_INFORMATION pThreadInfo;
  1102. char* LargeBuffer1;
  1103. NTSTATUS status;
  1104. ULONG ReturnLength;
  1105. ULONG CurrentBufferSize;
  1106. ULONG GroupType;
  1107. ULONG TotalOffset = 0;
  1108. OBJECT_ATTRIBUTES objectAttributes;
  1109. BOOLEAN WasEnabled = TRUE;
  1110. BOOLEAN bExtended = TRUE;
  1111. LargeBuffer1 = WmipMemReserve ( MAX_BUFFER_SIZE );
  1112. if (LargeBuffer1 == NULL) {
  1113. return STATUS_NO_MEMORY;
  1114. }
  1115. if (WmipMemCommit (LargeBuffer1, BUFFER_SIZE) == NULL) {
  1116. return STATUS_NO_MEMORY;
  1117. }
  1118. CurrentBufferSize = BUFFER_SIZE;
  1119. retry:
  1120. if (bExtended) {
  1121. status = NtQuerySystemInformation(
  1122. SystemExtendedProcessInformation,
  1123. LargeBuffer1,
  1124. CurrentBufferSize,
  1125. &ReturnLength
  1126. );
  1127. }
  1128. else {
  1129. status = NtQuerySystemInformation(
  1130. SystemProcessInformation,
  1131. LargeBuffer1,
  1132. CurrentBufferSize,
  1133. &ReturnLength
  1134. );
  1135. }
  1136. if (status == STATUS_INFO_LENGTH_MISMATCH) {
  1137. //
  1138. // Increase buffer size.
  1139. //
  1140. CurrentBufferSize += 8192;
  1141. if (WmipMemCommit (LargeBuffer1, CurrentBufferSize) == NULL) {
  1142. return STATUS_NO_MEMORY;
  1143. }
  1144. goto retry;
  1145. }
  1146. if (!NT_SUCCESS(status)) {
  1147. if (bExtended) {
  1148. bExtended = FALSE;
  1149. goto retry;
  1150. }
  1151. WmipMemFree(LargeBuffer1);
  1152. return(status);
  1153. }
  1154. //
  1155. // Adjust Privileges to obtain the module information
  1156. //
  1157. if (fEnableFlags & EVENT_TRACE_FLAG_IMAGE_LOAD) {
  1158. status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,
  1159. TRUE, FALSE, &WasEnabled);
  1160. if (!NT_SUCCESS(status)) {
  1161. WmipMemFree(LargeBuffer1);
  1162. return (status);
  1163. }
  1164. }
  1165. TotalOffset = 0;
  1166. pProcessInfo = (SYSTEM_PROCESS_INFORMATION *) LargeBuffer1;
  1167. while (TRUE) {
  1168. ULONG Size;
  1169. ULONG Length = 0;
  1170. ULONG SidLength = 0;
  1171. PUCHAR AuxPtr;
  1172. PULONG_PTR AuxInfo;
  1173. ANSI_STRING s;
  1174. HANDLE Token;
  1175. HANDLE pProcess;
  1176. PCLIENT_ID Cid;
  1177. ULONG TempInfo[128];
  1178. PWMI_PROCESS_INFORMATION WmiProcessInfo;
  1179. Size = FIELD_OFFSET(WMI_PROCESS_INFORMATION, Sid);
  1180. GroupType = EVENT_TRACE_GROUP_PROCESS +
  1181. ((StartFlag) ? EVENT_TRACE_TYPE_DC_START
  1182. : EVENT_TRACE_TYPE_DC_END);
  1183. pThreadInfo = (PSYSTEM_THREAD_INFORMATION) (pProcessInfo+1);
  1184. if (pProcessInfo->NumberOfThreads > 0) {
  1185. Cid = (PCLIENT_ID) &pThreadInfo->ClientId;
  1186. }
  1187. else {
  1188. Cid = NULL;
  1189. }
  1190. // if at termination, rundown thread first before process
  1191. if ( (!StartFlag) &&
  1192. (fEnableFlags & EVENT_TRACE_FLAG_THREAD) ){
  1193. status = WmipThreadRunDown(Logger,
  1194. pProcessInfo,
  1195. StartFlag,
  1196. bExtended);
  1197. if (!NT_SUCCESS(status)) {
  1198. break;
  1199. }
  1200. }
  1201. if (fEnableFlags & EVENT_TRACE_FLAG_PROCESS) {
  1202. if ( pProcessInfo->ImageName.Buffer &&
  1203. pProcessInfo->ImageName.Length > 0 ) {
  1204. RtlUnicodeStringToAnsiString(
  1205. &s,
  1206. (PUNICODE_STRING)&pProcessInfo->ImageName,
  1207. TRUE);
  1208. Length = s.Length + 1;
  1209. }
  1210. else {
  1211. Length = 1;
  1212. }
  1213. InitializeObjectAttributes(
  1214. &objectAttributes, 0, 0, NULL, NULL);
  1215. status = NtOpenProcess(
  1216. &pProcess,
  1217. PROCESS_QUERY_INFORMATION,
  1218. &objectAttributes,
  1219. Cid);
  1220. if (NT_SUCCESS(status)) {
  1221. status = NtOpenProcessToken(
  1222. pProcess,
  1223. TOKEN_READ,
  1224. &Token);
  1225. if (NT_SUCCESS(status)) {
  1226. status = NtQueryInformationToken(
  1227. Token,
  1228. TokenUser,
  1229. TempInfo,
  1230. 256,
  1231. &SidLength);
  1232. NtClose(Token);
  1233. }
  1234. NtClose(pProcess);
  1235. }
  1236. if ( (!NT_SUCCESS(status)) || SidLength <= 0) {
  1237. TempInfo[0] = 0;
  1238. SidLength = sizeof(ULONG);
  1239. }
  1240. Size += Length + SidLength;
  1241. WmiProcessInfo = (PWMI_PROCESS_INFORMATION)
  1242. WmipGetTraceBuffer( Logger,
  1243. pThreadInfo,
  1244. GroupType,
  1245. Size);
  1246. if (WmiProcessInfo == NULL) {
  1247. status = STATUS_NO_MEMORY;
  1248. break;
  1249. }
  1250. WmiProcessInfo->ProcessId = HandleToUlong(pProcessInfo->UniqueProcessId);
  1251. WmiProcessInfo->ParentId = HandleToUlong(pProcessInfo->InheritedFromUniqueProcessId);
  1252. WmiProcessInfo->SessionId = pProcessInfo->SessionId;
  1253. WmiProcessInfo->PageDirectoryBase = pProcessInfo->PageDirectoryBase;
  1254. WmiProcessInfo->ExitStatus = 0;
  1255. AuxPtr = (PUCHAR) (&WmiProcessInfo->Sid);
  1256. RtlCopyMemory(AuxPtr, &TempInfo, SidLength);
  1257. AuxPtr += SidLength;
  1258. if ( Length > 1) {
  1259. RtlCopyMemory(AuxPtr, s.Buffer, Length);
  1260. AuxPtr += Length;
  1261. RtlFreeAnsiString(&s);
  1262. }
  1263. *AuxPtr = '\0';
  1264. AuxPtr++;
  1265. }
  1266. // if at beginning, trace threads after process
  1267. if (StartFlag) {
  1268. if (fEnableFlags & EVENT_TRACE_FLAG_THREAD) {
  1269. WmipThreadRunDown(Logger, pProcessInfo, StartFlag, bExtended);
  1270. }
  1271. if (fEnableFlags & EVENT_TRACE_FLAG_IMAGE_LOAD) {
  1272. if (pProcessInfo->UniqueProcessId == 0) {
  1273. WmipSysModuleRunDown(Logger, pThreadInfo);
  1274. }
  1275. else
  1276. WmipProcessModuleRunDown(
  1277. Logger,
  1278. (HANDLE) pProcessInfo->UniqueProcessId,
  1279. pThreadInfo);
  1280. }
  1281. }
  1282. if (pProcessInfo->NextEntryOffset == 0) {
  1283. break;
  1284. }
  1285. TotalOffset += pProcessInfo->NextEntryOffset;
  1286. pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)&LargeBuffer1[TotalOffset];
  1287. }
  1288. //
  1289. // Restore privileges back to what it was before
  1290. //
  1291. if (fEnableFlags & EVENT_TRACE_FLAG_IMAGE_LOAD) {
  1292. status = RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE,
  1293. WasEnabled,
  1294. FALSE,
  1295. &WasEnabled);
  1296. }
  1297. WmipMemFree(LargeBuffer1);
  1298. return status;
  1299. }
  1300. VOID
  1301. WmipInitString(
  1302. IN PVOID Destination,
  1303. IN PVOID Buffer,
  1304. IN ULONG Size
  1305. )
  1306. {
  1307. PSTRING s = (PSTRING) Destination;
  1308. s->Buffer = Buffer;
  1309. s->Length = 0;
  1310. if (Buffer != NULL)
  1311. s->MaximumLength = (USHORT) Size;
  1312. else
  1313. s->MaximumLength = 0;
  1314. }
  1315. VOID
  1316. WmipGenericTraceEnable(
  1317. IN ULONG RequestCode,
  1318. IN PVOID Buffer,
  1319. IN OUT PVOID *RequestAddress
  1320. )
  1321. {
  1322. PGUIDMAPENTRY pControlGMEntry = *RequestAddress;
  1323. PWNODE_HEADER Wnode = (PWNODE_HEADER) Buffer;
  1324. PTRACE_REG_INFO pTraceRegInfo;
  1325. PTRACE_ENABLE_CONTEXT pContext = (PTRACE_ENABLE_CONTEXT)&Wnode->HistoricalContext;
  1326. *RequestAddress = NULL;
  1327. if (Wnode == NULL || pControlGMEntry == NULL)
  1328. return;
  1329. if (!Wnode->Flags & WNODE_FLAG_TRACED_GUID)
  1330. return;
  1331. pTraceRegInfo = pControlGMEntry->pControlGuidData;
  1332. WmipAssert(pTraceRegInfo != NULL);
  1333. if (pTraceRegInfo->InProgressEvent != NULL) {
  1334. LARGE_INTEGER Timeout = {(ULONG)(-NOTIFY_RETRY_COUNT * 1000 * 10), -1};
  1335. // TODO: Raghu - what if it times out??
  1336. NtWaitForSingleObject(pTraceRegInfo->InProgressEvent, 0, &Timeout);
  1337. }
  1338. *RequestAddress = pTraceRegInfo->NotifyRoutine;
  1339. if (RequestCode == WMI_ENABLE_EVENTS) {
  1340. pControlGMEntry->LoggerContext = Wnode->HistoricalContext;
  1341. if (pContext->InternalFlag & EVENT_TRACE_INTERNAL_FLAG_PRIVATE) {
  1342. pTraceRegInfo->EnabledState = TRUE;
  1343. if (!WmipIsPrivateLoggerOn())
  1344. *RequestAddress = NULL; // Do not notify if the logger is not up.
  1345. }
  1346. }
  1347. else if (RequestCode == WMI_DISABLE_EVENTS) {
  1348. if (pContext->InternalFlag & EVENT_TRACE_INTERNAL_FLAG_PRIVATE) {
  1349. pTraceRegInfo->EnabledState = FALSE;
  1350. }
  1351. pControlGMEntry->LoggerContext = 0;
  1352. }
  1353. }
  1354. ULONG
  1355. WmipAddLogHeaderToLogFile(
  1356. IN OUT PWMI_LOGGER_INFORMATION LoggerInfo,
  1357. IN PWMI_REF_CLOCK RefClock,
  1358. IN ULONG Update
  1359. )
  1360. {
  1361. NTSTATUS Status;
  1362. HANDLE LogFile = INVALID_HANDLE_VALUE;
  1363. ULONG BufferSize;
  1364. ULONG MemorySize;
  1365. ULONG TraceKernel;
  1366. SYSTEM_BASIC_INFORMATION SystemInfo;
  1367. WMI_LOGGER_CONTEXT Logger;
  1368. IO_STATUS_BLOCK IoStatus;
  1369. PWMI_BUFFER_HEADER Buffer;
  1370. FILE_POSITION_INFORMATION FileInfo;
  1371. LPWSTR FileName = NULL;
  1372. LPWSTR FileNameBuffer = NULL;
  1373. ULONG HeaderSize;
  1374. struct WMI_LOGFILE_HEADER {
  1375. WMI_BUFFER_HEADER BufferHeader;
  1376. SYSTEM_TRACE_HEADER SystemHeader;
  1377. TRACE_LOGFILE_HEADER LogFileHeader;
  1378. };
  1379. struct WMI_LOGFILE_HEADER LoggerBuffer;
  1380. BOOLEAN bLogFileAppend =
  1381. (LoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_APPEND)
  1382. ? (TRUE) : (FALSE);
  1383. if (LoggerInfo == NULL)
  1384. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  1385. if (LoggerInfo->Wnode.BufferSize < sizeof(WMI_LOGGER_INFORMATION))
  1386. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  1387. if ( !(LoggerInfo->Wnode.Flags & WNODE_FLAG_TRACED_GUID) )
  1388. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  1389. if ((LoggerInfo->LogFileMode & EVENT_TRACE_FILE_MODE_NEWFILE) &&
  1390. (LoggerInfo->LogFileName.Length > 0)) {
  1391. FileName = (LPWSTR) WmipAlloc(LoggerInfo->LogFileName.Length + 64);
  1392. if (FileName == NULL) {
  1393. return WmipSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  1394. }
  1395. swprintf(FileName, LoggerInfo->LogFileName.Buffer, 1);
  1396. FileNameBuffer = FileName;
  1397. }
  1398. if (FileName == NULL)
  1399. FileName = (LPWSTR) LoggerInfo->LogFileName.Buffer;
  1400. //
  1401. // If it is Append Mode, we need to open the file and make sure the
  1402. // pick up the BufferSize
  1403. //
  1404. if ( bLogFileAppend ) {
  1405. ULONG ReadSize = sizeof(WMI_BUFFER_HEADER)
  1406. + sizeof(SYSTEM_TRACE_HEADER)
  1407. + sizeof(TRACE_LOGFILE_HEADER);
  1408. ULONG nBytesRead = 0;
  1409. //
  1410. // Update and Append do not mix. To Append LoggerInfo
  1411. // must have LogFileName
  1412. //
  1413. if ( (Update) || (LoggerInfo->LogFileName.Length <= 0) ) {
  1414. if (FileNameBuffer != NULL) {
  1415. WmipFree(FileNameBuffer);
  1416. }
  1417. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  1418. }
  1419. LogFile = WmipCreateFileW(FileName,
  1420. GENERIC_READ | GENERIC_WRITE,
  1421. FILE_SHARE_READ,
  1422. NULL,
  1423. OPEN_EXISTING,
  1424. FILE_ATTRIBUTE_NORMAL,
  1425. NULL);
  1426. if (LogFile == INVALID_HANDLE_VALUE) {
  1427. // cannot OPEN_EXISTING, assume that logfile is not there and
  1428. // create a new one.
  1429. //
  1430. bLogFileAppend = FALSE;
  1431. LoggerInfo->LogFileMode = LoggerInfo->LogFileMode
  1432. & (~ (EVENT_TRACE_FILE_MODE_APPEND));
  1433. }
  1434. else {
  1435. // read TRACE_LOGFILE_HEADER structure and update LoggerInfo
  1436. // members.
  1437. //
  1438. Status = WmipReadFile(LogFile,
  1439. (LPVOID) & LoggerBuffer,
  1440. ReadSize,
  1441. & nBytesRead,
  1442. NULL);
  1443. if (nBytesRead < ReadSize) {
  1444. NtClose(LogFile);
  1445. if (FileNameBuffer != NULL) {
  1446. WmipFree(FileNameBuffer);
  1447. }
  1448. return WmipSetDosError(ERROR_BAD_PATHNAME);
  1449. }
  1450. if ( LoggerBuffer.LogFileHeader.LogFileMode
  1451. & EVENT_TRACE_FILE_MODE_CIRCULAR) {
  1452. NtClose(LogFile);
  1453. if (FileNameBuffer != NULL) {
  1454. WmipFree(FileNameBuffer);
  1455. }
  1456. return WmipSetDosError(ERROR_BAD_PATHNAME);
  1457. }
  1458. LoggerInfo->BufferSize =
  1459. LoggerBuffer.LogFileHeader.BufferSize / 1024;
  1460. LoggerInfo->BuffersWritten =
  1461. LoggerBuffer.LogFileHeader.BuffersWritten;
  1462. LoggerInfo->MaximumFileSize =
  1463. LoggerBuffer.LogFileHeader.MaximumFileSize;
  1464. // Write back logfile append mode so WmipFinalizeLogFile() correctly
  1465. // update BuffersWritten field
  1466. //
  1467. FileInfo.CurrentByteOffset.QuadPart =
  1468. LOGFILE_FIELD_OFFSET(EndTime);
  1469. Status = NtSetInformationFile(LogFile,
  1470. & IoStatus,
  1471. & FileInfo,
  1472. sizeof(FILE_POSITION_INFORMATION),
  1473. FilePositionInformation);
  1474. if (!NT_SUCCESS(Status)) {
  1475. NtClose(LogFile);
  1476. if (FileNameBuffer != NULL) {
  1477. WmipFree(FileNameBuffer);
  1478. }
  1479. return WmipSetNtStatus(Status);
  1480. }
  1481. LoggerBuffer.LogFileHeader.EndTime.QuadPart = 0;
  1482. Status = NtWriteFile(LogFile,
  1483. NULL,
  1484. NULL,
  1485. NULL,
  1486. & IoStatus,
  1487. & LoggerBuffer.LogFileHeader.EndTime,
  1488. sizeof(LARGE_INTEGER),
  1489. NULL,
  1490. NULL);
  1491. if (! NT_SUCCESS(Status)) {
  1492. NtClose(LogFile);
  1493. if (FileNameBuffer != NULL) {
  1494. WmipFree(FileNameBuffer);
  1495. }
  1496. return WmipSetNtStatus(Status);
  1497. }
  1498. // build checksum structure
  1499. //
  1500. if (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
  1501. LoggerInfo->Checksum = NULL;
  1502. }
  1503. else {
  1504. LoggerInfo->Checksum = WmipAlloc(
  1505. sizeof(WNODE_HEADER) + sizeof(TRACE_LOGFILE_HEADER));
  1506. if (LoggerInfo->Checksum != NULL) {
  1507. PBYTE ptrChecksum = LoggerInfo->Checksum;
  1508. RtlCopyMemory(ptrChecksum,
  1509. & LoggerBuffer.BufferHeader,
  1510. sizeof(WNODE_HEADER));
  1511. ptrChecksum += sizeof(WNODE_HEADER);
  1512. RtlCopyMemory(ptrChecksum,
  1513. & LoggerBuffer.LogFileHeader,
  1514. sizeof(TRACE_LOGFILE_HEADER));
  1515. }
  1516. else {
  1517. if (FileNameBuffer != NULL) {
  1518. WmipFree(FileNameBuffer);
  1519. }
  1520. return WmipSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  1521. }
  1522. }
  1523. }
  1524. }
  1525. // get the system parameters first
  1526. LoggerInfo->LogFileHandle = NULL;
  1527. Status = NtQuerySystemInformation(
  1528. SystemBasicInformation,
  1529. &SystemInfo, sizeof (SystemInfo), NULL);
  1530. if (!NT_SUCCESS(Status)) {
  1531. if (FileNameBuffer != NULL) {
  1532. WmipFree(FileNameBuffer);
  1533. }
  1534. return WmipSetNtStatus(Status);
  1535. }
  1536. // choose some logical default value for buffer size if user
  1537. // has not provided one
  1538. MemorySize = SystemInfo.NumberOfPhysicalPages * SystemInfo.PageSize
  1539. / 1024 / 1024;
  1540. if (MemorySize <= 32)
  1541. BufferSize = SystemInfo.PageSize;
  1542. else if (MemorySize <= 64)
  1543. BufferSize = SystemInfo.PageSize;
  1544. else if (MemorySize <= 128)
  1545. BufferSize = SystemInfo.PageSize * 2;
  1546. else if (MemorySize <= 256)
  1547. BufferSize = SystemInfo.PageSize * 2;
  1548. else if (MemorySize > 512)
  1549. BufferSize = SystemInfo.PageSize * 2;
  1550. else if (MemorySize <= 256)
  1551. BufferSize = SystemInfo.PageSize * 2;
  1552. else if (MemorySize > 512)
  1553. BufferSize = 64 * 1024; // allocation size
  1554. else // > 256 && < 512
  1555. BufferSize = SystemInfo.PageSize * 2;
  1556. if (LoggerInfo->BufferSize > 1024) // limit to 1Mb
  1557. BufferSize = 1024 * 1024;
  1558. else if (LoggerInfo->BufferSize > 0)
  1559. BufferSize = LoggerInfo->BufferSize * 1024;
  1560. TraceKernel = IsEqualGUID(&LoggerInfo->Wnode.Guid, &SystemTraceControlGuid);
  1561. if (!TraceKernel) {
  1562. GUID guid;
  1563. RtlZeroMemory(&guid, sizeof(GUID));
  1564. if (IsEqualGUID(&LoggerInfo->Wnode.Guid, &guid)) {
  1565. // Generate a Guid for this logger stream
  1566. // This will ensure buffer filtering at the WMI service
  1567. // based on this GUID.
  1568. UUID uid;
  1569. WmipUuidCreate(&uid);
  1570. LoggerInfo->Wnode.Guid = uid;
  1571. }
  1572. }
  1573. if (!Update) {
  1574. // don't want to update BufferSize information if the request is
  1575. // to update logger session
  1576. //
  1577. LoggerInfo->BufferSize = BufferSize / 1024;
  1578. }
  1579. if (LoggerInfo->LogFileName.Length <= 0)
  1580. return ERROR_SUCCESS; //goto SendToKm;
  1581. //
  1582. // We assumed the exposed API has checked for either RealTime or FileName
  1583. // is provided
  1584. //
  1585. // open the file for writing synchronously for the logger
  1586. // others may want to read it as well.
  1587. // For logfile append mode, logfile has been opened previously
  1588. //
  1589. if (! bLogFileAppend) {
  1590. /* LogFile = WmipCreateFileW(
  1591. (PWCHAR) LoggerInfo->LogFileName.Buffer,
  1592. GENERIC_WRITE,
  1593. FILE_SHARE_READ,
  1594. NULL,
  1595. CREATE_ALWAYS,
  1596. FILE_ATTRIBUTE_NORMAL,
  1597. NULL
  1598. ); */
  1599. LogFile = WmipCreateFile(
  1600. FileName,
  1601. FILE_GENERIC_WRITE,
  1602. FILE_SHARE_READ,
  1603. FILE_OVERWRITE_IF,
  1604. 0);
  1605. if (LogFile == INVALID_HANDLE_VALUE) {
  1606. if (FileNameBuffer != NULL) {
  1607. WmipFree(FileNameBuffer);
  1608. }
  1609. return WmipSetDosError(ERROR_BAD_PATHNAME);
  1610. }
  1611. }
  1612. LoggerInfo->LogFileHandle = LogFile;
  1613. //
  1614. // If this is an Update call, then we need to pick up the original
  1615. // buffer size for the LogFileHeader.
  1616. //
  1617. if (Update) {
  1618. PWMI_LOGGER_INFORMATION pTempLoggerInfo;
  1619. PWCHAR strLoggerName = NULL;
  1620. PWCHAR strLogFileName = NULL;
  1621. ULONG ErrCode;
  1622. ULONG SizeNeeded = sizeof(WMI_LOGGER_INFORMATION) + MAXSTR * sizeof(WCHAR) * 2;
  1623. SizeNeeded = (SizeNeeded +7) & ~7;
  1624. pTempLoggerInfo = WmipAlloc(SizeNeeded);
  1625. if (pTempLoggerInfo == NULL) {
  1626. return WmipSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  1627. }
  1628. RtlZeroMemory(pTempLoggerInfo, SizeNeeded);
  1629. pTempLoggerInfo->Wnode.BufferSize = SizeNeeded;
  1630. pTempLoggerInfo->Wnode.Flags |= WNODE_FLAG_TRACED_GUID;
  1631. pTempLoggerInfo->Wnode.HistoricalContext = LoggerInfo->Wnode.HistoricalContext;
  1632. pTempLoggerInfo->Wnode.Guid = LoggerInfo->Wnode.Guid;
  1633. if (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
  1634. pTempLoggerInfo->LogFileMode |= EVENT_TRACE_PRIVATE_LOGGER_MODE;
  1635. }
  1636. strLoggerName = (PWCHAR) ( ((PUCHAR) pTempLoggerInfo)
  1637. + sizeof(WMI_LOGGER_INFORMATION));
  1638. WmipInitString(&pTempLoggerInfo->LoggerName,
  1639. strLoggerName,
  1640. MAXSTR * sizeof(WCHAR));
  1641. if (LoggerInfo->LoggerName.Length > 0) {
  1642. RtlCopyUnicodeString( &pTempLoggerInfo->LoggerName,
  1643. &LoggerInfo->LoggerName);
  1644. }
  1645. strLogFileName = (PWCHAR) ( ((PUCHAR) pTempLoggerInfo)
  1646. + sizeof(WMI_LOGGER_INFORMATION)
  1647. + MAXSTR * sizeof(WCHAR) );
  1648. WmipInitString(&pTempLoggerInfo->LogFileName,
  1649. strLogFileName,
  1650. MAXSTR * sizeof(WCHAR) );
  1651. //
  1652. // Call QueryLogger
  1653. //
  1654. ErrCode = WmipQueryLogger(pTempLoggerInfo, FALSE);
  1655. BufferSize = pTempLoggerInfo->BufferSize * 1024;
  1656. WmipFree(pTempLoggerInfo);
  1657. if (ErrCode != ERROR_SUCCESS) {
  1658. return ErrCode;
  1659. }
  1660. }
  1661. //
  1662. // Before Allocating the Buffer for Logfile Header make
  1663. // sure the buffer size is atleast as large as the LogFileHeader
  1664. //
  1665. HeaderSize = sizeof(LoggerBuffer)
  1666. + LoggerInfo->LoggerName.Length + sizeof(WCHAR)
  1667. + LoggerInfo->LogFileName.Length + sizeof(WCHAR);
  1668. if (HeaderSize > BufferSize) {
  1669. //
  1670. // Round it to the nearest power of 2 and check for max size 1 MB
  1671. //
  1672. double dTemp = log (HeaderSize / 1024.0) / log (2.0);
  1673. ULONG lTemp = (ULONG) (dTemp + 0.99);
  1674. HeaderSize = (1 << lTemp);
  1675. if (HeaderSize > 1024) {
  1676. NtClose(LogFile);
  1677. if (FileNameBuffer != NULL) {
  1678. WmipFree(FileNameBuffer);
  1679. }
  1680. return WmipSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  1681. }
  1682. LoggerInfo->BufferSize = HeaderSize;
  1683. BufferSize = HeaderSize * 1024;
  1684. }
  1685. // allocate a buffer to write logger header and process/thread
  1686. // rundown information
  1687. //
  1688. Logger.LogFileHandle = LogFile;
  1689. Logger.BufferSize = BufferSize;
  1690. Logger.TimerResolution = SystemInfo.TimerResolution;
  1691. Logger.BufferSpace = WmipAlloc(BufferSize);
  1692. if (Logger.BufferSpace == NULL) {
  1693. NtClose(LogFile);
  1694. if (FileNameBuffer != NULL) {
  1695. WmipFree(FileNameBuffer);
  1696. }
  1697. return WmipSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  1698. }
  1699. if (LoggerInfo->Wnode.ClientContext != EVENT_TRACE_CLOCK_SYSTEMTIME) {
  1700. LoggerInfo->Wnode.ClientContext = EVENT_TRACE_CLOCK_PERFCOUNTER;
  1701. }
  1702. Logger.UsePerfClock = LoggerInfo->Wnode.ClientContext;
  1703. // initialize buffer first
  1704. RtlZeroMemory(Logger.BufferSpace, BufferSize);
  1705. Buffer = (PWMI_BUFFER_HEADER) Logger.BufferSpace;
  1706. Buffer->Offset = sizeof(WMI_BUFFER_HEADER);
  1707. if (TraceKernel) {
  1708. Buffer->Wnode.Guid = SystemTraceControlGuid;
  1709. }
  1710. else {
  1711. Buffer->Wnode.Guid = LoggerInfo->Wnode.Guid;
  1712. }
  1713. Buffer->Wnode.BufferSize = BufferSize;
  1714. Buffer->ClientContext.Alignment = (UCHAR)WmiTraceAlignment;
  1715. Buffer->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  1716. if (bLogFileAppend) {
  1717. Logger.BuffersWritten = LoggerBuffer.LogFileHeader.BuffersWritten;
  1718. WmipSetFilePointer(LogFile, 0, NULL, FILE_END);
  1719. }
  1720. else {
  1721. PTRACE_LOGFILE_HEADER LogfileHeader;
  1722. OSVERSIONINFO sVersionInfo;
  1723. Logger.BuffersWritten = 0;
  1724. HeaderSize = sizeof(TRACE_LOGFILE_HEADER)
  1725. + LoggerInfo->LoggerName.Length + sizeof(WCHAR)
  1726. + LoggerInfo->LogFileName.Length + sizeof(WCHAR);
  1727. LogfileHeader = (PTRACE_LOGFILE_HEADER)
  1728. WmipGetTraceBuffer(
  1729. &Logger,
  1730. NULL,
  1731. EVENT_TRACE_GROUP_HEADER + EVENT_TRACE_TYPE_INFO,
  1732. HeaderSize
  1733. );
  1734. if (LogfileHeader == NULL) {
  1735. NtClose(LogFile);
  1736. WmipFree(Logger.BufferSpace);
  1737. if (FileNameBuffer != NULL) {
  1738. WmipFree(FileNameBuffer);
  1739. }
  1740. return WmipSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  1741. }
  1742. if (Logger.UsePerfClock == EVENT_TRACE_CLOCK_PERFCOUNTER) {
  1743. LARGE_INTEGER CurrentTime;
  1744. LARGE_INTEGER Frequency;
  1745. Status = NtQueryPerformanceCounter(&CurrentTime, &Frequency);
  1746. LogfileHeader->PerfFreq = Frequency;
  1747. LogfileHeader->ReservedFlags = EVENT_TRACE_CLOCK_PERFCOUNTER;
  1748. }
  1749. //
  1750. // Start and End Times are wall clock time
  1751. //
  1752. if (RefClock != NULL) {
  1753. PSYSTEM_TRACE_HEADER Header;
  1754. LogfileHeader->StartTime = RefClock->StartTime;
  1755. Header = (PSYSTEM_TRACE_HEADER) ( (char *) LogfileHeader - sizeof(SYSTEM_TRACE_HEADER) );
  1756. Header->SystemTime = RefClock->StartPerfClock;
  1757. }
  1758. else {
  1759. LogfileHeader->StartTime.QuadPart = WmipGetSystemTime();
  1760. }
  1761. RtlZeroMemory(&sVersionInfo, sizeof(OSVERSIONINFO));
  1762. sVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  1763. WmipGetVersionExA(&sVersionInfo);
  1764. LogfileHeader->BufferSize = BufferSize;
  1765. LogfileHeader->VersionDetail.MajorVersion =
  1766. (UCHAR)sVersionInfo.dwMajorVersion;
  1767. LogfileHeader->VersionDetail.MinorVersion =
  1768. (UCHAR)sVersionInfo.dwMinorVersion;
  1769. LogfileHeader->VersionDetail.SubVersion = TRACE_VERSION_MAJOR;
  1770. LogfileHeader->VersionDetail.SubMinorVersion = TRACE_VERSION_MINOR;
  1771. LogfileHeader->ProviderVersion = sVersionInfo.dwBuildNumber;
  1772. LogfileHeader->StartBuffers = 1;
  1773. LogfileHeader->LogFileMode
  1774. = LoggerInfo->LogFileMode & (~(EVENT_TRACE_REAL_TIME_MODE));
  1775. LogfileHeader->NumberOfProcessors = SystemInfo.NumberOfProcessors;
  1776. if (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE)
  1777. {
  1778. if ( (LoggerInfo->NumberOfProcessors > 0) &&
  1779. (LoggerInfo->LogFileMode & EVENT_TRACE_RELOG_MODE) ) {
  1780. LogfileHeader->NumberOfProcessors = LoggerInfo->NumberOfProcessors;
  1781. }
  1782. else {
  1783. LoggerInfo->NumberOfProcessors = SystemInfo.NumberOfProcessors;
  1784. }
  1785. }
  1786. LogfileHeader->MaximumFileSize = LoggerInfo->MaximumFileSize;
  1787. LogfileHeader->TimerResolution = SystemInfo.TimerResolution;
  1788. LogfileHeader->LoggerName = (PWCHAR) ( (PUCHAR) LogfileHeader
  1789. + sizeof(TRACE_LOGFILE_HEADER) );
  1790. LogfileHeader->LogFileName = (PWCHAR) ((PUCHAR)LogfileHeader->LoggerName
  1791. + LoggerInfo->LoggerName.Length
  1792. + sizeof (WCHAR));
  1793. RtlCopyMemory(LogfileHeader->LoggerName,
  1794. LoggerInfo->LoggerName.Buffer,
  1795. LoggerInfo->LoggerName.Length + sizeof(WCHAR));
  1796. RtlCopyMemory(LogfileHeader->LogFileName,
  1797. LoggerInfo->LogFileName.Buffer,
  1798. LoggerInfo->LogFileName.Length + sizeof(WCHAR));
  1799. WmipGetTimeZoneInformation(&LogfileHeader->TimeZone);
  1800. LogfileHeader->PointerSize = sizeof(PVOID);
  1801. if (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
  1802. LoggerInfo->Checksum = NULL;
  1803. }
  1804. else {
  1805. LoggerInfo->Checksum = WmipAlloc(
  1806. sizeof(WNODE_HEADER)
  1807. + sizeof(TRACE_LOGFILE_HEADER));
  1808. if (LoggerInfo->Checksum != NULL) {
  1809. PBYTE ptrChecksum = LoggerInfo->Checksum;
  1810. RtlCopyMemory(ptrChecksum, Buffer, sizeof(WNODE_HEADER));
  1811. ptrChecksum += sizeof(WNODE_HEADER);
  1812. RtlCopyMemory(
  1813. ptrChecksum, LogfileHeader, sizeof(TRACE_LOGFILE_HEADER));
  1814. }
  1815. else {
  1816. NtClose(LogFile);
  1817. WmipFree(Logger.BufferSpace);
  1818. if (FileNameBuffer != NULL) {
  1819. WmipFree(FileNameBuffer);
  1820. }
  1821. return WmipSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  1822. }
  1823. }
  1824. }
  1825. // Dump the GuidMaps to File at the Start
  1826. //
  1827. if (!Update) {
  1828. if (TraceKernel) {
  1829. ULONG EnableFlags = LoggerInfo->EnableFlags;
  1830. if (EnableFlags & EVENT_TRACE_FLAG_EXTENSION) {
  1831. PTRACE_ENABLE_FLAG_EXTENSION tFlagExt;
  1832. tFlagExt = (PTRACE_ENABLE_FLAG_EXTENSION)
  1833. &LoggerInfo->EnableFlags;
  1834. EnableFlags = *(PULONG)((PCHAR)LoggerInfo + tFlagExt->Offset);
  1835. }
  1836. WmipDumpHardwareConfig(&Logger);
  1837. WmipProcessRunDown( &Logger, TRUE, EnableFlags );
  1838. }
  1839. else {
  1840. WmipDumpGuidMaps(&Logger, NULL, FALSE);
  1841. }
  1842. }
  1843. Buffer = (PWMI_BUFFER_HEADER) Logger.BufferSpace;
  1844. // flush the last buffer
  1845. if (Buffer->Offset < Logger.BufferSize) {
  1846. RtlFillMemory(
  1847. (char *) Buffer + Buffer->Offset,
  1848. Logger.BufferSize - Buffer->Offset,
  1849. 0xFF);
  1850. }
  1851. Status = NtWriteFile(
  1852. LogFile,
  1853. NULL,
  1854. NULL,
  1855. NULL,
  1856. &IoStatus,
  1857. Logger.BufferSpace,
  1858. BufferSize,
  1859. NULL,
  1860. NULL);
  1861. Logger.BuffersWritten++;
  1862. if ((LoggerInfo->LogFileMode == EVENT_TRACE_FILE_MODE_CIRCULAR) ) {
  1863. //
  1864. // We need to write the number of StartBuffers in the
  1865. // Circular Logfile header to process it properly.
  1866. FileInfo.CurrentByteOffset.QuadPart =
  1867. LOGFILE_FIELD_OFFSET(StartBuffers);
  1868. Status = NtSetInformationFile(
  1869. LogFile,
  1870. &IoStatus,
  1871. &FileInfo,
  1872. sizeof(FILE_POSITION_INFORMATION),
  1873. FilePositionInformation
  1874. );
  1875. if (!NT_SUCCESS(Status)) {
  1876. NtClose(LogFile);
  1877. if (FileNameBuffer != NULL) {
  1878. WmipFree(FileNameBuffer);
  1879. }
  1880. return WmipSetNtStatus(Status);
  1881. }
  1882. Status = NtWriteFile(
  1883. LogFile,
  1884. NULL,
  1885. NULL,
  1886. NULL,
  1887. &IoStatus,
  1888. &Logger.BuffersWritten,
  1889. sizeof(ULONG),
  1890. NULL,
  1891. NULL
  1892. );
  1893. if (NT_SUCCESS(Status)) {
  1894. PTRACE_LOGFILE_HEADER pLogFileHeader;
  1895. NtFlushBuffersFile(Logger.LogFileHandle, &IoStatus);
  1896. // update StartBuffers in Checksum
  1897. //
  1898. pLogFileHeader = (PTRACE_LOGFILE_HEADER)
  1899. (((PUCHAR) LoggerInfo->Checksum) + sizeof(WNODE_HEADER));
  1900. pLogFileHeader->StartBuffers = Logger.BuffersWritten;
  1901. }
  1902. }
  1903. //
  1904. // As a last thing update the Number of BuffersWritten so far
  1905. // in the header and also update the checksum. This is to prevent
  1906. // Logger failing Update calls under high load.
  1907. //
  1908. FileInfo.CurrentByteOffset.QuadPart =
  1909. LOGFILE_FIELD_OFFSET(BuffersWritten);
  1910. Status = NtSetInformationFile(
  1911. LogFile,
  1912. &IoStatus,
  1913. &FileInfo,
  1914. sizeof(FILE_POSITION_INFORMATION),
  1915. FilePositionInformation
  1916. );
  1917. if (!NT_SUCCESS(Status)) {
  1918. NtClose(LogFile);
  1919. return WmipSetNtStatus(Status);
  1920. }
  1921. Status = NtWriteFile(
  1922. LogFile,
  1923. NULL,
  1924. NULL,
  1925. NULL,
  1926. &IoStatus,
  1927. &Logger.BuffersWritten,
  1928. sizeof(ULONG),
  1929. NULL,
  1930. NULL
  1931. );
  1932. if (NT_SUCCESS(Status)) {
  1933. PTRACE_LOGFILE_HEADER pLogFileHeader;
  1934. NtFlushBuffersFile(Logger.LogFileHandle, &IoStatus);
  1935. // update StartBuffers in Checksum
  1936. //
  1937. if ( !(LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) ) {
  1938. pLogFileHeader = (PTRACE_LOGFILE_HEADER)
  1939. (((PUCHAR) LoggerInfo->Checksum) + sizeof(WNODE_HEADER));
  1940. pLogFileHeader->BuffersWritten = Logger.BuffersWritten;
  1941. }
  1942. }
  1943. NtClose(LogFile);
  1944. LogFile = WmipCreateFileW(
  1945. FileName,
  1946. GENERIC_WRITE,
  1947. FILE_SHARE_READ,
  1948. NULL,
  1949. OPEN_EXISTING,
  1950. FILE_FLAG_NO_BUFFERING,
  1951. NULL
  1952. );
  1953. /* LogFile = WmipCreateFile(
  1954. FileName,
  1955. FILE_GENERIC_WRITE,
  1956. FILE_SHARE_READ,
  1957. FILE_OPEN,
  1958. FILE_NO_INTERMEDIATE_BUFFERING);
  1959. */
  1960. if (FileNameBuffer != NULL) {
  1961. WmipFree(FileNameBuffer);
  1962. }
  1963. if (LogFile == INVALID_HANDLE_VALUE) {
  1964. return WmipGetLastError();
  1965. }
  1966. LoggerInfo->LogFileHandle = LogFile;
  1967. LoggerInfo->BuffersWritten = Logger.BuffersWritten;
  1968. WmipFree(Logger.BufferSpace);
  1969. return ERROR_SUCCESS;
  1970. }
  1971. ULONG
  1972. WmipDumpGuidMaps(
  1973. IN PWMI_LOGGER_CONTEXT Logger,
  1974. IN PLIST_ENTRY GuidMapListHeadPtr,
  1975. IN ULONG RealTimeFlag
  1976. )
  1977. /*++
  1978. Routine Description:
  1979. This routine communicates with the WMI Service and obtains all the
  1980. Trace Guids that are currently registered and those guids that unregistered
  1981. in the middle of a Logging session.
  1982. The GuidMaps are dumped to the logfile or added to the current GuidMapList
  1983. for real time processing.
  1984. Arguments:
  1985. Logger Logger Context.
  1986. RealTimeFlag Flag to denote real time processing.
  1987. Return Value:
  1988. Returns the number of Trace GUIDS obtained from the WMI service.
  1989. --*/
  1990. {
  1991. #if 0
  1992. ULONG Status;
  1993. PTRACEGUIDMAP GuidMapList = NULL;
  1994. ULONG MaxGuidCount;
  1995. ULONG TotalGuidCount;
  1996. ULONG ReturnGuidCount;
  1997. ULONG BusyRetries;
  1998. // Ensure that wmi service is around and willing to send us notifications
  1999. Status = WmipEnableNotifications();
  2000. if (Status != ERROR_SUCCESS)
  2001. {
  2002. WmipSetLastError(Status);
  2003. return(0);
  2004. }
  2005. MaxGuidCount = 10;
  2006. retry:
  2007. TotalGuidCount = 0;
  2008. ReturnGuidCount = 0;
  2009. GuidMapList = WmipAlloc(MaxGuidCount * sizeof(TRACEGUIDMAP));
  2010. if (GuidMapList == NULL)
  2011. {
  2012. WmipSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2013. return (0);
  2014. }
  2015. RtlZeroMemory(GuidMapList, MaxGuidCount * sizeof(TRACEGUIDMAP));
  2016. BusyRetries = 0;
  2017. do
  2018. {
  2019. try
  2020. {
  2021. #if 0
  2022. Status = EnumerateTraceGuidMap(WmipDcCtxHandle,
  2023. MaxGuidCount,
  2024. &TotalGuidCount,
  2025. &ReturnGuidCount,
  2026. GuidMapList);
  2027. #endif
  2028. } except(EXCEPTION_EXECUTE_HANDLER) {
  2029. Status = GetExceptionCode();
  2030. if (Status == STATUS_ACCESS_VIOLATION)
  2031. {
  2032. Status = ERROR_NOACCESS;
  2033. WmipFree(GuidMapList);
  2034. WmipSetLastError(Status);
  2035. return (0);
  2036. }
  2037. }
  2038. if (Status == RPC_S_SERVER_TOO_BUSY)
  2039. {
  2040. WmipDebugPrint(("WMI: EnumerateTraceGuidMap too busy for the %d time\n",
  2041. BusyRetries));
  2042. WmipSleep(RPC_BUSY_WAIT_TIMER);
  2043. BusyRetries++;
  2044. }
  2045. } while ((Status == RPC_S_SERVER_TOO_BUSY) &&
  2046. (BusyRetries < RPC_BUSY_WAIT_RETRIES));
  2047. //
  2048. // If RPC was successful, then write out these events to logfile.
  2049. //
  2050. if (Status == ERROR_MORE_DATA) {
  2051. MaxGuidCount = TotalGuidCount;
  2052. WmipFree(GuidMapList);
  2053. goto retry;
  2054. }
  2055. else if (Status == ERROR_SUCCESS) {
  2056. ULONG GroupType;
  2057. ULONG i;
  2058. ULONG Size;
  2059. PULONG AuxInfo;
  2060. PTRACEGUIDMAP pTraceGuidMap = GuidMapList;
  2061. GroupType = EVENT_TRACE_GROUP_HEADER + EVENT_TRACE_TYPE_GUIDMAP;
  2062. Size = sizeof(TRACEGUIDMAP);
  2063. for (i=0; i < ReturnGuidCount; i++) {
  2064. if (RealTimeFlag) {
  2065. WmipAddGuidHandleToGuidMapList(GuidMapListHeadPtr, pTraceGuidMap->GuidMapHandle,
  2066. &pTraceGuidMap->Guid);
  2067. }
  2068. else {
  2069. AuxInfo = (PULONG) WmipGetTraceBuffer(
  2070. Logger,
  2071. NULL,
  2072. GroupType,
  2073. Size);
  2074. if (AuxInfo == NULL) {
  2075. WmipFree(GuidMapList);
  2076. WmipSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2077. return(0);
  2078. }
  2079. RtlCopyMemory(AuxInfo, pTraceGuidMap, sizeof(TRACEGUIDMAP));
  2080. }
  2081. pTraceGuidMap++;
  2082. }
  2083. }
  2084. WmipFree(GuidMapList);
  2085. WmipSetLastError(Status);
  2086. return(ReturnGuidCount);
  2087. #else
  2088. WmipSetLastError(ERROR_INVALID_PARAMETER);
  2089. return(0);
  2090. #endif
  2091. }
  2092. ULONG
  2093. WmiUnregisterGuids(
  2094. IN WMIHANDLE WMIHandle,
  2095. IN LPGUID Guid,
  2096. OUT ULONG64 *LoggerContext
  2097. )
  2098. /*++
  2099. Routine Description:
  2100. This routine informs WMI that a data provider is no longer available
  2101. to receive requests for the guids previously registered. WMI will
  2102. unregister any guids registered with this handle.
  2103. Arguments:
  2104. WMIHandle - Handle returned from WMIRegisterGuids that represents
  2105. the guids whose data is not longer available.
  2106. Guid - Pointer to the control Guid which is unregistering
  2107. LoggerContext - Returned value of the LoggerContext
  2108. Return Value:
  2109. Returns status code
  2110. --*/
  2111. {
  2112. ULONG Status;
  2113. ULONG ReturnSize;
  2114. WMIUNREGGUIDS UnregGuids;
  2115. UnregGuids.RequestHandle.Handle = WMIHandle;
  2116. UnregGuids.Guid = *Guid;
  2117. Status = WmipSendWmiKMRequest(NULL,
  2118. IOCTL_WMI_UNREGISTER_GUIDS,
  2119. &UnregGuids,
  2120. sizeof(WMIUNREGGUIDS),
  2121. &UnregGuids,
  2122. sizeof(WMIUNREGGUIDS),
  2123. &ReturnSize,
  2124. NULL);
  2125. WmipSetLastError(Status);
  2126. return(Status);
  2127. }
  2128. ULONG
  2129. WmipFlushLogger(
  2130. IN OUT PWMI_LOGGER_INFORMATION LoggerInfo
  2131. )
  2132. /*++
  2133. Routine Description:
  2134. This is the actual routine to communicate with the kernel to start
  2135. the logger. All the required parameters must be in LoggerInfo.
  2136. Arguments:
  2137. LoggerInfo The actual parameters to be passed to and return from
  2138. kernel.
  2139. Return Value:
  2140. The status of performing the action requested.
  2141. --*/
  2142. {
  2143. ULONG Status;
  2144. ULONG BufferSize;
  2145. PTRACE_ENABLE_CONTEXT pContext;
  2146. if ( (LoggerInfo == NULL)
  2147. || (LoggerInfo->Wnode.BufferSize < sizeof(WMI_LOGGER_INFORMATION))
  2148. || (! (LoggerInfo->Wnode.Flags & WNODE_FLAG_TRACED_GUID))) {
  2149. return WmipSetDosError(ERROR_INVALID_PARAMETER);
  2150. }
  2151. pContext = (PTRACE_ENABLE_CONTEXT) & LoggerInfo->Wnode.HistoricalContext;
  2152. if ( (pContext->InternalFlag != 0)
  2153. && (pContext->InternalFlag != EVENT_TRACE_INTERNAL_FLAG_PRIVATE)) {
  2154. // Currently only one possible InternalFlag value. This will filter
  2155. // out some bogus LoggerHandle
  2156. //
  2157. return WmipSetDosError(ERROR_INVALID_HANDLE);
  2158. }
  2159. if (LoggerInfo->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) {
  2160. Status = WmipSendUmLogRequest(
  2161. WmiFlushLoggerCode,
  2162. LoggerInfo
  2163. );
  2164. }
  2165. else {
  2166. Status = WmipSendWmiKMRequest( // actually start the logger here
  2167. NULL,
  2168. IOCTL_WMI_FLUSH_LOGGER,
  2169. LoggerInfo,
  2170. LoggerInfo->Wnode.BufferSize,
  2171. LoggerInfo,
  2172. LoggerInfo->Wnode.BufferSize,
  2173. &BufferSize,
  2174. NULL
  2175. );
  2176. }
  2177. return WmipSetDosError(Status);
  2178. }
  2179. #endif