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.

2209 lines
83 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. log_pm.c
  5. Abstract:
  6. <abstract>
  7. --*/
  8. #include <windows.h>
  9. #include <limits.h>
  10. #include <pdh.h>
  11. #include "pdhidef.h"
  12. #include "perftype.h"
  13. #include "log_pm.h"
  14. #include "pdhmsg.h"
  15. #include "perftype.h"
  16. #include "perfdata.h"
  17. #define PointerSeek(pBase, lFileOffset) ((PVOID) ((PBYTE) pBase + lFileOffset))
  18. int
  19. PdhiCompareLogCounterInstance(
  20. PPDHI_LOG_COUNTER pCounter,
  21. LPWSTR szCounter,
  22. LPWSTR szInstance,
  23. DWORD dwInstance,
  24. LPWSTR szParent
  25. );
  26. void
  27. PdhiFreeLogCounterNode(
  28. PPDHI_LOG_COUNTER pCounter,
  29. DWORD dwLevel
  30. );
  31. void
  32. PdhiFreeLogObjectNode(
  33. PPDHI_LOG_OBJECT pObject,
  34. DWORD dwLevel
  35. );
  36. void
  37. PdhiFreeLogMachineTable(
  38. PPDHI_LOG_MACHINE * MachineTable
  39. );
  40. PPDHI_LOG_MACHINE
  41. PdhiFindLogMachine(
  42. PPDHI_LOG_MACHINE * MachineTable,
  43. LPWSTR szMachine,
  44. BOOL bInsert
  45. );
  46. PPDHI_LOG_OBJECT
  47. PdhiFindLogObject(
  48. PPDHI_LOG_MACHINE pMachine,
  49. PPDHI_LOG_OBJECT * ObjectTable,
  50. LPWSTR szObject,
  51. BOOL bInsert
  52. );
  53. PPDHI_LOG_COUNTER
  54. PdhiFindLogCounter(
  55. PPDHI_LOG pLog,
  56. PPDHI_LOG_MACHINE * MachineTable,
  57. LPWSTR szMachine,
  58. LPWSTR szObject,
  59. LPWSTR szCounter,
  60. DWORD dwCounterType,
  61. DWORD dwDefaultScale,
  62. LPWSTR szInstance,
  63. DWORD dwInstance,
  64. LPWSTR szParent,
  65. DWORD dwParent,
  66. LPDWORD pdwIndex,
  67. BOOL bInsert
  68. );
  69. PDH_FUNCTION
  70. PdhiEnumCachedMachines(
  71. PPDHI_LOG_MACHINE MachineList,
  72. LPVOID pBuffer,
  73. LPDWORD lpdwBufferSize,
  74. BOOL bUnicodeDest
  75. )
  76. {
  77. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  78. DWORD dwBufferUsed = 0;
  79. DWORD dwNewBuffer = 0;
  80. DWORD dwItemCount = 0;
  81. LPVOID LocalBuffer = NULL;
  82. LPVOID TempBuffer = NULL;
  83. DWORD LocalBufferSize = 0;
  84. PPDHI_LOG_MACHINE pMachine;
  85. LocalBufferSize = MEDIUM_BUFFER_SIZE;
  86. LocalBuffer = G_ALLOC(LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
  87. if (LocalBuffer == NULL) {
  88. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  89. goto Cleanup;
  90. }
  91. dwItemCount = 0;
  92. dwBufferUsed = 0;
  93. dwItemCount = 0;
  94. for (pMachine = MachineList; pMachine != NULL; pMachine = pMachine->next) {
  95. if (pMachine->szMachine != NULL) {
  96. dwNewBuffer = (lstrlenW(pMachine->szMachine) + 1);
  97. while (LocalBufferSize < (dwBufferUsed + dwNewBuffer)) {
  98. TempBuffer = LocalBuffer;
  99. LocalBufferSize += MEDIUM_BUFFER_SIZE;
  100. LocalBuffer = G_REALLOC(TempBuffer, LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
  101. if (LocalBuffer == NULL) {
  102. if (TempBuffer != NULL) G_FREE(TempBuffer);
  103. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  104. goto Cleanup;
  105. }
  106. }
  107. dwNewBuffer = AddUniqueWideStringToMultiSz((LPVOID) LocalBuffer, pMachine->szMachine, bUnicodeDest);
  108. if (dwNewBuffer > 0) {
  109. dwBufferUsed = dwNewBuffer;
  110. dwItemCount ++;
  111. }
  112. }
  113. else {
  114. dwNewBuffer = 0;
  115. }
  116. }
  117. if (pdhStatus == ERROR_SUCCESS) {
  118. if (dwItemCount > 0) {
  119. dwBufferUsed ++;
  120. }
  121. if (pBuffer && (dwBufferUsed <= * lpdwBufferSize)) {
  122. RtlCopyMemory(pBuffer, LocalBuffer, dwBufferUsed * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
  123. }
  124. else {
  125. if (pBuffer) RtlCopyMemory(pBuffer,
  126. LocalBuffer,
  127. (* lpdwBufferSize) * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
  128. pdhStatus = PDH_MORE_DATA;
  129. }
  130. * lpdwBufferSize = dwBufferUsed;
  131. }
  132. Cleanup:
  133. if (LocalBuffer != NULL) G_FREE(LocalBuffer);
  134. return pdhStatus;
  135. }
  136. PDH_FUNCTION
  137. PdhiEnumCachedObjects(
  138. PPDHI_LOG_MACHINE MachineList,
  139. LPCWSTR szMachineName,
  140. LPVOID pBuffer,
  141. LPDWORD pcchBufferSize,
  142. DWORD dwDetailLevel,
  143. BOOL bUnicodeDest
  144. )
  145. {
  146. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  147. DWORD dwBufferUsed = 0;
  148. DWORD dwNewBuffer = 0;
  149. DWORD dwItemCount = 0;
  150. LPVOID LocalBuffer = NULL;
  151. LPVOID TempBuffer = NULL;
  152. DWORD LocalBufferSize = 0;
  153. PPDHI_LOG_MACHINE pMachine = NULL;
  154. PPDHI_LOG_OBJECT pObject = NULL;
  155. LPWSTR szLocMachine = (LPWSTR) szMachineName;
  156. UNREFERENCED_PARAMETER(dwDetailLevel);
  157. LocalBufferSize = MEDIUM_BUFFER_SIZE;
  158. LocalBuffer = G_ALLOC(LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
  159. if (LocalBuffer == NULL) {
  160. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  161. goto Cleanup;
  162. }
  163. if (szLocMachine == NULL) szLocMachine = (LPWSTR) szStaticLocalMachineName;
  164. dwBufferUsed = 0;
  165. dwNewBuffer = 0;
  166. dwItemCount = 0;
  167. for (pMachine = MachineList; pMachine != NULL; pMachine = pMachine->next) {
  168. if (lstrcmpiW(pMachine->szMachine, szLocMachine) == 0) break;
  169. }
  170. if (pMachine != NULL) {
  171. for (pObject = pMachine->ObjList; pObject != NULL; pObject = pObject->next) {
  172. if (pObject->szObject != NULL) {
  173. dwNewBuffer = (lstrlenW(pObject->szObject) + 1);
  174. while (LocalBufferSize < (dwBufferUsed + dwNewBuffer)) {
  175. LocalBufferSize += MEDIUM_BUFFER_SIZE;
  176. TempBuffer = LocalBuffer;
  177. LocalBuffer = G_REALLOC(TempBuffer,
  178. LocalBufferSize * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
  179. if (LocalBuffer == NULL) {
  180. if (TempBuffer != NULL) G_FREE(TempBuffer);
  181. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  182. goto Cleanup;
  183. }
  184. }
  185. dwNewBuffer = AddUniqueWideStringToMultiSz((LPVOID) LocalBuffer, pObject->szObject, bUnicodeDest);
  186. if (dwNewBuffer > 0) {
  187. dwBufferUsed = dwNewBuffer;
  188. dwItemCount ++;
  189. }
  190. }
  191. else {
  192. dwNewBuffer = 0;
  193. }
  194. }
  195. }
  196. else {
  197. pdhStatus = PDH_CSTATUS_NO_MACHINE;
  198. }
  199. if (pdhStatus == ERROR_SUCCESS) {
  200. if (dwItemCount > 0) {
  201. dwBufferUsed ++;
  202. }
  203. if (dwBufferUsed > 0) {
  204. if (pBuffer && (dwBufferUsed <= * pcchBufferSize)) {
  205. RtlCopyMemory(pBuffer, LocalBuffer, dwBufferUsed * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
  206. }
  207. else {
  208. if (pBuffer) RtlCopyMemory(pBuffer,
  209. LocalBuffer,
  210. (* pcchBufferSize) * (bUnicodeDest ? sizeof(WCHAR) : sizeof(CHAR)));
  211. pdhStatus = PDH_MORE_DATA;
  212. }
  213. }
  214. * pcchBufferSize = dwBufferUsed;
  215. }
  216. Cleanup:
  217. G_FREE(LocalBuffer);
  218. return pdhStatus;
  219. }
  220. PDH_FUNCTION
  221. PdhiEnumCachedObjectItems(
  222. PPDHI_LOG_MACHINE MachineList,
  223. LPCWSTR szMachineName,
  224. LPCWSTR szObjectName,
  225. PDHI_COUNTER_TABLE CounterTable,
  226. DWORD dwDetailLevel,
  227. DWORD dwFlags
  228. )
  229. {
  230. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  231. DWORD dwItemCount = 0;
  232. LPWSTR szFullInstance = NULL;
  233. DWORD dwFullInstance = SMALL_BUFFER_SIZE;
  234. LPWSTR szLocMachine = (LPWSTR) szMachineName;
  235. PPDHI_INSTANCE pInstance;
  236. PPDHI_INST_LIST pInstList;
  237. PPDHI_LOG_MACHINE pMachine = NULL;
  238. PPDHI_LOG_OBJECT pObject = NULL;
  239. PPDHI_LOG_COUNTER pCounter = NULL;
  240. UNREFERENCED_PARAMETER(dwDetailLevel);
  241. UNREFERENCED_PARAMETER(dwFlags);
  242. if (szLocMachine == NULL) szLocMachine = (LPWSTR) szStaticLocalMachineName;
  243. for (pMachine = MachineList; pMachine != NULL; pMachine = pMachine->next) {
  244. if (lstrcmpiW(pMachine->szMachine, szLocMachine) == 0) break;
  245. }
  246. if (pMachine != NULL) {
  247. pObject = PdhiFindLogObject(pMachine, & (pMachine->ObjTable), (LPWSTR) szObjectName, FALSE);
  248. }
  249. else {
  250. pdhStatus = PDH_CSTATUS_NO_MACHINE;
  251. pObject = NULL;
  252. }
  253. if (pObject != NULL) {
  254. WCHAR szIndexNumber[20];
  255. szFullInstance = G_ALLOC(dwFullInstance * sizeof(WCHAR));
  256. if (szFullInstance == NULL) {
  257. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  258. goto Cleanup;
  259. }
  260. for (pCounter = pObject->CtrList; pCounter != NULL; pCounter = pCounter->next) {
  261. pdhStatus = PdhiFindCounterInstList(CounterTable, pCounter->szCounter, & pInstList);
  262. if (pdhStatus != ERROR_SUCCESS) continue;
  263. if (pCounter->szInstance != NULL && pCounter->szInstance[0] != L'\0') {
  264. if (pCounter->szParent != NULL && pCounter->szParent[0] != L'\0') {
  265. swprintf(szFullInstance, L"%ws%ws%ws",
  266. pCounter->szParent, L"/", pCounter->szInstance);
  267. }
  268. else {
  269. lstrcpynW(szFullInstance, pCounter->szInstance, dwFullInstance);
  270. }
  271. if (pCounter->dwInstance > 0) {
  272. ZeroMemory(szIndexNumber, 20 * sizeof(WCHAR));
  273. _ultow(pCounter->dwInstance, szIndexNumber, 10);
  274. lstrcatW(szFullInstance, L"#");
  275. lstrcatW(szFullInstance, szIndexNumber);
  276. }
  277. pdhStatus = PdhiFindInstance(& pInstList->InstList, szFullInstance, TRUE, & pInstance);
  278. }
  279. if (pdhStatus == ERROR_SUCCESS) {
  280. dwItemCount ++;
  281. }
  282. }
  283. }
  284. else if (pdhStatus == ERROR_SUCCESS) {
  285. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  286. }
  287. if (dwItemCount > 0) {
  288. // then the routine was successful. Errors that occurred
  289. // while scanning will be ignored as long as at least
  290. // one entry was successfully read
  291. pdhStatus = ERROR_SUCCESS;
  292. }
  293. Cleanup:
  294. G_FREE(szFullInstance);
  295. return pdhStatus;
  296. }
  297. int
  298. PdhiComparePmLogInstance(
  299. PPDHI_LOG_COUNTER pCounter,
  300. LPWSTR szInstance,
  301. DWORD dwInstance,
  302. LPWSTR szParent,
  303. BOOL bUpdate
  304. )
  305. {
  306. int iResult = 0;
  307. if ((pCounter->szInstance != NULL && pCounter->szInstance[0] != L'\0')
  308. && (szInstance != NULL && szInstance[0] != L'\0')) {
  309. iResult = lstrcmpiW(szInstance, pCounter->szInstance);
  310. }
  311. else if ((pCounter->szInstance != NULL && pCounter->szInstance[0] != L'\0')
  312. && (szInstance == NULL || szInstance[0] == L'\0')) {
  313. iResult = -1;
  314. }
  315. else if ((pCounter->szInstance == NULL || pCounter->szInstance[0] == L'\0')
  316. && (szInstance != NULL && szInstance[0] != L'\0')) {
  317. iResult = 1;
  318. }
  319. if (iResult != 0) goto Cleanup;
  320. iResult = (dwInstance < pCounter->dwInstance) ? (-1) : ((dwInstance > pCounter->dwInstance) ? (1) : (0));
  321. if (iResult != 0) goto Cleanup;
  322. if ((pCounter->szParent != NULL && pCounter->szParent[0] != L'\0')
  323. && (szParent != NULL && szParent[0] != L'\0')) {
  324. iResult = lstrcmpiW(szParent, pCounter->szParent);
  325. }
  326. else if ((pCounter->szParent != NULL && pCounter->szParent[0] != L'\0')
  327. && (szParent == NULL || szParent[0] == L'\0')) {
  328. iResult = -1;
  329. }
  330. else if ((pCounter->szParent == NULL || pCounter->szParent[0] == L'\0')
  331. && (szParent != NULL && szParent[0] != L'\0')) {
  332. iResult = 1;
  333. }
  334. Cleanup:
  335. return iResult;
  336. }
  337. PPDHI_LOG_COUNTER
  338. PdhiFindPmCounterInstance(
  339. PPDHI_LOG_OBJECT pObject,
  340. LPWSTR szCounter,
  341. DWORD dwCounterType,
  342. DWORD dwDefaultScale,
  343. LPWSTR szInstance,
  344. DWORD dwInstance,
  345. LPWSTR szParent,
  346. DWORD dwParent,
  347. LPDWORD pdwIndex,
  348. BOOL bInstance,
  349. BOOL bInsert
  350. )
  351. {
  352. PPDHI_LOG_COUNTER pCounter = NULL;
  353. PPDHI_LOG_COUNTER pNode = NULL;
  354. PPDHI_LOG_COUNTER * pStack[MAX_BTREE_DEPTH];
  355. PPDHI_LOG_COUNTER * pLink;
  356. int dwStack = 0;
  357. PPDHI_LOG_COUNTER pParent;
  358. PPDHI_LOG_COUNTER pSibling;
  359. PPDHI_LOG_COUNTER pChild;
  360. int iCompare;
  361. if (bInstance) {
  362. pStack[dwStack ++] = & (pObject->InstTable);
  363. pCounter = pObject->InstTable;
  364. }
  365. else {
  366. pStack[dwStack ++] = & (pObject->CtrTable);
  367. pCounter = pObject->CtrTable;
  368. }
  369. while (pCounter != NULL) {
  370. if (bInstance) {
  371. iCompare = PdhiComparePmLogInstance(pCounter, szInstance, dwInstance, szParent, bInsert);
  372. }
  373. else {
  374. iCompare = lstrcmpiW(szCounter, pCounter->szCounter);
  375. }
  376. if (iCompare < 0) {
  377. pStack[dwStack ++] = & (pCounter->left);
  378. pCounter = pCounter->left;
  379. }
  380. else if (iCompare > 0) {
  381. pStack[dwStack ++] = & (pCounter->right);
  382. pCounter = pCounter->right;
  383. }
  384. else {
  385. break;
  386. }
  387. }
  388. if (bInsert) {
  389. if (pCounter == NULL) {
  390. DWORD dwCounterLen = lstrlenW(szCounter) + 1;
  391. DWORD dwInstanceLen = 0;
  392. DWORD dwParentLen = 0;
  393. DWORD dwBufSize = sizeof(PDHI_LOG_COUNTER) + sizeof(WCHAR) * dwCounterLen;
  394. if (szInstance != NULL) {
  395. dwInstanceLen = lstrlenW(szInstance) + 1;
  396. dwBufSize += (sizeof(WCHAR) * dwInstanceLen);
  397. }
  398. else {
  399. dwBufSize += sizeof(WCHAR);
  400. }
  401. if (szParent != NULL) {
  402. dwParentLen = lstrlenW(szParent) + 1;
  403. dwBufSize += (sizeof(WCHAR) * dwParentLen);
  404. }
  405. else {
  406. dwBufSize += sizeof(WCHAR);
  407. }
  408. pCounter = G_ALLOC(dwBufSize);
  409. if (pCounter == NULL) goto Cleanup;
  410. if (bInstance) {
  411. pCounter->next = pObject->InstList;
  412. pObject->InstList = pCounter;
  413. }
  414. else {
  415. pCounter->next = pObject->CtrList;
  416. pObject->CtrList = pCounter;
  417. }
  418. pCounter->bIsRed = TRUE;
  419. pCounter->left = NULL;
  420. pCounter->right = NULL;
  421. pCounter->dwParent = dwParent;
  422. pCounter->TimeStamp = 0;
  423. pCounter->dwInstance = dwInstance;
  424. pCounter->dwCounterID = (* pdwIndex);
  425. if (! bInstance) {
  426. pCounter->dwCounterType = dwCounterType;
  427. pCounter->dwDefaultScale = dwDefaultScale;
  428. }
  429. if (szCounter == NULL || szCounter[0] == L'\0') {
  430. pCounter->szCounter = NULL;
  431. }
  432. else {
  433. pCounter->szCounter = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER));
  434. lstrcpynW(pCounter->szCounter, szCounter, dwCounterLen);
  435. }
  436. if (szInstance == NULL || szInstance[0] == L'\0') {
  437. pCounter->szInstance = NULL;
  438. }
  439. else {
  440. pCounter->szInstance = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER)
  441. + sizeof(WCHAR) * dwCounterLen);
  442. lstrcpynW(pCounter->szInstance, szInstance, dwInstanceLen);
  443. }
  444. if (szParent == NULL || szParent[0] == L'\0') {
  445. pCounter->szParent = NULL;
  446. }
  447. else {
  448. if (pCounter->szInstance != NULL) {
  449. pCounter->szParent = (LPWSTR) (((PCHAR) pCounter)
  450. + sizeof(PDHI_LOG_COUNTER) + sizeof(WCHAR) * (dwCounterLen + dwInstanceLen));
  451. }
  452. else {
  453. pCounter->szParent = (LPWSTR) (((PCHAR) pCounter) + sizeof(PDHI_LOG_COUNTER)
  454. + sizeof(WCHAR) * dwCounterLen);
  455. }
  456. lstrcpynW(pCounter->szParent, szParent, dwParentLen);
  457. }
  458. pLink = pStack[-- dwStack];
  459. * pLink = pCounter;
  460. pChild = NULL;
  461. pNode = pCounter;
  462. while (dwStack > 0) {
  463. pLink = pStack[-- dwStack];
  464. pParent = * pLink;
  465. if (! pParent->bIsRed) {
  466. pSibling = (pParent->left == pNode) ? pParent->right : pParent->left;
  467. if (pSibling && pSibling->bIsRed) {
  468. pNode->bIsRed = FALSE;
  469. pSibling->bIsRed = FALSE;
  470. pParent->bIsRed = TRUE;
  471. }
  472. else {
  473. if (pChild && pChild->bIsRed) {
  474. if (pChild == pNode->left) {
  475. if (pNode == pParent->left) {
  476. pParent->bIsRed = TRUE;
  477. pParent->left = pNode->right;
  478. pNode->right = pParent;
  479. pNode->bIsRed = FALSE;
  480. * pLink = pNode;
  481. }
  482. else {
  483. pParent->bIsRed = TRUE;
  484. pParent->right = pChild->left;
  485. pChild->left = pParent;
  486. pNode->left = pChild->right;
  487. pChild->right = pNode;
  488. pChild->bIsRed = FALSE;
  489. * pLink = pChild;
  490. }
  491. }
  492. else {
  493. if (pNode == pParent->right) {
  494. pParent->bIsRed = TRUE;
  495. pParent->right = pNode->left;
  496. pNode->left = pParent;
  497. pNode->bIsRed = FALSE;
  498. * pLink = pNode;
  499. }
  500. else {
  501. pParent->bIsRed = TRUE;
  502. pParent->left = pChild->right;
  503. pChild->right = pParent;
  504. pNode->right = pChild->left;
  505. pChild->left = pNode;
  506. pChild->bIsRed = FALSE;
  507. * pLink = pChild;
  508. }
  509. }
  510. }
  511. break;
  512. }
  513. }
  514. pChild = pNode;
  515. pNode = pParent;
  516. }
  517. if (bInstance) {
  518. pObject->InstTable->bIsRed = FALSE;
  519. }
  520. else {
  521. pObject->CtrTable->bIsRed = FALSE;
  522. }
  523. }
  524. else if (bInstance) {
  525. pCounter->dwCounterType ++;
  526. if (pCounter->dwCounterType > pCounter->dwDefaultScale) {
  527. pCounter->dwDefaultScale = pCounter->dwCounterType;
  528. }
  529. }
  530. }
  531. else if (pCounter != NULL) {
  532. * pdwIndex = pCounter->dwCounterID;
  533. }
  534. Cleanup:
  535. return pCounter;
  536. }
  537. PDH_FUNCTION
  538. PdhiBuildPmLogIndexTable(
  539. PPLAYBACKLOG pPmLog
  540. )
  541. {
  542. PDH_STATUS Status = ERROR_SUCCESS;
  543. PLOGHEADER pLogHeader = (PLOGHEADER) pPmLog->pHeader;
  544. PLOGINDEXBLOCK pIndexBlock = NULL;
  545. DWORD dwOffset = pLogHeader->iLength;
  546. DWORD dwIndex = 0;
  547. int i;
  548. if (dwOffset == sizeof(LOGHEADER)) {
  549. while (dwOffset != 0) {
  550. pIndexBlock = (PLOGINDEXBLOCK) PointerSeek(pLogHeader, dwOffset);
  551. dwIndex += pIndexBlock->iNumIndexes;
  552. dwOffset = pIndexBlock->lNextBlockOffset;
  553. }
  554. pPmLog->dwLastIndex = dwIndex;
  555. G_FREE(pPmLog->LogIndexTable);
  556. pPmLog->LogIndexTable = G_ALLOC(dwIndex * sizeof(PLOGINDEX));
  557. if (pPmLog->LogIndexTable == NULL) {
  558. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  559. goto Cleanup;
  560. }
  561. dwIndex = 0;
  562. dwOffset = pLogHeader->iLength;
  563. while (dwOffset != 0) {
  564. pIndexBlock = (PLOGINDEXBLOCK) PointerSeek(pLogHeader, dwOffset);
  565. for (i = 0; i < pIndexBlock->iNumIndexes; i ++) {
  566. pPmLog->LogIndexTable[dwIndex + i] = & (pIndexBlock->aIndexes[i]);
  567. }
  568. dwIndex += pIndexBlock->iNumIndexes;
  569. dwOffset = pIndexBlock->lNextBlockOffset;
  570. }
  571. }
  572. else {
  573. Status = PDH_INVALID_ARGUMENT;
  574. }
  575. Cleanup:
  576. if (Status != ERROR_SUCCESS) {
  577. G_FREE(pPmLog->LogIndexTable);
  578. pPmLog->dwLastIndex = 0;
  579. pPmLog->dwCurrentIndex = 0;
  580. }
  581. return Status;
  582. }
  583. void
  584. PdhiFreeCounterStringNode(
  585. PPDHI_PM_STRING pString,
  586. DWORD dwLevel
  587. )
  588. {
  589. if (pString != NULL) {
  590. if (pString->left != NULL) {
  591. PdhiFreeCounterStringNode(pString->left, dwLevel + 1);
  592. }
  593. if (pString->right != NULL) {
  594. PdhiFreeCounterStringNode(pString->right, dwLevel + 1);
  595. }
  596. G_FREE(pString);
  597. }
  598. }
  599. void
  600. PdhiFreePmMachineList(
  601. PPLAYBACKLOG pPmLog
  602. )
  603. {
  604. PPMLOG_COUNTERNAMES pMachine = pPmLog->pFirstCounterNameTables;
  605. PPMLOG_COUNTERNAMES pTmpMachine;
  606. while (pMachine != NULL) {
  607. pTmpMachine = pMachine;
  608. pMachine = pTmpMachine->pNext;
  609. PdhiFreeCounterStringNode(pTmpMachine->StringTree, 0);
  610. G_FREE(pTmpMachine);
  611. }
  612. }
  613. PPDHI_PM_STRING
  614. PdhiFindPmString(
  615. PPMLOG_COUNTERNAMES pMachine,
  616. LPCWSTR szString,
  617. LPDWORD pdwIndex,
  618. BOOL bInsert
  619. )
  620. {
  621. PDH_STATUS Status = ERROR_SUCCESS;
  622. PPDHI_PM_STRING * pStack[MAX_BTREE_DEPTH];
  623. int iStack = 0;
  624. int iCompare = 0;
  625. PPDHI_PM_STRING pString = pMachine->StringTree;
  626. PPDHI_PM_STRING * pLink;
  627. PPDHI_PM_STRING pNode;
  628. PPDHI_PM_STRING pParent;
  629. PPDHI_PM_STRING pSibling;
  630. PPDHI_PM_STRING pChild;
  631. pStack[iStack ++] = & pMachine->StringTree;
  632. while (pString != NULL) {
  633. iCompare = lstrcmpiW(szString, pString->szString);
  634. if (iCompare > 0) {
  635. if (iStack >= MAX_BTREE_DEPTH) {
  636. Status = PDH_UNABLE_READ_LOG_HEADER;
  637. break;
  638. }
  639. pStack[iStack ++] = & (pString->right);
  640. pString = pString->right;
  641. }
  642. else if (iCompare < 0) {
  643. if (iStack >= MAX_BTREE_DEPTH) {
  644. Status = PDH_UNABLE_READ_LOG_HEADER;
  645. break;
  646. }
  647. pStack[iStack ++] = & (pString->left);
  648. pString = pString->left;
  649. }
  650. else {
  651. break;
  652. }
  653. }
  654. if (Status != ERROR_SUCCESS) goto Cleanup;
  655. if (pString != NULL) {
  656. if (pdwIndex != NULL) {
  657. * pdwIndex = pString->dwIndex;
  658. }
  659. }
  660. else if (bInsert && pdwIndex != NULL) {
  661. pString = G_ALLOC(sizeof(PDHI_PM_STRING));
  662. if (pString != NULL) {
  663. pString->szString = (LPWSTR) szString;
  664. pString->dwIndex = * pdwIndex;
  665. pString->bIsRed = TRUE;
  666. pString->left = NULL;
  667. pString->right = NULL;
  668. pLink = pStack[-- iStack];
  669. * pLink = pString;
  670. pNode = pString;
  671. pChild = NULL;
  672. while (iStack > 0) {
  673. pLink = pStack[-- iStack];
  674. pParent = * pLink;
  675. if (! pParent->bIsRed) {
  676. pSibling = (pParent->left == pNode) ? pParent->right : pParent->left;
  677. if (pSibling && pSibling->bIsRed) {
  678. pNode->bIsRed = FALSE;
  679. pSibling->bIsRed = FALSE;
  680. pParent->bIsRed = TRUE;
  681. }
  682. else {
  683. if (pChild && pChild->bIsRed) {
  684. if (pChild == pNode->left) {
  685. if (pNode == pParent->left) {
  686. pParent->bIsRed = TRUE;
  687. pParent->left = pNode->right;
  688. pNode->right = pParent;
  689. pNode->bIsRed = FALSE;
  690. * pLink = pNode;
  691. }
  692. else {
  693. pParent->bIsRed = TRUE;
  694. pParent->right = pChild->left;
  695. pChild->left = pParent;
  696. pNode->left = pChild->right;
  697. pChild->right = pNode;
  698. pChild->bIsRed = FALSE;
  699. * pLink = pChild;
  700. }
  701. }
  702. else {
  703. if (pNode == pParent->right) {
  704. pParent->bIsRed = TRUE;
  705. pParent->right = pNode->left;
  706. pNode->left = pParent;
  707. pNode->bIsRed = FALSE;
  708. * pLink = pNode;
  709. }
  710. else {
  711. pParent->bIsRed = TRUE;
  712. pParent->left = pChild->right;
  713. pChild->right = pParent;
  714. pNode->right = pChild->left;
  715. pChild->left = pNode;
  716. pChild->bIsRed = FALSE;
  717. * pLink = pChild;
  718. }
  719. }
  720. }
  721. break;
  722. }
  723. }
  724. pChild = pNode;
  725. pNode = pParent;
  726. }
  727. pMachine->StringTree->bIsRed = FALSE;
  728. }
  729. else {
  730. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  731. }
  732. }
  733. Cleanup:
  734. if (Status != ERROR_SUCCESS) SetLastError(Status);
  735. return pString;
  736. }
  737. PDH_FUNCTION
  738. PdhiBuildPmLogStringTable(
  739. PPLAYBACKLOG pPmLog,
  740. PLOGFILECOUNTERNAME pLogName,
  741. PPMLOG_COUNTERNAMES pMachine,
  742. long lSize
  743. )
  744. {
  745. PDH_STATUS Status = ERROR_SUCCESS;
  746. PPDHI_PM_STRING pString;
  747. LPWSTR szName;
  748. DWORD dwName;
  749. DWORD dwIndex;
  750. long lUsed = 0;
  751. if (lSize > pLogName->lUnmatchCounterNames
  752. || pLogName->lCurrentCounterNameOffset < 0
  753. || pLogName->lCurrentCounterNameOffset >= pPmLog->llFileSize
  754. || pLogName->lCurrentCounterNameOffset + pLogName->lUnmatchCounterNames > pPmLog->llFileSize) {
  755. Status = PDH_UNABLE_READ_LOG_HEADER;
  756. }
  757. else if (pLogName->lBaseCounterNameOffset > 0) {
  758. PLOGFILECOUNTERNAME pBaseName = (PLOGFILECOUNTERNAME)
  759. PointerSeek(pPmLog->pHeader, pLogName->lBaseCounterNameOffset);
  760. Status = PdhiBuildPmLogStringTable(pPmLog, pBaseName, pMachine, pLogName->lMatchLength);
  761. }
  762. if (Status != ERROR_SUCCESS) goto Cleanup;
  763. szName = (LPWSTR) PointerSeek(pPmLog->pHeader, pLogName->lCurrentCounterNameOffset);
  764. while (Status == ERROR_SUCCESS && lUsed <= lSize && szName[0] != L'\0') {
  765. dwIndex = wcstoul(szName, NULL, 10);
  766. if (dwIndex > 0 && dwIndex <= pMachine->dwLastIndex) {
  767. dwName = lstrlenW(szName) + 1;
  768. lUsed += (sizeof(WCHAR) * dwName);
  769. if (lUsed <= lSize) {
  770. szName += dwName;
  771. pMachine->szNameTable[dwIndex] = szName;
  772. pString = PdhiFindPmString(pMachine, szName, & dwIndex, TRUE);
  773. if (pString == NULL) Status = GetLastError();
  774. }
  775. }
  776. dwName = lstrlenW(szName) + 1;
  777. lUsed += (sizeof(WCHAR) * dwName);
  778. szName += dwName;
  779. }
  780. Cleanup:
  781. return Status;
  782. }
  783. DWORD
  784. PdhiLookupLogPerfIndexByName(
  785. PPLAYBACKLOG pPlaybackLog,
  786. LPCWSTR szMachineName,
  787. DWORD dwLangId,
  788. DWORD dwLastId,
  789. LPCWSTR szNameBuffer
  790. )
  791. {
  792. DWORD dwIndex = 0;
  793. PDH_STATUS Status = PDH_CSTATUS_NO_MACHINE;
  794. PPMLOG_COUNTERNAMES pMachine = pPlaybackLog->pFirstCounterNameTables;
  795. while (pMachine != NULL) {
  796. if (lstrcmpiW(szMachineName, pMachine->szSystemName) == 0) break;
  797. pMachine = pMachine->pNext;
  798. }
  799. if (pMachine != NULL) {
  800. PPDHI_PM_STRING pString = PdhiFindPmString(pMachine, szNameBuffer, & dwIndex, FALSE);
  801. if (pString == NULL) {
  802. Status = GetLastError();
  803. dwIndex = wcstoul(szNameBuffer, NULL, 10);
  804. }
  805. }
  806. if (dwIndex == 0) SetLastError(Status);
  807. return dwIndex;
  808. }
  809. LPCWSTR
  810. PdhiLookupLogPerfNameByIndex(
  811. PPLAYBACKLOG pPlaybackLog,
  812. LPCWSTR szMachineName,
  813. DWORD dwLangId,
  814. DWORD dwIndex
  815. )
  816. {
  817. PPMLOG_COUNTERNAMES pMachine = pPlaybackLog->pFirstCounterNameTables;
  818. LPWSTR szReturn = NULL;
  819. static WCHAR szNumber[16];
  820. while (pMachine != NULL) {
  821. if (lstrcmpiW(szMachineName, pMachine->szSystemName) == 0) break;
  822. pMachine = pMachine->pNext;
  823. }
  824. if (pMachine != NULL) {
  825. if (dwIndex <= pMachine->dwLastIndex && dwLangId == pMachine->dwLangId) {
  826. szReturn = pMachine->szNameTable[dwIndex];
  827. }
  828. if (szReturn == NULL) {
  829. SetLastError(PDH_CSTATUS_NO_OBJECT);
  830. ZeroMemory(szNumber, sizeof(szNumber));
  831. _ltow(dwIndex, szNumber, 10);
  832. szReturn = szNumber;
  833. }
  834. }
  835. else {
  836. SetLastError(PDH_CSTATUS_NO_MACHINE);
  837. }
  838. return (LPCWSTR) szReturn;
  839. }
  840. PDH_FUNCTION
  841. PdhiCachePerfDataBlock(
  842. PPLAYBACKLOG pPmLog,
  843. PLOGINDEX pIndex
  844. )
  845. {
  846. PDH_STATUS Status = ERROR_SUCCESS;
  847. PPERF_DATA_BLOCK pBlock;
  848. PPERF_OBJECT_TYPE pObject;
  849. PPERF_COUNTER_DEFINITION pCounter;
  850. int i;
  851. PVOID pEndObject;
  852. LPWSTR szMachine;
  853. LPWSTR szLogMachine = NULL;
  854. LPWSTR szObject;
  855. DWORD dwObjects;
  856. PPDHI_LOG_MACHINE pLoggedMachine = NULL;
  857. PPDHI_LOG_OBJECT pLoggedObject = NULL;
  858. PPMLOG_COUNTERNAMES pCounterTable = NULL;
  859. for (i = 0; i < pIndex->iSystemsLogged; i ++) {
  860. if (i == 0) {
  861. pBlock = (PPERF_DATA_BLOCK) PointerSeek(pPmLog->pHeader, pIndex->lDataOffset);
  862. }
  863. else {
  864. pBlock = (PPERF_DATA_BLOCK) PointerSeek(pBlock, pBlock->TotalByteLength);
  865. }
  866. if (pBlock->TotalByteLength <= sizeof(PERF_DATA_BLOCK) || pBlock->HeaderLength <= sizeof(PERF_DATA_BLOCK)) {
  867. continue;
  868. }
  869. dwObjects = pBlock->NumObjectTypes;
  870. pEndObject = PointerSeek(pBlock, pBlock->TotalByteLength);
  871. szMachine = (LPWSTR) PointerSeek(pBlock, sizeof(PERF_DATA_BLOCK));
  872. G_FREE(szLogMachine);
  873. szLogMachine = G_ALLOC((lstrlenW(szMachine) + 3) * sizeof(WCHAR));
  874. if (szLogMachine == NULL) {
  875. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  876. break;
  877. }
  878. swprintf(szLogMachine, L"\\\\%ws", szMachine);
  879. pLoggedMachine = PdhiFindLogMachine(& pPmLog->MachineList, szLogMachine, TRUE);
  880. if (pLoggedMachine == NULL) {
  881. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  882. break;
  883. }
  884. pCounterTable = pPmLog->pFirstCounterNameTables;
  885. while (pCounterTable != NULL) {
  886. if (lstrcmpiW(pCounterTable->szSystemName, szLogMachine) == 0) break;
  887. pCounterTable = pCounterTable->pNext;
  888. }
  889. if (pCounterTable == NULL) continue;
  890. pObject = FirstObject(pBlock);
  891. while ((pObject != NULL) && ((PVOID) pObject < pEndObject) && (dwObjects > 0)) {
  892. dwObjects --;
  893. if (pObject->TotalByteLength > sizeof(PERF_OBJECT_TYPE)
  894. && pObject->DefinitionLength > sizeof(PERF_OBJECT_TYPE)
  895. && pObject->ObjectNameTitleIndex <= pCounterTable->dwLastIndex) {
  896. szObject = (LPWSTR) PdhiLookupLogPerfNameByIndex(pPmLog,
  897. szLogMachine,
  898. pCounterTable->dwLangId,
  899. pObject->ObjectNameTitleIndex);
  900. if (szObject != NULL) {
  901. pLoggedObject = PdhiFindLogObject(pLoggedMachine,
  902. & pLoggedMachine->ObjTable,
  903. szObject,
  904. TRUE);
  905. if (pLoggedObject == NULL) {
  906. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  907. break;
  908. }
  909. pLoggedObject->bNeedExpand = TRUE;
  910. pLoggedObject->dwObject = pObject->ObjectNameTitleIndex;
  911. }
  912. }
  913. pObject = (dwObjects > 0) ? NextObject(pObject) : NULL;
  914. }
  915. }
  916. G_FREE(szLogMachine);
  917. return Status;
  918. }
  919. PDH_FUNCTION
  920. PdhiCachePmLogHeader(
  921. PPLAYBACKLOG pPmLog
  922. )
  923. {
  924. PDH_STATUS Status = ERROR_SUCCESS;
  925. PLOGINDEX * IndexTable;
  926. DWORD i;
  927. int iMaxSystemLogged = -1;
  928. DWORD dwIndex = 0;
  929. if (pPmLog == NULL) {
  930. Status = PDH_INVALID_ARGUMENT;
  931. goto Cleanup;
  932. }
  933. else if (pPmLog->pFirstCounterNameTables != NULL && pPmLog->MachineList != NULL) {
  934. goto Cleanup;
  935. }
  936. IndexTable = pPmLog->LogIndexTable;
  937. for (i = 0; i < pPmLog->dwLastIndex; i ++) {
  938. // Ignore first uFlags 0x00000000 and LogFileIndexBookmark index entries.
  939. //
  940. if ((IndexTable[i]->uFlags & LogFileIndexCounterName) != 0) {
  941. // For LogFileIndexCounterName index entries, cache counter name/explain string table.
  942. if (IndexTable[i]->lDataOffset < pPmLog->llFileSize) {
  943. PLOGFILECOUNTERNAME pLogName = (PLOGFILECOUNTERNAME)
  944. PointerSeek(pPmLog->pHeader, IndexTable[i]->lDataOffset);
  945. PPMLOG_COUNTERNAMES pMachine = pPmLog->pFirstCounterNameTables;
  946. while (pMachine != NULL) {
  947. if (lstrcmpiW(pMachine->szSystemName, pLogName->szComputer) == 0) break;
  948. }
  949. if (pMachine == NULL) {
  950. pMachine = (PPMLOG_COUNTERNAMES) G_ALLOC(
  951. sizeof(PMLOG_COUNTERNAMES) + sizeof(LPWSTR) * (pLogName->dwLastCounterId + 1));
  952. if (pMachine != NULL) {
  953. pMachine->szSystemName = pLogName->szComputer;
  954. pMachine->szNameTable = PointerSeek(pMachine, sizeof(PMLOG_COUNTERNAMES));
  955. pMachine->dwLangId = pLogName->dwLangId;
  956. pMachine->dwLastIndex = pLogName->dwLastCounterId;
  957. pMachine->pNext = pPmLog->pFirstCounterNameTables;
  958. pPmLog->pFirstCounterNameTables = pMachine;
  959. }
  960. else {
  961. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  962. }
  963. }
  964. if (Status == ERROR_SUCCESS) {
  965. Status = PdhiBuildPmLogStringTable(pPmLog, pLogName, pMachine, pLogName->lUnmatchCounterNames);
  966. }
  967. }
  968. else {
  969. Status = PDH_UNABLE_READ_LOG_HEADER;
  970. }
  971. if (Status != ERROR_SUCCESS) break;
  972. }
  973. else if ((IndexTable[i]->uFlags & LogFileIndexData) != 0) {
  974. // Process first LogFileIndexData block for initial machine-object cache structure.
  975. //
  976. if (IndexTable[i]->iSystemsLogged > iMaxSystemLogged) {
  977. iMaxSystemLogged = IndexTable[i]->iSystemsLogged;
  978. dwIndex = i;
  979. }
  980. }
  981. }
  982. if (Status == ERROR_SUCCESS) {
  983. Status = (iMaxSystemLogged > 0) ? PdhiCachePerfDataBlock(pPmLog, IndexTable[dwIndex])
  984. : PDH_UNABLE_READ_LOG_HEADER;
  985. }
  986. Cleanup:
  987. return Status;
  988. }
  989. PPERF_DATA_BLOCK
  990. PdhiDataFromIndex(
  991. PPLAYBACKLOG pPlaybackLog,
  992. PLOGINDEX pLogIndex,
  993. LPCWSTR lpszSystemName
  994. )
  995. {
  996. PPERF_DATA_BLOCK pPerfData;
  997. PPERF_DATA_BLOCK pRtnBlock = NULL;
  998. LPWSTR szLoggedComputerName = NULL;
  999. int iNumSystem ;
  1000. // Note: NULL lpszSystemName means return first logged system name
  1001. // at the specified index.
  1002. pPerfData = PointerSeek(pPlaybackLog->pHeader, pLogIndex->lDataOffset);
  1003. for (iNumSystem = 0; iNumSystem < pLogIndex->iSystemsLogged; iNumSystem ++) {
  1004. if (pPerfData && pPerfData->Signature[0] == (WCHAR)'P' &&
  1005. pPerfData->Signature[1] == (WCHAR)'E' &&
  1006. pPerfData->Signature[2] == (WCHAR)'R' &&
  1007. pPerfData->Signature[3] == (WCHAR)'F') {
  1008. szLoggedComputerName = (LPWSTR) PointerSeek(pPerfData, pPerfData->SystemNameOffset);
  1009. if (lpszSystemName == NULL) {
  1010. pRtnBlock = pPerfData;
  1011. break;
  1012. }
  1013. else if (lstrlenW(lpszSystemName) > 2 && lpszSystemName[0] == L'\\' && lpszSystemName[1] == L'\\') {
  1014. if (lstrcmpiW(szLoggedComputerName, & (lpszSystemName[2])) == 0) {
  1015. pRtnBlock = pPerfData;
  1016. break;
  1017. }
  1018. }
  1019. else if (lstrcmpiW(szLoggedComputerName, lpszSystemName) == 0) {
  1020. pRtnBlock = pPerfData;
  1021. break;
  1022. }
  1023. pPerfData = (PPERFDATA)((PBYTE) pPerfData + pPerfData->TotalByteLength);
  1024. }
  1025. else {
  1026. break;
  1027. }
  1028. }
  1029. return pRtnBlock;
  1030. }
  1031. PPERF_OBJECT_TYPE
  1032. PdhiFindPerfObject(
  1033. PPERF_DATA_BLOCK pBlock,
  1034. DWORD dwObject
  1035. )
  1036. {
  1037. DWORD dwCount = pBlock->NumObjectTypes;
  1038. PVOID ptrEnd = PointerSeek(pBlock, pBlock->TotalByteLength);
  1039. PPERF_OBJECT_TYPE pObject = FirstObject(pBlock);
  1040. while (pObject != NULL && ((PVOID) pObject < ptrEnd) && dwCount > 0) {
  1041. dwCount --;
  1042. if (pObject->ObjectNameTitleIndex == dwObject) break;
  1043. pObject = (dwCount > 0) ? NextObject(pObject) : NULL;
  1044. if ((PVOID) pObject >= ptrEnd) pObject = NULL;
  1045. }
  1046. return pObject;
  1047. }
  1048. PDH_FUNCTION
  1049. PdhiCachePmLogObject(
  1050. PPLAYBACKLOG pPmLog,
  1051. LPWSTR szMachineName,
  1052. LPWSTR szObjectName
  1053. )
  1054. {
  1055. PDH_STATUS Status = ERROR_SUCCESS;
  1056. PPMLOG_COUNTERNAMES pCounterTable = NULL;
  1057. PPDHI_LOG_MACHINE pLogMachine = PdhiFindLogMachine(& pPmLog->MachineList, szMachineName, FALSE);
  1058. PPDHI_LOG_OBJECT pLogObject = NULL;
  1059. PPDHI_LOG_COUNTER pLogCounter = NULL;
  1060. PPDHI_LOG_COUNTER pLogInst;
  1061. PPDHI_LOG_COUNTER pLogInstHead;
  1062. PPERF_DATA_BLOCK pBlock;
  1063. PPERF_OBJECT_TYPE pObject;
  1064. PPERF_OBJECT_TYPE pParentObject;
  1065. PPERF_COUNTER_DEFINITION pCounter;
  1066. PPERF_INSTANCE_DEFINITION pInstance;
  1067. PPERF_INSTANCE_DEFINITION pParentInstance;
  1068. LPWSTR szCounter;
  1069. LPWSTR szInstance;
  1070. LPWSTR szParent;
  1071. DWORD dwInstance;
  1072. DWORD dwParent;
  1073. BOOL bInstance = FALSE;
  1074. DWORD i;
  1075. PVOID ptrEnd;
  1076. DWORD dwCount;
  1077. DWORD dwCounterID;
  1078. if (pLogMachine != NULL) {
  1079. pLogObject = PdhiFindLogObject(pLogMachine, & pLogMachine->ObjTable, szObjectName, FALSE);
  1080. }
  1081. if (pLogObject == NULL) {
  1082. Status = PDH_INVALID_ARGUMENT;
  1083. }
  1084. else if (pLogObject->bNeedExpand) {
  1085. pCounterTable = pPmLog->pFirstCounterNameTables;
  1086. while (pCounterTable != NULL) {
  1087. if (lstrcmpiW(pCounterTable->szSystemName, szMachineName) == 0) break;
  1088. pCounterTable = pCounterTable->pNext;
  1089. }
  1090. if (pCounterTable == NULL) {
  1091. Status = PDH_INVALID_ARGUMENT;
  1092. goto Cleanup;
  1093. }
  1094. for (i = 0; i < pPmLog->dwLastIndex; i ++) {
  1095. pBlock = PdhiDataFromIndex(pPmLog, pPmLog->LogIndexTable[i], szMachineName);
  1096. if (pBlock == NULL) continue;
  1097. pObject = PdhiFindPerfObject(pBlock, pLogObject->dwObject);
  1098. if (pObject == NULL) {
  1099. continue;
  1100. }
  1101. else if (pObject->TotalByteLength <= sizeof(PERF_OBJECT_TYPE)
  1102. || pObject->DefinitionLength <= sizeof(PERF_OBJECT_TYPE)) {
  1103. continue;
  1104. }
  1105. dwCount = pObject->NumCounters;
  1106. ptrEnd = PointerSeek(pObject, pObject->DefinitionLength);
  1107. pCounter = FirstCounter(pObject);
  1108. while (pCounter != NULL && ((PVOID) pCounter < ptrEnd) && dwCount > 0) {
  1109. dwCount --;
  1110. szCounter = (LPWSTR) PdhiLookupLogPerfNameByIndex(pPmLog,
  1111. szMachineName,
  1112. pCounterTable->dwLangId,
  1113. pCounter->CounterNameTitleIndex);
  1114. if (szCounter != NULL) {
  1115. pLogCounter = PdhiFindPmCounterInstance(pLogObject,
  1116. szCounter,
  1117. pCounter->CounterType,
  1118. pCounter->DefaultScale,
  1119. NULL,
  1120. 0,
  1121. NULL,
  1122. pCounter->CounterOffset,
  1123. & pCounter->CounterNameTitleIndex,
  1124. FALSE,
  1125. TRUE);
  1126. if (pLogCounter == NULL) {
  1127. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1128. break;
  1129. }
  1130. else if (pCounter->CounterType & PERF_TIMER_100NS) {
  1131. pLogCounter->TimeBase = (LONGLONG) 10000000;
  1132. }
  1133. else if (pCounter->CounterType & PERF_OBJECT_TIMER) {
  1134. // then get the time base freq from the object
  1135. pLogCounter->TimeBase = pObject->PerfFreq.QuadPart;
  1136. }
  1137. else { // if (pPerfCounter->CounterType & PERF_TIMER_TICK or other)
  1138. pLogCounter->TimeBase = pBlock->PerfFreq.QuadPart;
  1139. }
  1140. }
  1141. pCounter = NextCounter(pCounter);
  1142. if ((PVOID) pCounter >= ptrEnd) pCounter = NULL;
  1143. }
  1144. if (Status != ERROR_SUCCESS) continue;
  1145. dwCount = pObject->NumInstances;
  1146. bInstance = (dwCount != PERF_NO_INSTANCES) && (dwCount != 0);
  1147. if (bInstance) {
  1148. for (pLogCounter = pLogObject->InstList; pLogCounter != NULL; pLogCounter = pLogCounter->next) {
  1149. pLogCounter->dwCounterType = 0;
  1150. }
  1151. ptrEnd = PointerSeek(pObject, pObject->TotalByteLength);
  1152. pInstance = FirstInstance(pObject);
  1153. while (pInstance != NULL && ((PVOID) pInstance < ptrEnd) && dwCount > 0) {
  1154. dwCount --;
  1155. szInstance = (pInstance->NameOffset != 0) ? (LPWSTR) PointerSeek(pInstance, pInstance->NameOffset)
  1156. : NULL;
  1157. dwInstance = pInstance->UniqueID;
  1158. szParent = NULL;
  1159. dwParent = PERF_NO_UNIQUE_ID;
  1160. dwCounterID = 0;
  1161. if (pInstance->ParentObjectTitleIndex != 0) {
  1162. pParentObject = PdhiFindPerfObject(pBlock, pInstance->ParentObjectTitleIndex);
  1163. if (pParentObject != NULL && pParentObject->TotalByteLength > sizeof(PERF_OBJECT_TYPE)
  1164. && pParentObject->DefinitionLength > sizeof(PERF_OBJECT_TYPE)) {
  1165. pParentInstance = GetInstance(pParentObject, pInstance->ParentObjectInstance);
  1166. if (pParentInstance != NULL) {
  1167. szParent = (pParentInstance->NameOffset != 0)
  1168. ? (LPWSTR) PointerSeek(pParentInstance, pParentInstance->NameOffset) : NULL;
  1169. dwParent = pParentInstance->UniqueID;
  1170. dwCounterID = 1;
  1171. }
  1172. }
  1173. }
  1174. if (PdhiFindPmCounterInstance(pLogObject, NULL, 0, 0,
  1175. szInstance, dwInstance, szParent, dwParent, & dwCounterID, TRUE, TRUE) == NULL) {
  1176. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  1177. break;
  1178. }
  1179. pInstance = NextInstance(pInstance);
  1180. if ((PVOID) pInstance >= ptrEnd) pInstance = NULL;
  1181. }
  1182. }
  1183. if (pObject->NumInstances == PERF_NO_INSTANCES) break;
  1184. }
  1185. pLogInstHead = pLogObject->InstList;
  1186. pLogObject->InstList = NULL;
  1187. pLogObject->InstTable = NULL;
  1188. for (pLogInst = pLogInstHead; pLogInst != NULL; pLogInst = pLogInst->next) {
  1189. if (pLogInst->dwInstance != 0 && pLogInst->dwInstance != PERF_NO_UNIQUE_ID) {
  1190. PdhiFindPmCounterInstance(pLogObject,
  1191. NULL,
  1192. 0,
  1193. 0,
  1194. pLogInst->szInstance,
  1195. pLogInst->dwInstance,
  1196. pLogInst->szParent,
  1197. pLogInst->dwParent,
  1198. & pLogInst->dwCounterID,
  1199. TRUE,
  1200. TRUE);
  1201. }
  1202. else {
  1203. for (i = 0; i < pLogInst->dwDefaultScale; i ++) {
  1204. PdhiFindPmCounterInstance(pLogObject,
  1205. NULL,
  1206. 0,
  1207. 0,
  1208. pLogInst->szInstance,
  1209. i,
  1210. pLogInst->szParent,
  1211. pLogInst->dwParent,
  1212. & pLogInst->dwCounterID,
  1213. TRUE,
  1214. TRUE);
  1215. }
  1216. }
  1217. }
  1218. while (pLogInstHead != NULL) {
  1219. pLogInst = pLogInstHead;
  1220. pLogInstHead = pLogInst->next;
  1221. G_FREE(pLogInst);
  1222. }
  1223. pLogObject->bNeedExpand = FALSE;
  1224. }
  1225. Cleanup:
  1226. return Status;
  1227. }
  1228. PDH_FUNCTION
  1229. PdhiRewindPmLog(
  1230. PPDHI_LOG pLog,
  1231. PPLAYBACKLOG pPmLog
  1232. )
  1233. {
  1234. PDH_STATUS Status = ERROR_SUCCESS;
  1235. if (pPmLog->dwFirstIndex == 0) {
  1236. PLOGINDEX pIndex = NULL;
  1237. DWORD i;
  1238. for (i = 0; i < pPmLog->dwLastIndex; i ++) {
  1239. pIndex = pPmLog->LogIndexTable[i];
  1240. if ((pIndex->uFlags & LogFileIndexData) != 0) break;
  1241. }
  1242. if (i < pPmLog->dwLastIndex) {
  1243. pPmLog->dwFirstIndex = i;
  1244. }
  1245. }
  1246. if (pPmLog->dwFirstIndex != pPmLog->dwCurrentIndex) {
  1247. pLog->dwLastRecordRead = pPmLog->dwFirstIndex;
  1248. pPmLog->dwCurrentIndex = pPmLog->dwFirstIndex;
  1249. pLog->pLastRecordRead = PointerSeek(pPmLog->pHeader,
  1250. pPmLog->LogIndexTable[pPmLog->dwFirstIndex]->lDataOffset);
  1251. }
  1252. return Status;
  1253. }
  1254. PDH_FUNCTION
  1255. PdhiOpenInputPerfmonLog(
  1256. PPDHI_LOG pLog
  1257. )
  1258. {
  1259. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1260. PPLAYBACKLOG pPmPbLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1261. pLog->StreamFile = (FILE *) ((DWORD_PTR) (-1));
  1262. // map file as a memory array for reading
  1263. if (pLog->hMappedLogFile != NULL && pLog->lpMappedFileBase != NULL) {
  1264. pLog->dwLastRecordRead = 0;
  1265. pLog->pLastRecordRead = NULL;
  1266. pLog->pPerfmonInfo = G_ALLOC(sizeof(PLAYBACKLOG));
  1267. if (pLog->pPerfmonInfo != NULL) {
  1268. pPmPbLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1269. // assumes structure was 0-init'd on allocation
  1270. pPmPbLog->llFileSize = pLog->llFileSize;
  1271. pPmPbLog->szFilePath = pLog->szLogFileName;
  1272. pPmPbLog->pHeader = pLog->lpMappedFileBase;
  1273. pPmPbLog->iTotalTics = 1;
  1274. pPmPbLog->dwFirstIndex = 0;
  1275. pPmPbLog->MachineList = NULL;
  1276. pPmPbLog->pFirstCounterNameTables = NULL;
  1277. pdhStatus = PdhiBuildPmLogIndexTable(pPmPbLog);
  1278. if (pdhStatus == ERROR_SUCCESS) {
  1279. pdhStatus = PdhiRewindPmLog(pLog, pPmPbLog);
  1280. }
  1281. }
  1282. else {
  1283. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1284. }
  1285. }
  1286. else {
  1287. // return PDH Error
  1288. pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  1289. }
  1290. return pdhStatus;
  1291. }
  1292. PDH_FUNCTION
  1293. PdhiClosePerfmonLog(
  1294. PPDHI_LOG pLog,
  1295. DWORD dwFlags
  1296. )
  1297. {
  1298. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1299. PPLAYBACKLOG pPlaybackLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1300. DBG_UNREFERENCED_PARAMETER(dwFlags);
  1301. if (pPlaybackLog != NULL) {
  1302. G_FREE(pPlaybackLog->LogIndexTable);
  1303. PdhiFreeLogMachineTable(& pPlaybackLog->MachineList);
  1304. PdhiFreePmMachineList(pPlaybackLog);
  1305. G_FREE(pLog->pPerfmonInfo);
  1306. pLog->pPerfmonInfo = NULL;
  1307. }
  1308. return pdhStatus;
  1309. }
  1310. PDH_FUNCTION
  1311. PdhiGetPerfmonLogCounterInfo(
  1312. PPDHI_LOG pLog,
  1313. PPDHI_COUNTER pCounter
  1314. )
  1315. {
  1316. PDH_STATUS pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  1317. PPLAYBACKLOG pPlaybackLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1318. PPDHI_LOG_MACHINE pLogMachine = NULL;
  1319. PPDHI_LOG_OBJECT pLogObject = NULL;
  1320. PPDHI_LOG_COUNTER pLogCounter = NULL;
  1321. PPDHI_LOG_COUNTER pLogInstance = NULL;
  1322. DWORD dwCounter;
  1323. PPERF_DATA_BLOCK pPerfData = NULL;
  1324. PPERF_OBJECT_TYPE pObjectDef;
  1325. PPERF_COUNTER_DEFINITION pPerfCounter;
  1326. PPERF_INSTANCE_DEFINITION pInstanceDef;
  1327. DWORD dwObjectId = 0;
  1328. LOGPOSITION LogPosition;
  1329. LOGINDEX * pLogIndex;
  1330. LPWSTR * pCounterNames = NULL;
  1331. DWORD dwLastCounterNameIndex = 0;
  1332. BOOL bObjectNumber = FALSE;
  1333. if (pPlaybackLog != NULL) {
  1334. pdhStatus = PdhiCachePmLogHeader(pPlaybackLog);
  1335. if (pdhStatus == ERROR_SUCCESS) {
  1336. pdhStatus = PdhiCachePmLogObject(pPlaybackLog,
  1337. pCounter->pCounterPath->szMachineName,
  1338. pCounter->pCounterPath->szObjectName);
  1339. }
  1340. }
  1341. if (pdhStatus == ERROR_SUCCESS) {
  1342. pLogMachine = PdhiFindLogMachine(& pPlaybackLog->MachineList, pCounter->pCounterPath->szMachineName, FALSE);
  1343. pCounter->pThisRawItemList = (LPVOID) pLogMachine;
  1344. if (pLogMachine != NULL) {
  1345. pLogObject = PdhiFindLogObject(
  1346. pLogMachine, & pLogMachine->ObjTable, pCounter->pCounterPath->szObjectName, FALSE);
  1347. pCounter->pLastRawItemList = (LPVOID) pLogObject;
  1348. if (pLogObject == NULL) {
  1349. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  1350. }
  1351. }
  1352. else {
  1353. pdhStatus = PDH_CSTATUS_NO_MACHINE;
  1354. }
  1355. }
  1356. if (pdhStatus == ERROR_SUCCESS) {
  1357. pLogCounter = PdhiFindPmCounterInstance(pLogObject,
  1358. pCounter->pCounterPath->szCounterName,
  1359. 0,
  1360. 0,
  1361. NULL,
  1362. 0,
  1363. NULL,
  1364. 0,
  1365. & dwCounter,
  1366. FALSE,
  1367. FALSE);
  1368. pCounter->pThisObject = (LPVOID) pLogCounter;
  1369. if (pCounter->pCounterPath->szInstanceName != NULL) {
  1370. pLogInstance = PdhiFindPmCounterInstance(pLogObject,
  1371. NULL,
  1372. 0,
  1373. 0,
  1374. pCounter->pCounterPath->szInstanceName,
  1375. pCounter->pCounterPath->dwIndex,
  1376. pCounter->pCounterPath->szParentName,
  1377. 0,
  1378. & dwCounter,
  1379. TRUE,
  1380. FALSE);
  1381. pCounter->pLastObject = (LPVOID) pLogInstance;
  1382. }
  1383. }
  1384. if (pLogCounter != NULL) {
  1385. if (pCounter->pCounterPath->szInstanceName != NULL) {
  1386. if (pLogInstance == NULL) {
  1387. pdhStatus = PDH_CSTATUS_NO_INSTANCE;
  1388. }
  1389. }
  1390. pCounter->plCounterInfo.dwObjectId = pLogObject->dwObject;
  1391. if (pLogInstance) {
  1392. pCounter->plCounterInfo.lInstanceId = (pLogInstance->szInstance == NULL)
  1393. ? pLogInstance->dwInstance : PERF_NO_UNIQUE_ID;
  1394. pCounter->plCounterInfo.dwParentObjectId = pLogInstance->dwParent;
  1395. }
  1396. else {
  1397. pCounter->plCounterInfo.lInstanceId = PERF_NO_UNIQUE_ID;
  1398. pCounter->plCounterInfo.dwParentObjectId = PERF_NO_UNIQUE_ID;
  1399. }
  1400. pCounter->plCounterInfo.szInstanceName = pCounter->pCounterPath->szInstanceName;
  1401. pCounter->plCounterInfo.szParentInstanceName = pCounter->pCounterPath->szParentName;
  1402. pCounter->plCounterInfo.dwCounterId = pLogCounter->dwCounterID;
  1403. pCounter->plCounterInfo.dwCounterType = pLogCounter->dwCounterType;
  1404. pCounter->plCounterInfo.dwCounterSize = pLogCounter->dwInstance;
  1405. pCounter->plCounterInfo.lDefaultScale = pLogCounter->dwDefaultScale;
  1406. pCounter->TimeBase = pLogCounter->TimeBase;
  1407. }
  1408. else {
  1409. pdhStatus = PDH_CSTATUS_NO_COUNTER;
  1410. }
  1411. return pdhStatus;
  1412. }
  1413. PDH_FUNCTION
  1414. PdhiEnumMachinesFromPerfmonLog(
  1415. PPDHI_LOG pLog,
  1416. LPVOID pBuffer,
  1417. LPDWORD pcchBufferSize,
  1418. BOOL bUnicodeDest
  1419. )
  1420. {
  1421. PDH_STATUS pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  1422. PPLAYBACKLOG pPlaybackLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1423. if (pPlaybackLog != NULL) {
  1424. pdhStatus = PdhiCachePmLogHeader(pPlaybackLog);
  1425. if (pdhStatus == ERROR_SUCCESS) {
  1426. pdhStatus = PdhiEnumCachedMachines(pPlaybackLog->MachineList, pBuffer, pcchBufferSize, bUnicodeDest);
  1427. }
  1428. }
  1429. return pdhStatus;
  1430. }
  1431. PDH_FUNCTION
  1432. PdhiEnumObjectsFromPerfmonLog(
  1433. PPDHI_LOG pLog,
  1434. LPCWSTR lpszSystemName,
  1435. LPVOID pBuffer,
  1436. LPDWORD pcchBufferSize,
  1437. DWORD dwDetailLevel,
  1438. BOOL bUnicodeDest
  1439. )
  1440. {
  1441. PDH_STATUS pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  1442. PPLAYBACKLOG pPlaybackLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1443. if (pPlaybackLog != NULL) {
  1444. pdhStatus = PdhiCachePmLogHeader(pPlaybackLog);
  1445. if (pdhStatus == ERROR_SUCCESS) {
  1446. pdhStatus = PdhiEnumCachedObjects(
  1447. pPlaybackLog->MachineList, lpszSystemName, pBuffer, pcchBufferSize, dwDetailLevel, bUnicodeDest);
  1448. }
  1449. }
  1450. return pdhStatus;
  1451. }
  1452. PDH_FUNCTION
  1453. PdhiEnumObjectItemsFromPerfmonLog(
  1454. PPDHI_LOG pLog,
  1455. LPCWSTR szMachineName,
  1456. LPCWSTR szObjectName,
  1457. PDHI_COUNTER_TABLE CounterTable,
  1458. DWORD dwDetailLevel,
  1459. DWORD dwFlags
  1460. )
  1461. {
  1462. PDH_STATUS pdhStatus = PDH_LOG_FILE_OPEN_ERROR;
  1463. PPLAYBACKLOG pPlaybackLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1464. DBG_UNREFERENCED_PARAMETER(dwFlags);
  1465. DBG_UNREFERENCED_PARAMETER(dwDetailLevel);
  1466. if (pPlaybackLog != NULL) {
  1467. pdhStatus = PdhiCachePmLogHeader(pPlaybackLog);
  1468. if (pdhStatus == ERROR_SUCCESS) {
  1469. pdhStatus = PdhiCachePmLogObject(pPlaybackLog, (LPWSTR) szMachineName, (LPWSTR) szObjectName);
  1470. }
  1471. }
  1472. if (pdhStatus == ERROR_SUCCESS) {
  1473. PPDHI_LOG_MACHINE pMachine = NULL;
  1474. PPDHI_LOG_OBJECT pObject = NULL;
  1475. PPDHI_LOG_COUNTER pCtr = NULL;
  1476. PPDHI_LOG_COUNTER pInst = NULL;
  1477. PPDHI_INST_LIST pFirstInstList = NULL;
  1478. PPDHI_INST_LIST pInstList = NULL;
  1479. PPDHI_INSTANCE pInstance = NULL;
  1480. LONG nCounterCount = 0;
  1481. LONG nInstanceCount = 0;
  1482. pMachine = PdhiFindLogMachine(& pPlaybackLog->MachineList, (LPWSTR) szMachineName, FALSE);
  1483. if (pMachine == NULL) {
  1484. pdhStatus = PDH_CSTATUS_NO_MACHINE;
  1485. }
  1486. else {
  1487. pObject = PdhiFindLogObject(pMachine, & (pMachine->ObjTable), (LPWSTR) szObjectName, FALSE);
  1488. if (pObject == NULL) {
  1489. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  1490. }
  1491. }
  1492. if (pdhStatus == ERROR_SUCCESS) {
  1493. for (pCtr = pObject->CtrList; pCtr != NULL; pCtr = pCtr->next) {
  1494. pdhStatus = PdhiFindCounterInstList(CounterTable, pCtr->szCounter, & pInstList);
  1495. if (pdhStatus != ERROR_SUCCESS) {
  1496. continue;
  1497. }
  1498. else {
  1499. nCounterCount ++;
  1500. if (pFirstInstList == NULL) {
  1501. pFirstInstList = pInstList;
  1502. }
  1503. }
  1504. }
  1505. if (pFirstInstList != NULL) {
  1506. pInst = pObject->InstList;
  1507. if (pInst != NULL && pInst != PDH_INVALID_POINTER) {
  1508. LPWSTR szFullInstance = G_ALLOC(SMALL_BUFFER_SIZE * sizeof(WCHAR));
  1509. if (szFullInstance != NULL) {
  1510. while (pInst != NULL) {
  1511. ZeroMemory(szFullInstance, SMALL_BUFFER_SIZE * sizeof(WCHAR));
  1512. if (pInst->szInstance != NULL) {
  1513. if (pInst->dwCounterID != 0) {
  1514. if (pInst->szParent != NULL) {
  1515. if (pInst->dwInstance != 0 && pInst->dwInstance != PERF_NO_UNIQUE_ID) {
  1516. swprintf(szFullInstance, L"%ws%ws%ws#%u",
  1517. pInst->szParent, cszSlash, pInst->szInstance, pInst->dwInstance);
  1518. }
  1519. else {
  1520. swprintf(szFullInstance, L"%ws%ws%ws",
  1521. pInst->szParent, cszSlash, pInst->szInstance);
  1522. }
  1523. }
  1524. else {
  1525. if (pInst->dwInstance != 0 && pInst->dwInstance != PERF_NO_UNIQUE_ID) {
  1526. swprintf(szFullInstance, L"%u%ws%ws#%u",
  1527. pInst->dwParent, cszSlash, pInst->szInstance, pInst->dwInstance);
  1528. }
  1529. else {
  1530. swprintf(szFullInstance, L"%u%ws%ws",
  1531. pInst->dwParent, cszSlash, pInst->szInstance);
  1532. }
  1533. }
  1534. }
  1535. else if (pInst->dwInstance != 0 && pInst->dwInstance != PERF_NO_UNIQUE_ID) {
  1536. swprintf(szFullInstance, L"%ws#%u",
  1537. pInst->szInstance, pInst->dwInstance);
  1538. }
  1539. else {
  1540. lstrcpynW(szFullInstance, pInst->szInstance, SMALL_BUFFER_SIZE - 1);
  1541. }
  1542. }
  1543. else if (pInst->dwCounterID != 0) {
  1544. if (pInst->szParent != NULL) {
  1545. swprintf(szFullInstance, L"%ws%ws%u",
  1546. pInst->szParent, cszSlash, pInst->dwInstance);
  1547. }
  1548. else {
  1549. swprintf(szFullInstance, L"%u%ws%u",
  1550. pInst->dwParent, cszSlash, pInst->dwInstance);
  1551. }
  1552. }
  1553. else {
  1554. swprintf(szFullInstance, L"%u", pInst->dwInstance);
  1555. }
  1556. pdhStatus = PdhiFindInstance(& pFirstInstList->InstList, szFullInstance, TRUE, & pInstance);
  1557. if (pdhStatus == ERROR_SUCCESS) {
  1558. nInstanceCount ++;
  1559. }
  1560. pInst = pInst->next;
  1561. }
  1562. }
  1563. else {
  1564. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1565. }
  1566. }
  1567. }
  1568. if (nCounterCount == 0 && nInstanceCount == 0) {
  1569. if (pdhStatus == ERROR_SUCCESS) {
  1570. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  1571. }
  1572. }
  1573. else if (pdhStatus != PDH_MORE_DATA) {
  1574. // then the routine was successful. Errors that occurred
  1575. // while scanning will be ignored as long as at least
  1576. // one entry was successfully read
  1577. pdhStatus = ERROR_SUCCESS;
  1578. }
  1579. }
  1580. }
  1581. return pdhStatus;
  1582. }
  1583. PDH_FUNCTION
  1584. PdhiGetMatchingPerfmonLogRecord(
  1585. PPDHI_LOG pLog,
  1586. LONGLONG * pStartTime,
  1587. LPDWORD pdwIndex
  1588. )
  1589. {
  1590. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1591. PPLAYBACKLOG pPlaybackLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1592. DWORD dwThisIndex = 0;
  1593. DWORD dwLastIndex = 0;
  1594. LONGLONG llThisTime = 0;
  1595. PPERF_DATA_BLOCK pPerfData;
  1596. FILETIME ftGMT;
  1597. if (pPlaybackLog == NULL) {
  1598. pdhStatus = PDH_LOG_FILE_OPEN_ERROR; // log is invalid
  1599. }
  1600. else {
  1601. dwLastIndex = pPlaybackLog->dwFirstIndex;
  1602. for (dwThisIndex = pPlaybackLog->dwFirstIndex; dwThisIndex < pPlaybackLog->dwLastIndex; dwThisIndex ++) {
  1603. pPerfData = (PPERF_DATA_BLOCK) PointerSeek(
  1604. pPlaybackLog->pHeader, pPlaybackLog->LogIndexTable[dwThisIndex]->lDataOffset);
  1605. if (pPerfData != NULL) {
  1606. SystemTimeToFileTime(& pPerfData->SystemTime, & ftGMT);
  1607. FileTimeToLocalFileTime(& ftGMT, (FILETIME *) & llThisTime);
  1608. if (llThisTime == * pStartTime) {
  1609. // record found
  1610. break;
  1611. }
  1612. else if (llThisTime > * pStartTime) {
  1613. // go back one
  1614. dwThisIndex = dwLastIndex;
  1615. break;
  1616. }
  1617. else {
  1618. dwLastIndex = dwThisIndex;
  1619. // go to the next one
  1620. }
  1621. }
  1622. else {
  1623. dwLastIndex = dwThisIndex;
  1624. // go to the next one
  1625. }
  1626. }
  1627. if (dwThisIndex == pPlaybackLog->dwLastIndex) {
  1628. // then there's no more records in the log
  1629. pdhStatus = PDH_ENTRY_NOT_IN_LOG_FILE;
  1630. }
  1631. }
  1632. if (pdhStatus == ERROR_SUCCESS) {
  1633. if (pdwIndex != NULL) * pdwIndex = dwThisIndex;
  1634. if (pLog->dwLastRecordRead != dwThisIndex) {
  1635. pLog->dwLastRecordRead = dwThisIndex;
  1636. pPlaybackLog->dwCurrentIndex = dwThisIndex;
  1637. pLog->pLastRecordRead = PointerSeek(pPlaybackLog->pHeader,
  1638. pPlaybackLog->LogIndexTable[dwThisIndex]->lDataOffset);
  1639. }
  1640. }
  1641. return pdhStatus;
  1642. }
  1643. DWORD
  1644. PdhiGetPmBaseCounterOffset(
  1645. PPDHI_LOG_COUNTER pCounter,
  1646. PPERF_OBJECT_TYPE pPerfObject
  1647. )
  1648. {
  1649. DWORD dwReturn = pCounter->dwInstance;
  1650. if (pCounter->dwInstance == 0) {
  1651. PPERF_COUNTER_DEFINITION pPerfCounter = FirstCounter(pPerfObject);
  1652. DWORD dwCounter = pPerfObject->NumCounters;
  1653. PVOID pEndGuard = PointerSeek(pPerfObject, pPerfObject->DefinitionLength);
  1654. while (pPerfCounter != NULL && dwCounter > 0) {
  1655. dwCounter --;
  1656. if (pPerfCounter->CounterNameTitleIndex == pCounter->dwCounterID) {
  1657. pPerfCounter = NextCounter(pPerfCounter);
  1658. if (pPerfCounter == NULL) break;
  1659. if ((((LPVOID) pPerfCounter) < pEndGuard)
  1660. && ((pPerfCounter->CounterType & PERF_COUNTER_BASE) != 0)) {
  1661. dwReturn = pPerfCounter->CounterOffset;
  1662. break;
  1663. }
  1664. }
  1665. if (((LPVOID) pPerfCounter) < pEndGuard) {
  1666. pPerfCounter = NextCounter(pPerfCounter);
  1667. }
  1668. if (((LPVOID) pPerfCounter) >= pEndGuard) pPerfCounter = NULL;
  1669. }
  1670. pCounter->dwInstance = dwReturn;
  1671. }
  1672. return dwReturn;
  1673. }
  1674. PDH_FUNCTION
  1675. PdhiGetCounterValueFromPerfmonLog(
  1676. PPDHI_LOG pLog,
  1677. DWORD dwIndex,
  1678. PPDHI_COUNTER pCounter,
  1679. PPDH_RAW_COUNTER pValue
  1680. )
  1681. {
  1682. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1683. PPLAYBACKLOG pPlaybackLog = (PPLAYBACKLOG) pLog->pPerfmonInfo;
  1684. PLOGINDEX pIndex = NULL;
  1685. PPERF_DATA_BLOCK pPerfData = NULL;
  1686. PPERF_OBJECT_TYPE pPerfObject = NULL;
  1687. PPERF_INSTANCE_DEFINITION pPerfInst = NULL;
  1688. PPERF_COUNTER_BLOCK pCtrBlock = NULL;
  1689. LPVOID pEndGuard;
  1690. PPDHI_LOG_MACHINE pLogMachine = (PPDHI_LOG_MACHINE) pCounter->pThisRawItemList;
  1691. PPDHI_LOG_OBJECT pLogObject = (PPDHI_LOG_OBJECT) pCounter->pLastRawItemList;
  1692. PPDHI_LOG_COUNTER pLogCounter = (PPDHI_LOG_COUNTER) pCounter->pThisObject;
  1693. PPDHI_LOG_COUNTER pLogInstance = (PPDHI_LOG_COUNTER) pCounter->pLastObject;
  1694. BOOL bReturn;
  1695. DWORD LocalCType;
  1696. DWORD * pdwData;
  1697. UNALIGNED LONGLONG * pllData;
  1698. LPVOID pData = NULL;
  1699. FILETIME ftGMT;
  1700. if (pPlaybackLog == NULL) {
  1701. pdhStatus = PDH_LOG_FILE_OPEN_ERROR; // log is invalid
  1702. }
  1703. else if (dwIndex < pPlaybackLog->dwFirstIndex) {
  1704. // invalid dwIndex value
  1705. pdhStatus = PDH_INVALID_ARGUMENT;
  1706. }
  1707. else if (dwIndex >= pPlaybackLog->dwLastIndex) {
  1708. pdhStatus = PDH_NO_MORE_DATA;
  1709. }
  1710. else if (pLogMachine == NULL || pLogObject == NULL || pLogCounter == NULL) {
  1711. pdhStatus = PDH_ENTRY_NOT_IN_LOG_FILE;
  1712. }
  1713. else {
  1714. if (pLog->dwLastRecordRead != dwIndex) {
  1715. pLog->dwLastRecordRead = dwIndex;
  1716. pPlaybackLog->dwCurrentIndex = dwIndex;
  1717. pLog->pLastRecordRead = PointerSeek(pPlaybackLog->pHeader,
  1718. pPlaybackLog->LogIndexTable[dwIndex]->lDataOffset);
  1719. }
  1720. pIndex = pPlaybackLog->LogIndexTable[dwIndex];
  1721. }
  1722. if (pdhStatus == ERROR_SUCCESS) {
  1723. // find a matching system...
  1724. if (pLogMachine->pBlock != NULL && pLogMachine->dwIndex == dwIndex) {
  1725. pPerfData = pLogMachine->pBlock;
  1726. }
  1727. else {
  1728. pPerfData = PdhiDataFromIndex(pPlaybackLog, pIndex, pCounter->pCounterPath->szMachineName);
  1729. pLogMachine->pBlock = pPerfData;
  1730. pLogMachine->dwIndex = dwIndex;
  1731. }
  1732. if (pPerfData == NULL) {
  1733. pdhStatus = PDH_CSTATUS_NO_MACHINE;
  1734. pLogObject->pObjData = NULL;
  1735. pLogObject->dwIndex = dwIndex;
  1736. }
  1737. else if (pLogObject->pObjData != NULL && pLogObject->dwIndex == dwIndex) {
  1738. pPerfObject = pLogObject->pObjData;
  1739. }
  1740. else {
  1741. pEndGuard = PointerSeek(pPerfData, pPerfData->TotalByteLength);
  1742. pPerfObject = PdhiFindPerfObject(pPerfData, pLogObject->dwObject);
  1743. pLogObject->dwIndex = dwIndex;
  1744. if (pPerfObject != NULL && ((LPVOID) pPerfObject) < pEndGuard) {
  1745. pLogObject->pObjData = pPerfObject;
  1746. }
  1747. else {
  1748. pLogObject->pObjData = NULL;
  1749. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  1750. }
  1751. }
  1752. }
  1753. if (pdhStatus == ERROR_SUCCESS) {
  1754. pEndGuard = PointerSeek(pPerfObject, pPerfObject->TotalByteLength);
  1755. if (pPerfObject->NumInstances == PERF_NO_INSTANCES) {
  1756. pCtrBlock = (PPERF_COUNTER_BLOCK) PointerSeek(pPerfObject, pPerfObject->DefinitionLength);
  1757. if (pCtrBlock != NULL && ((LPVOID) pCtrBlock) < pEndGuard) {
  1758. pData = PointerSeek(pCtrBlock, pLogCounter->dwParent);
  1759. if (pData >= pEndGuard) pData = NULL;
  1760. }
  1761. }
  1762. else if (pLogInstance != NULL) {
  1763. if (pLogInstance->szCounter != NULL && pLogInstance->dwCounterType == dwIndex) {
  1764. pCtrBlock = (PPERF_COUNTER_BLOCK) pLogInstance->szCounter;
  1765. }
  1766. else {
  1767. if (pCounter->plCounterInfo.lInstanceId == PERF_NO_UNIQUE_ID
  1768. && pCounter->pCounterPath->szInstanceName != NULL) {
  1769. pPerfInst = GetInstanceByName(pPerfData,
  1770. pPerfObject,
  1771. pCounter->pCounterPath->szInstanceName,
  1772. pCounter->pCounterPath->szParentName,
  1773. pCounter->pCounterPath->dwIndex);
  1774. if (pPerfInst == NULL && pCounter->pCounterPath->szInstanceName[0] >= L'0'
  1775. && pCounter->pCounterPath->szInstanceName[0] <= L'9') {
  1776. LONG lInstanceId = (LONG) _wtoi(pCounter->pCounterPath->szInstanceName);
  1777. pPerfInst = GetInstanceByUniqueId(pPerfObject, lInstanceId);
  1778. }
  1779. }
  1780. else {
  1781. pPerfInst = GetInstanceByUniqueId(pPerfObject, pCounter->plCounterInfo.lInstanceId);
  1782. }
  1783. if (((LPVOID) pPerfInst) >= pEndGuard) pPerfInst = NULL;
  1784. if (pPerfInst != NULL) {
  1785. pCtrBlock = (PPERF_COUNTER_BLOCK) PointerSeek(pPerfInst, pPerfInst->ByteLength);
  1786. if (((LPVOID) pCtrBlock) >= pEndGuard) pCtrBlock = NULL;
  1787. }
  1788. pLogInstance->szCounter = (LPVOID) pCtrBlock;
  1789. pLogInstance->dwCounterType = dwIndex;
  1790. }
  1791. if (pCtrBlock != NULL) {
  1792. pData = PointerSeek(pCtrBlock, pLogCounter->dwParent);
  1793. if (pData >= pEndGuard) pData = NULL;
  1794. }
  1795. else {
  1796. pdhStatus = PDH_CSTATUS_NO_INSTANCE;
  1797. }
  1798. }
  1799. else {
  1800. pdhStatus = PDH_CSTATUS_NO_INSTANCE;
  1801. }
  1802. }
  1803. if (pdhStatus == ERROR_SUCCESS) {
  1804. if (pData == NULL) {
  1805. pdhStatus = PDH_INVALID_DATA;
  1806. }
  1807. else {
  1808. // assume success
  1809. bReturn = TRUE;
  1810. // convert system time in GMT to Local File time
  1811. SystemTimeToFileTime(& pPerfData->SystemTime, & ftGMT);
  1812. FileTimeToLocalFileTime(& ftGMT, & pValue->TimeStamp);
  1813. pValue->MultiCount = 1; // unless changed
  1814. // load counter value based on counter type
  1815. LocalCType = pCounter->plCounterInfo.dwCounterType;
  1816. switch (LocalCType) {
  1817. //
  1818. // these counter types are loaded as:
  1819. // Numerator = Counter data from perf data block
  1820. // Denominator = Perf Time from perf data block
  1821. // (the time base is the PerfFreq)
  1822. //
  1823. case PERF_COUNTER_COUNTER:
  1824. case PERF_COUNTER_QUEUELEN_TYPE:
  1825. case PERF_SAMPLE_COUNTER:
  1826. pValue->FirstValue = (LONGLONG) (* (DWORD *) pData);
  1827. pValue->SecondValue = pPerfData->PerfTime.QuadPart;
  1828. break;
  1829. case PERF_OBJ_TIME_TIMER:
  1830. pValue->FirstValue = (LONGLONG) (* (DWORD *) pData);
  1831. pValue->SecondValue = pPerfObject->PerfTime.QuadPart;
  1832. break;
  1833. case PERF_COUNTER_100NS_QUEUELEN_TYPE:
  1834. pllData = (UNALIGNED LONGLONG *) pData;
  1835. pValue->FirstValue = * pllData;
  1836. pValue->SecondValue = pPerfData->PerfTime100nSec.QuadPart;
  1837. break;
  1838. case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
  1839. pllData = (UNALIGNED LONGLONG *) pData;
  1840. pValue->FirstValue = * pllData;
  1841. pValue->SecondValue = pPerfObject->PerfTime.QuadPart;
  1842. break;
  1843. case PERF_COUNTER_TIMER:
  1844. case PERF_COUNTER_TIMER_INV:
  1845. case PERF_COUNTER_BULK_COUNT:
  1846. case PERF_COUNTER_MULTI_TIMER:
  1847. case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
  1848. pllData = (UNALIGNED LONGLONG *) pData;
  1849. pValue->FirstValue = * pllData;
  1850. pValue->SecondValue = pPerfData->PerfTime.QuadPart;
  1851. if ((LocalCType & PERF_MULTI_COUNTER) == PERF_MULTI_COUNTER) {
  1852. pValue->MultiCount = (DWORD) * ++ pllData;
  1853. }
  1854. break;
  1855. //
  1856. // These counters do not use any time reference
  1857. //
  1858. case PERF_COUNTER_RAWCOUNT:
  1859. case PERF_COUNTER_RAWCOUNT_HEX:
  1860. pValue->FirstValue = (LONGLONG) (* (DWORD *) pData);
  1861. pValue->SecondValue = 0;
  1862. break;
  1863. case PERF_COUNTER_LARGE_RAWCOUNT:
  1864. case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
  1865. pValue->FirstValue = * (LONGLONG *) pData;
  1866. pValue->SecondValue = 0;
  1867. break;
  1868. //
  1869. // These counters use the 100 Ns time base in thier calculation
  1870. //
  1871. case PERF_100NSEC_TIMER:
  1872. case PERF_100NSEC_TIMER_INV:
  1873. case PERF_100NSEC_MULTI_TIMER:
  1874. case PERF_100NSEC_MULTI_TIMER_INV:
  1875. pllData = (UNALIGNED LONGLONG *) pData;
  1876. pValue->FirstValue = * pllData;
  1877. pValue->SecondValue = pPerfData->PerfTime100nSec.QuadPart;
  1878. if ((LocalCType & PERF_MULTI_COUNTER) == PERF_MULTI_COUNTER) {
  1879. ++ pllData;
  1880. pValue->MultiCount = * (DWORD *) pllData;
  1881. }
  1882. break;
  1883. //
  1884. // These counters use two data points, the one pointed to by
  1885. // pData and the one immediately after
  1886. //
  1887. case PERF_SAMPLE_FRACTION:
  1888. case PERF_RAW_FRACTION:
  1889. pdwData = (DWORD *) pData;
  1890. pValue->FirstValue = (LONGLONG) (* pdwData);
  1891. // find the pointer to the base value in the structure
  1892. PdhiGetPmBaseCounterOffset(pLogCounter, pPerfObject);
  1893. if (pLogCounter->dwInstance > 0) {
  1894. pData = PointerSeek(pCtrBlock, pLogCounter->dwInstance);
  1895. pdwData = (DWORD *) pData;
  1896. pValue->SecondValue = (LONGLONG) (* pdwData);
  1897. }
  1898. else {
  1899. // unable to locate base value
  1900. pValue->SecondValue = 0;
  1901. bReturn = FALSE;
  1902. }
  1903. break;
  1904. case PERF_PRECISION_SYSTEM_TIMER:
  1905. case PERF_PRECISION_100NS_TIMER:
  1906. case PERF_PRECISION_OBJECT_TIMER:
  1907. pllData = (LONGLONG *) pData;
  1908. pValue->FirstValue = * pllData;
  1909. // find the pointer to the base value in the structure
  1910. PdhiGetPmBaseCounterOffset(pLogCounter, pPerfObject);
  1911. if (pLogCounter->dwInstance > 0) {
  1912. pData = PointerSeek(pCtrBlock, pLogCounter->dwInstance);
  1913. pllData = (LONGLONG *) pData;
  1914. pValue->SecondValue = * pllData;
  1915. }
  1916. else {
  1917. // unable to locate base value
  1918. pValue->SecondValue = 0;
  1919. bReturn = FALSE;
  1920. }
  1921. break;
  1922. case PERF_AVERAGE_TIMER:
  1923. case PERF_AVERAGE_BULK:
  1924. // counter (numerator) is a LONGLONG, while the
  1925. // denominator is just a DWORD
  1926. pllData = (UNALIGNED LONGLONG *) pData;
  1927. pValue->FirstValue = * pllData;
  1928. PdhiGetPmBaseCounterOffset(pLogCounter, pPerfObject);
  1929. if (pLogCounter->dwInstance > 0) {
  1930. pData = PointerSeek(pCtrBlock, pLogCounter->dwInstance);
  1931. pdwData = (DWORD *) pData;
  1932. pValue->SecondValue = * pdwData;
  1933. }
  1934. else {
  1935. pValue->SecondValue = 0;
  1936. bReturn = FALSE;
  1937. }
  1938. break;
  1939. //
  1940. // These counters are used as the part of another counter
  1941. // and as such should not be used, but in case they are
  1942. // they'll be handled here.
  1943. //
  1944. case PERF_SAMPLE_BASE:
  1945. case PERF_AVERAGE_BASE:
  1946. case PERF_COUNTER_MULTI_BASE:
  1947. case PERF_RAW_BASE:
  1948. pValue->FirstValue = 0;
  1949. pValue->SecondValue = 0;
  1950. break;
  1951. case PERF_ELAPSED_TIME:
  1952. // this counter type needs the object perf data as well
  1953. pValue->SecondValue = pPerfObject->PerfTime.QuadPart;
  1954. pCounter->TimeBase = pPerfObject->PerfFreq.QuadPart;
  1955. pllData = (UNALIGNED LONGLONG *) pData;
  1956. pValue->FirstValue = *pllData;
  1957. break;
  1958. //
  1959. // These counters are not supported by this function (yet)
  1960. //
  1961. case PERF_COUNTER_TEXT:
  1962. case PERF_COUNTER_NODATA:
  1963. case PERF_COUNTER_HISTOGRAM_TYPE:
  1964. pValue->FirstValue = 0;
  1965. pValue->SecondValue = 0;
  1966. break;
  1967. default:
  1968. // an unidentified counter was returned so
  1969. pValue->FirstValue = 0;
  1970. pValue->SecondValue = 0;
  1971. bReturn = FALSE;
  1972. break;
  1973. }
  1974. pValue->CStatus = PDH_CSTATUS_VALID_DATA;
  1975. }
  1976. }
  1977. return pdhStatus;
  1978. }
  1979. PDH_FUNCTION
  1980. PdhiGetTimeRangeFromPerfmonLog(
  1981. PPDHI_LOG pLog,
  1982. LPDWORD pdwNumEntries,
  1983. PPDH_TIME_INFO pInfo,
  1984. LPDWORD pdwBufferSize
  1985. )
  1986. /*++
  1987. the first entry in the buffer returned is the total time range covered
  1988. in the file, if there are multiple time blocks in the log file, then
  1989. subsequent entries will identify each segment in the file.
  1990. --*/
  1991. {
  1992. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1993. PPLAYBACKLOG pPlaybackLog = (PLAYBACKLOG *) pLog->pPerfmonInfo;
  1994. PDH_TIME_INFO LocalTimeInfo = {0,0,0};
  1995. PPERF_DATA_BLOCK pPerfData;
  1996. FILETIME ftGMT;
  1997. if (pPlaybackLog == NULL) {
  1998. pdhStatus = PDH_INVALID_HANDLE; // log is invalid
  1999. }
  2000. else {
  2001. pPerfData = (PPERF_DATA_BLOCK) PointerSeek(
  2002. pPlaybackLog->pHeader, pPlaybackLog->LogIndexTable[pPlaybackLog->dwFirstIndex]->lDataOffset);
  2003. if (pPerfData != NULL) {
  2004. SystemTimeToFileTime(& pPerfData->SystemTime, & ftGMT);
  2005. FileTimeToLocalFileTime(& ftGMT, (FILETIME *) & LocalTimeInfo.StartTime);
  2006. }
  2007. else {
  2008. pdhStatus = PDH_NO_DATA;
  2009. }
  2010. pPerfData = (PPERF_DATA_BLOCK) PointerSeek(
  2011. pPlaybackLog->pHeader, pPlaybackLog->LogIndexTable[pPlaybackLog->dwLastIndex - 1]->lDataOffset);
  2012. if (pPerfData != NULL) {
  2013. SystemTimeToFileTime(& pPerfData->SystemTime, & ftGMT);
  2014. FileTimeToLocalFileTime(& ftGMT, (FILETIME *) & LocalTimeInfo.EndTime);
  2015. }
  2016. else {
  2017. pdhStatus = PDH_NO_DATA;
  2018. }
  2019. }
  2020. if (pdhStatus == ERROR_SUCCESS) {
  2021. LocalTimeInfo.SampleCount = pPlaybackLog->dwLastIndex - pPlaybackLog->dwFirstIndex;
  2022. if (pInfo != NULL && * pdwBufferSize >= sizeof(PDH_TIME_INFO)) {
  2023. * pdwNumEntries = 1;
  2024. * pInfo = LocalTimeInfo;
  2025. * pdwBufferSize = sizeof(PDH_TIME_INFO);
  2026. pdhStatus = ERROR_SUCCESS;
  2027. }
  2028. else {
  2029. * pdwBufferSize = sizeof(PDH_TIME_INFO);
  2030. pdhStatus = PDH_MORE_DATA;
  2031. }
  2032. }
  2033. return pdhStatus;
  2034. }
  2035. PDH_FUNCTION
  2036. PdhiReadRawPerfmonLogRecord(
  2037. PPDHI_LOG pLog,
  2038. FILETIME * ftRecord,
  2039. PPDH_RAW_LOG_RECORD pBuffer,
  2040. LPDWORD pdwBufferLength
  2041. )
  2042. {
  2043. PDH_STATUS pdhStatus = PDH_NOT_IMPLEMENTED;
  2044. DBG_UNREFERENCED_PARAMETER(pLog);
  2045. DBG_UNREFERENCED_PARAMETER(ftRecord);
  2046. DBG_UNREFERENCED_PARAMETER(pBuffer);
  2047. DBG_UNREFERENCED_PARAMETER(pdwBufferLength);
  2048. return pdhStatus;
  2049. }