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.

4103 lines
148 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. log_wmi.c
  5. Abstract:
  6. <abstract>
  7. --*/
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <nt.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. #include <windows.h>
  14. #include <assert.h>
  15. #include <pdh.h>
  16. #include "pdhidef.h"
  17. #include "perfdata.h"
  18. #include "log_bin.h"
  19. #include "log_wmi.h"
  20. #include "strings.h"
  21. #include "pdhmsg.h"
  22. #pragma warning ( disable : 4201 )
  23. #include <initguid.h>
  24. #include <wmistr.h>
  25. #include <ntwmi.h>
  26. #pragma warning ( default : 4201 )
  27. GUID PdhTransactionGuid = // 933f3bb3-943e-490d-9ced-3cbb14c14479
  28. { 0x933f3bb3, 0x943e, 0x490d, 0x9c, 0xed, 0x3c, 0xbb, 0x14, 0xc1, 0x44, 0x79 };
  29. PDHI_BINARY_LOG_RECORD_HEADER PdhNullCounterHeader = {
  30. BINLOG_TYPE_DATA_PSEUDO, 48 };
  31. PDH_RAW_COUNTER PdhNullCounter = {
  32. 0, // CStatus
  33. { 0, 0 }, // TimeStamp
  34. 0, // FirstValue
  35. 0, // SecondValue
  36. 0 // MultiCount
  37. };
  38. #define PDH_MAX_LOGFILES 32
  39. #define PDH_MAX_PATH 1024
  40. #define PDH_BLOCK_BUFFER_SIZE 8000
  41. #define PDH_WMI_BUFFER_SIZE 64
  42. #define PDH_WMI_BUFFER_SIZE_BYTE 64 * 1024
  43. #define PDH_LOG_HEADER_EVENT 0x20
  44. #define PDH_LOG_DATA_BLOCK_EVENT 0x22
  45. #define PDH_LOG_CATALOG_LIST_EVENT 0x23
  46. #define PDH_LOG_COUNTER_STRING_EVENT 0x24
  47. #define PDH_EVENT_VERSION 60
  48. #define PDH_WMI_MAX_BUFFERS 512
  49. #define PDH_WMI_DEFAULT_BUFFERS 32
  50. #define PDH_WMI_BUFFER_INCREMENT 16
  51. #define PDH_RESOURCE_NAME L"MofResource"
  52. #define TIME_DELTA 100000
  53. TRACEHANDLE PdhTraceRegistrationHandle = (TRACEHANDLE) 0;
  54. // For PDH WMI event trace logfile output
  55. //
  56. typedef struct _PDH_WMI_LOG_INFO {
  57. DWORD dwLogVersion; // version stamp
  58. DWORD dwFlags; // option flags
  59. } PDH_WMI_LOG_INFO, *PPDH_WMI_LOG_INFO;
  60. typedef struct _PDH_EVENT_TRACE_PROPERTIES {
  61. EVENT_TRACE_PROPERTIES LoggerInfo;
  62. WCHAR LoggerName[PDH_MAX_PATH];
  63. WCHAR LogFileName[PDH_MAX_PATH];
  64. GUID LogFileGuid;
  65. LONGLONG TimeStamp;
  66. LPWSTR MachineList;
  67. DWORD MachineListSize;
  68. BOOLEAN bHeaderEvent;
  69. } PDH_EVENT_TRACE_PROPERTIES, * PPDH_EVENT_TRACE_PROPERTIES;
  70. typedef struct _PDH_WMI_EVENT_TRACE {
  71. EVENT_TRACE_HEADER EventHeader;
  72. MOF_FIELD MofFields[4];
  73. } PDH_WMI_EVENT_TRACE, * PPDH_WMI_EVENT_TRACE;
  74. // For PDH WMI event trace logfile input
  75. //
  76. typedef enum _PDH_PROCESS_TRACE_STATE {
  77. PdhProcessTraceNormal,
  78. PdhProcessTraceRewind,
  79. PdhProcessTraceComplete,
  80. PdhProcessTraceEnd,
  81. PdhProcessTraceExit
  82. } PDH_PROCESS_TRACE_STATE;
  83. typedef struct _PDH_WMI_PERF_MACHINE {
  84. LIST_ENTRY Entry;
  85. LIST_ENTRY LogObjectList;
  86. LPWSTR pszBuffer;
  87. DWORD dwLastId;
  88. DWORD dwBufSize;
  89. LPWSTR * ptrStrAry;
  90. } PDH_WMI_PERF_MACHINE, * PPDH_WMI_PERF_MACHINE;
  91. typedef struct _PDH_WMI_PERF_OBJECT {
  92. LIST_ENTRY Entry;
  93. DWORD dwObjectId;
  94. LPWSTR szObjectName;
  95. PVOID ptrBuffer;
  96. } PDH_WMI_PERF_OBJECT, * PPDH_WMI_PERF_OBJECT;
  97. typedef struct _PDH_COUNTER_PATH {
  98. LIST_ENTRY Entry;
  99. ULONGLONG TimeStamp;
  100. PVOID CounterPathBuffer;
  101. ULONG CounterPathSize;
  102. ULONG CounterCount;
  103. } PDH_COUNTER_PATH, * PPDH_COUNTER_PATH;
  104. typedef struct _PDH_WMI_LOGFILE_INFO {
  105. GUID LogFileGuid;
  106. LIST_ENTRY CounterPathList;
  107. LIST_ENTRY PerfMachineList;
  108. ULONGLONG TimeStart;
  109. ULONGLONG TimeEnd;
  110. ULONGLONG TimeFreq;
  111. ULONGLONG TimePrev;
  112. PVOID DataBlock;
  113. ULONG ValidEntries;
  114. ULONG DataBlockSize;
  115. ULONG DataBlockAlloc;
  116. ULONG ulNumDataBlocks;
  117. ULONG ulDataBlocksCopied;
  118. ULONG ulCounters;
  119. } PDH_WMI_LOGFILE_INFO, * PPDH_WMI_LOGFILE_INFO;
  120. typedef struct _PDH_LOGGER_CONTEXT {
  121. PDH_WMI_LOGFILE_INFO LogInfo[PDH_MAX_LOGFILES];
  122. TRACEHANDLE LogFileHandle[PDH_MAX_LOGFILES];
  123. LPWSTR LogFileName[PDH_MAX_LOGFILES];
  124. ULONGLONG TimeFreq;
  125. HANDLE hThreadWork;
  126. HANDLE hSyncPDH;
  127. HANDLE hSyncWMI;
  128. PVOID CounterPathBuffer;
  129. PVOID tmpBuffer;
  130. PDH_PROCESS_TRACE_STATE LoggerState;
  131. ULONG LogFileCount;
  132. ULONG LoggerCount;
  133. ULONG RefCount;
  134. DWORD dwThread;
  135. BOOLEAN bCounterPathChanged;
  136. BOOLEAN bFirstDataBlockRead;
  137. BOOLEAN bDataBlockProcessed;
  138. BOOLEAN bFirstRun;
  139. } PDH_LOGGER_CONTEXT, * PPDH_LOGGER_CONTEXT;
  140. PPDH_LOGGER_CONTEXT ContextTable[PDH_MAX_LOGFILES];
  141. DWORD ContextCount = 0;
  142. HANDLE hPdhContextMutex;
  143. typedef struct _PDH_DATA_BLOCK_TRANSFER {
  144. ULONGLONG CurrentTime;
  145. PVOID pRecord;
  146. DWORD dwCurrentSize;
  147. PDH_STATUS Status;
  148. } PDH_DATA_BLOCK_TRANSFER, * PPDH_DATA_BLOCK_TRANSFER;
  149. PDH_DATA_BLOCK_TRANSFER DataBlockInfo = { 0, NULL, 0, ERROR_SUCCESS };
  150. void
  151. GuidToString(PWCHAR s, LPGUID piid)
  152. {
  153. swprintf(s, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  154. piid->Data1,
  155. piid->Data2,
  156. piid->Data3,
  157. piid->Data4[0],
  158. piid->Data4[1],
  159. piid->Data4[2],
  160. piid->Data4[3],
  161. piid->Data4[4],
  162. piid->Data4[5],
  163. piid->Data4[6],
  164. piid->Data4[7]);
  165. }
  166. PPDH_LOGGER_CONTEXT
  167. PdhWmiGetCurrentContext(
  168. IN DWORD dwLine)
  169. {
  170. PPDH_LOGGER_CONTEXT CurrentContext = NULL;
  171. DWORD dwThread = GetCurrentThreadId();
  172. DWORD i;
  173. if (WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex) == ERROR_SUCCESS) {
  174. for (i = 0; i < ContextCount; i ++) {
  175. if (ContextTable[i]->dwThread == dwThread) {
  176. CurrentContext = ContextTable[i];
  177. break;
  178. }
  179. }
  180. RELEASE_MUTEX(hPdhContextMutex);
  181. }
  182. return CurrentContext;
  183. }
  184. DWORD
  185. PdhWmiGetLoggerContext(
  186. IN DWORD dwLine,
  187. IN PPDH_LOGGER_CONTEXT pLoggerContext)
  188. {
  189. DWORD i = ContextCount;
  190. if (pLoggerContext != NULL) {
  191. if (WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex) == ERROR_SUCCESS) {
  192. for (i = 0; i < ContextCount; i ++) {
  193. if (ContextTable[i] == pLoggerContext) {
  194. break;
  195. }
  196. }
  197. RELEASE_MUTEX(hPdhContextMutex);
  198. }
  199. }
  200. return i;
  201. }
  202. #define GetCurrentContext() PdhWmiGetCurrentContext(__LINE__)
  203. #define GetLoggerContext(X) PdhWmiGetLoggerContext(__LINE__,X)
  204. #if 0
  205. PDH_FUNCTION
  206. PdhiBuildEmptyBlock(
  207. IN PPDHI_LOG pLog,
  208. IN LONGLONG TimeStamp,
  209. OUT ULONG * lenMofData,
  210. OUT PVOID * ptrMofData)
  211. {
  212. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  213. PPDHI_COUNTER pThisCounter;
  214. PPDHI_BINARY_LOG_RECORD_HEADER pLogCounterBuffer = NULL;
  215. PPDHI_BINARY_LOG_RECORD_HEADER pThisLogCounter = NULL;
  216. PPDH_RAW_COUNTER pSingleCounter;
  217. PPDHI_RAW_COUNTER_ITEM_BLOCK pMultiCounter;
  218. PPERF_DATA_BLOCK pObjectCounter;
  219. DWORD dwBufSize = 0;
  220. if (pLog->pQuery == NULL || pLog->pQuery->pCounterListHead == NULL) {
  221. pdhStatus = PDH_NO_DATA;
  222. goto Cleanup;
  223. }
  224. pThisCounter = pLog->pQuery->pCounterListHead;
  225. do {
  226. DWORD dwType = (pThisCounter->dwFlags & PDHIC_COUNTER_OBJECT)
  227. ? (PDHIC_COUNTER_OBJECT)
  228. : ( (pThisCounter->dwFlags & PDHIC_MULTI_INSTANCE)
  229. ? (PDHIC_MULTI_INSTANCE) : (0));
  230. DWORD dwCtrBufSize = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  231. DWORD dwNewSize;
  232. int nItem;
  233. switch (dwType) {
  234. case PDHIC_MULTI_INSTANCE:
  235. dwCtrBufSize += sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK);
  236. break;
  237. case PDHIC_COUNTER_OBJECT:
  238. dwCtrBufSize += sizeof(PERF_DATA_BLOCK);
  239. break;
  240. default:
  241. dwCtrBufSize += sizeof(PDH_RAW_COUNTER);
  242. break;
  243. }
  244. if (pLogCounterBuffer == NULL) {
  245. dwBufSize = (dwCtrBufSize + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  246. pLogCounterBuffer = G_ALLOC(dwBufSize);
  247. if (pLogCounterBuffer == NULL) {
  248. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  249. break;
  250. }
  251. pThisLogCounter = (PPDHI_BINARY_LOG_RECORD_HEADER)
  252. ( ((PUCHAR) pLogCounterBuffer)
  253. + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  254. }
  255. else {
  256. PPDHI_BINARY_LOG_RECORD_HEADER ptrTemp = pLogCounterBuffer;
  257. dwNewSize = (dwBufSize + dwCtrBufSize);
  258. pLogCounterBuffer = G_REALLOC(ptrTemp, dwNewSize);
  259. if (pLogCounterBuffer == NULL) {
  260. G_FREE(ptrTemp);
  261. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  262. break;
  263. }
  264. pThisLogCounter = (PPDHI_BINARY_LOG_RECORD_HEADER)
  265. ((LPBYTE) pLogCounterBuffer + dwBufSize);
  266. dwBufSize += (USHORT) dwCtrBufSize;
  267. }
  268. assert (dwCtrBufSize < 0x00010000);
  269. pThisLogCounter->dwLength = LOWORD(dwCtrBufSize);
  270. if (dwType == PDHIC_COUNTER_OBJECT) {
  271. FILETIME tmpFileTime;
  272. pThisLogCounter->dwType = BINLOG_TYPE_DATA_LOC_OBJECT;
  273. pObjectCounter = (PPERF_DATA_BLOCK)
  274. ((LPBYTE) pThisLogCounter +
  275. sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  276. pObjectCounter->Signature[0] = L'P';
  277. pObjectCounter->Signature[1] = L'E';
  278. pObjectCounter->Signature[2] = L'R';
  279. pObjectCounter->Signature[3] = L'F';
  280. pObjectCounter->LittleEndian = TRUE;
  281. pObjectCounter->Version = PERF_DATA_VERSION;
  282. pObjectCounter->Revision = PERF_DATA_REVISION;
  283. pObjectCounter->TotalByteLength = sizeof(PERF_DATA_BLOCK);
  284. pObjectCounter->NumObjectTypes = 1;
  285. pObjectCounter->DefaultObject = pThisCounter->plCounterInfo.dwObjectId;
  286. pObjectCounter->SystemNameLength = 0;
  287. pObjectCounter->SystemNameOffset = 0;
  288. pObjectCounter->HeaderLength = sizeof(PERF_DATA_BLOCK);
  289. pObjectCounter->PerfTime.QuadPart = 0;
  290. pObjectCounter->PerfFreq.QuadPart = 0;
  291. pObjectCounter->PerfTime100nSec.QuadPart = 0;
  292. tmpFileTime.dwLowDateTime = LODWORD(TimeStamp);
  293. tmpFileTime.dwHighDateTime = HIDWORD(TimeStamp);
  294. FileTimeToSystemTime(& tmpFileTime, & pObjectCounter->SystemTime);
  295. }
  296. else if (dwType == PDHIC_MULTI_INSTANCE) {
  297. pThisLogCounter->dwType = BINLOG_TYPE_DATA_MULTI;
  298. pMultiCounter = (PPDHI_RAW_COUNTER_ITEM_BLOCK)
  299. ((LPBYTE) pThisLogCounter +
  300. sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  301. ZeroMemory(pMultiCounter, sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK));
  302. pMultiCounter->CStatus = ERROR_SUCCESS;
  303. pMultiCounter->TimeStamp.dwLowDateTime = LODWORD(TimeStamp);
  304. pMultiCounter->TimeStamp.dwHighDateTime = HIDWORD(TimeStamp);
  305. }
  306. else {
  307. pThisLogCounter->dwType = BINLOG_TYPE_DATA_SINGLE;
  308. pSingleCounter = (PPDH_RAW_COUNTER)
  309. ((LPBYTE) pThisLogCounter +
  310. sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  311. ZeroMemory(pSingleCounter, sizeof(PDH_RAW_COUNTER));
  312. pSingleCounter->CStatus = ERROR_SUCCESS;
  313. pSingleCounter->TimeStamp.dwLowDateTime = LODWORD(TimeStamp);
  314. pSingleCounter->TimeStamp.dwHighDateTime = HIDWORD(TimeStamp);
  315. }
  316. pThisCounter = pThisCounter->next.flink; // go to next in list
  317. } while (pThisCounter != pLog->pQuery->pCounterListHead);
  318. if (pLogCounterBuffer) {
  319. pLogCounterBuffer->dwType = BINLOG_TYPE_DATA;
  320. pLogCounterBuffer->dwLength = dwBufSize;
  321. }
  322. Cleanup:
  323. * lenMofData = dwBufSize;
  324. * ptrMofData = pLogCounterBuffer;
  325. return pdhStatus;
  326. }
  327. #endif
  328. PDH_FUNCTION
  329. PdhWmiTraceEvent(
  330. IN PPDHI_LOG pLog,
  331. IN ULONG PdhEventType,
  332. IN ULONGLONG TimeStamp,
  333. IN ULONG lenMofData,
  334. IN PVOID ptrMofData);
  335. PDH_FUNCTION
  336. PdhiBuildPerfCounterList(
  337. IN PPDHI_LOG pLog,
  338. IN PPDH_EVENT_TRACE_PROPERTIES LoggerInfo,
  339. IN PPDHI_COUNTER pCounter)
  340. {
  341. PDH_STATUS Status = ERROR_SUCCESS;
  342. PPERF_MACHINE pMachine = pCounter->pQMachine->pMachine;
  343. LPWSTR * pString = pMachine->szPerfStrings;
  344. BYTE * pType = pMachine->typePerfStrings;
  345. DWORD dwLastId = pMachine->dwLastPerfString;
  346. DWORD i;
  347. DWORD dwBufSize = 0;
  348. LPWSTR pszBuffer = NULL;
  349. LPWSTR pszCurrent;
  350. BOOLEAN bNewEvent = TRUE;
  351. if (LoggerInfo->MachineList != NULL) {
  352. pszCurrent = LoggerInfo->MachineList;
  353. while (* pszCurrent != L'\0') {
  354. if (lstrcmpiW(pszCurrent, pMachine->szName) == 0) {
  355. // Machine Perf Counter List already there, bail out.
  356. //
  357. goto Cleanup;
  358. }
  359. pszCurrent += (lstrlenW(pszCurrent) + 1);
  360. }
  361. }
  362. if (LoggerInfo->MachineList != NULL) {
  363. LPWSTR pszTemp = LoggerInfo->MachineList;
  364. LoggerInfo->MachineList = G_REALLOC( pszTemp,
  365. sizeof(WCHAR) * (LoggerInfo->MachineListSize + (lstrlenW(pMachine->szName) + 1)));
  366. if (LoggerInfo->MachineList != NULL) {
  367. pszCurrent = LoggerInfo->MachineList
  368. + (LoggerInfo->MachineListSize - 1);
  369. LoggerInfo->MachineListSize += (lstrlenW(pMachine->szName) + 1);
  370. }
  371. else {
  372. G_FREE(pszTemp);
  373. }
  374. }
  375. else {
  376. LoggerInfo->MachineListSize = (lstrlenW(pMachine->szName) + 2);
  377. LoggerInfo->MachineList =
  378. G_ALLOC(sizeof(WCHAR) * LoggerInfo->MachineListSize);
  379. if (LoggerInfo->MachineList != NULL) {
  380. pszCurrent = LoggerInfo->MachineList;
  381. }
  382. }
  383. if (LoggerInfo->MachineList == NULL) {
  384. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  385. goto Cleanup;
  386. }
  387. lstrcpyW(pszCurrent, pMachine->szName);
  388. dwBufSize = sizeof(WCHAR) * (lstrlenW(pMachine->szName) + 1);
  389. pszBuffer = (LPWSTR) G_ALLOC(PDH_BLOCK_BUFFER_SIZE);
  390. if (pszBuffer == NULL) {
  391. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  392. goto Cleanup;
  393. }
  394. __try {
  395. WCHAR szIndex[10];
  396. DWORD dwNewSize = 0;
  397. for (i = 0; i < dwLastId; i ++) {
  398. if (pString[i] == NULL || pType[i] != STR_COUNTER) continue;
  399. ZeroMemory(szIndex, sizeof(WCHAR) * 10);
  400. _ltow(i, szIndex, 10);
  401. dwNewSize = sizeof(WCHAR) * ( lstrlenW(szIndex) + 1
  402. + lstrlenW(pString[i]) + 1);
  403. if (dwBufSize + dwNewSize >= PDH_BLOCK_BUFFER_SIZE) {
  404. Status = PdhWmiTraceEvent(pLog,
  405. PDH_LOG_COUNTER_STRING_EVENT,
  406. LoggerInfo->TimeStamp - 1,
  407. dwBufSize,
  408. pszBuffer);
  409. bNewEvent = TRUE;
  410. }
  411. if (bNewEvent) {
  412. ZeroMemory(pszBuffer, PDH_BLOCK_BUFFER_SIZE);
  413. lstrcpyW(pszBuffer, pMachine->szName);
  414. pszCurrent = pszBuffer + (lstrlenW(pszBuffer) + 1);
  415. dwBufSize = sizeof(WCHAR) * (lstrlenW(pMachine->szName) + 1);
  416. bNewEvent = FALSE;
  417. }
  418. lstrcpyW(pszCurrent, szIndex);
  419. pszCurrent += (lstrlenW(pszCurrent) + 1);
  420. lstrcpyW(pszCurrent, pString[i]);
  421. pszCurrent += (lstrlenW(pszCurrent) + 1);
  422. dwBufSize += dwNewSize;
  423. }
  424. Status = PdhWmiTraceEvent(pLog,
  425. PDH_LOG_COUNTER_STRING_EVENT,
  426. LoggerInfo->TimeStamp - 1,
  427. dwBufSize,
  428. pszBuffer);
  429. }
  430. __except (EXCEPTION_EXECUTE_HANDLER) {
  431. Status = GetExceptionCode();
  432. }
  433. Cleanup:
  434. if (pszBuffer != NULL) {
  435. G_FREE(pszBuffer);
  436. }
  437. return Status;
  438. }
  439. PDH_FUNCTION
  440. PdhiBuildLogHeaderBlock(
  441. IN PPDHI_LOG pLog,
  442. IN PPDH_EVENT_TRACE_PROPERTIES LoggerInfo)
  443. {
  444. PDH_STATUS Status = ERROR_SUCCESS;
  445. PVOID ptrOutBuffer = NULL;
  446. PVOID ptrTemp;
  447. PPDH_WMI_LOG_INFO pLogInfo = NULL;
  448. DWORD SizeAlloc = sizeof(PDH_WMI_LOG_INFO);
  449. DWORD NewSizeAlloc;
  450. PPDHI_COUNTER pThisCounter;
  451. PPDHI_COUNTER pThisCounterHead;
  452. DWORD dwPathBufSize;
  453. PPDHI_LOG_COUNTER_PATH pLogCounter;
  454. LONG lBufOffset;
  455. PWCHAR pBufferBase;
  456. ptrOutBuffer = G_ALLOC(sizeof(PDH_WMI_LOG_INFO));
  457. if (ptrOutBuffer == NULL) {
  458. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  459. goto Cleanup;
  460. }
  461. pLogInfo = (PPDH_WMI_LOG_INFO) ptrOutBuffer;
  462. pLogInfo->dwLogVersion = WMILOG_VERSION;
  463. pLogInfo->dwFlags = pLog->dwLogFormat;
  464. pThisCounter = pThisCounterHead = (pLog->pQuery)
  465. ? (pLog->pQuery->pCounterListHead)
  466. : (NULL);
  467. if (pThisCounter != NULL) {
  468. do {
  469. dwPathBufSize = sizeof(PDHI_LOG_COUNTER_PATH) + sizeof(DWORD);
  470. if (pThisCounter->pCounterPath->szMachineName != NULL) {
  471. dwPathBufSize += sizeof(WCHAR) * (1 +
  472. lstrlenW(pThisCounter->pCounterPath->szMachineName));
  473. }
  474. if (pThisCounter->pCounterPath->szObjectName != NULL) {
  475. dwPathBufSize += sizeof(WCHAR) * (1 +
  476. lstrlenW(pThisCounter->pCounterPath->szObjectName));
  477. }
  478. if (pThisCounter->dwFlags & PDHIC_COUNTER_OBJECT) {
  479. Status = PdhiBuildPerfCounterList(
  480. pLog, LoggerInfo, pThisCounter);
  481. if (Status != ERROR_SUCCESS) {
  482. goto Cleanup;
  483. }
  484. }
  485. if (pThisCounter->pCounterPath->szInstanceName != NULL) {
  486. dwPathBufSize += sizeof(WCHAR) * (1 +
  487. lstrlenW(pThisCounter->pCounterPath->szInstanceName));
  488. }
  489. if (pThisCounter->pCounterPath->szParentName != NULL) {
  490. dwPathBufSize += sizeof(WCHAR) * (1 +
  491. lstrlenW(pThisCounter->pCounterPath->szParentName));
  492. }
  493. if (pThisCounter->pCounterPath->szCounterName != NULL) {
  494. dwPathBufSize += sizeof(WCHAR) * (1 +
  495. lstrlenW(pThisCounter->pCounterPath->szCounterName));
  496. }
  497. dwPathBufSize = QWORD_MULTIPLE(dwPathBufSize);
  498. NewSizeAlloc = SizeAlloc + dwPathBufSize;
  499. ptrTemp = ptrOutBuffer;
  500. ptrOutBuffer = G_REALLOC(ptrTemp, NewSizeAlloc);
  501. if (ptrOutBuffer == NULL) {
  502. G_FREE(ptrTemp);
  503. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  504. goto Cleanup;
  505. }
  506. pLogCounter = (PPDHI_LOG_COUNTER_PATH)
  507. (((LPBYTE) ptrOutBuffer) + SizeAlloc);
  508. SizeAlloc = NewSizeAlloc;
  509. RtlZeroMemory(pLogCounter, dwPathBufSize);
  510. pLogCounter->dwLength = dwPathBufSize;
  511. pLogCounter->dwFlags = pThisCounter->dwFlags;
  512. pLogCounter->dwUserData = pThisCounter->dwUserData;
  513. if (pThisCounter->dwFlags & PDHIC_COUNTER_OBJECT) {
  514. pLogCounter->dwCounterType = PDHIC_COUNTER_OBJECT;
  515. pLogCounter->lDefaultScale = 0;
  516. pLogCounter->dwIndex = 0;
  517. }
  518. else {
  519. pLogCounter->dwCounterType =
  520. pThisCounter->plCounterInfo.dwCounterType;
  521. pLogCounter->lDefaultScale =
  522. pThisCounter->plCounterInfo.lDefaultScale;
  523. pLogCounter->dwIndex =
  524. pThisCounter->pCounterPath->dwIndex;
  525. }
  526. pLogCounter->llTimeBase = pThisCounter->TimeBase;
  527. // if this is a wild card path, then move the strings up
  528. // 1 dword in the buffer allowing the first DWORD of the
  529. // the buffer to contain the offset into the catalog
  530. // of the instances found in this log file. This list
  531. // will be built after the log is closed.
  532. lBufOffset = 0; // in WORDS (not bytes)
  533. if (pThisCounter->pCounterPath->szInstanceName != NULL) {
  534. if (* pThisCounter->pCounterPath->szInstanceName == SPLAT_L) {
  535. lBufOffset = sizeof(DWORD);
  536. }
  537. }
  538. #if DBG
  539. if (lBufOffset > 0)
  540. * (LPDWORD) (& pLogCounter->Buffer[0]) = 0x12345678;
  541. #endif
  542. if (pThisCounter->pCounterPath->szMachineName != NULL) {
  543. pLogCounter->lMachineNameOffset = lBufOffset;
  544. pBufferBase = (PWCHAR)
  545. ((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
  546. lstrcpyW(pBufferBase,
  547. pThisCounter->pCounterPath->szMachineName);
  548. lBufOffset += sizeof(WCHAR) * (1 +
  549. lstrlenW(pThisCounter->pCounterPath->szMachineName));
  550. }
  551. else {
  552. pLogCounter->lMachineNameOffset = (LONG) -1;
  553. }
  554. if (pThisCounter->pCounterPath->szObjectName != NULL) {
  555. pLogCounter->lObjectNameOffset = lBufOffset;
  556. pBufferBase = (PWCHAR)
  557. ((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
  558. lstrcpyW(pBufferBase,
  559. pThisCounter->pCounterPath->szObjectName);
  560. lBufOffset += sizeof(WCHAR) * (1 +
  561. lstrlenW(pThisCounter->pCounterPath->szObjectName));
  562. }
  563. else {
  564. pLogCounter->lObjectNameOffset = (LONG) -1;
  565. }
  566. if (pThisCounter->pCounterPath->szInstanceName != NULL) {
  567. pLogCounter->lInstanceOffset = lBufOffset;
  568. pBufferBase = (PWCHAR)
  569. ((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
  570. lstrcpyW(pBufferBase,
  571. pThisCounter->pCounterPath->szInstanceName);
  572. lBufOffset += sizeof(WCHAR) * (1 +
  573. lstrlenW(pThisCounter->pCounterPath->szInstanceName));
  574. }
  575. else {
  576. pLogCounter->lInstanceOffset = (LONG) -1;
  577. }
  578. if (pThisCounter->pCounterPath->szParentName != NULL) {
  579. pLogCounter->lParentOffset = lBufOffset;
  580. pBufferBase = (PWCHAR)
  581. ((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
  582. lstrcpyW(pBufferBase,
  583. pThisCounter->pCounterPath->szParentName);
  584. lBufOffset += sizeof(WCHAR) * (1 +
  585. lstrlenW(pThisCounter->pCounterPath->szParentName));
  586. }
  587. else {
  588. pLogCounter->lParentOffset = (LONG) -1;
  589. }
  590. if (pThisCounter->pCounterPath->szCounterName != NULL) {
  591. pLogCounter->lCounterOffset = lBufOffset;
  592. pBufferBase = (PWCHAR)
  593. ((LPBYTE) & pLogCounter->Buffer[0] + lBufOffset);
  594. lstrcpyW(pBufferBase,
  595. pThisCounter->pCounterPath->szCounterName);
  596. lBufOffset += sizeof(WCHAR) * (1 +
  597. lstrlenW(pThisCounter->pCounterPath->szCounterName));
  598. }
  599. else {
  600. pLogCounter->lCounterOffset = (LONG) -1;
  601. }
  602. pThisCounter = pThisCounter->next.flink;
  603. } while (pThisCounter != pThisCounterHead);
  604. }
  605. if (Status == ERROR_SUCCESS) {
  606. Status = PdhWmiTraceEvent(pLog,
  607. PDH_LOG_HEADER_EVENT,
  608. LoggerInfo->TimeStamp - 1,
  609. SizeAlloc,
  610. ptrOutBuffer);
  611. }
  612. Cleanup:
  613. if (ptrOutBuffer) {
  614. G_FREE(ptrOutBuffer);
  615. }
  616. return Status;
  617. }
  618. PDH_FUNCTION
  619. PdhWmiTraceEvent(
  620. IN PPDHI_LOG pLog,
  621. IN ULONG PdhEventType,
  622. IN ULONGLONG TimeStamp,
  623. IN ULONG lenMofData,
  624. IN PVOID ptrMofData)
  625. {
  626. PDH_STATUS Status = PDH_INVALID_HANDLE;
  627. if ( (pLog->dwLogFormat & PDH_LOG_WRITE_ACCESS)
  628. && ((TRACEHANDLE) pLog->hLogFileHandle != (TRACEHANDLE) 0)) {
  629. PDH_WMI_EVENT_TRACE Wnode;
  630. PPDH_EVENT_TRACE_PROPERTIES LoggerInfo =
  631. (PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
  632. DWORD dwNumEvents = (lenMofData / PDH_BLOCK_BUFFER_SIZE);
  633. DWORD dwCurrentEvent = 1;
  634. PVOID ptrCurrentMof = ptrMofData;
  635. BOOL bIncreaseBuffer = TRUE;
  636. if (lenMofData > PDH_BLOCK_BUFFER_SIZE * dwNumEvents) {
  637. dwNumEvents ++;
  638. }
  639. for (Status = ERROR_SUCCESS, dwCurrentEvent = 1;
  640. (Status == ERROR_SUCCESS) && (dwCurrentEvent <= dwNumEvents);
  641. dwCurrentEvent ++) {
  642. USHORT sMofLen = (lenMofData > PDH_BLOCK_BUFFER_SIZE)
  643. ? (PDH_BLOCK_BUFFER_SIZE) : ((USHORT) lenMofData);
  644. RtlZeroMemory(& Wnode, sizeof(PDH_WMI_EVENT_TRACE));
  645. Wnode.EventHeader.Size = sizeof(PDH_WMI_EVENT_TRACE);
  646. Wnode.EventHeader.Class.Type = (UCHAR) PdhEventType;
  647. Wnode.EventHeader.Class.Version = PDH_EVENT_VERSION;
  648. Wnode.EventHeader.GuidPtr = (ULONGLONG) & PdhTransactionGuid;
  649. Wnode.EventHeader.Flags = WNODE_FLAG_TRACED_GUID
  650. | WNODE_FLAG_USE_GUID_PTR
  651. | WNODE_FLAG_USE_MOF_PTR
  652. | WNODE_FLAG_USE_TIMESTAMP;
  653. if ( PdhEventType == PDH_LOG_HEADER_EVENT
  654. || PdhEventType == PDH_LOG_COUNTER_STRING_EVENT) {
  655. Wnode.EventHeader.Flags |= WNODE_FLAG_PERSIST_EVENT;
  656. }
  657. Wnode.EventHeader.TimeStamp.QuadPart = TimeStamp;
  658. Wnode.MofFields[0].Length = sizeof(GUID);
  659. Wnode.MofFields[0].DataPtr = (ULONGLONG) & LoggerInfo->LogFileGuid;
  660. Wnode.MofFields[1].Length = sizeof(DWORD);
  661. Wnode.MofFields[1].DataPtr = (ULONGLONG) & dwCurrentEvent;
  662. Wnode.MofFields[2].Length = sizeof(DWORD);
  663. Wnode.MofFields[2].DataPtr = (ULONGLONG) & dwNumEvents;
  664. Wnode.MofFields[3].Length = sMofLen;
  665. Wnode.MofFields[3].DataPtr = (ULONGLONG) ptrCurrentMof;
  666. bIncreaseBuffer = TRUE;
  667. while (bIncreaseBuffer == TRUE) {
  668. Status = TraceEvent((TRACEHANDLE) pLog->hLogFileHandle,
  669. (PEVENT_TRACE_HEADER) & Wnode);
  670. if (Status == ERROR_NOT_ENOUGH_MEMORY) {
  671. if (LoggerInfo->LoggerInfo.MaximumBuffers >= PDH_WMI_MAX_BUFFERS) {
  672. bIncreaseBuffer = FALSE;
  673. }
  674. else {
  675. EVENT_TRACE_PROPERTIES tmpLoggerInfo;
  676. LoggerInfo->LoggerInfo.MaximumBuffers += PDH_WMI_BUFFER_INCREMENT;
  677. RtlCopyMemory(& tmpLoggerInfo,
  678. & LoggerInfo->LoggerInfo,
  679. sizeof(EVENT_TRACE_PROPERTIES));
  680. tmpLoggerInfo.Wnode.BufferSize = sizeof(EVENT_TRACE_PROPERTIES);
  681. tmpLoggerInfo.LoggerNameOffset = 0;
  682. tmpLoggerInfo.LogFileNameOffset = 0;
  683. Status = ControlTraceW((TRACEHANDLE) pLog->hLogFileHandle,
  684. LoggerInfo->LoggerName,
  685. (PEVENT_TRACE_PROPERTIES) & tmpLoggerInfo,
  686. EVENT_TRACE_CONTROL_UPDATE);
  687. DebugPrint((1, "UpdateTrace(0x%08X,%d)(%d,0x%08X)\n",
  688. pLog->hLogFileHandle,
  689. LoggerInfo->LoggerInfo.MaximumBuffers,
  690. Status,
  691. Status));
  692. bIncreaseBuffer = (Status == ERROR_SUCCESS || Status == ERROR_MORE_DATA) ? (TRUE) : (FALSE);
  693. }
  694. }
  695. else {
  696. bIncreaseBuffer = FALSE;
  697. }
  698. }
  699. if (Status != ERROR_SUCCESS) {
  700. DebugPrint((1, "PdhWmiTraceEvent(0x%08X,%d,%d/%d,%d,0x%08X,%I64d) fails (%d,0x%08X)\n",
  701. pLog->hLogFileHandle,
  702. PdhEventType,
  703. dwCurrentEvent,
  704. dwNumEvents,
  705. sMofLen,
  706. Wnode.EventHeader.Flags,
  707. Wnode.EventHeader.TimeStamp.QuadPart,
  708. Status,
  709. Status));
  710. }
  711. if (Status == ERROR_SUCCESS) {
  712. lenMofData -= sMofLen;
  713. ptrCurrentMof = (PVOID) (((LPBYTE) ptrCurrentMof) + sMofLen);
  714. }
  715. }
  716. }
  717. return Status;
  718. }
  719. ULONG whextoi(WCHAR *s)
  720. {
  721. long len;
  722. ULONG num, base, hex;
  723. if (s == NULL || s[0] == L'\0') {
  724. return 0;
  725. }
  726. len = (long) wcslen(s); // we expect all strings to be less than MAXSTR
  727. if (len == 0) {
  728. return 0;
  729. }
  730. hex = 0;
  731. base = 1;
  732. num = 0;
  733. while (-- len >= 0) {
  734. if (s[len] >= L'0' && s[len] <= L'9')
  735. num = s[len] - L'0';
  736. else if (s[len] >= L'a' && s[len] <= L'f')
  737. num = (s[len] - L'a') + 10;
  738. else if (s[len] >= L'A' && s[len] <= L'F')
  739. num = (s[len] - L'A') + 10;
  740. else
  741. continue;
  742. hex += num * base;
  743. base = base * 16;
  744. }
  745. return hex;
  746. }
  747. PDH_FUNCTION
  748. PdhiCheckWmiLogFileType(
  749. IN LPCWSTR LogFileName,
  750. IN LPDWORD LogFileType)
  751. {
  752. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  753. HANDLE hFile = NULL;
  754. hFile = CreateFileW(LogFileName,
  755. GENERIC_READ,
  756. FILE_SHARE_READ | FILE_SHARE_WRITE,
  757. NULL,
  758. OPEN_EXISTING,
  759. FILE_ATTRIBUTE_NORMAL,
  760. NULL);
  761. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
  762. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  763. }
  764. else {
  765. BYTE TraceBuffer[PDH_WMI_BUFFER_SIZE_BYTE];
  766. ULONG ByteRead = 0;
  767. INT bResult = ReadFile(hFile,
  768. (LPVOID) TraceBuffer,
  769. PDH_WMI_BUFFER_SIZE_BYTE,
  770. & ByteRead,
  771. NULL);
  772. if (bResult > 0 && ByteRead == PDH_WMI_BUFFER_SIZE_BYTE) {
  773. PWMI_BUFFER_HEADER BufferHeader;
  774. PTRACE_LOGFILE_HEADER LogFileHeader;
  775. BufferHeader = (PWMI_BUFFER_HEADER) TraceBuffer;
  776. LogFileHeader = (PTRACE_LOGFILE_HEADER)
  777. (TraceBuffer + sizeof(WMI_BUFFER_HEADER)
  778. + sizeof(SYSTEM_TRACE_HEADER));
  779. if ( BufferHeader->Wnode.BufferSize == PDH_WMI_BUFFER_SIZE_BYTE
  780. && LogFileHeader->BufferSize == PDH_WMI_BUFFER_SIZE_BYTE) {
  781. // preassume that this is PDH event trace counter logfile
  782. //
  783. * LogFileType = PDH_LOG_TYPE_BINARY;
  784. }
  785. else {
  786. * LogFileType = PDH_LOG_TYPE_UNDEFINED;
  787. }
  788. }
  789. }
  790. return pdhStatus;
  791. }
  792. PDH_FUNCTION
  793. PdhWmiGetLoggerName(
  794. IN PPDHI_LOG pLog,
  795. IN PPDH_EVENT_TRACE_PROPERTIES LoggerInfo)
  796. {
  797. PDH_STATUS Status = ERROR_SUCCESS;
  798. BYTE TraceBuffer[PDH_WMI_BUFFER_SIZE_BYTE]; // read in the first trace buffer
  799. HANDLE hFile;
  800. ULONG ByteRead = 0;
  801. hFile = CreateFileW(LoggerInfo->LogFileName,
  802. GENERIC_READ,
  803. FILE_SHARE_READ | FILE_SHARE_WRITE,
  804. NULL,
  805. OPEN_EXISTING,
  806. FILE_ATTRIBUTE_NORMAL,
  807. NULL);
  808. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
  809. Status = PDH_LOG_FILE_OPEN_ERROR;
  810. }
  811. else {
  812. INT bResult =
  813. ReadFile(hFile, (LPVOID) TraceBuffer, PDH_WMI_BUFFER_SIZE_BYTE, & ByteRead, NULL);
  814. if (bResult == 0 || ByteRead != PDH_WMI_BUFFER_SIZE_BYTE) {
  815. Status = PDH_LOG_FILE_OPEN_ERROR;
  816. }
  817. CloseHandle(hFile);
  818. }
  819. if (Status == ERROR_SUCCESS) {
  820. PTRACE_LOGFILE_HEADER pHeader = (PTRACE_LOGFILE_HEADER)
  821. (TraceBuffer + sizeof(WMI_BUFFER_HEADER) + sizeof(SYSTEM_TRACE_HEADER));
  822. if (pHeader->BuffersWritten > 1) {
  823. UINT i;
  824. WCHAR strTmp[PDH_MAX_PATH];
  825. LPWSTR LoggerName = (LPWSTR) (((LPBYTE) pHeader) + sizeof(TRACE_LOGFILE_HEADER));
  826. lstrcpynW(LoggerInfo->LoggerName, LoggerName, PDH_MAX_PATH);
  827. wcsncpy(strTmp, LoggerName, 8);
  828. strTmp[8] = L'\0';
  829. LoggerInfo->LogFileGuid.Data1 = whextoi(strTmp);
  830. wcsncpy(strTmp, & LoggerName[9], 4);
  831. strTmp[4] = L'\0';
  832. LoggerInfo->LogFileGuid.Data2 = (USHORT) whextoi(strTmp);
  833. wcsncpy(strTmp, & LoggerName[14], 4);
  834. strTmp[4] = L'\0';
  835. LoggerInfo->LogFileGuid.Data3 = (USHORT) whextoi(strTmp);
  836. for (i = 0; i < 2; i ++) {
  837. wcsncpy(strTmp, & LoggerName[19 + (i * 2)], 2);
  838. strTmp[2] = L'\0';
  839. LoggerInfo->LogFileGuid.Data4[i] = (UCHAR) whextoi(strTmp);
  840. }
  841. for (i = 2; i < 8; i ++) {
  842. wcsncpy(strTmp, & LoggerName[20 + (i * 2)], 2);
  843. strTmp[2] = L'\0';
  844. LoggerInfo->LogFileGuid.Data4[i] = (UCHAR) whextoi(strTmp);
  845. }
  846. }
  847. else {
  848. // Only 1 trace buffer written, no PDH events yet.
  849. // It is safe to discard this one and create a new one.
  850. //
  851. Status = PDH_LOG_FILE_OPEN_ERROR;
  852. DebugPrint((1,"PdhWmiGetLoggerName(0x%08X,0x%08X,0x%08X,\"%ws\")\n",
  853. Status, pLog, LoggerInfo, LoggerInfo->LogFileName));
  854. }
  855. }
  856. return Status;
  857. }
  858. PDH_FUNCTION
  859. PdhiOpenOutputWmiLog(
  860. IN PPDHI_LOG pLog)
  861. {
  862. PDH_STATUS Status = PDH_LOG_FILE_CREATE_ERROR;
  863. PPDH_EVENT_TRACE_PROPERTIES LoggerInfo;
  864. pLog->lpMappedFileBase = G_ALLOC(sizeof(PDH_EVENT_TRACE_PROPERTIES));
  865. if (pLog->lpMappedFileBase == NULL) {
  866. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  867. goto Cleanup;
  868. }
  869. LoggerInfo = (PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
  870. RtlZeroMemory(LoggerInfo, sizeof(PDH_EVENT_TRACE_PROPERTIES));
  871. // Start PDH kernel logger
  872. //
  873. LoggerInfo->LoggerInfo.Wnode.BufferSize =
  874. sizeof(PDH_EVENT_TRACE_PROPERTIES);
  875. LoggerInfo->LoggerInfo.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  876. LoggerInfo->LoggerInfo.Wnode.ClientContext = EVENT_TRACE_CLOCK_SYSTEMTIME;
  877. LoggerInfo->LoggerInfo.BufferSize = PDH_WMI_BUFFER_SIZE;
  878. LoggerInfo->LoggerInfo.LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
  879. LoggerInfo->LoggerInfo.LogFileNameOffset = sizeof(EVENT_TRACE_PROPERTIES)
  880. + sizeof(WCHAR) * PDH_MAX_PATH;
  881. _wfullpath(LoggerInfo->LogFileName, pLog->szLogFileName, PDH_MAX_PATH);
  882. if ( !(pLog->dwLogFormat & PDH_LOG_OPT_CIRCULAR)
  883. && (pLog->dwLogFormat & PDH_LOG_OPT_APPEND)) {
  884. Status = PdhWmiGetLoggerName(pLog, LoggerInfo);
  885. if (Status != ERROR_SUCCESS) {
  886. // if cannot get LogFileGuid from logfile, erase the old one
  887. // and create new one
  888. //
  889. RPC_STATUS rpcStatus = UuidCreate(& LoggerInfo->LogFileGuid);
  890. GuidToString(LoggerInfo->LoggerName, & LoggerInfo->LogFileGuid);
  891. }
  892. else {
  893. LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_FILE_MODE_APPEND;
  894. }
  895. }
  896. else {
  897. RPC_STATUS rpcStatus = UuidCreate(& LoggerInfo->LogFileGuid);
  898. GuidToString(LoggerInfo->LoggerName, & LoggerInfo->LogFileGuid);
  899. }
  900. if (pLog->dwLogFormat & PDH_LOG_OPT_CIRCULAR) {
  901. LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_FILE_MODE_CIRCULAR;
  902. }
  903. else {
  904. LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_FILE_MODE_SEQUENTIAL;
  905. }
  906. LoggerInfo->LoggerInfo.LogFileMode |= EVENT_TRACE_USE_PAGED_MEMORY;
  907. if (pLog->llMaxSize == 0) {
  908. LoggerInfo->LoggerInfo.MaximumFileSize = 0;
  909. }
  910. else {
  911. LoggerInfo->LoggerInfo.MaximumFileSize =
  912. (ULONG) ((pLog->llMaxSize / 1024) / 1024);
  913. }
  914. LoggerInfo->LoggerInfo.MaximumBuffers = PDH_WMI_DEFAULT_BUFFERS;
  915. LoggerInfo->bHeaderEvent = FALSE;
  916. Status = StartTraceW((PTRACEHANDLE) & pLog->hLogFileHandle,
  917. LoggerInfo->LoggerName,
  918. (PEVENT_TRACE_PROPERTIES) LoggerInfo);
  919. if (Status != ERROR_SUCCESS) {
  920. DebugPrint((1, "StartTraceW(%ws,%ws,0x%08X,%I64d) fails (0x%08X,%c)\n",
  921. LoggerInfo->LoggerName,
  922. LoggerInfo->LogFileName,
  923. LoggerInfo->LoggerInfo.LogFileMode,
  924. pLog->llMaxSize,
  925. Status,
  926. LoggerInfo->bHeaderEvent ? 'T' : 'F'));
  927. }
  928. Cleanup:
  929. if (Status != ERROR_SUCCESS) {
  930. if (pLog->lpMappedFileBase) {
  931. G_FREE(pLog->lpMappedFileBase);
  932. pLog->lpMappedFileBase = NULL;
  933. }
  934. Status = PDH_LOG_FILE_CREATE_ERROR;
  935. }
  936. return Status;
  937. }
  938. PDH_FUNCTION
  939. PdhiWriteWmiLogRecord (
  940. IN PPDHI_LOG pLog,
  941. IN SYSTEMTIME * stTimeStamp,
  942. IN LPCWSTR szUserString
  943. )
  944. {
  945. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  946. PPDHI_BINARY_LOG_RECORD_HEADER pLogCounterBuffer = NULL;
  947. PPDHI_BINARY_LOG_RECORD_HEADER pThisLogCounter = NULL;
  948. PPDH_RAW_COUNTER pSingleCounter;
  949. PPDHI_RAW_COUNTER_ITEM_BLOCK pMultiCounter;
  950. PPDHI_COUNTER pThisCounter;
  951. PPERF_DATA_BLOCK pObjectCounter;
  952. DWORD dwBufSize = 0;
  953. ULONGLONG TimeStamp = 0;
  954. FILETIME tFileTime;
  955. PPDH_EVENT_TRACE_PROPERTIES LoggerInfo =
  956. (PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
  957. DBG_UNREFERENCED_PARAMETER(szUserString);
  958. SystemTimeToFileTime(stTimeStamp, & tFileTime);
  959. pThisCounter = pLog->pQuery ? pLog->pQuery->pCounterListHead : NULL;
  960. if (pThisCounter == NULL) {
  961. return PDH_NO_DATA;
  962. }
  963. do {
  964. DWORD dwType = (pThisCounter->dwFlags & PDHIC_COUNTER_OBJECT)
  965. ? (PDHIC_COUNTER_OBJECT)
  966. : ( (pThisCounter->dwFlags & PDHIC_MULTI_INSTANCE)
  967. ? (PDHIC_MULTI_INSTANCE) : (0));
  968. DWORD dwCtrBufSize = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  969. DWORD dwNewSize;
  970. int nItem;
  971. switch (dwType) {
  972. case PDHIC_MULTI_INSTANCE:
  973. if (pThisCounter->pThisRawItemList) {
  974. dwCtrBufSize += pThisCounter->pThisRawItemList->dwLength;
  975. }
  976. else {
  977. dwCtrBufSize += sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK);
  978. }
  979. break;
  980. case PDHIC_COUNTER_OBJECT:
  981. if (pThisCounter->pThisObject) {
  982. dwCtrBufSize += pThisCounter->pThisObject->TotalByteLength;
  983. }
  984. else {
  985. dwCtrBufSize += sizeof(PERF_DATA_BLOCK);
  986. }
  987. break;
  988. default:
  989. dwCtrBufSize += sizeof(PDH_RAW_COUNTER);
  990. break;
  991. }
  992. if (dwCtrBufSize > 0) {
  993. // extend buffer to accomodate this new counter
  994. //
  995. if (pLogCounterBuffer == NULL) {
  996. // add in room for the master record header
  997. // then allocate the first one
  998. //
  999. dwBufSize = (dwCtrBufSize + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  1000. pLogCounterBuffer = G_ALLOC(dwBufSize);
  1001. // set counter data pointer to just after the master
  1002. // record header
  1003. //
  1004. if (pLogCounterBuffer == NULL) {
  1005. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1006. break;
  1007. }
  1008. pThisLogCounter = (PPDHI_BINARY_LOG_RECORD_HEADER)
  1009. ( ((PUCHAR) pLogCounterBuffer)
  1010. + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  1011. assert (dwCtrBufSize < 0x00010000);
  1012. pThisLogCounter->dwLength = LOWORD(dwCtrBufSize);
  1013. }
  1014. else {
  1015. PPDHI_BINARY_LOG_RECORD_HEADER ptrTemp = pLogCounterBuffer;
  1016. dwNewSize = (dwBufSize + dwCtrBufSize);
  1017. pLogCounterBuffer = G_REALLOC(ptrTemp, dwNewSize);
  1018. if (pLogCounterBuffer == NULL) {
  1019. G_FREE(ptrTemp);
  1020. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1021. break;
  1022. }
  1023. pThisLogCounter = (PPDHI_BINARY_LOG_RECORD_HEADER)
  1024. ((LPBYTE) pLogCounterBuffer + dwBufSize);
  1025. dwBufSize += dwCtrBufSize;
  1026. assert (dwCtrBufSize < 0x00010000);
  1027. pThisLogCounter->dwLength = LOWORD(dwCtrBufSize);
  1028. }
  1029. }
  1030. if (dwType == PDHIC_COUNTER_OBJECT) {
  1031. FILETIME LocFileTime;
  1032. pThisLogCounter->dwType = BINLOG_TYPE_DATA_LOC_OBJECT;
  1033. pObjectCounter = (PPERF_DATA_BLOCK)
  1034. ((LPBYTE) pThisLogCounter +
  1035. sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  1036. if (pThisCounter->pThisObject) {
  1037. RtlCopyMemory(pObjectCounter,
  1038. pThisCounter->pThisObject,
  1039. pThisCounter->pThisObject->TotalByteLength);
  1040. SystemTimeToFileTime(& pThisCounter->pThisObject->SystemTime,
  1041. & LocFileTime);
  1042. }
  1043. else {
  1044. if (TimeStamp != 0) {
  1045. LocFileTime.dwLowDateTime = LODWORD(TimeStamp);
  1046. LocFileTime.dwHighDateTime = HIDWORD(TimeStamp);
  1047. }
  1048. else {
  1049. LocFileTime = tFileTime;
  1050. }
  1051. pObjectCounter->Signature[0] = L'P';
  1052. pObjectCounter->Signature[1] = L'E';
  1053. pObjectCounter->Signature[2] = L'R';
  1054. pObjectCounter->Signature[3] = L'F';
  1055. pObjectCounter->LittleEndian = TRUE;
  1056. pObjectCounter->Version = PERF_DATA_VERSION;
  1057. pObjectCounter->Revision = PERF_DATA_REVISION;
  1058. pObjectCounter->TotalByteLength = sizeof(PERF_DATA_BLOCK);
  1059. pObjectCounter->NumObjectTypes = 1;
  1060. pObjectCounter->DefaultObject = pThisCounter->plCounterInfo.dwObjectId;
  1061. pObjectCounter->SystemNameLength = 0;
  1062. pObjectCounter->SystemNameOffset = 0;
  1063. pObjectCounter->HeaderLength = sizeof(PERF_DATA_BLOCK);
  1064. pObjectCounter->PerfTime.QuadPart = 0;
  1065. pObjectCounter->PerfFreq.QuadPart = 0;
  1066. pObjectCounter->PerfTime100nSec.QuadPart = 0;
  1067. FileTimeToSystemTime(& LocFileTime,
  1068. & pObjectCounter->SystemTime);
  1069. }
  1070. TimeStamp = MAKELONGLONG(LocFileTime.dwLowDateTime,
  1071. LocFileTime.dwHighDateTime);
  1072. }
  1073. else if (dwType == PDHIC_MULTI_INSTANCE) {
  1074. // multiple counter
  1075. //
  1076. pThisLogCounter->dwType = BINLOG_TYPE_DATA_MULTI;
  1077. pMultiCounter = (PPDHI_RAW_COUNTER_ITEM_BLOCK)
  1078. ((LPBYTE) pThisLogCounter +
  1079. sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  1080. if (pThisCounter->pThisRawItemList) {
  1081. RtlCopyMemory(pMultiCounter,
  1082. pThisCounter->pThisRawItemList,
  1083. pThisCounter->pThisRawItemList->dwLength);
  1084. }
  1085. else {
  1086. FILETIME LocFileTime;
  1087. if (TimeStamp != 0) {
  1088. LocFileTime.dwLowDateTime = LODWORD(TimeStamp);
  1089. LocFileTime.dwHighDateTime = HIDWORD(TimeStamp);
  1090. }
  1091. else {
  1092. LocFileTime = tFileTime;
  1093. }
  1094. ZeroMemory(pMultiCounter,
  1095. sizeof(PDHI_RAW_COUNTER_ITEM_BLOCK));
  1096. pMultiCounter->CStatus = PDH_CSTATUS_INVALID_DATA;
  1097. pMultiCounter->TimeStamp.dwLowDateTime =
  1098. LocFileTime.dwLowDateTime;
  1099. pMultiCounter->TimeStamp.dwHighDateTime =
  1100. LocFileTime.dwHighDateTime;
  1101. }
  1102. TimeStamp = MAKELONGLONG(pMultiCounter->TimeStamp.dwLowDateTime,
  1103. pMultiCounter->TimeStamp.dwHighDateTime);
  1104. }
  1105. else {
  1106. pThisLogCounter->dwType = BINLOG_TYPE_DATA_SINGLE;
  1107. pSingleCounter = (PPDH_RAW_COUNTER)
  1108. ((LPBYTE) pThisLogCounter +
  1109. sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  1110. RtlCopyMemory( pSingleCounter,
  1111. & pThisCounter->ThisValue,
  1112. sizeof(PDH_RAW_COUNTER));
  1113. if (pSingleCounter->CStatus != ERROR_SUCCESS) {
  1114. if (TimeStamp != 0) {
  1115. pSingleCounter->TimeStamp.dwLowDateTime =
  1116. LODWORD(TimeStamp);
  1117. pSingleCounter->TimeStamp.dwHighDateTime =
  1118. HIDWORD(TimeStamp);
  1119. }
  1120. else {
  1121. pSingleCounter->TimeStamp.dwLowDateTime =
  1122. tFileTime.dwLowDateTime;
  1123. pSingleCounter->TimeStamp.dwHighDateTime =
  1124. tFileTime.dwHighDateTime;
  1125. }
  1126. }
  1127. TimeStamp = (ULONGLONG) MAKELONGLONG(
  1128. pSingleCounter->TimeStamp.dwLowDateTime,
  1129. pSingleCounter->TimeStamp.dwHighDateTime);
  1130. }
  1131. pThisCounter = pThisCounter->next.flink; // go to next in list
  1132. } while (pThisCounter != pLog->pQuery->pCounterListHead);
  1133. if (TimeStamp == 0) {
  1134. TimeStamp = MAKELONGLONG(tFileTime.dwLowDateTime,
  1135. tFileTime.dwHighDateTime);
  1136. }
  1137. if (pdhStatus == ERROR_SUCCESS && pLogCounterBuffer) {
  1138. pLogCounterBuffer->dwType = BINLOG_TYPE_DATA;
  1139. pLogCounterBuffer->dwLength = dwBufSize;
  1140. LoggerInfo->TimeStamp = TimeStamp;
  1141. if (! LoggerInfo->bHeaderEvent) {
  1142. ULONG HeaderMofLength = 0;
  1143. PVOID HeaderMofData = NULL;
  1144. ULONG EventType;
  1145. if (LoggerInfo->LoggerInfo.LogFileMode
  1146. & EVENT_TRACE_FILE_MODE_APPEND) {
  1147. #if 0
  1148. pdhStatus = PdhiBuildEmptyBlock(pLog,
  1149. LoggerInfo->TimeStamp - 1,
  1150. & HeaderMofLength,
  1151. & HeaderMofData);
  1152. if (pdhStatus == ERROR_SUCCESS) {
  1153. pdhStatus = PdhWmiTraceEvent(pLog,
  1154. PDH_LOG_DATA_BLOCK_EVENT,
  1155. LoggerInfo->TimeStamp - 1,
  1156. HeaderMofLength,
  1157. HeaderMofData);
  1158. }
  1159. if (HeaderMofData) {
  1160. G_FREE(HeaderMofData);
  1161. }
  1162. #endif
  1163. }
  1164. else {
  1165. pdhStatus = PdhiBuildLogHeaderBlock(pLog, LoggerInfo);
  1166. }
  1167. LoggerInfo->bHeaderEvent = TRUE;
  1168. }
  1169. }
  1170. if (pdhStatus == ERROR_SUCCESS && pLogCounterBuffer) {
  1171. pdhStatus = PdhWmiTraceEvent(pLog,
  1172. PDH_LOG_DATA_BLOCK_EVENT,
  1173. TimeStamp,
  1174. dwBufSize,
  1175. (PVOID) pLogCounterBuffer);
  1176. }
  1177. if (pLogCounterBuffer != NULL) {
  1178. G_FREE(pLogCounterBuffer);
  1179. }
  1180. return pdhStatus;
  1181. }
  1182. PDH_FUNCTION
  1183. PdhiWriteWmiLogHeader (
  1184. IN PPDHI_LOG pLog,
  1185. IN LPCWSTR szUserCaption)
  1186. {
  1187. UNREFERENCED_PARAMETER (pLog);
  1188. UNREFERENCED_PARAMETER (szUserCaption);
  1189. return ERROR_SUCCESS;
  1190. }
  1191. PDH_FUNCTION
  1192. PdhiCloseWmiLog(
  1193. IN PPDHI_LOG pLog,
  1194. IN DWORD dwFlags)
  1195. {
  1196. PDH_STATUS Status = PDH_INVALID_ARGUMENT;
  1197. UNREFERENCED_PARAMETER (pLog);
  1198. UNREFERENCED_PARAMETER (dwFlags);
  1199. if (pLog->dwLogFormat & PDH_LOG_WRITE_ACCESS) {
  1200. if ((TRACEHANDLE) pLog->hLogFileHandle != (TRACEHANDLE) 0) {
  1201. PPDH_EVENT_TRACE_PROPERTIES LoggerInfo =
  1202. (PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
  1203. if (LoggerInfo == NULL) {
  1204. Status = PDH_INVALID_HANDLE;
  1205. }
  1206. else {
  1207. ULONG HeaderMofLength = 0;
  1208. PVOID HeaderMofData = NULL;
  1209. #if 0
  1210. Status = PdhiBuildEmptyBlock(pLog,
  1211. LoggerInfo->TimeStamp,
  1212. & HeaderMofLength,
  1213. & HeaderMofData);
  1214. if (Status == ERROR_SUCCESS) {
  1215. Status = PdhWmiTraceEvent(pLog,
  1216. PDH_LOG_DATA_BLOCK_EVENT,
  1217. LoggerInfo->TimeStamp + 1,
  1218. HeaderMofLength,
  1219. HeaderMofData);
  1220. }
  1221. if (HeaderMofData) {
  1222. G_FREE(HeaderMofData);
  1223. }
  1224. #endif
  1225. Status = ControlTraceW((TRACEHANDLE) pLog->hLogFileHandle,
  1226. LoggerInfo->LoggerName,
  1227. (PEVENT_TRACE_PROPERTIES) LoggerInfo,
  1228. EVENT_TRACE_CONTROL_STOP);
  1229. if (Status != ERROR_SUCCESS) {
  1230. DebugPrint((1, "StopTrace(0x%08X,%ws,%ws) fails (%d)\n",
  1231. pLog->hLogFileHandle,
  1232. LoggerInfo->LoggerName,
  1233. LoggerInfo->LogFileName,
  1234. Status,
  1235. Status));
  1236. }
  1237. if (LoggerInfo->MachineList != NULL) {
  1238. G_FREE(LoggerInfo->MachineList);
  1239. }
  1240. G_FREE(pLog->lpMappedFileBase);
  1241. pLog->lpMappedFileBase = NULL;
  1242. }
  1243. pLog->hLogFileHandle = INVALID_HANDLE_VALUE;
  1244. if (PdhTraceRegistrationHandle != (TRACEHANDLE) 0) {
  1245. Status = UnregisterTraceGuids(PdhTraceRegistrationHandle);
  1246. if (Status != ERROR_SUCCESS) {
  1247. DebugPrint((4,
  1248. "UnregisterTraceGuid(0x%08X) fails (%d,0x%08X)\n",
  1249. PdhTraceRegistrationHandle,
  1250. Status,
  1251. Status));
  1252. }
  1253. }
  1254. }
  1255. else {
  1256. Status = PDH_INVALID_HANDLE;
  1257. }
  1258. }
  1259. else if (pLog->dwLogFormat & PDH_LOG_READ_ACCESS) {
  1260. ULONG i;
  1261. DWORD dwExitCode;
  1262. PPDH_LOGGER_CONTEXT CurrentContext =
  1263. (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  1264. DWORD dwContext = GetLoggerContext(CurrentContext);
  1265. if (dwContext < ContextCount) {
  1266. Status = WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex);
  1267. if (Status == ERROR_SUCCESS) {
  1268. CurrentContext->RefCount --;
  1269. if (CurrentContext->RefCount > 0) {
  1270. RELEASE_MUTEX(hPdhContextMutex);
  1271. return ERROR_SUCCESS;
  1272. }
  1273. }
  1274. else {
  1275. return Status;
  1276. }
  1277. if (dwContext != ContextCount - 1) {
  1278. ContextTable[dwContext] = ContextTable[ContextCount - 1];
  1279. }
  1280. ContextCount --;
  1281. ContextTable[ContextCount] = NULL;
  1282. RELEASE_MUTEX(hPdhContextMutex);
  1283. if (CurrentContext->hThreadWork != NULL
  1284. && CurrentContext->hThreadWork != INVALID_HANDLE_VALUE) {
  1285. if (GetExitCodeThread(CurrentContext->hThreadWork, & dwExitCode)
  1286. && dwExitCode == STILL_ACTIVE) {
  1287. CurrentContext->LoggerState = PdhProcessTraceEnd;
  1288. SetEvent(CurrentContext->hSyncWMI);
  1289. while (CurrentContext->LoggerState != PdhProcessTraceExit) {
  1290. _sleep(1);
  1291. }
  1292. if (TerminateThread(CurrentContext->hThreadWork, 0)) {
  1293. WaitForSingleObject(CurrentContext->hThreadWork, INFINITE);
  1294. }
  1295. }
  1296. }
  1297. if (CurrentContext->hSyncWMI != NULL) {
  1298. CloseHandle(CurrentContext->hSyncWMI);
  1299. }
  1300. if (CurrentContext->hSyncPDH != NULL) {
  1301. CloseHandle(CurrentContext->hSyncPDH);
  1302. }
  1303. for (i = 0; i < CurrentContext->LoggerCount; i ++) {
  1304. if (! IsListEmpty(& CurrentContext->LogInfo[i].CounterPathList)) {
  1305. PLIST_ENTRY PathHead =
  1306. & CurrentContext->LogInfo[i].CounterPathList;
  1307. PLIST_ENTRY PathNext = PathHead->Flink;
  1308. PPDH_COUNTER_PATH pCounterPath;
  1309. while (PathHead != PathNext) {
  1310. pCounterPath = CONTAINING_RECORD(PathNext,
  1311. PDH_COUNTER_PATH,
  1312. Entry);
  1313. PathNext = PathNext->Flink;
  1314. RemoveEntryList(& pCounterPath->Entry);
  1315. G_FREE(pCounterPath->CounterPathBuffer);
  1316. G_FREE(pCounterPath);
  1317. }
  1318. }
  1319. if (! IsListEmpty(& CurrentContext->LogInfo[i].PerfMachineList)) {
  1320. PLIST_ENTRY PathHead =
  1321. & CurrentContext->LogInfo[i].PerfMachineList;
  1322. PLIST_ENTRY PathNext = PathHead->Flink;
  1323. PPDH_WMI_PERF_MACHINE pPerfMachine;
  1324. while (PathHead != PathNext) {
  1325. pPerfMachine = CONTAINING_RECORD(PathNext,
  1326. PDH_WMI_PERF_MACHINE,
  1327. Entry);
  1328. PathNext = PathNext->Flink;
  1329. RemoveEntryList(& pPerfMachine->Entry);
  1330. if (! IsListEmpty(& pPerfMachine->LogObjectList)) {
  1331. PLIST_ENTRY pHead =
  1332. & pPerfMachine->LogObjectList;
  1333. PLIST_ENTRY pNext = pHead->Flink;
  1334. PPDH_WMI_PERF_OBJECT pPerfObject;
  1335. while (pHead != pNext) {
  1336. pPerfObject = CONTAINING_RECORD(
  1337. pNext, PDH_WMI_PERF_OBJECT, Entry);
  1338. pNext = pNext->Flink;
  1339. RemoveEntryList(& pPerfObject->Entry);
  1340. G_FREE(pPerfObject->ptrBuffer);
  1341. G_FREE(pPerfObject);
  1342. }
  1343. }
  1344. G_FREE(pPerfMachine->pszBuffer);
  1345. G_FREE(pPerfMachine->ptrStrAry);
  1346. G_FREE(pPerfMachine);
  1347. }
  1348. }
  1349. if (CurrentContext->LogInfo[i].DataBlock) {
  1350. G_FREE(CurrentContext->LogInfo[i].DataBlock);
  1351. }
  1352. }
  1353. if (CurrentContext->tmpBuffer) {
  1354. G_FREE(CurrentContext->tmpBuffer);
  1355. }
  1356. if (CurrentContext->CounterPathBuffer) {
  1357. G_FREE(CurrentContext->CounterPathBuffer);
  1358. }
  1359. G_FREE(pLog->lpMappedFileBase);
  1360. pLog->lpMappedFileBase = NULL;
  1361. pLog->pLastRecordRead = NULL;
  1362. Status = ERROR_SUCCESS;
  1363. }
  1364. else {
  1365. Status = PDH_INVALID_HANDLE;
  1366. }
  1367. }
  1368. return Status;
  1369. }
  1370. PDH_FUNCTION
  1371. PdhiAddWmiLogFileGuid(
  1372. PPDH_LOGGER_CONTEXT CurrentContext,
  1373. LPGUID pGuid)
  1374. {
  1375. PDH_STATUS Status = ERROR_SUCCESS;
  1376. ULONG i;
  1377. for (i = 0; i < CurrentContext->LoggerCount; i ++) {
  1378. if (IsEqualGUID(pGuid, & CurrentContext->LogInfo[i].LogFileGuid))
  1379. break;
  1380. }
  1381. if (i == CurrentContext->LoggerCount) {
  1382. CurrentContext->LogInfo[i].LogFileGuid = * pGuid;
  1383. CurrentContext->LoggerCount ++;
  1384. if (CurrentContext->LoggerCount > CurrentContext->LogFileCount) {
  1385. DebugPrint((4, "LogFileCount(%d) LoggerCount(%d) mismatch\n",
  1386. CurrentContext->LoggerCount,
  1387. CurrentContext->LogFileCount));
  1388. }
  1389. }
  1390. return Status;
  1391. }
  1392. ULONG
  1393. PdhiFindLogFileGuid(
  1394. PPDH_LOGGER_CONTEXT CurrentContext,
  1395. LPGUID pGuid)
  1396. {
  1397. ULONG i;
  1398. for (i = 0; i < CurrentContext->LoggerCount; i ++) {
  1399. if (IsEqualGUID(pGuid, & CurrentContext->LogInfo[i].LogFileGuid))
  1400. break;
  1401. }
  1402. return i;
  1403. }
  1404. ULONGLONG
  1405. PdhWmiGetDataBlockTimeStamp(
  1406. PPDH_LOGGER_CONTEXT CurrentContext,
  1407. PEVENT_TRACE pEvent,
  1408. BOOLEAN bFirstRun)
  1409. {
  1410. PVOID pDataBlock = pEvent->MofData;
  1411. ULONGLONG TimeStamp = pEvent->Header.TimeStamp.QuadPart;
  1412. if (TimeStamp > 0) {
  1413. LPGUID pLogFileGuid = (LPGUID) pDataBlock;
  1414. ULONG i;
  1415. for (i = 0; i < CurrentContext->LoggerCount; i ++) {
  1416. if (IsEqualGUID( pLogFileGuid,
  1417. & CurrentContext->LogInfo[i].LogFileGuid)) {
  1418. break;
  1419. }
  1420. }
  1421. if (i < CurrentContext->LoggerCount) {
  1422. if (bFirstRun) {
  1423. if ( pEvent->Header.Class.Version < PDH_EVENT_VERSION
  1424. || CurrentContext->LogInfo[i].TimePrev < TimeStamp) {
  1425. CurrentContext->LogInfo[i].ValidEntries ++;
  1426. }
  1427. if (CurrentContext->LogInfo[i].TimeStart == 0) {
  1428. CurrentContext->LogInfo[i].TimeStart = TimeStamp;
  1429. CurrentContext->LogInfo[i].TimePrev = TimeStamp;
  1430. }
  1431. else {
  1432. // no need to update StartTime.
  1433. // Always assume the first trace event has the StartTime.
  1434. //
  1435. if (CurrentContext->LogInfo[i].TimeEnd < TimeStamp) {
  1436. CurrentContext->LogInfo[i].TimeEnd = TimeStamp;
  1437. }
  1438. if ( (TimeStamp - CurrentContext->LogInfo[i].TimePrev)
  1439. < (CurrentContext->LogInfo[i].TimeFreq)) {
  1440. CurrentContext->LogInfo[i].TimeFreq =
  1441. TimeStamp - CurrentContext->LogInfo[i].TimePrev;
  1442. }
  1443. CurrentContext->LogInfo[i].TimePrev = TimeStamp;
  1444. }
  1445. }
  1446. else {
  1447. assert(CurrentContext->LogInfo[i].TimePrev <= TimeStamp);
  1448. assert(CurrentContext->LogInfo[i].TimeStart <= TimeStamp);
  1449. assert(CurrentContext->LogInfo[i].TimeEnd >= TimeStamp);
  1450. CurrentContext->LogInfo[i].TimePrev = TimeStamp;
  1451. }
  1452. }
  1453. }
  1454. return TimeStamp;
  1455. }
  1456. PDH_FUNCTION
  1457. PdhiWmiComputeCounterBlocks(
  1458. PPDH_LOGGER_CONTEXT CurrentContext,
  1459. PEVENT_TRACE pEvent)
  1460. {
  1461. LPGUID pLogFileGuid;
  1462. PDH_STATUS Status = ERROR_SUCCESS;
  1463. PVOID pDataBlock;
  1464. ULONG i;
  1465. ULONG ulNumDataBlocks;
  1466. ULONG ulDataBlocksCopied;
  1467. ULONG ulBufferSize;
  1468. ULONG ulBlockIndex;
  1469. BOOLEAN bOldEvent;
  1470. if (CurrentContext == NULL || pEvent == NULL) {
  1471. return PDH_INVALID_DATA;
  1472. }
  1473. bOldEvent = (pEvent->Header.Class.Version < PDH_EVENT_VERSION);
  1474. pLogFileGuid = (LPGUID) pEvent->MofData;
  1475. if (pLogFileGuid == NULL) {
  1476. return PDH_INVALID_DATA;
  1477. }
  1478. for (i = 0; i < CurrentContext->LoggerCount; i ++) {
  1479. if (IsEqualGUID(pLogFileGuid,
  1480. & CurrentContext->LogInfo[i].LogFileGuid)) {
  1481. break;
  1482. }
  1483. }
  1484. if (i == CurrentContext->LoggerCount) {
  1485. return PDH_INVALID_DATA;
  1486. }
  1487. ulNumDataBlocks = CurrentContext->LogInfo[i].ulNumDataBlocks;
  1488. ulDataBlocksCopied = CurrentContext->LogInfo[i].ulDataBlocksCopied;
  1489. if (ulNumDataBlocks > 0 && ulNumDataBlocks == ulDataBlocksCopied) {
  1490. if (CurrentContext->LogInfo[i].DataBlock != NULL) {
  1491. G_FREE(CurrentContext->LogInfo[i].DataBlock);
  1492. CurrentContext->LogInfo[i].DataBlock = NULL;
  1493. }
  1494. goto Cleanup;
  1495. }
  1496. if (ulNumDataBlocks == 0) {
  1497. if (bOldEvent) {
  1498. ulNumDataBlocks = 1;
  1499. ulBufferSize = pEvent->MofLength;
  1500. }
  1501. else {
  1502. ulNumDataBlocks = * (DWORD *) ( ((LPBYTE) pEvent->MofData)
  1503. + sizeof(GUID) + sizeof(DWORD));
  1504. ulBufferSize = ulNumDataBlocks * PDH_BLOCK_BUFFER_SIZE
  1505. + sizeof(GUID);
  1506. }
  1507. if (CurrentContext->LogInfo[i].DataBlock != NULL) {
  1508. G_FREE(CurrentContext->LogInfo[i].DataBlock);
  1509. CurrentContext->LogInfo[i].DataBlock = NULL;
  1510. }
  1511. CurrentContext->LogInfo[i].DataBlock = G_ALLOC(ulBufferSize);
  1512. if (CurrentContext->LogInfo[i].DataBlock == NULL) {
  1513. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1514. goto Cleanup;
  1515. }
  1516. CurrentContext->LogInfo[i].ulNumDataBlocks = ulNumDataBlocks;
  1517. CurrentContext->LogInfo[i].ulDataBlocksCopied = 0;
  1518. CurrentContext->LogInfo[i].DataBlockAlloc = ulBufferSize;
  1519. }
  1520. if (bOldEvent) {
  1521. RtlCopyMemory(CurrentContext->LogInfo[i].DataBlock,
  1522. pEvent->MofData,
  1523. pEvent->MofLength);
  1524. }
  1525. else {
  1526. ulBlockIndex = * (DWORD *) (((LPBYTE) pEvent->MofData) + sizeof(GUID));
  1527. pDataBlock = (PVOID)
  1528. ( ((LPBYTE) CurrentContext->LogInfo[i].DataBlock)
  1529. + sizeof(GUID)
  1530. + PDH_BLOCK_BUFFER_SIZE * (ulBlockIndex - 1));
  1531. RtlCopyMemory(pDataBlock,
  1532. (PVOID) (((LPBYTE) pEvent->MofData)
  1533. + sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD)),
  1534. pEvent->MofLength - sizeof(GUID)
  1535. - sizeof(DWORD) - sizeof(DWORD));
  1536. }
  1537. CurrentContext->LogInfo[i].ulDataBlocksCopied ++;
  1538. if (CurrentContext->LogInfo[i].ulDataBlocksCopied >=
  1539. CurrentContext->LogInfo[i].ulNumDataBlocks) {
  1540. DWORD dwTotal;
  1541. DWORD dwCurrent;
  1542. DWORD dwCounters = 0;
  1543. BOOLEAN bValidBlock = TRUE;
  1544. PPDHI_BINARY_LOG_RECORD_HEADER pCurrent;
  1545. PPDHI_BINARY_LOG_RECORD_HEADER pMasterRec;
  1546. pDataBlock = CurrentContext->LogInfo[i].DataBlock;
  1547. pMasterRec = (PPDHI_BINARY_LOG_RECORD_HEADER)
  1548. ((LPBYTE) pDataBlock + sizeof(GUID));
  1549. dwTotal = pMasterRec->dwLength;
  1550. pCurrent = pMasterRec;
  1551. dwCurrent = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  1552. while (bValidBlock && dwCurrent < dwTotal) {
  1553. pCurrent = (PPDHI_BINARY_LOG_RECORD_HEADER)
  1554. ((LPBYTE) pMasterRec + dwCurrent);
  1555. if (LOWORD(pCurrent->dwType) != BINLOG_START_WORD) {
  1556. bValidBlock = FALSE;
  1557. }
  1558. else {
  1559. dwCurrent += pCurrent->dwLength;
  1560. dwCounters ++;
  1561. }
  1562. }
  1563. if (bValidBlock) {
  1564. CurrentContext->LogInfo[i].ulCounters += dwCounters;
  1565. }
  1566. }
  1567. Cleanup:
  1568. return Status;
  1569. }
  1570. PDH_FUNCTION
  1571. PdhiAddCounterPathRecord(
  1572. PPDH_LOGGER_CONTEXT CurrentContext,
  1573. PEVENT_TRACE pEvent,
  1574. LPGUID pLogFileGuid,
  1575. ULONG BufferSize,
  1576. PVOID pBuffer,
  1577. ULONGLONG TimeStamp,
  1578. DWORD dwIndex,
  1579. DWORD dwCount,
  1580. BOOLEAN * pNeedUpdate)
  1581. {
  1582. PPDH_COUNTER_PATH pNewCounter;
  1583. ULONG i;
  1584. PVOID pCounterPath;
  1585. i = PdhiFindLogFileGuid(CurrentContext, pLogFileGuid);
  1586. if (i == CurrentContext->LoggerCount) {
  1587. return PDH_INVALID_DATA;
  1588. }
  1589. if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
  1590. if ( CurrentContext->LogInfo[i].DataBlock
  1591. && CurrentContext->LogInfo[i].ulNumDataBlocks != dwCount) {
  1592. G_FREE(CurrentContext->LogInfo[i].DataBlock);
  1593. CurrentContext->LogInfo[i].DataBlock = NULL;
  1594. }
  1595. if (CurrentContext->LogInfo[i].DataBlock == NULL) {
  1596. CurrentContext->LogInfo[i].DataBlock =
  1597. G_ALLOC(PDH_BLOCK_BUFFER_SIZE * dwCount);
  1598. if (CurrentContext->LogInfo[i].DataBlock == NULL) {
  1599. return PDH_MEMORY_ALLOCATION_FAILURE;
  1600. }
  1601. CurrentContext->LogInfo[i].DataBlockAlloc = PDH_BLOCK_BUFFER_SIZE * dwCount;
  1602. CurrentContext->LogInfo[i].DataBlockSize = 0;
  1603. CurrentContext->LogInfo[i].ulNumDataBlocks = dwCount;
  1604. CurrentContext->LogInfo[i].ulDataBlocksCopied = 0;
  1605. }
  1606. pCounterPath = (PVOID) ( ((LPBYTE) CurrentContext->LogInfo[i].DataBlock)
  1607. + (dwIndex - 1) * PDH_BLOCK_BUFFER_SIZE);
  1608. if (BufferSize > PDH_BLOCK_BUFFER_SIZE) {
  1609. BufferSize = PDH_BLOCK_BUFFER_SIZE;
  1610. }
  1611. RtlCopyMemory(pCounterPath, pBuffer, BufferSize);
  1612. CurrentContext->LogInfo[i].ulDataBlocksCopied ++;
  1613. CurrentContext->LogInfo[i].DataBlockSize += BufferSize;
  1614. if ( CurrentContext->LogInfo[i].ulDataBlocksCopied
  1615. < CurrentContext->LogInfo[i].ulNumDataBlocks) {
  1616. return ERROR_SUCCESS;
  1617. }
  1618. pCounterPath = (PVOID) (((LPBYTE) CurrentContext->LogInfo[i].DataBlock)
  1619. + sizeof(PDH_WMI_LOG_INFO));
  1620. BufferSize = CurrentContext->LogInfo[i].DataBlockSize
  1621. - sizeof(PDH_WMI_LOG_INFO);
  1622. }
  1623. if (! IsListEmpty(& CurrentContext->LogInfo[i].CounterPathList)) {
  1624. PLIST_ENTRY PathHead = & CurrentContext->LogInfo[i].CounterPathList;
  1625. PLIST_ENTRY PathNext = PathHead->Flink;
  1626. while (PathHead != PathNext) {
  1627. pNewCounter = CONTAINING_RECORD(PathNext,
  1628. PDH_COUNTER_PATH,
  1629. Entry);
  1630. PathNext = PathNext->Flink;
  1631. if (TimeStamp == pNewCounter->TimeStamp) {
  1632. // CounterPath record is already in the list
  1633. //
  1634. return ERROR_SUCCESS;
  1635. }
  1636. }
  1637. }
  1638. pNewCounter = G_ALLOC(sizeof(PDH_COUNTER_PATH));
  1639. if (pNewCounter == NULL) {
  1640. return PDH_MEMORY_ALLOCATION_FAILURE;
  1641. }
  1642. pNewCounter->TimeStamp = TimeStamp;
  1643. pNewCounter->CounterPathBuffer = G_ALLOC(BufferSize);
  1644. if (pNewCounter->CounterPathBuffer == NULL) {
  1645. G_FREE(pNewCounter);
  1646. return PDH_MEMORY_ALLOCATION_FAILURE;
  1647. }
  1648. pNewCounter->CounterPathSize = BufferSize;
  1649. if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
  1650. RtlCopyMemory(pNewCounter->CounterPathBuffer, pCounterPath, BufferSize);
  1651. }
  1652. else {
  1653. RtlCopyMemory(pNewCounter->CounterPathBuffer, pBuffer, BufferSize);
  1654. }
  1655. pNewCounter->CounterCount = 0;
  1656. {
  1657. PPDHI_LOG_COUNTER_PATH pPath = pNewCounter->CounterPathBuffer;
  1658. ULONG dwProcessed = 0;
  1659. while (dwProcessed < BufferSize) {
  1660. pNewCounter->CounterCount ++;
  1661. dwProcessed += pPath->dwLength;
  1662. pPath = (PPDHI_LOG_COUNTER_PATH)
  1663. (((LPBYTE) pPath) + pPath->dwLength);
  1664. }
  1665. }
  1666. InsertTailList(& CurrentContext->LogInfo[i].CounterPathList,
  1667. & pNewCounter->Entry);
  1668. * pNeedUpdate = TRUE;
  1669. if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
  1670. G_FREE(CurrentContext->LogInfo[i].DataBlock);
  1671. CurrentContext->LogInfo[i].DataBlock = NULL;
  1672. CurrentContext->LogInfo[i].DataBlockAlloc = 0;
  1673. CurrentContext->LogInfo[i].DataBlockSize = 0;
  1674. CurrentContext->LogInfo[i].ulNumDataBlocks = 0;
  1675. CurrentContext->LogInfo[i].ulDataBlocksCopied = 0;
  1676. }
  1677. return ERROR_SUCCESS;
  1678. }
  1679. PDH_FUNCTION
  1680. PdhiAddPerfMachine(
  1681. IN PPDH_LOGGER_CONTEXT CurrentContext,
  1682. IN PVOID pMofDataBlock,
  1683. IN DWORD dwMofLength)
  1684. {
  1685. PDH_STATUS Status = ERROR_SUCCESS;
  1686. LPGUID pLogFileGuid = (LPGUID) pMofDataBlock;
  1687. LPWSTR pszMachineName = (LPWSTR) (((LPBYTE) pMofDataBlock)
  1688. + sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD));
  1689. DWORD dwBufSize = dwMofLength
  1690. - sizeof(GUID) - sizeof(DWORD) - sizeof(DWORD);
  1691. ULONG i;
  1692. LPWSTR pszTmpBuffer;
  1693. DWORD dwThisId;
  1694. DWORD dwBufUsed;
  1695. PPDH_WMI_PERF_MACHINE pCurrentMachine = NULL;
  1696. BOOLEAN bNewMachine = TRUE;
  1697. i = PdhiFindLogFileGuid(CurrentContext, pLogFileGuid);
  1698. if (i == CurrentContext->LoggerCount) {
  1699. Status = PDH_INVALID_DATA;
  1700. goto Cleanup;
  1701. }
  1702. if (! IsListEmpty(& CurrentContext->LogInfo[i].PerfMachineList)) {
  1703. PLIST_ENTRY pHead = & CurrentContext->LogInfo[i].PerfMachineList;
  1704. PLIST_ENTRY pNext = pHead->Flink;
  1705. while (pNext != pHead) {
  1706. PPDH_WMI_PERF_MACHINE pMachine =
  1707. CONTAINING_RECORD(pNext, PDH_WMI_PERF_MACHINE, Entry);
  1708. if (lstrcmpiW(pMachine->pszBuffer, pszMachineName) == 0) {
  1709. pCurrentMachine = pMachine;
  1710. bNewMachine = FALSE;
  1711. break;
  1712. }
  1713. pNext = pNext->Flink;
  1714. }
  1715. }
  1716. if (bNewMachine) {
  1717. pCurrentMachine = G_ALLOC(sizeof(PDH_WMI_PERF_MACHINE));
  1718. if (pCurrentMachine == NULL) {
  1719. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1720. goto Cleanup;
  1721. }
  1722. InsertTailList(& CurrentContext->LogInfo[i].PerfMachineList,
  1723. & pCurrentMachine->Entry);
  1724. pCurrentMachine->pszBuffer = G_ALLOC(dwBufSize);
  1725. if (pCurrentMachine->pszBuffer == NULL) {
  1726. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1727. goto Cleanup;
  1728. }
  1729. RtlCopyMemory(pCurrentMachine->pszBuffer, pszMachineName, dwBufSize);
  1730. pCurrentMachine->dwBufSize = dwBufSize;
  1731. InitializeListHead(& pCurrentMachine->LogObjectList);
  1732. }
  1733. else {
  1734. pszTmpBuffer = pCurrentMachine->pszBuffer;
  1735. dwBufSize -= (sizeof(WCHAR) * (lstrlenW(pszMachineName) + 1));
  1736. pszMachineName += (lstrlenW(pszMachineName) + 1);
  1737. pCurrentMachine->pszBuffer = G_ALLOC(
  1738. pCurrentMachine->dwBufSize + dwBufSize);
  1739. if (pCurrentMachine->pszBuffer == NULL) {
  1740. pCurrentMachine->pszBuffer = pszTmpBuffer;
  1741. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1742. goto Cleanup;
  1743. }
  1744. RtlCopyMemory(pCurrentMachine->pszBuffer,
  1745. pszTmpBuffer,
  1746. pCurrentMachine->dwBufSize);
  1747. G_FREE(pszTmpBuffer);
  1748. pszTmpBuffer = (LPWSTR)
  1749. ( ((LPBYTE) pCurrentMachine->pszBuffer)
  1750. + pCurrentMachine->dwBufSize);
  1751. RtlCopyMemory(pszTmpBuffer, pszMachineName, dwBufSize);
  1752. pCurrentMachine->dwBufSize += dwBufSize;
  1753. }
  1754. dwBufSize = pCurrentMachine->dwBufSize;
  1755. pCurrentMachine->dwLastId = 0;
  1756. i = lstrlenW(pCurrentMachine->pszBuffer) + 1;
  1757. pszTmpBuffer = pCurrentMachine->pszBuffer + i;
  1758. dwBufUsed = sizeof(WCHAR) * i;
  1759. while ((dwBufUsed < dwBufSize) && (* pszTmpBuffer)) {
  1760. do {
  1761. dwThisId = wcstoul(pszTmpBuffer, NULL, 10);
  1762. if (dwThisId > pCurrentMachine->dwLastId) {
  1763. pCurrentMachine->dwLastId = dwThisId;
  1764. }
  1765. i = lstrlenW(pszTmpBuffer) + 1;
  1766. dwBufUsed += (sizeof(WCHAR) * i);
  1767. if (dwBufUsed < dwBufSize) {
  1768. pszTmpBuffer += i;
  1769. }
  1770. }
  1771. while ((dwThisId == 0) && (* pszTmpBuffer)
  1772. && dwBufUsed < dwBufSize);
  1773. i = lstrlenW(pszTmpBuffer) + 1;
  1774. dwBufUsed += (sizeof(WCHAR) * i);
  1775. if ((* pszTmpBuffer) && (dwBufUsed < dwBufSize)) {
  1776. pszTmpBuffer += i;
  1777. }
  1778. }
  1779. if (pCurrentMachine->dwLastId == 0) {
  1780. Status = PDH_CANNOT_READ_NAME_STRINGS;
  1781. goto Cleanup;
  1782. }
  1783. if (! bNewMachine) {
  1784. G_FREE(pCurrentMachine->ptrStrAry);
  1785. pCurrentMachine->ptrStrAry = NULL;
  1786. }
  1787. pCurrentMachine->ptrStrAry =
  1788. G_ALLOC(sizeof(LPWSTR) * (pCurrentMachine->dwLastId + 1));
  1789. if (pCurrentMachine->ptrStrAry == NULL) {
  1790. Status = PDH_CANNOT_READ_NAME_STRINGS;
  1791. goto Cleanup;
  1792. }
  1793. i = lstrlenW(pCurrentMachine->pszBuffer) + 1;
  1794. pszTmpBuffer = pCurrentMachine->pszBuffer + i;
  1795. dwBufUsed = sizeof(WCHAR) * i;
  1796. while ((dwBufUsed < dwBufSize) && (* pszTmpBuffer)) {
  1797. do {
  1798. dwThisId = wcstoul(pszTmpBuffer, NULL, 10);
  1799. i = lstrlenW(pszTmpBuffer) + 1;
  1800. dwBufUsed += (sizeof(WCHAR) * i);
  1801. if (dwBufUsed < dwBufSize) {
  1802. pszTmpBuffer += i;
  1803. }
  1804. }
  1805. while ((dwThisId == 0) && (* pszTmpBuffer)
  1806. && dwBufUsed < dwBufSize);
  1807. if (dwThisId > 0 && dwThisId <= pCurrentMachine->dwLastId) {
  1808. pCurrentMachine->ptrStrAry[dwThisId] = pszTmpBuffer;
  1809. }
  1810. i = lstrlenW(pszTmpBuffer) + 1;
  1811. dwBufUsed += (sizeof(WCHAR) * i);
  1812. if ((* pszTmpBuffer) && (dwBufUsed < dwBufSize)) {
  1813. pszTmpBuffer += i;
  1814. }
  1815. }
  1816. Cleanup:
  1817. if (Status != ERROR_SUCCESS) {
  1818. if (bNewMachine) {
  1819. if (pCurrentMachine != NULL) {
  1820. if (pCurrentMachine->pszBuffer != NULL) {
  1821. G_FREE(pCurrentMachine->pszBuffer);
  1822. }
  1823. RemoveEntryList(& pCurrentMachine->Entry);
  1824. G_FREE(pCurrentMachine);
  1825. }
  1826. }
  1827. else if (pCurrentMachine != NULL) {
  1828. if (pCurrentMachine->pszBuffer != NULL) {
  1829. G_FREE(pCurrentMachine->pszBuffer);
  1830. }
  1831. RemoveEntryList(& pCurrentMachine->Entry);
  1832. G_FREE(pCurrentMachine);
  1833. }
  1834. }
  1835. return Status;
  1836. }
  1837. PDH_FUNCTION
  1838. PdhiGetCounterPathRecord(
  1839. IN PPDH_LOGGER_CONTEXT CurrentContext,
  1840. IN PVOID pRecord,
  1841. IN ULONG dwMaxSize)
  1842. {
  1843. PDH_STATUS Status = ERROR_SUCCESS;
  1844. DWORD CurrentSize = sizeof(PDHI_BINARY_LOG_HEADER_RECORD);
  1845. if (CurrentContext->bCounterPathChanged) {
  1846. PPDHI_BINARY_LOG_HEADER_RECORD pBinLogHeader = NULL;
  1847. PVOID pCounterPath;
  1848. ULONG i;
  1849. if (CurrentContext->CounterPathBuffer) {
  1850. G_FREE(CurrentContext->CounterPathBuffer);
  1851. }
  1852. CurrentContext->CounterPathBuffer = G_ALLOC(CurrentSize);
  1853. if (CurrentContext->CounterPathBuffer == NULL) {
  1854. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1855. goto Cleanup;
  1856. }
  1857. for (i = 0; i < CurrentContext->LoggerCount; i ++) {
  1858. if (! IsListEmpty(& CurrentContext->LogInfo[i].CounterPathList)) {
  1859. PLIST_ENTRY PathHead =
  1860. & CurrentContext->LogInfo[i].CounterPathList;
  1861. PLIST_ENTRY PathNext = PathHead->Flink;
  1862. PPDH_COUNTER_PATH pCurrentPath;
  1863. while (Status == ERROR_SUCCESS && PathNext != PathHead) {
  1864. PVOID ptrTemp;
  1865. pCurrentPath = CONTAINING_RECORD(PathNext,
  1866. PDH_COUNTER_PATH,
  1867. Entry);
  1868. PathNext = PathNext->Flink;
  1869. ptrTemp = CurrentContext->CounterPathBuffer;
  1870. CurrentContext->CounterPathBuffer = G_REALLOC(
  1871. ptrTemp, CurrentSize + pCurrentPath->CounterPathSize);
  1872. if (CurrentContext->CounterPathBuffer == NULL) {
  1873. G_FREE(ptrTemp);
  1874. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1875. goto Cleanup;
  1876. }
  1877. pCounterPath = (PVOID) (((PUCHAR)
  1878. CurrentContext->CounterPathBuffer) + CurrentSize);
  1879. RtlCopyMemory(pCounterPath,
  1880. pCurrentPath->CounterPathBuffer,
  1881. pCurrentPath->CounterPathSize);
  1882. CurrentSize += pCurrentPath->CounterPathSize;
  1883. }
  1884. }
  1885. }
  1886. pBinLogHeader = (PPDHI_BINARY_LOG_HEADER_RECORD)
  1887. CurrentContext->CounterPathBuffer;
  1888. RtlZeroMemory(pBinLogHeader, sizeof(PDHI_BINARY_LOG_HEADER_RECORD));
  1889. pBinLogHeader->RecHeader.dwType = BINLOG_TYPE_CATALOG_LIST;
  1890. pBinLogHeader->Info.dwLogVersion = BINLOG_VERSION;
  1891. pBinLogHeader->RecHeader.dwLength = CurrentSize;
  1892. CurrentContext->bCounterPathChanged = FALSE;
  1893. }
  1894. else if (CurrentContext->CounterPathBuffer == NULL) {
  1895. return PDH_ENTRY_NOT_IN_LOG_FILE;
  1896. }
  1897. else {
  1898. CurrentSize = ((PPDHI_BINARY_LOG_HEADER_RECORD)
  1899. CurrentContext->CounterPathBuffer)->RecHeader.dwLength;
  1900. }
  1901. if (pRecord != NULL) {
  1902. if (dwMaxSize < CurrentSize) {
  1903. CurrentSize = dwMaxSize;
  1904. Status = PDH_MORE_DATA;
  1905. }
  1906. RtlCopyMemory(pRecord, CurrentContext->CounterPathBuffer, CurrentSize);
  1907. }
  1908. Cleanup:
  1909. return Status;
  1910. }
  1911. ULONG
  1912. WINAPI
  1913. PdhWmiFirstBufferCallback(
  1914. PEVENT_TRACE_LOGFILEW LogFile)
  1915. {
  1916. UNREFERENCED_PARAMETER(LogFile);
  1917. return TRUE;
  1918. }
  1919. ULONG
  1920. WINAPI
  1921. PdhWmiBufferCallback(
  1922. PEVENT_TRACE_LOGFILEW LogFile)
  1923. {
  1924. ULONG bResult;
  1925. PPDH_LOGGER_CONTEXT CurrentContext;
  1926. UNREFERENCED_PARAMETER(LogFile);
  1927. CurrentContext = GetCurrentContext();
  1928. bResult = (CurrentContext && CurrentContext->LoggerState == PdhProcessTraceNormal)
  1929. ? (TRUE) : (FALSE);
  1930. return bResult;
  1931. }
  1932. void
  1933. WINAPI
  1934. PdhWmiFirstEventCallback(
  1935. PEVENT_TRACE pEvent)
  1936. {
  1937. DWORD dwMofHeader;
  1938. DWORD dwCurrentBlock;
  1939. DWORD dwTotalBlocks;
  1940. PPDH_LOGGER_CONTEXT CurrentContext;
  1941. CurrentContext = GetCurrentContext();
  1942. if (pEvent == NULL) {
  1943. goto Cleanup;
  1944. }
  1945. else if (IsEqualGUID(& pEvent->Header.Guid, & EventTraceGuid)) {
  1946. goto Cleanup;
  1947. }
  1948. else if (! IsEqualGUID(& pEvent->Header.Guid, & PdhTransactionGuid)) {
  1949. goto Cleanup;
  1950. }
  1951. else if (CurrentContext == NULL) {
  1952. goto Cleanup;
  1953. }
  1954. dwMofHeader = (pEvent->Header.Class.Version >= PDH_EVENT_VERSION)
  1955. ? (sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD))
  1956. : (sizeof(GUID));
  1957. switch (pEvent->Header.Class.Type) {
  1958. case PDH_LOG_HEADER_EVENT:
  1959. assert(pEvent->MofLength >= sizeof(PDH_WMI_LOG_INFO) + sizeof(GUID));
  1960. PdhiAddWmiLogFileGuid(CurrentContext, (LPGUID) pEvent->MofData);
  1961. if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
  1962. dwCurrentBlock = * (DWORD *)
  1963. (((LPBYTE) pEvent->MofData) + sizeof(GUID));
  1964. dwTotalBlocks = * (DWORD *)
  1965. (((LPBYTE) pEvent->MofData) + sizeof(GUID) + sizeof(DWORD));
  1966. PdhiAddCounterPathRecord(
  1967. CurrentContext,
  1968. pEvent,
  1969. (LPGUID) pEvent->MofData,
  1970. pEvent->MofLength - dwMofHeader,
  1971. (PVOID) (((PUCHAR) pEvent->MofData) + dwMofHeader),
  1972. pEvent->Header.TimeStamp.QuadPart,
  1973. dwCurrentBlock,
  1974. dwTotalBlocks,
  1975. & CurrentContext->bCounterPathChanged);
  1976. }
  1977. else {
  1978. dwCurrentBlock = dwTotalBlocks = 1;
  1979. PdhiAddCounterPathRecord(
  1980. CurrentContext,
  1981. pEvent,
  1982. (LPGUID) pEvent->MofData,
  1983. pEvent->MofLength - sizeof(GUID) - sizeof(PDH_WMI_LOG_INFO),
  1984. (PVOID) (((PUCHAR) pEvent->MofData)
  1985. + sizeof(GUID) + sizeof(PDH_WMI_LOG_INFO)),
  1986. pEvent->Header.TimeStamp.QuadPart,
  1987. dwCurrentBlock,
  1988. dwTotalBlocks,
  1989. & CurrentContext->bCounterPathChanged);
  1990. }
  1991. break;
  1992. case PDH_LOG_DATA_BLOCK_EVENT:
  1993. PdhWmiGetDataBlockTimeStamp(CurrentContext, pEvent, TRUE);
  1994. PdhiWmiComputeCounterBlocks(CurrentContext, pEvent);
  1995. break;
  1996. case PDH_LOG_COUNTER_STRING_EVENT:
  1997. PdhiAddWmiLogFileGuid(CurrentContext, (LPGUID) pEvent->MofData);
  1998. PdhiAddPerfMachine(CurrentContext, pEvent->MofData, pEvent->MofLength);
  1999. break;
  2000. default:
  2001. DebugPrint((4, "PdhWmiFirstEventCallback(), unknown EventType %d\n",
  2002. pEvent->Header.Class.Type));
  2003. break;
  2004. }
  2005. Cleanup:
  2006. return;
  2007. }
  2008. void
  2009. WINAPI
  2010. PdhWmiEventCallback(
  2011. PEVENT_TRACE pEvent)
  2012. {
  2013. LPGUID pLogFileGuid;
  2014. ULONG iLogFile;
  2015. BOOLEAN bNotifyPDH = FALSE;
  2016. ULONGLONG EventTime = 0;
  2017. ULONGLONG EventTimePrev = 0;
  2018. DWORD dwNumDataBlocks = 0;
  2019. DWORD dwBlockIndex = 0;
  2020. DWORD dwBufferSize = 0;
  2021. PPDH_LOGGER_CONTEXT CurrentContext = GetCurrentContext();
  2022. if (CurrentContext == NULL) {
  2023. goto Cleanup;
  2024. }
  2025. if (pEvent == NULL) {
  2026. DebugPrint((4, "PdhWmiEventCallback() with NULL PEVENT_TRACE\n"));
  2027. goto Cleanup;
  2028. }
  2029. else if (IsEqualGUID(& pEvent->Header.Guid, & EventTraceGuid)) {
  2030. goto Cleanup;
  2031. }
  2032. else if ((CurrentContext->LoggerState != PdhProcessTraceNormal) ||
  2033. (! IsEqualGUID(& pEvent->Header.Guid, & PdhTransactionGuid))) {
  2034. goto Cleanup;
  2035. }
  2036. switch (pEvent->Header.Class.Type) {
  2037. case PDH_LOG_HEADER_EVENT:
  2038. case PDH_LOG_COUNTER_STRING_EVENT:
  2039. // counter path information has been collected during the first run
  2040. //
  2041. break;
  2042. case PDH_LOG_DATA_BLOCK_EVENT:
  2043. pLogFileGuid = (LPGUID) pEvent->MofData;
  2044. iLogFile = PdhiFindLogFileGuid(CurrentContext, pLogFileGuid);
  2045. if (iLogFile >= CurrentContext->LoggerCount) {
  2046. break;
  2047. }
  2048. EventTimePrev = CurrentContext->LogInfo[iLogFile].TimePrev;
  2049. EventTime = PdhWmiGetDataBlockTimeStamp(CurrentContext, pEvent, FALSE);
  2050. if (EventTime == 0 || EventTimePrev > EventTime) {
  2051. break;
  2052. }
  2053. if ( pEvent->Header.Class.Version < PDH_EVENT_VERSION
  2054. || EventTimePrev < EventTime) {
  2055. dwNumDataBlocks = * (DWORD *) ( ((LPBYTE) pEvent->MofData)
  2056. + sizeof(GUID) + sizeof(DWORD));
  2057. dwBufferSize = (pEvent->Header.Class.Version >= PDH_EVENT_VERSION)
  2058. ? (dwNumDataBlocks * PDH_BLOCK_BUFFER_SIZE + sizeof(GUID))
  2059. : (pEvent->MofLength);
  2060. if (CurrentContext->LogInfo[iLogFile].DataBlock == NULL) {
  2061. CurrentContext->LogInfo[iLogFile].DataBlock = G_ALLOC(dwBufferSize);
  2062. }
  2063. else if ( CurrentContext->LogInfo[iLogFile].DataBlockAlloc
  2064. < dwBufferSize) {
  2065. PVOID ptrTemp = CurrentContext->LogInfo[iLogFile].DataBlock;
  2066. CurrentContext->LogInfo[iLogFile].DataBlock = G_REALLOC(ptrTemp, dwBufferSize);
  2067. if (CurrentContext->LogInfo[iLogFile].DataBlock == NULL) {
  2068. G_FREE(ptrTemp);
  2069. }
  2070. }
  2071. if ( (CurrentContext->LogInfo[iLogFile].DataBlock != NULL)
  2072. && (pEvent->Header.Class.Version >= PDH_EVENT_VERSION)) {
  2073. RtlCopyMemory(CurrentContext->LogInfo[iLogFile].DataBlock,
  2074. pLogFileGuid,
  2075. sizeof(GUID));
  2076. CurrentContext->LogInfo[iLogFile].DataBlockSize = sizeof(GUID);
  2077. CurrentContext->LogInfo[iLogFile].DataBlockAlloc = dwBufferSize;
  2078. CurrentContext->LogInfo[iLogFile].ulNumDataBlocks = dwNumDataBlocks;
  2079. CurrentContext->LogInfo[iLogFile].ulDataBlocksCopied = 0;
  2080. }
  2081. }
  2082. dwBlockIndex = * (DWORD *) (((LPBYTE) pEvent->MofData) + sizeof(GUID));
  2083. if (CurrentContext->LogInfo[iLogFile].DataBlock != NULL) {
  2084. if (pEvent->Header.Class.Version >= PDH_EVENT_VERSION) {
  2085. PVOID ptrDataBlock = (PVOID)
  2086. ( ((LPBYTE) CurrentContext->LogInfo[iLogFile].DataBlock)
  2087. + sizeof(GUID)
  2088. + PDH_BLOCK_BUFFER_SIZE * (dwBlockIndex - 1));
  2089. RtlCopyMemory(ptrDataBlock,
  2090. (PVOID) (((LPBYTE) pEvent->MofData)
  2091. + sizeof(GUID) + sizeof(DWORD) + sizeof(DWORD)),
  2092. pEvent->MofLength - sizeof(GUID)
  2093. - sizeof(DWORD) - sizeof(DWORD));
  2094. CurrentContext->LogInfo[iLogFile].ulDataBlocksCopied ++;
  2095. CurrentContext->LogInfo[iLogFile].DataBlockSize +=
  2096. pEvent->MofLength - sizeof(GUID)
  2097. - sizeof(DWORD) - sizeof(DWORD);
  2098. }
  2099. else {
  2100. RtlCopyMemory(CurrentContext->LogInfo[iLogFile].DataBlock,
  2101. pEvent->MofData,
  2102. pEvent->MofLength);
  2103. CurrentContext->LogInfo[iLogFile].DataBlockSize = pEvent->MofLength;
  2104. }
  2105. }
  2106. if (pEvent->Header.Class.Version < PDH_EVENT_VERSION) {
  2107. if (DataBlockInfo.CurrentTime == (ULONGLONG) 0) {
  2108. // no CurrentTime comparison, just get the data block
  2109. //
  2110. DataBlockInfo.CurrentTime = EventTime;
  2111. }
  2112. if (DataBlockInfo.CurrentTime <= EventTime) {
  2113. DataBlockInfo.pRecord =
  2114. CurrentContext->LogInfo[iLogFile].DataBlock;
  2115. DataBlockInfo.dwCurrentSize = pEvent->MofLength;
  2116. DataBlockInfo.Status = ERROR_SUCCESS;
  2117. bNotifyPDH = TRUE;
  2118. CurrentContext->bDataBlockProcessed = FALSE;
  2119. }
  2120. }
  2121. else if ( CurrentContext->LogInfo[iLogFile].ulDataBlocksCopied
  2122. >= CurrentContext->LogInfo[iLogFile].ulNumDataBlocks) {
  2123. if (DataBlockInfo.CurrentTime == (ULONGLONG) 0) {
  2124. // no CurrentTime comparison, just get the data block
  2125. //
  2126. DataBlockInfo.CurrentTime = EventTime;
  2127. }
  2128. if (DataBlockInfo.CurrentTime <= EventTime) {
  2129. DataBlockInfo.pRecord =
  2130. CurrentContext->LogInfo[iLogFile].DataBlock;
  2131. DataBlockInfo.dwCurrentSize =
  2132. CurrentContext->LogInfo[iLogFile].DataBlockSize;
  2133. DataBlockInfo.Status = ERROR_SUCCESS;
  2134. bNotifyPDH = TRUE;
  2135. CurrentContext->bDataBlockProcessed = FALSE;
  2136. }
  2137. }
  2138. break;
  2139. default:
  2140. DebugPrint((4, "PdhWmiEventCallback(), unknown EventType %d\n",
  2141. pEvent->Header.Class.Type));
  2142. break;
  2143. }
  2144. Cleanup:
  2145. if (bNotifyPDH) {
  2146. // Signal that we get the current DataBlock event, then wait for next
  2147. // DataBlock requests.
  2148. //
  2149. SetEvent(CurrentContext->hSyncPDH);
  2150. WaitForSingleObject(CurrentContext->hSyncWMI, INFINITE);
  2151. }
  2152. }
  2153. PDH_FUNCTION
  2154. PdhProcessLog(
  2155. PPDH_LOGGER_CONTEXT CurrentContext)
  2156. {
  2157. PDH_STATUS Status = ERROR_SUCCESS;
  2158. LONG i;
  2159. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  2160. return PDH_INVALID_HANDLE;
  2161. }
  2162. CurrentContext->bFirstRun = TRUE;
  2163. CurrentContext->dwThread = GetCurrentThreadId();
  2164. do {
  2165. CurrentContext->LoggerState = PdhProcessTraceNormal;
  2166. CurrentContext->bFirstDataBlockRead = FALSE;
  2167. CurrentContext->bDataBlockProcessed = FALSE;
  2168. for (i = 0; i < (LONG) CurrentContext->LoggerCount; i ++) {
  2169. CurrentContext->LogInfo[i].TimePrev = 0;
  2170. if (CurrentContext->LogInfo[i].DataBlock) {
  2171. G_FREE(CurrentContext->LogInfo[i].DataBlock);
  2172. CurrentContext->LogInfo[i].DataBlock = NULL;
  2173. }
  2174. CurrentContext->LogInfo[i].DataBlockSize = 0;
  2175. }
  2176. RtlZeroMemory(& DataBlockInfo, sizeof(PDH_DATA_BLOCK_TRANSFER));
  2177. Status = ProcessTrace(CurrentContext->LogFileHandle,
  2178. CurrentContext->LogFileCount,
  2179. NULL,
  2180. NULL);
  2181. if (Status != ERROR_SUCCESS && Status != ERROR_CANCELLED) {
  2182. DebugPrint((4, "ProcessTrace(0x%08X,%d) fails (%d,0x%08X)\n",
  2183. CurrentContext,
  2184. CurrentContext->LogFileCount,
  2185. Status,
  2186. Status));
  2187. }
  2188. if (CurrentContext->bFirstRun) {
  2189. CurrentContext->bFirstRun = FALSE;
  2190. CurrentContext->LoggerState = PdhProcessTraceRewind;
  2191. CurrentContext->TimeFreq = CurrentContext->LogInfo[0].TimeFreq;
  2192. for (i = 1; i < (LONG) CurrentContext->LogFileCount; i ++) {
  2193. if ( CurrentContext->TimeFreq
  2194. > CurrentContext->LogInfo[i].TimeFreq) {
  2195. CurrentContext->TimeFreq =
  2196. CurrentContext->LogInfo[i].TimeFreq;
  2197. }
  2198. }
  2199. }
  2200. else if (CurrentContext->LoggerState == PdhProcessTraceNormal) {
  2201. CurrentContext->LoggerState = PdhProcessTraceComplete;
  2202. DataBlockInfo.Status = PDH_END_OF_LOG_FILE;
  2203. // Wake up PDH main thread so that PdhiReadNextWmiRecord() will
  2204. // notice END_OF_LOG_FILE condition. Wait PDH main thread to wake
  2205. // me up and rewind logger. After wake up, LoggerState should
  2206. // be reset to PdhProcessTraceNormal.
  2207. //
  2208. SetEvent(CurrentContext->hSyncPDH);
  2209. Status = WaitForSingleObject(CurrentContext->hSyncWMI,
  2210. INFINITE);
  2211. assert(CurrentContext->LoggerState == PdhProcessTraceRewind);
  2212. }
  2213. for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
  2214. Status = CloseTrace(CurrentContext->LogFileHandle[i]);
  2215. if (Status != ERROR_SUCCESS) {
  2216. DebugPrint((4, "CloseTrace(%d,%ws) fails (%d,0x%08X)\n",
  2217. CurrentContext->LogFileHandle[i],
  2218. CurrentContext->LogFileName[i],
  2219. Status,
  2220. Status));
  2221. }
  2222. }
  2223. if (CurrentContext->LoggerState == PdhProcessTraceRewind) {
  2224. EVENT_TRACE_LOGFILEW EvmFile;
  2225. for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
  2226. RtlZeroMemory(& EvmFile, sizeof(EVENT_TRACE_LOGFILE));
  2227. EvmFile.BufferCallback = PdhWmiBufferCallback;
  2228. EvmFile.EventCallback = PdhWmiEventCallback;
  2229. EvmFile.LogFileName = CurrentContext->LogFileName[i];
  2230. CurrentContext->LogFileHandle[i] = OpenTraceW(& EvmFile);
  2231. if ( CurrentContext->LogFileHandle[i] == 0
  2232. || CurrentContext->LogFileHandle[i] ==
  2233. (TRACEHANDLE) INVALID_HANDLE_VALUE) {
  2234. DebugPrint((4,"OpenTraceW(%d,%ws) fails\n",
  2235. i,
  2236. CurrentContext->LogFileName[i]));
  2237. while (--i >= 0) {
  2238. CloseTrace(CurrentContext->LogFileHandle[i]);
  2239. }
  2240. Status = PDH_LOG_FILE_OPEN_ERROR;
  2241. DataBlockInfo.Status = PDH_LOG_FILE_OPEN_ERROR;
  2242. SetEvent(CurrentContext->hSyncPDH);
  2243. goto Cleanup;
  2244. }
  2245. }
  2246. }
  2247. } while (CurrentContext->LoggerState == PdhProcessTraceRewind);
  2248. Cleanup:
  2249. CurrentContext->LoggerState = PdhProcessTraceExit;
  2250. return Status;
  2251. }
  2252. PDH_FUNCTION
  2253. PdhiOpenInputWmiLog(
  2254. IN PPDHI_LOG pLog)
  2255. {
  2256. PDH_STATUS Status = ERROR_SUCCESS;
  2257. PPDHI_LOG pLogCurrent = pLog;
  2258. PPDH_LOGGER_CONTEXT CurrentContext;
  2259. EVENT_TRACE_LOGFILEW EvmFile;
  2260. WCHAR LogFileName[PDH_MAX_PATH];
  2261. LONG i;
  2262. DWORD ThreadId;
  2263. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2264. if (CurrentContext != NULL) {
  2265. if (GetLoggerContext(CurrentContext) < ContextCount) {
  2266. CurrentContext->RefCount ++;
  2267. pLog->lpMappedFileBase = (PVOID) CurrentContext;
  2268. return ERROR_SUCCESS;
  2269. }
  2270. else {
  2271. DebugPrint((4, "PdhiOpenInputWmiLog(0x%08X,0x%08X,0x%08X)\n",
  2272. pLog,
  2273. pLog->lpMappedFileBase,
  2274. CurrentContext));
  2275. return PDH_INVALID_ARGUMENT;
  2276. }
  2277. }
  2278. CurrentContext = (PPDH_LOGGER_CONTEXT) G_ALLOC(sizeof(PDH_LOGGER_CONTEXT));
  2279. if (CurrentContext == NULL) {
  2280. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  2281. goto Cleanup;
  2282. }
  2283. pLog->lpMappedFileBase = (PVOID) CurrentContext;
  2284. RtlZeroMemory(CurrentContext, sizeof(PDH_LOGGER_CONTEXT));
  2285. for (i = 0; i < PDH_MAX_LOGFILES && pLogCurrent; i ++) {
  2286. CurrentContext->LogFileName[i] = pLogCurrent->szLogFileName;
  2287. pLogCurrent = pLogCurrent->NextLog;
  2288. }
  2289. CurrentContext->LogFileCount = i;
  2290. CurrentContext->LoggerCount = 0;
  2291. for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
  2292. InitializeListHead(& CurrentContext->LogInfo[i].CounterPathList);
  2293. InitializeListHead(& CurrentContext->LogInfo[i].PerfMachineList);
  2294. }
  2295. CurrentContext->RefCount = 1;
  2296. CurrentContext->hSyncWMI = CreateEvent(NULL, FALSE, FALSE, NULL);
  2297. CurrentContext->hSyncPDH = CreateEvent(NULL, FALSE, FALSE, NULL);
  2298. if (CurrentContext->hSyncWMI == NULL || CurrentContext->hSyncPDH == NULL) {
  2299. Status = PDH_INVALID_HANDLE;
  2300. goto Cleanup;
  2301. }
  2302. Status = WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex);
  2303. if (Status == ERROR_SUCCESS) {
  2304. if (ContextCount < PDH_MAX_LOGFILES) {
  2305. ContextTable[ContextCount] = CurrentContext;
  2306. ContextCount ++;
  2307. }
  2308. else {
  2309. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  2310. }
  2311. RELEASE_MUTEX(hPdhContextMutex);
  2312. }
  2313. if (Status != ERROR_SUCCESS) {
  2314. goto Cleanup;
  2315. }
  2316. for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
  2317. RtlZeroMemory(& EvmFile, sizeof(EVENT_TRACE_LOGFILE));
  2318. EvmFile.BufferCallback = PdhWmiFirstBufferCallback;
  2319. EvmFile.EventCallback = PdhWmiFirstEventCallback;
  2320. EvmFile.LogFileName = LogFileName;
  2321. _wfullpath(EvmFile.LogFileName,
  2322. CurrentContext->LogFileName[i],
  2323. PDH_MAX_PATH);
  2324. CurrentContext->LogFileHandle[i] = OpenTraceW(& EvmFile);
  2325. if ( CurrentContext->LogFileHandle[i] == 0
  2326. || CurrentContext->LogFileHandle[i] ==
  2327. (TRACEHANDLE) INVALID_HANDLE_VALUE) {
  2328. DebugPrint((4,"OpenTraceW(%d,%ws) fails\n",
  2329. i,
  2330. CurrentContext->LogFileName[i]));
  2331. while (--i >= 0) {
  2332. CloseTrace(CurrentContext->LogFileHandle[i]);
  2333. }
  2334. Status = PDH_LOG_FILE_OPEN_ERROR;
  2335. goto Cleanup;
  2336. }
  2337. }
  2338. CurrentContext->hThreadWork = CreateThread(
  2339. NULL,
  2340. 0,
  2341. (LPTHREAD_START_ROUTINE) PdhProcessLog,
  2342. CurrentContext,
  2343. 0,
  2344. (LPDWORD) & ThreadId);
  2345. if (CurrentContext->hThreadWork == NULL) {
  2346. Status = GetLastError();
  2347. DebugPrint((4, "CreateThread() fails (%d,0x%08X)\n",
  2348. Status, Status));
  2349. for (i = 0; i < (LONG) CurrentContext->LogFileCount; i ++) {
  2350. Status = CloseTrace(CurrentContext->LogFileHandle[i]);
  2351. if (Status != ERROR_SUCCESS) {
  2352. DebugPrint((4, "CloseTrace(0x%08X,%ws) fails (%d,0x%08X)\n",
  2353. CurrentContext->LogFileHandle[i],
  2354. CurrentContext->LogFileName[i],
  2355. Status,
  2356. Status));
  2357. }
  2358. }
  2359. goto Cleanup;
  2360. }
  2361. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2362. Cleanup:
  2363. if (Status != ERROR_SUCCESS) {
  2364. if (CurrentContext != NULL) {
  2365. DWORD dwContext = GetLoggerContext(CurrentContext);
  2366. if (dwContext < ContextCount) {
  2367. if ( WAIT_FOR_AND_LOCK_MUTEX(hPdhContextMutex)
  2368. == ERROR_SUCCESS) {
  2369. if (dwContext != ContextCount - 1) {
  2370. ContextTable[dwContext] = ContextTable[ContextCount - 1];
  2371. }
  2372. ContextTable[ContextCount - 1] = NULL;
  2373. ContextCount --;
  2374. RELEASE_MUTEX(hPdhContextMutex);
  2375. }
  2376. else {
  2377. ContextTable[dwContext] = NULL;
  2378. }
  2379. }
  2380. if (CurrentContext->hSyncWMI) {
  2381. CloseHandle(CurrentContext->hSyncWMI);
  2382. }
  2383. if (CurrentContext->hSyncPDH) {
  2384. CloseHandle(CurrentContext->hSyncPDH);
  2385. }
  2386. G_FREE(CurrentContext);
  2387. CurrentContext = NULL;
  2388. }
  2389. pLog->lpMappedFileBase = NULL;
  2390. }
  2391. return Status;
  2392. }
  2393. PDH_FUNCTION
  2394. PdhiRewindWmiLog(
  2395. IN PPDHI_LOG pLog)
  2396. {
  2397. PDH_STATUS Status = PDH_INVALID_HANDLE;
  2398. PPDH_LOGGER_CONTEXT CurrentContext;
  2399. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2400. if (GetLoggerContext(CurrentContext) < ContextCount) {
  2401. CurrentContext->LoggerState = PdhProcessTraceRewind;
  2402. SetEvent(CurrentContext->hSyncWMI);
  2403. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2404. Status = ERROR_SUCCESS;
  2405. }
  2406. return Status;
  2407. }
  2408. PDH_FUNCTION
  2409. PdhiReadWmiHeaderRecord(
  2410. IN PPDHI_LOG pLog,
  2411. IN LPVOID pRecord,
  2412. IN DWORD dwMaxSize)
  2413. {
  2414. PDH_STATUS Status = ERROR_SUCCESS;
  2415. PPDH_LOGGER_CONTEXT CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2416. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  2417. return PDH_INVALID_HANDLE;
  2418. }
  2419. // Wait until logfiles are scaned first to collect
  2420. // 1) Counter Path information
  2421. // 2) Time Range information
  2422. //
  2423. while (CurrentContext->bFirstRun) {
  2424. _sleep(1);
  2425. }
  2426. Status = PdhiGetCounterPathRecord(CurrentContext, pRecord, dwMaxSize);
  2427. pLog->pLastRecordRead = CurrentContext->CounterPathBuffer;
  2428. return Status;
  2429. }
  2430. PDH_FUNCTION
  2431. PdhiBuildDataBlock(
  2432. IN PPDHI_LOG pLog,
  2433. IN ULONGLONG TimeStamp)
  2434. {
  2435. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2436. LONG Offset = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  2437. LONG CopySize;
  2438. LONG CheckSize;
  2439. ULONG i;
  2440. LONG CurrentSize = PDH_WMI_BUFFER_SIZE_BYTE;
  2441. PPDH_LOGGER_CONTEXT CurrentContext;
  2442. PPDHI_BINARY_LOG_RECORD_HEADER pHeader;
  2443. PVOID pBlock;
  2444. PPDHI_BINARY_LOG_RECORD_HEADER pCounterHeader;
  2445. PPDH_RAW_COUNTER pSingleCounter;
  2446. PPDHI_LOG_COUNTER_PATH pCounterPath;
  2447. BOOLEAN bValidBlock;
  2448. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2449. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  2450. return PDH_INVALID_HANDLE;
  2451. }
  2452. if (CurrentContext->tmpBuffer != NULL) {
  2453. G_FREE(CurrentContext->tmpBuffer);
  2454. CurrentContext->tmpBuffer = NULL;
  2455. }
  2456. pHeader = (PPDHI_BINARY_LOG_RECORD_HEADER)
  2457. G_ALLOC(PDH_WMI_BUFFER_SIZE_BYTE);
  2458. if (pHeader == NULL) {
  2459. return PDH_MEMORY_ALLOCATION_FAILURE;
  2460. }
  2461. pHeader->dwType = BINLOG_TYPE_DATA;
  2462. for (i = 0; i < CurrentContext->LoggerCount; i ++) {
  2463. CopySize = CurrentContext->LogInfo[i].DataBlockSize
  2464. - sizeof(GUID) - sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  2465. bValidBlock = TRUE;
  2466. if (Offset + CopySize > CurrentSize) {
  2467. while (Offset + CopySize > CurrentSize) {
  2468. CurrentSize += PDH_WMI_BUFFER_SIZE_BYTE;
  2469. }
  2470. CurrentContext->tmpBuffer = pHeader;
  2471. pHeader = G_REALLOC(CurrentContext->tmpBuffer, CurrentSize);
  2472. if (pHeader == NULL) {
  2473. G_FREE(CurrentContext->tmpBuffer);
  2474. CurrentContext->tmpBuffer = NULL;
  2475. return PDH_MEMORY_ALLOCATION_FAILURE;
  2476. }
  2477. CurrentContext->tmpBuffer = NULL;
  2478. }
  2479. pBlock = (PVOID) (((PUCHAR) pHeader) + Offset);
  2480. if ( (CurrentContext->LogInfo[i].DataBlock)
  2481. && (CopySize > 0)
  2482. && ( DataBlockInfo.CurrentTime
  2483. <= CurrentContext->LogInfo[i].TimeEnd)) {
  2484. CheckSize = sizeof(GUID);
  2485. while (bValidBlock && CheckSize < CopySize) {
  2486. pCounterHeader = (PPDHI_BINARY_LOG_RECORD_HEADER)
  2487. (((PUCHAR) CurrentContext->LogInfo[i].DataBlock) + CheckSize);
  2488. if (LOWORD(pCounterHeader->dwType) == BINLOG_START_WORD) {
  2489. CheckSize += pCounterHeader->dwLength;
  2490. }
  2491. else {
  2492. bValidBlock = FALSE;
  2493. }
  2494. }
  2495. }
  2496. else {
  2497. bValidBlock = FALSE;
  2498. }
  2499. if (bValidBlock == TRUE) {
  2500. RtlCopyMemory(
  2501. pBlock,
  2502. (PVOID) ( ((PUCHAR) CurrentContext->LogInfo[i].DataBlock)
  2503. + sizeof(GUID)
  2504. + sizeof(PDHI_BINARY_LOG_RECORD_HEADER)),
  2505. CopySize);
  2506. Offset += CopySize;
  2507. }
  2508. else {
  2509. // need to sneak in pseudo counter block
  2510. //
  2511. PVOID pCounterBlock;
  2512. ULONG BlockSize = 0;
  2513. ULONG j;
  2514. for (j = 0; j < CurrentContext->LogInfo[i].ulCounters; j ++) {
  2515. pBlock = (PVOID) (((PUCHAR) pHeader) + Offset);
  2516. RtlCopyMemory(pBlock,
  2517. & PdhNullCounterHeader,
  2518. sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  2519. pSingleCounter = (PPDH_RAW_COUNTER) (((PUCHAR) pBlock)
  2520. + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  2521. RtlCopyMemory(pSingleCounter,
  2522. & PdhNullCounter,
  2523. sizeof(PDH_RAW_COUNTER));
  2524. pSingleCounter->TimeStamp.dwLowDateTime = LODWORD(TimeStamp);
  2525. pSingleCounter->TimeStamp.dwHighDateTime = HIDWORD(TimeStamp);
  2526. Offset = Offset + sizeof(PDH_RAW_COUNTER)
  2527. + sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  2528. }
  2529. }
  2530. }
  2531. pHeader->dwLength = Offset;
  2532. CurrentContext->tmpBuffer = pHeader;
  2533. return pdhStatus;
  2534. }
  2535. PDH_FUNCTION
  2536. PdhiReadNextWmiRecord(
  2537. IN PPDHI_LOG pLog,
  2538. IN LPVOID pRecord,
  2539. IN DWORD dwMaxSize,
  2540. IN BOOLEAN bAllCounter)
  2541. {
  2542. PDH_STATUS Status = ERROR_SUCCESS;
  2543. PPDH_LOGGER_CONTEXT CurrentContext;
  2544. ULONGLONG CurrentTime;
  2545. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2546. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  2547. Status = PDH_INVALID_HANDLE;
  2548. goto Cleanup;
  2549. }
  2550. // Wait until logfiles are scaned first to collect
  2551. // 1) Counter Path information
  2552. // 2) Time Range information
  2553. //
  2554. while (CurrentContext->bFirstRun) {
  2555. _sleep(1);
  2556. }
  2557. if (CurrentContext->LoggerState == PdhProcessTraceComplete) {
  2558. CurrentContext->LoggerState = PdhProcessTraceRewind;
  2559. SetEvent(CurrentContext->hSyncWMI);
  2560. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2561. Status = PDH_END_OF_LOG_FILE;
  2562. goto Cleanup;
  2563. }
  2564. if (! CurrentContext->bFirstDataBlockRead) {
  2565. CurrentContext->bFirstDataBlockRead = TRUE;
  2566. CurrentContext->bDataBlockProcessed = TRUE;
  2567. }
  2568. else if (! CurrentContext->bDataBlockProcessed) {
  2569. CurrentContext->bDataBlockProcessed = TRUE;
  2570. }
  2571. else {
  2572. DataBlockInfo.CurrentTime = (ULONGLONG) 0;
  2573. SetEvent(CurrentContext->hSyncWMI);
  2574. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2575. }
  2576. if (CurrentContext->LoggerState == PdhProcessTraceComplete) {
  2577. CurrentContext->LoggerState = PdhProcessTraceRewind;
  2578. SetEvent(CurrentContext->hSyncWMI);
  2579. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2580. Status = PDH_END_OF_LOG_FILE;
  2581. goto Cleanup;
  2582. }
  2583. if (bAllCounter && CurrentContext->LogFileCount > 1) {
  2584. CurrentTime = DataBlockInfo.CurrentTime;
  2585. while ( (CurrentContext->LoggerState != PdhProcessTraceComplete)
  2586. && (DataBlockInfo.CurrentTime - CurrentTime <= TIME_DELTA)) {
  2587. DataBlockInfo.CurrentTime = (ULONGLONG) 0;
  2588. SetEvent(CurrentContext->hSyncWMI);
  2589. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2590. }
  2591. CurrentContext->bDataBlockProcessed = FALSE;
  2592. Status = DataBlockInfo.Status;
  2593. if (Status == ERROR_SUCCESS) {
  2594. Status = PdhiBuildDataBlock(pLog, CurrentTime);
  2595. }
  2596. if (Status == ERROR_SUCCESS) {
  2597. pLog->pLastRecordRead = CurrentContext->tmpBuffer;
  2598. }
  2599. }
  2600. else {
  2601. if (bAllCounter) {
  2602. pLog->pLastRecordRead =
  2603. (((PUCHAR) DataBlockInfo.pRecord) + sizeof(GUID));
  2604. }
  2605. else {
  2606. pLog->pLastRecordRead = ((PUCHAR) DataBlockInfo.pRecord);
  2607. }
  2608. CurrentContext->bDataBlockProcessed = TRUE;
  2609. Status = DataBlockInfo.Status;
  2610. }
  2611. if (Status == ERROR_SUCCESS) {
  2612. if (dwMaxSize < DataBlockInfo.dwCurrentSize - sizeof(GUID)) {
  2613. Status = PDH_MORE_DATA;
  2614. }
  2615. if (pRecord) {
  2616. RtlCopyMemory(pRecord,
  2617. pLog->pLastRecordRead,
  2618. (Status == ERROR_SUCCESS) ? (DataBlockInfo.dwCurrentSize)
  2619. : (dwMaxSize));
  2620. }
  2621. }
  2622. Cleanup:
  2623. return Status;
  2624. }
  2625. PDH_FUNCTION
  2626. PdhiReadTimeWmiRecord(
  2627. IN PPDHI_LOG pLog,
  2628. IN ULONGLONG TimeStamp,
  2629. IN LPVOID pRecord,
  2630. IN DWORD dwMaxSize)
  2631. {
  2632. PDH_STATUS Status = ERROR_SUCCESS;
  2633. PPDH_LOGGER_CONTEXT CurrentContext;
  2634. BOOLEAN TimeInRange = FALSE;
  2635. BOOLEAN bRewind = TRUE;
  2636. ULONG i;
  2637. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2638. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  2639. Status = PDH_INVALID_HANDLE;
  2640. goto Cleanup;
  2641. }
  2642. if (TimeStamp == MIN_TIME_VALUE) {
  2643. TimeStamp = CurrentContext->LogInfo[0].TimeStart;
  2644. }
  2645. if (TimeStamp == MAX_TIME_VALUE) {
  2646. TimeStamp = CurrentContext->LogInfo[0].TimeEnd;
  2647. }
  2648. for (i = 0; i < (ULONG) CurrentContext->LoggerCount; i ++) {
  2649. if ( TimeStamp >= CurrentContext->LogInfo[i].TimeStart
  2650. && TimeStamp <= CurrentContext->LogInfo[i].TimeEnd) {
  2651. TimeInRange = TRUE;
  2652. break;
  2653. }
  2654. }
  2655. if (! TimeInRange) {
  2656. Status = PDH_INVALID_ARGUMENT;
  2657. goto Cleanup;
  2658. }
  2659. // Wait until logfiles are scaned first to collect
  2660. // 1) Counter Path information
  2661. // 2) Time Range information
  2662. //
  2663. while (CurrentContext->bFirstRun) {
  2664. _sleep(1);
  2665. }
  2666. if (CurrentContext->LoggerState == PdhProcessTraceComplete) {
  2667. CurrentContext->LoggerState = PdhProcessTraceRewind;
  2668. SetEvent(CurrentContext->hSyncWMI);
  2669. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2670. Status = PDH_END_OF_LOG_FILE;
  2671. goto Cleanup;
  2672. }
  2673. ReScan:
  2674. if (! CurrentContext->bFirstDataBlockRead) {
  2675. CurrentContext->bFirstDataBlockRead = TRUE;
  2676. CurrentContext->bDataBlockProcessed = TRUE;
  2677. }
  2678. else if (! CurrentContext->bDataBlockProcessed) {
  2679. CurrentContext->bDataBlockProcessed = TRUE;
  2680. }
  2681. else {
  2682. DataBlockInfo.CurrentTime = 0;
  2683. SetEvent(CurrentContext->hSyncWMI);
  2684. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2685. }
  2686. if (CurrentContext->LoggerState == PdhProcessTraceComplete) {
  2687. CurrentContext->LoggerState = PdhProcessTraceRewind;
  2688. SetEvent(CurrentContext->hSyncWMI);
  2689. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2690. Status = PDH_END_OF_LOG_FILE;
  2691. goto Cleanup;
  2692. }
  2693. else if (DataBlockInfo.CurrentTime > TimeStamp) {
  2694. if (bRewind) {
  2695. bRewind = FALSE;
  2696. CurrentContext->LoggerState = PdhProcessTraceRewind;
  2697. SetEvent(CurrentContext->hSyncWMI);
  2698. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2699. goto ReScan;
  2700. }
  2701. }
  2702. while ( (CurrentContext->LoggerState != PdhProcessTraceComplete)
  2703. && (( ((LONGLONG) TimeStamp)
  2704. - ((LONGLONG) DataBlockInfo.CurrentTime))
  2705. > TIME_DELTA)) {
  2706. DataBlockInfo.CurrentTime = (ULONGLONG) 0;
  2707. SetEvent(CurrentContext->hSyncWMI);
  2708. WaitForSingleObject(CurrentContext->hSyncPDH, INFINITE);
  2709. }
  2710. CurrentContext->bDataBlockProcessed = TRUE;
  2711. Status = DataBlockInfo.Status;
  2712. if (Status == ERROR_SUCCESS) {
  2713. Status = PdhiBuildDataBlock(pLog, TimeStamp);
  2714. }
  2715. if (Status == ERROR_SUCCESS) {
  2716. pLog->pLastRecordRead = CurrentContext->tmpBuffer;
  2717. }
  2718. if (Status == ERROR_SUCCESS) {
  2719. if (dwMaxSize < DataBlockInfo.dwCurrentSize - sizeof(GUID)) {
  2720. Status = PDH_MORE_DATA;
  2721. }
  2722. if (pRecord) {
  2723. RtlCopyMemory(pRecord,
  2724. (((PUCHAR) DataBlockInfo.pRecord) + sizeof(GUID)),
  2725. (Status == ERROR_SUCCESS) ? (DataBlockInfo.dwCurrentSize)
  2726. : (dwMaxSize));
  2727. }
  2728. }
  2729. Cleanup:
  2730. return Status;
  2731. }
  2732. PDH_FUNCTION
  2733. PdhiGetTimeRangeFromWmiLog (
  2734. IN PPDHI_LOG pLog,
  2735. IN LPDWORD pdwNumEntries,
  2736. IN PPDH_TIME_INFO pInfo,
  2737. IN LPDWORD pdwBufferSize)
  2738. {
  2739. PDH_STATUS Status = ERROR_SUCCESS;
  2740. PPDH_LOGGER_CONTEXT CurrentContext;
  2741. ULONG i;
  2742. ULONGLONG StartTime;
  2743. ULONGLONG EndTime;
  2744. ULONG EntryCount;
  2745. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2746. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  2747. return PDH_INVALID_HANDLE;
  2748. }
  2749. // Wait until logfiles are scaned first to collect
  2750. // 1) Counter Path information
  2751. // 2) Time Range information
  2752. //
  2753. while (CurrentContext->bFirstRun) {
  2754. _sleep(1);
  2755. }
  2756. for (StartTime = CurrentContext->LogInfo[0].TimeStart,
  2757. EndTime = CurrentContext->LogInfo[0].TimeEnd,
  2758. EntryCount = CurrentContext->LogInfo[0].ValidEntries,
  2759. i = 1;
  2760. i < CurrentContext->LoggerCount;
  2761. i ++) {
  2762. if ( StartTime == 0
  2763. || ( CurrentContext->LogInfo[i].TimeStart != 0
  2764. && StartTime > CurrentContext->LogInfo[i].TimeStart)) {
  2765. StartTime = CurrentContext->LogInfo[i].TimeStart;
  2766. }
  2767. if (EndTime < CurrentContext->LogInfo[i].TimeEnd)
  2768. EndTime = CurrentContext->LogInfo[i].TimeEnd;
  2769. EntryCount += CurrentContext->LogInfo[i].ValidEntries;
  2770. }
  2771. if (* pdwBufferSize >= sizeof(PDH_TIME_INFO)) {
  2772. * (LONGLONG *) (& pInfo->StartTime) = StartTime;
  2773. * (LONGLONG *) (& pInfo->EndTime) = EndTime;
  2774. pInfo->SampleCount = EntryCount;
  2775. * pdwBufferSize = sizeof(PDH_TIME_INFO);
  2776. * pdwNumEntries = 1;
  2777. }
  2778. else {
  2779. Status = PDH_MORE_DATA;
  2780. }
  2781. return Status;
  2782. }
  2783. PPDH_WMI_PERF_MACHINE
  2784. PdhWmiGetLogNameTable(
  2785. IN PPDHI_LOG pLog,
  2786. IN LPCWSTR szMachineName,
  2787. IN DWORD dwLangId
  2788. )
  2789. {
  2790. PPDH_WMI_PERF_MACHINE pReturnMachine = NULL;
  2791. PPDH_LOGGER_CONTEXT CurrentContext;
  2792. DWORD i;
  2793. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2794. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  2795. return NULL;
  2796. }
  2797. for (i = 0;
  2798. pReturnMachine == NULL && i < CurrentContext->LoggerCount;
  2799. i ++) {
  2800. if (! IsListEmpty(& CurrentContext->LogInfo[i].PerfMachineList)) {
  2801. PLIST_ENTRY pHead = & CurrentContext->LogInfo[i].PerfMachineList;
  2802. PLIST_ENTRY pNext = pHead->Flink;
  2803. while (pNext != pHead) {
  2804. PPDH_WMI_PERF_MACHINE pMachine =
  2805. CONTAINING_RECORD(pNext, PDH_WMI_PERF_MACHINE, Entry);
  2806. if (lstrcmpiW(pMachine->pszBuffer, szMachineName) == 0) {
  2807. pReturnMachine = pMachine;
  2808. break;
  2809. }
  2810. pNext = pNext->Flink;
  2811. }
  2812. }
  2813. }
  2814. return pReturnMachine;
  2815. }
  2816. PPDH_WMI_PERF_OBJECT
  2817. PdhWmiAddPerfObject(
  2818. IN PPDHI_LOG pLog,
  2819. IN LPCWSTR szMachineName,
  2820. IN DWORD dwLangId,
  2821. IN LPCWSTR szObjectName,
  2822. IN DWORD dwObjectId,
  2823. IN PPERF_DATA_BLOCK pDataBlock
  2824. )
  2825. {
  2826. PPDH_WMI_PERF_OBJECT pPerfObject = NULL;
  2827. PPDH_WMI_PERF_MACHINE pPerfMachine =
  2828. PdhWmiGetLogNameTable(pLog, szMachineName, dwLangId);
  2829. PLIST_ENTRY pHead;
  2830. PLIST_ENTRY pNext;
  2831. PPDH_WMI_PERF_OBJECT pCurrentObj;
  2832. if (pPerfMachine == NULL) {
  2833. SetLastError(PDH_ENTRY_NOT_IN_LOG_FILE);
  2834. goto Cleanup;
  2835. }
  2836. pHead = & pPerfMachine->LogObjectList;
  2837. pNext = pHead->Flink;
  2838. while (pNext != pHead) {
  2839. pCurrentObj = CONTAINING_RECORD(pNext, PDH_WMI_PERF_OBJECT, Entry);
  2840. if (lstrcmpiW(pCurrentObj->szObjectName, szObjectName) == 0) {
  2841. pPerfObject = pCurrentObj;
  2842. break;
  2843. }
  2844. pNext = pNext->Flink;
  2845. }
  2846. if (pPerfObject != NULL) {
  2847. goto Cleanup;
  2848. }
  2849. pPerfObject = G_ALLOC(sizeof(PDH_WMI_PERF_OBJECT));
  2850. if (pPerfObject == NULL) {
  2851. SetLastError(PDH_MEMORY_ALLOCATION_FAILURE);
  2852. goto Cleanup;
  2853. }
  2854. pPerfObject->ptrBuffer = G_ALLOC(pDataBlock->TotalByteLength
  2855. + sizeof(WCHAR) * (lstrlenW(szObjectName) + 1));
  2856. if (pPerfObject->ptrBuffer == NULL) {
  2857. G_FREE(pPerfObject);
  2858. SetLastError(PDH_MEMORY_ALLOCATION_FAILURE);
  2859. goto Cleanup;
  2860. }
  2861. pPerfObject->dwObjectId = dwObjectId;
  2862. RtlCopyMemory(pPerfObject->ptrBuffer,
  2863. pDataBlock,
  2864. pDataBlock->TotalByteLength);
  2865. pPerfObject->szObjectName = (LPWSTR)
  2866. (((LPBYTE) pPerfObject->ptrBuffer) + pDataBlock->TotalByteLength);
  2867. lstrcpyW(pPerfObject->szObjectName, szObjectName);
  2868. InsertTailList(& pPerfMachine->LogObjectList, & pPerfObject->Entry);
  2869. Cleanup:
  2870. return pPerfObject;
  2871. }
  2872. DWORD
  2873. PdhWmiGetLogPerfIndexByName(
  2874. IN PPDHI_LOG pLog,
  2875. IN LPCWSTR szMachineName,
  2876. IN DWORD dwLangId,
  2877. IN LPCWSTR szNameBuffer
  2878. )
  2879. {
  2880. PPDH_WMI_PERF_MACHINE pMachine;
  2881. DWORD dwLastIndex;
  2882. LPWSTR * pNameArray;
  2883. DWORD dwIndex;
  2884. SetLastError(ERROR_SUCCESS);
  2885. pMachine = PdhWmiGetLogNameTable(pLog, szMachineName, dwLangId);
  2886. if (pMachine != NULL && pMachine->ptrStrAry != NULL) {
  2887. dwLastIndex = pMachine->dwLastId;
  2888. pNameArray = pMachine->ptrStrAry;
  2889. for (dwIndex = 1; dwIndex <= dwLastIndex; dwIndex ++) {
  2890. if (lstrcmpiW(szNameBuffer, pNameArray[dwIndex]) == 0) {
  2891. if ((dwIndex & 0x00000001) == 0) {
  2892. // counter name index should be even integer
  2893. //
  2894. break;
  2895. }
  2896. }
  2897. }
  2898. if (dwIndex > dwLastIndex) {
  2899. SetLastError(PDH_STRING_NOT_FOUND);
  2900. dwIndex = 0;
  2901. }
  2902. }
  2903. else {
  2904. SetLastError(PDH_ENTRY_NOT_IN_LOG_FILE);
  2905. dwIndex = 0;
  2906. }
  2907. return dwIndex;
  2908. }
  2909. LPWSTR
  2910. PdhWmiGetLogPerfNameByIndex (
  2911. IN PPDHI_LOG pLog,
  2912. IN LPCWSTR szMachineName,
  2913. IN DWORD dwLangId,
  2914. IN DWORD dwIndex
  2915. )
  2916. {
  2917. PPDH_WMI_PERF_MACHINE pMachine;
  2918. LPWSTR pszReturnName = NULL;
  2919. LPWSTR * pNameArray;
  2920. static WCHAR szNumber[16];
  2921. pMachine = PdhWmiGetLogNameTable(pLog, szMachineName, dwLangId);
  2922. if (pMachine != NULL && pMachine->ptrStrAry != NULL
  2923. && dwIndex < pMachine->dwLastId) {
  2924. pNameArray = pMachine->ptrStrAry;
  2925. pszReturnName = pNameArray[dwIndex];
  2926. }
  2927. if (pszReturnName == NULL) {
  2928. // unable to find name string, return numeric index string
  2929. //
  2930. memset(szNumber, 0, sizeof (szNumber));
  2931. _ltow(dwIndex, szNumber, 10);
  2932. pszReturnName = szNumber;
  2933. }
  2934. return pszReturnName;
  2935. }
  2936. PPDHI_BINARY_LOG_RECORD_HEADER
  2937. PdhiGetWmiSubRecord(
  2938. IN PPDHI_LOG pLog,
  2939. IN PPDHI_BINARY_LOG_RECORD_HEADER pRecord,
  2940. IN DWORD dwRecordId,
  2941. IN LPGUID LogFileGuid)
  2942. {
  2943. PPDHI_BINARY_LOG_RECORD_HEADER pThisRecord;
  2944. PPDH_LOGGER_CONTEXT CurrentContext;
  2945. DWORD dwRecordType;
  2946. DWORD dwRecordLength;
  2947. DWORD dwBytesProcessed;
  2948. DWORD dwThisSubRecordId;
  2949. DWORD dwLocalIndex;
  2950. ULONG i;
  2951. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  2952. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  2953. return (NULL);
  2954. }
  2955. dwLocalIndex = dwRecordId;
  2956. for (i = 0; i < CurrentContext->LoggerCount; i ++) {
  2957. PLIST_ENTRY pHead = & CurrentContext->LogInfo[i].CounterPathList;
  2958. if (! IsListEmpty(pHead)) {
  2959. PLIST_ENTRY pNext = pHead->Flink;
  2960. PPDH_COUNTER_PATH pCounterPath =
  2961. CONTAINING_RECORD(pNext, PDH_COUNTER_PATH, Entry);
  2962. if (dwLocalIndex <= pCounterPath->CounterCount) {
  2963. break;
  2964. }
  2965. dwLocalIndex -= pCounterPath->CounterCount;
  2966. }
  2967. }
  2968. assert(i < CurrentContext->LoggerCount);
  2969. __try {
  2970. if ( (i >= CurrentContext->LoggerCount)
  2971. || (! IsEqualGUID( LogFileGuid,
  2972. & CurrentContext->LogInfo[i].LogFileGuid))) {
  2973. // binary log record does not contain intended object's counter
  2974. //
  2975. return NULL;
  2976. }
  2977. }
  2978. __except(EXCEPTION_EXECUTE_HANDLER) {
  2979. return NULL;
  2980. }
  2981. dwRecordType = ((PPDHI_BINARY_LOG_RECORD_HEADER) pRecord)->dwType;
  2982. dwRecordLength = ((PPDHI_BINARY_LOG_RECORD_HEADER) pRecord)->dwLength;
  2983. pThisRecord = (PPDHI_BINARY_LOG_RECORD_HEADER)
  2984. (((LPBYTE) pRecord) + sizeof(PDHI_BINARY_LOG_RECORD_HEADER));
  2985. dwBytesProcessed = sizeof(PDHI_BINARY_LOG_RECORD_HEADER);
  2986. if (dwBytesProcessed < dwRecordLength) {
  2987. dwThisSubRecordId = 1;
  2988. while (dwThisSubRecordId < dwLocalIndex) {
  2989. if ((WORD)(pThisRecord->dwType & 0x0000FFFF) == BINLOG_START_WORD) {
  2990. dwBytesProcessed += pThisRecord->dwLength;
  2991. pThisRecord = (PPDHI_BINARY_LOG_RECORD_HEADER)
  2992. (((LPBYTE)pThisRecord) + pThisRecord->dwLength);
  2993. if (dwBytesProcessed >= dwRecordLength) {
  2994. break;
  2995. }
  2996. else {
  2997. dwThisSubRecordId ++;
  2998. }
  2999. }
  3000. else {
  3001. break;
  3002. }
  3003. }
  3004. }
  3005. else {
  3006. dwThisSubRecordId = 0;
  3007. }
  3008. if (dwThisSubRecordId == dwLocalIndex) {
  3009. if ((WORD)(pThisRecord->dwType & 0x0000FFFF) != BINLOG_START_WORD) {
  3010. pThisRecord = NULL;
  3011. }
  3012. }
  3013. else {
  3014. pThisRecord = NULL;
  3015. }
  3016. return pThisRecord;
  3017. }
  3018. PDH_FUNCTION
  3019. PdhWmiEnumObjectItemsFromDataBlock(
  3020. IN PPDHI_LOG pLog,
  3021. IN PPERF_DATA_BLOCK pDataBlock,
  3022. IN LPCWSTR szMachineName,
  3023. IN LPCWSTR szObjectName,
  3024. IN DWORD dwObjectId,
  3025. IN DWORD dwLangId,
  3026. IN PDHI_COUNTER_TABLE CounterTable
  3027. )
  3028. {
  3029. PDH_STATUS Status = ERROR_SUCCESS;
  3030. PERF_OBJECT_TYPE * pObjectDef = GetObjectDefByTitleIndex(pDataBlock, dwObjectId);
  3031. PERF_COUNTER_DEFINITION * pCountDef;
  3032. PERF_INSTANCE_DEFINITION * pInstDef;
  3033. DWORD dwItems;
  3034. LPWSTR szItemName;
  3035. DWORD dwItemLen;
  3036. WCHAR szInstanceName[1024];
  3037. PPDHI_INST_LIST pInstList = NULL;
  3038. PPDHI_INSTANCE pInstance = NULL;
  3039. PPDHI_INST_LIST pFirstInstList = NULL;
  3040. PPDH_WMI_PERF_OBJECT pPerfObj;
  3041. if (pObjectDef == NULL) {
  3042. Status = PDH_ENTRY_NOT_IN_LOG_FILE;
  3043. goto Cleanup;
  3044. }
  3045. pPerfObj = PdhWmiAddPerfObject(pLog,
  3046. szMachineName,
  3047. 9,
  3048. szObjectName,
  3049. dwObjectId,
  3050. pDataBlock);
  3051. if (pPerfObj == NULL) {
  3052. Status = GetLastError();
  3053. goto Cleanup;
  3054. }
  3055. dwItems = 0;
  3056. pCountDef = FirstCounter(pObjectDef);
  3057. while (dwItems < (DWORD) pObjectDef->NumCounters) {
  3058. szItemName = PdhWmiGetLogPerfNameByIndex(
  3059. pLog,
  3060. szMachineName,
  3061. dwLangId,
  3062. pCountDef->CounterNameTitleIndex);
  3063. Status = PdhiFindCounterInstList(
  3064. CounterTable, szItemName, & pInstList);
  3065. if (Status == ERROR_SUCCESS && pFirstInstList == NULL
  3066. && pInstList != NULL) {
  3067. pFirstInstList = pInstList;
  3068. }
  3069. dwItems ++;
  3070. pCountDef = NextCounter(pCountDef);
  3071. }
  3072. if (pFirstInstList == NULL) {
  3073. Status = PDH_NO_COUNTERS;
  3074. goto Cleanup;
  3075. }
  3076. if (pObjectDef->NumInstances != PERF_NO_INSTANCES) {
  3077. dwItems = 0;
  3078. pInstDef = FirstInstance(pObjectDef);
  3079. while (dwItems < (DWORD) pObjectDef->NumInstances) {
  3080. ZeroMemory(szInstanceName, sizeof(WCHAR) * 1024);
  3081. dwItemLen = GetFullInstanceNameStr(
  3082. pDataBlock,
  3083. pObjectDef,
  3084. pInstDef,
  3085. szInstanceName);
  3086. if (dwItemLen > 0) {
  3087. Status = PdhiFindInstance(
  3088. & pFirstInstList->InstList,
  3089. szInstanceName,
  3090. (lstrcmpiW(szInstanceName, L"_Total") == 0) ? FALSE : TRUE,
  3091. & pInstance);
  3092. }
  3093. dwItems ++;
  3094. pInstDef = NextInstance(pInstDef);
  3095. }
  3096. }
  3097. Cleanup:
  3098. return Status;
  3099. }
  3100. PDH_FUNCTION
  3101. PdhiEnumObjectItemsFromWmiLog (
  3102. IN PPDHI_LOG pLog,
  3103. IN LPCWSTR szMachineName,
  3104. IN LPCWSTR szObjectName,
  3105. IN PDHI_COUNTER_TABLE CounterTable,
  3106. IN DWORD dwDetailLevel,
  3107. IN DWORD dwFlags
  3108. )
  3109. {
  3110. DWORD dwTempBufferSize;
  3111. LPVOID pTempBuffer = NULL;
  3112. LPVOID ptrTemp;
  3113. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3114. PPDHI_BINARY_LOG_HEADER_RECORD pHeader;
  3115. PPDHI_LOG_COUNTER_PATH pPath;
  3116. PPDHI_BINARY_LOG_RECORD_HEADER pThisMasterRecord;
  3117. PPDHI_BINARY_LOG_RECORD_HEADER pThisSubRecord;
  3118. PPDHI_RAW_COUNTER_ITEM_BLOCK pDataBlock;
  3119. PPDHI_RAW_COUNTER_ITEM pDataItem;
  3120. DWORD dwBytesProcessed;
  3121. LONG nItemCount = 0;
  3122. LPBYTE pFirstChar;
  3123. LPWSTR szThisMachineName = NULL;
  3124. LPWSTR szThisObjectName = NULL;
  3125. LPWSTR szThisCounterName = NULL;
  3126. LPWSTR szThisInstanceName = NULL;
  3127. LPWSTR szThisParentName;
  3128. WCHAR szCompositeInstance[1024];
  3129. DWORD dwRecordLength;
  3130. BOOL bCopyThisObject;
  3131. BOOL bMachineDataBlockScaned = FALSE;
  3132. BOOL bInstanceListScanned = FALSE;
  3133. DWORD dwIndex;
  3134. DWORD dwDataItemIndex;
  3135. DWORD dwObjectId;
  3136. PPERF_DATA_BLOCK pPerfBlock;
  3137. PPDHI_INST_LIST pInstList = NULL;
  3138. PPDHI_INSTANCE pInstance = NULL;
  3139. PPDH_LOGGER_CONTEXT CurrentContext;
  3140. UNREFERENCED_PARAMETER (dwDetailLevel);
  3141. UNREFERENCED_PARAMETER (dwFlags);
  3142. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  3143. if (GetLoggerContext(CurrentContext) >= ContextCount) {
  3144. pdhStatus = PDH_INVALID_ARGUMENT;
  3145. goto Cleanup;
  3146. }
  3147. if (pLog->dwMaxRecordSize == 0) {
  3148. // no size is defined so start with 64K
  3149. pLog->dwMaxRecordSize = 0x010000;
  3150. }
  3151. dwTempBufferSize = pLog->dwMaxRecordSize;
  3152. pTempBuffer = G_ALLOC(dwTempBufferSize);
  3153. if (pTempBuffer == NULL) {
  3154. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3155. goto Cleanup;
  3156. }
  3157. // read in the catalog record
  3158. pdhStatus = PdhiReadWmiHeaderRecord(pLog, pTempBuffer, dwTempBufferSize);
  3159. while (pdhStatus == PDH_MORE_DATA) {
  3160. if (* (WORD *) pTempBuffer == BINLOG_START_WORD) {
  3161. dwTempBufferSize = ((DWORD *) pTempBuffer)[1];
  3162. if (dwTempBufferSize < pLog->dwMaxRecordSize) {
  3163. pdhStatus = PDH_ENTRY_NOT_IN_LOG_FILE;
  3164. }
  3165. else {
  3166. pLog->dwMaxRecordSize = dwTempBufferSize;
  3167. }
  3168. }
  3169. else {
  3170. pdhStatus = PDH_ENTRY_NOT_IN_LOG_FILE;
  3171. }
  3172. ptrTemp = pTempBuffer;
  3173. pTempBuffer = G_REALLOC(ptrTemp, dwTempBufferSize);
  3174. if (pTempBuffer == NULL) {
  3175. G_FREE(ptrTemp);
  3176. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3177. }
  3178. if (pdhStatus == PDH_MORE_DATA) {
  3179. pdhStatus = PdhiReadWmiHeaderRecord(
  3180. pLog, pTempBuffer, dwTempBufferSize);
  3181. }
  3182. }
  3183. if (pdhStatus != ERROR_SUCCESS) {
  3184. goto Cleanup;
  3185. }
  3186. pHeader = (PPDHI_BINARY_LOG_HEADER_RECORD) pTempBuffer;
  3187. dwRecordLength = ((PPDHI_BINARY_LOG_RECORD_HEADER) pTempBuffer)->dwLength;
  3188. pPath = (PPDHI_LOG_COUNTER_PATH)
  3189. ((LPBYTE) pTempBuffer + sizeof(PDHI_BINARY_LOG_HEADER_RECORD));
  3190. dwBytesProcessed = sizeof(PDHI_BINARY_LOG_HEADER_RECORD);
  3191. dwIndex = 0;
  3192. while (dwBytesProcessed < dwRecordLength) {
  3193. bCopyThisObject = FALSE;
  3194. szThisObjectName = NULL;
  3195. dwIndex ++;
  3196. pFirstChar = (LPBYTE) & pPath->Buffer[0];
  3197. if (pPath->lMachineNameOffset >= 0L) {
  3198. szThisMachineName = (LPWSTR) ( (LPBYTE) pFirstChar
  3199. + pPath->lMachineNameOffset);
  3200. if (lstrcmpiW(szThisMachineName, szMachineName) == 0) {
  3201. if (pPath->dwFlags & PDHIC_COUNTER_BLOCK) {
  3202. if (bMachineDataBlockScaned == FALSE) {
  3203. bCopyThisObject = TRUE;
  3204. bMachineDataBlockScaned = TRUE;
  3205. }
  3206. }
  3207. else if (pPath->lObjectNameOffset >= 0) {
  3208. szThisObjectName = (LPWSTR) ( (LPBYTE) pFirstChar
  3209. + pPath->lObjectNameOffset);
  3210. if (lstrcmpiW(szThisObjectName, szObjectName) == 0) {
  3211. bCopyThisObject = TRUE;
  3212. }
  3213. }
  3214. }
  3215. }
  3216. else if (pPath->lObjectNameOffset >= 0) {
  3217. szThisObjectName = (LPWSTR) ( (LPBYTE) pFirstChar
  3218. + pPath->lObjectNameOffset);
  3219. if (lstrcmpiW(szThisObjectName, szObjectName) == 0) {
  3220. bCopyThisObject = TRUE;
  3221. }
  3222. }
  3223. dwObjectId = 0;
  3224. if (bCopyThisObject) {
  3225. if ( (pPath->dwFlags & PDHIC_COUNTER_OBJECT)
  3226. || (pPath->dwFlags & PDHIC_COUNTER_BLOCK)) {
  3227. dwObjectId = PdhWmiGetLogPerfIndexByName(
  3228. pLog, szMachineName, 9, szObjectName);
  3229. if (dwObjectId == 0) {
  3230. dwObjectId = wcstoul(szObjectName, NULL, 10);
  3231. if (dwObjectId == 0) {
  3232. szThisCounterName = NULL;
  3233. bCopyThisObject = FALSE;
  3234. }
  3235. }
  3236. }
  3237. else if (pPath->lCounterOffset > 0) {
  3238. szThisCounterName = (LPWSTR) ( (LPBYTE)pFirstChar
  3239. + pPath->lCounterOffset);
  3240. }
  3241. else {
  3242. szThisCounterName = NULL;
  3243. bCopyThisObject = FALSE;
  3244. }
  3245. }
  3246. if (bCopyThisObject) {
  3247. if (dwObjectId == 0) {
  3248. pdhStatus = PdhiFindCounterInstList(
  3249. CounterTable,
  3250. szThisCounterName,
  3251. & pInstList);
  3252. if (pdhStatus == ERROR_SUCCESS && pInstList != NULL) {
  3253. nItemCount ++;
  3254. }
  3255. }
  3256. if (pPath->lInstanceOffset >= 0) {
  3257. szThisInstanceName = (LPWSTR) ( (LPBYTE) pFirstChar
  3258. + pPath->lInstanceOffset);
  3259. }
  3260. if ( dwObjectId > 0
  3261. || (pInstList != NULL && szThisInstanceName != NULL)) {
  3262. if (szThisInstanceName && * szThisInstanceName != SPLAT_L) {
  3263. if (pPath->lParentOffset >= 0) {
  3264. szThisParentName = (LPWSTR)
  3265. ((LPBYTE) pFirstChar + pPath->lParentOffset);
  3266. lstrcpyW(szCompositeInstance, szThisParentName);
  3267. lstrcatW(szCompositeInstance, cszSlash);
  3268. lstrcatW(szCompositeInstance, szThisInstanceName);
  3269. }
  3270. else {
  3271. lstrcpyW(szCompositeInstance, szThisInstanceName);
  3272. }
  3273. if (pPath->dwIndex > 0 && pPath->dwIndex != PERF_NO_UNIQUE_ID) {
  3274. lstrcatW(szCompositeInstance, L"#");
  3275. _ltow(pPath->dwIndex,
  3276. (LPWSTR)( szCompositeInstance
  3277. + lstrlenW(szCompositeInstance)),
  3278. 10L);
  3279. }
  3280. pdhStatus = PdhiFindInstance(
  3281. & pInstList->InstList,
  3282. szCompositeInstance,
  3283. (lstrcmpiW(szCompositeInstance, L"_Total") == 0)
  3284. ? FALSE : TRUE,
  3285. & pInstance);
  3286. if (pdhStatus == ERROR_SUCCESS && pInstance != NULL) {
  3287. nItemCount ++;
  3288. }
  3289. }
  3290. else if (dwObjectId > 0 || !bInstanceListScanned) {
  3291. pdhStatus = PdhiRewindWmiLog(pLog);
  3292. if (pdhStatus == ERROR_SUCCESS) {
  3293. pdhStatus = PdhiReadNextWmiRecord(
  3294. pLog, NULL, 0, FALSE);
  3295. while ( pdhStatus == ERROR_SUCCESS
  3296. || pdhStatus == PDH_MORE_DATA) {
  3297. PdhiResetInstanceCount(CounterTable);
  3298. pdhStatus = ERROR_SUCCESS;
  3299. pThisMasterRecord =
  3300. (PPDHI_BINARY_LOG_RECORD_HEADER)
  3301. ( ((PUCHAR) pLog->pLastRecordRead)
  3302. + sizeof(GUID));
  3303. pThisSubRecord = PdhiGetWmiSubRecord(
  3304. pLog,
  3305. pThisMasterRecord,
  3306. dwIndex,
  3307. (LPGUID)(pLog->pLastRecordRead));
  3308. if (pThisSubRecord == NULL) {
  3309. // this data record does not contain
  3310. // counter record for selected object,
  3311. // skip to next one.
  3312. //
  3313. pdhStatus = PdhiReadNextWmiRecord(
  3314. pLog, NULL, 0, FALSE);
  3315. continue;
  3316. }
  3317. if (pThisSubRecord->dwType == BINLOG_TYPE_DATA_OBJECT
  3318. || pThisSubRecord->dwType == BINLOG_TYPE_DATA_LOC_OBJECT) {
  3319. pPerfBlock = (PPERF_DATA_BLOCK)
  3320. ((LPBYTE)pThisSubRecord +
  3321. sizeof (PDHI_BINARY_LOG_RECORD_HEADER));
  3322. pdhStatus = PdhWmiEnumObjectItemsFromDataBlock(
  3323. pLog,
  3324. pPerfBlock,
  3325. szMachineName,
  3326. szObjectName,
  3327. dwObjectId,
  3328. 9,
  3329. CounterTable);
  3330. if (pdhStatus == PDH_ENTRY_NOT_IN_LOG_FILE) {
  3331. pdhStatus = ERROR_SUCCESS;
  3332. }
  3333. }
  3334. else {
  3335. pDataBlock = (PPDHI_RAW_COUNTER_ITEM_BLOCK)
  3336. ((LPBYTE)pThisSubRecord +
  3337. sizeof (PDHI_BINARY_LOG_RECORD_HEADER));
  3338. if (pDataBlock->dwLength > 0) {
  3339. for (dwDataItemIndex = 0;
  3340. dwDataItemIndex < pDataBlock->dwItemCount;
  3341. dwDataItemIndex++) {
  3342. pDataItem = & pDataBlock->pItemArray[dwDataItemIndex];
  3343. szThisInstanceName = (LPWSTR)
  3344. (((LPBYTE) pDataBlock) + pDataItem->szName);
  3345. pdhStatus = PdhiFindInstance(
  3346. & pInstList->InstList,
  3347. szThisInstanceName,
  3348. (lstrcmpiW(szThisInstanceName, L"_Total") == 0)
  3349. ? FALSE : TRUE,
  3350. & pInstance);
  3351. if (pdhStatus == ERROR_SUCCESS) {
  3352. nItemCount++;
  3353. }
  3354. }
  3355. }
  3356. }
  3357. if (pdhStatus != ERROR_SUCCESS) {
  3358. break;
  3359. }
  3360. else {
  3361. pdhStatus = PdhiReadNextWmiRecord(pLog, NULL, 0, FALSE);
  3362. }
  3363. }
  3364. if (pdhStatus == PDH_END_OF_LOG_FILE) {
  3365. pdhStatus = ERROR_SUCCESS;
  3366. }
  3367. if (pdhStatus == ERROR_SUCCESS) {
  3368. bInstanceListScanned = TRUE;
  3369. }
  3370. }
  3371. }
  3372. }
  3373. }
  3374. ZeroMemory(szCompositeInstance, sizeof(szCompositeInstance));
  3375. dwBytesProcessed += pPath->dwLength;
  3376. pPath = (PPDHI_LOG_COUNTER_PATH) ( (LPBYTE) pPath
  3377. + pPath->dwLength);
  3378. }
  3379. if ((nItemCount > 0) && (pdhStatus != PDH_INSUFFICIENT_BUFFER)
  3380. && (pdhStatus != PDH_MORE_DATA)) {
  3381. pdhStatus = ERROR_SUCCESS;
  3382. }
  3383. Cleanup:
  3384. if (pTempBuffer != NULL)
  3385. G_FREE(pTempBuffer);
  3386. return pdhStatus;
  3387. }
  3388. PDH_FUNCTION
  3389. PdhiGetWmiLogCounterInfo(
  3390. IN PPDHI_LOG pLog,
  3391. IN PPDHI_COUNTER pCounter)
  3392. {
  3393. PDH_STATUS Status = ERROR_SUCCESS;
  3394. DWORD dwObjectId = PdhWmiGetLogPerfIndexByName(
  3395. pLog,
  3396. pCounter->pCounterPath->szMachineName,
  3397. 9,
  3398. pCounter->pCounterPath->szObjectName);
  3399. DWORD dwCounterId = wcstoul(pCounter->pCounterPath->szCounterName,
  3400. NULL, 10);
  3401. PPDH_WMI_PERF_MACHINE pMachine = NULL;
  3402. PPDH_WMI_PERF_OBJECT pObject = NULL;
  3403. PLIST_ENTRY pHead;
  3404. PLIST_ENTRY pNext;
  3405. PPERF_DATA_BLOCK pDataBlock = NULL;
  3406. PERF_OBJECT_TYPE * pPerfObject = NULL;
  3407. DWORD dwItems = 0;
  3408. PERF_COUNTER_DEFINITION * pPerfCounter;
  3409. PERF_INSTANCE_DEFINITION * pPerfInstance;
  3410. PPDH_LOGGER_CONTEXT CurrentContext;
  3411. BOOL bNeedEnumerate = TRUE;
  3412. CurrentContext = (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  3413. if (GetLoggerContext(CurrentContext) < ContextCount) {
  3414. pMachine = PdhWmiGetLogNameTable(pLog,
  3415. pCounter->pCounterPath->szMachineName,
  3416. 9);
  3417. if (pMachine == NULL) {
  3418. Status = PDH_ENTRY_NOT_IN_LOG_FILE;
  3419. goto Cleanup;
  3420. }
  3421. pHead = & pMachine->LogObjectList;
  3422. pNext = pHead->Flink;
  3423. while (pNext != pHead) {
  3424. pObject = CONTAINING_RECORD(pNext, PDH_WMI_PERF_OBJECT, Entry);
  3425. if (pObject->dwObjectId == dwObjectId) {
  3426. bNeedEnumerate = FALSE;
  3427. break;
  3428. }
  3429. pNext = pNext->Flink;
  3430. }
  3431. if (bNeedEnumerate) {
  3432. DWORD dwCounterSize = 0;
  3433. DWORD dwInstanceSize = 0;
  3434. Status = PdhiEnumLoggedObjectItems(
  3435. (HLOG) pLog,
  3436. pCounter->pCounterPath->szMachineName,
  3437. pCounter->pCounterPath->szObjectName,
  3438. NULL,
  3439. & dwCounterSize,
  3440. NULL,
  3441. & dwInstanceSize,
  3442. 0,
  3443. 0,
  3444. TRUE);
  3445. if (Status != ERROR_SUCCESS && Status != PDH_MORE_DATA
  3446. && Status != PDH_INSUFFICIENT_BUFFER) {
  3447. goto Cleanup;
  3448. }
  3449. Status = ERROR_SUCCESS;
  3450. }
  3451. }
  3452. else {
  3453. Status = PDH_INVALID_ARGUMENT;
  3454. goto Cleanup;
  3455. }
  3456. if (dwObjectId == 0) {
  3457. dwObjectId = wcstoul(pCounter->pCounterPath->szObjectName, NULL, 10);
  3458. if (dwObjectId != 0) {
  3459. Status = ERROR_SUCCESS;
  3460. }
  3461. else {
  3462. Status = PDH_ENTRY_NOT_IN_LOG_FILE;
  3463. }
  3464. }
  3465. else {
  3466. Status = ERROR_SUCCESS;
  3467. }
  3468. if (Status != ERROR_SUCCESS) {
  3469. goto Cleanup;
  3470. }
  3471. pMachine = PdhWmiGetLogNameTable(pLog,
  3472. pCounter->pCounterPath->szMachineName,
  3473. 9);
  3474. if (pMachine == NULL) {
  3475. Status = PDH_ENTRY_NOT_IN_LOG_FILE;
  3476. goto Cleanup;
  3477. }
  3478. pHead = & pMachine->LogObjectList;
  3479. pNext = pHead->Flink;
  3480. while (pNext != pHead) {
  3481. PPDH_WMI_PERF_OBJECT pThisObject = CONTAINING_RECORD(
  3482. pNext, PDH_WMI_PERF_OBJECT, Entry);
  3483. if (pThisObject->dwObjectId == dwObjectId) {
  3484. pObject = pThisObject;
  3485. break;
  3486. }
  3487. pNext = pNext->Flink;
  3488. }
  3489. if (pObject == NULL) {
  3490. Status = PDH_ENTRY_NOT_IN_LOG_FILE;
  3491. goto Cleanup;
  3492. }
  3493. pDataBlock = (PPERF_DATA_BLOCK) pObject->ptrBuffer;
  3494. if (pDataBlock == NULL) {
  3495. Status = PDH_ENTRY_NOT_IN_LOG_FILE;
  3496. goto Cleanup;
  3497. }
  3498. pPerfObject = GetObjectDefByTitleIndex(pDataBlock, dwObjectId);
  3499. if (pPerfObject == NULL) {
  3500. Status = PDH_CSTATUS_NO_OBJECT;
  3501. goto Cleanup;
  3502. }
  3503. dwItems = 0;
  3504. pPerfCounter = FirstCounter(pPerfObject);
  3505. while (dwItems < pPerfObject->NumCounters) {
  3506. if ( pPerfCounter->CounterNameTitleIndex > 0
  3507. && pPerfCounter->CounterNameTitleIndex <= pMachine->dwLastId) {
  3508. if (lstrcmpiW(pCounter->pCounterPath->szCounterName,
  3509. pMachine->ptrStrAry[pPerfCounter->CounterNameTitleIndex])
  3510. == 0) {
  3511. break;
  3512. }
  3513. if ( dwCounterId != 0
  3514. && dwCounterId == pPerfCounter->CounterNameTitleIndex) {
  3515. break;
  3516. }
  3517. }
  3518. dwItems ++;
  3519. if (dwItems < pPerfObject->NumCounters) {
  3520. pPerfCounter = NextCounter(pPerfCounter);
  3521. if (pPerfCounter == NULL) {
  3522. break;
  3523. }
  3524. }
  3525. else {
  3526. pPerfCounter = NULL;
  3527. }
  3528. }
  3529. if (dwItems == pPerfObject->NumCounters) {
  3530. pPerfCounter = NULL;
  3531. }
  3532. if (pPerfCounter == NULL) {
  3533. Status = PDH_CSTATUS_NO_OBJECT;
  3534. goto Cleanup;
  3535. }
  3536. pCounter->plCounterInfo.dwObjectId = dwObjectId;
  3537. pCounter->plCounterInfo.dwCounterId = pPerfCounter->CounterNameTitleIndex;
  3538. pCounter->plCounterInfo.dwCounterType = pPerfCounter->CounterType;
  3539. pCounter->plCounterInfo.dwCounterSize = pPerfCounter->CounterSize;
  3540. pCounter->plCounterInfo.lDefaultScale = pPerfCounter->DefaultScale;
  3541. if (pCounter->plCounterInfo.dwCounterType & PERF_TIMER_100NS) {
  3542. pCounter->TimeBase = (LONGLONG) 10000000;
  3543. }
  3544. else if (pCounter->plCounterInfo.dwCounterType & PERF_OBJECT_TIMER) {
  3545. pCounter->TimeBase = pPerfObject->PerfFreq.QuadPart;
  3546. }
  3547. else {
  3548. pCounter->TimeBase = pDataBlock->PerfFreq.QuadPart;
  3549. }
  3550. if (pPerfObject->NumInstances == PERF_NO_INSTANCES) {
  3551. pCounter->plCounterInfo.lInstanceId = 0;
  3552. pCounter->plCounterInfo.szInstanceName = NULL;
  3553. pCounter->plCounterInfo.dwParentObjectId = 0;
  3554. pCounter->plCounterInfo.szParentInstanceName = NULL;
  3555. }
  3556. else {
  3557. pPerfInstance = FirstInstance(pPerfObject);
  3558. if (pPerfInstance->UniqueID == PERF_NO_UNIQUE_ID) {
  3559. pCounter->plCounterInfo.lInstanceId = PERF_NO_UNIQUE_ID;
  3560. pCounter->plCounterInfo.szInstanceName = pCounter->pCounterPath->szInstanceName;
  3561. pCounter->plCounterInfo.dwParentObjectId = (DWORD)PERF_NO_UNIQUE_ID;
  3562. pCounter->plCounterInfo.szParentInstanceName = pCounter->pCounterPath->szParentName;
  3563. }
  3564. else {
  3565. LONG lTempId;
  3566. if (pCounter->pCounterPath->szInstanceName != NULL) {
  3567. lTempId = wcstoul(pCounter->pCounterPath->szInstanceName,
  3568. NULL,
  3569. 10);
  3570. }
  3571. else {
  3572. lTempId = 0;
  3573. }
  3574. pCounter->plCounterInfo.lInstanceId = lTempId;
  3575. pCounter->plCounterInfo.szInstanceName = NULL;
  3576. if (pCounter->pCounterPath->szParentName != NULL) {
  3577. lTempId = wcstoul(pCounter->pCounterPath->szParentName,
  3578. NULL,
  3579. 10);
  3580. }
  3581. else {
  3582. lTempId = 0;
  3583. }
  3584. pCounter->plCounterInfo.dwParentObjectId = lTempId;
  3585. pCounter->plCounterInfo.szParentInstanceName = NULL;
  3586. }
  3587. }
  3588. Cleanup:
  3589. return Status;
  3590. }
  3591. PDH_FUNCTION
  3592. PdhiGetWmiLogFileSize(
  3593. IN PPDHI_LOG pLog,
  3594. IN LONGLONG * llSize)
  3595. {
  3596. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3597. LONGLONG SizeSum = 0;
  3598. DWORD dwFileSizeLow;
  3599. DWORD dwFileSizeHigh;
  3600. DWORD dwError;
  3601. HANDLE hFile;
  3602. if (pLog->dwLogFormat & PDH_LOG_WRITE_ACCESS) {
  3603. PPDH_EVENT_TRACE_PROPERTIES LoggerInfo =
  3604. (PPDH_EVENT_TRACE_PROPERTIES) pLog->lpMappedFileBase;
  3605. if (LoggerInfo != NULL && LoggerInfo->LogFileName != NULL
  3606. && LoggerInfo->LogFileName[0] != L'\0') {
  3607. hFile = CreateFileW(
  3608. LoggerInfo->LogFileName,
  3609. GENERIC_READ,
  3610. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3611. NULL,
  3612. OPEN_EXISTING,
  3613. FILE_ATTRIBUTE_NORMAL,
  3614. NULL);
  3615. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
  3616. DWORD Win32Error = GetLastError();
  3617. switch (Win32Error) {
  3618. case ERROR_FILE_NOT_FOUND:
  3619. pdhStatus = PDH_FILE_NOT_FOUND;
  3620. break;
  3621. case ERROR_ALREADY_EXISTS:
  3622. pdhStatus = PDH_FILE_ALREADY_EXISTS;
  3623. break;
  3624. default:
  3625. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  3626. break;
  3627. }
  3628. }
  3629. else {
  3630. dwFileSizeLow = GetFileSize(hFile, & dwFileSizeHigh);
  3631. if ( (dwFileSizeLow == 0xFFFFFFFF)
  3632. && ((dwError = GetLastError()) != NO_ERROR)) {
  3633. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  3634. }
  3635. else {
  3636. if (dwFileSizeHigh != 0) {
  3637. SizeSum += (dwFileSizeHigh << (sizeof(DWORD) * 8));
  3638. }
  3639. SizeSum += dwFileSizeLow;
  3640. }
  3641. CloseHandle(hFile);
  3642. }
  3643. }
  3644. else {
  3645. pdhStatus = PDH_INVALID_ARGUMENT;
  3646. }
  3647. }
  3648. else {
  3649. PPDH_LOGGER_CONTEXT CurrentContext =
  3650. (PPDH_LOGGER_CONTEXT) pLog->lpMappedFileBase;
  3651. if (GetLoggerContext(CurrentContext) < ContextCount) {
  3652. LONG i;
  3653. for (i = 0, hFile = NULL, dwFileSizeLow = 0, dwFileSizeHigh = 0;
  3654. (pdhStatus == ERROR_SUCCESS)
  3655. && (i < (LONG) CurrentContext->LogFileCount);
  3656. i ++, hFile = NULL, dwFileSizeLow = 0, dwFileSizeHigh = 0) {
  3657. hFile = CreateFileW(
  3658. CurrentContext->LogFileName[i],
  3659. GENERIC_READ,
  3660. FILE_SHARE_READ | FILE_SHARE_WRITE,
  3661. NULL,
  3662. OPEN_EXISTING,
  3663. FILE_ATTRIBUTE_NORMAL,
  3664. NULL);
  3665. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE) {
  3666. DWORD Win32Error = GetLastError();
  3667. switch (Win32Error) {
  3668. case ERROR_FILE_NOT_FOUND:
  3669. pdhStatus = PDH_FILE_NOT_FOUND;
  3670. break;
  3671. case ERROR_ALREADY_EXISTS:
  3672. pdhStatus = PDH_FILE_ALREADY_EXISTS;
  3673. break;
  3674. default:
  3675. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  3676. break;
  3677. }
  3678. break;
  3679. }
  3680. dwFileSizeLow = GetFileSize(hFile, & dwFileSizeHigh);
  3681. if ( (dwFileSizeLow == 0xFFFFFFFF)
  3682. && ((dwError = GetLastError()) != NO_ERROR)) {
  3683. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  3684. }
  3685. else {
  3686. if (dwFileSizeHigh != 0) {
  3687. SizeSum = SizeSum + (dwFileSizeHigh << (sizeof(DWORD) * 8));
  3688. }
  3689. SizeSum += dwFileSizeLow;
  3690. }
  3691. CloseHandle(hFile);
  3692. }
  3693. }
  3694. else {
  3695. pdhStatus = PDH_INVALID_ARGUMENT;
  3696. }
  3697. }
  3698. if (pdhStatus == ERROR_SUCCESS) {
  3699. __try {
  3700. * llSize = SizeSum;
  3701. }
  3702. __except (EXCEPTION_EXECUTE_HANDLER) {
  3703. pdhStatus = PDH_INVALID_ARGUMENT;
  3704. }
  3705. }
  3706. return pdhStatus;
  3707. }