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

1560 lines
60 KiB

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