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.

745 lines
21 KiB

  1. /*++
  2. Copyright (C) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. calcfuns.c
  5. Abstract:
  6. Counter calculation functions
  7. --*/
  8. #include <windows.h>
  9. #include <stdlib.h>
  10. #include <assert.h>
  11. #include <math.h>
  12. #include <pdh.h>
  13. #include "pdhicalc.h"
  14. #include "pdhitype.h"
  15. #include "pdhidef.h"
  16. #include "pdhmsg.h"
  17. BOOL
  18. AssignCalcFunction (
  19. IN DWORD dwCounterType,
  20. IN LPCOUNTERCALC *pCalcFunc,
  21. IN LPCOUNTERSTAT *pStatFunc
  22. )
  23. {
  24. BOOL bReturn = TRUE;
  25. // reset the last error value
  26. SetLastError (ERROR_SUCCESS);
  27. if (pCalcFunc == NULL || pStatFunc == NULL) {
  28. SetLastError(PDH_INVALID_ARGUMENT);
  29. return FALSE;
  30. }
  31. else {
  32. __try {
  33. * pCalcFunc = PdhiCalcNoData;
  34. * pStatFunc = PdhiComputeNoDataStats;
  35. }
  36. except (EXCEPTION_EXECUTE_HANDLER) {
  37. return FALSE;
  38. }
  39. }
  40. switch (dwCounterType) {
  41. case PERF_DOUBLE_RAW:
  42. *pCalcFunc = PdhiCalcDouble;
  43. *pStatFunc = PdhiComputeRawCountStats;
  44. break;
  45. case PERF_AVERAGE_TIMER:
  46. *pCalcFunc = PdhiCalcAverage;
  47. *pStatFunc = PdhiComputeFirstLastStats;
  48. break;
  49. case PERF_ELAPSED_TIME:
  50. *pCalcFunc = PdhiCalcElapsedTime;
  51. *pStatFunc = PdhiComputeRawCountStats;
  52. break;
  53. case PERF_RAW_FRACTION:
  54. case PERF_LARGE_RAW_FRACTION:
  55. *pCalcFunc = PdhiCalcRawFraction;
  56. *pStatFunc = PdhiComputeRawCountStats;
  57. break;
  58. case PERF_COUNTER_COUNTER:
  59. case PERF_COUNTER_BULK_COUNT:
  60. case PERF_SAMPLE_COUNTER:
  61. *pCalcFunc = PdhiCalcCounter;
  62. *pStatFunc = PdhiComputeFirstLastStats;
  63. break;
  64. case PERF_AVERAGE_BULK:
  65. case PERF_COUNTER_TIMER:
  66. case PERF_100NSEC_TIMER:
  67. case PERF_OBJ_TIME_TIMER:
  68. case PERF_COUNTER_QUEUELEN_TYPE:
  69. case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
  70. case PERF_COUNTER_100NS_QUEUELEN_TYPE:
  71. case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
  72. case PERF_SAMPLE_FRACTION:
  73. case PERF_COUNTER_MULTI_TIMER:
  74. case PERF_100NSEC_MULTI_TIMER:
  75. case PERF_PRECISION_SYSTEM_TIMER:
  76. case PERF_PRECISION_100NS_TIMER:
  77. case PERF_PRECISION_OBJECT_TIMER:
  78. *pCalcFunc = PdhiCalcTimer;
  79. *pStatFunc = PdhiComputeFirstLastStats;
  80. break;
  81. case PERF_COUNTER_TIMER_INV:
  82. case PERF_100NSEC_TIMER_INV:
  83. case PERF_COUNTER_MULTI_TIMER_INV:
  84. case PERF_100NSEC_MULTI_TIMER_INV:
  85. *pCalcFunc = PdhiCalcInverseTimer;
  86. *pStatFunc = PdhiComputeFirstLastStats;
  87. break;
  88. case PERF_COUNTER_RAWCOUNT:
  89. case PERF_COUNTER_LARGE_RAWCOUNT:
  90. case PERF_COUNTER_RAWCOUNT_HEX:
  91. case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
  92. *pCalcFunc = PdhiCalcRawCounter;
  93. *pStatFunc = PdhiComputeRawCountStats;
  94. break;
  95. case PERF_COUNTER_DELTA:
  96. case PERF_COUNTER_LARGE_DELTA:
  97. *pCalcFunc = PdhiCalcDelta;
  98. *pStatFunc = PdhiComputeRawCountStats;
  99. break;
  100. case PERF_COUNTER_TEXT:
  101. case PERF_SAMPLE_BASE:
  102. case PERF_AVERAGE_BASE:
  103. case PERF_COUNTER_MULTI_BASE:
  104. case PERF_RAW_BASE:
  105. //case PERF_LARGE_RAW_BASE:
  106. case PERF_COUNTER_HISTOGRAM_TYPE:
  107. case PERF_COUNTER_NODATA:
  108. case PERF_PRECISION_TIMESTAMP:
  109. *pCalcFunc = PdhiCalcNoData;
  110. *pStatFunc = PdhiComputeNoDataStats;
  111. break;
  112. default:
  113. // an unrecognized counter type. Define the function, but
  114. // return false.
  115. *pCalcFunc = PdhiCalcNoData;
  116. *pStatFunc = PdhiComputeNoDataStats;
  117. SetLastError (PDH_FUNCTION_NOT_FOUND);
  118. bReturn = FALSE;
  119. break;
  120. }
  121. return bReturn;
  122. }
  123. double
  124. APIENTRY
  125. PdhiCalcDouble (
  126. PPDH_RAW_COUNTER pThisValue,
  127. PPDH_RAW_COUNTER pLastValue,
  128. LONGLONG *pllTimeBase,
  129. LPDWORD pdwStatus
  130. )
  131. {
  132. double dReturn;
  133. DWORD dwStatus;
  134. UNREFERENCED_PARAMETER(pLastValue);
  135. UNREFERENCED_PARAMETER(pllTimeBase);
  136. dReturn = *(DOUBLE *)&pThisValue->FirstValue;
  137. if (dReturn < 0) {
  138. dReturn = 0.0f;
  139. dwStatus = PDH_CSTATUS_INVALID_DATA;
  140. } else {
  141. dwStatus = pThisValue->CStatus;
  142. }
  143. if (pdwStatus != NULL) {
  144. *pdwStatus = dwStatus;
  145. }
  146. return dReturn;
  147. }
  148. double
  149. APIENTRY
  150. PdhiCalcAverage (
  151. PPDH_RAW_COUNTER pThisValue,
  152. PPDH_RAW_COUNTER pLastValue,
  153. LONGLONG *pllTimeBase,
  154. LPDWORD pdwStatus
  155. )
  156. {
  157. LONGLONG llNumDiff;
  158. LONGLONG llDenDiff = 0;
  159. double dNum;
  160. double dDen;
  161. double dReturn = 0.0f;
  162. DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
  163. // test access to the required second parameter (lastValue)
  164. __try {
  165. if (pLastValue != NULL) {
  166. if (IsSuccessSeverity(pLastValue->CStatus)) {
  167. llDenDiff = pThisValue->SecondValue - pLastValue->SecondValue;
  168. } else {
  169. dwStatus = pLastValue->CStatus;
  170. }
  171. } else {
  172. dwStatus = PDH_CSTATUS_INVALID_DATA;
  173. }
  174. } __except (EXCEPTION_EXECUTE_HANDLER) {
  175. dwStatus = PDH_INVALID_ARGUMENT;
  176. }
  177. if (dwStatus == PDH_CSTATUS_VALID_DATA) {
  178. if ((llDenDiff > 0) && (*pllTimeBase > 0)) {
  179. llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue;
  180. if (llNumDiff > 0) {
  181. dNum = (double)llNumDiff;
  182. dNum /= (double)*pllTimeBase;
  183. dDen = (double)llDenDiff;
  184. dReturn = (dNum / dDen);
  185. } else if (llNumDiff != 0) {
  186. dwStatus = PDH_CALC_NEGATIVE_VALUE;
  187. }
  188. } else {
  189. if (llDenDiff < 0) {
  190. dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR;
  191. } else if (*pllTimeBase < 0) {
  192. dwStatus = PDH_CALC_NEGATIVE_TIMEBASE;
  193. }
  194. }
  195. }
  196. if (pdwStatus != NULL) {
  197. *pdwStatus = dwStatus;
  198. }
  199. return dReturn;
  200. }
  201. double
  202. APIENTRY
  203. PdhiCalcElapsedTime (
  204. PPDH_RAW_COUNTER pThisValue,
  205. PPDH_RAW_COUNTER pLastValue,
  206. LONGLONG *pllTimeBase,
  207. LPDWORD pdwStatus
  208. )
  209. {
  210. LONGLONG llDiff;
  211. double dReturn = 0.0f;
  212. DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
  213. UNREFERENCED_PARAMETER(pLastValue);
  214. // test access to the required second parameter (lastValue)
  215. __try {
  216. if (IsSuccessSeverity(pThisValue->CStatus)) {
  217. llDiff = pThisValue->SecondValue - pThisValue->FirstValue;
  218. } else {
  219. dwStatus = pThisValue->CStatus;
  220. }
  221. } __except (EXCEPTION_EXECUTE_HANDLER) {
  222. dwStatus = PDH_INVALID_ARGUMENT;
  223. }
  224. if (dwStatus == PDH_CSTATUS_VALID_DATA) {
  225. if (*pllTimeBase > 0) {
  226. llDiff = pThisValue->SecondValue - pThisValue->FirstValue;
  227. if (llDiff > 0) {
  228. dReturn = (double)llDiff;
  229. dReturn /= (double)*pllTimeBase;
  230. } else {
  231. if (llDiff < 0) {
  232. dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR;
  233. }
  234. }
  235. } else {
  236. if (*pllTimeBase < 0) {
  237. dwStatus = PDH_CALC_NEGATIVE_TIMEBASE;
  238. }
  239. }
  240. }
  241. if (pdwStatus != NULL) {
  242. *pdwStatus = dwStatus;
  243. }
  244. return dReturn;
  245. }
  246. double
  247. APIENTRY
  248. PdhiCalcRawFraction (
  249. PPDH_RAW_COUNTER pThisValue,
  250. PPDH_RAW_COUNTER pLastValue,
  251. LONGLONG *pllTimeBase,
  252. LPDWORD pdwStatus
  253. )
  254. {
  255. LONGLONG llDen;
  256. double dReturn = 0.0f;
  257. DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
  258. UNREFERENCED_PARAMETER(pLastValue);
  259. UNREFERENCED_PARAMETER(pllTimeBase);
  260. if ((llDen = pThisValue->SecondValue) > 0) {
  261. dReturn = (double)(pThisValue->FirstValue);
  262. dReturn /= (double)llDen;
  263. } else {
  264. if (llDen < 0) {
  265. dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR;
  266. }
  267. dReturn = (double)0.0;
  268. }
  269. if (pdwStatus != NULL) {
  270. *pdwStatus = dwStatus;
  271. }
  272. return dReturn;
  273. }
  274. double
  275. APIENTRY
  276. PdhiCalcCounter (
  277. PPDH_RAW_COUNTER pThisValue,
  278. PPDH_RAW_COUNTER pLastValue,
  279. LONGLONG *pllTimeBase,
  280. LPDWORD pdwStatus
  281. )
  282. {
  283. LONGLONG llNumDiff;
  284. LONGLONG llDenDiff = 0;
  285. double dNum;
  286. double dDen;
  287. double dReturn = 0.0f;
  288. double dMulti;
  289. DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
  290. // test access to the required second parameter (lastValue)
  291. __try {
  292. if (pLastValue != NULL) {
  293. if (IsSuccessSeverity(pLastValue->CStatus)) {
  294. llDenDiff = pThisValue->SecondValue - pLastValue->SecondValue;
  295. } else {
  296. dwStatus = pLastValue->CStatus;
  297. }
  298. } else {
  299. dwStatus = PDH_CSTATUS_INVALID_DATA;
  300. }
  301. } __except (EXCEPTION_EXECUTE_HANDLER) {
  302. dwStatus = PDH_INVALID_ARGUMENT;
  303. }
  304. if (dwStatus == PDH_CSTATUS_VALID_DATA) {
  305. if ((llDenDiff > 0) && (*pllTimeBase)) {
  306. llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue;
  307. if (llNumDiff > 0) {
  308. dNum = (double)llNumDiff;
  309. dDen = (double)llDenDiff;
  310. dDen /= (double)*pllTimeBase;
  311. dReturn = (dNum / dDen);
  312. if (pThisValue->MultiCount > 1) {
  313. // don't do this if the count is <= 1
  314. dMulti = (double) pThisValue->FirstValue;
  315. dReturn /= dMulti;
  316. }
  317. } else if (llNumDiff < 0) {
  318. dwStatus = PDH_CALC_NEGATIVE_VALUE;
  319. } else {
  320. // just return 0 & normal status
  321. }
  322. } else {
  323. if (llDenDiff < 0) {
  324. dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR;
  325. } else if (*pllTimeBase < 0) {
  326. dwStatus = PDH_CALC_NEGATIVE_TIMEBASE;
  327. }
  328. }
  329. }
  330. if (pdwStatus != NULL) {
  331. *pdwStatus = dwStatus;
  332. }
  333. return dReturn;
  334. }
  335. double
  336. APIENTRY
  337. PdhiCalcTimer (
  338. PPDH_RAW_COUNTER pThisValue,
  339. PPDH_RAW_COUNTER pLastValue,
  340. LONGLONG *pllTimeBase,
  341. LPDWORD pdwStatus
  342. )
  343. {
  344. LONGLONG llNumDiff;
  345. LONGLONG llDenDiff = 0;
  346. double dReturn = 0.0f;
  347. DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
  348. UNREFERENCED_PARAMETER(pllTimeBase);
  349. // test access to the required second parameter (lastValue)
  350. __try {
  351. if (pLastValue != NULL) {
  352. if (IsSuccessSeverity(pLastValue->CStatus)) {
  353. llDenDiff = pThisValue->SecondValue - pLastValue->SecondValue;
  354. } else {
  355. dwStatus = pLastValue->CStatus;
  356. }
  357. } else {
  358. // the last value wasn't passed in
  359. dwStatus = PDH_CSTATUS_INVALID_DATA;
  360. }
  361. } __except (EXCEPTION_EXECUTE_HANDLER) {
  362. dwStatus = PDH_INVALID_ARGUMENT;
  363. }
  364. if (dwStatus == PDH_CSTATUS_VALID_DATA) {
  365. if (llDenDiff > 0) {
  366. llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue;
  367. if (llNumDiff > 0) {
  368. dReturn = (double)llNumDiff;
  369. dReturn /= (double)llDenDiff;
  370. if (pThisValue->MultiCount > 1) {
  371. // don't do this if the count is <= 1
  372. dReturn /= (double)pThisValue->MultiCount;
  373. }
  374. } else if (llNumDiff < 0) {
  375. dwStatus = PDH_CALC_NEGATIVE_VALUE;
  376. } else {
  377. // just return 0 and a normal status
  378. }
  379. } else {
  380. if (llDenDiff < 0) {
  381. dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR;
  382. }
  383. }
  384. }
  385. if (pdwStatus != NULL) {
  386. *pdwStatus = dwStatus;
  387. }
  388. return dReturn;
  389. }
  390. double
  391. APIENTRY
  392. PdhiCalcInverseTimer (
  393. PPDH_RAW_COUNTER pThisValue,
  394. PPDH_RAW_COUNTER pLastValue,
  395. LONGLONG *pllTimeBase,
  396. LPDWORD pdwStatus
  397. )
  398. {
  399. LONGLONG llNumDiff;
  400. LONGLONG llDenDiff = 0;
  401. double dReturn = 0.0f;
  402. double dNumDiff, dDenDiff;
  403. double dRatio;
  404. DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
  405. UNREFERENCED_PARAMETER(pllTimeBase);
  406. // test access to the required second parameter (lastValue)
  407. __try {
  408. if (pLastValue != NULL) {
  409. if (IsSuccessSeverity(pLastValue->CStatus)) {
  410. llDenDiff = pThisValue->SecondValue - pLastValue->SecondValue;
  411. } else {
  412. dwStatus = pLastValue->CStatus;
  413. }
  414. } else {
  415. dwStatus = PDH_CSTATUS_INVALID_DATA;
  416. }
  417. } __except (EXCEPTION_EXECUTE_HANDLER) {
  418. dwStatus = PDH_INVALID_ARGUMENT;
  419. }
  420. if (dwStatus == PDH_CSTATUS_VALID_DATA) {
  421. if (llDenDiff > 0) {
  422. llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue;
  423. if (llNumDiff >= 0) {
  424. dNumDiff = (double)llNumDiff;
  425. dDenDiff = (double)llDenDiff;
  426. dRatio = dNumDiff;
  427. dRatio /= dDenDiff;
  428. if (pThisValue->MultiCount <= 1) {
  429. dReturn = (double)1.0;
  430. } else {
  431. dReturn = (double)pThisValue->MultiCount;
  432. }
  433. // subtract the result from the multi count to get the
  434. // "inverse" time
  435. dReturn -= dRatio;
  436. if (dReturn < (double)0.0) {
  437. // allow a "fudge" factor before reporting errors
  438. if (dReturn < (double)(-0.1)) {
  439. dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR;
  440. }
  441. dReturn = (double)0.0;
  442. }
  443. } else if (llNumDiff < 0) {
  444. dwStatus = PDH_CALC_NEGATIVE_VALUE;
  445. }
  446. } else {
  447. if (llDenDiff < 0) {
  448. dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR;
  449. }
  450. dReturn = (double)0.0;
  451. }
  452. }
  453. if (pdwStatus != NULL) {
  454. *pdwStatus = dwStatus;
  455. }
  456. return dReturn;
  457. }
  458. double
  459. APIENTRY
  460. PdhiCalcRawCounter (
  461. PPDH_RAW_COUNTER pThisValue,
  462. PPDH_RAW_COUNTER pLastValue,
  463. LONGLONG *pllTimeBase,
  464. LPDWORD pdwStatus
  465. )
  466. {
  467. UNREFERENCED_PARAMETER(pLastValue);
  468. UNREFERENCED_PARAMETER(pllTimeBase);
  469. if (pdwStatus != NULL) {
  470. *pdwStatus = pThisValue->CStatus;
  471. }
  472. return (double)pThisValue->FirstValue;
  473. }
  474. double
  475. APIENTRY
  476. PdhiCalcNoData (
  477. PPDH_RAW_COUNTER pThisValue,
  478. PPDH_RAW_COUNTER pLastValue,
  479. LONGLONG *pllTimeBase,
  480. LPDWORD pdwStatus
  481. )
  482. {
  483. UNREFERENCED_PARAMETER(pThisValue);
  484. UNREFERENCED_PARAMETER(pLastValue);
  485. UNREFERENCED_PARAMETER(pllTimeBase);
  486. if (pdwStatus != NULL) {
  487. *pdwStatus = PDH_NO_DATA;
  488. }
  489. return (double)0.0;
  490. }
  491. double
  492. APIENTRY
  493. PdhiCalcDelta (
  494. PPDH_RAW_COUNTER pThisValue,
  495. PPDH_RAW_COUNTER pLastValue,
  496. LONGLONG *pllTimeBase,
  497. LPDWORD pdwStatus
  498. )
  499. {
  500. LONGLONG llNumDiff = 0;
  501. double dReturn = 0.0f;
  502. DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
  503. UNREFERENCED_PARAMETER(pllTimeBase);
  504. // test access to the required second parameter (lastValue)
  505. __try {
  506. if (pLastValue != NULL) {
  507. if (IsSuccessSeverity(pLastValue->CStatus)) {
  508. llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue;
  509. } else {
  510. dwStatus = pLastValue->CStatus;
  511. }
  512. } else {
  513. dwStatus = PDH_CSTATUS_INVALID_DATA;
  514. }
  515. } __except (EXCEPTION_EXECUTE_HANDLER) {
  516. dwStatus = PDH_INVALID_ARGUMENT;
  517. }
  518. if (dwStatus == PDH_CSTATUS_VALID_DATA) {
  519. if (llNumDiff < 0) {
  520. dwStatus = PDH_CALC_NEGATIVE_VALUE;
  521. dReturn = (double)0.0;
  522. } else {
  523. dReturn = (double)llNumDiff;
  524. }
  525. }
  526. if (pdwStatus != NULL) {
  527. *pdwStatus = dwStatus;
  528. }
  529. return dReturn;
  530. }
  531. PDH_STATUS
  532. PdhiComputeFormattedValue (
  533. IN LPCOUNTERCALC pCalcFunc,
  534. IN DWORD dwCounterType,
  535. IN LONG lScale,
  536. IN DWORD dwFormat,
  537. IN PPDH_RAW_COUNTER pRawValue1,
  538. IN PPDH_RAW_COUNTER pRawValue2,
  539. IN PLONGLONG pTimeBase,
  540. IN DWORD dwReserved,
  541. IN PPDH_FMT_COUNTERVALUE pValue
  542. )
  543. {
  544. double dResult = (double)0.0;
  545. double dScale;
  546. PDH_STATUS lStatus = ERROR_SUCCESS;
  547. DWORD dwValueStatus = PDH_CSTATUS_VALID_DATA;
  548. UNREFERENCED_PARAMETER(dwReserved);
  549. __try {
  550. // make sure the counter values are valid before continuing
  551. if (pRawValue1 != NULL) {
  552. if ((pRawValue1->CStatus != PDH_CSTATUS_NEW_DATA) &&
  553. (pRawValue1->CStatus != PDH_CSTATUS_VALID_DATA)) {
  554. dwValueStatus = pRawValue1->CStatus;
  555. lStatus = PDH_INVALID_DATA;
  556. }
  557. } else {
  558. // this is a required parameter
  559. dwValueStatus = PDH_CSTATUS_INVALID_DATA;
  560. lStatus = PDH_INVALID_ARGUMENT;
  561. }
  562. if ((lStatus == ERROR_SUCCESS) && (pRawValue2 != NULL)) {
  563. // this is an optional parameter, but if present, it must be valid
  564. if ((pRawValue2->CStatus != PDH_CSTATUS_NEW_DATA) &&
  565. (pRawValue2->CStatus != PDH_CSTATUS_VALID_DATA)) {
  566. dwValueStatus = pRawValue2->CStatus;
  567. lStatus = PDH_INVALID_DATA;
  568. }
  569. }
  570. if ( ((dwFormat & PDH_FMT_LONG) != 0)
  571. && ((dwFormat & PDH_FMT_LARGE) != 0)) {
  572. dwValueStatus = PDH_CSTATUS_INVALID_DATA;
  573. lStatus = PDH_INVALID_ARGUMENT;
  574. }
  575. else if ( ((dwFormat & PDH_FMT_LONG) != 0)
  576. || ((dwFormat & PDH_FMT_LARGE) != 0)) {
  577. if (dwFormat & PDH_FMT_DOUBLE) {
  578. dwValueStatus = PDH_CSTATUS_INVALID_DATA;
  579. lStatus = PDH_INVALID_ARGUMENT;
  580. }
  581. }
  582. if (lScale > PDH_MAX_SCALE || lScale < PDH_MIN_SCALE) {
  583. dwValueStatus = PDH_CSTATUS_INVALID_DATA;
  584. lStatus = PDH_INVALID_ARGUMENT;
  585. }
  586. if (pTimeBase == NULL) {
  587. dwValueStatus = PDH_CSTATUS_INVALID_DATA;
  588. lStatus = PDH_INVALID_ARGUMENT;
  589. }
  590. else {
  591. LONGLONG tmpTimeBase = * pTimeBase;
  592. * pTimeBase = tmpTimeBase;
  593. }
  594. } __except (EXCEPTION_EXECUTE_HANDLER) {
  595. dwValueStatus = PDH_CSTATUS_INVALID_DATA;
  596. lStatus = PDH_INVALID_ARGUMENT;
  597. }
  598. if (lStatus == ERROR_SUCCESS) {
  599. // call the counter's calculation function if the raw value is valid
  600. if (IsSuccessSeverity(pRawValue1->CStatus)) {
  601. __try {
  602. dResult = (*pCalcFunc)(
  603. pRawValue1,
  604. pRawValue2,
  605. pTimeBase,
  606. &dwValueStatus);
  607. // format returned value
  608. if ((dwCounterType & 0xF0000000) == PERF_DISPLAY_PERCENT) {
  609. // scale to show percent
  610. dResult *= (double)100.0;
  611. // this should probably be controlled by a registry
  612. // value as is the case with PERFMON
  613. if (!(dwFormat & PDH_FMT_NOCAP100)) {
  614. if (dResult > (double)100.0) dResult = (double)100.0;
  615. }
  616. }
  617. if (!(dwFormat & PDH_FMT_NOSCALE)) {
  618. //now scale
  619. dScale = pow (10.0, (double)lScale);
  620. dResult *= dScale;
  621. }
  622. if (dwFormat & PDH_FMT_1000) {
  623. //now scale
  624. dResult *= (double)1000.0;
  625. }
  626. } __except (EXCEPTION_EXECUTE_HANDLER) {
  627. // something failed
  628. dResult = (double)0.0;
  629. dwValueStatus = PDH_INVALID_ARGUMENT;
  630. }
  631. } else {
  632. dwValueStatus = pRawValue1->CStatus;
  633. }
  634. if (!IsSuccessSeverity(dwValueStatus)) {
  635. // an error occured so pass that on to the caller
  636. lStatus = dwValueStatus;
  637. }
  638. } //end if valid counter data
  639. // now format
  640. __try {
  641. if (dwFormat & PDH_FMT_LONG) {
  642. pValue->longValue = (LONG)dResult;
  643. } else if (dwFormat & PDH_FMT_LARGE) {
  644. pValue->largeValue = (LONGLONG)dResult;
  645. } else {
  646. // double is the default
  647. pValue->doubleValue = dResult;
  648. }
  649. pValue->CStatus = dwValueStatus;
  650. } __except (EXCEPTION_EXECUTE_HANDLER) {
  651. lStatus = PDH_INVALID_ARGUMENT;
  652. }
  653. return lStatus;
  654. }