Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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