|
|
/*++
Copyright (C) 1995-1999 Microsoft Corporation
Module Name:
calcfuns.c
Abstract:
Counter calculation functions WMICOOKER.DLL depends on this file also. \nt\admin\wmi\wbem\winmgmt\wmicooker
--*/
#include <windows.h>
#include <math.h>
#include "strsafe.h"
#include <pdh.h>
#include "pdhitype.h"
#include "pdhidef.h"
#include "pdhicalc.h"
#include "pdhmsg.h"
BOOL AssignCalcFunction( DWORD dwCounterType, LPCOUNTERCALC * pCalcFunc, LPCOUNTERSTAT * pStatFunc ) { BOOL bReturn = TRUE;
// reset the last error value
SetLastError(ERROR_SUCCESS);
if (pCalcFunc == NULL || pStatFunc == NULL) { SetLastError(PDH_INVALID_ARGUMENT); bReturn = FALSE; } else { __try { * pCalcFunc = PdhiCalcNoData; * pStatFunc = PdhiComputeNoDataStats; } except (EXCEPTION_EXECUTE_HANDLER) { bReturn = FALSE; } } if (bReturn) { switch (dwCounterType) { case PERF_DOUBLE_RAW: * pCalcFunc = PdhiCalcDouble; * pStatFunc = PdhiComputeRawCountStats; break;
case PERF_AVERAGE_TIMER: * pCalcFunc = PdhiCalcAverage; * pStatFunc = PdhiComputeFirstLastStats; break;
case PERF_ELAPSED_TIME: * pCalcFunc = PdhiCalcElapsedTime; * pStatFunc = PdhiComputeRawCountStats; break;
case PERF_RAW_FRACTION: case PERF_LARGE_RAW_FRACTION: * pCalcFunc = PdhiCalcRawFraction; * pStatFunc = PdhiComputeRawCountStats; break;
case PERF_COUNTER_COUNTER: case PERF_COUNTER_BULK_COUNT: case PERF_SAMPLE_COUNTER: * pCalcFunc = PdhiCalcCounter; * pStatFunc = PdhiComputeFirstLastStats; break;
case PERF_AVERAGE_BULK: case PERF_COUNTER_TIMER: case PERF_100NSEC_TIMER: case PERF_OBJ_TIME_TIMER: case PERF_COUNTER_QUEUELEN_TYPE: case PERF_COUNTER_LARGE_QUEUELEN_TYPE: case PERF_COUNTER_100NS_QUEUELEN_TYPE: case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE: case PERF_SAMPLE_FRACTION: case PERF_COUNTER_MULTI_TIMER: case PERF_100NSEC_MULTI_TIMER: case PERF_PRECISION_SYSTEM_TIMER: case PERF_PRECISION_100NS_TIMER: case PERF_PRECISION_OBJECT_TIMER: * pCalcFunc = PdhiCalcTimer; * pStatFunc = PdhiComputeFirstLastStats; break;
case PERF_COUNTER_TIMER_INV: case PERF_100NSEC_TIMER_INV: case PERF_COUNTER_MULTI_TIMER_INV: case PERF_100NSEC_MULTI_TIMER_INV: * pCalcFunc = PdhiCalcInverseTimer; * pStatFunc = PdhiComputeFirstLastStats; break;
case PERF_COUNTER_RAWCOUNT: case PERF_COUNTER_LARGE_RAWCOUNT: case PERF_COUNTER_RAWCOUNT_HEX: case PERF_COUNTER_LARGE_RAWCOUNT_HEX: * pCalcFunc = PdhiCalcRawCounter; * pStatFunc = PdhiComputeRawCountStats; break;
case PERF_COUNTER_DELTA: case PERF_COUNTER_LARGE_DELTA: * pCalcFunc = PdhiCalcDelta; * pStatFunc = PdhiComputeRawCountStats; break;
case PERF_COUNTER_TEXT: case PERF_SAMPLE_BASE: case PERF_AVERAGE_BASE: case PERF_COUNTER_MULTI_BASE: case PERF_RAW_BASE: //case PERF_LARGE_RAW_BASE:
case PERF_COUNTER_HISTOGRAM_TYPE: case PERF_COUNTER_NODATA: case PERF_PRECISION_TIMESTAMP: * pCalcFunc = PdhiCalcNoData; * pStatFunc = PdhiComputeNoDataStats; break;
default: // an unrecognized counter type. Define the function, but
// return false.
* pCalcFunc = PdhiCalcNoData; * pStatFunc = PdhiComputeNoDataStats; SetLastError(PDH_FUNCTION_NOT_FOUND); bReturn = FALSE; break; } } return bReturn; }
BOOL PdhiCounterNeedLastValue( DWORD dwCounterType ) { BOOL bReturn = TRUE; switch (dwCounterType) { case PERF_DOUBLE_RAW: case PERF_ELAPSED_TIME: case PERF_RAW_FRACTION: case PERF_LARGE_RAW_FRACTION: case PERF_COUNTER_RAWCOUNT: case PERF_COUNTER_LARGE_RAWCOUNT: case PERF_COUNTER_RAWCOUNT_HEX: case PERF_COUNTER_LARGE_RAWCOUNT_HEX: case PERF_COUNTER_TEXT: case PERF_SAMPLE_BASE: case PERF_AVERAGE_BASE: case PERF_COUNTER_MULTI_BASE: case PERF_RAW_BASE: //case PERF_LARGE_RAW_BASE:
case PERF_COUNTER_HISTOGRAM_TYPE: case PERF_COUNTER_NODATA: case PERF_PRECISION_TIMESTAMP: bReturn = FALSE; break;
case PERF_AVERAGE_TIMER: case PERF_COUNTER_COUNTER: case PERF_COUNTER_BULK_COUNT: case PERF_SAMPLE_COUNTER: case PERF_AVERAGE_BULK: case PERF_COUNTER_TIMER: case PERF_100NSEC_TIMER: case PERF_OBJ_TIME_TIMER: case PERF_COUNTER_QUEUELEN_TYPE: case PERF_COUNTER_LARGE_QUEUELEN_TYPE: case PERF_COUNTER_100NS_QUEUELEN_TYPE: case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE: case PERF_SAMPLE_FRACTION: case PERF_COUNTER_MULTI_TIMER: case PERF_100NSEC_MULTI_TIMER: case PERF_PRECISION_SYSTEM_TIMER: case PERF_PRECISION_100NS_TIMER: case PERF_PRECISION_OBJECT_TIMER: case PERF_COUNTER_TIMER_INV: case PERF_100NSEC_TIMER_INV: case PERF_COUNTER_MULTI_TIMER_INV: case PERF_100NSEC_MULTI_TIMER_INV: case PERF_COUNTER_DELTA: case PERF_COUNTER_LARGE_DELTA:
default: bReturn = TRUE; break; }
return bReturn; }
double APIENTRY PdhiCalcDouble( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { double dReturn; DWORD dwStatus;
UNREFERENCED_PARAMETER(pLastValue); UNREFERENCED_PARAMETER(pllTimeBase);
dReturn = * (DOUBLE *) & pThisValue->FirstValue;
if (dReturn < 0) { dReturn = 0.0f; dwStatus = PDH_CSTATUS_INVALID_DATA; } else { dwStatus = pThisValue->CStatus; } if (pdwStatus != NULL) { * pdwStatus = dwStatus; } return dReturn; }
double APIENTRY PdhiCalcAverage( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { LONGLONG llNumDiff; LONGLONG llDenDiff = 0; double dNum; double dDen; double dReturn = 0.0f; DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
// test access to the required second parameter (lastValue)
__try { if (pLastValue != NULL) { if (IsSuccessSeverity(pLastValue->CStatus)) { llDenDiff = pThisValue->SecondValue - pLastValue->SecondValue; } else { dwStatus = pLastValue->CStatus; } } else { dwStatus = PDH_CSTATUS_INVALID_DATA; } } __except (EXCEPTION_EXECUTE_HANDLER) { dwStatus = PDH_INVALID_ARGUMENT; }
if (dwStatus == PDH_CSTATUS_VALID_DATA) { if ((llDenDiff > 0) && (* pllTimeBase > 0)) { llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue; if (llNumDiff < 0) { llNumDiff += MAXDWORD; } if (llNumDiff > 0) { dNum = (double) llNumDiff; dNum /= (double) * pllTimeBase; dDen = (double) llDenDiff; dReturn = (dNum / dDen); } else if (llNumDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_VALUE; } } else { if (llDenDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR; } else if (* pllTimeBase < 0) { dwStatus = PDH_CALC_NEGATIVE_TIMEBASE; } } } if (pdwStatus != NULL) { * pdwStatus = dwStatus; } return dReturn; }
double APIENTRY PdhiCalcElapsedTime( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { LONGLONG llDiff; double dReturn = 0.0f; DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
UNREFERENCED_PARAMETER(pLastValue); // test access to the required second parameter (lastValue)
__try { if (IsSuccessSeverity(pThisValue->CStatus)) { llDiff = pThisValue->SecondValue - pThisValue->FirstValue; } else { dwStatus = pThisValue->CStatus; } } __except (EXCEPTION_EXECUTE_HANDLER) { dwStatus = PDH_INVALID_ARGUMENT; }
if (dwStatus == PDH_CSTATUS_VALID_DATA) { if (* pllTimeBase > 0) { llDiff = pThisValue->SecondValue - pThisValue->FirstValue; if (llDiff > 0) { dReturn = (double) llDiff; dReturn /= (double) * pllTimeBase; } else { if (llDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR; } } } else { if (* pllTimeBase < 0) { dwStatus = PDH_CALC_NEGATIVE_TIMEBASE; } } } if (pdwStatus != NULL) { * pdwStatus = dwStatus; } return dReturn; }
double APIENTRY PdhiCalcRawFraction( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { LONGLONG llDen; double dReturn = 0.0f; DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
UNREFERENCED_PARAMETER(pLastValue); UNREFERENCED_PARAMETER(pllTimeBase);
if ((llDen = pThisValue->SecondValue) > 0) { dReturn = (double)(pThisValue->FirstValue); dReturn /= (double)llDen; } else { if (llDen < 0) { dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR; } dReturn = (double)0.0; } if (pdwStatus != NULL) { * pdwStatus = dwStatus; } return dReturn; }
double APIENTRY PdhiCalcCounter( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { LONGLONG llNumDiff; LONGLONG llDenDiff = 0; double dNum; double dDen; double dReturn = 0.0f; double dMulti; DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
// test access to the required second parameter (lastValue)
__try { if (pLastValue != NULL) { if (IsSuccessSeverity(pLastValue->CStatus)) { llDenDiff = pThisValue->SecondValue - pLastValue->SecondValue; } else { dwStatus = pLastValue->CStatus; } } else { dwStatus = PDH_CSTATUS_INVALID_DATA; } } __except (EXCEPTION_EXECUTE_HANDLER) { dwStatus = PDH_INVALID_ARGUMENT; }
if (dwStatus == PDH_CSTATUS_VALID_DATA) { if ((llDenDiff > 0) && (* pllTimeBase)) { llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue; if (llNumDiff < 0) { llNumDiff += MAXDWORD; } if (llNumDiff > 0) { dNum = (double) llNumDiff; dDen = (double) llDenDiff; dDen /= (double) * pllTimeBase; dReturn = (dNum / dDen); if (pThisValue->MultiCount > 1) { // don't do this if the count is <= 1
dMulti = (double) pThisValue->FirstValue; dReturn /= dMulti; } } else if (llNumDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_VALUE; } } else { if (llDenDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR; } else if (* pllTimeBase < 0) { dwStatus = PDH_CALC_NEGATIVE_TIMEBASE; } } } if (pdwStatus != NULL) { * pdwStatus = dwStatus; } return dReturn; }
double APIENTRY PdhiCalcTimer( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { LONGLONG llNumDiff; LONGLONG llDenDiff = 0; double dReturn = 0.0f; DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
UNREFERENCED_PARAMETER(pllTimeBase);
// test access to the required second parameter (lastValue)
__try { if (pLastValue != NULL) { if (IsSuccessSeverity(pLastValue->CStatus)) { llDenDiff = pThisValue->SecondValue - pLastValue->SecondValue; } else { dwStatus = pLastValue->CStatus; } } else { // the last value wasn't passed in
dwStatus = PDH_CSTATUS_INVALID_DATA; } } __except (EXCEPTION_EXECUTE_HANDLER) { dwStatus = PDH_INVALID_ARGUMENT; }
if (dwStatus == PDH_CSTATUS_VALID_DATA) { if (llDenDiff > 0) { llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue; if (llNumDiff < 0) { llNumDiff += MAXDWORD; } if (llNumDiff > 0) { dReturn = (double) llNumDiff; dReturn /= (double) llDenDiff; if (pThisValue->MultiCount > 1) { // don't do this if the count is <= 1
dReturn /= (double)pThisValue->MultiCount; } } else if (llNumDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_VALUE; } } else { if (llDenDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR; } } } if (pdwStatus != NULL) { * pdwStatus = dwStatus; } return dReturn; }
double APIENTRY PdhiCalcInverseTimer( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { LONGLONG llNumDiff; LONGLONG llDenDiff = 0; double dReturn = 0.0f; double dNumDiff, dDenDiff; double dRatio; DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
UNREFERENCED_PARAMETER(pllTimeBase); // test access to the required second parameter (lastValue)
__try { if (pLastValue != NULL) { if (IsSuccessSeverity(pLastValue->CStatus)) { llDenDiff = pThisValue->SecondValue - pLastValue->SecondValue; } else { dwStatus = pLastValue->CStatus; } } else { dwStatus = PDH_CSTATUS_INVALID_DATA; } } __except (EXCEPTION_EXECUTE_HANDLER) { dwStatus = PDH_INVALID_ARGUMENT; } if (dwStatus == PDH_CSTATUS_VALID_DATA) { if (llDenDiff > 0) { llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue; if (llNumDiff < 0) { llNumDiff += MAXDWORD; } if (llNumDiff >= 0) { dNumDiff = (double)llNumDiff; dDenDiff = (double)llDenDiff; dRatio = dNumDiff; dRatio /= dDenDiff; if (pThisValue->MultiCount <= 1) { dReturn = (double) 1.0; } else { dReturn = (double) pThisValue->MultiCount; } // subtract the result from the multi count to get the
// "inverse" time
dReturn -= dRatio;
if (dReturn < (double) 0.0) { // allow a "fudge" factor before reporting errors
if (dReturn < (double) (-0.1)) { dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR; } dReturn = (double) 0.0; } } else if (llNumDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_VALUE; } } else { if (llDenDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_DENOMINATOR; } dReturn = (double) 0.0; } } if (pdwStatus != NULL) { * pdwStatus = dwStatus; } return dReturn; }
double APIENTRY PdhiCalcRawCounter( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { UNREFERENCED_PARAMETER(pLastValue); UNREFERENCED_PARAMETER(pllTimeBase); if (pdwStatus != NULL) { * pdwStatus = pThisValue->CStatus; } return (double) pThisValue->FirstValue; }
double APIENTRY PdhiCalcNoData( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { UNREFERENCED_PARAMETER(pThisValue); UNREFERENCED_PARAMETER(pLastValue); UNREFERENCED_PARAMETER(pllTimeBase); if (pdwStatus != NULL) { * pdwStatus = PDH_NO_DATA; } return (double) 0.0; }
double APIENTRY PdhiCalcDelta( PPDH_RAW_COUNTER pThisValue, PPDH_RAW_COUNTER pLastValue, LONGLONG * pllTimeBase, LPDWORD pdwStatus ) { LONGLONG llNumDiff = 0; double dReturn = 0.0f; DWORD dwStatus = PDH_CSTATUS_VALID_DATA;
UNREFERENCED_PARAMETER(pllTimeBase); // test access to the required second parameter (lastValue)
__try { if (pLastValue != NULL) { if (IsSuccessSeverity(pLastValue->CStatus)) { llNumDiff = pThisValue->FirstValue - pLastValue->FirstValue; } else { dwStatus = pLastValue->CStatus; } } else { dwStatus = PDH_CSTATUS_INVALID_DATA; } } __except (EXCEPTION_EXECUTE_HANDLER) { dwStatus = PDH_INVALID_ARGUMENT; }
if (dwStatus == PDH_CSTATUS_VALID_DATA) { if (llNumDiff < 0) { llNumDiff += MAXDWORD; } if (llNumDiff < 0) { dwStatus = PDH_CALC_NEGATIVE_VALUE; dReturn = (double) 0.0; } else { dReturn = (double)llNumDiff; } } if (pdwStatus != NULL) { * pdwStatus = dwStatus; } return dReturn; }
PDH_STATUS PdhiComputeFormattedValue( LPCOUNTERCALC pCalcFunc, DWORD dwCounterType, LONG lScale, DWORD dwFormat, PPDH_RAW_COUNTER pRawValue1, PPDH_RAW_COUNTER pRawValue2, PLONGLONG pTimeBase, DWORD dwReserved, PPDH_FMT_COUNTERVALUE pValue ) { double dResult = (double)0.0; double dScale; PDH_STATUS lStatus = ERROR_SUCCESS; DWORD dwValueStatus = PDH_CSTATUS_VALID_DATA;
UNREFERENCED_PARAMETER(dwReserved);
__try { // make sure the counter values are valid before continuing
if (pRawValue1 != NULL) { if ((pRawValue1->CStatus != PDH_CSTATUS_NEW_DATA) && (pRawValue1->CStatus != PDH_CSTATUS_VALID_DATA)) { dwValueStatus = pRawValue1->CStatus; lStatus = PDH_INVALID_DATA; } } else { // this is a required parameter
dwValueStatus = PDH_CSTATUS_INVALID_DATA; lStatus = PDH_INVALID_ARGUMENT; }
if ((lStatus == ERROR_SUCCESS) && (pRawValue2 != NULL)) { if (PdhiCounterNeedLastValue(dwCounterType) == TRUE) { // this is an optional parameter, but if present, it must be valid
if ((pRawValue2->CStatus != PDH_CSTATUS_NEW_DATA) && (pRawValue2->CStatus != PDH_CSTATUS_VALID_DATA)) { dwValueStatus = pRawValue2->CStatus; lStatus = PDH_INVALID_DATA; } } }
if (((dwFormat & PDH_FMT_LONG) != 0) && ((dwFormat & PDH_FMT_LARGE) != 0)) { dwValueStatus = PDH_CSTATUS_INVALID_DATA; lStatus = PDH_INVALID_ARGUMENT; } else if (((dwFormat & PDH_FMT_LONG) != 0) || ((dwFormat & PDH_FMT_LARGE) != 0)) { if (dwFormat & PDH_FMT_DOUBLE) { dwValueStatus = PDH_CSTATUS_INVALID_DATA; lStatus = PDH_INVALID_ARGUMENT; } }
if (lScale > PDH_MAX_SCALE || lScale < PDH_MIN_SCALE) { dwValueStatus = PDH_CSTATUS_INVALID_DATA; lStatus = PDH_INVALID_ARGUMENT; } if (pTimeBase == NULL) { dwValueStatus = PDH_CSTATUS_INVALID_DATA; lStatus = PDH_INVALID_ARGUMENT; } else { LONGLONG tmpTimeBase = * pTimeBase; * pTimeBase = tmpTimeBase; } } __except (EXCEPTION_EXECUTE_HANDLER) { dwValueStatus = PDH_CSTATUS_INVALID_DATA; lStatus = PDH_INVALID_ARGUMENT; } if (lStatus == ERROR_SUCCESS) { // call the counter's calculation function if the raw value is valid
if (IsSuccessSeverity(pRawValue1->CStatus)) { __try { dResult = (* pCalcFunc)(pRawValue1, pRawValue2, pTimeBase, & dwValueStatus); // format returned value
if ((dwCounterType & 0xF0000000) == PERF_DISPLAY_PERCENT) { // scale to show percent
dResult *= (double) 100.0; // this should probably be controlled by a registry
// value as is the case with PERFMON
if (! (dwFormat & PDH_FMT_NOCAP100)) { if (dResult > (double) 100.0) dResult = (double) 100.0; } } if (!(dwFormat & PDH_FMT_NOSCALE)) { //now scale
dScale = pow(10.0, (double)lScale); dResult *= dScale; }
if (dwFormat & PDH_FMT_1000) { //now scale
dResult *= (double) 1000.0; } } __except (EXCEPTION_EXECUTE_HANDLER) { // something failed
dResult = (double) 0.0; dwValueStatus = PDH_INVALID_ARGUMENT; } } else { dwValueStatus = pRawValue1->CStatus; } if (!IsSuccessSeverity(dwValueStatus)) { // an error occured so pass that on to the caller
lStatus = dwValueStatus; } } //end if valid counter data
// now format
__try { if (dwFormat & PDH_FMT_LONG) { pValue->longValue = (LONG) dResult; } else if (dwFormat & PDH_FMT_LARGE) { pValue->largeValue = (LONGLONG) dResult; } else { // double is the default
pValue->doubleValue = dResult; } pValue->CStatus = dwValueStatus; } __except (EXCEPTION_EXECUTE_HANDLER) { lStatus = PDH_INVALID_ARGUMENT; } return lStatus; }
|