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.

1793 lines
71 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1992-1993 Microsoft Corporation
  3. Module Name:
  4. counters.c
  5. Abstract:
  6. This module contains the routines to calculate "DataPoint" values from
  7. the registry data.
  8. The algoritms were lifted from RussBls's "Data.C" in winmeter.
  9. All the math is done in floating point to get the correct results, at
  10. the sacrifice of efficiency on a 386 with not 387. We can always
  11. revisit these routines later.
  12. Revision History:
  13. Bob Watson 11/04/92
  14. -- modified calculations to use more integer math and "early
  15. exits" to improve efficiency on slower & non-coprocessor
  16. machines
  17. --*/
  18. //==========================================================================//
  19. // Includes //
  20. //==========================================================================//
  21. #include "perfmon.h" // perfmon include files
  22. #include "counters.h" // Exported declarations for this file
  23. #include "perfmsg.h" // message file definitions
  24. //==========================================================================//
  25. // Constants //
  26. //==========================================================================//
  27. #ifdef DBG_COUNTER_DATA
  28. #undef DBG_COUNTER_DATA
  29. #endif
  30. //#define DBG_COUNTER_DATA
  31. #define INVERT PERF_COUNTER_TIMER_INV
  32. #define NS100_INVERT PERF_100NSEC_TIMER_INV
  33. #define NS100 PERF_100NSEC_TIMER
  34. #define TIMER_MULTI PERF_COUNTER_MULTI_TIMER
  35. #define TIMER_MULTI_INVERT PERF_COUNTER_MULTI_TIMER_INV
  36. #define NS100_MULTI PERF_100NSEC_MULTI_TIMER
  37. #define NS100_MULTI_INVERT PERF_100NSEC_MULTI_TIMER_INV
  38. #define FRACTION 1
  39. #define BULK 1
  40. #define TOO_BIG (FLOAT)1500000000
  41. //==========================================================================//
  42. // Local Functions //
  43. //==========================================================================//
  44. #define eLIntToFloat(LI) (FLOAT)( ((LARGE_INTEGER *)(LI))->QuadPart )
  45. static LPTSTR cszSpace = TEXT(" ");
  46. FLOAT
  47. eGetTimeInterval(
  48. IN PLARGE_INTEGER pliCurrentTime,
  49. IN PLARGE_INTEGER pliPreviousTime,
  50. IN PLARGE_INTEGER pliFreq
  51. )
  52. /*++
  53. Routine Description:
  54. Get the difference between the current and previous time counts,
  55. then divide by the frequency.
  56. Arguments:
  57. IN pCurrentTime
  58. IN pPreviousTime
  59. used to compute the duration of this sample (the time between
  60. samples
  61. IN pliFreq
  62. # of counts (clock ticks) per second
  63. Return Value:
  64. Floating point representation of Time Interval (seconds)
  65. --*/
  66. {
  67. FLOAT eTimeDifference;
  68. FLOAT eFreq;
  69. FLOAT eTimeInterval ;
  70. LARGE_INTEGER liDifference;
  71. // Get the number of counts that have occured since the last sample
  72. liDifference.QuadPart = pliCurrentTime->QuadPart -
  73. pliPreviousTime->QuadPart;
  74. if (liDifference.QuadPart <= 0) {
  75. return (FLOAT) 0.0f;
  76. } else {
  77. eTimeDifference = eLIntToFloat(&liDifference);
  78. // Get the counts per second
  79. eFreq = eLIntToFloat(pliFreq) ;
  80. if (eFreq <= 0.0f)
  81. return (FLOAT) 0.0f;
  82. // Get the time since the last sample.
  83. eTimeInterval = eTimeDifference / eFreq ;
  84. return (eTimeInterval) ;
  85. }
  86. } // eGetTimeInterval
  87. FLOAT
  88. Counter_Counter_Common(
  89. IN PLINESTRUCT pLineStruct,
  90. IN INT iType
  91. )
  92. /*++
  93. Routine Description:
  94. Take the difference between the current and previous counts
  95. then divide by the time interval
  96. Arguments:
  97. IN pLineStruct
  98. Line structure containing data to perform computations on
  99. IN iType
  100. Counter Type
  101. Return Value:
  102. Floating point representation of outcome
  103. --*/
  104. {
  105. FLOAT eTimeInterval;
  106. FLOAT eDifference;
  107. FLOAT eCount ;
  108. BOOL bValueDrop = FALSE ;
  109. LARGE_INTEGER liDifference;
  110. if (iType != BULK) {
  111. pLineStruct->lnaCounterValue[0].HighPart = 0;
  112. }
  113. liDifference.QuadPart = pLineStruct->lnaCounterValue[0].QuadPart -
  114. pLineStruct->lnaOldCounterValue[0].QuadPart;
  115. if (liDifference.QuadPart <= 0) {
  116. if (bReportEvents && (liDifference.QuadPart < 0)) {
  117. wMessageIndex = 0;
  118. dwMessageDataBytes = 0;
  119. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  120. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  121. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  122. if (pLineStruct->lnInstanceName != NULL){
  123. if (pLineStruct->lnPINName != NULL) {
  124. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  125. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  126. } else {
  127. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  128. szMessageArray[wMessageIndex++] = cszSpace;
  129. }
  130. } else {
  131. szMessageArray[wMessageIndex++] = cszSpace;
  132. szMessageArray[wMessageIndex++] = cszSpace;
  133. }
  134. if (iType != BULK) {
  135. dwMessageData[dwMessageDataBytes++] = // recent data
  136. pLineStruct->lnaCounterValue[0].LowPart;
  137. dwMessageData[dwMessageDataBytes++] = // previous data
  138. pLineStruct->lnaOldCounterValue[0].LowPart;
  139. } else { // 8 byte counter values
  140. dwMessageData[dwMessageDataBytes++] = // recent data
  141. pLineStruct->lnaCounterValue[0].LowPart;
  142. dwMessageData[dwMessageDataBytes++] = // recent data
  143. pLineStruct->lnaCounterValue[0].HighPart;
  144. dwMessageData[dwMessageDataBytes++] = // previous data
  145. pLineStruct->lnaOldCounterValue[0].LowPart;
  146. dwMessageData[dwMessageDataBytes++] = // previous data
  147. pLineStruct->lnaOldCounterValue[0].HighPart;
  148. }
  149. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  150. ReportEvent (hEventLog,
  151. EVENTLOG_WARNING_TYPE, // error type
  152. 0, // category (not used)
  153. (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event,
  154. NULL, // SID (not used),
  155. wMessageIndex, // number of strings
  156. dwMessageDataBytes, // sizeof raw data
  157. szMessageArray, // message text array
  158. (LPVOID)&dwMessageData[0]); // raw data
  159. }
  160. return (FLOAT) 0.0f;
  161. } else {
  162. eTimeInterval = eGetTimeInterval(&pLineStruct->lnNewTime,
  163. &pLineStruct->lnOldTime,
  164. &pLineStruct->lnPerfFreq) ;
  165. if (eTimeInterval <= 0.0f) {
  166. if ((eTimeInterval < 0.0f) && bReportEvents) {
  167. wMessageIndex = 0;
  168. dwMessageDataBytes = 0;
  169. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  170. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  171. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  172. if (pLineStruct->lnInstanceName != NULL){
  173. if (pLineStruct->lnPINName != NULL) {
  174. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  175. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  176. } else {
  177. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  178. szMessageArray[wMessageIndex++] = cszSpace;
  179. }
  180. } else {
  181. szMessageArray[wMessageIndex++] = cszSpace;
  182. szMessageArray[wMessageIndex++] = cszSpace;
  183. }
  184. dwMessageData[dwMessageDataBytes++] = // recent data
  185. pLineStruct->lnNewTime.LowPart;
  186. dwMessageData[dwMessageDataBytes++] = // recent data
  187. pLineStruct->lnNewTime.HighPart;
  188. dwMessageData[dwMessageDataBytes++] = // previous data
  189. pLineStruct->lnOldTime.LowPart;
  190. dwMessageData[dwMessageDataBytes++] = // previous data
  191. pLineStruct->lnOldTime.HighPart;
  192. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  193. ReportEvent (hEventLog,
  194. EVENTLOG_ERROR_TYPE, // error type
  195. 0, // category (not used)
  196. (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event,
  197. NULL, // SID (not used),
  198. wMessageIndex, // number of strings
  199. dwMessageDataBytes, // sizeof raw data
  200. szMessageArray, // message text array
  201. (LPVOID)&dwMessageData[0]); // raw data
  202. return (FLOAT) 0.0f;
  203. }
  204. } else {
  205. eDifference = eLIntToFloat (&liDifference);
  206. eCount = eDifference / eTimeInterval ;
  207. if (bValueDrop && (eCount > ((FLOAT)TOO_BIG))) {
  208. // ignore this bogus data since it is too big for
  209. // the wrap-around case
  210. wMessageIndex = 0;
  211. dwMessageDataBytes = 0;
  212. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  213. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  214. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  215. if (pLineStruct->lnInstanceName != NULL){
  216. if (pLineStruct->lnPINName != NULL) {
  217. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  218. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  219. } else {
  220. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  221. szMessageArray[wMessageIndex++] = cszSpace;
  222. }
  223. } else {
  224. szMessageArray[wMessageIndex++] = cszSpace;
  225. szMessageArray[wMessageIndex++] = cszSpace;
  226. }
  227. dwMessageData[dwMessageDataBytes++] = // recent data
  228. liDifference.LowPart;
  229. dwMessageData[dwMessageDataBytes++] = // recent data
  230. liDifference.HighPart;
  231. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  232. ReportEvent (hEventLog,
  233. EVENTLOG_WARNING_TYPE, // error type
  234. 0, // category (not used)
  235. (DWORD)PERFMON_ERROR_VALUE_OUT_OF_BOUNDS, // event
  236. NULL, // SID (not used),
  237. wMessageIndex, // number of strings
  238. dwMessageDataBytes, // sizeof raw data
  239. szMessageArray, // message text array
  240. (LPVOID)&dwMessageData[0]); // raw data
  241. eCount = (FLOAT) 0.0f ;
  242. }
  243. return(eCount) ;
  244. }
  245. }
  246. return (FLOAT) 0.0f;
  247. } // Counter_Counter_Common
  248. FLOAT
  249. Counter_Average_Timer(
  250. IN PLINESTRUCT pLineStruct
  251. )
  252. /*++
  253. Routine Description:
  254. Take the differences between the current and previous times and counts
  255. divide the time interval by the counts multiply by 10,000,000 (convert
  256. from 100 nsec to sec)
  257. Arguments:
  258. IN pLineStruct
  259. Line structure containing data to perform computations on
  260. Return Value:
  261. Floating point representation of outcome
  262. --*/
  263. {
  264. FLOAT eTimeInterval;
  265. FLOAT eCount;
  266. LARGE_INTEGER liDifference;
  267. // Get the current and previous counts.
  268. pLineStruct->lnaCounterValue[1].HighPart = 0;
  269. liDifference.QuadPart = pLineStruct->lnaCounterValue[1].QuadPart -
  270. pLineStruct->lnaOldCounterValue[1].QuadPart;
  271. if ( liDifference.QuadPart <= 0) {
  272. if ((liDifference.QuadPart < 0) && bReportEvents) {
  273. wMessageIndex = 0;
  274. dwMessageDataBytes = 0;
  275. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  276. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  277. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  278. if (pLineStruct->lnInstanceName != NULL){
  279. if (pLineStruct->lnPINName != NULL) {
  280. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  281. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  282. } else {
  283. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  284. szMessageArray[wMessageIndex++] = cszSpace;
  285. }
  286. } else {
  287. szMessageArray[wMessageIndex++] = cszSpace;
  288. szMessageArray[wMessageIndex++] = cszSpace;
  289. }
  290. dwMessageData[dwMessageDataBytes++] = // recent data
  291. pLineStruct->lnaCounterValue[1].LowPart;
  292. dwMessageData[dwMessageDataBytes++] = // previous data
  293. pLineStruct->lnaOldCounterValue[1].LowPart;
  294. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  295. ReportEvent (hEventLog,
  296. EVENTLOG_WARNING_TYPE, // error type
  297. 0, // category (not used)
  298. (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event,
  299. NULL, // SID (not used),
  300. wMessageIndex, // number of strings
  301. dwMessageDataBytes, // sizeof raw data
  302. szMessageArray, // message text array
  303. (LPVOID)&dwMessageData[0]); // raw data
  304. }
  305. return (FLOAT) 0.0f;
  306. } else {
  307. // Get the amount of time that has passed since the last sample
  308. eTimeInterval = eGetTimeInterval(&pLineStruct->lnaCounterValue[0],
  309. &pLineStruct->lnaOldCounterValue[0],
  310. &pLineStruct->lnPerfFreq) ;
  311. if (eTimeInterval <= 0.0f) { // return 0 if negative time has passed
  312. if ((eTimeInterval < 0.0f) & bReportEvents) {
  313. wMessageIndex = 0;
  314. dwMessageDataBytes = 0;
  315. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  316. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  317. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  318. if (pLineStruct->lnInstanceName != NULL){
  319. if (pLineStruct->lnPINName != NULL) {
  320. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  321. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  322. } else {
  323. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  324. szMessageArray[wMessageIndex++] = cszSpace;
  325. }
  326. } else {
  327. szMessageArray[wMessageIndex++] = cszSpace;
  328. szMessageArray[wMessageIndex++] = cszSpace;
  329. }
  330. dwMessageData[dwMessageDataBytes++] = // recent data
  331. pLineStruct->lnaCounterValue[0].LowPart;
  332. dwMessageData[dwMessageDataBytes++] = // recent data
  333. pLineStruct->lnaCounterValue[0].HighPart;
  334. dwMessageData[dwMessageDataBytes++] = // previous data
  335. pLineStruct->lnaOldCounterValue[0].LowPart;
  336. dwMessageData[dwMessageDataBytes++] = // previous data
  337. pLineStruct->lnaOldCounterValue[0].HighPart;
  338. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  339. ReportEvent (hEventLog,
  340. EVENTLOG_ERROR_TYPE, // error type
  341. 0, // category (not used)
  342. (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event,
  343. NULL, // SID (not used),
  344. wMessageIndex, // number of strings
  345. dwMessageDataBytes, // sizeof raw data
  346. szMessageArray, // message text array
  347. (LPVOID)&dwMessageData[0]); // raw data
  348. }
  349. return (0.0f);
  350. } else {
  351. // Get the number of counts in this time interval.
  352. eCount = eTimeInterval / eLIntToFloat (&liDifference);
  353. return(eCount) ;
  354. }
  355. }
  356. } //Counter_Average_Timer
  357. FLOAT
  358. Counter_Average_Bulk(
  359. IN PLINESTRUCT pLineStruct
  360. )
  361. /*++
  362. Routine Description:
  363. Take the differences between the current and previous byte counts and
  364. operation counts divide the bulk count by the operation counts
  365. Arguments:
  366. IN pLineStruct
  367. Line structure containing data to perform computations on
  368. Return Value:
  369. Floating point representation of outcome
  370. --*/
  371. {
  372. FLOAT eBulkDelta;
  373. FLOAT eDifference;
  374. FLOAT eCount;
  375. LARGE_INTEGER liDifference;
  376. LARGE_INTEGER liBulkDelta;
  377. // Get the bulk count increment since the last sample
  378. liBulkDelta.QuadPart = pLineStruct->lnaCounterValue[0].QuadPart -
  379. pLineStruct->lnaOldCounterValue[0].QuadPart;
  380. if (liBulkDelta.QuadPart <= 0) {
  381. if ((liBulkDelta.QuadPart < 0) && bReportEvents) {
  382. wMessageIndex = 0;
  383. dwMessageDataBytes = 0;
  384. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  385. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  386. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  387. if (pLineStruct->lnInstanceName != NULL){
  388. if (pLineStruct->lnPINName != NULL) {
  389. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  390. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  391. } else {
  392. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  393. szMessageArray[wMessageIndex++] = cszSpace;
  394. }
  395. } else {
  396. szMessageArray[wMessageIndex++] = cszSpace;
  397. szMessageArray[wMessageIndex++] = cszSpace;
  398. }
  399. dwMessageData[dwMessageDataBytes++] = // recent data
  400. pLineStruct->lnaCounterValue[0].LowPart;
  401. dwMessageData[dwMessageDataBytes++] = // recent data
  402. pLineStruct->lnaCounterValue[0].HighPart;
  403. dwMessageData[dwMessageDataBytes++] = // previous data
  404. pLineStruct->lnaOldCounterValue[0].LowPart;
  405. dwMessageData[dwMessageDataBytes++] = // previous data
  406. pLineStruct->lnaOldCounterValue[0].HighPart;
  407. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  408. ReportEvent (hEventLog,
  409. EVENTLOG_WARNING_TYPE, // error type
  410. 0, // category (not used)
  411. (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event,
  412. NULL, // SID (not used),
  413. wMessageIndex, // number of strings
  414. dwMessageDataBytes, // sizeof raw data
  415. szMessageArray, // message text array
  416. (LPVOID)&dwMessageData[0]); // raw data
  417. }
  418. return (FLOAT) 0.0f;
  419. } else {
  420. // Get the current and previous counts.
  421. pLineStruct->lnaCounterValue[1].HighPart = 0;
  422. liDifference.QuadPart = pLineStruct->lnaCounterValue[1].QuadPart -
  423. pLineStruct->lnaOldCounterValue[1].QuadPart;
  424. // Get the number of counts in this time interval.
  425. if ( liDifference.QuadPart <= 0) {
  426. if ((liDifference.QuadPart < 0) && bReportEvents) {
  427. // Counter value invalid
  428. wMessageIndex = 0;
  429. dwMessageDataBytes = 0;
  430. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  431. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  432. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  433. if (pLineStruct->lnInstanceName != NULL){
  434. if (pLineStruct->lnPINName != NULL) {
  435. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  436. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  437. } else {
  438. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  439. szMessageArray[wMessageIndex++] = cszSpace;
  440. }
  441. } else {
  442. szMessageArray[wMessageIndex++] = cszSpace;
  443. szMessageArray[wMessageIndex++] = cszSpace;
  444. }
  445. dwMessageData[dwMessageDataBytes++] = // recent data
  446. pLineStruct->lnaCounterValue[1].LowPart;
  447. dwMessageData[dwMessageDataBytes++] = // recent data
  448. pLineStruct->lnaCounterValue[1].HighPart;
  449. dwMessageData[dwMessageDataBytes++] = // previous data
  450. pLineStruct->lnaOldCounterValue[1].LowPart;
  451. dwMessageData[dwMessageDataBytes++] = // previous data
  452. pLineStruct->lnaOldCounterValue[1].HighPart;
  453. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  454. ReportEvent (hEventLog,
  455. EVENTLOG_WARNING_TYPE, // error type
  456. 0, // category (not used)
  457. (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event,
  458. NULL, // SID (not used),
  459. wMessageIndex, // number of strings
  460. dwMessageDataBytes, // sizeof raw data
  461. szMessageArray, // message text array
  462. (LPVOID)&dwMessageData[0]); // raw data
  463. }
  464. return (FLOAT) 0.0f;
  465. } else {
  466. eBulkDelta = eLIntToFloat (&liBulkDelta);
  467. eDifference = eLIntToFloat (&liDifference);
  468. eCount = eBulkDelta / eDifference ;
  469. // Scale the value to up to 1 second
  470. return(eCount) ;
  471. }
  472. }
  473. } // Counter_Average_Bulk
  474. FLOAT
  475. Counter_Timer_Common(
  476. IN PLINESTRUCT pLineStruct,
  477. IN INT iType
  478. )
  479. /*++
  480. Routine Description:
  481. Take the difference between the current and previous counts,
  482. Normalize the count (counts per interval)
  483. divide by the time interval (count = % of interval)
  484. if (invert)
  485. subtract from 1 (the normalized size of an interval)
  486. multiply by 100 (convert to a percentage)
  487. this value from 100.
  488. Arguments:
  489. IN pLineStruct
  490. Line structure containing data to perform computations on
  491. IN iType
  492. Counter Type
  493. Return Value:
  494. Floating point representation of outcome
  495. --*/
  496. {
  497. FLOAT eTimeInterval;
  498. FLOAT eDifference;
  499. FLOAT eFreq;
  500. FLOAT eFraction;
  501. FLOAT eMultiBase;
  502. FLOAT eCount ;
  503. LARGE_INTEGER liTimeInterval;
  504. LARGE_INTEGER liDifference;
  505. LARGE_INTEGER liFreq;
  506. // test to see if the previous sample was 0, if so, return 0 since
  507. // the difference between a "valid" value and 0 will likely exceed
  508. // 100%. It's better to keep the value at 0 until a valid one can
  509. // be displayed, rather than display a 100% spike, then a valid value.
  510. if (pLineStruct->lnaOldCounterValue[0].QuadPart == 0) {
  511. return (FLOAT)0.0f;
  512. }
  513. // Get the amount of time that has passed since the last sample
  514. if (iType == NS100 ||
  515. iType == NS100_INVERT ||
  516. iType == NS100_MULTI ||
  517. iType == NS100_MULTI_INVERT) {
  518. liTimeInterval.QuadPart = pLineStruct->lnNewTime100Ns.QuadPart -
  519. pLineStruct->lnOldTime100Ns.QuadPart;
  520. eTimeInterval = eLIntToFloat (&liTimeInterval);
  521. } else {
  522. liTimeInterval.QuadPart = pLineStruct->lnNewTime.QuadPart -
  523. pLineStruct->lnOldTime.QuadPart;
  524. eTimeInterval = eGetTimeInterval(&pLineStruct->lnNewTime,
  525. &pLineStruct->lnOldTime,
  526. &pLineStruct->lnPerfFreq) ;
  527. }
  528. if (liTimeInterval.QuadPart <= 0) {
  529. if ((liTimeInterval.QuadPart < 0) && bReportEvents) {
  530. wMessageIndex = 0;
  531. dwMessageDataBytes = 0;
  532. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  533. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  534. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  535. if (pLineStruct->lnInstanceName != NULL){
  536. if (pLineStruct->lnPINName != NULL) {
  537. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  538. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  539. } else {
  540. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  541. szMessageArray[wMessageIndex++] = cszSpace;
  542. }
  543. } else {
  544. szMessageArray[wMessageIndex++] = cszSpace;
  545. szMessageArray[wMessageIndex++] = cszSpace;
  546. }
  547. dwMessageData[dwMessageDataBytes++] = // recent data
  548. pLineStruct->lnNewTime.LowPart;
  549. dwMessageData[dwMessageDataBytes++] = // recent data
  550. pLineStruct->lnNewTime.HighPart;
  551. dwMessageData[dwMessageDataBytes++] = // previous data
  552. pLineStruct->lnOldTime.LowPart;
  553. dwMessageData[dwMessageDataBytes++] = // previous data
  554. pLineStruct->lnOldTime.HighPart;
  555. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  556. ReportEvent (hEventLog,
  557. EVENTLOG_ERROR_TYPE, // error type
  558. 0, // category (not used)
  559. (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event,
  560. NULL, // SID (not used),
  561. wMessageIndex, // number of strings
  562. dwMessageDataBytes, // sizeof raw data
  563. szMessageArray, // message text array
  564. (LPVOID)&dwMessageData[0]); // raw data
  565. }
  566. return (FLOAT) 0.0f;
  567. }
  568. // Get the current and previous counts.
  569. liDifference.QuadPart = pLineStruct->lnaCounterValue[0].QuadPart -
  570. pLineStruct->lnaOldCounterValue[0].QuadPart;
  571. // Get the number of counts in this time interval.
  572. // (1, 2, 3 or any number of seconds could have gone by since
  573. // the last sample)
  574. eDifference = eLIntToFloat (&liDifference) ;
  575. if (iType == 0 || iType == INVERT)
  576. {
  577. // Get the counts per interval (second)
  578. liFreq.QuadPart = pLineStruct->lnPerfFreq.QuadPart;
  579. if ((liFreq.QuadPart <= 0) && bReportEvents) {
  580. wMessageIndex = 0;
  581. dwMessageDataBytes = 0;
  582. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  583. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  584. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  585. if (pLineStruct->lnInstanceName != NULL){
  586. if (pLineStruct->lnPINName != NULL) {
  587. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  588. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  589. } else {
  590. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  591. szMessageArray[wMessageIndex++] = cszSpace;
  592. }
  593. } else {
  594. szMessageArray[wMessageIndex++] = cszSpace;
  595. szMessageArray[wMessageIndex++] = cszSpace;
  596. }
  597. dwMessageData[dwMessageDataBytes++] = liFreq.LowPart;
  598. dwMessageData[dwMessageDataBytes++] = liFreq.HighPart;
  599. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  600. ReportEvent (hEventLog,
  601. EVENTLOG_ERROR_TYPE, // error type
  602. 0, // category (not used)
  603. (DWORD)PERFMON_ERROR_BAD_FREQUENCY, // event,
  604. NULL, // SID (not used),
  605. wMessageIndex, // number of strings
  606. dwMessageDataBytes, // sizeof raw data
  607. szMessageArray, // message text array
  608. (LPVOID)&dwMessageData[0]); // raw data
  609. return (FLOAT) 0.0f;
  610. } else {
  611. eFreq = eLIntToFloat(&pLineStruct->lnPerfFreq) ;
  612. }
  613. // Calculate the fraction of the counts that are used by whatever
  614. // we are measuring to convert to units per second
  615. eFraction = eDifference / eFreq ;
  616. }
  617. else
  618. {
  619. // for 100 NS counters, the frequency is not included since it
  620. // would cancel out since both numerator & denominator are returned
  621. // in 100 NS units. Non "100 NS" counter types are normalized to
  622. // seconds.
  623. eFraction = eDifference ;
  624. liFreq.QuadPart = 10000000;
  625. }
  626. // Calculate the fraction of time used by what were measuring.
  627. if (eTimeInterval > 0.0)
  628. eCount = eFraction / eTimeInterval ;
  629. else
  630. eCount = 0.0;
  631. // If this is an inverted count take care of the inversion.
  632. if (iType == INVERT || iType == NS100_INVERT)
  633. eCount = (FLOAT) 1.0 - eCount ;
  634. if (eCount <= (FLOAT)0.0f) {
  635. // the threshold for reporting an error is -.1 since some timers
  636. // have a small margin of error that should never exceed this value
  637. // but can fall below 0 at times. Typically this error is no more
  638. // than -0.01
  639. if ((eCount < (FLOAT)-0.1f) && bReportEvents) {
  640. wMessageIndex = 0;
  641. dwMessageDataBytes = 0;
  642. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  643. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  644. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  645. if (pLineStruct->lnInstanceName != NULL){
  646. if (pLineStruct->lnPINName != NULL) {
  647. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  648. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  649. } else {
  650. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  651. szMessageArray[wMessageIndex++] = cszSpace;
  652. }
  653. } else {
  654. szMessageArray[wMessageIndex++] = cszSpace;
  655. szMessageArray[wMessageIndex++] = cszSpace;
  656. }
  657. dwMessageData[dwMessageDataBytes++] = // recent data
  658. pLineStruct->lnaCounterValue[0].LowPart;
  659. dwMessageData[dwMessageDataBytes++] = // recent data
  660. pLineStruct->lnaCounterValue[0].HighPart;
  661. dwMessageData[dwMessageDataBytes++] = // previous data
  662. pLineStruct->lnaOldCounterValue[0].LowPart;
  663. dwMessageData[dwMessageDataBytes++] = // previous data
  664. pLineStruct->lnaOldCounterValue[0].HighPart;
  665. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  666. ReportEvent (hEventLog,
  667. EVENTLOG_WARNING_TYPE, // error type
  668. 0, // category (not used)
  669. (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event,
  670. NULL, // SID (not used),
  671. wMessageIndex, // number of strings
  672. dwMessageDataBytes, // sizeof raw data
  673. szMessageArray, // message text array
  674. (LPVOID)&dwMessageData[0]); // raw data
  675. }
  676. // don't just return here, since 0 is possibly a valid value
  677. eCount = (FLOAT)0.0f;
  678. }
  679. // If this is a multi count take care of the base
  680. if (iType == TIMER_MULTI || iType == NS100_MULTI ||
  681. iType == TIMER_MULTI_INVERT || iType == NS100_MULTI_INVERT) {
  682. if (pLineStruct->lnaCounterValue[1].LowPart <= 0) {
  683. #if 0
  684. if ((pLineStruct->lnaCounterValue[1].LowPart < 0) &&
  685. bReportEvents) {
  686. wMessageIndex = 0;
  687. dwMessageDataBytes = 0;
  688. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  689. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  690. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  691. if (pLineStruct->lnInstanceName != NULL){
  692. if (pLineStruct->lnPINName != NULL) {
  693. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  694. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  695. } else {
  696. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  697. szMessageArray[wMessageIndex++] = cszSpace;
  698. }
  699. } else {
  700. szMessageArray[wMessageIndex++] = cszSpace;
  701. szMessageArray[wMessageIndex++] = cszSpace;
  702. }
  703. dwMessageData[dwMessageDataBytes++] = // recent data
  704. pLineStruct->lnaCounterValue[1].LowPart;
  705. dwMessageDataBytes *= sizeof (DWORD);
  706. ReportEvent (hEventLog,
  707. EVENTLOG_ERROR_TYPE, // error type
  708. 0, // category (not used)
  709. (DWORD)PERFMON_ERROR_INVALID_BASE, // event,
  710. NULL, // SID (not used),
  711. wMessageIndex, // number of strings
  712. dwMessageDataBytes, // sizeof raw data
  713. szMessageArray, // message text array
  714. (LPVOID)&dwMessageData[0]); // raw data
  715. }
  716. #endif
  717. return (FLOAT) 0.0f;
  718. } else {
  719. eMultiBase = (FLOAT)pLineStruct->lnaCounterValue[1].LowPart ;
  720. }
  721. // If this is an inverted multi count take care of the inversion.
  722. if (iType == TIMER_MULTI_INVERT || iType == NS100_MULTI_INVERT) {
  723. eCount = (FLOAT) eMultiBase - eCount ;
  724. }
  725. eCount /= eMultiBase;
  726. }
  727. // Scale the value to up to 100.
  728. eCount *= 100.0f ;
  729. if (((eCount > 100.0f) && (bCapPercentsAt100)) &&
  730. iType != NS100_MULTI &&
  731. iType != NS100_MULTI_INVERT &&
  732. iType != TIMER_MULTI &&
  733. iType != TIMER_MULTI_INVERT) {
  734. if (bReportEvents) {
  735. wMessageIndex = 0;
  736. dwMessageDataBytes = 0;
  737. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  738. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  739. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  740. if (pLineStruct->lnInstanceName != NULL){
  741. if (pLineStruct->lnPINName != NULL) {
  742. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  743. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  744. } else {
  745. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  746. szMessageArray[wMessageIndex++] = cszSpace;
  747. }
  748. } else {
  749. szMessageArray[wMessageIndex++] = cszSpace;
  750. szMessageArray[wMessageIndex++] = cszSpace;
  751. }
  752. dwMessageData[dwMessageDataBytes++] =
  753. pLineStruct->lnaCounterValue[0].LowPart;
  754. dwMessageData[dwMessageDataBytes++] =
  755. pLineStruct->lnaCounterValue[0].HighPart;
  756. dwMessageData[dwMessageDataBytes++] =
  757. pLineStruct->lnaOldCounterValue[0].LowPart;
  758. dwMessageData[dwMessageDataBytes++] =
  759. pLineStruct->lnaOldCounterValue[0].HighPart;
  760. dwMessageData[dwMessageDataBytes++] = liTimeInterval.LowPart;
  761. dwMessageData[dwMessageDataBytes++] = liTimeInterval.HighPart;
  762. dwMessageData[dwMessageDataBytes++] = liFreq.LowPart;
  763. dwMessageData[dwMessageDataBytes++] = liFreq.HighPart;
  764. dwMessageDataBytes *= sizeof(DWORD);
  765. ReportEvent (hEventLog,
  766. EVENTLOG_WARNING_TYPE, // error type
  767. 0, // category (not used)
  768. (DWORD)PERFMON_ERROR_VALUE_OUT_OF_RANGE, // event,
  769. NULL, // SID (not used),
  770. wMessageIndex, // number of strings
  771. dwMessageDataBytes, // sizeof raw data
  772. szMessageArray, // message text array
  773. (LPVOID)&dwMessageData[0]); // raw data
  774. }
  775. eCount = 100.0f; // limit value to 100.0%
  776. }
  777. return(eCount) ;
  778. } // Counter_Timer_Common
  779. FLOAT
  780. Counter_Raw_Fraction(
  781. IN PLINESTRUCT pLineStruct,
  782. IN BOOL bLargeValue
  783. )
  784. /*++
  785. Routine Description:
  786. Evaluate a raw fraction (no time, just two values: Numerator and
  787. Denominator) and multiply by 100 (to make a percentage;
  788. Arguments:
  789. IN pLineStruct
  790. Line structure containing data to perform computations on
  791. Return Value:
  792. Floating point representation of outcome
  793. --*/
  794. {
  795. FLOAT eCount ;
  796. LARGE_INTEGER liNumerator;
  797. if (pLineStruct->lnaCounterValue[0].LowPart == 0) {
  798. // numerator is 0 so just bail here
  799. return (FLOAT)0.0f;
  800. } else {
  801. if (!bLargeValue) {
  802. liNumerator.QuadPart =
  803. pLineStruct->lnaCounterValue[0].LowPart * 100L;
  804. } else {
  805. liNumerator.QuadPart =
  806. pLineStruct->lnaCounterValue[0].QuadPart * 100L;
  807. }
  808. }
  809. // now test and compute base (denominator)
  810. if (pLineStruct->lnaCounterValue[1].QuadPart == 0 ) {
  811. // invalid value for denominator
  812. if (bReportEvents) {
  813. wMessageIndex = 0;
  814. dwMessageDataBytes = 0;
  815. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  816. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  817. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  818. if (pLineStruct->lnInstanceName != NULL){
  819. if (pLineStruct->lnPINName != NULL) {
  820. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  821. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  822. } else {
  823. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  824. szMessageArray[wMessageIndex++] = cszSpace;
  825. }
  826. } else {
  827. szMessageArray[wMessageIndex++] = cszSpace;
  828. szMessageArray[wMessageIndex++] = cszSpace;
  829. }
  830. dwMessageData[dwMessageDataBytes++] = // recent data
  831. pLineStruct->lnaCounterValue[0].LowPart;
  832. dwMessageData[dwMessageDataBytes++] = // recent data
  833. pLineStruct->lnaCounterValue[1].LowPart;
  834. dwMessageDataBytes *= sizeof (DWORD);
  835. ReportEvent (hEventLog,
  836. EVENTLOG_ERROR_TYPE, // error type
  837. 0, // category (not used)
  838. (DWORD)PERFMON_ERROR_INVALID_BASE, // event,
  839. NULL, // SID (not used),
  840. wMessageIndex, // number of strings
  841. dwMessageDataBytes, // sizeof raw data
  842. szMessageArray, // message text array
  843. (LPVOID)&dwMessageData[0]); // raw data
  844. }
  845. return (0.0f);
  846. } else {
  847. // if base is OK, then get fraction
  848. eCount = eLIntToFloat(&liNumerator) /
  849. (FLOAT) pLineStruct->lnaCounterValue[1].QuadPart;
  850. return(eCount) ;
  851. }
  852. } // Counter_Raw_Fraction
  853. FLOAT
  854. eElapsedTime(
  855. PLINESTRUCT pLineStruct,
  856. INT iType
  857. )
  858. /*++
  859. Routine Description:
  860. Converts 100NS elapsed time to fractional seconds
  861. Arguments:
  862. IN pLineStruct
  863. Line structure containing data to perform computations on
  864. IN iType
  865. Unused.
  866. Return Value:
  867. Floating point representation of elapsed time in seconds
  868. --*/
  869. {
  870. FLOAT eSeconds ;
  871. LARGE_INTEGER liDifference;
  872. if (pLineStruct->lnaCounterValue[0].QuadPart <= 0) {
  873. // no data [start time = 0] so return 0
  874. // this really doesn't warrant an error message
  875. return (FLOAT) 0.0f;
  876. } else {
  877. // otherwise compute difference between current time and start time
  878. liDifference.QuadPart =
  879. pLineStruct->lnNewTime.QuadPart - // sample time in obj. units
  880. pLineStruct->lnaCounterValue[0].QuadPart; // start time in obj. units
  881. if ((liDifference.QuadPart <= 0) ||
  882. (pLineStruct->lnObject.PerfFreq.QuadPart <= 0)) {
  883. if ((bReportEvents) && ((liDifference.QuadPart < 0) ||
  884. (pLineStruct->lnObject.PerfFreq.QuadPart < 0))) {
  885. wMessageIndex = 0;
  886. dwMessageDataBytes = 0;
  887. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  888. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  889. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  890. if (pLineStruct->lnInstanceName != NULL){
  891. if (pLineStruct->lnPINName != NULL) {
  892. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  893. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  894. } else {
  895. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  896. szMessageArray[wMessageIndex++] = cszSpace;
  897. }
  898. } else {
  899. szMessageArray[wMessageIndex++] = cszSpace;
  900. szMessageArray[wMessageIndex++] = cszSpace;
  901. }
  902. if (liDifference.QuadPart < 0) {
  903. dwMessageData[dwMessageDataBytes++] =
  904. pLineStruct->lnNewTime.LowPart;
  905. dwMessageData[dwMessageDataBytes++] =
  906. pLineStruct->lnNewTime.HighPart;
  907. dwMessageData[dwMessageDataBytes++] =
  908. pLineStruct->lnaCounterValue[0].LowPart;
  909. dwMessageData[dwMessageDataBytes++] =
  910. pLineStruct->lnaCounterValue[0].HighPart;
  911. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  912. ReportEvent (hEventLog,
  913. EVENTLOG_ERROR_TYPE, // error type
  914. 0, // category (not used)
  915. (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event,
  916. NULL, // SID (not used),
  917. wMessageIndex, // number of strings
  918. dwMessageDataBytes, // sizeof raw data
  919. szMessageArray, // message text array
  920. (LPVOID)&dwMessageData[0]); // raw data
  921. } else {
  922. dwMessageData[dwMessageDataBytes++] =
  923. pLineStruct->lnObject.PerfFreq.LowPart;
  924. dwMessageData[dwMessageDataBytes++] =
  925. pLineStruct->lnObject.PerfFreq.HighPart;
  926. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  927. ReportEvent (hEventLog,
  928. EVENTLOG_ERROR_TYPE, // error type
  929. 0, // category (not used)
  930. (DWORD)PERFMON_ERROR_BAD_FREQUENCY, // event,
  931. NULL, // SID (not used),
  932. wMessageIndex, // number of strings
  933. dwMessageDataBytes, // sizeof raw data
  934. szMessageArray, // message text array
  935. (LPVOID)&dwMessageData[0]); // raw data
  936. }
  937. }
  938. return (FLOAT) 0.0f;
  939. } else {
  940. // convert to fractional seconds using object counter
  941. eSeconds = eLIntToFloat (&liDifference);
  942. eSeconds /= eLIntToFloat (&pLineStruct->lnObject.PerfFreq);
  943. return (eSeconds);
  944. }
  945. }
  946. } // eElapsedTime
  947. FLOAT
  948. Sample_Common(
  949. PLINESTRUCT pLineStruct,
  950. INT iType
  951. )
  952. /*++
  953. Routine Description:
  954. Divites "Top" differenced by Base Difference
  955. Arguments:
  956. IN pLineStruct
  957. Line structure containing data to perform computations on
  958. IN iType
  959. Counter Type
  960. Return Value:
  961. Floating point representation of outcome
  962. --*/
  963. {
  964. double eCount ;
  965. LONG lDifference;
  966. LONG lBaseDifference;
  967. double dReturn;
  968. lDifference = pLineStruct->lnaCounterValue[0].LowPart -
  969. pLineStruct->lnaOldCounterValue[0].LowPart ;
  970. if (lDifference <= 0) {
  971. if ((lDifference < 0) && bReportEvents) {
  972. wMessageIndex = 0;
  973. dwMessageDataBytes = 0;
  974. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  975. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  976. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  977. if (pLineStruct->lnInstanceName != NULL){
  978. if (pLineStruct->lnPINName != NULL) {
  979. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  980. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  981. } else {
  982. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  983. szMessageArray[wMessageIndex++] = cszSpace;
  984. }
  985. } else {
  986. szMessageArray[wMessageIndex++] = cszSpace;
  987. szMessageArray[wMessageIndex++] = cszSpace;
  988. }
  989. dwMessageData[dwMessageDataBytes++] = // recent data
  990. pLineStruct->lnaCounterValue[0].LowPart;
  991. dwMessageData[dwMessageDataBytes++] = // previous data
  992. pLineStruct->lnaOldCounterValue[0].LowPart;
  993. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  994. ReportEvent (hEventLog,
  995. EVENTLOG_WARNING_TYPE, // error type
  996. 0, // category (not used)
  997. (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event,
  998. NULL, // SID (not used),
  999. wMessageIndex, // number of strings
  1000. dwMessageDataBytes, // sizeof raw data
  1001. szMessageArray, // message text array
  1002. (LPVOID)&dwMessageData[0]); // raw data
  1003. }
  1004. dReturn = (double) 0.0f;
  1005. } else {
  1006. lBaseDifference = pLineStruct->lnaCounterValue[1].LowPart -
  1007. pLineStruct->lnaOldCounterValue[1].LowPart ;
  1008. if ( lBaseDifference <= 0 ) {
  1009. // invalid value
  1010. if ((lBaseDifference < 0 ) && bReportEvents) {
  1011. wMessageIndex = 0;
  1012. dwMessageDataBytes = 0;
  1013. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  1014. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  1015. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  1016. if (pLineStruct->lnInstanceName != NULL){
  1017. if (pLineStruct->lnPINName != NULL) {
  1018. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  1019. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  1020. } else {
  1021. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  1022. szMessageArray[wMessageIndex++] = cszSpace;
  1023. }
  1024. } else {
  1025. szMessageArray[wMessageIndex++] = cszSpace;
  1026. szMessageArray[wMessageIndex++] = cszSpace;
  1027. }
  1028. dwMessageData[dwMessageDataBytes++] = // recent data
  1029. pLineStruct->lnaCounterValue[1].LowPart;
  1030. dwMessageData[dwMessageDataBytes++] = // previous data
  1031. pLineStruct->lnaOldCounterValue[1].LowPart;
  1032. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  1033. ReportEvent (hEventLog,
  1034. EVENTLOG_ERROR_TYPE, // error type
  1035. 0, // category (not used)
  1036. (DWORD)PERFMON_ERROR_INVALID_BASE, // event,
  1037. NULL, // SID (not used),
  1038. wMessageIndex, // number of strings
  1039. dwMessageDataBytes, // sizeof raw data
  1040. szMessageArray, // message text array
  1041. (LPVOID)&dwMessageData[0]); // raw data
  1042. }
  1043. dReturn = (0.0f);
  1044. } else {
  1045. eCount = lDifference / lBaseDifference ;
  1046. if (iType == FRACTION) {
  1047. eCount *= 100.0f ;
  1048. }
  1049. dReturn = eCount;
  1050. }
  1051. }
  1052. return (FLOAT)dReturn;
  1053. } // Sample_Common
  1054. //==========================================================================//
  1055. // Exported Functions //
  1056. //==========================================================================//
  1057. /*****************************************************************************
  1058. * Counter_Counter - Take the difference between the current and previous
  1059. * counts then divide by the time interval
  1060. ****************************************************************************/
  1061. #define Counter_Counter(pLineStruct) \
  1062. Counter_Counter_Common(pLineStruct, 0)
  1063. /*****************************************************************************
  1064. * Counter_Bulk - Take the difference between the current and previous
  1065. * counts then divide by the time interval
  1066. * Same as a Counter_counter except it uses large_ints
  1067. ****************************************************************************/
  1068. #define Counter_Bulk(pLineStruct) \
  1069. Counter_Counter_Common(pLineStruct, BULK)
  1070. /*****************************************************************************
  1071. * Counter_Timer100Ns -
  1072. *
  1073. * Need to review with RussBl exactly what he is doing here.
  1074. ****************************************************************************/
  1075. #define Counter_Timer100Ns(pLineStruct) \
  1076. Counter_Timer_Common(pLineStruct, NS100)
  1077. /*****************************************************************************
  1078. * Counter_Timer100Ns_Inv -
  1079. *
  1080. * Need to review with RussBl exactly what he is doing here.
  1081. ****************************************************************************/
  1082. #define Counter_Timer100Ns_Inv(pLineStruct) \
  1083. Counter_Timer_Common(pLineStruct, NS100_INVERT)
  1084. /*****************************************************************************
  1085. * Counter_Timer_Multi -
  1086. *
  1087. * Need to review with RussBl exactly what he is doing here.
  1088. ****************************************************************************/
  1089. #define Counter_Timer_Multi(pLineStruct) \
  1090. Counter_Timer_Common(pLineStruct, TIMER_MULTI)
  1091. /*****************************************************************************
  1092. * Counter_Timer_Multi_Inv -
  1093. *
  1094. * Need to review with RussBl exactly what he is doing here.
  1095. ****************************************************************************/
  1096. #define Counter_Timer_Multi_Inv(pLineStruct) \
  1097. Counter_Timer_Common(pLineStruct, TIMER_MULTI_INVERT)
  1098. /*****************************************************************************
  1099. * Counter_Timer100Ns_Multi -
  1100. *
  1101. * Need to review with RussBl exactly what he is doing here.
  1102. ****************************************************************************/
  1103. #define Counter_Timer100Ns_Multi(pLineStruct) \
  1104. Counter_Timer_Common(pLineStruct, NS100_MULTI)
  1105. /*****************************************************************************
  1106. * Counter_Timer100Ns_Multi_Inv -
  1107. *
  1108. * Need to review with RussBl exactly what he is doing here.
  1109. ****************************************************************************/
  1110. #define Counter_Timer100Ns_Multi_Inv(pLineStruct) \
  1111. Counter_Timer_Common(pLineStruct, NS100_MULTI_INVERT)
  1112. /*****************************************************************************
  1113. * Counter_Timer - Take the difference between the current and previous
  1114. * counts,
  1115. * Normalize the count (counts per interval)
  1116. * divide by the time interval (count = % of interval)
  1117. * multiply by 100 (convert to a percentage)
  1118. * this value from 100.
  1119. ****************************************************************************/
  1120. #define Counter_Timer(pLineStruct) \
  1121. Counter_Timer_Common(pLineStruct, 0)
  1122. /*****************************************************************************
  1123. * Counter_Timer_Inv - Take the difference between the current and previous
  1124. * counts,
  1125. * Normalize the count (counts per interval)
  1126. * divide by the time interval (count = % of interval)
  1127. * subtract from 1 (the normalized size of an interval)
  1128. * multiply by 100 (convert to a percentage)
  1129. * this value from 100.
  1130. ****************************************************************************/
  1131. #define Counter_Timer_Inv(pLineStruct) \
  1132. Counter_Timer_Common(pLineStruct, INVERT)
  1133. /*****************************************************************************
  1134. * Sample_Counter -
  1135. ****************************************************************************/
  1136. #define Sample_Counter(pLineStruct) \
  1137. Sample_Common(pLineStruct, 0)
  1138. /*****************************************************************************
  1139. * Sample_Fraction -
  1140. ****************************************************************************/
  1141. #define Sample_Fraction(pLineStruct) \
  1142. Sample_Common(pLineStruct, FRACTION)
  1143. /*****************************************************************************
  1144. * Counter_Rawcount - This is just a raw count.
  1145. ****************************************************************************/
  1146. #define Counter_Rawcount(pLineStruct) \
  1147. ((FLOAT) (pLineStruct->lnaCounterValue[0].LowPart))
  1148. /*****************************************************************************
  1149. * Counter_Large_Rawcount - This is just a raw count.
  1150. ****************************************************************************/
  1151. #define Counter_Large_Rawcount(pLineStruct) \
  1152. ((FLOAT) eLIntToFloat(&(pLineStruct->lnaCounterValue[0])))
  1153. /*****************************************************************************
  1154. * Counter_Elapsed_Time -
  1155. ****************************************************************************/
  1156. #define Counter_Elapsed_Time(pLineStruct) \
  1157. eElapsedTime (pLineStruct, 0)
  1158. #define CQLFLAGS_LARGE ((DWORD)0x00000001)
  1159. #define CQLFLAGS_100NS ((DWORD)0x00000002)
  1160. FLOAT Counter_Queuelen(PLINESTRUCT pLineStruct, DWORD dwFlags)
  1161. /*++
  1162. Routine Description:
  1163. Take the difference between the current and previous counts,
  1164. divide by the time interval (count = decimal fraction of interval)
  1165. Value can exceed 1.00.
  1166. Arguments:
  1167. IN pLineStruct
  1168. Line structure containing data to perform computations on
  1169. IN iType
  1170. Counter Type
  1171. Return Value:
  1172. Floating point representation of outcome
  1173. --*/
  1174. {
  1175. FLOAT eTimeDiff;
  1176. FLOAT eDifference;
  1177. FLOAT eCount;
  1178. LONGLONG llDifference;
  1179. LONGLONG llTimeDiff;
  1180. // Get the amount of time that has passed since the last sample
  1181. if (dwFlags & CQLFLAGS_100NS) {
  1182. llTimeDiff = pLineStruct->lnNewTime100Ns.QuadPart -
  1183. pLineStruct->lnOldTime100Ns.QuadPart;
  1184. } else {
  1185. llTimeDiff = pLineStruct->lnNewTime.QuadPart -
  1186. pLineStruct->lnOldTime.QuadPart;
  1187. }
  1188. if (llTimeDiff <= 0) {
  1189. if ((llTimeDiff < 0 ) && bReportEvents) {
  1190. wMessageIndex = 0;
  1191. dwMessageDataBytes = 0;
  1192. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  1193. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  1194. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  1195. if (pLineStruct->lnInstanceName != NULL){
  1196. if (pLineStruct->lnPINName != NULL) {
  1197. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  1198. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  1199. } else {
  1200. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  1201. szMessageArray[wMessageIndex++] = cszSpace;
  1202. }
  1203. } else {
  1204. szMessageArray[wMessageIndex++] = cszSpace;
  1205. szMessageArray[wMessageIndex++] = cszSpace;
  1206. }
  1207. dwMessageData[dwMessageDataBytes++] = // recent data
  1208. pLineStruct->lnNewTime.LowPart;
  1209. dwMessageData[dwMessageDataBytes++] = // recent data
  1210. pLineStruct->lnNewTime.HighPart;
  1211. dwMessageData[dwMessageDataBytes++] = // previous data
  1212. pLineStruct->lnOldTime.LowPart;
  1213. dwMessageData[dwMessageDataBytes++] = // previous data
  1214. pLineStruct->lnOldTime.HighPart;
  1215. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  1216. ReportEvent (hEventLog,
  1217. EVENTLOG_ERROR_TYPE, // error type
  1218. 0, // category (not used)
  1219. (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event,
  1220. NULL, // SID (not used),
  1221. wMessageIndex, // number of strings
  1222. dwMessageDataBytes, // sizeof raw data
  1223. szMessageArray, // message text array
  1224. (LPVOID)&dwMessageData[0]); // raw data
  1225. }
  1226. return (FLOAT)0.0f;
  1227. } else {
  1228. eTimeDiff = (FLOAT)llTimeDiff;
  1229. }
  1230. // Get the current and previous counts.
  1231. if (dwFlags & CQLFLAGS_LARGE) {
  1232. llDifference = pLineStruct->lnaCounterValue[0].QuadPart -
  1233. pLineStruct->lnaOldCounterValue[0].QuadPart;
  1234. } else {
  1235. llDifference = (LONGLONG)(pLineStruct->lnaCounterValue[0].LowPart -
  1236. pLineStruct->lnaOldCounterValue[0].LowPart);
  1237. }
  1238. eDifference = (FLOAT)llDifference;
  1239. if (eDifference < 0.0f) {
  1240. if (bReportEvents) {
  1241. wMessageIndex = 0;
  1242. dwMessageDataBytes = 0;
  1243. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  1244. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  1245. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  1246. if (pLineStruct->lnInstanceName != NULL){
  1247. if (pLineStruct->lnPINName != NULL) {
  1248. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  1249. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  1250. } else {
  1251. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  1252. szMessageArray[wMessageIndex++] = cszSpace;
  1253. }
  1254. } else {
  1255. szMessageArray[wMessageIndex++] = cszSpace;
  1256. szMessageArray[wMessageIndex++] = cszSpace;
  1257. }
  1258. if (!(dwFlags & CQLFLAGS_LARGE)) {
  1259. dwMessageData[dwMessageDataBytes++] = // recent data
  1260. pLineStruct->lnaCounterValue[0].LowPart;
  1261. dwMessageData[dwMessageDataBytes++] = // previous data
  1262. pLineStruct->lnaOldCounterValue[0].LowPart;
  1263. } else { // 8 byte counter values
  1264. dwMessageData[dwMessageDataBytes++] = // recent data
  1265. pLineStruct->lnaCounterValue[0].LowPart;
  1266. dwMessageData[dwMessageDataBytes++] = // recent data
  1267. pLineStruct->lnaCounterValue[0].HighPart;
  1268. dwMessageData[dwMessageDataBytes++] = // previous data
  1269. pLineStruct->lnaOldCounterValue[0].LowPart;
  1270. dwMessageData[dwMessageDataBytes++] = // previous data
  1271. pLineStruct->lnaOldCounterValue[0].HighPart;
  1272. }
  1273. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  1274. ReportEvent (hEventLog,
  1275. EVENTLOG_WARNING_TYPE, // error type
  1276. 0, // category (not used)
  1277. (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event,
  1278. NULL, // SID (not used),
  1279. wMessageIndex, // number of strings
  1280. dwMessageDataBytes, // sizeof raw data
  1281. szMessageArray, // message text array
  1282. (LPVOID)&dwMessageData[0]); // raw data
  1283. }
  1284. eCount = 0.0f ;
  1285. } else {
  1286. eCount = eDifference / eTimeDiff;
  1287. }
  1288. return(eCount) ;
  1289. }
  1290. FLOAT Counter_Delta(PLINESTRUCT pLineStruct, BOOL bLargeData)
  1291. /*++
  1292. Routine Description:
  1293. Take the difference between the current and previous counts,
  1294. Arguments:
  1295. IN pLineStruct
  1296. Line structure containing data to perform computations on
  1297. Return Value:
  1298. Floating point representation of outcome
  1299. --*/
  1300. {
  1301. FLOAT eDifference;
  1302. LONGLONG llDifference;
  1303. ULONGLONG ullThisValue, ullPrevValue;
  1304. // Get the current and previous counts.
  1305. if (!bLargeData) {
  1306. // then clear the high part of the word
  1307. ullThisValue = (ULONGLONG)pLineStruct->lnaCounterValue[0].LowPart;
  1308. ullPrevValue = (ULONGLONG)pLineStruct->lnaOldCounterValue[0].LowPart;
  1309. } else {
  1310. ullThisValue = (ULONGLONG)pLineStruct->lnaCounterValue[0].QuadPart;
  1311. ullPrevValue = (ULONGLONG)pLineStruct->lnaOldCounterValue[0].QuadPart;
  1312. }
  1313. if (ullThisValue > ullPrevValue) {
  1314. llDifference = (LONGLONG)(ullThisValue - ullPrevValue);
  1315. eDifference = (FLOAT)llDifference;
  1316. } else {
  1317. // the new value is smaller than or equal to the old value
  1318. // and negative numbers are not allowed.
  1319. if ((ullThisValue < ullPrevValue) && bReportEvents) {
  1320. wMessageIndex = 0;
  1321. dwMessageDataBytes = 0;
  1322. szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName;
  1323. szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName;
  1324. szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName;
  1325. if (pLineStruct->lnInstanceName != NULL){
  1326. if (pLineStruct->lnPINName != NULL) {
  1327. szMessageArray[wMessageIndex++] = pLineStruct->lnPINName;
  1328. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  1329. } else {
  1330. szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName;
  1331. szMessageArray[wMessageIndex++] = cszSpace;
  1332. }
  1333. } else {
  1334. szMessageArray[wMessageIndex++] = cszSpace;
  1335. szMessageArray[wMessageIndex++] = cszSpace;
  1336. }
  1337. if (!bLargeData) {
  1338. dwMessageData[dwMessageDataBytes++] = // recent data
  1339. pLineStruct->lnaCounterValue[0].LowPart;
  1340. dwMessageData[dwMessageDataBytes++] = // previous data
  1341. pLineStruct->lnaOldCounterValue[0].LowPart;
  1342. } else { // 8 byte counter values
  1343. dwMessageData[dwMessageDataBytes++] = // recent data
  1344. pLineStruct->lnaCounterValue[0].LowPart;
  1345. dwMessageData[dwMessageDataBytes++] = // recent data
  1346. pLineStruct->lnaCounterValue[0].HighPart;
  1347. dwMessageData[dwMessageDataBytes++] = // previous data
  1348. pLineStruct->lnaOldCounterValue[0].LowPart;
  1349. dwMessageData[dwMessageDataBytes++] = // previous data
  1350. pLineStruct->lnaOldCounterValue[0].HighPart;
  1351. }
  1352. dwMessageDataBytes *= sizeof(DWORD); // convert index to size
  1353. ReportEvent (hEventLog,
  1354. EVENTLOG_WARNING_TYPE, // error type
  1355. 0, // category (not used)
  1356. (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event,
  1357. NULL, // SID (not used),
  1358. wMessageIndex, // number of strings
  1359. dwMessageDataBytes, // sizeof raw data
  1360. szMessageArray, // message text array
  1361. (LPVOID)&dwMessageData[0]); // raw data
  1362. }
  1363. eDifference = 0.0f;
  1364. }
  1365. return(eDifference) ;
  1366. }
  1367. /*****************************************************************************
  1368. * Counter_Null - The counters that return nothing go here.
  1369. ****************************************************************************/
  1370. #define Counter_Null(pline) \
  1371. ((FLOAT) 0.0)
  1372. FLOAT
  1373. CounterEntry (
  1374. PLINESTRUCT pLine
  1375. )
  1376. {
  1377. FLOAT fReturn;
  1378. #ifdef DBG_COUNTER_DATA
  1379. PLINESTRUCT pLineStruct = pLine;
  1380. WCHAR szBuffer[512];
  1381. WCHAR szBuffer2[512];
  1382. swprintf (szBuffer2, L"\nPERFMON:CALC\t%s\\%s",
  1383. pLineStruct->lnSystemName,
  1384. pLineStruct->lnObjectName);
  1385. lstrcpyW (szBuffer, szBuffer2);
  1386. if (pLineStruct->lnInstanceName != NULL){
  1387. if (pLineStruct->lnPINName != NULL) {
  1388. swprintf (szBuffer2, L"\\(%s/%s)",
  1389. pLineStruct->lnPINName,
  1390. pLineStruct->lnInstanceName);
  1391. } else {
  1392. swprintf (szBuffer2, L"\\(%s)",
  1393. pLineStruct->lnInstanceName);
  1394. }
  1395. lstrcatW (szBuffer, szBuffer2);
  1396. }
  1397. swprintf (szBuffer2, L"\\%s\t%u\t%I64u\t%I64u\t%I64u",
  1398. pLineStruct->lnCounterName,
  1399. pLineStruct->lnCounterType,
  1400. pLineStruct->lnNewTime100Ns,
  1401. pLineStruct->lnaCounterValue[0].QuadPart,
  1402. pLineStruct->lnaCounterValue[1].QuadPart);
  1403. lstrcatW (szBuffer, szBuffer2);
  1404. #endif
  1405. switch (pLine->lnCounterType) {
  1406. case PERF_COUNTER_COUNTER:
  1407. fReturn = Counter_Counter (pLine);
  1408. break;
  1409. case PERF_COUNTER_TIMER:
  1410. case PERF_PRECISION_SYSTEM_TIMER: // precision value is not used
  1411. fReturn = Counter_Timer (pLine);
  1412. break;
  1413. case PERF_COUNTER_QUEUELEN_TYPE:
  1414. fReturn = Counter_Queuelen(pLine, 0);
  1415. break;
  1416. case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
  1417. fReturn = Counter_Queuelen(pLine, CQLFLAGS_LARGE);
  1418. break;
  1419. case PERF_COUNTER_100NS_QUEUELEN_TYPE:
  1420. fReturn = Counter_Queuelen(pLine, CQLFLAGS_LARGE | CQLFLAGS_100NS);
  1421. break;
  1422. case PERF_COUNTER_BULK_COUNT:
  1423. fReturn = Counter_Bulk (pLine);
  1424. break;
  1425. case PERF_COUNTER_RAWCOUNT:
  1426. case PERF_COUNTER_RAWCOUNT_HEX:
  1427. fReturn = Counter_Rawcount(pLine);
  1428. break;
  1429. case PERF_COUNTER_LARGE_RAWCOUNT:
  1430. case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
  1431. fReturn = Counter_Large_Rawcount(pLine);
  1432. break;
  1433. case PERF_SAMPLE_FRACTION:
  1434. fReturn = Sample_Fraction(pLine);
  1435. break;
  1436. case PERF_SAMPLE_COUNTER:
  1437. fReturn = Sample_Counter (pLine);
  1438. break;
  1439. case PERF_COUNTER_TIMER_INV:
  1440. fReturn = Counter_Timer_Inv (pLine);
  1441. break;
  1442. case PERF_AVERAGE_TIMER:
  1443. fReturn = Counter_Average_Timer (pLine);
  1444. break;
  1445. case PERF_AVERAGE_BULK:
  1446. fReturn = Counter_Average_Bulk (pLine);
  1447. break;
  1448. case PERF_100NSEC_TIMER:
  1449. case PERF_PRECISION_100NS_TIMER: // precision value is not used
  1450. fReturn = Counter_Timer100Ns (pLine);
  1451. break;
  1452. case PERF_100NSEC_TIMER_INV:
  1453. fReturn = Counter_Timer100Ns_Inv (pLine);
  1454. break;
  1455. case PERF_COUNTER_MULTI_TIMER:
  1456. fReturn = Counter_Timer_Multi (pLine);
  1457. break;
  1458. case PERF_COUNTER_MULTI_TIMER_INV:
  1459. fReturn = Counter_Timer_Multi_Inv (pLine);
  1460. break;
  1461. case PERF_100NSEC_MULTI_TIMER:
  1462. fReturn = Counter_Timer100Ns_Multi (pLine);
  1463. break;
  1464. case PERF_100NSEC_MULTI_TIMER_INV:
  1465. fReturn = Counter_Timer100Ns_Multi_Inv (pLine);
  1466. break;
  1467. case PERF_RAW_FRACTION:
  1468. fReturn = Counter_Raw_Fraction (pLine, FALSE);
  1469. break;
  1470. case PERF_LARGE_RAW_FRACTION:
  1471. fReturn = Counter_Raw_Fraction (pLine, TRUE);
  1472. break;
  1473. case PERF_ELAPSED_TIME:
  1474. fReturn = Counter_Elapsed_Time (pLine);
  1475. break;
  1476. case PERF_COUNTER_DELTA:
  1477. fReturn = Counter_Delta(pLine, FALSE);
  1478. break;
  1479. case PERF_COUNTER_LARGE_DELTA:
  1480. fReturn = Counter_Delta(pLine, TRUE);
  1481. break;
  1482. case PERF_COUNTER_TEXT:
  1483. case PERF_COUNTER_NODATA:
  1484. case PERF_RAW_BASE:
  1485. case PERF_LARGE_RAW_BASE:
  1486. case PERF_COUNTER_MULTI_BASE:
  1487. // case PERF_SAMPLE_BASE:
  1488. // case PERF_AVERAGE_BASE:
  1489. default:
  1490. fReturn = Counter_Null (pLine);
  1491. break;
  1492. }
  1493. #ifdef DBG_COUNTER_DATA
  1494. swprintf (szBuffer2, L"\t%g", fReturn);
  1495. lstrcatW (szBuffer, szBuffer2);
  1496. OutputDebugStringW(szBuffer);
  1497. #endif
  1498. return fReturn;
  1499. }
  1500. BOOL
  1501. IsCounterSupported (
  1502. DWORD dwCounterType
  1503. )
  1504. {
  1505. switch (dwCounterType) {
  1506. // supported counters
  1507. case PERF_COUNTER_COUNTER:
  1508. case PERF_COUNTER_TIMER:
  1509. case PERF_COUNTER_QUEUELEN_TYPE:
  1510. case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
  1511. case PERF_COUNTER_100NS_QUEUELEN_TYPE:
  1512. case PERF_COUNTER_BULK_COUNT:
  1513. case PERF_COUNTER_RAWCOUNT:
  1514. case PERF_COUNTER_RAWCOUNT_HEX:
  1515. case PERF_COUNTER_LARGE_RAWCOUNT:
  1516. case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
  1517. case PERF_SAMPLE_FRACTION:
  1518. case PERF_SAMPLE_COUNTER:
  1519. case PERF_COUNTER_TIMER_INV:
  1520. case PERF_AVERAGE_TIMER:
  1521. case PERF_AVERAGE_BULK:
  1522. case PERF_100NSEC_TIMER:
  1523. case PERF_100NSEC_TIMER_INV:
  1524. case PERF_COUNTER_MULTI_TIMER:
  1525. case PERF_COUNTER_MULTI_TIMER_INV:
  1526. case PERF_100NSEC_MULTI_TIMER:
  1527. case PERF_100NSEC_MULTI_TIMER_INV:
  1528. case PERF_RAW_FRACTION:
  1529. case PERF_ELAPSED_TIME:
  1530. case PERF_COUNTER_DELTA:
  1531. case PERF_COUNTER_LARGE_DELTA:
  1532. case PERF_PRECISION_100NS_TIMER:
  1533. case PERF_PRECISION_SYSTEM_TIMER:
  1534. case PERF_LARGE_RAW_FRACTION:
  1535. return TRUE;
  1536. // unsupported counters
  1537. case PERF_COUNTER_TEXT:
  1538. case PERF_COUNTER_NODATA:
  1539. case PERF_RAW_BASE:
  1540. case PERF_LARGE_RAW_BASE:
  1541. // case PERF_SAMPLE_BASE:
  1542. // case PERF_AVERAGE_BASE:
  1543. case PERF_COUNTER_MULTI_BASE:
  1544. // case PERF_PRECISION_TIMESTAMP:
  1545. default:
  1546. return FALSE;
  1547. }
  1548. }