Windows NT 4.0 source code leak
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.

1695 lines
68 KiB

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