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.

3802 lines
126 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. logapi.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. #ifdef DBG
  17. #include <stdio.h> // only for fprintf
  18. #endif
  19. #include <nt.h>
  20. #include <ntrtl.h> // for ntutrl.h
  21. #include <nturtl.h> // for RTL_CRITICAL_SECTION in winbase.h/wtypes.h
  22. #include <wtypes.h> // for LPGUID in wmium.h
  23. #include <ntverp.h>
  24. #include <limits.h>
  25. #include "wmiump.h"
  26. #include "evntrace.h"
  27. #include "tracelib.h"
  28. #include "trcapi.h"
  29. #include <strsafe.h>
  30. #define MAXSTR 1024
  31. #define MAXINST 0XFFFFFFFF
  32. #define TRACE_RETRY_COUNT 5
  33. #define TRACE_HEADER_FULL (TRACE_HEADER_FLAG | TRACE_HEADER_EVENT_TRACE \
  34. | (TRACE_HEADER_TYPE_FULL_HEADER << 16))
  35. #define TRACE_HEADER_INSTANCE (TRACE_HEADER_FLAG | TRACE_HEADER_EVENT_TRACE \
  36. | (TRACE_HEADER_TYPE_INSTANCE << 16))
  37. ULONG EtwpIsBBTOn = 0;
  38. //
  39. // This guid is used by RegisterTraceGuids when register a tracelog
  40. // provider. Any ACLs for controlling registration should be placed on
  41. // this guid. Note that since the kernel will created unnamed guid
  42. // objects, multiple tracelog providers can register without issue.
  43. //
  44. // {DF8480A1-7492-4f45-AB78-1084642581FB}
  45. GUID RegisterReservedGuid = { 0xdf8480a1, 0x7492, 0x4f45, 0xab, 0x78, 0x10, 0x84, 0x64, 0x25, 0x81, 0xfb };
  46. HANDLE EtwpDeviceHandle = NULL;
  47. VOID
  48. EtwpCopyInfoToProperties(
  49. IN PWMI_LOGGER_INFORMATION Info,
  50. IN PEVENT_TRACE_PROPERTIES Properties
  51. );
  52. VOID
  53. EtwpCopyPropertiesToInfo(
  54. IN PEVENT_TRACE_PROPERTIES Properties,
  55. IN PWMI_LOGGER_INFORMATION Info
  56. );
  57. VOID
  58. EtwpFixupLoggerStrings(
  59. PWMI_LOGGER_INFORMATION LoggerInfo
  60. );
  61. ULONG
  62. EtwpCheckForEnoughFreeSpace(
  63. PWCHAR FullLogFileName,
  64. ULONG FullLogFileNameLen,
  65. ULONG MaxFileSizeSpecified,
  66. ULONG AppendMode,
  67. ULONG UseKBytes
  68. );
  69. ULONG
  70. WMIAPI
  71. EtwUnregisterTraceGuids(
  72. IN TRACEHANDLE RegistrationHandle
  73. );
  74. VOID
  75. EtwpFixupLoggerStrings(
  76. PWMI_LOGGER_INFORMATION LoggerInfo
  77. )
  78. /*++
  79. Routine Description:
  80. This function resets the LoggerName.Buffer and LogFileName.Buffer
  81. pointers based on the Overall size of the structure and the individual
  82. lengths of the two strings.
  83. Assumptions: WMI_LOGGER_INFORMATION structure is laid out as follows.
  84. WMI_LOGGER_INFORMATION
  85. +----------------------+
  86. | Wnode.BufferSize ----|--------> size of the entire block including
  87. | | the two strings.
  88. | |
  89. | |
  90. | |
  91. | ... |
  92. | |
  93. | |
  94. +----------------------+
  95. | LoggerName.Length |
  96. | LoggerName.MaxLength |
  97. | LoggerName.Buffer----|----+
  98. | | |
  99. +----------------------+ |
  100. | LogFileName.Length | |
  101. | LogFileName.MaxLength| |
  102. +-----|-LogFileName.Buffer | |
  103. | +----------------------+ |
  104. | | ... | |
  105. | | | |
  106. | +----------------------+<---+ Offset = sizeof(WMI_LOGGER_INFORMATION)
  107. | | |
  108. | | LoggerName String |
  109. | | |
  110. +---->+----------------------+<---- Offset += LoggerName.MaximumLength
  111. | |
  112. | LogFileName String |
  113. | |
  114. +----------------------+
  115. Arguments:
  116. LoggerInfo Logger Information Structure
  117. Return Value:
  118. No return value.
  119. --*/
  120. {
  121. ULONG Offset = sizeof(WMI_LOGGER_INFORMATION);
  122. ULONG LoggerInfoSize;
  123. if (LoggerInfo == NULL)
  124. return;
  125. LoggerInfoSize = LoggerInfo->Wnode.BufferSize;
  126. if (LoggerInfoSize <= Offset)
  127. return;
  128. //
  129. // Fixup LoggerName first
  130. //
  131. if (LoggerInfo->LoggerName.Length > 0) {
  132. LoggerInfo->LoggerName.Buffer = (PWCHAR) ((PUCHAR)LoggerInfo + Offset);
  133. Offset += LoggerInfo->LoggerName.MaximumLength;
  134. }
  135. if (LoggerInfoSize <= Offset)
  136. return;
  137. if (LoggerInfo->LogFileName.Length > 0) {
  138. LoggerInfo->LogFileName.Buffer = (PWCHAR)((PUCHAR)LoggerInfo + Offset);
  139. Offset += LoggerInfo->LogFileName.MaximumLength;
  140. }
  141. #ifdef DBG
  142. EtwpAssert(LoggerInfoSize >= Offset);
  143. #endif
  144. }
  145. ULONG
  146. EtwpCheckForEnoughFreeSpace(
  147. PWCHAR FullLogFileName,
  148. ULONG FullLogFileNameLen,
  149. ULONG MaxFileSizeSpecified,
  150. ULONG AppendMode,
  151. ULONG UseKBytes
  152. )
  153. {
  154. ULONG NeededSpace = MaxFileSizeSpecified;
  155. ULONG SizeNeeded;
  156. UINT ReturnedSizeNeeded;
  157. PWCHAR strLogFileDir = NULL;
  158. WCHAR strSystemDir[MAX_PATH];
  159. if (NeededSpace && AppendMode) {
  160. ULONG Status;
  161. WIN32_FILE_ATTRIBUTE_DATA FileAttributes;
  162. ULONGLONG ExistingFileSize;
  163. ULONG ExistingFileSizeInMBytes, ExistingFileSizeInKBytes;
  164. if (EtwpGetFileAttributesExW(FullLogFileName,
  165. GetFileExInfoStandard,
  166. (LPVOID)(&FileAttributes))) {
  167. ExistingFileSize = (((ULONGLONG)FileAttributes.nFileSizeHigh) << 32)
  168. + FileAttributes.nFileSizeLow;
  169. ExistingFileSizeInMBytes = (ULONG)(ExistingFileSize / (1024 * 1024));
  170. ExistingFileSizeInKBytes = (ULONG)(ExistingFileSize / 1024);
  171. if (!UseKBytes) {
  172. if (ExistingFileSizeInMBytes >= NeededSpace) {
  173. return ERROR_DISK_FULL;
  174. }
  175. else {
  176. NeededSpace -= ExistingFileSizeInMBytes;
  177. }
  178. }
  179. else {
  180. if (ExistingFileSizeInKBytes >= NeededSpace) {
  181. return ERROR_DISK_FULL;
  182. }
  183. else {
  184. NeededSpace -= ExistingFileSizeInKBytes;
  185. }
  186. }
  187. }
  188. else { // GetFileAttributesExW() failed
  189. Status = EtwpGetLastError();
  190. // If the file is not found, advapi32.dll treats
  191. // the case as EVENT_TRACE_FILE_MODE_NEWFILE
  192. // So, we will let it go here.
  193. if (ERROR_FILE_NOT_FOUND != Status) {
  194. return Status;
  195. }
  196. }
  197. }
  198. RtlZeroMemory(&strSystemDir[0], sizeof(WCHAR) * MAX_PATH);
  199. ReturnedSizeNeeded = EtwpGetSystemDirectoryW(strSystemDir, MAX_PATH);
  200. if (ReturnedSizeNeeded == 0) {
  201. return EtwpGetLastError();
  202. }
  203. if (ReturnedSizeNeeded < 2 || FullLogFileNameLen < 2) {
  204. // This really cannot happen.
  205. return ERROR_INVALID_PARAMETER;
  206. }
  207. if (FullLogFileName[1] == L':' && strSystemDir[1] == L':') {
  208. if (!_wcsnicmp(FullLogFileName, strSystemDir, 1)) {
  209. if (!UseKBytes) {
  210. if (ULONG_MAX - 200 < NeededSpace) {
  211. // Addition may incur overflow
  212. return ERROR_DISK_FULL;
  213. }
  214. NeededSpace += 200;
  215. }
  216. else { // Using KBytes
  217. if (ULONG_MAX - (200 * 1024) < NeededSpace) {
  218. // Addition may incur overflow
  219. return ERROR_DISK_FULL;
  220. }
  221. else {
  222. NeededSpace += 200 * 1024;
  223. }
  224. }
  225. }
  226. }
  227. // Check for space only when we have to
  228. if (NeededSpace) {
  229. int i;
  230. ULARGE_INTEGER FreeBytesAvailable, TotalNumberOfBytes;
  231. ULONG FreeMegaBytes, FreeKiloBytes;
  232. strLogFileDir = EtwpAlloc((FullLogFileNameLen + 1) * sizeof(WCHAR));
  233. if (strLogFileDir == NULL) {
  234. return ERROR_NOT_ENOUGH_MEMORY;
  235. }
  236. wcsncpy(strLogFileDir, FullLogFileName, FullLogFileNameLen);
  237. for (i = FullLogFileNameLen - 1; i >= 0; i--) {
  238. if (strLogFileDir[i] == L'\\' || strLogFileDir[i] == L'/') {
  239. strLogFileDir[i] = '\0';
  240. break;
  241. }
  242. }
  243. if (i < 0) {
  244. // This really cannot happen.
  245. EtwpFree(strLogFileDir);
  246. strLogFileDir = NULL;
  247. }
  248. // it also works with network paths
  249. if (EtwpGetDiskFreeSpaceExW(strLogFileDir,
  250. &FreeBytesAvailable,
  251. &TotalNumberOfBytes,
  252. NULL)) {
  253. FreeMegaBytes = (ULONG)(FreeBytesAvailable.QuadPart / (1024 *1024));
  254. FreeKiloBytes = (ULONG)(FreeBytesAvailable.QuadPart / 1024);
  255. EtwpFree(strLogFileDir);
  256. if (!UseKBytes && FreeMegaBytes < NeededSpace) {
  257. return ERROR_DISK_FULL;
  258. }
  259. else if (UseKBytes && FreeKiloBytes < NeededSpace) {
  260. return ERROR_DISK_FULL;
  261. }
  262. }
  263. else {
  264. EtwpFree(strLogFileDir);
  265. return EtwpGetLastError();
  266. }
  267. }
  268. return ERROR_SUCCESS;
  269. }
  270. ULONG
  271. EtwpValidateLogFileMode(
  272. IN OUT PEVENT_TRACE_PROPERTIES Properties,
  273. IN ULONG IsLogFile
  274. )
  275. /*++
  276. Routine Description:
  277. This routine validates the LogFileMode field. Several combinations
  278. of mode are not allowed and this routine will trap all the invalid
  279. combinations. A similar check is made in the kernel in case anyone
  280. tries to call the IOCTL_WMI* directly.
  281. Arguments:
  282. Properties Logger properties.
  283. Return Value:
  284. The status of performing the action requested.
  285. --*/
  286. {
  287. //
  288. // 1. You need to specifiy either a LogFile or RealTimeMode
  289. //
  290. if (!(Properties->LogFileMode & EVENT_TRACE_REAL_TIME_MODE)) {
  291. if (!IsLogFile) {
  292. return ERROR_BAD_PATHNAME;
  293. }
  294. }
  295. //
  296. // 2, RealTimeMode from a Process Private logger is not allowed
  297. //
  298. if ((Properties->LogFileMode & EVENT_TRACE_REAL_TIME_MODE) &&
  299. (Properties->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) ) {
  300. return ERROR_INVALID_PARAMETER;
  301. }
  302. //
  303. // 3. We can not append to a circular or RealTimeMode
  304. //
  305. if (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_APPEND) {
  306. if ( (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR)
  307. || (Properties->LogFileMode & EVENT_TRACE_REAL_TIME_MODE)) {
  308. return ERROR_INVALID_PARAMETER;
  309. }
  310. }
  311. //
  312. // 4. For Preallocation, you must provide a LogFile and maximumSize.
  313. // Preallocation is not allowed with NEWFILE or ProcessPrivate.
  314. //
  315. if (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_PREALLOCATE) {
  316. if ( (Properties->MaximumFileSize == 0)
  317. || (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_NEWFILE)
  318. || (Properties->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE)
  319. || (!IsLogFile)) {
  320. return ERROR_INVALID_PARAMETER;
  321. }
  322. }
  323. //
  324. // 5. For USE_KBYTES, we need a logfile and a non-zero maximum size
  325. //
  326. if (Properties->LogFileMode & EVENT_TRACE_USE_KBYTES_FOR_SIZE) {
  327. if ((Properties->MaximumFileSize == 0)
  328. || (!IsLogFile)) {
  329. return ERROR_INVALID_PARAMETER;
  330. }
  331. }
  332. //
  333. // 6. Relogger is supported only with Private Logger
  334. //
  335. if (Properties->LogFileMode & EVENT_TRACE_RELOG_MODE) {
  336. if (!(Properties->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE)
  337. || (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR)
  338. || (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_NEWFILE)
  339. || (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_APPEND) ) {
  340. return ERROR_INVALID_PARAMETER;
  341. }
  342. }
  343. //
  344. // 7. NewFile mode is not supported for CIRCULAR or ProcessPrivate.
  345. // It is not supported for Kernel Logger. You must specify a logfile
  346. // and a maximum file size.
  347. //
  348. if (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_NEWFILE) {
  349. if ((Properties->MaximumFileSize == 0) ||
  350. (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) ||
  351. (Properties->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE) ||
  352. (IsLogFile != TRUE) ||
  353. (IsEqualGUID(&Properties->Wnode.Guid, &SystemTraceControlGuid))
  354. // Kernel Logger cannot be in newfile mode
  355. ){
  356. return ERROR_INVALID_PARAMETER;
  357. }
  358. }
  359. //
  360. // 8. Circular mode must specify a MaximumFileSize
  361. //
  362. if ( (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_CIRCULAR) &&
  363. (Properties->MaximumFileSize == 0) ) {
  364. return ERROR_INVALID_PARAMETER;
  365. }
  366. return ERROR_SUCCESS;
  367. }
  368. ULONG
  369. WMIAPI
  370. EtwStartTraceA(
  371. OUT PTRACEHANDLE LoggerHandle,
  372. IN LPCSTR LoggerName,
  373. IN OUT PEVENT_TRACE_PROPERTIES Properties
  374. )
  375. /*++
  376. Routine Description:
  377. This is the ANSI version routine to start a logger.
  378. The caller must pass in a pointer to accept the returned logger handle,
  379. and must provide a valid logger name.
  380. Arguments:
  381. LoggerHandle The handle to the logger to be returned.
  382. LoggerName A unique name for the logger
  383. Properties Logger properties. If the caller wishes to use WMI's
  384. defaults, all the numeric values must be set to 0.
  385. Furthermore, the LoggerName and LogFileName fields
  386. within must point to sufficient storage for the names
  387. to be returned.
  388. Return Value:
  389. The status of performing the action requested.
  390. --*/
  391. {
  392. NTSTATUS Status;
  393. ULONG ErrorCode;
  394. PWMI_LOGGER_INFORMATION LoggerInfo = NULL;
  395. ANSI_STRING AnsiString;
  396. ULONG IsLogFile;
  397. LPSTR CapturedName;
  398. ULONG SizeNeeded;
  399. ULONG LogFileNameLen, LoggerNameLen;
  400. PCHAR LogFileName;
  401. PTRACE_ENABLE_FLAG_EXTENSION FlagExt = NULL;
  402. PCHAR FullPathName=NULL;
  403. ULONG FullPathNameSize = MAXSTR;
  404. ULONG RelogPropSize = 0;
  405. EtwpInitProcessHeap();
  406. // first check to make sure that arguments passed are alright
  407. //
  408. if (Properties == NULL || LoggerHandle == NULL) {
  409. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  410. }
  411. if (LoggerName == NULL) {
  412. return EtwpSetDosError(ERROR_INVALID_NAME);
  413. }
  414. IsLogFile = TRUE;
  415. LogFileNameLen = 0;
  416. LoggerNameLen = 0;
  417. LogFileName = NULL;
  418. try {
  419. //
  420. // LoggerName is a Mandatory Parameter. Must provide space for it.
  421. //
  422. LoggerNameLen = strlen(LoggerName);
  423. SizeNeeded = sizeof (EVENT_TRACE_PROPERTIES) + LoggerNameLen + 1;
  424. //
  425. // Rules for Kernel Logger Identification
  426. // 1. If the logger name is "NT Kernel Logger", it is the kernel logger,
  427. // and the System GUID is copied as well.
  428. // 2. If the GUID is equal to the System GUID, but not the name, reject
  429. // the session.
  430. //
  431. if (!strcmp(LoggerName, KERNEL_LOGGER_NAMEA)) {
  432. Properties->Wnode.Guid = SystemTraceControlGuid;
  433. }
  434. else if (IsEqualGUID(&Properties->Wnode.Guid, &SystemTraceControlGuid)){
  435. // LoggerName is not "NT Kernel Logger", but Guid is
  436. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  437. }
  438. // If the caller supplied loggername and LogFileName offsets
  439. // make sure they are in range.
  440. //
  441. if (Properties->LoggerNameOffset > 0)
  442. if ((Properties->LoggerNameOffset < sizeof (EVENT_TRACE_PROPERTIES))
  443. || (Properties->LoggerNameOffset > Properties->Wnode.BufferSize))
  444. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  445. if (Properties->LogFileNameOffset > 0) {
  446. ULONG RetValue;
  447. if ((Properties->LogFileNameOffset < sizeof(EVENT_TRACE_PROPERTIES))
  448. || (Properties->LogFileNameOffset > Properties->Wnode.BufferSize))
  449. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  450. LogFileName = ((PCHAR)Properties + Properties->LogFileNameOffset );
  451. SizeNeeded += (strlen(LogFileName) + 1) * sizeof(CHAR);
  452. Retry:
  453. FullPathName = EtwpAlloc(FullPathNameSize);
  454. if (FullPathName == NULL) {
  455. return EtwpSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  456. }
  457. RetValue = EtwpGetFullPathNameA(LogFileName,
  458. FullPathNameSize,
  459. FullPathName,
  460. NULL);
  461. if (RetValue != 0) {
  462. if (RetValue > FullPathNameSize) {
  463. EtwpFree(FullPathName);
  464. FullPathNameSize = RetValue;
  465. goto Retry;
  466. }
  467. else {
  468. LogFileName = FullPathName;
  469. }
  470. }
  471. LogFileNameLen = strlen(LogFileName);
  472. if (LogFileNameLen == 0)
  473. IsLogFile = FALSE;
  474. }
  475. else
  476. IsLogFile = FALSE;
  477. //
  478. // Check to see if there is room in the Properties structure
  479. // to return both the InstanceName (LoggerName) and the LogFileName
  480. //
  481. // Note that we are only checking to see if there is room to return
  482. // relative path name for logfiles.
  483. //
  484. if (Properties->Wnode.BufferSize < SizeNeeded) {
  485. ErrorCode = ERROR_BAD_LENGTH;
  486. goto Cleanup;
  487. }
  488. CapturedName = (LPSTR) LoggerName;
  489. LoggerNameLen = strlen(CapturedName);
  490. if (LoggerNameLen <= 0) {
  491. ErrorCode = ERROR_INVALID_NAME;
  492. goto Cleanup;
  493. }
  494. ErrorCode = EtwpValidateLogFileMode(Properties, IsLogFile);
  495. if (ErrorCode != ERROR_SUCCESS) {
  496. goto Cleanup;
  497. }
  498. if (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_NEWFILE) {
  499. //
  500. // Check to see if there a %d Pattern in the LogFileName
  501. //
  502. PCHAR cptr = strchr(LogFileName, '%');
  503. if (NULL == cptr || cptr != strrchr(LogFileName, '%')) {
  504. ErrorCode = ERROR_INVALID_NAME;
  505. goto Cleanup;
  506. }
  507. else if (NULL == strstr(LogFileName, "%d")) {
  508. ErrorCode = ERROR_INVALID_NAME;
  509. goto Cleanup;
  510. }
  511. }
  512. // For UserMode logger the LoggerName and LogFileName must be
  513. // passed in as offsets.
  514. SizeNeeded = sizeof(WMI_LOGGER_INFORMATION) +
  515. (LoggerNameLen + 1) * sizeof(WCHAR) +
  516. (LogFileNameLen + 1) * sizeof(WCHAR);
  517. //
  518. // If the EXTENSION bit is set on the EnableFlags, then we are passing
  519. // the extended flags. The size of the flags are given as Number of ULONGs
  520. // in the Length field of TRACE_ENABLE_FLAG_EXTENSION structure.
  521. //
  522. // Check to see if the Properties structure has the right size for
  523. // extended flags.
  524. //
  525. if (Properties->EnableFlags & EVENT_TRACE_FLAG_EXTENSION) {
  526. FlagExt = (PTRACE_ENABLE_FLAG_EXTENSION) &Properties->EnableFlags;
  527. if ((FlagExt->Length == 0) || (FlagExt->Offset == 0) ||
  528. (FlagExt->Offset < sizeof(EVENT_TRACE_PROPERTIES)) ||
  529. (FlagExt->Offset > Properties->Wnode.BufferSize) ||
  530. (FlagExt->Length * sizeof(ULONG) > Properties->Wnode.BufferSize
  531. - sizeof(EVENT_TRACE_PROPERTIES))) {
  532. ErrorCode = ERROR_INVALID_PARAMETER;
  533. goto Cleanup;
  534. }
  535. SizeNeeded += FlagExt->Length * sizeof(ULONG);
  536. }
  537. //
  538. // If RELOG mode, then pass on the LOGFILE_HEADER from old logfile
  539. // appended to the LOGGER_INFORMATION
  540. //
  541. if (Properties->LogFileMode & EVENT_TRACE_RELOG_MODE) {
  542. PSYSTEM_TRACE_HEADER pSysHeader;
  543. pSysHeader = (PSYSTEM_TRACE_HEADER)
  544. ((PUCHAR)Properties + sizeof(EVENT_TRACE_PROPERTIES) );
  545. RelogPropSize = pSysHeader->Packet.Size;
  546. //
  547. // Before tagging on a structure at the end of user supplied strings
  548. // align it.
  549. //
  550. SizeNeeded = ALIGN_TO_POWER2(SizeNeeded, 8);
  551. SizeNeeded += RelogPropSize;
  552. }
  553. SizeNeeded = ALIGN_TO_POWER2(SizeNeeded, 8);
  554. LoggerInfo = EtwpAlloc(SizeNeeded);
  555. if (LoggerInfo == NULL) {
  556. ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  557. goto Cleanup;
  558. }
  559. RtlZeroMemory(LoggerInfo, SizeNeeded);
  560. // at this point, we need to prepare WMI_LOGGER_INFORMATION
  561. // which requires Ansi strings to be converted to UNICODE_STRING
  562. //
  563. *LoggerHandle = 0;
  564. EtwpCopyPropertiesToInfo(
  565. (PEVENT_TRACE_PROPERTIES) Properties,
  566. LoggerInfo);
  567. //
  568. // If we are relogging, the caller passes in the number of processors
  569. // for the Private logger to use via the ProviderId field in Wnode
  570. //
  571. LoggerInfo->NumberOfProcessors = Properties->Wnode.ProviderId;
  572. LoggerInfo->Wnode.ProviderId = 0;
  573. RtlInitAnsiString(&AnsiString, CapturedName);
  574. LoggerInfo->LoggerName.MaximumLength =
  575. (USHORT) (sizeof(WCHAR) * (LoggerNameLen + 1));
  576. LoggerInfo->LoggerName.Buffer =
  577. (LPWSTR) ( ((PUCHAR) LoggerInfo)
  578. + sizeof(WMI_LOGGER_INFORMATION));
  579. Status = RtlAnsiStringToUnicodeString(
  580. &LoggerInfo->LoggerName,
  581. &AnsiString, FALSE);
  582. if (!NT_SUCCESS(Status)) {
  583. ErrorCode = EtwpNtStatusToDosError(Status);
  584. goto Cleanup;
  585. }
  586. if (IsLogFile) {
  587. LoggerInfo->LogFileName.MaximumLength =
  588. (USHORT) (sizeof(WCHAR) * (LogFileNameLen + 1));
  589. LoggerInfo->LogFileName.Buffer =
  590. (LPWSTR) ( ((PUCHAR) LoggerInfo)
  591. + sizeof(WMI_LOGGER_INFORMATION)
  592. + LoggerInfo->LoggerName.MaximumLength);
  593. RtlInitAnsiString(&AnsiString, LogFileName);
  594. Status = RtlAnsiStringToUnicodeString(
  595. &LoggerInfo->LogFileName,
  596. &AnsiString, FALSE);
  597. if (!NT_SUCCESS(Status)) {
  598. ErrorCode = EtwpNtStatusToDosError(Status);
  599. goto Cleanup;
  600. }
  601. Status = EtwpCheckForEnoughFreeSpace(
  602. LoggerInfo->LogFileName.Buffer,
  603. LogFileNameLen,
  604. Properties->MaximumFileSize,
  605. (Properties->LogFileMode &
  606. EVENT_TRACE_FILE_MODE_APPEND),
  607. (Properties->LogFileMode &
  608. EVENT_TRACE_USE_KBYTES_FOR_SIZE)
  609. );
  610. if (Status != ERROR_SUCCESS) {
  611. ErrorCode = Status;
  612. goto Cleanup;
  613. }
  614. }
  615. LoggerInfo->Wnode.BufferSize = SizeNeeded;
  616. LoggerInfo->Wnode.Flags |= WNODE_FLAG_TRACED_GUID;
  617. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_EXTENSION) {
  618. PTRACE_ENABLE_FLAG_EXTENSION tFlagExt;
  619. ULONG Offset;
  620. tFlagExt = (PTRACE_ENABLE_FLAG_EXTENSION) &LoggerInfo->EnableFlags;
  621. Offset = SizeNeeded - (FlagExt->Length * sizeof(ULONG));
  622. tFlagExt->Offset = (USHORT) Offset;
  623. RtlCopyMemory(
  624. (PCHAR) LoggerInfo + Offset,
  625. (PCHAR) Properties + FlagExt->Offset,
  626. FlagExt->Length * sizeof(ULONG) );
  627. }
  628. if ( (Properties->LogFileMode & EVENT_TRACE_RELOG_MODE) &&
  629. (RelogPropSize > 0) ) {
  630. PSYSTEM_TRACE_HEADER pRelog, pSysHeader;
  631. PTRACE_LOGFILE_HEADER Relog;
  632. ULONG Offset;
  633. Offset = sizeof(WMI_LOGGER_INFORMATION) +
  634. LoggerInfo->LoggerName.MaximumLength +
  635. LoggerInfo->LogFileName.MaximumLength;
  636. Offset = ALIGN_TO_POWER2( Offset, 8 );
  637. pRelog = (PSYSTEM_TRACE_HEADER) ( ((PUCHAR) LoggerInfo) + Offset);
  638. pSysHeader = (PSYSTEM_TRACE_HEADER) ( (PUCHAR)Properties +
  639. sizeof(EVENT_TRACE_PROPERTIES) );
  640. RtlCopyMemory(pRelog, pSysHeader, RelogPropSize);
  641. }
  642. ErrorCode = EtwpStartLogger(LoggerInfo);
  643. if (ErrorCode == ERROR_SUCCESS) {
  644. ULONG AvailableLength, RequiredLength;
  645. PCHAR pLoggerName, pLogFileName;
  646. EtwpCopyInfoToProperties(
  647. LoggerInfo,
  648. (PEVENT_TRACE_PROPERTIES)Properties);
  649. if (Properties->LoggerNameOffset == 0) {
  650. Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  651. }
  652. pLoggerName = (PCHAR)((PCHAR)Properties +
  653. Properties->LoggerNameOffset );
  654. if (Properties->LoggerNameOffset > Properties->LogFileNameOffset )
  655. AvailableLength = Properties->Wnode.BufferSize -
  656. Properties->LoggerNameOffset;
  657. else
  658. AvailableLength = Properties->LogFileNameOffset -
  659. Properties->LoggerNameOffset;
  660. RequiredLength = strlen(CapturedName) + 1;
  661. if (RequiredLength <= AvailableLength) {
  662. StringCchCopyA(pLoggerName, AvailableLength, CapturedName);
  663. }
  664. *LoggerHandle = LoggerInfo->Wnode.HistoricalContext;
  665. //
  666. // If there is room copy fullpath name
  667. //
  668. if (Properties->LogFileNameOffset > Properties->LoggerNameOffset )
  669. AvailableLength = Properties->Wnode.BufferSize -
  670. Properties->LogFileNameOffset;
  671. else
  672. AvailableLength = Properties->LoggerNameOffset -
  673. Properties->LogFileNameOffset;
  674. if ( (LogFileNameLen > 0) && (AvailableLength >= LogFileNameLen) ) {
  675. pLogFileName = (PCHAR)((PCHAR)Properties +
  676. Properties->LogFileNameOffset );
  677. StringCchCopyA(pLogFileName, AvailableLength, LogFileName);
  678. }
  679. }
  680. }
  681. except (EXCEPTION_EXECUTE_HANDLER) {
  682. ErrorCode = EtwpNtStatusToDosError( GetExceptionCode() );
  683. }
  684. Cleanup:
  685. if (LoggerInfo != NULL)
  686. EtwpFree(LoggerInfo);
  687. if (FullPathName != NULL)
  688. EtwpFree(FullPathName);
  689. return EtwpSetDosError(ErrorCode);
  690. }
  691. ULONG
  692. WMIAPI
  693. EtwStartTraceW(
  694. OUT PTRACEHANDLE LoggerHandle,
  695. IN LPCWSTR LoggerName,
  696. IN OUT PEVENT_TRACE_PROPERTIES Properties
  697. )
  698. /*++
  699. Routine Description:
  700. This is the Unicode version routine to start a logger.
  701. The caller must pass in a pointer to accept the returned logger handle,
  702. and must provide a valid logger name.
  703. Arguments:
  704. LoggerHandle The handle to the logger to be returned.
  705. LoggerName A unique name for the logger
  706. Properties Logger properties. If the caller wishes to use WMI's
  707. defaults, all the numeric values must be set to 0.
  708. Furthermore, the LoggerName and LogFileName fields
  709. within must point to sufficient storage for the names
  710. to be returned.
  711. Return Value:
  712. The status of performing the action requested.
  713. --*/
  714. {
  715. ULONG ErrorCode;
  716. PWMI_LOGGER_INFORMATION LoggerInfo = NULL;
  717. ULONG IsLogFile;
  718. LPWSTR CapturedName;
  719. ULONG SizeNeeded;
  720. USHORT LogFileNameLen, LoggerNameLen;
  721. PWCHAR LogFileName;
  722. PTRACE_ENABLE_FLAG_EXTENSION FlagExt = NULL;
  723. PWCHAR FullPathName = NULL;
  724. ULONG FullPathNameSize = MAXSTR;
  725. ULONG RetValue;
  726. ULONG RelogPropSize = 0;
  727. EtwpInitProcessHeap();
  728. // first check to make sure that arguments passed are alright
  729. //
  730. if (Properties == NULL || LoggerHandle == NULL) {
  731. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  732. }
  733. if (LoggerName == NULL) {
  734. return EtwpSetDosError(ERROR_INVALID_NAME);
  735. }
  736. IsLogFile = TRUE;
  737. LogFileNameLen = 0;
  738. LoggerNameLen = 0;
  739. LogFileName = NULL;
  740. try {
  741. // LoggerName is a Mandatory Parameter. Must provide space for it.
  742. //
  743. CapturedName = (LPWSTR) LoggerName;
  744. LoggerNameLen = (USHORT) wcslen(CapturedName);
  745. SizeNeeded = sizeof (EVENT_TRACE_PROPERTIES) +
  746. (LoggerNameLen + 1) * sizeof(WCHAR);
  747. //
  748. // Rules for Kernel Logger Identification
  749. // 1. If the logger name is "NT Kernel Logger", it is the kernel logger,
  750. // and the System GUID is copied as well.
  751. // 2. If the GUID is equal to the System GUID, but not the name, reject
  752. // the session.
  753. //
  754. if (!wcscmp(LoggerName, KERNEL_LOGGER_NAMEW)) {
  755. Properties->Wnode.Guid = SystemTraceControlGuid;
  756. }
  757. else if (IsEqualGUID(&Properties->Wnode.Guid, &SystemTraceControlGuid)){
  758. // LoggerName is not "NT Kernel Logger", but Guid is
  759. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  760. }
  761. // If the caller supplied loggername and LogFileName offsets
  762. // make sure they are in range.
  763. //
  764. if (Properties->LoggerNameOffset > 0)
  765. if ((Properties->LoggerNameOffset < sizeof(EVENT_TRACE_PROPERTIES))
  766. || (Properties->LoggerNameOffset > Properties->Wnode.BufferSize))
  767. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  768. if (Properties->LogFileNameOffset > 0) {
  769. if ((Properties->LogFileNameOffset < sizeof(EVENT_TRACE_PROPERTIES))
  770. || (Properties->LogFileNameOffset > Properties->Wnode.BufferSize))
  771. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  772. LogFileName = (PWCHAR)((char*)Properties +
  773. Properties->LogFileNameOffset);
  774. SizeNeeded += (wcslen(LogFileName) +1) * sizeof(WCHAR);
  775. Retry:
  776. FullPathName = EtwpAlloc(FullPathNameSize * sizeof(WCHAR));
  777. if (FullPathName == NULL) {
  778. return EtwpSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  779. }
  780. RetValue = EtwpGetFullPathNameW(LogFileName,
  781. FullPathNameSize,
  782. FullPathName,
  783. NULL);
  784. if (RetValue != 0) {
  785. if (RetValue > FullPathNameSize) {
  786. EtwpFree(FullPathName);
  787. FullPathNameSize = RetValue;
  788. goto Retry;
  789. }
  790. else {
  791. LogFileName = FullPathName;
  792. }
  793. }
  794. LogFileNameLen = (USHORT) wcslen(LogFileName);
  795. if (LogFileNameLen <= 0)
  796. IsLogFile = FALSE;
  797. }
  798. else
  799. IsLogFile = FALSE;
  800. //
  801. // Check to see if there is room for both LogFileName and
  802. // LoggerName (InstanceName) to be returned
  803. //
  804. if (Properties->Wnode.BufferSize < SizeNeeded) {
  805. ErrorCode = ERROR_BAD_LENGTH;
  806. goto Cleanup;
  807. }
  808. LoggerNameLen = (USHORT) wcslen(CapturedName);
  809. if (LoggerNameLen <= 0) {
  810. ErrorCode = ERROR_INVALID_NAME;
  811. goto Cleanup;
  812. }
  813. ErrorCode = EtwpValidateLogFileMode(Properties, IsLogFile);
  814. if (ErrorCode != ERROR_SUCCESS) {
  815. goto Cleanup;
  816. }
  817. if (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_NEWFILE) {
  818. //
  819. // Check to see if there a %d Pattern in the LogFileName
  820. //
  821. PWCHAR wcptr = wcschr(LogFileName, L'%');
  822. if (NULL == wcptr || wcptr != wcsrchr(LogFileName, L'%')) {
  823. ErrorCode = ERROR_INVALID_NAME;
  824. goto Cleanup;
  825. }
  826. else if (NULL == wcsstr(LogFileName, L"%d")) {
  827. ErrorCode = ERROR_INVALID_NAME;
  828. goto Cleanup;
  829. }
  830. }
  831. SizeNeeded = sizeof(WMI_LOGGER_INFORMATION) +
  832. (LoggerNameLen +1) * sizeof(WCHAR) +
  833. (LogFileNameLen + 1) * sizeof(WCHAR);
  834. if (Properties->EnableFlags & EVENT_TRACE_FLAG_EXTENSION) {
  835. FlagExt = (PTRACE_ENABLE_FLAG_EXTENSION) &Properties->EnableFlags;
  836. if ((FlagExt->Length == 0) || (FlagExt->Offset == 0) ||
  837. (FlagExt->Offset < sizeof(EVENT_TRACE_PROPERTIES)) ||
  838. (FlagExt->Offset > Properties->Wnode.BufferSize) ||
  839. (FlagExt->Length * sizeof(ULONG) > Properties->Wnode.BufferSize
  840. - sizeof(EVENT_TRACE_PROPERTIES)))
  841. {
  842. ErrorCode = ERROR_INVALID_PARAMETER;
  843. goto Cleanup;
  844. }
  845. SizeNeeded += FlagExt->Length * sizeof(ULONG);
  846. }
  847. //
  848. // If RELOG mode, then pass on the LOGFILE_HEADER from old logfile
  849. // appended to the LOGGER_INFORMATION
  850. //
  851. if (Properties->LogFileMode & EVENT_TRACE_RELOG_MODE) {
  852. PSYSTEM_TRACE_HEADER pSysHeader;
  853. pSysHeader = (PSYSTEM_TRACE_HEADER)((PUCHAR)Properties +
  854. sizeof(EVENT_TRACE_PROPERTIES) );
  855. RelogPropSize = pSysHeader->Packet.Size;
  856. //
  857. // Need to align due to strings
  858. //
  859. SizeNeeded = ALIGN_TO_POWER2(SizeNeeded, 8);
  860. SizeNeeded += RelogPropSize;
  861. }
  862. SizeNeeded = ALIGN_TO_POWER2(SizeNeeded, 8);
  863. LoggerInfo = EtwpAlloc(SizeNeeded);
  864. if (LoggerInfo == NULL) {
  865. ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  866. goto Cleanup;
  867. }
  868. RtlZeroMemory(LoggerInfo, SizeNeeded);
  869. // at this point, we need to prepare WMI_LOGGER_INFORMATION
  870. // which requires wide char strings to be converted to UNICODE_STRING
  871. //
  872. *LoggerHandle = 0;
  873. EtwpCopyPropertiesToInfo(Properties, LoggerInfo);
  874. //
  875. // If we are relogging, the caller passes in the number of processors
  876. // for the Private logger to use via the ProviderId field in Wnode
  877. //
  878. LoggerInfo->NumberOfProcessors = Properties->Wnode.ProviderId;
  879. LoggerInfo->Wnode.ProviderId = 0;
  880. LoggerInfo->LoggerName.MaximumLength =
  881. sizeof(WCHAR) * (LoggerNameLen + 1);
  882. LoggerInfo->LoggerName.Length =
  883. sizeof(WCHAR) * LoggerNameLen;
  884. LoggerInfo->LoggerName.Buffer = (PWCHAR)
  885. (((PUCHAR) LoggerInfo) + sizeof(WMI_LOGGER_INFORMATION));
  886. wcsncpy(LoggerInfo->LoggerName.Buffer, LoggerName, LoggerNameLen);
  887. if (IsLogFile) {
  888. ULONG Status;
  889. LoggerInfo->LogFileName.MaximumLength =
  890. sizeof(WCHAR) * (LogFileNameLen + 1);
  891. LoggerInfo->LogFileName.Length =
  892. sizeof(WCHAR) * LogFileNameLen;
  893. LoggerInfo->LogFileName.Buffer = (PWCHAR)
  894. (((PUCHAR) LoggerInfo) + sizeof(WMI_LOGGER_INFORMATION)
  895. + LoggerInfo->LoggerName.MaximumLength);
  896. wcsncpy(LoggerInfo->LogFileName.Buffer,
  897. LogFileName,
  898. LogFileNameLen);
  899. Status = EtwpCheckForEnoughFreeSpace(
  900. LoggerInfo->LogFileName.Buffer,
  901. LogFileNameLen,
  902. Properties->MaximumFileSize,
  903. (Properties->LogFileMode &
  904. EVENT_TRACE_FILE_MODE_APPEND),
  905. (Properties->LogFileMode &
  906. EVENT_TRACE_USE_KBYTES_FOR_SIZE)
  907. );
  908. if (Status != ERROR_SUCCESS) {
  909. ErrorCode = Status;
  910. goto Cleanup;
  911. }
  912. }
  913. LoggerInfo->Wnode.BufferSize = SizeNeeded;
  914. LoggerInfo->Wnode.Flags |= WNODE_FLAG_TRACED_GUID;
  915. if (LoggerInfo->EnableFlags & EVENT_TRACE_FLAG_EXTENSION) {
  916. PTRACE_ENABLE_FLAG_EXTENSION tFlagExt;
  917. ULONG Offset;
  918. tFlagExt = (PTRACE_ENABLE_FLAG_EXTENSION) &LoggerInfo->EnableFlags;
  919. Offset = SizeNeeded - (FlagExt->Length * sizeof(ULONG));
  920. tFlagExt->Offset = (USHORT) Offset;
  921. RtlCopyMemory(
  922. (PCHAR) LoggerInfo + Offset,
  923. (PCHAR) Properties + FlagExt->Offset,
  924. FlagExt->Length * sizeof(ULONG) );
  925. }
  926. if ( (Properties->LogFileMode & EVENT_TRACE_RELOG_MODE) &&
  927. (RelogPropSize > 0) ) {
  928. PSYSTEM_TRACE_HEADER pRelog, pSysHeader;
  929. PTRACE_LOGFILE_HEADER Relog;
  930. ULONG Offset;
  931. Offset = sizeof(WMI_LOGGER_INFORMATION) +
  932. LoggerInfo->LoggerName.MaximumLength +
  933. LoggerInfo->LogFileName.MaximumLength;
  934. Offset = ALIGN_TO_POWER2(Offset, 8);
  935. pRelog = (PSYSTEM_TRACE_HEADER) ( ((PUCHAR) LoggerInfo) + Offset);
  936. pSysHeader = (PSYSTEM_TRACE_HEADER) (
  937. (PUCHAR)Properties +
  938. sizeof(EVENT_TRACE_PROPERTIES)
  939. );
  940. RtlCopyMemory(pRelog, pSysHeader, RelogPropSize);
  941. }
  942. ErrorCode = EtwpStartLogger(LoggerInfo);
  943. if (ErrorCode == ERROR_SUCCESS) {
  944. ULONG AvailableLength, RequiredLength;
  945. PWCHAR pLoggerName;
  946. PWCHAR pLogFileName;
  947. EtwpCopyInfoToProperties(LoggerInfo, Properties);
  948. if (Properties->LoggerNameOffset > 0) {
  949. Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  950. }
  951. pLoggerName = (PWCHAR)((PCHAR)Properties +
  952. Properties->LoggerNameOffset );
  953. if (Properties->LoggerNameOffset > Properties->LogFileNameOffset )
  954. AvailableLength = Properties->Wnode.BufferSize -
  955. Properties->LoggerNameOffset;
  956. else
  957. AvailableLength = Properties->LogFileNameOffset -
  958. Properties->LoggerNameOffset;
  959. RequiredLength = (wcslen(CapturedName) + 1) * sizeof(WCHAR);
  960. if (RequiredLength <= AvailableLength) {
  961. StringCbCopyW(pLoggerName, AvailableLength, CapturedName);
  962. }
  963. *LoggerHandle = LoggerInfo->Wnode.HistoricalContext;
  964. if (Properties->LogFileNameOffset > Properties->LoggerNameOffset )
  965. AvailableLength = Properties->Wnode.BufferSize -
  966. Properties->LogFileNameOffset;
  967. else
  968. AvailableLength = Properties->LoggerNameOffset -
  969. Properties->LogFileNameOffset;
  970. RequiredLength = LoggerInfo->LogFileName.Length;
  971. pLogFileName = (PWCHAR)((PCHAR)Properties +
  972. Properties->LogFileNameOffset );
  973. if ( (RequiredLength > 0) && (RequiredLength <= AvailableLength) ) {
  974. wcsncpy(pLogFileName,
  975. LoggerInfo->LogFileName.Buffer,
  976. LogFileNameLen
  977. );
  978. pLogFileName[LogFileNameLen] = L'\0';
  979. }
  980. }
  981. }
  982. except (EXCEPTION_EXECUTE_HANDLER) {
  983. ErrorCode = EtwpNtStatusToDosError( GetExceptionCode() );
  984. }
  985. Cleanup:
  986. if (LoggerInfo != NULL)
  987. EtwpFree(LoggerInfo);
  988. if (FullPathName != NULL)
  989. EtwpFree(FullPathName);
  990. return EtwpSetDosError(ErrorCode);
  991. }
  992. ULONG
  993. WMIAPI
  994. EtwControlTraceA(
  995. IN TRACEHANDLE LoggerHandle,
  996. IN LPCSTR LoggerName,
  997. IN OUT PEVENT_TRACE_PROPERTIES Properties,
  998. IN ULONG Control
  999. )
  1000. /*++
  1001. Routine Description:
  1002. This is the ANSI version routine to control and query an existing logger.
  1003. The caller must pass in either a valid handle, or a logger name to
  1004. reference the logger instance. If both are given, the logger name will
  1005. be used.
  1006. Arguments:
  1007. LoggerHandle The handle to the logger instance.
  1008. LoggerName A instance name for the logger
  1009. Properties Logger properties to be returned to the caller.
  1010. Control This can be one of the following:
  1011. EVENT_TRACE_CONTROL_QUERY - to query the logger
  1012. EVENT_TRACE_CONTROL_STOP - to stop the logger
  1013. EVENT_TRACE_CONTROL_UPDATE - to update the logger
  1014. EVENT_TRACE_CONTROL_FLUSH - to flush the logger
  1015. Return Value:
  1016. The status of performing the action requested.
  1017. --*/
  1018. {
  1019. NTSTATUS Status;
  1020. ULONG ErrorCode;
  1021. BOOLEAN IsKernelTrace = FALSE;
  1022. BOOLEAN bFreeString = FALSE;
  1023. PWMI_LOGGER_INFORMATION LoggerInfo = NULL;
  1024. PWCHAR strLoggerName = NULL;
  1025. PWCHAR strLogFileName = NULL;
  1026. ULONG sizeNeeded = 0;
  1027. PCHAR FullPathName = NULL;
  1028. ULONG LoggerNameLen = MAXSTR;
  1029. ULONG LogFileNameLen = MAXSTR;
  1030. ULONG FullPathNameSize = MAXSTR;
  1031. ULONG RetValue;
  1032. PTRACE_ENABLE_CONTEXT pContext;
  1033. ANSI_STRING String;
  1034. EtwpInitProcessHeap();
  1035. RtlZeroMemory(&String, sizeof(ANSI_STRING));
  1036. if (Properties == NULL) {
  1037. ErrorCode = ERROR_INVALID_PARAMETER;
  1038. goto Cleanup;
  1039. }
  1040. try {
  1041. if (Properties->Wnode.BufferSize < sizeof(EVENT_TRACE_PROPERTIES) ) {
  1042. ErrorCode = ERROR_BAD_LENGTH;
  1043. goto Cleanup;
  1044. }
  1045. //
  1046. // If the caller supplied loggername and LogFileName offsets
  1047. // make sure they are in range.
  1048. //
  1049. if (Properties->LoggerNameOffset > 0) {
  1050. if ((Properties->LoggerNameOffset < sizeof(EVENT_TRACE_PROPERTIES))
  1051. || (Properties->LoggerNameOffset > Properties->Wnode.BufferSize))
  1052. {
  1053. ErrorCode = ERROR_INVALID_PARAMETER;
  1054. goto Cleanup;
  1055. }
  1056. }
  1057. if (Properties->LogFileNameOffset > 0) {
  1058. if ((Properties->LogFileNameOffset < sizeof(EVENT_TRACE_PROPERTIES))
  1059. || (Properties->LogFileNameOffset > Properties->Wnode.BufferSize))
  1060. {
  1061. ErrorCode = ERROR_INVALID_PARAMETER;
  1062. goto Cleanup;
  1063. }
  1064. }
  1065. if (LoggerName != NULL) {
  1066. LoggerNameLen = strlen(LoggerName) + 1;
  1067. //
  1068. // Rules for Kernel Logger Identification when a string is given
  1069. // instead of handle
  1070. // 1. If the logger name is "NT Kernel Logger", it is the
  1071. // kernel logger, and the System GUID is copied as well.
  1072. // 2. If the GUID is equal to the System GUID, but not the name,
  1073. // reject the session.
  1074. // 3. If the logger name is null or of size 0, and the GUID is
  1075. // equal to the System GUID, let it proceed as the kernel logger.
  1076. //
  1077. if (!strcmp(LoggerName, KERNEL_LOGGER_NAMEA)) {
  1078. Properties->Wnode.Guid = SystemTraceControlGuid;
  1079. }
  1080. else if (IsEqualGUID(&Properties->Wnode.Guid, &SystemTraceControlGuid)) {
  1081. // LoggerName is not "NT Kernel Logger", but Guid is
  1082. if (strlen(LoggerName) > 0) {
  1083. ErrorCode = ERROR_INVALID_PARAMETER;
  1084. goto Cleanup;
  1085. }
  1086. }
  1087. }
  1088. if (IsEqualGUID(&Properties->Wnode.Guid, &SystemTraceControlGuid)) {
  1089. IsKernelTrace = TRUE;
  1090. }
  1091. if ((LoggerHandle == 0) && (!IsKernelTrace)) {
  1092. if ((LoggerName == NULL) || (strlen(LoggerName) <= 0)) {
  1093. ErrorCode = ERROR_INVALID_PARAMETER;
  1094. goto Cleanup;
  1095. }
  1096. }
  1097. //
  1098. // We do not support UpdateTrace to a new file with APPEND mode
  1099. //
  1100. if ( (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_APPEND) &&
  1101. (Control == EVENT_TRACE_CONTROL_UPDATE) &&
  1102. (Properties->LogFileNameOffset > 0) ) {
  1103. ErrorCode = ERROR_INVALID_PARAMETER;
  1104. goto Cleanup;
  1105. }
  1106. /*
  1107. if (LoggerHandle != 0) {
  1108. pContext = (PTRACE_ENABLE_CONTEXT) &LoggerHandle;
  1109. if ( (pContext->InternalFlag != 0) &&
  1110. (pContext->InternalFlag != EVENT_TRACE_INTERNAL_FLAG_PRIVATE)) {
  1111. // Currently only one possible InternalFlag value. This will filter
  1112. // out some bogus LoggerHandle
  1113. //
  1114. return EtwpSetDosError(ERROR_INVALID_HANDLE);
  1115. }
  1116. }
  1117. */
  1118. }
  1119. except (EXCEPTION_EXECUTE_HANDLER) {
  1120. ErrorCode = ERROR_NOACCESS;
  1121. goto Cleanup;
  1122. }
  1123. RetryFull:
  1124. // Extra 32 bytes for UMlogger to append instance name to logfilename.
  1125. LogFileNameLen += 16;
  1126. sizeNeeded = sizeof(WMI_LOGGER_INFORMATION) +
  1127. (LoggerNameLen + LogFileNameLen) * sizeof(WCHAR);
  1128. sizeNeeded = ALIGN_TO_POWER2(sizeNeeded, 8);
  1129. LoggerInfo = (PWMI_LOGGER_INFORMATION) EtwpAlloc(sizeNeeded);
  1130. if (LoggerInfo == NULL) {
  1131. ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  1132. goto Cleanup;
  1133. }
  1134. RtlZeroMemory(LoggerInfo, sizeNeeded);
  1135. strLoggerName = (PWCHAR) ( ((PUCHAR) LoggerInfo)
  1136. + sizeof(WMI_LOGGER_INFORMATION));
  1137. EtwpInitString(&LoggerInfo->LoggerName,
  1138. strLoggerName,
  1139. LoggerNameLen * sizeof(WCHAR));
  1140. strLogFileName = (PWCHAR) ( ((PUCHAR) LoggerInfo)
  1141. + sizeof(WMI_LOGGER_INFORMATION)
  1142. + LoggerNameLen * sizeof(WCHAR));
  1143. EtwpInitString(&LoggerInfo->LogFileName,
  1144. strLogFileName,
  1145. LogFileNameLen * sizeof(WCHAR));
  1146. // Look for logger name first
  1147. //
  1148. try {
  1149. if (LoggerName != NULL) {
  1150. if (strlen(LoggerName) > 0) {
  1151. ANSI_STRING AnsiString;
  1152. RtlInitAnsiString(&AnsiString, LoggerName);
  1153. Status = RtlAnsiStringToUnicodeString(
  1154. &LoggerInfo->LoggerName, &AnsiString, FALSE);
  1155. if (!NT_SUCCESS(Status)) {
  1156. ErrorCode = EtwpNtStatusToDosError(Status);
  1157. goto Cleanup;
  1158. }
  1159. }
  1160. }
  1161. // InitString up above already does this.
  1162. // LoggerInfo->LogFileName.Buffer = (PWCHAR)
  1163. // (((PCHAR) LoggerInfo) + sizeof(WMI_LOGGER_INFORMATION)
  1164. // + LoggerInfo->LoggerName.MaximumLength);
  1165. //
  1166. if (Properties->LogFileNameOffset >= sizeof(EVENT_TRACE_PROPERTIES)) {
  1167. ULONG lenLogFileName;
  1168. PCHAR strLogFileNameA;
  1169. strLogFileNameA = (PCHAR) ( ((PCHAR) Properties)
  1170. + Properties->LogFileNameOffset);
  1171. Retry:
  1172. FullPathName = EtwpAlloc(FullPathNameSize);
  1173. if (FullPathName == NULL) {
  1174. ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  1175. goto Cleanup;
  1176. }
  1177. RetValue = EtwpGetFullPathNameA(strLogFileNameA,
  1178. FullPathNameSize,
  1179. FullPathName,
  1180. NULL);
  1181. if (RetValue != 0) {
  1182. if (RetValue > FullPathNameSize) {
  1183. EtwpFree(FullPathName);
  1184. FullPathNameSize = RetValue;
  1185. goto Retry;
  1186. }
  1187. else {
  1188. strLogFileNameA = FullPathName;
  1189. }
  1190. }
  1191. lenLogFileName = strlen(strLogFileNameA);
  1192. if (lenLogFileName > 0) {
  1193. ANSI_STRING ansiLogFileName;
  1194. RtlInitAnsiString(& ansiLogFileName, strLogFileNameA);
  1195. LoggerInfo->LogFileName.MaximumLength =
  1196. sizeof(WCHAR) * ((USHORT) (lenLogFileName + 1));
  1197. Status = RtlAnsiStringToUnicodeString(
  1198. & LoggerInfo->LogFileName, & ansiLogFileName, FALSE);
  1199. if (!NT_SUCCESS(Status)) {
  1200. ErrorCode = EtwpNtStatusToDosError(Status);
  1201. goto Cleanup;
  1202. }
  1203. }
  1204. }
  1205. // stuff the loggerhandle in Wnode
  1206. LoggerInfo->Wnode.HistoricalContext = LoggerHandle;
  1207. LoggerInfo->LogFileMode = Properties->LogFileMode;
  1208. LoggerInfo->Wnode.BufferSize = sizeNeeded;
  1209. LoggerInfo->Wnode.Flags |= WNODE_FLAG_TRACED_GUID;
  1210. //
  1211. // For Private Loggers the Guid is required to determine the provider
  1212. //
  1213. LoggerInfo->Wnode.Guid = Properties->Wnode.Guid;
  1214. switch (Control) {
  1215. case EVENT_TRACE_CONTROL_QUERY :
  1216. ErrorCode = EtwpQueryLogger(LoggerInfo, FALSE);
  1217. break;
  1218. case EVENT_TRACE_CONTROL_STOP :
  1219. ErrorCode = EtwpStopLogger(LoggerInfo);
  1220. break;
  1221. case EVENT_TRACE_CONTROL_UPDATE :
  1222. EtwpCopyPropertiesToInfo((PEVENT_TRACE_PROPERTIES) Properties,
  1223. LoggerInfo);
  1224. LoggerInfo->Wnode.HistoricalContext = LoggerHandle;
  1225. LoggerInfo->Wnode.Flags |= WNODE_FLAG_TRACED_GUID;
  1226. ErrorCode = EtwpQueryLogger(LoggerInfo, TRUE);
  1227. break;
  1228. case EVENT_TRACE_CONTROL_FLUSH :
  1229. ErrorCode = EtwpFlushLogger(LoggerInfo);
  1230. break;
  1231. default :
  1232. ErrorCode = ERROR_INVALID_PARAMETER;
  1233. }
  1234. //
  1235. // The Kernel call could fail with ERROR_MORE_DATA and we need to retry
  1236. // with sufficient buffer space for the two strings. The size required
  1237. // is returned in the MaximuumLength field.
  1238. //
  1239. if (ErrorCode == ERROR_MORE_DATA) {
  1240. LogFileNameLen = LoggerInfo->LogFileName.MaximumLength /
  1241. sizeof(WCHAR);
  1242. LoggerNameLen = LoggerInfo->LoggerName.MaximumLength /
  1243. sizeof(WCHAR);
  1244. if (LoggerInfo != NULL) {
  1245. EtwpFree(LoggerInfo);
  1246. LoggerInfo = NULL;
  1247. }
  1248. if (FullPathName != NULL) {
  1249. EtwpFree(FullPathName);
  1250. FullPathName = NULL;
  1251. }
  1252. goto RetryFull;
  1253. }
  1254. //
  1255. // The Kernel call succeeded. Now we need to get the output and
  1256. // pass it back to the caller. This is complicated by the fact that
  1257. // WMI_LOGGER_INFORMATION structure uses pointers instead of offsets.
  1258. //
  1259. if (ErrorCode == ERROR_SUCCESS) {
  1260. PCHAR pLoggerName, pLogFileName;
  1261. ULONG BytesAvailable;
  1262. ULONG Length = 0;
  1263. EtwpCopyInfoToProperties(
  1264. LoggerInfo,
  1265. (PEVENT_TRACE_PROPERTIES)Properties);
  1266. //
  1267. // need to convert the strings back
  1268. //
  1269. EtwpFixupLoggerStrings(LoggerInfo);
  1270. //
  1271. // Now we need to copy the strings into Properties structure after
  1272. // converting them to ANSI strings
  1273. //
  1274. if (Properties->LoggerNameOffset == 0)
  1275. Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  1276. if (Properties->LoggerNameOffset > Properties->LogFileNameOffset)
  1277. BytesAvailable = Properties->Wnode.BufferSize -
  1278. Properties->LoggerNameOffset;
  1279. else
  1280. BytesAvailable = Properties->LogFileNameOffset -
  1281. Properties->LoggerNameOffset;
  1282. Status = RtlUnicodeStringToAnsiString(
  1283. &String, &LoggerInfo->LoggerName, TRUE);
  1284. if (NT_SUCCESS(Status)) {
  1285. bFreeString = TRUE;
  1286. Length = String.Length;
  1287. if (BytesAvailable < (Length + sizeof(CHAR)) ) {
  1288. PWNODE_TOO_SMALL WnodeSmall = (PWNODE_TOO_SMALL) Properties;
  1289. WnodeSmall->SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) +
  1290. Length +
  1291. LoggerInfo->LogFileName.Length +
  1292. 2 * sizeof(CHAR);
  1293. WnodeSmall->WnodeHeader.Flags |= WNODE_FLAG_TOO_SMALL;
  1294. ErrorCode = ERROR_MORE_DATA;
  1295. goto Cleanup;
  1296. }
  1297. else {
  1298. pLoggerName = (PCHAR) ((PCHAR)Properties +
  1299. Properties->LoggerNameOffset);
  1300. RtlZeroMemory(pLoggerName, BytesAvailable);
  1301. if (Length > 0) {
  1302. strncpy(pLoggerName, String.Buffer, Length);
  1303. }
  1304. //
  1305. // Though the RtlZeroMemory above and the BytesAvailable
  1306. // takes care of this, we want to be explicit about
  1307. // null terminating this string
  1308. //
  1309. pLoggerName[Length] = '\0';
  1310. }
  1311. ErrorCode = RtlNtStatusToDosError(Status);
  1312. }
  1313. if (Properties->LogFileNameOffset == 0) {
  1314. Properties->LogFileNameOffset = Properties->LoggerNameOffset +
  1315. Length + sizeof(CHAR);
  1316. }
  1317. if (Properties->LogFileNameOffset > Properties->LoggerNameOffset)
  1318. BytesAvailable = Properties->Wnode.BufferSize -
  1319. Properties->LogFileNameOffset;
  1320. else
  1321. BytesAvailable = Properties->LoggerNameOffset -
  1322. Properties->LogFileNameOffset;
  1323. RtlFreeAnsiString(&String);
  1324. bFreeString = FALSE;
  1325. Status = RtlUnicodeStringToAnsiString(
  1326. &String, &LoggerInfo->LogFileName, TRUE);
  1327. if (NT_SUCCESS(Status)) {
  1328. bFreeString = TRUE;
  1329. Length = String.Length;
  1330. if (BytesAvailable < (Length + sizeof(CHAR)) ) {
  1331. PWNODE_TOO_SMALL WnodeSmall = (PWNODE_TOO_SMALL) Properties;
  1332. WnodeSmall->SizeNeeded = (Properties->Wnode.BufferSize -
  1333. BytesAvailable) +
  1334. Length +
  1335. sizeof(CHAR);
  1336. WnodeSmall->WnodeHeader.Flags |= WNODE_FLAG_TOO_SMALL;
  1337. ErrorCode = ERROR_MORE_DATA;
  1338. }
  1339. else {
  1340. pLogFileName = (PCHAR) ((PCHAR)Properties +
  1341. Properties->LogFileNameOffset
  1342. );
  1343. RtlZeroMemory(pLogFileName, BytesAvailable);
  1344. strncpy(pLogFileName, String.Buffer, Length );
  1345. }
  1346. ErrorCode = RtlNtStatusToDosError(Status);
  1347. }
  1348. }
  1349. }
  1350. except (EXCEPTION_EXECUTE_HANDLER) {
  1351. ErrorCode = EtwpNtStatusToDosError(GetExceptionCode());
  1352. }
  1353. Cleanup:
  1354. if (bFreeString)
  1355. RtlFreeAnsiString(&String);
  1356. if (LoggerInfo != NULL)
  1357. EtwpFree(LoggerInfo);
  1358. if (FullPathName != NULL)
  1359. EtwpFree(FullPathName);
  1360. return EtwpSetDosError(ErrorCode);
  1361. }
  1362. ULONG
  1363. WMIAPI
  1364. EtwControlTraceW(
  1365. IN TRACEHANDLE LoggerHandle,
  1366. IN LPCWSTR LoggerName,
  1367. IN OUT PEVENT_TRACE_PROPERTIES Properties,
  1368. IN ULONG Control
  1369. )
  1370. /*++
  1371. Routine Description:
  1372. This is the ANSI version routine to control and query an existing logger.
  1373. The caller must pass in either a valid handle, or a logger name to
  1374. reference the logger instance. If both are given, the logger name will
  1375. be used.
  1376. Arguments:
  1377. LoggerHandle The handle to the logger instance.
  1378. LoggerName A instance name for the logger
  1379. Properties Logger properties to be returned to the caller.
  1380. Control This can be one of the following:
  1381. EVENT_TRACE_CONTROL_QUERY - to query the logger
  1382. EVENT_TRACE_CONTROL_STOP - to stop the logger
  1383. EVENT_TRACE_CONTROL_UPDATE - to update the logger
  1384. EVENT_TRACE_CONTROL_FLUSH - to flush the logger
  1385. Return Value:
  1386. The status of performing the action requested.
  1387. --*/
  1388. {
  1389. ULONG ErrorCode;
  1390. BOOLEAN IsKernelTrace = FALSE;
  1391. PWMI_LOGGER_INFORMATION LoggerInfo = NULL;
  1392. PWCHAR strLoggerName = NULL;
  1393. PWCHAR strLogFileName = NULL;
  1394. ULONG sizeNeeded = 0;
  1395. PWCHAR FullPathName = NULL;
  1396. ULONG LoggerNameLen = MAXSTR;
  1397. ULONG LogFileNameLen = MAXSTR;
  1398. ULONG RetValue;
  1399. PTRACE_ENABLE_CONTEXT pContext;
  1400. EtwpInitProcessHeap();
  1401. if (Properties == NULL) {
  1402. ErrorCode = ERROR_INVALID_PARAMETER;
  1403. goto Cleanup;
  1404. }
  1405. try {
  1406. if (Properties->Wnode.BufferSize < sizeof(EVENT_TRACE_PROPERTIES) ) {
  1407. ErrorCode = ERROR_BAD_LENGTH;
  1408. goto Cleanup;
  1409. }
  1410. //
  1411. // If the caller supplied loggername and LogFileName offsets
  1412. // make sure they are in range.
  1413. //
  1414. if (Properties->LoggerNameOffset > 0) {
  1415. if ((Properties->LoggerNameOffset < sizeof (EVENT_TRACE_PROPERTIES))
  1416. || (Properties->LoggerNameOffset > Properties->Wnode.BufferSize)) {
  1417. ErrorCode = ERROR_INVALID_PARAMETER;
  1418. goto Cleanup;
  1419. }
  1420. }
  1421. if (Properties->LogFileNameOffset > 0) {
  1422. if ((Properties->LogFileNameOffset < sizeof(EVENT_TRACE_PROPERTIES))
  1423. || (Properties->LogFileNameOffset > Properties->Wnode.BufferSize))
  1424. {
  1425. ErrorCode = ERROR_INVALID_PARAMETER;
  1426. goto Cleanup;
  1427. }
  1428. }
  1429. if (LoggerName != NULL) {
  1430. LoggerNameLen = wcslen(LoggerName) + 1;
  1431. //
  1432. // Rules for Kernel Logger Identification when a string is given
  1433. // instead of handle
  1434. // 1. If the logger name is "NT Kernel Logger", it is the
  1435. // kernel logger, and the System GUID is copied as well.
  1436. // 2. If the GUID is equal to the System GUID, but not the name,
  1437. // reject the session.
  1438. // 3. If the logger name is null or of size 0, and the GUID is
  1439. // equal to the System GUID, let it proceed as the kernel logger.
  1440. //
  1441. if (!wcscmp(LoggerName, KERNEL_LOGGER_NAMEW)) {
  1442. Properties->Wnode.Guid = SystemTraceControlGuid;
  1443. }
  1444. else if (IsEqualGUID(&Properties->Wnode.Guid,
  1445. &SystemTraceControlGuid)) {
  1446. // LoggerName is not "NT Kernel Logger", but Guid is
  1447. if (wcslen(LoggerName) > 0) {
  1448. ErrorCode = ERROR_INVALID_PARAMETER;
  1449. goto Cleanup;
  1450. }
  1451. }
  1452. }
  1453. if (IsEqualGUID(&Properties->Wnode.Guid, &SystemTraceControlGuid)) {
  1454. IsKernelTrace = TRUE;
  1455. }
  1456. if ((LoggerHandle == 0) && (!IsKernelTrace)) {
  1457. if ((LoggerName == NULL) || (wcslen(LoggerName) <= 0)) {
  1458. ErrorCode = ERROR_INVALID_PARAMETER;
  1459. goto Cleanup;
  1460. }
  1461. }
  1462. //
  1463. // We do not support UpdateTrace to a new file with APPEND mode
  1464. //
  1465. if ( (Properties->LogFileMode & EVENT_TRACE_FILE_MODE_APPEND) &&
  1466. (Control == EVENT_TRACE_CONTROL_UPDATE) &&
  1467. (Properties->LogFileNameOffset > 0) ) {
  1468. ErrorCode = ERROR_INVALID_PARAMETER;
  1469. goto Cleanup;
  1470. }
  1471. //
  1472. // If LoggerHandle is supplied, check to see if it valid
  1473. //
  1474. /*
  1475. if (LoggerHandle != 0) {
  1476. pContext = (PTRACE_ENABLE_CONTEXT) &LoggerHandle;
  1477. if ((pContext->InternalFlag != 0) &&
  1478. (pContext->InternalFlag != EVENT_TRACE_INTERNAL_FLAG_PRIVATE)) {
  1479. // Currently only one possible InternalFlag value. This will filter
  1480. // out some bogus LoggerHandle
  1481. //
  1482. return EtwpSetDosError(ERROR_INVALID_HANDLE);
  1483. }
  1484. }
  1485. */
  1486. }
  1487. except (EXCEPTION_EXECUTE_HANDLER) {
  1488. ErrorCode = ERROR_NOACCESS;
  1489. goto Cleanup;
  1490. }
  1491. RetryFull:
  1492. //
  1493. // Add an extra 16 characters to the LogFileName since the UMLogger
  1494. // could munge the name to add the PIDs at the end.
  1495. //
  1496. LogFileNameLen += 16;
  1497. sizeNeeded = sizeof(WMI_LOGGER_INFORMATION) +
  1498. (LoggerNameLen + LogFileNameLen) * sizeof(WCHAR);
  1499. sizeNeeded = ALIGN_TO_POWER2(sizeNeeded, 8);
  1500. LoggerInfo = (PWMI_LOGGER_INFORMATION) EtwpAlloc(sizeNeeded);
  1501. if (LoggerInfo == NULL) {
  1502. ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  1503. goto Cleanup;
  1504. }
  1505. RtlZeroMemory(LoggerInfo, sizeNeeded);
  1506. strLoggerName = (PWCHAR) ( ((PUCHAR) LoggerInfo)
  1507. + sizeof(WMI_LOGGER_INFORMATION));
  1508. EtwpInitString(&LoggerInfo->LoggerName,
  1509. strLoggerName,
  1510. LoggerNameLen * sizeof(WCHAR));
  1511. strLogFileName = (PWCHAR) ( ((PUCHAR) LoggerInfo)
  1512. + sizeof(WMI_LOGGER_INFORMATION)
  1513. + LoggerNameLen * sizeof(WCHAR));
  1514. EtwpInitString(&LoggerInfo->LogFileName,
  1515. strLogFileName,
  1516. LogFileNameLen * sizeof(WCHAR));
  1517. try {
  1518. if (LoggerName != NULL) {
  1519. if (wcslen(LoggerName) > 0) {
  1520. StringCchCopyW(strLoggerName, LoggerNameLen, LoggerName);
  1521. RtlInitUnicodeString(&LoggerInfo->LoggerName, strLoggerName);
  1522. }
  1523. }
  1524. if (Properties->LogFileNameOffset >= sizeof(EVENT_TRACE_PROPERTIES)) {
  1525. ULONG lenLogFileName;
  1526. ULONG FullPathNameSize = MAXSTR;
  1527. strLogFileName = (PWCHAR) ( ((PCHAR) Properties)
  1528. + Properties->LogFileNameOffset);
  1529. Retry:
  1530. FullPathName = EtwpAlloc(FullPathNameSize * sizeof(WCHAR));
  1531. if (FullPathName == NULL) {
  1532. ErrorCode = ERROR_NOT_ENOUGH_MEMORY;
  1533. goto Cleanup;
  1534. }
  1535. RetValue = EtwpGetFullPathNameW(strLogFileName,
  1536. FullPathNameSize,
  1537. FullPathName,
  1538. NULL
  1539. );
  1540. if (RetValue != 0) {
  1541. if (RetValue > FullPathNameSize) {
  1542. EtwpFree(FullPathName);
  1543. FullPathNameSize = RetValue;
  1544. goto Retry;
  1545. }
  1546. else {
  1547. strLogFileName = FullPathName;
  1548. }
  1549. }
  1550. lenLogFileName = wcslen(strLogFileName);
  1551. LoggerInfo->LogFileName.Buffer = (PWCHAR)
  1552. (((PCHAR) LoggerInfo) + sizeof(WMI_LOGGER_INFORMATION)
  1553. + LoggerInfo->LoggerName.MaximumLength);
  1554. if (lenLogFileName > 0) {
  1555. LoggerInfo->LogFileName.MaximumLength =
  1556. sizeof(WCHAR) * ((USHORT) (lenLogFileName + 1));
  1557. LoggerInfo->LogFileName.Length =
  1558. sizeof(WCHAR) * ((USHORT) (lenLogFileName));
  1559. wcsncpy(LoggerInfo->LogFileName.Buffer,
  1560. strLogFileName,
  1561. lenLogFileName);
  1562. }
  1563. else {
  1564. LoggerInfo->LogFileName.Length = 0;
  1565. LoggerInfo->LogFileName.MaximumLength = MAXSTR * sizeof(WCHAR);
  1566. }
  1567. }
  1568. LoggerInfo->LogFileMode = Properties->LogFileMode;
  1569. LoggerInfo->Wnode.HistoricalContext = LoggerHandle;
  1570. LoggerInfo->Wnode.BufferSize = sizeNeeded;
  1571. LoggerInfo->Wnode.Flags |= WNODE_FLAG_TRACED_GUID;
  1572. //
  1573. // For Private Loggers, the Guid must be supplied
  1574. //
  1575. LoggerInfo->Wnode.Guid = Properties->Wnode.Guid;
  1576. switch (Control) {
  1577. case EVENT_TRACE_CONTROL_QUERY :
  1578. ErrorCode = EtwpQueryLogger(LoggerInfo, FALSE);
  1579. break;
  1580. case EVENT_TRACE_CONTROL_STOP :
  1581. ErrorCode = EtwpStopLogger(LoggerInfo);
  1582. break;
  1583. case EVENT_TRACE_CONTROL_UPDATE :
  1584. EtwpCopyPropertiesToInfo(Properties, LoggerInfo);
  1585. LoggerInfo->Wnode.HistoricalContext = LoggerHandle;
  1586. ErrorCode = EtwpQueryLogger(LoggerInfo, TRUE);
  1587. break;
  1588. case EVENT_TRACE_CONTROL_FLUSH :
  1589. ErrorCode = EtwpFlushLogger(LoggerInfo);
  1590. break;
  1591. default :
  1592. ErrorCode = ERROR_INVALID_PARAMETER;
  1593. }
  1594. //
  1595. // The Kernel call could fail with ERROR_MORE_DATA and we need to retry
  1596. // with sufficient buffer space for the two strings. The size required
  1597. // is returned in the MaximuumLength field.
  1598. //
  1599. if (ErrorCode == ERROR_MORE_DATA) {
  1600. LogFileNameLen = LoggerInfo->LogFileName.MaximumLength /
  1601. sizeof(WCHAR);
  1602. LoggerNameLen = LoggerInfo->LoggerName.MaximumLength /
  1603. sizeof(WCHAR);
  1604. if (LoggerInfo != NULL) {
  1605. EtwpFree(LoggerInfo);
  1606. LoggerInfo = NULL;
  1607. }
  1608. if (FullPathName != NULL) {
  1609. EtwpFree(FullPathName);
  1610. FullPathName = NULL;
  1611. }
  1612. goto RetryFull;
  1613. }
  1614. if (ErrorCode == ERROR_SUCCESS) {
  1615. ULONG Length = 0;
  1616. ULONG BytesAvailable = 0;
  1617. PWCHAR pLoggerName, pLogFileName;
  1618. EtwpCopyInfoToProperties(LoggerInfo, Properties);
  1619. EtwpFixupLoggerStrings(LoggerInfo);
  1620. if (Properties->LoggerNameOffset == 0)
  1621. Properties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  1622. if (Properties->LoggerNameOffset > Properties->LogFileNameOffset )
  1623. BytesAvailable = Properties->Wnode.BufferSize -
  1624. Properties->LoggerNameOffset;
  1625. else
  1626. BytesAvailable = Properties->LogFileNameOffset -
  1627. Properties->LoggerNameOffset;
  1628. Length = LoggerInfo->LoggerName.Length;
  1629. if (Length > 0) {
  1630. if (BytesAvailable < (Length + sizeof(WCHAR) )) {
  1631. PWNODE_TOO_SMALL WnodeSmall = (PWNODE_TOO_SMALL) Properties;
  1632. WnodeSmall->SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) +
  1633. Length +
  1634. LoggerInfo->LogFileName.Length +
  1635. 2 * sizeof(WCHAR);
  1636. WnodeSmall->WnodeHeader.Flags |= WNODE_FLAG_TOO_SMALL;
  1637. Length = BytesAvailable - sizeof(WCHAR);
  1638. ErrorCode = ERROR_MORE_DATA;
  1639. goto Cleanup;
  1640. }
  1641. else {
  1642. pLoggerName = (PWCHAR) ((PCHAR)Properties +
  1643. Properties->LoggerNameOffset);
  1644. RtlZeroMemory(pLoggerName, BytesAvailable);
  1645. wcsncpy(pLoggerName,
  1646. LoggerInfo->LoggerName.Buffer,
  1647. Length/2 );
  1648. pLoggerName[Length/2] = L'\0';
  1649. }
  1650. }
  1651. if (Properties->LogFileNameOffset == 0) {
  1652. Properties->LogFileNameOffset = Properties->LoggerNameOffset +
  1653. Length + sizeof(WCHAR);
  1654. }
  1655. if (Properties->LogFileNameOffset > Properties->LoggerNameOffset )
  1656. BytesAvailable = Properties->Wnode.BufferSize -
  1657. Properties->LogFileNameOffset;
  1658. else
  1659. BytesAvailable = Properties->LoggerNameOffset -
  1660. Properties->LogFileNameOffset;
  1661. //
  1662. // Check for space to return LogFileName.
  1663. //
  1664. Length = LoggerInfo->LogFileName.Length;
  1665. if (Length > 0) {
  1666. if (BytesAvailable < (Length + sizeof(WCHAR)) ) {
  1667. PWNODE_TOO_SMALL WnodeSmall = (PWNODE_TOO_SMALL) Properties;
  1668. WnodeSmall->SizeNeeded = sizeof(EVENT_TRACE_PROPERTIES) +
  1669. Length +
  1670. LoggerInfo->LogFileName.Length +
  1671. 2 * sizeof(WCHAR);
  1672. WnodeSmall->WnodeHeader.Flags |= WNODE_FLAG_TOO_SMALL;
  1673. Length = BytesAvailable - sizeof(WCHAR);
  1674. ErrorCode = ERROR_MORE_DATA;
  1675. }
  1676. else {
  1677. pLogFileName = (PWCHAR) ((PCHAR)Properties +
  1678. Properties->LogFileNameOffset);
  1679. RtlZeroMemory(pLogFileName, BytesAvailable);
  1680. wcsncpy(pLogFileName,
  1681. LoggerInfo->LogFileName.Buffer, Length/2 );
  1682. pLogFileName[Length/2] = L'\0';
  1683. }
  1684. }
  1685. }
  1686. }
  1687. except (EXCEPTION_EXECUTE_HANDLER) {
  1688. ErrorCode = EtwpNtStatusToDosError(GetExceptionCode());
  1689. }
  1690. Cleanup:
  1691. if (LoggerInfo != NULL)
  1692. EtwpFree(LoggerInfo);
  1693. if (FullPathName != NULL)
  1694. EtwpFree(FullPathName);
  1695. return EtwpSetDosError(ErrorCode);
  1696. }
  1697. ULONG
  1698. EtwpEnableDisableKernelTrace(
  1699. IN ULONG Enable,
  1700. IN ULONG EnableFlag
  1701. )
  1702. {
  1703. ULONG status;
  1704. PWMI_LOGGER_INFORMATION pLoggerInfo;
  1705. ULONG Flags;
  1706. GUID Guid;
  1707. ULONG SizeNeeded = 0;
  1708. ULONG RetryCount = 1;
  1709. WMITRACEENABLEDISABLEINFO TraceEnableInfo;
  1710. ULONG ReturnSize;
  1711. //
  1712. // We need to query the kernel logger to find the current flags
  1713. // and construct the new flags to update with.
  1714. //
  1715. SizeNeeded = sizeof(WMI_LOGGER_INFORMATION) + 2 * MAXSTR * sizeof(WCHAR);
  1716. SizeNeeded = ALIGN_TO_POWER2(SizeNeeded, 8);
  1717. pLoggerInfo = EtwpAlloc(SizeNeeded);
  1718. if (pLoggerInfo == NULL) {
  1719. return EtwpSetDosError(ERROR_NOT_ENOUGH_MEMORY);
  1720. }
  1721. RtlZeroMemory(pLoggerInfo, SizeNeeded);
  1722. pLoggerInfo->Wnode.BufferSize = SizeNeeded;
  1723. pLoggerInfo->Wnode.Guid = SystemTraceControlGuid;
  1724. pLoggerInfo->Wnode.Flags |= WNODE_FLAG_TRACED_GUID;
  1725. WmiSetLoggerId(KERNEL_LOGGER_ID, &pLoggerInfo->Wnode.HistoricalContext);
  1726. status = EtwpQueryLogger(pLoggerInfo, FALSE);
  1727. if (status != ERROR_SUCCESS) {
  1728. EtwpFree(pLoggerInfo);
  1729. return EtwpSetDosError(status);
  1730. }
  1731. Flags = pLoggerInfo->EnableFlags;
  1732. //
  1733. // If Enabling, we need to pass down the final state of the flags
  1734. // ie., the old flags plus the new flags.
  1735. // If disabling, we need to pass down the only the flags that
  1736. // are already turned on and being turned off now.
  1737. //
  1738. if (Enable) {
  1739. Flags |= EnableFlag;
  1740. }
  1741. else {
  1742. Flags &= EnableFlag;
  1743. }
  1744. //
  1745. // At this point if the Flags are 0, then no change is being
  1746. // requested.
  1747. //
  1748. if (Flags) {
  1749. pLoggerInfo->EnableFlags = Flags;
  1750. status = EtwpQueryLogger(pLoggerInfo, TRUE);
  1751. }
  1752. EtwpFree(pLoggerInfo);
  1753. return EtwpSetDosError(status);
  1754. }
  1755. ULONG
  1756. WMIAPI
  1757. EtwEnableTrace(
  1758. IN ULONG Enable,
  1759. IN ULONG EnableFlag,
  1760. IN ULONG EnableLevel,
  1761. IN LPCGUID ControlGuid,
  1762. IN TRACEHANDLE TraceHandle
  1763. )
  1764. {
  1765. ULONG status;
  1766. PTRACE_ENABLE_CONTEXT pTraceHandle = (PTRACE_ENABLE_CONTEXT)&TraceHandle;
  1767. GUID Guid;
  1768. WMITRACEENABLEDISABLEINFO TraceEnableInfo;
  1769. ULONG ReturnSize;
  1770. EtwpInitProcessHeap();
  1771. // We only accept T/F for Enable code. In future, we really should take
  1772. // enumerated request codes. Declaring the Enable as ULONG instead
  1773. // of BOOLEAN should give us room for expansion.
  1774. if ( (ControlGuid == NULL)
  1775. || (EnableLevel > 255)
  1776. || ((Enable != TRUE) && (Enable != FALSE))
  1777. || (TraceHandle == (TRACEHANDLE)INVALID_HANDLE_VALUE)
  1778. || (TraceHandle == (TRACEHANDLE)0 ) ) {
  1779. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  1780. }
  1781. try {
  1782. Guid = *ControlGuid;
  1783. }
  1784. except (EXCEPTION_EXECUTE_HANDLER) {
  1785. return EtwpSetDosError(ERROR_NOACCESS);
  1786. }
  1787. //
  1788. // If this is for the Kernel Logger, we need to actually make
  1789. // an UpdateTrace call
  1790. //
  1791. if ( IsEqualGUID(&SystemTraceControlGuid, &Guid) ) {
  1792. status = EtwpEnableDisableKernelTrace(Enable, EnableFlag);
  1793. }
  1794. else {
  1795. pTraceHandle->Level = (UCHAR)EnableLevel;
  1796. pTraceHandle->EnableFlags = EnableFlag;
  1797. //
  1798. // For Non-Kernel Providers, simply call the WMI IOCTL
  1799. //
  1800. RtlZeroMemory(&TraceEnableInfo, sizeof(WMITRACEENABLEDISABLEINFO) );
  1801. TraceEnableInfo.Guid = Guid;
  1802. TraceEnableInfo.Enable = (BOOLEAN)Enable;
  1803. TraceEnableInfo.LoggerContext = TraceHandle;
  1804. status = EtwpSendWmiKMRequest(NULL,
  1805. IOCTL_WMI_ENABLE_DISABLE_TRACELOG,
  1806. &TraceEnableInfo,
  1807. sizeof(WMITRACEENABLEDISABLEINFO),
  1808. NULL,
  1809. 0,
  1810. &ReturnSize,
  1811. NULL);
  1812. }
  1813. return EtwpSetDosError(status);
  1814. }
  1815. ULONG
  1816. EtwpTraceEvent(
  1817. IN TRACEHANDLE LoggerHandle,
  1818. IN PWNODE_HEADER Wnode
  1819. )
  1820. {
  1821. NTSTATUS NtStatus;
  1822. IO_STATUS_BLOCK IoStatus;
  1823. PULONG TraceMarker;
  1824. ULONG Size;
  1825. PEVENT_TRACE_HEADER EventTrace = (PEVENT_TRACE_HEADER)Wnode;
  1826. USHORT LoggerId;
  1827. PTRACE_ENABLE_CONTEXT pContext = (PTRACE_ENABLE_CONTEXT)&LoggerHandle;
  1828. ULONG Status;
  1829. Wnode->HistoricalContext = LoggerHandle;
  1830. if ( (pContext->InternalFlag & EVENT_TRACE_INTERNAL_FLAG_PRIVATE) &&
  1831. (EtwpIsBBTOn == 0) ) {
  1832. Status = EtwpTraceUmEvent(Wnode);
  1833. return EtwpSetDosError(Status);
  1834. }
  1835. //
  1836. // Not a process private logger event. It is going to the kernel.
  1837. //
  1838. Size = EventTrace->Size;
  1839. //
  1840. // Now the LoggerHandle is expected to be filled in by the caller.
  1841. // But check to see if it has a valid value.
  1842. //
  1843. LoggerId = WmiGetLoggerId(LoggerHandle);
  1844. if ((LoggerId == 0) || (LoggerId == KERNEL_LOGGER_ID)) {
  1845. return ERROR_INVALID_HANDLE;
  1846. }
  1847. //
  1848. // When BBT buffers are active, we override all user mode logging
  1849. // to log to this one stream (Global Logger).
  1850. //
  1851. if (EtwpIsBBTOn) {
  1852. WmiSetLoggerId(WMI_GLOBAL_LOGGER_ID, &Wnode->HistoricalContext);
  1853. }
  1854. NtStatus = NtTraceEvent(NULL,
  1855. ETW_NT_FLAGS_TRACE_HEADER,
  1856. sizeof(WNODE_HEADER),
  1857. Wnode);
  1858. return EtwpNtStatusToDosError( NtStatus );
  1859. }
  1860. ULONG
  1861. WMIAPI
  1862. EtwTraceEvent(
  1863. IN TRACEHANDLE LoggerHandle,
  1864. IN PEVENT_TRACE_HEADER EventTrace
  1865. )
  1866. /*++
  1867. Routine Description:
  1868. This is the main entry point for logging events from user mode. The caller
  1869. must supply the LoggerHandle and a pointer to the evnet being logged.
  1870. This routine needs to make sure that the contents of the EventTrace
  1871. record are restored back to the way caller sent it. (Internally, they
  1872. are modified but restored before return).
  1873. Arguments:
  1874. LoggerHandle The handle to the logger instance.
  1875. EventTrace Pointer to the Event being logged.
  1876. Return Value:
  1877. The status of performing the action requested.
  1878. --*/
  1879. {
  1880. ULONG Status, SavedMarker;
  1881. PULONG TraceMarker;
  1882. ULONG Size;
  1883. ULONGLONG SavedGuidPtr;
  1884. BOOLEAN RestoreSavedGuidPtr = FALSE;
  1885. ULONG Flags;
  1886. EtwpInitProcessHeap();
  1887. if (EventTrace == NULL ) {
  1888. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  1889. }
  1890. try {
  1891. TraceMarker = (PULONG) EventTrace;
  1892. SavedMarker = *TraceMarker;
  1893. Flags = EventTrace->Flags;
  1894. EventTrace->Flags |= WNODE_FLAG_TRACED_GUID;
  1895. Size = EventTrace->Size;
  1896. if (Size < sizeof(EVENT_TRACE_HEADER)) {
  1897. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  1898. }
  1899. *TraceMarker = 0;
  1900. EventTrace->Size = (USHORT)Size;
  1901. *TraceMarker |= TRACE_HEADER_FULL;
  1902. if (EventTrace->Flags & WNODE_FLAG_USE_GUID_PTR) {
  1903. RestoreSavedGuidPtr = TRUE;
  1904. SavedGuidPtr = EventTrace->GuidPtr;
  1905. }
  1906. Status = EtwpTraceEvent(LoggerHandle, (PWNODE_HEADER) EventTrace);
  1907. *TraceMarker = SavedMarker;
  1908. EventTrace->Flags = Flags;
  1909. if (RestoreSavedGuidPtr) {
  1910. EventTrace->GuidPtr = SavedGuidPtr;
  1911. }
  1912. }
  1913. except (EXCEPTION_EXECUTE_HANDLER) {
  1914. Status = EtwpNtStatusToDosError( GetExceptionCode() );
  1915. }
  1916. return EtwpSetDosError(Status);
  1917. }
  1918. ULONG
  1919. WMIAPI
  1920. EtwTraceEventInstance(
  1921. IN TRACEHANDLE LoggerHandle,
  1922. IN PEVENT_INSTANCE_HEADER EventTrace,
  1923. IN PEVENT_INSTANCE_INFO pInstInfo,
  1924. IN PEVENT_INSTANCE_INFO pParentInstInfo
  1925. )
  1926. /*++
  1927. Routine Description:
  1928. This routine logs an event with its instance information. The caller
  1929. must supply the LoggerHandle, the Event to log and the Instance info.
  1930. Optionally, the cally may specify the Parent Instance info.
  1931. This routine needs to make sure that the contents of the EventTrace
  1932. record are restored back to the way caller sent it. (Internally, they
  1933. are modified but restored before return).
  1934. EVENT_INSTANCE_HEADER contains pointer for Guid and ParentGuid. In W2K,
  1935. this record is logged with the pointers and later decoded to Guids during
  1936. post processing using the GuidMaps dumped in the logfile.
  1937. For WinXP and above, we no longer use the GuidMaps. We convert the
  1938. EVENT_INSTANCE_HEADER to larger sized EVENT_INSTANCE_GUID_HEADER with the
  1939. Guids already translated. There is no decoding needed during postprocessing
  1940. as a result.
  1941. Arguments:
  1942. LoggerHandle The handle to the logger instance.
  1943. EventTrace Pointer to the Event being logged.
  1944. pInstInfo Pointer to Instance Information
  1945. pParentInfo Pointer to Parent's Instance Information
  1946. Return Value:
  1947. The status of performing the action requested.
  1948. --*/
  1949. {
  1950. PULONG TraceMarker;
  1951. PGUIDMAPENTRY GuidMapEntry;
  1952. ULONG Size, MofSize;
  1953. ULONG Flags;
  1954. PEVENT_INSTANCE_HEADER InstanceHeader= (PEVENT_INSTANCE_HEADER) EventTrace;
  1955. PEVENT_INSTANCE_GUID_HEADER InstanceGuidHeader;
  1956. ULONG Status;
  1957. struct { // This is the same structure as _EVENT_TRACE defined in evntrace.h
  1958. EVENT_INSTANCE_GUID_HEADER NewInstanceHeader;
  1959. MOF_FIELD MofField[MAX_MOF_FIELDS];
  1960. } InstanceEventTrace;
  1961. EtwpInitProcessHeap();
  1962. if ((EventTrace == NULL ) || (pInstInfo == NULL)) {
  1963. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  1964. }
  1965. try {
  1966. InstanceGuidHeader = &(InstanceEventTrace.NewInstanceHeader);
  1967. Flags = EventTrace->Flags;
  1968. TraceMarker = (PULONG)(InstanceGuidHeader);
  1969. Flags |= WNODE_FLAG_TRACED_GUID;
  1970. Size = EventTrace->Size;
  1971. if (Size < sizeof(EVENT_INSTANCE_HEADER)) {
  1972. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  1973. }
  1974. // Copy the contents of the instance header to the new structure.
  1975. RtlCopyMemory(InstanceGuidHeader,
  1976. InstanceHeader,
  1977. FIELD_OFFSET(EVENT_INSTANCE_HEADER, ParentRegHandle)
  1978. );
  1979. *TraceMarker = 0;
  1980. *TraceMarker |= TRACE_HEADER_INSTANCE;
  1981. //
  1982. // With EVENT_INSTANCE_HEADER we don't want the logger
  1983. // to try to dereference the GuidPtr since it is
  1984. // just a hash value for the Guid and not really a LPGUID.
  1985. //
  1986. if (InstanceGuidHeader->Flags & WNODE_FLAG_USE_GUID_PTR) {
  1987. InstanceGuidHeader->Flags &= ~WNODE_FLAG_USE_GUID_PTR;
  1988. }
  1989. GuidMapEntry = (PGUIDMAPENTRY) pInstInfo->RegHandle;
  1990. if (GuidMapEntry == NULL) {
  1991. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  1992. }
  1993. InstanceGuidHeader->InstanceId = pInstInfo->InstanceId;
  1994. // Newly added line for copying GUID
  1995. InstanceGuidHeader->Guid = GuidMapEntry->Guid;
  1996. if (pParentInstInfo != NULL) {
  1997. GuidMapEntry = (PGUIDMAPENTRY) pParentInstInfo->RegHandle;
  1998. if (GuidMapEntry == NULL) {
  1999. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2000. }
  2001. InstanceGuidHeader->ParentInstanceId =
  2002. pParentInstInfo->InstanceId;
  2003. // Newly added line for copying parent GUID
  2004. InstanceGuidHeader->ParentGuid = GuidMapEntry->Guid;
  2005. }
  2006. else {
  2007. InstanceGuidHeader->ParentInstanceId = 0;
  2008. RtlZeroMemory(&(InstanceGuidHeader->ParentGuid), sizeof(GUID));
  2009. }
  2010. if (InstanceGuidHeader->Flags & WNODE_FLAG_USE_MOF_PTR) {
  2011. PUCHAR Src, Dest;
  2012. MofSize = Size - sizeof(EVENT_INSTANCE_HEADER);
  2013. // Let's make sure we have a valid size
  2014. if ((MofSize % sizeof(MOF_FIELD)) != 0) {
  2015. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2016. }
  2017. Src = (PUCHAR)EventTrace + sizeof(EVENT_INSTANCE_HEADER);
  2018. Dest = (PUCHAR)InstanceGuidHeader +
  2019. sizeof(EVENT_INSTANCE_GUID_HEADER);
  2020. RtlCopyMemory(Dest, Src, MofSize);
  2021. // Correct the Size of the event.
  2022. // We already know Size >= sizeof(EVENT_INSTANCE_HEADER).
  2023. InstanceGuidHeader->Size = (USHORT)(Size -
  2024. sizeof(EVENT_INSTANCE_HEADER) +
  2025. sizeof(EVENT_INSTANCE_GUID_HEADER)
  2026. );
  2027. }
  2028. else {
  2029. MofSize = Size - sizeof(EVENT_INSTANCE_HEADER);
  2030. InstanceGuidHeader->Flags |= WNODE_FLAG_USE_MOF_PTR;
  2031. InstanceEventTrace.MofField[0].DataPtr =
  2032. (ULONG64) ((PUCHAR)EventTrace + sizeof(EVENT_INSTANCE_HEADER));
  2033. InstanceEventTrace.MofField[0].Length = MofSize;
  2034. // Correct the Size of the event. We are forcing the use of Mof Ptr.
  2035. InstanceGuidHeader->Size =
  2036. (USHORT)(sizeof(EVENT_INSTANCE_GUID_HEADER) + sizeof(MOF_FIELD));
  2037. }
  2038. Status = EtwpTraceEvent(
  2039. LoggerHandle,
  2040. (PWNODE_HEADER) InstanceGuidHeader
  2041. );
  2042. EventTrace->Flags = Flags;
  2043. }
  2044. except (EXCEPTION_EXECUTE_HANDLER) {
  2045. Status = EtwpNtStatusToDosError( GetExceptionCode() );
  2046. #if DBG
  2047. EtwpDebugPrint(("ETW: Exception in TraceEventInstance Status = %d\n",
  2048. Status));
  2049. #endif
  2050. }
  2051. return EtwpSetDosError(Status);
  2052. }
  2053. PTRACE_REG_INFO
  2054. EtwpAllocateGuidMaps(
  2055. IN WMIDPREQUEST RequestAddress,
  2056. IN PVOID RequestContext,
  2057. IN LPCGUID ControlGuid,
  2058. IN ULONG GuidCount,
  2059. IN PTRACE_GUID_REGISTRATION GuidReg
  2060. )
  2061. /*++
  2062. Routine Description:
  2063. The purpose of this routine is to allocate in calling process's address
  2064. space a hash of all the Guids being registered. Also to stash away
  2065. callback address and context.
  2066. Arguments:
  2067. RequestAddress Pointer of the Enable callback function
  2068. RequestContext Pointer to the Context to be passed back during callback
  2069. ControlGuid Pointer to control guid being registered.
  2070. GuidCount Count of Transaction Guids (0 to WMIMAXREGGUIDCOUNT)
  2071. GuidReg Pointer to transaction guid reg
  2072. Return Value:
  2073. Pointer to the address of the TRACE_REG_INFO block
  2074. --*/
  2075. {
  2076. ULONG i;
  2077. ULONG SizeNeeded;
  2078. PUCHAR Buffer;
  2079. PTRACE_REG_INFO pTraceRegInfo;
  2080. PTRACE_GUID_REGISTRATION GuidRegPtr;
  2081. PGUIDMAPENTRY pTransGuidMapEntry, pControlGMEntry;
  2082. SizeNeeded = sizeof(TRACE_REG_INFO) +
  2083. sizeof(GUIDMAPENTRY) + // Control Guid
  2084. sizeof(GUIDMAPENTRY) * GuidCount; // Transaction Guids
  2085. Buffer = EtwpAlloc(SizeNeeded);
  2086. if (Buffer == NULL) {
  2087. return NULL;
  2088. }
  2089. RtlZeroMemory(Buffer, SizeNeeded);
  2090. pTraceRegInfo = (PTRACE_REG_INFO) Buffer;
  2091. pTraceRegInfo->NotifyRoutine = (PVOID)RequestAddress;
  2092. pTraceRegInfo->NotifyContext = RequestContext;
  2093. pControlGMEntry = (PGUIDMAPENTRY) ( Buffer + sizeof(TRACE_REG_INFO) );
  2094. pControlGMEntry->Guid = *ControlGuid;
  2095. //
  2096. // Initialize the list of Guid Map Entries.
  2097. //
  2098. pTransGuidMapEntry = (PGUIDMAPENTRY) ( Buffer +
  2099. sizeof(TRACE_REG_INFO) +
  2100. sizeof(GUIDMAPENTRY) );
  2101. for (i=1; i <= GuidCount; i++) {
  2102. GuidRegPtr = &GuidReg[i-1];
  2103. GuidRegPtr->RegHandle = pTransGuidMapEntry;
  2104. pTransGuidMapEntry->Guid = *GuidRegPtr->Guid;
  2105. //
  2106. // Uses PID as signature.
  2107. //
  2108. pTransGuidMapEntry->Reserved = EtwpGetCurrentProcessId();
  2109. pTransGuidMapEntry++;
  2110. }
  2111. return pTraceRegInfo;
  2112. }
  2113. ULONG
  2114. EtwpMakeCallbacks(
  2115. IN LPCGUID ControlGuid,
  2116. IN WMIDPREQUEST RequestAddress,
  2117. IN PVOID RequestContext,
  2118. IN TRACEHANDLE LoggerContext,
  2119. IN PTRACE_REG_INFO pTraceRegInfo
  2120. )
  2121. {
  2122. PTRACE_ENABLE_CONTEXT pContext = (PTRACE_ENABLE_CONTEXT)&LoggerContext;
  2123. BOOLEAN DeliverNotification = FALSE;
  2124. ULONG Status=ERROR_SUCCESS;
  2125. if (LoggerContext) {
  2126. DeliverNotification = TRUE;
  2127. if (pContext->InternalFlag & EVENT_TRACE_INTERNAL_FLAG_PRIVATE) {
  2128. // Before Delivering this Notification
  2129. // make sure that the Process Private logger
  2130. // is running.
  2131. pTraceRegInfo->EnabledState = TRUE;
  2132. pTraceRegInfo->LoggerContext = LoggerContext;
  2133. DeliverNotification = EtwpIsPrivateLoggerOn();
  2134. }
  2135. }
  2136. if(IsEqualGUID(&NtdllTraceGuid, ControlGuid))
  2137. {
  2138. DeliverNotification = TRUE;
  2139. }
  2140. if (DeliverNotification) {
  2141. try {
  2142. WNODE_HEADER Wnode;
  2143. ULONG InOutSize;
  2144. //
  2145. // Need to use a Local Wnode and a local InOutSize because
  2146. // the Callback function might alter it.
  2147. //
  2148. RtlZeroMemory(&Wnode, sizeof(Wnode));
  2149. Wnode.BufferSize = sizeof(Wnode);
  2150. Wnode.HistoricalContext = LoggerContext;
  2151. Wnode.Guid = *ControlGuid;
  2152. InOutSize = Wnode.BufferSize;
  2153. Status = (RequestAddress)(WMI_ENABLE_EVENTS,
  2154. RequestContext,
  2155. &InOutSize,
  2156. &Wnode);
  2157. } except (EXCEPTION_EXECUTE_HANDLER) {
  2158. #if DBG
  2159. Status = GetExceptionCode();
  2160. EtwpDebugPrint(("WMI: Enable Call caused exception%d\n",
  2161. Status));
  2162. #endif
  2163. Status = ERROR_WMI_DP_FAILED;
  2164. }
  2165. }
  2166. return Status;
  2167. }
  2168. ULONG
  2169. WMIAPI
  2170. EtwRegisterTraceGuidsW(
  2171. IN WMIDPREQUEST RequestAddress,
  2172. IN PVOID RequestContext,
  2173. IN LPCGUID ControlGuid,
  2174. IN ULONG GuidCount,
  2175. IN PTRACE_GUID_REGISTRATION GuidReg,
  2176. IN LPCWSTR MofImagePath,
  2177. IN LPCWSTR MofResourceName,
  2178. IN PTRACEHANDLE RegistrationHandle
  2179. )
  2180. /*++
  2181. Routine Description:
  2182. This routine performs the ETW provider registration. It takes one control
  2183. Guid and optionally several transaction Guids. It registers the ControlGuid
  2184. with the kernel and maintains the transaction Guids in a cache in the
  2185. process (GuidMaps). The GuidMaps are necessary if one uses the
  2186. TraceEventInstance API which requires us to decode the GuidReg pointer
  2187. back to the transaction Guid.
  2188. Arguments:
  2189. RequestAddress Pointer of the Enable callback function
  2190. RequestContext Pointer to the Context to be passed back during callback
  2191. ControlGuid Pointer to control guid being registered.
  2192. GuidCount Count of Transaction Guids (0 to WMIMAXREGGUIDCOUNT)
  2193. GuidReg Pointer to transaction guid reg
  2194. MofImagePath Mof Image Path
  2195. MofResourceName Mof Resource Name
  2196. RegistrationHandle Handle returned from this registration. Caller must
  2197. use it to call UnregisterTraceGuids to free up memory.
  2198. Return Value:
  2199. Return status from the call.
  2200. --*/
  2201. {
  2202. GUID Guid;
  2203. PTRACE_REG_INFO pTraceRegInfo = NULL;
  2204. TRACEHANDLE LoggerContext = 0;
  2205. HANDLE TraceCtxHandle;
  2206. ULONG Status;
  2207. EtwpInitProcessHeap();
  2208. if ((RequestAddress == NULL) ||
  2209. (RegistrationHandle == NULL) ||
  2210. (ControlGuid == NULL) ||
  2211. (GuidCount > WMIMAXREGGUIDCOUNT) )
  2212. {
  2213. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2214. }
  2215. try {
  2216. Guid = *ControlGuid;
  2217. *RegistrationHandle = (TRACEHANDLE) 0;
  2218. //
  2219. // Allocate GuidMaps, Registration Cookie
  2220. //
  2221. pTraceRegInfo = EtwpAllocateGuidMaps(RequestAddress,
  2222. RequestContext,
  2223. &Guid,
  2224. GuidCount,
  2225. GuidReg
  2226. );
  2227. if (pTraceRegInfo == NULL) {
  2228. return EtwpGetLastError();
  2229. }
  2230. Status = EtwpRegisterGuids(&RegisterReservedGuid,
  2231. &Guid,
  2232. MofImagePath,
  2233. MofResourceName,
  2234. &LoggerContext,
  2235. &TraceCtxHandle);
  2236. if (Status != ERROR_SUCCESS) {
  2237. EtwpFree(pTraceRegInfo);
  2238. return Status;
  2239. }
  2240. pTraceRegInfo->TraceCtxHandle = TraceCtxHandle;
  2241. *RegistrationHandle = (TRACEHANDLE)pTraceRegInfo;
  2242. //
  2243. // Make the Callback if we have to
  2244. //
  2245. Status = EtwpMakeCallbacks(&Guid,
  2246. RequestAddress,
  2247. RequestContext,
  2248. LoggerContext,
  2249. pTraceRegInfo);
  2250. if (Status != ERROR_SUCCESS) {
  2251. goto Cleanup;
  2252. }
  2253. //
  2254. // We are Done. Add the handle to the EventPump and return
  2255. //
  2256. Status = EtwpAddHandleToEventPump(&Guid,
  2257. (PVOID)TraceCtxHandle,
  2258. (ULONG_PTR)pTraceRegInfo,
  2259. 0,
  2260. TraceCtxHandle);
  2261. if (Status != ERROR_SUCCESS) {
  2262. goto Cleanup;
  2263. }
  2264. }
  2265. except (EXCEPTION_EXECUTE_HANDLER) {
  2266. Status = EtwpNtStatusToDosError(GetExceptionCode());
  2267. #if DBG
  2268. EtwpDebugPrint(("ETW: Registration call caused exception%d\n",
  2269. Status));
  2270. #endif
  2271. }
  2272. return EtwpSetDosError(Status);
  2273. Cleanup:
  2274. EtwUnregisterTraceGuids(*RegistrationHandle);
  2275. *RegistrationHandle = 0;
  2276. return (EtwpSetDosError(Status));
  2277. }
  2278. ULONG
  2279. WMIAPI
  2280. EtwRegisterTraceGuidsA(
  2281. IN WMIDPREQUEST RequestAddress,
  2282. IN PVOID RequestContext,
  2283. IN LPCGUID ControlGuid,
  2284. IN ULONG GuidCount,
  2285. IN PTRACE_GUID_REGISTRATION GuidReg,
  2286. IN LPCSTR MofImagePath,
  2287. IN LPCSTR MofResourceName,
  2288. IN PTRACEHANDLE RegistrationHandle
  2289. )
  2290. /*++
  2291. Routine Description:
  2292. ANSI thunk to RegisterTraceGuidsW
  2293. --*/
  2294. {
  2295. LPWSTR MofImagePathUnicode = NULL;
  2296. LPWSTR MofResourceNameUnicode = NULL;
  2297. ULONG Status;
  2298. EtwpInitProcessHeap();
  2299. if ((RequestAddress == NULL) ||
  2300. (RegistrationHandle == NULL) ||
  2301. (GuidCount <= 0) ||
  2302. (GuidReg == NULL) ||
  2303. (ControlGuid == NULL) ||
  2304. (GuidCount > WMIMAXREGGUIDCOUNT) )
  2305. {
  2306. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2307. }
  2308. Status = EtwpAnsiToUnicode(MofImagePath, &MofImagePathUnicode);
  2309. if (Status == ERROR_SUCCESS) {
  2310. if (MofResourceName) {
  2311. Status = EtwpAnsiToUnicode(MofResourceName,&MofResourceNameUnicode);
  2312. }
  2313. if (Status == ERROR_SUCCESS) {
  2314. Status = EtwRegisterTraceGuidsW(RequestAddress,
  2315. RequestContext,
  2316. ControlGuid,
  2317. GuidCount,
  2318. GuidReg,
  2319. MofImagePathUnicode,
  2320. MofResourceNameUnicode,
  2321. RegistrationHandle
  2322. );
  2323. if (MofResourceNameUnicode) {
  2324. EtwpFree(MofResourceNameUnicode);
  2325. }
  2326. }
  2327. if (MofImagePathUnicode) {
  2328. EtwpFree(MofImagePathUnicode);
  2329. }
  2330. }
  2331. return(Status);
  2332. }
  2333. ULONG
  2334. WMIAPI
  2335. EtwUnregisterTraceGuids(
  2336. IN TRACEHANDLE RegistrationHandle
  2337. )
  2338. {
  2339. // First check if the handle belongs to a Trace Control Guid.
  2340. // Then UnRegister all the regular trace guids controlled by
  2341. // this control guid and free up the storage allocated to maintain
  2342. // the TRACEGUIDMAPENTRY structures.
  2343. // Get to the real Registration Handle, stashed away in
  2344. // in the internal structures and pass it onto the call.
  2345. PGUIDMAPENTRY pControlGMEntry;
  2346. WMIHANDLE WmiRegistrationHandle;
  2347. ULONG Status;
  2348. PVOID RequestContext;
  2349. PTRACE_REG_INFO pTraceRegInfo = NULL;
  2350. ULONG64 LoggerContext = 0;
  2351. WMIDPREQUEST RequestAddress;
  2352. EtwpInitProcessHeap();
  2353. if (RegistrationHandle == 0) {
  2354. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2355. }
  2356. try {
  2357. pTraceRegInfo = (PTRACE_REG_INFO) RegistrationHandle;
  2358. pControlGMEntry = (PGUIDMAPENTRY)((PUCHAR)pTraceRegInfo +
  2359. sizeof(TRACE_REG_INFO) );
  2360. WmiRegistrationHandle = (WMIHANDLE)pTraceRegInfo->TraceCtxHandle;
  2361. if (WmiRegistrationHandle == NULL) {
  2362. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2363. }
  2364. Status = WmiUnregisterGuids(WmiRegistrationHandle,
  2365. &pControlGMEntry->Guid,
  2366. &LoggerContext);
  2367. if ((Status == ERROR_SUCCESS) && LoggerContext) {
  2368. WNODE_HEADER Wnode;
  2369. ULONG InOutSize = sizeof(Wnode);
  2370. RtlZeroMemory(&Wnode, InOutSize);
  2371. Wnode.BufferSize = sizeof(Wnode);
  2372. Wnode.HistoricalContext = LoggerContext;
  2373. Wnode.Guid = pControlGMEntry->Guid;
  2374. RequestAddress = pTraceRegInfo->NotifyRoutine;
  2375. RequestContext = pTraceRegInfo->NotifyContext;
  2376. Status = (RequestAddress)(WMI_DISABLE_EVENTS,
  2377. RequestContext,
  2378. &InOutSize,
  2379. &Wnode);
  2380. }
  2381. //
  2382. // At this point, it should be safe to delete the TraceRegInfo.
  2383. //
  2384. EtwpFree(pTraceRegInfo);
  2385. }
  2386. except (EXCEPTION_EXECUTE_HANDLER) {
  2387. Status = EtwpNtStatusToDosError(GetExceptionCode());
  2388. #if DBG
  2389. EtwpDebugPrint(("ETW: UnregisterTraceGuids exception%d\n", Status));
  2390. #endif
  2391. }
  2392. return EtwpSetDosError(Status);
  2393. }
  2394. ULONG
  2395. EtwpQueryAllUmTraceW(
  2396. OUT PEVENT_TRACE_PROPERTIES * PropertyArray,
  2397. IN BOOLEAN fEnabledOnly,
  2398. IN ULONG PropertyArrayCount,
  2399. OUT PULONG LoggerCount)
  2400. {
  2401. PWMI_LOGGER_INFORMATION pLoggerInfo;
  2402. PWMI_LOGGER_INFORMATION pLoggerInfoCurrent;
  2403. ULONG LoggerInfoSize;
  2404. ULONG SizeUsed;
  2405. ULONG SizeNeeded = 0;
  2406. ULONG Length;
  2407. ULONG lenLoggerName;
  2408. ULONG lenLogFileName;
  2409. ULONG Offset = 0;
  2410. ULONG i = * LoggerCount;
  2411. ULONG status;
  2412. PWCHAR strSrcW;
  2413. PWCHAR strDestW;
  2414. if (PropertyArrayCount <= i) {
  2415. return ERROR_NOT_ENOUGH_MEMORY;
  2416. }
  2417. LoggerInfoSize = (PropertyArrayCount - i)
  2418. * ( sizeof(WMI_LOGGER_INFORMATION)
  2419. + 2 * MAXSTR * sizeof(WCHAR));
  2420. LoggerInfoSize = ALIGN_TO_POWER2(LoggerInfoSize, 8);
  2421. pLoggerInfo = (PWMI_LOGGER_INFORMATION) EtwpAlloc(LoggerInfoSize);
  2422. if (pLoggerInfo == NULL) {
  2423. status = ERROR_NOT_ENOUGH_MEMORY;
  2424. goto Cleanup;
  2425. }
  2426. RtlZeroMemory(pLoggerInfo, LoggerInfoSize);
  2427. Length = sizeof(WMI_LOGGER_INFORMATION);
  2428. EtwpInitString(& pLoggerInfo->LoggerName,
  2429. (PWCHAR) ((PUCHAR) pLoggerInfo + Length),
  2430. MAXSTR * sizeof(WCHAR));
  2431. Length += MAXSTR * sizeof(WCHAR);
  2432. EtwpInitString(& pLoggerInfo->LogFileName,
  2433. (PWCHAR) ((PUCHAR) pLoggerInfo + Length),
  2434. MAXSTR * sizeof(WCHAR));
  2435. SizeUsed = pLoggerInfo->Wnode.BufferSize = LoggerInfoSize;
  2436. status = EtwpSendUmLogRequest( (fEnabledOnly) ? (TRACELOG_QUERYENABLED)
  2437. : (TRACELOG_QUERYALL),
  2438. pLoggerInfo
  2439. );
  2440. if (status != ERROR_SUCCESS)
  2441. goto Cleanup;
  2442. while (i < PropertyArrayCount && Offset < SizeUsed) {
  2443. PTRACE_ENABLE_CONTEXT pContext;
  2444. pLoggerInfoCurrent = (PWMI_LOGGER_INFORMATION)
  2445. (((PUCHAR) pLoggerInfo) + Offset);
  2446. pContext = (PTRACE_ENABLE_CONTEXT)
  2447. & pLoggerInfoCurrent->Wnode.HistoricalContext;
  2448. pContext->InternalFlag |= EVENT_TRACE_INTERNAL_FLAG_PRIVATE;
  2449. lenLoggerName = pLoggerInfoCurrent->LoggerName.Length / sizeof(WCHAR);
  2450. if (lenLoggerName >= MAXSTR)
  2451. lenLoggerName = MAXSTR - 1;
  2452. lenLogFileName = pLoggerInfoCurrent->LogFileName.Length / sizeof(WCHAR);
  2453. if (lenLogFileName >= MAXSTR)
  2454. lenLogFileName = MAXSTR - 1;
  2455. Length = sizeof(EVENT_TRACE_PROPERTIES)
  2456. + sizeof(WCHAR) * (lenLoggerName + 1)
  2457. + sizeof(WCHAR) * (lenLogFileName + 1);
  2458. if (PropertyArray[i]->Wnode.BufferSize >= Length) {
  2459. EtwpCopyInfoToProperties(pLoggerInfoCurrent, PropertyArray[i]);
  2460. strSrcW = (PWCHAR) ( ((PUCHAR) pLoggerInfoCurrent)
  2461. + sizeof(WMI_LOGGER_INFORMATION));
  2462. if (lenLoggerName > 0) {
  2463. if (PropertyArray[i]->LoggerNameOffset == 0) {
  2464. PropertyArray[i]->LoggerNameOffset =
  2465. sizeof(EVENT_TRACE_PROPERTIES);
  2466. }
  2467. strDestW = (PWCHAR) ( ((PUCHAR) PropertyArray[i])
  2468. + PropertyArray[i]->LoggerNameOffset);
  2469. wcsncpy(strDestW, strSrcW, lenLoggerName);
  2470. strDestW[lenLoggerName] = 0;
  2471. }
  2472. strSrcW = (PWCHAR) (((PUCHAR) pLoggerInfoCurrent)
  2473. + sizeof(WMI_LOGGER_INFORMATION)
  2474. + pLoggerInfoCurrent->LoggerName.MaximumLength);
  2475. if (lenLogFileName > 0) {
  2476. if (PropertyArray[i]->LogFileNameOffset == 0) {
  2477. PropertyArray[i]->LogFileNameOffset =
  2478. PropertyArray[i]->LoggerNameOffset
  2479. + sizeof(WCHAR) * (lenLoggerName + 1);
  2480. }
  2481. strDestW = (PWCHAR) ( ((PUCHAR) PropertyArray[i])
  2482. + PropertyArray[i]->LogFileNameOffset);
  2483. wcsncpy(strDestW, strSrcW, lenLogFileName);
  2484. strDestW[lenLogFileName] = 0;
  2485. }
  2486. }
  2487. Offset = Offset
  2488. + sizeof(WMI_LOGGER_INFORMATION)
  2489. + pLoggerInfoCurrent->LogFileName.MaximumLength
  2490. + pLoggerInfoCurrent->LoggerName.MaximumLength;
  2491. i ++;
  2492. }
  2493. * LoggerCount = i;
  2494. status = (* LoggerCount > PropertyArrayCount)
  2495. ? ERROR_MORE_DATA : ERROR_SUCCESS;
  2496. Cleanup:
  2497. if (pLoggerInfo)
  2498. EtwpFree(pLoggerInfo);
  2499. return EtwpSetDosError(status);
  2500. }
  2501. ULONG
  2502. EtwpQueryAllTraces(
  2503. OUT PEVENT_TRACE_PROPERTIES *PropertyArray,
  2504. IN ULONG PropertyArrayCount,
  2505. OUT PULONG LoggerCount,
  2506. IN ULONG IsUnicode
  2507. )
  2508. {
  2509. ULONG i, status;
  2510. ULONG returnCount = 0;
  2511. EVENT_TRACE_PROPERTIES LoggerInfo;
  2512. PEVENT_TRACE_PROPERTIES pLoggerInfo;
  2513. EtwpInitProcessHeap();
  2514. if ((LoggerCount == NULL)
  2515. || (PropertyArrayCount > MAXLOGGERS)
  2516. || (PropertyArray == NULL)
  2517. || (PropertyArrayCount == 0))
  2518. return ERROR_INVALID_PARAMETER;
  2519. if (*PropertyArray == NULL)
  2520. return ERROR_INVALID_PARAMETER;
  2521. try {
  2522. *LoggerCount = 0;
  2523. for (i=0; i<MAXLOGGERS; i++) {
  2524. if (returnCount < PropertyArrayCount) {
  2525. pLoggerInfo = PropertyArray[returnCount];
  2526. }
  2527. else {
  2528. pLoggerInfo = &LoggerInfo;
  2529. RtlZeroMemory(pLoggerInfo, sizeof(EVENT_TRACE_PROPERTIES));
  2530. pLoggerInfo->Wnode.BufferSize = sizeof(EVENT_TRACE_PROPERTIES);
  2531. }
  2532. WmiSetLoggerId(i, &pLoggerInfo->Wnode.HistoricalContext);
  2533. if (IsUnicode) {
  2534. status = EtwControlTraceW(
  2535. (TRACEHANDLE)pLoggerInfo->Wnode.HistoricalContext,
  2536. NULL,
  2537. pLoggerInfo,
  2538. EVENT_TRACE_CONTROL_QUERY);
  2539. }
  2540. else {
  2541. status = EtwControlTraceA(
  2542. (TRACEHANDLE)pLoggerInfo->Wnode.HistoricalContext,
  2543. NULL,
  2544. pLoggerInfo,
  2545. EVENT_TRACE_CONTROL_QUERY);
  2546. }
  2547. if (status == ERROR_SUCCESS)
  2548. returnCount++;
  2549. }
  2550. *LoggerCount = returnCount;
  2551. status = EtwpQueryAllUmTraceW(PropertyArray,
  2552. FALSE,
  2553. PropertyArrayCount,
  2554. LoggerCount);
  2555. }
  2556. except (EXCEPTION_EXECUTE_HANDLER) {
  2557. return EtwpSetDosError(ERROR_NOACCESS);
  2558. }
  2559. if (returnCount > PropertyArrayCount)
  2560. return ERROR_MORE_DATA;
  2561. else
  2562. return ERROR_SUCCESS;
  2563. }
  2564. ULONG
  2565. WMIAPI
  2566. EtwQueryAllTracesW(
  2567. OUT PEVENT_TRACE_PROPERTIES *PropertyArray,
  2568. IN ULONG PropertyArrayCount,
  2569. OUT PULONG LoggerCount
  2570. )
  2571. {
  2572. return EtwpQueryAllTraces(PropertyArray,
  2573. PropertyArrayCount,
  2574. LoggerCount, TRUE);
  2575. }
  2576. ULONG
  2577. EtwpQueryAllUmTraceA(
  2578. OUT PEVENT_TRACE_PROPERTIES * PropertyArray,
  2579. IN BOOLEAN fEnabledOnly,
  2580. IN ULONG PropertyArrayCount,
  2581. OUT PULONG LoggerCount)
  2582. {
  2583. PWMI_LOGGER_INFORMATION pLoggerInfo;
  2584. PWMI_LOGGER_INFORMATION pLoggerInfoCurrent;
  2585. ULONG LoggerInfoSize;
  2586. ULONG SizeUsed;
  2587. ULONG SizeNeeded = 0;
  2588. ULONG Length;
  2589. ULONG lenLoggerName;
  2590. ULONG lenLogFileName;
  2591. ULONG Offset = 0;
  2592. ULONG i = * LoggerCount;
  2593. ULONG status;
  2594. ANSI_STRING strBufferA;
  2595. PUCHAR strDestA;
  2596. if (PropertyArrayCount <= i) {
  2597. return ERROR_NOT_ENOUGH_MEMORY;
  2598. }
  2599. LoggerInfoSize = (PropertyArrayCount - i)
  2600. * ( sizeof(WMI_LOGGER_INFORMATION)
  2601. + 2 * MAXSTR * sizeof(WCHAR));
  2602. LoggerInfoSize = ALIGN_TO_POWER2(LoggerInfoSize, 8);
  2603. pLoggerInfo = (PWMI_LOGGER_INFORMATION) EtwpAlloc(LoggerInfoSize);
  2604. if (pLoggerInfo == NULL) {
  2605. status = ERROR_NOT_ENOUGH_MEMORY;
  2606. goto Cleanup;
  2607. }
  2608. RtlZeroMemory(pLoggerInfo, LoggerInfoSize);
  2609. Length = sizeof(WMI_LOGGER_INFORMATION);
  2610. EtwpInitString(& pLoggerInfo->LoggerName,
  2611. (PWCHAR) ((PUCHAR) pLoggerInfo + Length),
  2612. MAXSTR * sizeof(WCHAR));
  2613. Length += MAXSTR * sizeof(WCHAR);
  2614. EtwpInitString(& pLoggerInfo->LogFileName,
  2615. (PWCHAR) ((PUCHAR) pLoggerInfo + Length),
  2616. MAXSTR * sizeof(WCHAR));
  2617. SizeUsed = pLoggerInfo->Wnode.BufferSize = LoggerInfoSize;
  2618. status = EtwpSendUmLogRequest(
  2619. (fEnabledOnly) ? (TRACELOG_QUERYENABLED)
  2620. : (TRACELOG_QUERYALL),
  2621. pLoggerInfo
  2622. );
  2623. if (status != ERROR_SUCCESS)
  2624. goto Cleanup;
  2625. while (i < PropertyArrayCount && Offset < SizeUsed) {
  2626. PTRACE_ENABLE_CONTEXT pContext;
  2627. pLoggerInfoCurrent = (PWMI_LOGGER_INFORMATION)
  2628. (((PUCHAR) pLoggerInfo) + Offset);
  2629. pContext = (PTRACE_ENABLE_CONTEXT)
  2630. & pLoggerInfoCurrent->Wnode.HistoricalContext;
  2631. pContext->InternalFlag |= EVENT_TRACE_INTERNAL_FLAG_PRIVATE;
  2632. lenLoggerName = pLoggerInfoCurrent->LoggerName.Length / sizeof(WCHAR);
  2633. if (lenLoggerName >= MAXSTR)
  2634. lenLoggerName = MAXSTR - 1;
  2635. lenLogFileName = pLoggerInfoCurrent->LogFileName.Length / sizeof(WCHAR);
  2636. if (lenLogFileName >= MAXSTR)
  2637. lenLogFileName = MAXSTR - 1;
  2638. Length = sizeof(EVENT_TRACE_PROPERTIES)
  2639. + sizeof(CHAR) * (lenLoggerName + 1)
  2640. + sizeof(CHAR) * (lenLogFileName + 1);
  2641. if (PropertyArray[i]->Wnode.BufferSize >= Length) {
  2642. EtwpCopyInfoToProperties(pLoggerInfoCurrent, PropertyArray[i]);
  2643. if (lenLoggerName > 0) {
  2644. pLoggerInfoCurrent->LoggerName.Buffer = (PWCHAR)
  2645. ( ((PUCHAR) pLoggerInfoCurrent)
  2646. + sizeof(WMI_LOGGER_INFORMATION));
  2647. status = RtlUnicodeStringToAnsiString(& strBufferA,
  2648. & pLoggerInfoCurrent->LoggerName, TRUE);
  2649. if (NT_SUCCESS(status)) {
  2650. if (PropertyArray[i]->LoggerNameOffset == 0) {
  2651. PropertyArray[i]->LoggerNameOffset =
  2652. sizeof(EVENT_TRACE_PROPERTIES);
  2653. }
  2654. strDestA = (PCHAR) ( ((PUCHAR) PropertyArray[i])
  2655. + PropertyArray[i]->LoggerNameOffset);
  2656. StringCchCopyA(strDestA, lenLoggerName+1, strBufferA.Buffer);
  2657. RtlFreeAnsiString(& strBufferA);
  2658. }
  2659. strDestA[lenLoggerName] = 0;
  2660. }
  2661. if (lenLogFileName > 0) {
  2662. pLoggerInfoCurrent->LogFileName.Buffer = (PWCHAR)
  2663. ( ((PUCHAR) pLoggerInfoCurrent)
  2664. + sizeof(WMI_LOGGER_INFORMATION)
  2665. + pLoggerInfoCurrent->LoggerName.MaximumLength);
  2666. status = RtlUnicodeStringToAnsiString(& strBufferA,
  2667. & pLoggerInfoCurrent->LogFileName, TRUE);
  2668. if (NT_SUCCESS(status)) {
  2669. if (PropertyArray[i]->LogFileNameOffset == 0) {
  2670. PropertyArray[i]->LogFileNameOffset =
  2671. sizeof(EVENT_TRACE_PROPERTIES)
  2672. + sizeof(CHAR) * (lenLoggerName + 1);
  2673. }
  2674. strDestA = (PCHAR) ( ((PUCHAR) PropertyArray[i])
  2675. + PropertyArray[i]->LogFileNameOffset);
  2676. StringCchCopyA(strDestA, lenLogFileName+1, strBufferA.Buffer);
  2677. RtlFreeAnsiString(& strBufferA);
  2678. }
  2679. strDestA[lenLogFileName] = 0;
  2680. }
  2681. }
  2682. Offset = Offset
  2683. + sizeof(WMI_LOGGER_INFORMATION)
  2684. + pLoggerInfoCurrent->LogFileName.MaximumLength
  2685. + pLoggerInfoCurrent->LoggerName.MaximumLength;
  2686. i ++;
  2687. }
  2688. * LoggerCount = i;
  2689. status = (* LoggerCount > PropertyArrayCount)
  2690. ? ERROR_MORE_DATA : ERROR_SUCCESS;
  2691. Cleanup:
  2692. if (pLoggerInfo)
  2693. EtwpFree(pLoggerInfo);
  2694. return EtwpSetDosError(status);
  2695. }
  2696. ULONG
  2697. WMIAPI
  2698. EtwQueryAllTracesA(
  2699. OUT PEVENT_TRACE_PROPERTIES *PropertyArray,
  2700. IN ULONG PropertyArrayCount,
  2701. OUT PULONG LoggerCount
  2702. )
  2703. {
  2704. return EtwpQueryAllTraces(PropertyArray,
  2705. PropertyArrayCount,
  2706. LoggerCount, FALSE);
  2707. }
  2708. TRACEHANDLE
  2709. WMIAPI
  2710. EtwGetTraceLoggerHandle(
  2711. IN PVOID Buffer
  2712. )
  2713. {
  2714. TRACEHANDLE LoggerHandle = (TRACEHANDLE) INVALID_HANDLE_VALUE;
  2715. USHORT LoggerId;
  2716. EtwpInitProcessHeap();
  2717. if (Buffer == NULL) {
  2718. EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2719. return LoggerHandle;
  2720. }
  2721. try {
  2722. if (((PWNODE_HEADER)Buffer)->BufferSize < sizeof(WNODE_HEADER)) {
  2723. EtwpSetDosError(ERROR_BAD_LENGTH);
  2724. return LoggerHandle;
  2725. }
  2726. LoggerHandle = (TRACEHANDLE)((PWNODE_HEADER)Buffer)->HistoricalContext;
  2727. }
  2728. except (EXCEPTION_EXECUTE_HANDLER) {
  2729. EtwpSetDosError(ERROR_NOACCESS);
  2730. return (TRACEHANDLE) INVALID_HANDLE_VALUE;
  2731. }
  2732. LoggerId = WmiGetLoggerId(LoggerHandle);
  2733. if ((LoggerId >= MAXLOGGERS) && (LoggerId != KERNEL_LOGGER_ID))
  2734. {
  2735. EtwpSetDosError(ERROR_INVALID_HANDLE);
  2736. LoggerHandle = (TRACEHANDLE) INVALID_HANDLE_VALUE;
  2737. }
  2738. return LoggerHandle;
  2739. }
  2740. UCHAR
  2741. WMIAPI
  2742. EtwGetTraceEnableLevel(
  2743. IN TRACEHANDLE LoggerHandle
  2744. )
  2745. {
  2746. UCHAR Level;
  2747. USHORT LoggerId;
  2748. EtwpInitProcessHeap();
  2749. LoggerId = WmiGetLoggerId(LoggerHandle);
  2750. if (((LoggerId >= MAXLOGGERS) && (LoggerId != KERNEL_LOGGER_ID))
  2751. || (LoggerHandle == (TRACEHANDLE) NULL))
  2752. {
  2753. EtwpSetDosError(ERROR_INVALID_HANDLE);
  2754. return 0;
  2755. }
  2756. Level = WmiGetLoggerEnableLevel(LoggerHandle);
  2757. return Level;
  2758. }
  2759. ULONG
  2760. WMIAPI
  2761. EtwGetTraceEnableFlags(
  2762. IN TRACEHANDLE LoggerHandle
  2763. )
  2764. {
  2765. ULONG Flags;
  2766. USHORT LoggerId;
  2767. EtwpInitProcessHeap();
  2768. LoggerId = WmiGetLoggerId(LoggerHandle);
  2769. if (((LoggerId >= MAXLOGGERS) && (LoggerId != KERNEL_LOGGER_ID))
  2770. || (LoggerHandle == (TRACEHANDLE) NULL))
  2771. {
  2772. EtwpSetDosError(ERROR_INVALID_HANDLE);
  2773. return 0;
  2774. }
  2775. Flags = WmiGetLoggerEnableFlags(LoggerHandle);
  2776. return Flags;
  2777. }
  2778. ULONG
  2779. WMIAPI
  2780. EtwCreateTraceInstanceId(
  2781. IN PVOID RegHandle,
  2782. IN OUT PEVENT_INSTANCE_INFO pInst
  2783. )
  2784. /*++
  2785. Routine Description:
  2786. This call takes the Registration Handle for a traced GUID and fills in the
  2787. instanceId in the EVENT_INSTANCE_INFO structure provided by the caller.
  2788. Arguments:
  2789. RegHandle Registration Handle for the Guid.
  2790. pInst Pointer to the Instance information
  2791. Return Value:
  2792. The status of performing the action requested.
  2793. --*/
  2794. {
  2795. PGUIDMAPENTRY GuidMapEntry;
  2796. EtwpInitProcessHeap();
  2797. if ((RegHandle == NULL) || (pInst == NULL)) {
  2798. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2799. }
  2800. try {
  2801. pInst->RegHandle = RegHandle;
  2802. GuidMapEntry = (PGUIDMAPENTRY) RegHandle;
  2803. //
  2804. // Use the PID as a signature
  2805. //
  2806. if (GuidMapEntry->Reserved != EtwpGetCurrentProcessId() ) {
  2807. #if DBG
  2808. EtwpDebugPrint(("ETW: Bad RegHandle %x in CreateTraceInstanceId!\n", RegHandle));
  2809. #endif
  2810. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2811. }
  2812. if (GuidMapEntry->InstanceId >= MAXINST) {
  2813. InterlockedCompareExchange(&GuidMapEntry->InstanceId, MAXINST, 0);
  2814. }
  2815. pInst->InstanceId = InterlockedIncrement(&GuidMapEntry->InstanceId);
  2816. }
  2817. except (EXCEPTION_EXECUTE_HANDLER) {
  2818. return EtwpSetDosError(EtwpNtStatusToDosError(GetExceptionCode()));
  2819. }
  2820. return ERROR_SUCCESS;
  2821. }
  2822. ULONG
  2823. WMIAPI
  2824. EtwEnumerateTraceGuids(
  2825. IN OUT PTRACE_GUID_PROPERTIES *GuidPropertiesArray,
  2826. IN ULONG PropertyArrayCount,
  2827. OUT PULONG GuidCount
  2828. )
  2829. /*++
  2830. Routine Description:
  2831. This call returns all the registered trace control guids
  2832. with their current status.
  2833. Arguments:
  2834. GuidPropertiesArray Points to buffers to write trace control guid properties
  2835. PropertyArrayCount Size of the array provided
  2836. GuidCount Number of GUIDs written in the Array. If the
  2837. Array was smaller than the required size, GuidCount
  2838. returns the size needed.
  2839. Return Value:
  2840. The status of performing the action requested.
  2841. --*/
  2842. {
  2843. ULONG Status;
  2844. PWMIGUIDLISTINFO pGuidListInfo;
  2845. ULONG i, j;
  2846. EtwpInitProcessHeap();
  2847. try {
  2848. if ( (GuidPropertiesArray == NULL) || (*GuidPropertiesArray == NULL) ){
  2849. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2850. }
  2851. for (i=0; i < PropertyArrayCount; i++) {
  2852. if (GuidPropertiesArray[i] == NULL) {
  2853. return EtwpSetDosError(ERROR_INVALID_PARAMETER);
  2854. }
  2855. }
  2856. }
  2857. except (EXCEPTION_EXECUTE_HANDLER) {
  2858. Status = EtwpNtStatusToDosError( GetExceptionCode() );
  2859. return EtwpSetDosError(Status);
  2860. }
  2861. Status = EtwpEnumRegGuids(&pGuidListInfo);
  2862. if (Status == ERROR_SUCCESS) {
  2863. try {
  2864. PWMIGUIDPROPERTIES pGuidProperties = pGuidListInfo->GuidList;
  2865. j = 0;
  2866. for (i=0; i < pGuidListInfo->ReturnedGuidCount; i++) {
  2867. if (pGuidProperties->GuidType == 0) { // Trace Control Guid
  2868. if (j >= PropertyArrayCount) {
  2869. Status = ERROR_MORE_DATA;
  2870. }
  2871. else {
  2872. RtlCopyMemory(GuidPropertiesArray[j],
  2873. pGuidProperties,
  2874. sizeof(WMIGUIDPROPERTIES)
  2875. );
  2876. }
  2877. j++;
  2878. }
  2879. pGuidProperties++;
  2880. }
  2881. *GuidCount = j;
  2882. }
  2883. except (EXCEPTION_EXECUTE_HANDLER) {
  2884. Status = EtwpNtStatusToDosError( GetExceptionCode() );
  2885. }
  2886. EtwpFree(pGuidListInfo);
  2887. }
  2888. return EtwpSetDosError(Status);
  2889. }
  2890. // Stub APIs
  2891. ULONG
  2892. WMIAPI
  2893. EtwQueryTraceA(
  2894. IN TRACEHANDLE TraceHandle,
  2895. IN LPCSTR InstanceName,
  2896. IN OUT PEVENT_TRACE_PROPERTIES Properties
  2897. )
  2898. {
  2899. return EtwControlTraceA(
  2900. TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_QUERY);
  2901. }
  2902. ULONG
  2903. WMIAPI
  2904. EtwQueryTraceW(
  2905. IN TRACEHANDLE TraceHandle,
  2906. IN LPCWSTR InstanceName,
  2907. IN OUT PEVENT_TRACE_PROPERTIES Properties
  2908. )
  2909. {
  2910. return EtwControlTraceW(
  2911. TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_QUERY);
  2912. }
  2913. ULONG
  2914. WMIAPI
  2915. EtwStopTraceA(
  2916. IN TRACEHANDLE TraceHandle,
  2917. IN LPCSTR InstanceName,
  2918. IN OUT PEVENT_TRACE_PROPERTIES Properties
  2919. )
  2920. {
  2921. return EtwControlTraceA(
  2922. TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_STOP);
  2923. }
  2924. ULONG
  2925. WMIAPI
  2926. EtwStopTraceW(
  2927. IN TRACEHANDLE TraceHandle,
  2928. IN LPCWSTR InstanceName,
  2929. IN OUT PEVENT_TRACE_PROPERTIES Properties
  2930. )
  2931. {
  2932. return EtwControlTraceW(
  2933. TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_STOP);
  2934. }
  2935. ULONG
  2936. WMIAPI
  2937. EtwUpdateTraceA(
  2938. IN TRACEHANDLE TraceHandle,
  2939. IN LPCSTR InstanceName,
  2940. IN OUT PEVENT_TRACE_PROPERTIES Properties
  2941. )
  2942. {
  2943. return
  2944. EtwControlTraceA(
  2945. TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_UPDATE);
  2946. }
  2947. ULONG
  2948. WMIAPI
  2949. EtwUpdateTraceW(
  2950. IN TRACEHANDLE TraceHandle,
  2951. IN LPCWSTR InstanceName,
  2952. IN OUT PEVENT_TRACE_PROPERTIES Properties
  2953. )
  2954. {
  2955. return
  2956. EtwControlTraceW(
  2957. TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_UPDATE);
  2958. }
  2959. ULONG
  2960. WMIAPI
  2961. EtwFlushTraceA(
  2962. IN TRACEHANDLE TraceHandle,
  2963. IN LPCSTR InstanceName,
  2964. IN OUT PEVENT_TRACE_PROPERTIES Properties
  2965. )
  2966. {
  2967. return EtwControlTraceA(
  2968. TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_FLUSH);
  2969. }
  2970. ULONG
  2971. WMIAPI
  2972. EtwFlushTraceW(
  2973. IN TRACEHANDLE TraceHandle,
  2974. IN LPCWSTR InstanceName,
  2975. IN OUT PEVENT_TRACE_PROPERTIES Properties
  2976. )
  2977. {
  2978. return EtwControlTraceW(
  2979. TraceHandle, InstanceName, Properties, EVENT_TRACE_CONTROL_FLUSH);
  2980. }
  2981. ULONG
  2982. EtwpTraceMessage(
  2983. IN TRACEHANDLE LoggerHandle,
  2984. IN ULONG MessageFlags,
  2985. IN LPGUID MessageGuid,
  2986. IN USHORT MessageNumber,
  2987. IN va_list ArgList
  2988. )
  2989. {
  2990. NTSTATUS NtStatus;
  2991. IO_STATUS_BLOCK IoStatus;
  2992. PULONG TraceMarker;
  2993. ULONG Size;
  2994. ULONG Flags;
  2995. ULONG dataBytes, argCount ;
  2996. USHORT LoggerId;
  2997. PTRACE_ENABLE_CONTEXT pContext = (PTRACE_ENABLE_CONTEXT)&LoggerHandle;
  2998. va_list ap ;
  2999. PMESSAGE_TRACE_USER pMessage = NULL ;
  3000. try {
  3001. //
  3002. // Determine the number bytes to follow header
  3003. //
  3004. dataBytes = 0 ; // For Count of Bytes
  3005. argCount = 0 ; // For Count of Arguments
  3006. { // Allocation Block
  3007. PCHAR source;
  3008. ap = ArgList ;
  3009. while ((source = va_arg (ap, PVOID)) != NULL) {
  3010. size_t elemBytes;
  3011. elemBytes = va_arg (ap, size_t);
  3012. if ( elemBytes > (TRACE_MESSAGE_MAXIMUM_SIZE - sizeof(MESSAGE_TRACE_USER))) {
  3013. EtwpSetLastError(ERROR_BUFFER_OVERFLOW);
  3014. return(ERROR_BUFFER_OVERFLOW);
  3015. }
  3016. dataBytes += elemBytes;
  3017. argCount++ ;
  3018. }
  3019. } // end of allocation block
  3020. if (dataBytes > (TRACE_MESSAGE_MAXIMUM_SIZE - sizeof(MESSAGE_TRACE_USER))) {
  3021. EtwpSetLastError(ERROR_BUFFER_OVERFLOW);
  3022. return(ERROR_BUFFER_OVERFLOW);
  3023. }
  3024. if (pContext->InternalFlag & EVENT_TRACE_INTERNAL_FLAG_PRIVATE){
  3025. NtStatus = EtwpTraceUmMessage(dataBytes,
  3026. (ULONG64)LoggerHandle,
  3027. MessageFlags,
  3028. MessageGuid,
  3029. MessageNumber,
  3030. ArgList);
  3031. return EtwpNtStatusToDosError( NtStatus );
  3032. }
  3033. //
  3034. // Now the LoggerHandle is expected to be filled in by the caller.
  3035. // But check to see if it has a valid value.
  3036. //
  3037. LoggerId = WmiGetLoggerId(LoggerHandle);
  3038. if ((LoggerId == 0) || (LoggerId == KERNEL_LOGGER_ID)) {
  3039. return ERROR_INVALID_HANDLE;
  3040. }
  3041. Size = dataBytes + sizeof(MESSAGE_TRACE_USER) ;
  3042. pMessage = (PMESSAGE_TRACE_USER)EtwpAlloc(Size);
  3043. if (pMessage == NULL)
  3044. {
  3045. EtwpSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3046. return(ERROR_NOT_ENOUGH_MEMORY);
  3047. }
  3048. pMessage->MessageHeader.Marker = TRACE_MESSAGE | TRACE_HEADER_FLAG ;
  3049. //
  3050. // Fill in Header.
  3051. //
  3052. pMessage->MessageFlags = MessageFlags ;
  3053. pMessage->MessageHeader.Packet.MessageNumber = MessageNumber ;
  3054. pMessage->LoggerHandle = (ULONG64)LoggerHandle ;
  3055. // GUID ? or CompnentID ?
  3056. if (MessageFlags&TRACE_MESSAGE_COMPONENTID) {
  3057. RtlCopyMemory(&pMessage->MessageGuid,MessageGuid,sizeof(ULONG)) ;
  3058. } else if (MessageFlags&TRACE_MESSAGE_GUID) { // Can't have both
  3059. RtlCopyMemory(&pMessage->MessageGuid,MessageGuid,sizeof(GUID));
  3060. }
  3061. pMessage->DataSize = dataBytes ;
  3062. //
  3063. // Now Copy in the Data.
  3064. //
  3065. { // Allocation Block
  3066. va_list tap;
  3067. PCHAR dest = (PCHAR)&pMessage->Data ;
  3068. PCHAR source;
  3069. tap = ArgList ;
  3070. while ((source = va_arg (tap, PVOID)) != NULL) {
  3071. size_t elemBytes;
  3072. elemBytes = va_arg (tap, size_t);
  3073. RtlCopyMemory (dest, source, elemBytes);
  3074. dest += elemBytes;
  3075. }
  3076. } // Allocation Block
  3077. }
  3078. except (EXCEPTION_EXECUTE_HANDLER) {
  3079. if (pMessage != NULL) {
  3080. EtwpFree(pMessage);
  3081. }
  3082. return EtwpNtStatusToDosError( GetExceptionCode() );
  3083. }
  3084. NtStatus = NtTraceEvent((HANDLE)LoggerHandle,
  3085. ETW_NT_FLAGS_TRACE_MESSAGE,
  3086. Size,
  3087. pMessage);
  3088. if (pMessage != NULL) {
  3089. EtwpFree(pMessage);
  3090. }
  3091. return EtwpNtStatusToDosError( NtStatus );
  3092. }
  3093. ULONG
  3094. WMIAPI
  3095. EtwTraceMessage(
  3096. IN TRACEHANDLE LoggerHandle,
  3097. IN ULONG MessageFlags,
  3098. IN LPGUID MessageGuid,
  3099. IN USHORT MessageNumber,
  3100. ...
  3101. )
  3102. /*++
  3103. Routine Description:
  3104. This routine is used by WMI data providers to trace events. It expects the user
  3105. to pass in the handle to the logger. Also, the user cannot ask to log something
  3106. that is larger than the buffer size (minus buffer header).
  3107. Arguments:
  3108. IN TRACEHANDLE LoggerHandle - LoggerHandle obtained earlier
  3109. IN USHORT MessageFlags - Flags which both control what standard
  3110. values are logged and also included in the
  3111. message header to control decoding.
  3112. IN PGUID MessageGuid, - Pointer to the message GUID of this set of
  3113. messages or if TRACE_COMPONENTID is set the
  3114. actual compnent ID.
  3115. IN USHORT MessageNumber - The type of message being logged, associates
  3116. it with the appropriate format string
  3117. ... - List of arguments to be processed with the
  3118. format string these are stored as pairs of
  3119. PVOID - ptr to argument
  3120. ULONG - size of argument
  3121. and terminated by a pointer to NULL, length
  3122. of zero pair.
  3123. Return Value:
  3124. Status
  3125. --*/
  3126. {
  3127. ULONG Status ;
  3128. va_list ArgList ;
  3129. EtwpInitProcessHeap();
  3130. try {
  3131. va_start(ArgList,MessageNumber);
  3132. Status = EtwpTraceMessage(LoggerHandle,
  3133. MessageFlags,
  3134. MessageGuid,
  3135. MessageNumber,
  3136. ArgList);
  3137. }
  3138. except (EXCEPTION_EXECUTE_HANDLER) {
  3139. Status = EtwpNtStatusToDosError( GetExceptionCode() );
  3140. }
  3141. return EtwpSetDosError(Status);
  3142. }
  3143. ULONG
  3144. WMIAPI
  3145. EtwTraceMessageVa(
  3146. IN TRACEHANDLE LoggerHandle,
  3147. IN ULONG MessageFlags,
  3148. IN LPGUID MessageGuid,
  3149. IN USHORT MessageNumber,
  3150. IN va_list MessageArgList
  3151. )
  3152. // The Va version of TraceMessage
  3153. {
  3154. ULONG Status ;
  3155. EtwpInitProcessHeap();
  3156. try {
  3157. Status = EtwpTraceMessage(LoggerHandle,
  3158. MessageFlags,
  3159. MessageGuid,
  3160. MessageNumber,
  3161. MessageArgList);
  3162. }
  3163. except (EXCEPTION_EXECUTE_HANDLER) {
  3164. Status = EtwpNtStatusToDosError( GetExceptionCode() );
  3165. }
  3166. return EtwpSetDosError(Status);
  3167. }
  3168. #endif