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.

820 lines
24 KiB

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