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.

3334 lines
106 KiB

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