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.

1560 lines
56 KiB

  1. /*++
  2. Copyright (C) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. perfhelp.cpp
  5. Abstract:
  6. Registry-based performance counter reading helper
  7. --*/
  8. #include "wpheader.h"
  9. #include <stdio.h>
  10. BOOL PerfHelper::IsMatchingInstance (
  11. PERF_INSTANCE_DEFINITION *pInstanceDef,
  12. DWORD dwCodePage,
  13. LPWSTR szInstanceNameToMatch,
  14. DWORD dwInstanceNameLength
  15. )
  16. // compares pInstanceName to the name in the instance
  17. {
  18. DWORD dwThisInstanceNameLength;
  19. LPWSTR szThisInstanceName;
  20. WCHAR szBufferForANSINames[MAX_PATH];
  21. BOOL bReturn = FALSE;
  22. if (dwInstanceNameLength == 0) {
  23. // get the length to compare
  24. dwInstanceNameLength = lstrlenW (szInstanceNameToMatch);
  25. }
  26. if (dwCodePage == 0) {
  27. // try to take a shortcut here if it's a unicode string
  28. // compare to the length of the shortest string
  29. // get the pointer to this string
  30. szThisInstanceName = GetInstanceName(pInstanceDef);
  31. // convert instance Name from bytes to chars
  32. dwThisInstanceNameLength = pInstanceDef->NameLength / sizeof(WCHAR);
  33. // see if this length includes the term. null. If so shorten it
  34. if (szThisInstanceName[dwThisInstanceNameLength-1] == 0) {
  35. dwThisInstanceNameLength--;
  36. }
  37. } else {
  38. // go the long way and read/translate/convert the string
  39. dwThisInstanceNameLength =GetInstanceNameStr (pInstanceDef,
  40. szBufferForANSINames,
  41. dwCodePage);
  42. if (dwThisInstanceNameLength > 0) {
  43. szThisInstanceName = &szBufferForANSINames[0];
  44. } else {
  45. szThisInstanceName = (LPWSTR)cszSpace;
  46. }
  47. }
  48. // if the lengths are not equal then the names can't be either
  49. if (dwInstanceNameLength == dwThisInstanceNameLength) {
  50. if (lstrcmpiW(szInstanceNameToMatch, szThisInstanceName) == 0) {
  51. // this is a match
  52. bReturn = TRUE;
  53. } else {
  54. // this is not a match
  55. }
  56. }
  57. return bReturn;
  58. }
  59. BOOL PerfHelper::ParseInstanceName (
  60. IN LPCWSTR szInstanceString,
  61. IN LPWSTR szInstanceName,
  62. IN LPWSTR szParentName,
  63. IN LPDWORD lpIndex
  64. )
  65. /*
  66. parses the instance name formatted as follows
  67. [parent/]instance[#index]
  68. parent is optional and if present, is delimited by a forward slash
  69. index is optional and if present, is delimited by a colon
  70. parent and instance may be any legal file name character except a
  71. delimeter character "/#\()" Index must be a string composed of
  72. decimal digit characters (0-9), less than 10 characters in length, and
  73. equate to a value between 0 and 2**32-1 (inclusive).
  74. This function assumes that the instance name and parent name buffers
  75. are of sufficient size.
  76. NOTE: szInstanceName and szInstanceString can be the same buffer
  77. */
  78. {
  79. LPWSTR szSrcChar, szDestChar;
  80. BOOL bReturn = FALSE;
  81. WCHAR szIndexBuffer[MAX_PATH]; // just to be safe
  82. DWORD dwIndex = 0;
  83. szDestChar = (LPWSTR)szInstanceName;
  84. szSrcChar = (LPWSTR)szInstanceString;
  85. __try {
  86. do {
  87. *szDestChar++ = *szSrcChar++;
  88. } while ((*szSrcChar != 0) &&
  89. (*szSrcChar != wcSlash) &&
  90. (*szSrcChar != wcPoundSign));
  91. // see if that was really the parent or not
  92. if (*szSrcChar == wcSlash) {
  93. // terminate destination after test in case they are the same buffer
  94. *szDestChar = 0;
  95. szSrcChar++; // and move source pointer past delimter
  96. // it was the parent name so copy it to the parent
  97. lstrcpyW (szParentName, szInstanceName);
  98. // and copy the rest of the string after the "/" to the
  99. // instance name field
  100. szDestChar = szInstanceName;
  101. do {
  102. *szDestChar++ = *szSrcChar++;
  103. } while ((*szSrcChar != 0) && (*szSrcChar != wcPoundSign));
  104. } else {
  105. // that was the only element so load an empty string for the parent
  106. *szParentName = 0;
  107. }
  108. // *szSrcChar will either be pointing to the end of the input string
  109. // in which case the "0" index is assumed or it will be pointing
  110. // to the # delimiting the index argument in the string.
  111. if (*szSrcChar == wcPoundSign) {
  112. *szDestChar = 0; // terminate the destination string
  113. szSrcChar++; // move past delimter
  114. szDestChar = &szIndexBuffer[0];
  115. do {
  116. *szDestChar++ = *szSrcChar++;
  117. } while (*szSrcChar != 0);
  118. *szDestChar = 0;
  119. dwIndex = wcstoul (szIndexBuffer, NULL, 10);
  120. } else {
  121. *szDestChar = 0; // terminate the destination string
  122. dwIndex = 0;
  123. }
  124. *lpIndex = dwIndex;
  125. bReturn = TRUE;
  126. } __except (EXCEPTION_EXECUTE_HANDLER) {
  127. // unable to move strings
  128. bReturn = FALSE;
  129. }
  130. return bReturn;
  131. }
  132. #pragma warning ( disable : 4127) // while (TRUE) error
  133. PERF_OBJECT_TYPE *
  134. PerfHelper::GetObjectDefByTitleIndex(
  135. IN PERF_DATA_BLOCK *pDataBlock,
  136. IN DWORD ObjectTypeTitleIndex
  137. )
  138. {
  139. DWORD NumTypeDef;
  140. PERF_OBJECT_TYPE *pObjectDef = NULL;
  141. PERF_OBJECT_TYPE *pReturnObject = NULL;
  142. PERF_OBJECT_TYPE *pEndOfBuffer = NULL;
  143. __try {
  144. pObjectDef = FirstObject(pDataBlock);
  145. pEndOfBuffer = (PPERF_OBJECT_TYPE)
  146. ((DWORD_PTR)pDataBlock +
  147. pDataBlock->TotalByteLength);
  148. if (pObjectDef != NULL) {
  149. NumTypeDef = 0;
  150. while (1) {
  151. if ( pObjectDef->ObjectNameTitleIndex == ObjectTypeTitleIndex ) {
  152. pReturnObject = pObjectDef;
  153. break;
  154. } else {
  155. NumTypeDef++;
  156. if (NumTypeDef < pDataBlock->NumObjectTypes) {
  157. pObjectDef = NextObject(pObjectDef);
  158. //make sure next object is legit
  159. if (pObjectDef >= pEndOfBuffer) {
  160. // looks like we ran off the end of the data buffer
  161. assert (pObjectDef < pEndOfBuffer);
  162. break;
  163. } else {
  164. if (pObjectDef != NULL) {
  165. if (pObjectDef->TotalByteLength == 0) {
  166. // 0-length object buffer returned
  167. assert (pObjectDef->TotalByteLength > 0);
  168. break;
  169. }
  170. } else {
  171. // and continue
  172. assert (pObjectDef != NULL);
  173. break;
  174. }
  175. }
  176. } else {
  177. // no more data objects in this data block
  178. break;
  179. }
  180. }
  181. }
  182. } // else no object found
  183. } __except (EXCEPTION_EXECUTE_HANDLER) {
  184. pReturnObject = NULL;
  185. }
  186. return pReturnObject;
  187. }
  188. #pragma warning ( default : 4127) // while (TRUE) error
  189. #pragma warning ( disable : 4127) // while (TRUE) error
  190. PERF_OBJECT_TYPE *
  191. PerfHelper::GetObjectDefByName (
  192. IN PERF_DATA_BLOCK *pDataBlock,
  193. IN DWORD dwLastNameIndex,
  194. IN LPCWSTR *NameArray,
  195. IN LPCWSTR szObjectName
  196. )
  197. {
  198. DWORD NumTypeDef;
  199. PERF_OBJECT_TYPE *pReturnObject = NULL;
  200. PERF_OBJECT_TYPE *pObjectDef = NULL;
  201. PERF_OBJECT_TYPE *pEndOfBuffer = NULL;
  202. __try {
  203. pObjectDef = FirstObject(pDataBlock);
  204. pEndOfBuffer = (PPERF_OBJECT_TYPE)
  205. ((DWORD_PTR)pDataBlock +
  206. pDataBlock->TotalByteLength);
  207. if (pObjectDef != NULL) {
  208. NumTypeDef = 0;
  209. while (1) {
  210. if ( pObjectDef->ObjectNameTitleIndex < dwLastNameIndex ) {
  211. // look up name of object & compare
  212. if (lstrcmpiW(NameArray[pObjectDef->ObjectNameTitleIndex],
  213. szObjectName) == 0) {
  214. pReturnObject = pObjectDef;
  215. break;
  216. }
  217. }
  218. NumTypeDef++;
  219. if (NumTypeDef < pDataBlock->NumObjectTypes) {
  220. pObjectDef = NextObject(pObjectDef); // get next
  221. //make sure next object is legit
  222. if (pObjectDef != NULL) {
  223. if (pObjectDef->TotalByteLength > 0) {
  224. if (pObjectDef >= pEndOfBuffer) {
  225. // looks like we ran off the end of the data buffer
  226. assert (pObjectDef < pEndOfBuffer);
  227. break;
  228. }
  229. } else {
  230. // 0-length object buffer returned
  231. assert (pObjectDef->TotalByteLength > 0);
  232. break;
  233. }
  234. } else {
  235. // null pointer
  236. assert (pObjectDef != NULL);
  237. break;
  238. }
  239. } else {
  240. // end of data block
  241. break;
  242. }
  243. }
  244. } // else no object found
  245. } __except (EXCEPTION_EXECUTE_HANDLER) {
  246. pReturnObject = NULL;
  247. }
  248. return pReturnObject;
  249. }
  250. #pragma warning ( default : 4127) // while (TRUE) error
  251. PERF_INSTANCE_DEFINITION *
  252. PerfHelper::GetInstance(
  253. IN PERF_OBJECT_TYPE *pObjectDef,
  254. IN LONG InstanceNumber
  255. )
  256. {
  257. PERF_INSTANCE_DEFINITION *pInstanceDef;
  258. PERF_INSTANCE_DEFINITION *pReturnDef = NULL;
  259. PERF_INSTANCE_DEFINITION *pEndOfBuffer = NULL;
  260. LONG NumInstance;
  261. if (pObjectDef != NULL) {
  262. pInstanceDef = FirstInstance(pObjectDef);
  263. if (pInstanceDef != NULL) {
  264. pEndOfBuffer = (PERF_INSTANCE_DEFINITION *)EndOfObject(pObjectDef);
  265. for ( NumInstance = 0;
  266. NumInstance < pObjectDef->NumInstances;
  267. NumInstance++ ) {
  268. if ( InstanceNumber == NumInstance ) {
  269. pReturnDef = pInstanceDef;
  270. }
  271. pInstanceDef = NextInstance(pInstanceDef);
  272. // go to next instance in object and check for buffer overrun
  273. if (pInstanceDef >= pEndOfBuffer) {
  274. // something doesn't add up so bail out and return NULL
  275. break;
  276. }
  277. }
  278. }
  279. }
  280. return pReturnDef;
  281. }
  282. PERF_INSTANCE_DEFINITION *
  283. PerfHelper::GetInstanceByUniqueId(
  284. IN PERF_OBJECT_TYPE *pObjectDef,
  285. IN LONG InstanceUniqueId
  286. )
  287. {
  288. PERF_INSTANCE_DEFINITION *pInstanceDef;
  289. PERF_INSTANCE_DEFINITION *pReturnDef = NULL;
  290. PERF_INSTANCE_DEFINITION *pEndOfBuffer = NULL;
  291. LONG NumInstance;
  292. if (pObjectDef != NULL) {
  293. pInstanceDef = FirstInstance(pObjectDef);
  294. if (pInstanceDef != NULL) {
  295. pEndOfBuffer = (PERF_INSTANCE_DEFINITION *)EndOfObject(pObjectDef);
  296. for ( NumInstance = 0;
  297. NumInstance < pObjectDef->NumInstances;
  298. NumInstance++ ) {
  299. if ( InstanceUniqueId == pInstanceDef->UniqueID ) {
  300. pReturnDef = pInstanceDef;
  301. }
  302. pInstanceDef = NextInstance(pInstanceDef);
  303. // go to next instance in object and check for buffer overrun
  304. if (pInstanceDef >= pEndOfBuffer) {
  305. // something doesn't add up so bail out and return NULL
  306. break;
  307. }
  308. }
  309. }
  310. }
  311. return pReturnDef;
  312. }
  313. DWORD
  314. PerfHelper::GetAnsiInstanceName (PPERF_INSTANCE_DEFINITION pInstance,
  315. LPWSTR lpszInstance,
  316. DWORD dwCodePage)
  317. {
  318. LPSTR szSource;
  319. DWORD_PTR dwLength;
  320. UNREFERENCED_PARAMETER(dwCodePage);
  321. szSource = (LPSTR)GetInstanceName(pInstance);
  322. // the locale should be set here
  323. // pInstance->NameLength == the number of bytes (chars) in the string
  324. dwLength = mbstowcs (lpszInstance, szSource, pInstance->NameLength);
  325. lpszInstance[dwLength] = 0; // null terminate string buffer
  326. return (DWORD)dwLength;
  327. }
  328. DWORD
  329. PerfHelper::GetUnicodeInstanceName (PPERF_INSTANCE_DEFINITION pInstance,
  330. LPWSTR lpszInstance)
  331. {
  332. LPWSTR wszSource;
  333. DWORD dwLength;
  334. wszSource = GetInstanceName(pInstance) ;
  335. // pInstance->NameLength == length of string in BYTES so adjust to
  336. // number of wide characters here
  337. dwLength = pInstance->NameLength / sizeof(WCHAR);
  338. wcsncpy (lpszInstance,
  339. (LPWSTR)wszSource,
  340. dwLength);
  341. // add null termination if string length does not include the null
  342. if ((dwLength > 0) && (lpszInstance[dwLength-1] != 0)) { // i.e. it's the last character of the string
  343. lpszInstance[dwLength] = 0; // then add a terminating null char to the string
  344. } else {
  345. // assume that the length value includes the terminating NULL
  346. // so adjust value to indicate chars only
  347. dwLength--;
  348. }
  349. return (dwLength); // just incase there's null's in the string
  350. }
  351. DWORD
  352. PerfHelper::GetInstanceNameStr (PPERF_INSTANCE_DEFINITION pInstance,
  353. LPWSTR lpszInstance,
  354. DWORD dwCodePage)
  355. {
  356. DWORD dwCharSize;
  357. DWORD dwLength = 0;
  358. if (pInstance != NULL) {
  359. if (lpszInstance != NULL) {
  360. if (dwCodePage > 0) {
  361. dwCharSize = sizeof(CHAR);
  362. dwLength = GetAnsiInstanceName (pInstance, lpszInstance, dwCodePage);
  363. } else { // it's a UNICODE name
  364. dwCharSize = sizeof(WCHAR);
  365. dwLength = GetUnicodeInstanceName (pInstance, lpszInstance);
  366. }
  367. // sanity check here...
  368. // the returned string length (in characters) plus the terminating NULL
  369. // should be the same as the specified length in bytes divided by the
  370. // character size. If not then the codepage and instance data type
  371. // don't line up so test that here
  372. if ((dwLength + 1) != (pInstance->NameLength / dwCharSize)) {
  373. // something isn't quite right so try the "other" type of string type
  374. if (dwCharSize == sizeof(CHAR)) {
  375. // then we tried to read it as an ASCII string and that didn't work
  376. // so try it as a UNICODE (if that doesn't work give up and return
  377. // it any way.
  378. dwLength = GetUnicodeInstanceName (pInstance, lpszInstance);
  379. } else if (dwCharSize == sizeof(WCHAR)) {
  380. // then we tried to read it as a UNICODE string and that didn't work
  381. // so try it as an ASCII string (if that doesn't work give up and return
  382. // it any way.
  383. dwLength = GetAnsiInstanceName (pInstance, lpszInstance, dwCodePage);
  384. }
  385. }
  386. } // else return buffer is null
  387. } else {
  388. // no instance def object is specified so return an empty string
  389. *lpszInstance = 0;
  390. }
  391. return dwLength;
  392. }
  393. PERF_INSTANCE_DEFINITION *
  394. PerfHelper::GetInstanceByNameUsingParentTitleIndex(
  395. PERF_DATA_BLOCK *pDataBlock,
  396. PERF_OBJECT_TYPE *pObjectDef,
  397. LPWSTR pInstanceName,
  398. LPWSTR pParentName,
  399. DWORD dwIndex
  400. )
  401. {
  402. PERF_OBJECT_TYPE *pParentObj;
  403. PERF_INSTANCE_DEFINITION *pParentInst;
  404. PERF_INSTANCE_DEFINITION *pInstanceDef;
  405. PERF_INSTANCE_DEFINITION *pReturnDef = NULL;
  406. LONG NumInstance;
  407. DWORD dwLocalIndex;
  408. DWORD dwInstanceNameLength;
  409. pInstanceDef = FirstInstance(pObjectDef);
  410. assert (pInstanceDef != NULL);
  411. dwLocalIndex = dwIndex;
  412. dwInstanceNameLength = lstrlenW(pInstanceName);
  413. for ( NumInstance = 0;
  414. NumInstance < pObjectDef->NumInstances;
  415. NumInstance++ ) {
  416. if (IsMatchingInstance (pInstanceDef, pObjectDef->CodePage,
  417. pInstanceName, dwInstanceNameLength )) {
  418. // this is the correct instance, so see if we need to find a parent instance
  419. if ( pParentName == NULL ) {
  420. // No parent, we're done if this is the right "copy"
  421. if (dwLocalIndex == 0) {
  422. pReturnDef = pInstanceDef;
  423. break;
  424. } else {
  425. --dwLocalIndex;
  426. }
  427. } else {
  428. // Must match parent as well
  429. pParentObj = GetObjectDefByTitleIndex(
  430. pDataBlock,
  431. pInstanceDef->ParentObjectTitleIndex);
  432. if (!pParentObj) {
  433. // can't locate the parent, forget it
  434. break;
  435. }
  436. // Object type of parent found; now find parent
  437. // instance
  438. pParentInst = GetInstance(pParentObj,
  439. pInstanceDef->ParentObjectInstance);
  440. if (!pParentInst) {
  441. // can't locate the parent instance, forget it
  442. break ;
  443. }
  444. if (IsMatchingInstance (pParentInst, pParentObj->CodePage,
  445. pParentName, 0)) {
  446. // Parent Instance Name matches that passed in
  447. if (dwLocalIndex == 0) {
  448. pReturnDef = pInstanceDef;
  449. break;
  450. } else {
  451. --dwLocalIndex;
  452. }
  453. }
  454. }
  455. }
  456. // get the next one
  457. pInstanceDef = NextInstance(pInstanceDef);
  458. }
  459. return pReturnDef;
  460. }
  461. PERF_INSTANCE_DEFINITION *
  462. PerfHelper::GetInstanceByName(
  463. PERF_DATA_BLOCK *pDataBlock,
  464. PERF_OBJECT_TYPE *pObjectDef,
  465. LPWSTR pInstanceName,
  466. LPWSTR pParentName,
  467. DWORD dwIndex
  468. )
  469. {
  470. PERF_OBJECT_TYPE *pParentObj;
  471. PERF_INSTANCE_DEFINITION *pParentInst;
  472. PERF_INSTANCE_DEFINITION *pInstanceDef;
  473. PERF_INSTANCE_DEFINITION *pReturnDef = NULL;
  474. PERF_INSTANCE_DEFINITION *pEndOfBuffer = NULL;
  475. LONG NumInstance;
  476. DWORD dwLocalIndex;
  477. DWORD dwInstanceNameLength;
  478. pInstanceDef = FirstInstance(pObjectDef);
  479. if (pInstanceDef != NULL) {
  480. dwLocalIndex = dwIndex;
  481. dwInstanceNameLength = lstrlenW(pInstanceName);
  482. pEndOfBuffer = (PERF_INSTANCE_DEFINITION *)EndOfObject(pObjectDef);
  483. for ( NumInstance = 0;
  484. NumInstance < pObjectDef->NumInstances;
  485. NumInstance++ ) {
  486. if (IsMatchingInstance (pInstanceDef, pObjectDef->CodePage,
  487. pInstanceName, dwInstanceNameLength)) {
  488. // Instance name matches
  489. if ( !pInstanceDef->ParentObjectTitleIndex ) {
  490. // No parent, we're done
  491. if (dwLocalIndex == 0) {
  492. pReturnDef = pInstanceDef;
  493. break;
  494. } else {
  495. --dwLocalIndex;
  496. }
  497. } else {
  498. // Must match parent as well
  499. pParentObj = GetObjectDefByTitleIndex(
  500. pDataBlock,
  501. pInstanceDef->ParentObjectTitleIndex);
  502. if (pParentObj != NULL) {
  503. // Object type of parent found; now find parent
  504. // instance
  505. pParentInst = GetInstance(pParentObj,
  506. pInstanceDef->ParentObjectInstance);
  507. if (pParentInst != NULL) {
  508. if (IsMatchingInstance (pParentInst,
  509. pParentObj->CodePage, pParentName, 0)) {
  510. // Parent Instance Name matches that passed in
  511. if (dwLocalIndex == 0) {
  512. pReturnDef = pInstanceDef;
  513. break;
  514. } else {
  515. --dwLocalIndex;
  516. }
  517. }
  518. }
  519. } else {
  520. // keep trying
  521. }
  522. }
  523. }
  524. // go to next instance in object and check for buffer overrun
  525. pInstanceDef = NextInstance(pInstanceDef);
  526. if (pInstanceDef >= pEndOfBuffer) {
  527. // something doesn't add up so bail out and return NULL
  528. break;
  529. }
  530. }
  531. }
  532. return pReturnDef;
  533. } // GetInstanceByName
  534. DWORD
  535. PerfHelper::GetFullInstanceNameStr (
  536. PERF_DATA_BLOCK *pPerfData,
  537. PERF_OBJECT_TYPE *pObjectDef,
  538. PERF_INSTANCE_DEFINITION *pInstanceDef,
  539. LPWSTR szInstanceName
  540. )
  541. // compile instance name.
  542. // the instance name can either be just
  543. // the instance name itself or it can be
  544. // the concatenation of the parent instance,
  545. // a delimiting char (backslash) followed by
  546. // the instance name
  547. {
  548. WCHAR szInstanceNameString[1024];
  549. WCHAR szParentNameString[1024];
  550. DWORD dwLength = 0;
  551. PERF_OBJECT_TYPE *pParentObjectDef;
  552. PERF_INSTANCE_DEFINITION *pParentInstanceDef;
  553. szInstanceNameString[0] = UNICODE_NULL;
  554. szParentNameString[0] = UNICODE_NULL;
  555. if (pInstanceDef->UniqueID == PERF_NO_UNIQUE_ID) {
  556. dwLength = GetInstanceNameStr (pInstanceDef,
  557. szInstanceNameString,
  558. pObjectDef->CodePage);
  559. } else {
  560. // make a string out of the unique ID
  561. _ltow (pInstanceDef->UniqueID, szInstanceNameString, 10);
  562. dwLength = lstrlenW (szInstanceNameString);
  563. }
  564. if (pInstanceDef->ParentObjectTitleIndex > 0) {
  565. // then add in parent instance name
  566. pParentObjectDef = GetObjectDefByTitleIndex (
  567. pPerfData,
  568. pInstanceDef->ParentObjectTitleIndex);
  569. if (pParentObjectDef != NULL) {
  570. pParentInstanceDef = GetInstance (
  571. pParentObjectDef,
  572. pInstanceDef->ParentObjectInstance);
  573. assert ((UINT_PTR)pParentObjectDef != (DWORD)0xFFFFFFFF);
  574. if (pParentInstanceDef != NULL) {
  575. if (pParentInstanceDef->UniqueID == PERF_NO_UNIQUE_ID) {
  576. dwLength += GetInstanceNameStr (pParentInstanceDef,
  577. szParentNameString,
  578. pParentObjectDef->CodePage);
  579. } else {
  580. // make a string out of the unique ID
  581. _ltow (pParentInstanceDef->UniqueID, szParentNameString, 10);
  582. dwLength += lstrlenW (szParentNameString);
  583. }
  584. lstrcatW (szParentNameString, cszSlash);
  585. dwLength += 1;
  586. lstrcatW (szParentNameString, szInstanceNameString);
  587. lstrcpyW (szInstanceName, szParentNameString);
  588. } else {
  589. lstrcpyW (szInstanceName, szInstanceNameString);
  590. }
  591. } else {
  592. lstrcpyW (szInstanceName, szInstanceNameString);
  593. }
  594. } else {
  595. lstrcpyW (szInstanceName, szInstanceNameString);
  596. }
  597. return dwLength;
  598. }
  599. //***************************************************************************
  600. //
  601. // PerfHelper::GetInstances
  602. //
  603. // This is called to retrieve all instances of a given class.
  604. //
  605. // Parameters:
  606. // <pBuf> The perf blob retrieved from HKEY_PERFORMANCE_DATA.
  607. // <pClassMap> A map object of the class required.
  608. // <pSink> The sink to which to deliver the objects.
  609. //
  610. //***************************************************************************
  611. //
  612. void PerfHelper::GetInstances(
  613. LPBYTE pBuf,
  614. CClassMapInfo *pClassMap,
  615. IWbemObjectSink *pSink
  616. )
  617. {
  618. PPERF_OBJECT_TYPE PerfObj = 0;
  619. PPERF_OBJECT_TYPE pEndOfBuffer = 0;
  620. PPERF_INSTANCE_DEFINITION PerfInst = 0;
  621. PPERF_INSTANCE_DEFINITION pEndOfObject = 0;
  622. PPERF_COUNTER_DEFINITION PerfCntr = 0, CurCntr = 0;
  623. PPERF_COUNTER_BLOCK PtrToCntr = 0;
  624. PPERF_DATA_BLOCK PerfData = (PPERF_DATA_BLOCK) pBuf;
  625. DWORD i, j, k;
  626. IWbemObjectAccess *pNewInst = 0;
  627. IWbemClassObject *pClsObj = 0;
  628. WCHAR pName[MAX_PATH];
  629. LONG lStatus = 0;
  630. LONG hPropHandle;
  631. LPDWORD pdwVal;
  632. ULONGLONG *pullVal;
  633. HRESULT hRes;
  634. LONG64 llVal;
  635. // Get the first object type.
  636. // ==========================
  637. PerfObj = (PPERF_OBJECT_TYPE)((PBYTE)PerfData +
  638. PerfData->HeaderLength);
  639. if (PerfObj != NULL) {
  640. // get end of buffer
  641. pEndOfBuffer = (PPERF_OBJECT_TYPE)
  642. ((DWORD_PTR)PerfData +
  643. PerfData->TotalByteLength);
  644. // Process all objects.
  645. // ====================
  646. for (i = 0; i < PerfData->NumObjectTypes; i++ ) {
  647. // Within each PERF_OBJECT_TYPE is a series of
  648. // PERF_COUNTER_DEFINITION blocks.
  649. // ==========================================
  650. PerfCntr = (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj +
  651. PerfObj->HeaderLength);
  652. // If the current object isn't of the class we requested,
  653. // simply skip over it. I am not sure if this can really
  654. // happen or not in practice.
  655. // ======================================================
  656. if (PerfObj->ObjectNameTitleIndex != pClassMap->m_dwObjectId) {
  657. PerfObj = (PPERF_OBJECT_TYPE)((PBYTE)PerfObj +
  658. PerfObj->TotalByteLength);
  659. continue;
  660. }
  661. if (PerfObj->NumInstances > 0) {
  662. // Get the first instance.
  663. // =======================
  664. PerfInst = (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj +
  665. PerfObj->DefinitionLength);
  666. if (PerfInst < (PPERF_INSTANCE_DEFINITION)pEndOfBuffer) {
  667. // make sure we are still within the caller's buffer
  668. // then find the end of this object
  669. pEndOfObject = (PERF_INSTANCE_DEFINITION *)EndOfObject(PerfObj);
  670. // Retrieve all instances.
  671. // =======================
  672. for (k = 0; k < DWORD(PerfObj->NumInstances); k++ )
  673. {
  674. CurCntr = PerfCntr;
  675. pClsObj = NULL;
  676. pNewInst = NULL;
  677. HRESULT hr;
  678. // Get the first counter.
  679. // ======================
  680. PtrToCntr = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst +
  681. PerfInst->ByteLength);
  682. // Quickly clone a new instance to send back to the user.
  683. // Since SpawnInstance() returns an IWbemClassObject and
  684. // we really need an IWbemObjectAccess,we have to QI
  685. // after the spawn. We need to fix this, as this number
  686. // of calls is too time consuming.
  687. // ======================================================
  688. hr = pClassMap->m_pClassDef->SpawnInstance(0, &pClsObj);
  689. if (SUCCEEDED(hr))
  690. {
  691. pClsObj->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pNewInst);
  692. pClsObj->Release(); // We only need the IWbemObjectAccess pointer
  693. }
  694. else
  695. {
  696. break;
  697. }
  698. // Locate the instance name.
  699. // ==========================
  700. lStatus = GetFullInstanceNameStr (
  701. PerfData, PerfObj, PerfInst, pName);
  702. // Retrieve all counters.
  703. // ======================
  704. for(j = 0; j < PerfObj->NumCounters; j++ ) {
  705. // Find the WBEM property handle based on the counter title index.
  706. // This function does a quick binary search of the class map object
  707. // to find the handle that goes with this counter.
  708. // ================================================================
  709. hPropHandle = pClassMap->GetPropHandle(
  710. CM_MAKE_PerfObjectId(CurCntr->CounterNameTitleIndex,
  711. CurCntr->CounterType));
  712. if (hPropHandle == 0) {
  713. continue;
  714. }
  715. // update value according to data type
  716. if ((CurCntr->CounterType & 0x300) == 0) {
  717. pdwVal = LPDWORD((LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset));
  718. hRes = pNewInst->WriteDWORD(hPropHandle, *pdwVal);
  719. } else if ((CurCntr->CounterType & 0x300) == 0x100){
  720. pullVal = (ULONGLONG *)((LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset));
  721. llVal = Assign64((PLARGE_INTEGER) pullVal);
  722. hRes = pNewInst->WriteQWORD(hPropHandle, llVal);
  723. } else {
  724. //this shouldn't happen
  725. assert (FALSE);
  726. }
  727. // Get next counter.
  728. // =================
  729. CurCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)CurCntr +
  730. CurCntr->ByteLength);
  731. }
  732. // Write the instance 'name'
  733. // =========================
  734. if (pName && pClassMap->m_dwNameHandle) {
  735. pNewInst->WritePropertyValue(
  736. pClassMap->m_dwNameHandle,
  737. (DWORD)(((DWORD)(wcslen(pName)) + 1) * 2),
  738. LPBYTE(pName)
  739. );
  740. }
  741. // update the timestamp
  742. if (pClassMap->m_dwPerfTimeStampHandle) {
  743. UpdateTimers(pClassMap, pNewInst, PerfData, PerfObj);
  744. }
  745. // Deliver the instance to the user.
  746. // =================================
  747. pSink->Indicate(1, (IWbemClassObject **) &pNewInst);
  748. pNewInst->Release();
  749. // Move to the next perf instance.
  750. // ================================
  751. PerfInst = (PPERF_INSTANCE_DEFINITION)((PBYTE)PtrToCntr +
  752. PtrToCntr->ByteLength);
  753. if (PerfInst >= pEndOfObject) {
  754. // something doesn't add up so bail out of this object
  755. break;
  756. }
  757. }
  758. }
  759. }
  760. else if (PerfObj->NumInstances == PERF_NO_INSTANCES)
  761. {
  762. HRESULT hr;
  763. pClsObj = NULL;
  764. pNewInst = NULL;
  765. // Cases where the counters have one and only one instance.
  766. // ========================================================
  767. // Get the first counter.
  768. // ======================
  769. PtrToCntr = (PPERF_COUNTER_BLOCK) ((PBYTE)PerfObj +
  770. PerfObj->DefinitionLength );
  771. // Quickly clone a new instance to send back to the user.
  772. // Since SpawnInstance() returns an IWbemClassObject and
  773. // we really need an IWbemObjectAccess,we have to QI
  774. // after the spawn. We need to fix this, as this number
  775. // of calls is too time consuming.
  776. // ======================================================
  777. hr = pClassMap->m_pClassDef->SpawnInstance(0, &pClsObj);
  778. if (SUCCEEDED(hr))
  779. {
  780. pClsObj->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pNewInst);
  781. pClsObj->Release();
  782. // Retrieve all counters.
  783. // ======================
  784. for( j=0; j < PerfObj->NumCounters; j++ ) {
  785. // Find the WBEM property handle based on the counter title index.
  786. // This function does a quick binary search of the class map object
  787. // to find the handle that goes with this counter.
  788. // ================================================================
  789. hPropHandle = pClassMap->GetPropHandle(
  790. CM_MAKE_PerfObjectId(PerfCntr->CounterNameTitleIndex,
  791. PerfCntr->CounterType));
  792. if (hPropHandle == 0) {
  793. continue;
  794. }
  795. if ((PerfCntr->CounterType & 0x300) == 0) {
  796. pdwVal = LPDWORD((LPVOID)((PBYTE)PtrToCntr + PerfCntr->CounterOffset));
  797. hRes = pNewInst->WriteDWORD(hPropHandle, *pdwVal);
  798. } else if ((PerfCntr->CounterType & 0x300) == 0x100) {
  799. pullVal = (ULONGLONG *)((LPVOID)((PBYTE)PtrToCntr + PerfCntr->CounterOffset));
  800. llVal = Assign64((PLARGE_INTEGER) pullVal);
  801. hRes = pNewInst->WriteQWORD(hPropHandle, llVal);
  802. } else {
  803. // this shouldn't happen
  804. assert (FALSE);
  805. }
  806. PerfCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr +
  807. PerfCntr->ByteLength);
  808. }
  809. // update the timestamp
  810. if (pClassMap->m_dwPerfTimeStampHandle) {
  811. UpdateTimers(pClassMap, pNewInst, PerfData, PerfObj);
  812. }
  813. pSink->Indicate(1, (IWbemClassObject **) &pNewInst);
  814. pNewInst->Release();
  815. }
  816. } else {
  817. // this object can have instances, but currently doesn't
  818. // so there's nothing to report
  819. }
  820. // Get the next object type.
  821. // =========================
  822. PerfObj = (PPERF_OBJECT_TYPE)((PBYTE)PerfObj +
  823. PerfObj->TotalByteLength);
  824. if (PerfObj >= pEndOfBuffer) {
  825. // looks like we ran off the end of the data buffer
  826. break;
  827. }
  828. }
  829. }
  830. }
  831. void PerfHelper::RefreshEnumeratorInstances (
  832. IN RefresherCacheEl *pThisCacheEl,
  833. IN PPERF_DATA_BLOCK PerfData,
  834. IN PPERF_OBJECT_TYPE PerfObj
  835. )
  836. {
  837. LONG lNumObjInstances;
  838. LONG lStatus;
  839. HRESULT hRes;
  840. PPERF_INSTANCE_DEFINITION PerfInst = 0;
  841. PPERF_INSTANCE_DEFINITION pEndOfObject = 0;
  842. PPERF_COUNTER_DEFINITION PerfCntr = 0, CurCntr = 0;
  843. PPERF_COUNTER_BLOCK PtrToCntr = 0;
  844. WCHAR pName[MAX_PATH];
  845. LONG hPropHandle;
  846. LPDWORD pdwVal;
  847. ULONGLONG *pullVal;
  848. LONG64 llVal;
  849. IWbemObjectAccess *pNewInst = 0;
  850. assert (PerfObj != NULL);
  851. assert (pThisCacheEl != NULL);
  852. if (pThisCacheEl == NULL)
  853. return;
  854. // make sure we have enough pointers
  855. // handle the singleton object case
  856. if (PerfObj->NumInstances == PERF_NO_INSTANCES) {
  857. lNumObjInstances = 1;
  858. } else {
  859. lNumObjInstances = PerfObj->NumInstances;
  860. }
  861. if (pThisCacheEl->m_aEnumInstances.Size() < lNumObjInstances) {
  862. LONG i;
  863. // alloc and init the ID array
  864. if (pThisCacheEl->m_plIds != NULL) {
  865. delete (pThisCacheEl->m_plIds);
  866. }
  867. pThisCacheEl->m_lEnumArraySize = lNumObjInstances;
  868. pThisCacheEl->m_plIds = new LONG[lNumObjInstances];
  869. if (pThisCacheEl->m_plIds == NULL)
  870. return;
  871. for (i = 0; i < lNumObjInstances; i++) pThisCacheEl->m_plIds[i] = i;
  872. // add the new IWbemObjectAccess pointers
  873. for (i = pThisCacheEl->m_aEnumInstances.Size();
  874. i < PerfObj->NumInstances;
  875. i++)
  876. {
  877. IWbemClassObject * pClsObj = NULL;
  878. IWbemObjectAccess * pNewInst = NULL;
  879. HRESULT hr;
  880. hr = pThisCacheEl->m_pClassMap->m_pClassDef->SpawnInstance(0, &pClsObj);
  881. if (SUCCEEDED(hr))
  882. {
  883. pClsObj->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pNewInst);
  884. pClsObj->Release(); // We only need the IWbemObjectAccess pointer
  885. pThisCacheEl->m_aEnumInstances.Add (pNewInst);
  886. }
  887. }
  888. }
  889. assert (pThisCacheEl->m_aEnumInstances.Size() >= lNumObjInstances);
  890. // release enumerator items to prepare a new batch
  891. hRes = pThisCacheEl->m_pHiPerfEnum->RemoveAll(0);
  892. assert (hRes == S_OK);
  893. // update new instance list
  894. if (PerfObj->NumInstances == PERF_NO_INSTANCES) {
  895. //handle the singleton case
  896. } else if (PerfObj->NumInstances > 0) {
  897. // Get the first instance.
  898. // =======================
  899. PerfInst = (PPERF_INSTANCE_DEFINITION)((PBYTE)PerfObj +
  900. PerfObj->DefinitionLength);
  901. // get pointer to the end of this object buffer
  902. pEndOfObject = (PERF_INSTANCE_DEFINITION *)EndOfObject(PerfObj);
  903. // point to the first counter definition in the object
  904. PerfCntr = (PPERF_COUNTER_DEFINITION) ((PBYTE)PerfObj +
  905. PerfObj->HeaderLength);
  906. // Retrieve all instances.
  907. // =======================
  908. for (LONG k = 0; k < PerfObj->NumInstances; k++ ) {
  909. CurCntr = PerfCntr;
  910. // Get the first counter.
  911. // ======================
  912. PtrToCntr = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst +
  913. PerfInst->ByteLength);
  914. // get the IWbemObjectAccess pointer from our
  915. // cached array of pointers
  916. pNewInst = (IWbemObjectAccess *)(pThisCacheEl->m_aEnumInstances.GetAt(k));
  917. // Locate the instance name.
  918. // ==========================
  919. lStatus = GetFullInstanceNameStr (
  920. PerfData, PerfObj, PerfInst, pName);
  921. // Retrieve all counters.
  922. // ======================
  923. for(DWORD j = 0; j < PerfObj->NumCounters; j++ ) {
  924. // Find the WBEM property handle based on the counter title index.
  925. // This function does a quick binary search of the class map object
  926. // to find the handle that goes with this counter.
  927. // ================================================================
  928. hPropHandle = pThisCacheEl->m_pClassMap->GetPropHandle(
  929. CM_MAKE_PerfObjectId(CurCntr->CounterNameTitleIndex,
  930. CurCntr->CounterType));
  931. if (hPropHandle == 0) {
  932. continue;
  933. }
  934. // update value according to data type
  935. if ((CurCntr->CounterType & 0x300) == 0) {
  936. pdwVal = LPDWORD((LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset));
  937. hRes = pNewInst->WriteDWORD(hPropHandle, *pdwVal);
  938. } else if ((CurCntr->CounterType & 0x300) == 0x100){
  939. pullVal = (ULONGLONG *)((LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset));
  940. llVal = Assign64((PLARGE_INTEGER) pullVal);
  941. hRes = pNewInst->WriteQWORD(hPropHandle, llVal);
  942. } else {
  943. //this shouldn't happen
  944. assert (FALSE);
  945. }
  946. // Get next counter.
  947. // =================
  948. CurCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)CurCntr +
  949. CurCntr->ByteLength);
  950. }
  951. // Write the instance 'name'
  952. // =========================
  953. if (pName && pThisCacheEl->m_pClassMap->m_dwNameHandle) {
  954. pNewInst->WritePropertyValue(
  955. pThisCacheEl->m_pClassMap->m_dwNameHandle,
  956. (DWORD)(((DWORD)(wcslen(pName)) + 1) * 2),
  957. LPBYTE(pName)
  958. );
  959. }
  960. // update the timestamp
  961. if (pThisCacheEl->m_pClassMap->m_dwPerfTimeStampHandle) {
  962. UpdateTimers(pThisCacheEl->m_pClassMap, pNewInst, PerfData, PerfObj);
  963. }
  964. // Move to the next perf instance.
  965. // ================================
  966. PerfInst = (PPERF_INSTANCE_DEFINITION)((PBYTE)PtrToCntr +
  967. PtrToCntr->ByteLength);
  968. if (PerfInst >= pEndOfObject) {
  969. // something doesn't add up so bail out of this object
  970. break;
  971. }
  972. }
  973. } else {
  974. // no instances so there's nothing to do
  975. }
  976. if (lNumObjInstances > 0) {
  977. // update the hiperf enumerator object
  978. hRes = pThisCacheEl->m_pHiPerfEnum->AddObjects(
  979. 0,
  980. lNumObjInstances,
  981. pThisCacheEl->m_plIds,
  982. (IWbemObjectAccess __RPC_FAR *__RPC_FAR *)pThisCacheEl->m_aEnumInstances.GetArrayPtr());
  983. } else {
  984. // nothing to do since we've already cleared the enumerator above
  985. }
  986. return;
  987. }
  988. //***************************************************************************
  989. //
  990. // PerfHelper::RefreshInstances
  991. //
  992. // searches the refresher's list first then
  993. // looks up the corresponding items in the perf data structure
  994. //
  995. //***************************************************************************
  996. //
  997. void PerfHelper::RefreshInstances(
  998. LPBYTE pBuf,
  999. CNt5Refresher *pRef
  1000. )
  1001. {
  1002. PPERF_OBJECT_TYPE PerfObj = 0;
  1003. PPERF_INSTANCE_DEFINITION PerfInst = 0;
  1004. PPERF_COUNTER_DEFINITION PerfCntr = 0, CurCntr = 0;
  1005. PPERF_COUNTER_BLOCK PtrToCntr = 0;
  1006. PPERF_DATA_BLOCK PerfData = (PPERF_DATA_BLOCK) pBuf;
  1007. // for each refreshable object
  1008. PRefresherCacheEl pThisCacheEl;
  1009. DWORD dwNumCacheEntries = pRef->m_aCache.Size();
  1010. DWORD dwThisCacheEntryIndex = 0;
  1011. DWORD dwThisCounter;
  1012. DWORD dwThisInstanceIndex = 0;
  1013. DWORD dwNumInstancesInCache = 0;
  1014. IWbemObjectAccess *pInst = 0;
  1015. LONG hPropHandle;
  1016. LPDWORD pdwVal;
  1017. HRESULT hRes;
  1018. ULONGLONG *pullVal;
  1019. LONG64 llVal;
  1020. while (dwThisCacheEntryIndex < dwNumCacheEntries) {
  1021. // get this entry from the cache
  1022. pThisCacheEl = (PRefresherCacheEl) pRef->m_aCache[dwThisCacheEntryIndex];
  1023. // get class map from this entry
  1024. CClassMapInfo *pClassMap = pThisCacheEl->m_pClassMap;
  1025. // get perf object pointer from the perf data block
  1026. PerfObj = GetObjectDefByTitleIndex (
  1027. PerfData, pThisCacheEl->m_dwPerfObjIx);
  1028. if (PerfObj != NULL) {
  1029. // found the object so do each of the instances
  1030. // loaded in this refresher
  1031. PerfCntr = (PPERF_COUNTER_DEFINITION)
  1032. ((PBYTE)PerfObj +
  1033. PerfObj->HeaderLength);
  1034. // found so update the properties
  1035. if (PerfObj->NumInstances > 0) {
  1036. // see if they have an enumerator interface and refresh it if they do
  1037. if (pThisCacheEl->m_pHiPerfEnum != NULL) {
  1038. // refresh enum
  1039. RefreshEnumeratorInstances (pThisCacheEl, PerfData, PerfObj);
  1040. }
  1041. //do each instance in this class
  1042. dwThisInstanceIndex = 0;
  1043. dwNumInstancesInCache = pThisCacheEl->m_aInstances.Size();
  1044. while (dwThisInstanceIndex < dwNumInstancesInCache ) {
  1045. pInst = 0;
  1046. // get the pointer to this instance in the refresher
  1047. CachedInst *pInstInfo = PCachedInst(pThisCacheEl->m_aInstances[dwThisInstanceIndex]);
  1048. // get the pointer to the instance block in the current object
  1049. PerfInst = GetInstanceByName(
  1050. PerfData,
  1051. PerfObj,
  1052. pInstInfo->m_szInstanceName,
  1053. pInstInfo->m_szParentName,
  1054. pInstInfo->m_dwIndex);
  1055. IWbemObjectAccess *pInst = pInstInfo->m_pInst;
  1056. // Get the first counter.
  1057. // ======================
  1058. CurCntr = PerfCntr;
  1059. if (PerfInst != NULL) {
  1060. PtrToCntr = (PPERF_COUNTER_BLOCK)((PBYTE)PerfInst +
  1061. PerfInst->ByteLength);
  1062. // Retrieve all counters for the instance if it was one of the instances
  1063. // we are supposed to be refreshing.
  1064. // =====================================================================
  1065. for (dwThisCounter = 0; dwThisCounter < PerfObj->NumCounters; dwThisCounter++ ) {
  1066. hPropHandle = pClassMap->GetPropHandle(
  1067. CM_MAKE_PerfObjectId(CurCntr->CounterNameTitleIndex,
  1068. CurCntr->CounterType));
  1069. if (hPropHandle == 0) {
  1070. continue;
  1071. }
  1072. // Data is (LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset);
  1073. if ((CurCntr->CounterType & 0x300) == 0) {
  1074. pdwVal = LPDWORD((LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset));
  1075. hRes = pInst->WriteDWORD(hPropHandle, *pdwVal);
  1076. } else if ((CurCntr->CounterType & 0x300) == 0x100) {
  1077. pullVal = (ULONGLONG *)((LPVOID)((PBYTE)PtrToCntr + CurCntr->CounterOffset));
  1078. llVal = Assign64((PLARGE_INTEGER) pullVal);
  1079. hRes = pInst->WriteQWORD(hPropHandle, llVal);
  1080. } else {
  1081. // This shouldn't happen
  1082. assert (FALSE);
  1083. }
  1084. // Get next counter.
  1085. // =================
  1086. CurCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)CurCntr +
  1087. CurCntr->ByteLength);
  1088. }
  1089. // update the timestamp
  1090. if (pClassMap->m_dwPerfTimeStampHandle) {
  1091. UpdateTimers(pClassMap, pInst, PerfData, PerfObj);
  1092. } // else no timestamp handle present
  1093. } else {
  1094. // then there's no data for this
  1095. // instance anymore so zero out the values and continue
  1096. for (dwThisCounter = 0; dwThisCounter < PerfObj->NumCounters; dwThisCounter++ ) {
  1097. hPropHandle = pClassMap->GetPropHandle(
  1098. CM_MAKE_PerfObjectId(CurCntr->CounterNameTitleIndex,
  1099. CurCntr->CounterType));
  1100. if (hPropHandle == 0) {
  1101. continue;
  1102. }
  1103. if ((CurCntr->CounterType & 0x300) == 0) {
  1104. hRes = pInst->WriteDWORD(hPropHandle, 0);
  1105. } else if ((CurCntr->CounterType & 0x300) == 0x100) {
  1106. hRes = pInst->WriteQWORD(hPropHandle, 0);
  1107. } else {
  1108. // This shouldn't happen
  1109. assert (FALSE);
  1110. }
  1111. // Get next counter.
  1112. // =================
  1113. CurCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)CurCntr +
  1114. CurCntr->ByteLength);
  1115. }
  1116. // update the timestamp
  1117. if (pClassMap->m_dwPerfTimeStampHandle) {
  1118. // save system timer tick
  1119. pInst->WriteQWORD(pClassMap->m_dwPerfTimeStampHandle , 0);
  1120. // use system 100 NS timer
  1121. pInst->WriteQWORD(pClassMap->m_dw100NsTimeStampHandle, 0);
  1122. // use timer from object
  1123. pInst->WriteQWORD(pClassMap->m_dwObjectTimeStampHandle, 0);
  1124. }
  1125. }
  1126. // Get the next instance.
  1127. // =====================
  1128. dwThisInstanceIndex++;
  1129. }
  1130. } else if (PerfObj->NumInstances == PERF_NO_INSTANCES
  1131. && NULL != pThisCacheEl->m_pSingleton ) {
  1132. // Check that the singleton instance did not get cleared
  1133. // due to no references.
  1134. // only a single instance so get the properties and
  1135. // update them
  1136. // Get the first counter.
  1137. // Find the singleton WBEM instance which correponds to the singleton perf instance
  1138. // along with its class def so that we have the property handles.
  1139. //
  1140. // Note that since the perf object index translates to a WBEM class and there
  1141. // can only be one instance, all that is required to find the instance in the
  1142. // refresher is the perf object title index.
  1143. // =================================================================================
  1144. pInst = pThisCacheEl->m_pSingleton;
  1145. // ======================
  1146. PtrToCntr = (PPERF_COUNTER_BLOCK) ((PBYTE)PerfObj +
  1147. PerfObj->DefinitionLength );
  1148. // Retrieve all counters if the instance is one we are supposed to be refreshing.
  1149. // ==============================================================================
  1150. for( dwThisCounter=0;
  1151. dwThisCounter < PerfObj->NumCounters;
  1152. dwThisCounter++ ) {
  1153. // Get the property handle for the counter.
  1154. // ========================================
  1155. hPropHandle = pClassMap->GetPropHandle(
  1156. CM_MAKE_PerfObjectId(PerfCntr->CounterNameTitleIndex,
  1157. PerfCntr->CounterType));
  1158. if (hPropHandle == 0) {
  1159. continue;
  1160. }
  1161. // update the data values based on the datatype
  1162. if ((PerfCntr->CounterType & 0x300) == 0) {
  1163. pdwVal = LPDWORD((LPVOID)((PBYTE)PtrToCntr + PerfCntr->CounterOffset));
  1164. hRes = pInst->WriteDWORD(hPropHandle, *pdwVal);
  1165. } else if ((PerfCntr->CounterType & 0x300) == 0x100){
  1166. pullVal = (ULONGLONG *)((LPVOID)((PBYTE)PtrToCntr + PerfCntr->CounterOffset));
  1167. llVal = Assign64((PLARGE_INTEGER) pullVal);
  1168. hRes = pInst->WriteQWORD(hPropHandle, llVal);
  1169. } else {
  1170. // this shouldn't happen
  1171. assert (FALSE);
  1172. }
  1173. // get next counter definition
  1174. PerfCntr = (PPERF_COUNTER_DEFINITION)((PBYTE)PerfCntr +
  1175. PerfCntr->ByteLength);
  1176. }
  1177. // update the timestamp
  1178. if (pClassMap->m_dwPerfTimeStampHandle) {
  1179. UpdateTimers(pClassMap, pInst, PerfData, PerfObj);
  1180. }
  1181. } else {
  1182. // this object could have instances but doesn't so
  1183. // skip
  1184. }
  1185. } else {
  1186. // desired object not found in data
  1187. }
  1188. // Get the next refresher object
  1189. // =========================
  1190. dwThisCacheEntryIndex++;
  1191. }
  1192. }
  1193. //***************************************************************************
  1194. //
  1195. // QueryInstances
  1196. //
  1197. // Used to send back all instances of a perf counter. The counter
  1198. // is specified by the <pClassMap> object, which is tightly bound to
  1199. // a particular counter.
  1200. //
  1201. //***************************************************************************
  1202. //
  1203. BOOL PerfHelper::QueryInstances(
  1204. CPerfObjectAccess *pPerfObj,
  1205. CClassMapInfo *pClassMap,
  1206. IWbemObjectSink *pSink
  1207. )
  1208. {
  1209. DWORD dwBufSize = 0;
  1210. LPBYTE pBuf = NULL;
  1211. LONG lStatus;
  1212. BOOL bReturn = FALSE;
  1213. WCHAR szValueNum[MAX_PATH];
  1214. for (;;) {
  1215. dwBufSize += 0x10000; // 64K
  1216. assert (dwBufSize< 0x100000); // make sure we don't do this forever
  1217. pBuf = new BYTE[dwBufSize];
  1218. assert (pBuf != NULL);
  1219. if (pBuf != NULL) {
  1220. // either do a global or a costly query depending on the
  1221. // object being queried
  1222. if (pClassMap->GetObjectId() > 0) {
  1223. _ultow (pClassMap->GetObjectId(), (LPWSTR)szValueNum, 10);
  1224. } else if (pClassMap->IsCostly()) {
  1225. lstrcpyW (szValueNum, cszCostly);
  1226. } else {
  1227. lstrcpyW (szValueNum, cszGlobal);
  1228. }
  1229. lStatus = pPerfObj->CollectData (pBuf, &dwBufSize, szValueNum);
  1230. if (lStatus == ERROR_MORE_DATA) {
  1231. // toss the old buffer as it's not useful
  1232. delete pBuf;
  1233. continue;
  1234. } else if (lStatus == ERROR_SUCCESS) {
  1235. bReturn = TRUE;
  1236. }
  1237. break;
  1238. } else {
  1239. // memory allocation failure
  1240. break;
  1241. }
  1242. }
  1243. if (bReturn && (pBuf != NULL)) {
  1244. // a good buffer was returned so
  1245. // Decode the instances and send them back.
  1246. // ========================================
  1247. GetInstances(pBuf, pClassMap, pSink);
  1248. }
  1249. // Cleanup.
  1250. // ========
  1251. if (pBuf != NULL) delete pBuf;
  1252. return bReturn;
  1253. }
  1254. //***************************************************************************
  1255. //
  1256. // RefreshInstances
  1257. //
  1258. // Used to refresh a set of instances.
  1259. //
  1260. //***************************************************************************
  1261. //
  1262. BOOL PerfHelper::RefreshInstances(
  1263. CNt5Refresher *pRef
  1264. )
  1265. {
  1266. DWORD dwBufSize = 0;
  1267. LPBYTE pBuf = NULL;
  1268. LONG lStatus;
  1269. BOOL bReturn = FALSE;
  1270. for (;;) {
  1271. dwBufSize += 0x10000; // 64K
  1272. assert (dwBufSize< 0x100000); // make sure we don't do this forever
  1273. pBuf = new BYTE[dwBufSize];
  1274. assert (pBuf != NULL);
  1275. if (pBuf != NULL) {
  1276. lStatus = pRef->m_PerfObj.CollectData (pBuf, &dwBufSize);
  1277. if (lStatus == ERROR_MORE_DATA) {
  1278. // toss the old buffer as it's not useful
  1279. delete pBuf;
  1280. continue;
  1281. } else if (lStatus == ERROR_SUCCESS) {
  1282. bReturn = TRUE;
  1283. }
  1284. break;
  1285. } else {
  1286. // memory allocation failure
  1287. break;
  1288. }
  1289. }
  1290. if (bReturn && (pBuf != NULL)) {
  1291. // update the instances and send them back.
  1292. // ========================================
  1293. RefreshInstances(pBuf, pRef);
  1294. }
  1295. // Cleanup.
  1296. // ========
  1297. if (pBuf != NULL) delete pBuf;
  1298. return bReturn;
  1299. }
  1300. VOID
  1301. PerfHelper::UpdateTimers(
  1302. CClassMapInfo *pClassMap,
  1303. IWbemObjectAccess *pInst,
  1304. PPERF_DATA_BLOCK PerfData,
  1305. PPERF_OBJECT_TYPE PerfObj
  1306. )
  1307. {
  1308. LONG64 llVal;
  1309. // save system timer tick
  1310. llVal = Assign64(&PerfData->PerfTime);
  1311. pInst->WriteQWORD(
  1312. pClassMap->m_dwPerfTimeStampHandle ,
  1313. llVal
  1314. );
  1315. // use timer from object
  1316. llVal = Assign64(&PerfObj->PerfTime);
  1317. pInst->WriteQWORD(
  1318. pClassMap->m_dwObjectTimeStampHandle,
  1319. llVal
  1320. );
  1321. // use system 100 NS timer
  1322. llVal = Assign64(&PerfData->PerfTime100nSec);
  1323. pInst->WriteQWORD(
  1324. pClassMap->m_dw100NsTimeStampHandle,
  1325. llVal
  1326. );
  1327. // save system timer freq
  1328. llVal = Assign64(&PerfData->PerfFreq);
  1329. pInst->WriteQWORD(
  1330. pClassMap->m_dwPerfFrequencyHandle ,
  1331. llVal
  1332. );
  1333. // use timer from object
  1334. llVal = Assign64(&PerfObj->PerfFreq);
  1335. pInst->WriteQWORD(
  1336. pClassMap->m_dwObjectFrequencyHandle,
  1337. llVal
  1338. );
  1339. // use system 100 NS Freq
  1340. pInst->WriteQWORD(
  1341. pClassMap->m_dw100NsFrequencyHandle,
  1342. (LONGLONG)10000000);
  1343. }