/*++ BUILD Version: 0001 // Increment this if a change has global effects Copyright (c) 1992-1993 Microsoft Corporation Module Name: counters.c Abstract: This module contains the routines to calculate "DataPoint" values from the registry data. The algoritms were lifted from RussBls's "Data.C" in winmeter. All the math is done in floating point to get the correct results, at the sacrifice of efficiency on a 386 with not 387. We can always revisit these routines later. Revision History: Bob Watson 11/04/92 -- modified calculations to use more integer math and "early exits" to improve efficiency on slower & non-coprocessor machines --*/ //==========================================================================// // Includes // //==========================================================================// #include "perfmon.h" // perfmon include files #include "counters.h" // Exported declarations for this file #include "perfmsg.h" // message file definitions //==========================================================================// // Constants // //==========================================================================// #define INVERT PERF_COUNTER_TIMER_INV #define NS100_INVERT PERF_100NSEC_TIMER_INV #define NS100 PERF_100NSEC_TIMER #define TIMER_MULTI PERF_COUNTER_MULTI_TIMER #define TIMER_MULTI_INVERT PERF_COUNTER_MULTI_TIMER_INV #define NS100_MULTI PERF_100NSEC_MULTI_TIMER #define NS100_MULTI_INVERT PERF_100NSEC_MULTI_TIMER_INV #define FRACTION 1 #define BULK 1 #define TOO_BIG (FLOAT)1500000000 //==========================================================================// // Local Functions // //==========================================================================// #define eLIntToFloat(LI) (FLOAT)( ((LARGE_INTEGER *)(LI))->QuadPart ) static LPTSTR cszSpace = TEXT(" "); FLOAT eGetTimeInterval( IN PLARGE_INTEGER pliCurrentTime, IN PLARGE_INTEGER pliPreviousTime, IN PLARGE_INTEGER pliFreq ) /*++ Routine Description: Get the difference between the current and previous time counts, then divide by the frequency. Arguments: IN pCurrentTime IN pPreviousTime used to compute the duration of this sample (the time between samples IN pliFreq # of counts (clock ticks) per second Return Value: Floating point representation of Time Interval (seconds) --*/ { FLOAT eTimeDifference; FLOAT eFreq; FLOAT eTimeInterval ; LARGE_INTEGER liDifference; // Get the number of counts that have occured since the last sample liDifference.QuadPart = pliCurrentTime->QuadPart - pliPreviousTime->QuadPart; if (liDifference.QuadPart <= 0) { return (FLOAT) 0.0f; } else { eTimeDifference = eLIntToFloat(&liDifference); // Get the counts per second eFreq = eLIntToFloat(pliFreq) ; if (eFreq <= 0.0f) return (FLOAT) 0.0f; // Get the time since the last sample. eTimeInterval = eTimeDifference / eFreq ; return (eTimeInterval) ; } } // eGetTimeInterval FLOAT Counter_Counter_Common( IN PLINESTRUCT pLineStruct, IN INT iType ) /*++ Routine Description: Take the difference between the current and previous counts then divide by the time interval Arguments: IN pLineStruct Line structure containing data to perform computations on IN iType Counter Type Return Value: Floating point representation of outcome --*/ { FLOAT eTimeInterval; FLOAT eDifference; FLOAT eCount ; BOOL bValueDrop = FALSE ; LARGE_INTEGER liDifference; if (iType != BULK) { liDifference.HighPart = 0; liDifference.LowPart = pLineStruct->lnaCounterValue[0].LowPart - pLineStruct->lnaOldCounterValue[0].LowPart; } else { liDifference.QuadPart = pLineStruct->lnaCounterValue[0].QuadPart - pLineStruct->lnaOldCounterValue[0].QuadPart; } if (liDifference.QuadPart <= 0) { if (bReportEvents && (liDifference.QuadPart < 0)) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } if (iType != BULK) { dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; } else { // 8 byte counter values dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].HighPart; } dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (FLOAT) 0.0f; } else { eTimeInterval = eGetTimeInterval(&pLineStruct->lnNewTime, &pLineStruct->lnOldTime, &pLineStruct->lnPerfFreq) ; if (eTimeInterval <= 0.0f) { if ((eTimeInterval < 0.0f) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnNewTime.LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnNewTime.HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnOldTime.LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnOldTime.HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data return (FLOAT) 0.0f; } } else { eDifference = eLIntToFloat (&liDifference); eCount = eDifference / eTimeInterval ; if (bValueDrop && (eCount > ((FLOAT)TOO_BIG))) { // ignore this bogus data since it is too big for // the wrap-around case wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data liDifference.LowPart; dwMessageData[dwMessageDataBytes++] = // recent data liDifference.HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_VALUE_OUT_OF_BOUNDS, // event NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data eCount = (FLOAT) 0.0f ; } return(eCount) ; } } } // Counter_Counter_Common FLOAT Counter_Average_Timer( IN PLINESTRUCT pLineStruct ) /*++ Routine Description: Take the differences between the current and previous times and counts divide the time interval by the counts multiply by 10,000,000 (convert from 100 nsec to sec) Arguments: IN pLineStruct Line structure containing data to perform computations on Return Value: Floating point representation of outcome --*/ { FLOAT eTimeInterval; FLOAT eCount; LARGE_INTEGER liDifference; // Get the current and previous counts. liDifference.HighPart = 0; liDifference.LowPart = pLineStruct->lnaCounterValue[1].LowPart - pLineStruct->lnaOldCounterValue[1].LowPart; if ( liDifference.QuadPart <= 0) { if ((liDifference.QuadPart < 0) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[1].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[1].LowPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (FLOAT) 0.0f; } else { // Get the amount of time that has passed since the last sample eTimeInterval = eGetTimeInterval(&pLineStruct->lnaCounterValue[0], &pLineStruct->lnaOldCounterValue[0], &pLineStruct->lnPerfFreq) ; if (eTimeInterval <= 0.0f) { // return 0 if negative time has passed if ((eTimeInterval < 0.0f) & bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (0.0f); } else { // Get the number of counts in this time interval. eCount = eTimeInterval / eLIntToFloat (&liDifference); return(eCount) ; } } } //Counter_Average_Timer FLOAT Counter_Average_Bulk( IN PLINESTRUCT pLineStruct ) /*++ Routine Description: Take the differences between the current and previous byte counts and operation counts divide the bulk count by the operation counts Arguments: IN pLineStruct Line structure containing data to perform computations on Return Value: Floating point representation of outcome --*/ { FLOAT eBulkDelta; FLOAT eDifference; FLOAT eCount; LARGE_INTEGER liDifference; LARGE_INTEGER liBulkDelta; // Get the bulk count increment since the last sample liBulkDelta.QuadPart = pLineStruct->lnaCounterValue[0].QuadPart - pLineStruct->lnaOldCounterValue[0].QuadPart; if (liBulkDelta.QuadPart <= 0) { if ((liBulkDelta.QuadPart < 0) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (FLOAT) 0.0f; } else { // Get the current and previous counts. liDifference.HighPart = 0; liDifference.LowPart = pLineStruct->lnaCounterValue[1].LowPart - pLineStruct->lnaOldCounterValue[1].LowPart; // Get the number of counts in this time interval. if ( liDifference.QuadPart <= 0) { if ((liDifference.QuadPart < 0) && bReportEvents) { // Counter value invalid wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[1].LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[1].HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[1].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[1].HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (FLOAT) 0.0f; } else { eBulkDelta = eLIntToFloat (&liBulkDelta); eDifference = eLIntToFloat (&liDifference); eCount = eBulkDelta / eDifference ; // Scale the value to up to 1 second return(eCount) ; } } } // Counter_Average_Bulk FLOAT Counter_Timer_Common( IN PLINESTRUCT pLineStruct, IN INT iType ) /*++ Routine Description: Take the difference between the current and previous counts, Normalize the count (counts per interval) divide by the time interval (count = % of interval) if (invert) subtract from 1 (the normalized size of an interval) multiply by 100 (convert to a percentage) this value from 100. Arguments: IN pLineStruct Line structure containing data to perform computations on IN iType Counter Type Return Value: Floating point representation of outcome --*/ { FLOAT eTimeInterval; FLOAT eDifference; FLOAT eFreq; FLOAT eFraction; FLOAT eMultiBase; FLOAT eCount ; LARGE_INTEGER liTimeInterval; LARGE_INTEGER liDifference; LARGE_INTEGER liFreq; // test to see if the previous sample was 0, if so, return 0 since // the difference between a "valid" value and 0 will likely exceed // 100%. It's better to keep the value at 0 until a valid one can // be displayed, rather than display a 100% spike, then a valid value. if (pLineStruct->lnaOldCounterValue[0].QuadPart == 0) { return (FLOAT)0.0f; } // Get the amount of time that has passed since the last sample if (iType == NS100 || iType == NS100_INVERT || iType == NS100_MULTI || iType == NS100_MULTI_INVERT) { liTimeInterval.QuadPart = pLineStruct->lnNewTime100Ns.QuadPart - pLineStruct->lnOldTime100Ns.QuadPart; eTimeInterval = eLIntToFloat (&liTimeInterval); } else { liTimeInterval.QuadPart = pLineStruct->lnNewTime.QuadPart - pLineStruct->lnOldTime.QuadPart; eTimeInterval = eGetTimeInterval(&pLineStruct->lnNewTime, &pLineStruct->lnOldTime, &pLineStruct->lnPerfFreq) ; } if (liTimeInterval.QuadPart <= 0) { if ((liTimeInterval.QuadPart < 0) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnNewTime.LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnNewTime.HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnOldTime.LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnOldTime.HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (FLOAT) 0.0f; } // Get the current and previous counts. liDifference.QuadPart = pLineStruct->lnaCounterValue[0].QuadPart - pLineStruct->lnaOldCounterValue[0].QuadPart; // Get the number of counts in this time interval. // (1, 2, 3 or any number of seconds could have gone by since // the last sample) eDifference = eLIntToFloat (&liDifference) ; if (iType == 0 || iType == INVERT) { // Get the counts per interval (second) liFreq.QuadPart = pLineStruct->lnPerfFreq.QuadPart; if ((liFreq.QuadPart <= 0) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = liFreq.LowPart; dwMessageData[dwMessageDataBytes++] = liFreq.HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_BAD_FREQUENCY, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data return (FLOAT) 0.0f; } else { eFreq = eLIntToFloat(&pLineStruct->lnPerfFreq) ; } // Calculate the fraction of the counts that are used by whatever // we are measuring to convert to units per second eFraction = eDifference / eFreq ; } else { // for 100 NS counters, the frequency is not included since it // would cancel out since both numerator & denominator are returned // in 100 NS units. Non "100 NS" counter types are normalized to // seconds. eFraction = eDifference ; liFreq.QuadPart = 10000000; } // Calculate the fraction of time used by what were measuring. eCount = eFraction / eTimeInterval ; // If this is an inverted count take care of the inversion. if (iType == INVERT || iType == NS100_INVERT) eCount = (FLOAT) 1.0 - eCount ; if (eCount <= (FLOAT)0.0f) { // the threshold for reporting an error is -.1 since some timers // have a small margin of error that should never exceed this value // but can fall below 0 at times. Typically this error is no more // than -0.01 if ((eCount < (FLOAT)-0.1f) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } // don't just return here, since 0 is possibly a valid value eCount = (FLOAT)0.0f; } // If this is a multi count take care of the base if (iType == TIMER_MULTI || iType == NS100_MULTI || iType == TIMER_MULTI_INVERT || iType == NS100_MULTI_INVERT) { if (pLineStruct->lnaCounterValue[1].LowPart <= 0) { if ((pLineStruct->lnaCounterValue[1].LowPart < 0) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[1].LowPart; dwMessageDataBytes *= sizeof (DWORD); ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_INVALID_BASE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (FLOAT) 0.0f; } else { eMultiBase = (FLOAT)pLineStruct->lnaCounterValue[1].LowPart ; } // If this is an inverted multi count take care of the inversion. if (iType == TIMER_MULTI_INVERT || iType == NS100_MULTI_INVERT) { eCount = (FLOAT) eMultiBase - eCount ; } eCount /= eMultiBase; } // Scale the value to up to 100. eCount *= 100.0f ; if (eCount > 100.0f && iType != NS100_MULTI && iType != NS100_MULTI_INVERT && iType != TIMER_MULTI && iType != TIMER_MULTI_INVERT) { if (bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = pLineStruct->lnaCounterValue[0].HighPart; dwMessageData[dwMessageDataBytes++] = pLineStruct->lnaOldCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = pLineStruct->lnaOldCounterValue[0].HighPart; dwMessageData[dwMessageDataBytes++] = liTimeInterval.LowPart; dwMessageData[dwMessageDataBytes++] = liTimeInterval.HighPart; dwMessageData[dwMessageDataBytes++] = liFreq.LowPart; dwMessageData[dwMessageDataBytes++] = liFreq.HighPart; dwMessageDataBytes *= sizeof(DWORD); ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_VALUE_OUT_OF_RANGE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } eCount = 100.0f; // limit value to 100.0% } return(eCount) ; } // Counter_Timer_Common FLOAT Counter_Raw_Fraction( IN PLINESTRUCT pLineStruct ) /*++ Routine Description: Evaluate a raw fraction (no time, just two values: Numerator and Denominator) and multiply by 100 (to make a percentage; Arguments: IN pLineStruct Line structure containing data to perform computations on Return Value: Floating point representation of outcome --*/ { FLOAT eCount ; LARGE_INTEGER liNumerator; if (pLineStruct->lnaCounterValue[0].LowPart == 0) { // numerator is 0 so just bail here return (FLOAT)0.0f; } else { liNumerator.QuadPart = pLineStruct->lnaCounterValue[0].LowPart * 100L; } // now test and compute base (denominator) if (pLineStruct->lnaCounterValue[1].LowPart == 0 ) { // invalid value for denominator if (bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[1].LowPart; dwMessageDataBytes *= sizeof (DWORD); ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_INVALID_BASE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (0.0f); } else { // if base is OK, then get fraction eCount = eLIntToFloat(&liNumerator) / (FLOAT) pLineStruct->lnaCounterValue[1].LowPart; return(eCount) ; } } // Counter_Raw_Fraction FLOAT eElapsedTime( PLINESTRUCT pLineStruct, INT iType ) /*++ Routine Description: Converts 100NS elapsed time to fractional seconds Arguments: IN pLineStruct Line structure containing data to perform computations on IN iType Unused. Return Value: Floating point representation of elapsed time in seconds --*/ { FLOAT eSeconds ; LARGE_INTEGER liDifference; if (pLineStruct->lnaCounterValue[0].QuadPart <= 0) { // no data [start time = 0] so return 0 // this really doesn't warrant an error message return (FLOAT) 0.0f; } else { // otherwise compute difference between current time and start time liDifference.QuadPart = pLineStruct->lnNewTime.QuadPart - // sample time in obj. units pLineStruct->lnaCounterValue[0].QuadPart; // start time in obj. units if ((liDifference.QuadPart <= 0) || (pLineStruct->lnObject.PerfFreq.QuadPart <= 0)) { if ((bReportEvents) && ((liDifference.QuadPart < 0) || (pLineStruct->lnObject.PerfFreq.QuadPart < 0))) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } if (liDifference.QuadPart < 0) { dwMessageData[dwMessageDataBytes++] = pLineStruct->lnNewTime.LowPart; dwMessageData[dwMessageDataBytes++] = pLineStruct->lnNewTime.HighPart; dwMessageData[dwMessageDataBytes++] = pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = pLineStruct->lnaCounterValue[0].HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } else { dwMessageData[dwMessageDataBytes++] = pLineStruct->lnObject.PerfFreq.LowPart; dwMessageData[dwMessageDataBytes++] = pLineStruct->lnObject.PerfFreq.HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_BAD_FREQUENCY, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } } return (FLOAT) 0.0f; } else { // convert to fractional seconds using object counter eSeconds = eLIntToFloat (&liDifference) / eLIntToFloat (&pLineStruct->lnObject.PerfFreq); return (eSeconds); } } } // eElapsedTime FLOAT Sample_Common( PLINESTRUCT pLineStruct, INT iType ) /*++ Routine Description: Divites "Top" differenced by Base Difference Arguments: IN pLineStruct Line structure containing data to perform computations on IN iType Counter Type Return Value: Floating point representation of outcome --*/ { FLOAT eCount ; LONG lDifference; LONG lBaseDifference; lDifference = pLineStruct->lnaCounterValue[0].LowPart - pLineStruct->lnaOldCounterValue[0].LowPart ; if (lDifference <= 0) { if ((lDifference < 0) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (FLOAT) 0.0f; } else { lBaseDifference = pLineStruct->lnaCounterValue[1].LowPart - pLineStruct->lnaOldCounterValue[1].LowPart ; if ( lBaseDifference <= 0 ) { // invalid value if ((lBaseDifference < 0 ) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[1].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[1].LowPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_INVALID_BASE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (0.0f); } else { eCount = (FLOAT)lDifference / (FLOAT)lBaseDifference ; if (iType == FRACTION) { eCount *= (FLOAT) 100.0f ; } return(eCount) ; } } } // Sample_Common //==========================================================================// // Exported Functions // //==========================================================================// /***************************************************************************** * Counter_Counter - Take the difference between the current and previous * counts then divide by the time interval ****************************************************************************/ #define Counter_Counter(pLineStruct) \ Counter_Counter_Common(pLineStruct, 0) /***************************************************************************** * Counter_Bulk - Take the difference between the current and previous * counts then divide by the time interval * Same as a Counter_counter except it uses large_ints ****************************************************************************/ #define Counter_Bulk(pLineStruct) \ Counter_Counter_Common(pLineStruct, BULK) /***************************************************************************** * Counter_Timer100Ns - * * Need to review with RussBl exactly what he is doing here. ****************************************************************************/ #define Counter_Timer100Ns(pLineStruct) \ Counter_Timer_Common(pLineStruct, NS100) /***************************************************************************** * Counter_Timer100Ns_Inv - * * Need to review with RussBl exactly what he is doing here. ****************************************************************************/ #define Counter_Timer100Ns_Inv(pLineStruct) \ Counter_Timer_Common(pLineStruct, NS100_INVERT) /***************************************************************************** * Counter_Timer_Multi - * * Need to review with RussBl exactly what he is doing here. ****************************************************************************/ #define Counter_Timer_Multi(pLineStruct) \ Counter_Timer_Common(pLineStruct, TIMER_MULTI) /***************************************************************************** * Counter_Timer_Multi_Inv - * * Need to review with RussBl exactly what he is doing here. ****************************************************************************/ #define Counter_Timer_Multi_Inv(pLineStruct) \ Counter_Timer_Common(pLineStruct, TIMER_MULTI_INVERT) /***************************************************************************** * Counter_Timer100Ns_Multi - * * Need to review with RussBl exactly what he is doing here. ****************************************************************************/ #define Counter_Timer100Ns_Multi(pLineStruct) \ Counter_Timer_Common(pLineStruct, NS100_MULTI) /***************************************************************************** * Counter_Timer100Ns_Multi_Inv - * * Need to review with RussBl exactly what he is doing here. ****************************************************************************/ #define Counter_Timer100Ns_Multi_Inv(pLineStruct) \ Counter_Timer_Common(pLineStruct, NS100_MULTI_INVERT) /***************************************************************************** * Counter_Timer - Take the difference between the current and previous * counts, * Normalize the count (counts per interval) * divide by the time interval (count = % of interval) * multiply by 100 (convert to a percentage) * this value from 100. ****************************************************************************/ #define Counter_Timer(pLineStruct) \ Counter_Timer_Common(pLineStruct, 0) /***************************************************************************** * Counter_Timer_Inv - Take the difference between the current and previous * counts, * Normalize the count (counts per interval) * divide by the time interval (count = % of interval) * subtract from 1 (the normalized size of an interval) * multiply by 100 (convert to a percentage) * this value from 100. ****************************************************************************/ #define Counter_Timer_Inv(pLineStruct) \ Counter_Timer_Common(pLineStruct, INVERT) /***************************************************************************** * Sample_Counter - ****************************************************************************/ #define Sample_Counter(pLineStruct) \ Sample_Common(pLineStruct, 0) /***************************************************************************** * Sample_Fraction - ****************************************************************************/ #define Sample_Fraction(pLineStruct) \ Sample_Common(pLineStruct, FRACTION) /***************************************************************************** * Counter_Rawcount - This is just a raw count. ****************************************************************************/ #define Counter_Rawcount(pLineStruct) \ ((FLOAT) (pLineStruct->lnaCounterValue[0].LowPart)) /***************************************************************************** * Counter_Large_Rawcount - This is just a raw count. ****************************************************************************/ #define Counter_Large_Rawcount(pLineStruct) \ ((FLOAT) eLIntToFloat(&(pLineStruct->lnaCounterValue[0]))) /***************************************************************************** * Counter_Elapsed_Time - ****************************************************************************/ #define Counter_Elapsed_Time(pLineStruct) \ eElapsedTime (pLineStruct, 0) FLOAT Counter_Queuelen(PLINESTRUCT pLineStruct, BOOL bLargeData) /*++ Routine Description: Take the difference between the current and previous counts, divide by the time interval (count = decimal fraction of interval) Value can exceed 1.00. Arguments: IN pLineStruct Line structure containing data to perform computations on IN iType Counter Type Return Value: Floating point representation of outcome --*/ { FLOAT eTimeDiff; FLOAT eDifference; FLOAT eCount; LONGLONG llDifference; LONGLONG llTimeDiff; // Get the amount of time that has passed since the last sample llTimeDiff = pLineStruct->lnNewTime.QuadPart - pLineStruct->lnOldTime.QuadPart; if (llTimeDiff <= 0) { if ((llTimeDiff < 0 ) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnNewTime.LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnNewTime.HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnOldTime.LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnOldTime.HighPart; dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_TIME, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } return (FLOAT)0.0f; } else { eTimeDiff = (FLOAT)llTimeDiff; } // Get the current and previous counts. if (bLargeData) { llDifference = pLineStruct->lnaCounterValue[0].QuadPart - pLineStruct->lnaOldCounterValue[0].QuadPart; } else { llDifference = (LONGLONG)(pLineStruct->lnaCounterValue[0].LowPart - pLineStruct->lnaOldCounterValue[0].LowPart); } eDifference = (FLOAT)llDifference; if (eDifference < 0.0f) { if (bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } if (!bLargeData) { dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; } else { // 8 byte counter values dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].HighPart; } dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } eCount = 0.0f ; } else { eCount = eDifference / eTimeDiff; } return(eCount) ; } FLOAT Counter_Delta(PLINESTRUCT pLineStruct, BOOL bLargeData) /*++ Routine Description: Take the difference between the current and previous counts, Arguments: IN pLineStruct Line structure containing data to perform computations on Return Value: Floating point representation of outcome --*/ { FLOAT eDifference; LONGLONG llDifference; ULONGLONG ullThisValue, ullPrevValue; // Get the current and previous counts. if (!bLargeData) { // then clear the high part of the word ullThisValue = (ULONGLONG)pLineStruct->lnaCounterValue[0].LowPart; ullPrevValue = (ULONGLONG)pLineStruct->lnaOldCounterValue[0].LowPart; } else { ullThisValue = (ULONGLONG)pLineStruct->lnaCounterValue[0].QuadPart; ullPrevValue = (ULONGLONG)pLineStruct->lnaOldCounterValue[0].QuadPart; } if (ullThisValue > ullPrevValue) { llDifference = (LONGLONG)(ullThisValue - ullPrevValue); eDifference = (FLOAT)llDifference; } else { // the new value is smaller than or equal to the old value // and negative numbers are not allowed. if ((ullThisValue < ullPrevValue) && bReportEvents) { wMessageIndex = 0; dwMessageDataBytes = 0; szMessageArray[wMessageIndex++] = pLineStruct->lnSystemName; szMessageArray[wMessageIndex++] = pLineStruct->lnObjectName; szMessageArray[wMessageIndex++] = pLineStruct->lnCounterName; if (pLineStruct->lnInstanceName != NULL){ if (pLineStruct->lnPINName != NULL) { szMessageArray[wMessageIndex++] = pLineStruct->lnPINName; szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; } else { szMessageArray[wMessageIndex++] = pLineStruct->lnInstanceName; szMessageArray[wMessageIndex++] = cszSpace; } } else { szMessageArray[wMessageIndex++] = cszSpace; szMessageArray[wMessageIndex++] = cszSpace; } if (!bLargeData) { dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; } else { // 8 byte counter values dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // recent data pLineStruct->lnaCounterValue[0].HighPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].LowPart; dwMessageData[dwMessageDataBytes++] = // previous data pLineStruct->lnaOldCounterValue[0].HighPart; } dwMessageDataBytes *= sizeof(DWORD); // convert index to size ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, // error type 0, // category (not used) (DWORD)PERFMON_ERROR_NEGATIVE_VALUE, // event, NULL, // SID (not used), wMessageIndex, // number of strings dwMessageDataBytes, // sizeof raw data szMessageArray, // message text array (LPVOID)&dwMessageData[0]); // raw data } eDifference = 0.0f; } return(eDifference) ; } /***************************************************************************** * Counter_Null - The counters that return nothing go here. ****************************************************************************/ #define Counter_Null(pline) \ ((FLOAT) 0.0) FLOAT CounterEntry ( PLINESTRUCT pLine ) { switch (pLine->lnCounterType) { case PERF_COUNTER_COUNTER: return Counter_Counter (pLine); case PERF_COUNTER_TIMER: return Counter_Timer (pLine); case PERF_COUNTER_QUEUELEN_TYPE: return Counter_Queuelen(pLine, FALSE); case PERF_COUNTER_LARGE_QUEUELEN_TYPE: return Counter_Queuelen(pLine, TRUE); case PERF_COUNTER_BULK_COUNT: return Counter_Bulk (pLine); case PERF_COUNTER_TEXT: return Counter_Null (pLine); case PERF_COUNTER_RAWCOUNT: case PERF_COUNTER_RAWCOUNT_HEX: return Counter_Rawcount(pLine); case PERF_COUNTER_LARGE_RAWCOUNT: case PERF_COUNTER_LARGE_RAWCOUNT_HEX: return Counter_Large_Rawcount(pLine); case PERF_SAMPLE_FRACTION: return Sample_Fraction(pLine); case PERF_SAMPLE_COUNTER: return Sample_Counter (pLine); case PERF_COUNTER_NODATA: return Counter_Null (pLine); case PERF_COUNTER_TIMER_INV: return Counter_Timer_Inv (pLine); case PERF_RAW_BASE: // case PERF_SAMPLE_BASE: // case PERF_AVERAGE_BASE: return Counter_Null (pLine); case PERF_AVERAGE_TIMER: return Counter_Average_Timer (pLine); case PERF_AVERAGE_BULK: return Counter_Average_Bulk (pLine); case PERF_100NSEC_TIMER: return Counter_Timer100Ns (pLine); case PERF_100NSEC_TIMER_INV: return Counter_Timer100Ns_Inv (pLine); case PERF_COUNTER_MULTI_TIMER: return Counter_Timer_Multi (pLine); case PERF_COUNTER_MULTI_TIMER_INV: return Counter_Timer_Multi_Inv (pLine); case PERF_COUNTER_MULTI_BASE: return Counter_Null (pLine); case PERF_100NSEC_MULTI_TIMER: return Counter_Timer100Ns_Multi (pLine); case PERF_100NSEC_MULTI_TIMER_INV: return Counter_Timer100Ns_Multi_Inv (pLine); case PERF_RAW_FRACTION: return Counter_Raw_Fraction (pLine); case PERF_ELAPSED_TIME: return Counter_Elapsed_Time (pLine); case PERF_COUNTER_DELTA: return Counter_Delta(pLine, FALSE); case PERF_COUNTER_LARGE_DELTA: return Counter_Delta(pLine, TRUE); default: return Counter_Null (pLine); } } BOOL IsCounterSupported ( DWORD dwCounterType ) { switch (dwCounterType) { // supported counters case PERF_COUNTER_COUNTER: case PERF_COUNTER_TIMER: case PERF_COUNTER_QUEUELEN_TYPE: case PERF_COUNTER_LARGE_QUEUELEN_TYPE: case PERF_COUNTER_BULK_COUNT: case PERF_COUNTER_RAWCOUNT: case PERF_COUNTER_RAWCOUNT_HEX: case PERF_COUNTER_LARGE_RAWCOUNT: case PERF_COUNTER_LARGE_RAWCOUNT_HEX: case PERF_SAMPLE_FRACTION: case PERF_SAMPLE_COUNTER: case PERF_COUNTER_TIMER_INV: case PERF_AVERAGE_TIMER: case PERF_AVERAGE_BULK: case PERF_100NSEC_TIMER: case PERF_100NSEC_TIMER_INV: case PERF_COUNTER_MULTI_TIMER: case PERF_COUNTER_MULTI_TIMER_INV: case PERF_100NSEC_MULTI_TIMER: case PERF_100NSEC_MULTI_TIMER_INV: case PERF_RAW_FRACTION: case PERF_ELAPSED_TIME: case PERF_COUNTER_DELTA: case PERF_COUNTER_LARGE_DELTA: return TRUE; // unsupported counters case PERF_COUNTER_TEXT: case PERF_COUNTER_NODATA: case PERF_RAW_BASE: // case PERF_SAMPLE_BASE: // case PERF_AVERAGE_BASE: case PERF_COUNTER_MULTI_BASE: default: return FALSE; } }