Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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