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.

836 lines
24 KiB

  1. #define _UNICODE
  2. #define UNICODE
  3. #include <nt.h>
  4. #include <ntrtl.h>
  5. #include <nturtl.h>
  6. #include <windows.h>
  7. #include <stdio.h>
  8. #pragma warning(disable: 4201) // error C4201: nonstandard extension used : nameless struct/union
  9. #include <wmistr.h>
  10. #include <evntrace.h>
  11. #include <guiddef.h>
  12. #include <rpc.h>
  13. #include <rpcdce.h>
  14. #define REG_TRACE_REGKEY TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Tracing")
  15. #define REG_TRACE_ENABLED TEXT("EnableTracing")
  16. #define REG_TRACE_LOG_FILE_NAME TEXT("LogFileName")
  17. #define REG_TRACE_LOG_SESSION_NAME TEXT("LogSessionName")
  18. #define REG_TRACE_LOG_BUFFER_SIZE TEXT("BufferSize")
  19. #define REG_TRACE_LOG_MIN_BUFFERS TEXT("MinBuffers")
  20. #define REG_TRACE_LOG_MAX_BUFFERS TEXT("MaxBuffers")
  21. #define REG_TRACE_LOG_MAX_FILESIZE TEXT("MaxFileSize")
  22. #define REG_TRACE_LOG_MAX_HISTORY TEXT("MaxHistorySize")
  23. #define REG_TRACE_LOG_MAX_BACKUPS TEXT("MaxBackups")
  24. #define REG_TRACE_ACTIVE TEXT("Active")
  25. #define REG_TRACE_CONTROL TEXT("ControlFlags")
  26. #define REG_TRACE_LEVEL TEXT("Level")
  27. #define REG_TRACE_GUID TEXT("Guid")
  28. #include "wmlum.h"
  29. #ifndef ARRAYSIZE
  30. #define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
  31. #endif
  32. VOID RegisterIfNecessary(LPWSTR KeyName, LPCGUID Guid);
  33. WMLPRINTFUNC WmiLibPrint = 0;
  34. #define NT_LOGGER L"NT Kernel Logger"
  35. VOID
  36. MyDbgPrint(
  37. UINT Level,
  38. PCHAR FormatString,
  39. ...
  40. )
  41. /*++
  42. Routine Description:
  43. Prints a message to the debugger or console, as appropriate.
  44. Arguments:
  45. String - The initial message string to print.
  46. Any FormatMessage-compatible arguments to be inserted in the
  47. ErrorMessage before it is logged.
  48. Return Value:
  49. None.
  50. --*/
  51. {
  52. CHAR Buffer[256];
  53. DWORD Bytes;
  54. va_list ArgList;
  55. if (WmiLibPrint == NULL) {
  56. return;
  57. }
  58. va_start(ArgList, FormatString);
  59. Bytes = FormatMessageA(FORMAT_MESSAGE_FROM_STRING,
  60. FormatString,
  61. 0,
  62. 0,
  63. Buffer,
  64. sizeof(Buffer) / sizeof(CHAR),
  65. &ArgList);
  66. va_end(ArgList);
  67. if (Bytes != 0) {
  68. (*WmiLibPrint)(Level, Buffer);
  69. }
  70. }
  71. UINT HexVal(int ch) { return isdigit(ch) ? ch - '0' : ch - 'a' + 10; }
  72. UINT Hex(LPWSTR s, int n)
  73. {
  74. UINT res = 0;
  75. while(n--) { res = res * 16 + HexVal(*s++); }
  76. return res;
  77. }
  78. VOID
  79. GuidFromStr(
  80. IN LPWSTR str,
  81. OUT LPGUID guid)
  82. {
  83. guid->Data1 = Hex(str + 0, 8);
  84. guid->Data2 = (USHORT)Hex(str + 9, 4);
  85. guid->Data3 = (USHORT)Hex(str + 14, 4);
  86. guid->Data4[0] = (UCHAR) Hex(str + 19, 2);
  87. guid->Data4[1] = (UCHAR) Hex(str + 21, 2);
  88. guid->Data4[2] = (UCHAR) Hex(str + 24, 2);
  89. guid->Data4[3] = (UCHAR) Hex(str + 26, 2);
  90. guid->Data4[4] = (UCHAR) Hex(str + 28, 2);
  91. guid->Data4[5] = (UCHAR) Hex(str + 30, 2);
  92. guid->Data4[6] = (UCHAR) Hex(str + 32, 2);
  93. guid->Data4[7] = (UCHAR) Hex(str + 34, 2);
  94. }
  95. typedef struct _INHERITED_DATA {
  96. BOOL Active;
  97. ULONG ControlFlags;
  98. ULONG LogLevel;
  99. ULONG Reserved;
  100. TRACEHANDLE Logger;
  101. GUID Guid;
  102. BOOL GuidDefined;
  103. } INHERITED_DATA, *PINHERITED_DATA;
  104. VOID
  105. ReadCommonData(
  106. IN HKEY hk,
  107. IN OUT PINHERITED_DATA data
  108. )
  109. {
  110. ULONG ulTemp;
  111. ULONG dwSize;
  112. WCHAR szGuid[16 * 3 + 1];
  113. dwSize = sizeof(ulTemp);
  114. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_ACTIVE,
  115. NULL, NULL, (BYTE *) &ulTemp, &dwSize))
  116. {
  117. data->Active = ulTemp;
  118. }
  119. dwSize = sizeof(ulTemp);
  120. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_CONTROL,
  121. NULL, NULL,
  122. (BYTE *) &ulTemp, &dwSize))
  123. {
  124. data->ControlFlags = ulTemp;
  125. }
  126. dwSize = sizeof(ulTemp);
  127. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LEVEL,
  128. NULL, NULL,
  129. (BYTE *) &ulTemp,
  130. &dwSize))
  131. {
  132. data->LogLevel = ulTemp;
  133. }
  134. dwSize = sizeof(szGuid);
  135. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_GUID,
  136. NULL, NULL,
  137. (BYTE *) &szGuid,
  138. &dwSize))
  139. {
  140. GuidFromStr(szGuid, &data->Guid);
  141. data->GuidDefined = TRUE;
  142. }
  143. return;
  144. }
  145. typedef struct _FULL_LOGGER_INFO {
  146. EVENT_TRACE_PROPERTIES LoggerInfo;
  147. WCHAR logFileName[MAX_PATH + 512];
  148. WCHAR logSessionName[MAX_PATH + 512];
  149. ULONG MaxHistorySize;
  150. ULONG MaxBackups;
  151. } FULL_LOGGER_INFO, *PFULL_LOGGER_INFO;
  152. GUID MySystemTraceControlGuid = { /* 9e814aad-3204-11d2-9a82-006008a86939 */
  153. 0x9e814aad,
  154. 0x3204,
  155. 0x11d2,
  156. {0x9a, 0x82, 0x00, 0x60, 0x08, 0xa8, 0x69, 0x39}
  157. };
  158. #define ULONG_PTR_DIFF(bigger, smaller) \
  159. static_cast<ULONG>( (char*)(bigger) - (char*)(smaller) )
  160. VOID
  161. ReadLoggerInfo(
  162. IN HKEY hk,
  163. OUT PTRACEHANDLE Logger)
  164. {
  165. FULL_LOGGER_INFO x;
  166. WCHAR tmpName[MAX_PATH + 512];
  167. WCHAR tmpName2[MAX_PATH + 512];
  168. ULONG ulTemp;
  169. ULONG dwReadSize = sizeof(ulTemp);
  170. ULONG status;
  171. SYSTEMTIME localTime;
  172. BOOL success;
  173. RtlZeroMemory(&x.LoggerInfo, sizeof(x));
  174. x.LoggerInfo.Wnode.BufferSize = sizeof(x);
  175. x.LoggerInfo.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  176. x.LoggerInfo.LogFileNameOffset = ULONG_PTR_DIFF(&x.logFileName, &x);
  177. x.LoggerInfo.LoggerNameOffset = ULONG_PTR_DIFF(&x.logSessionName, &x);
  178. x.LoggerInfo.LogFileMode = EVENT_TRACE_FILE_MODE_CIRCULAR;
  179. //
  180. // If the key describes a logger,
  181. // it should have at least LOG_SESSION_NAME value
  182. //
  183. dwReadSize = sizeof(x.logSessionName);
  184. status = RegQueryValueEx(hk, REG_TRACE_LOG_SESSION_NAME,
  185. NULL, NULL,
  186. (BYTE *) &x.logSessionName, &dwReadSize);
  187. if (status != ERROR_SUCCESS) {
  188. return;
  189. }
  190. if ( wcscmp(x.logSessionName, NT_LOGGER) == 0) {
  191. MyDbgPrint(3,"[WML] Enabling system tracing\n",
  192. x.logSessionName,
  193. x.LoggerInfo.Wnode.HistoricalContext);
  194. x.LoggerInfo.Wnode.Guid = MySystemTraceControlGuid;
  195. x.LoggerInfo.EnableFlags |=
  196. EVENT_TRACE_FLAG_PROCESS |
  197. EVENT_TRACE_FLAG_THREAD |
  198. EVENT_TRACE_FLAG_DISK_IO |
  199. EVENT_TRACE_FLAG_NETWORK_TCPIP |
  200. EVENT_TRACE_FLAG_REGISTRY;
  201. }
  202. // Let's query, whether there is a logger with this name
  203. status = QueryTrace(0, x.logSessionName, &x.LoggerInfo);
  204. if (ERROR_SUCCESS == status) {
  205. MyDbgPrint(1,"[WML] Query successful Logger %1!ws! %2!08X!:%3!08X!\n",
  206. x.logSessionName,
  207. x.LoggerInfo.Wnode.HistoricalContext);
  208. *Logger = x.LoggerInfo.Wnode.HistoricalContext;
  209. return;
  210. }
  211. if (ERROR_WMI_INSTANCE_NOT_FOUND != status) {
  212. MyDbgPrint(1,"[WML] Query of %1!ws! failed %2!d!\n",
  213. x.logSessionName, status);
  214. }
  215. // There is no logger runing
  216. // First, We will query logFileName value into tmpName variable
  217. // and then expand it into logFileName
  218. dwReadSize = sizeof(tmpName);
  219. status = RegQueryValueEx(hk, REG_TRACE_LOG_FILE_NAME,
  220. NULL, NULL,
  221. (BYTE *) &tmpName, &dwReadSize);
  222. if (status != ERROR_SUCCESS) {
  223. // If there is no logFileName, then this node doesn't describe
  224. // a logger. Bail out.
  225. MyDbgPrint(1,"[WML] Cannot read log file name, status %1!d!\n", status);
  226. return;
  227. }
  228. dwReadSize = ExpandEnvironmentStrings(tmpName, x.logFileName, ARRAYSIZE(x.logFileName) );
  229. if (dwReadSize == 0 || dwReadSize > ARRAYSIZE(x.logFileName)) {
  230. MyDbgPrint(1,"[WML] Expansion of %1!ws! failed, return value %2!d!\n", tmpName, dwReadSize);
  231. CopyMemory(x.logFileName, tmpName, sizeof(x.logFileName));
  232. }
  233. MyDbgPrint(3,"[WML] FileName %1!S!\n", x.logFileName);
  234. MyDbgPrint(3,"[WML] Session %1!S!\n", x.logSessionName);
  235. dwReadSize = sizeof(ulTemp);
  236. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_BUFFER_SIZE,
  237. NULL, NULL,
  238. (BYTE *) &ulTemp, &dwReadSize))
  239. x.LoggerInfo.BufferSize = ulTemp;
  240. dwReadSize = sizeof(ulTemp);
  241. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MIN_BUFFERS,
  242. NULL, NULL,
  243. (BYTE *) &ulTemp, &dwReadSize))
  244. x.LoggerInfo.MinimumBuffers = ulTemp;
  245. dwReadSize = sizeof(ulTemp);
  246. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MAX_BUFFERS,
  247. NULL, NULL,
  248. (BYTE *) &ulTemp, &dwReadSize))
  249. x.LoggerInfo.MaximumBuffers = ulTemp;
  250. dwReadSize = sizeof(ulTemp);
  251. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MAX_FILESIZE,
  252. NULL, NULL,
  253. (BYTE *) &ulTemp, &dwReadSize))
  254. x.LoggerInfo.MaximumFileSize = ulTemp;
  255. x.MaxHistorySize = 4 * x.LoggerInfo.MaximumFileSize;
  256. dwReadSize = sizeof(ulTemp);
  257. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MAX_HISTORY,
  258. NULL, NULL,
  259. (BYTE *) &ulTemp, &dwReadSize))
  260. x.MaxHistorySize = ulTemp;
  261. dwReadSize = sizeof(ulTemp);
  262. if (ERROR_SUCCESS == RegQueryValueEx(hk, REG_TRACE_LOG_MAX_BACKUPS,
  263. NULL, NULL,
  264. (BYTE *) &ulTemp, &dwReadSize))
  265. x.MaxBackups = ulTemp;
  266. if (x.MaxBackups == 0) {
  267. // We need to check whether the file already exist and rename it //
  268. GetLocalTime(&localTime);
  269. _snwprintf(tmpName, ARRAYSIZE(tmpName),
  270. L"%1ws.%04d%02d%02d%02d%02d%02d",
  271. x.logFileName,
  272. localTime.wYear,localTime.wMonth,localTime.wDay,
  273. localTime.wHour,localTime.wMinute,localTime.wSecond);
  274. success = MoveFile(x.logFileName, tmpName);
  275. if (!success) {
  276. status = GetLastError();
  277. } else {
  278. status = ERROR_SUCCESS;
  279. }
  280. MyDbgPrint(3,"[WML] Rename %1!ws! => %2!ws!, status %3!d!\n",
  281. x.logFileName, tmpName, status);
  282. } else {
  283. int i;
  284. for (i = x.MaxBackups; i >= 1; --i) {
  285. _snwprintf(tmpName2, ARRAYSIZE(tmpName),
  286. L"%1ws.%03d",
  287. x.logFileName, i);
  288. if (i == 1) {
  289. wcscpy(tmpName, x.logFileName);
  290. } else {
  291. _snwprintf(tmpName, ARRAYSIZE(tmpName),
  292. L"%1ws.%03d",
  293. x.logFileName, i-1);
  294. }
  295. success = MoveFileEx(tmpName, tmpName2, MOVEFILE_REPLACE_EXISTING);
  296. if (!success) {
  297. status = GetLastError();
  298. } else {
  299. status = ERROR_SUCCESS;
  300. }
  301. MyDbgPrint(3,"[WML] Rename %1!ws! => %2!ws!, status %3!d!\n",
  302. tmpName, tmpName2, status);
  303. }
  304. }
  305. status = StartTrace(Logger, x.logSessionName, &x.LoggerInfo);
  306. *Logger = x.LoggerInfo.Wnode.HistoricalContext;
  307. MyDbgPrint(1,"[WML] Logger %1!ws! started %3!08X!:%4!08X! %2!d!\n",
  308. x.logSessionName, status, *Logger);
  309. }
  310. WCHAR szModuleName[MAX_PATH+500];
  311. ULONG
  312. InitWmiInternal(
  313. IN HKEY Dir OPTIONAL, // if 0, then current ...
  314. IN LPWSTR ProductName,
  315. IN PINHERITED_DATA InheritedData OPTIONAL
  316. )
  317. {
  318. ULONG status;
  319. INHERITED_DATA data;
  320. HKEY CloseMe = 0;
  321. HKEY hk = 0;
  322. //ULONG ulTemp;
  323. //ULONG dwReadSize = sizeof(ulTemp);
  324. DWORD dwSizeOfModuleName;
  325. DWORD dwIndex;
  326. MyDbgPrint(2, "[WML] Init %1!ws!\n", ProductName);
  327. if (InheritedData) {
  328. data = *InheritedData;
  329. } else {
  330. ZeroMemory(&data, sizeof(data));
  331. }
  332. data.GuidDefined = FALSE;
  333. if (!Dir) {
  334. status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  335. REG_TRACE_REGKEY,
  336. 0,
  337. KEY_READ,
  338. &CloseMe);
  339. if (status != ERROR_SUCCESS) {
  340. MyDbgPrint(1,"[WML] Failed to open Trace Key, %1!d!\n", status);
  341. goto exit_gracefully;
  342. }
  343. Dir = CloseMe;
  344. }
  345. status = RegOpenKeyEx(Dir,
  346. ProductName,
  347. 0,
  348. KEY_READ,
  349. &hk);
  350. if (status != ERROR_SUCCESS) {
  351. MyDbgPrint(1,"[WML] Failed to open %1!ws! subkey, %2!d!\n", ProductName, status);
  352. goto exit_gracefully;
  353. }
  354. ReadLoggerInfo(hk, &data.Logger);
  355. ReadCommonData(hk, &data);
  356. if (!data.Active) {
  357. MyDbgPrint(1,"[WML] Tracing is not active for %1!ws!\n", ProductName);
  358. goto exit_gracefully;
  359. }
  360. if (data.GuidDefined) {
  361. // First, try to find its in the map. //
  362. // If it is there, we need to register this Guid //
  363. RegisterIfNecessary(ProductName, &data.Guid);
  364. // We can try to start tracing //
  365. if (data.Logger) {
  366. status = EnableTrace(data.Active,
  367. data.ControlFlags,
  368. data.LogLevel,
  369. &data.Guid,
  370. data.Logger);
  371. MyDbgPrint(1,"[WML] Enable=%1!d! %2!ws!, status %3!d!\n", data.
  372. Active, ProductName, status);
  373. }
  374. }
  375. dwSizeOfModuleName = sizeof(szModuleName);
  376. dwIndex = 0;
  377. while (ERROR_SUCCESS == (status = RegEnumKeyEx(hk, dwIndex,
  378. szModuleName,
  379. &dwSizeOfModuleName,
  380. NULL, NULL, NULL, NULL)))
  381. {
  382. InitWmiInternal(hk, szModuleName, &data);
  383. dwSizeOfModuleName = sizeof(szModuleName);
  384. ++dwIndex;
  385. }
  386. if (ERROR_NO_MORE_ITEMS == status) {
  387. status = ERROR_SUCCESS;
  388. }
  389. exit_gracefully:
  390. if (CloseMe) {
  391. RegCloseKey(CloseMe);
  392. }
  393. if (hk) {
  394. RegCloseKey(hk);
  395. }
  396. return status;
  397. }
  398. ULONG
  399. InitWmi(
  400. IN LPWSTR ProductName
  401. )
  402. {
  403. MyDbgPrint(1, "[WML] Initialize %1!ws!\n", ProductName);
  404. return InitWmiInternal(0, ProductName, 0);
  405. }
  406. #pragma warning(disable: 4512) // error C4512: 'blah-blah-blah' : assignment operator could not be generated
  407. #pragma warning(disable: 4100) // '_P' : unreferenced formal parameter
  408. #include <xmemory>
  409. #pragma warning(default: 4100)
  410. #include <map>
  411. //#include <xstring>
  412. struct wless {
  413. bool operator() (LPCWSTR a, LPCWSTR b) const { return lstrcmpW(a,b) < 0; }
  414. };
  415. typedef std::map<LPCWSTR, PWML_REG_STRUCT, wless > WIDE_STRING_MAP;
  416. WIDE_STRING_MAP* map;
  417. PWML_REG_STRUCT head;
  418. ULONG
  419. WmilibControlCallback(
  420. IN WMIDPREQUESTCODE RequestCode,
  421. IN PVOID Context,
  422. IN OUT ULONG *InOutBufferSize,
  423. IN OUT PVOID Buffer
  424. )
  425. {
  426. PWML_REG_STRUCT Ctx = (PWML_REG_STRUCT)Context;
  427. ULONG Status = ERROR_SUCCESS;
  428. switch (RequestCode)
  429. {
  430. case WMI_ENABLE_EVENTS:
  431. {
  432. Ctx->LoggerHandle = GetTraceLoggerHandle( Buffer );
  433. Ctx->EnableLevel = GetTraceEnableLevel(Ctx->LoggerHandle);
  434. Ctx->EnableFlags = GetTraceEnableFlags(Ctx->LoggerHandle);
  435. MyDbgPrint(3, "[WML] WMI_ENABLE_EVENTS Ctx 0x%1!08X! Flags %2!X! Lev %3!d! Logger %4!08X!:%5!08X!\n",
  436. Ctx, Ctx->EnableFlags, Ctx->EnableLevel, Ctx->LoggerHandle);
  437. break;
  438. }
  439. case WMI_DISABLE_EVENTS:
  440. {
  441. Ctx->LoggerHandle = 0;
  442. Ctx->EnableFlags = 0;
  443. Ctx->EnableLevel = 0;
  444. MyDbgPrint(3, "[WML] WMI_DISABLE_EVENTS Ctx 0x%1!08X!\n", Ctx);
  445. break;
  446. }
  447. default:
  448. {
  449. Status = ERROR_INVALID_PARAMETER;
  450. break;
  451. }
  452. }
  453. *InOutBufferSize = 0;
  454. return(Status);
  455. }
  456. VOID RegisterIfNecessary(
  457. LPWSTR KeyName,
  458. LPCGUID Guid)
  459. {
  460. WIDE_STRING_MAP::iterator i = map->find(KeyName);
  461. if ( i == map->end() ) {
  462. MyDbgPrint(2, "[WML] map: %1!ws!, not found\n", KeyName);
  463. return; // Not found //
  464. }
  465. MyDbgPrint(3, "[WML] map[%1!ws!]=0x%2!08X!\n", i->first, i->second);
  466. TRACE_GUID_REGISTRATION Reg;
  467. Reg.Guid = Guid;
  468. Reg.RegHandle = 0;
  469. ULONG status = RegisterTraceGuids(
  470. WmilibControlCallback,
  471. i->second, // Context for the callback
  472. Guid, // Control Guid
  473. 1, // # of dummies
  474. &Reg, // dummy trace guid
  475. 0, //ImagePath,
  476. 0, //ResourceName,
  477. &i->second->RegistrationHandle
  478. );
  479. if (status == ERROR_SUCCESS) {
  480. i->second->Next = head;
  481. head = i->second;
  482. } else {
  483. MyDbgPrint(1, "[WML] Failed to register %1!ws!, status %2!d!\n", KeyName, status);
  484. }
  485. }
  486. WCHAR DefaultLoggerName[] = L"DefaultLogger";
  487. ULONG
  488. CreateAppKey(LPCWSTR ProductName)
  489. {
  490. DWORD status;
  491. DWORD disposition;
  492. HKEY TracingKey = 0;
  493. HKEY ProductKey = 0;
  494. DWORD dwValue;
  495. status = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  496. REG_TRACE_REGKEY,
  497. 0,
  498. NULL, // Class
  499. REG_OPTION_NON_VOLATILE,
  500. KEY_READ | KEY_CREATE_SUB_KEY,
  501. NULL, // Sec Attributes
  502. &TracingKey,
  503. &disposition
  504. );
  505. if (status != ERROR_SUCCESS) {
  506. MyDbgPrint(1,"[WML] Failed to create Trace Key, %1!d!\n", status);
  507. goto exit_gracefully;
  508. }
  509. status = RegCreateKeyEx(TracingKey,
  510. ProductName,
  511. 0,
  512. NULL, // Class
  513. REG_OPTION_NON_VOLATILE,
  514. KEY_WRITE,
  515. NULL, // Sec Attributes
  516. &ProductKey,
  517. &disposition
  518. );
  519. if (status != ERROR_SUCCESS) {
  520. MyDbgPrint(1,"[WML] Failed to create Trace Key, %1!d!\n", status);
  521. goto exit_gracefully;
  522. }
  523. status = RegSetValueEx(ProductKey,
  524. REG_TRACE_LOG_SESSION_NAME,
  525. 0, // Reserved
  526. REG_EXPAND_SZ,
  527. (const BYTE*)DefaultLoggerName,
  528. sizeof(DefaultLoggerName) );
  529. if (status != ERROR_SUCCESS) {
  530. MyDbgPrint(1,"[WML] Failed to create LogSession value, %1!d!\n", status);
  531. goto exit_gracefully;
  532. }
  533. dwValue = 1;
  534. status = RegSetValueEx(ProductKey,
  535. REG_TRACE_ACTIVE,
  536. 0, // Reserved
  537. REG_DWORD,
  538. (const BYTE*)&dwValue,
  539. sizeof(dwValue) );
  540. if (status != ERROR_SUCCESS) {
  541. MyDbgPrint(1,"[WML] Failed to create Active value, %1!d!\n", status);
  542. goto exit_gracefully;
  543. }
  544. dwValue = 1;
  545. status = RegSetValueEx(ProductKey,
  546. REG_TRACE_LEVEL,
  547. 0, // Reserved
  548. REG_DWORD,
  549. (const BYTE*)&dwValue,
  550. sizeof(dwValue) );
  551. if (status != ERROR_SUCCESS) {
  552. MyDbgPrint(1,"[WML] Failed to create Level value, %1!d!\n", status);
  553. goto exit_gracefully;
  554. }
  555. dwValue = 1;
  556. status = RegSetValueEx(ProductKey,
  557. REG_TRACE_CONTROL,
  558. 0, // Reserved
  559. REG_DWORD,
  560. (const BYTE*)&dwValue,
  561. sizeof(dwValue) );
  562. if (status != ERROR_SUCCESS) {
  563. MyDbgPrint(1,"[WML] Failed to create Control value, %1!d!\n", status);
  564. goto exit_gracefully;
  565. }
  566. {
  567. WIDE_STRING_MAP::iterator i = map->begin();
  568. for(; i != map->end(); ++i) {
  569. status = RegCreateKeyEx(ProductKey,
  570. i->first,
  571. 0,
  572. NULL, // Class
  573. REG_OPTION_NON_VOLATILE,
  574. KEY_WRITE,
  575. NULL, // Sec Attributes
  576. &ProductKey,
  577. &disposition
  578. );
  579. if (status != ERROR_SUCCESS) {
  580. MyDbgPrint(1,"[WML] Failed to create %S Key, %1!d!\n", i->first, status);
  581. } else {
  582. GUID guid;
  583. WCHAR guidBuf[32+6+1];
  584. RPC_STATUS status = UuidCreate( &guid );
  585. if ( status != RPC_S_OK ) {
  586. MyDbgPrint(1,"[WML] UuidCreate failed, %1!d!\n", status);
  587. continue;
  588. }
  589. swprintf(guidBuf,L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  590. guid.Data1,guid.Data2,guid.Data3,
  591. guid.Data4[0],guid.Data4[1],guid.Data4[2],guid.Data4[3],
  592. guid.Data4[4],guid.Data4[5],guid.Data4[6],guid.Data4[7] );
  593. status = RegSetValueEx(ProductKey,
  594. REG_TRACE_GUID,
  595. 0, // Reserved
  596. REG_SZ,
  597. (const BYTE*)guidBuf,
  598. sizeof(guidBuf) );
  599. if (status != ERROR_SUCCESS) {
  600. MyDbgPrint(1,"[WML] Failed to create GUID value, %1!d!\n", status);
  601. }
  602. }
  603. }
  604. }
  605. exit_gracefully:
  606. if (ProductKey) {
  607. RegCloseKey(ProductKey);
  608. }
  609. if (TracingKey) {
  610. RegCloseKey(TracingKey);
  611. }
  612. return status;
  613. }
  614. ULONG
  615. WmlInitialize(
  616. IN LPWSTR ProductName,
  617. IN WMLPRINTFUNC PrintFunc,
  618. OUT WML_REG_HANDLE* Head,
  619. ... // Pairs: LPWSTR CtrlGuidName, Corresponding WML_REG_STRUCT
  620. )
  621. {
  622. WIDE_STRING_MAP map;
  623. LPWSTR str;
  624. va_list ap;
  625. WmiLibPrint = PrintFunc;
  626. *Head = 0;
  627. ::head = 0;
  628. ::map = &map;
  629. va_start(ap, Head);
  630. while(0 != (str = va_arg(ap, LPWSTR)) ) {
  631. map[ str ] = va_arg(ap, PWML_REG_STRUCT);
  632. }
  633. va_end(ap);
  634. ULONG status = InitWmiInternal(0, ProductName, 0);
  635. if (status == ERROR_FILE_NOT_FOUND) {
  636. status = CreateAppKey(ProductName);
  637. if (status == ERROR_SUCCESS) {
  638. status = InitWmiInternal(0, ProductName, 0);
  639. }
  640. }
  641. *Head = ::head;
  642. return status;
  643. }
  644. VOID
  645. WmlUninitialize(
  646. IN PWML_REG_STRUCT head
  647. )
  648. {
  649. while (head) {
  650. MyDbgPrint(3,"[WML] Unregister 0x%1!08X!\n", head);
  651. UnregisterTraceGuids(head->RegistrationHandle);
  652. head = head->Next;
  653. }
  654. }
  655. #define WML_USER_MODE
  656. typedef struct _TRACE_BUFFER {
  657. union {
  658. EVENT_TRACE_HEADER Trace;
  659. WNODE_HEADER Wnode;
  660. };
  661. MOF_FIELD MofFields[MAX_MOF_FIELDS + 1];
  662. } TRACE_BUFFER, *PTRACE_BUFFER;
  663. //////////////////////////////////////////////////////////////////////
  664. // 0 | Size | ProviderId | 0 |Size.HT.Mk | Typ.Lev.Version|
  665. // 2 | L o g g e r H a n d l e | 2 | T h r e a d I d |
  666. // 4 | T i m e S t a m p | 4 | T i m e S t a m p |
  667. // 6 | G U I D L o w | 6 | GUID Ptr / Guid L o w |
  668. // 8 | G U I D H I g h | 8 | G U I D H i g h |
  669. // 10 | ClientCtx | Flags | 10 |KernelTime | UserTime |
  670. //////////////////////////////////////////////////////////////////////
  671. ULONG
  672. WmlTrace(
  673. IN UINT Type,
  674. IN LPCGUID TraceGuid,
  675. IN TRACEHANDLE LoggerHandle,
  676. ... // Pairs: Address, Length
  677. )
  678. {
  679. TRACE_BUFFER TraceBuffer;
  680. ((PULONG)&TraceBuffer)[1] = Type;
  681. #ifndef WML_USER_MODE
  682. TraceBuffer.Wnode.HistoricalContext = LoggerHandle;
  683. #endif
  684. TraceBuffer.Trace.Guid = *TraceGuid;
  685. TraceBuffer.Wnode.Flags =
  686. WNODE_FLAG_USE_MOF_PTR | // MOF data are dereferenced
  687. WNODE_FLAG_TRACED_GUID; // Trace Event, not a WMI event
  688. {
  689. PMOF_FIELD ptr = TraceBuffer.MofFields;
  690. va_list ap;
  691. va_start(ap, LoggerHandle);
  692. do {
  693. if ( 0 == (ptr->Length = (ULONG)va_arg (ap, size_t)) ) {
  694. break;
  695. }
  696. ptr->DataPtr = (ULONGLONG)va_arg(ap, PVOID);
  697. } while ( ++ptr < &TraceBuffer.MofFields[MAX_MOF_FIELDS] );
  698. va_end(ap);
  699. TraceBuffer.Wnode.BufferSize = (ULONG) ((ULONG_PTR)ptr - (ULONG_PTR)&TraceBuffer);
  700. }
  701. #ifdef WML_USER_MODE
  702. ULONG status = TraceEvent( LoggerHandle, &TraceBuffer.Trace);
  703. if (status != ERROR_SUCCESS) {
  704. // Need to count failures and report them during unintialize or ...//
  705. }
  706. #else
  707. IoWMIWriteEvent(&TraceBuffer);
  708. #endif
  709. return ERROR_SUCCESS;
  710. }