mirror of https://github.com/lianthony/NT4.0
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.
852 lines
28 KiB
852 lines
28 KiB
/*++
|
|
|
|
Copyright (C) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
counter.c
|
|
|
|
Abstract:
|
|
|
|
counter processing functions exposed in pdh.dll
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <pdh.h>
|
|
#include "pdhitype.h"
|
|
#include "pdhidef.h"
|
|
|
|
|
|
PDH_FUNCTION
|
|
PdhGetFormattedCounterValue (
|
|
IN HCOUNTER hCounter,
|
|
IN DWORD dwFormat,
|
|
IN LPDWORD lpdwType,
|
|
IN PPDH_FMT_COUNTERVALUE pValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Function to retrieve, computer and format the specified counter's
|
|
current value. The values used are those currently in the counter
|
|
buffer. (The data is not collected by this routine.)
|
|
|
|
Arguments:
|
|
|
|
IN HCOUNTER hCounter
|
|
the handle to the counter whose value should be returned
|
|
|
|
IN DWORD dwFormat
|
|
the format flags that define how the counter value should be
|
|
formatted prior for return. These flags are defined in the
|
|
PDH.H header file.
|
|
|
|
IN LPDWORD lpdwType
|
|
an optional buffer in which the counter type value can be returned.
|
|
For the prototype, the flag values are defined in WINPERF.H
|
|
|
|
IN PPDH_FMT_COUNTERVALUE pValue
|
|
the pointer to the data buffer passed by the caller to receive
|
|
the data requested.
|
|
|
|
Return Value:
|
|
|
|
The WIN32 Error status of the function's operation. Common values
|
|
returned are:
|
|
ERROR_SUCCESS when all requested data is returned
|
|
PDH_INVALID_HANDLE if the handle is not recognized as valid
|
|
PDH_INVALID_ARGUMENT if an argument is not correct or is
|
|
incorrectly formatted.
|
|
PDH_INVALID_DATA if the counter does not contain valid data
|
|
or a successful status code
|
|
|
|
--*/
|
|
{
|
|
PPDHI_COUNTER pCounter;
|
|
PDH_STATUS lStatus = ERROR_SUCCESS;
|
|
|
|
if (!IsValidCounter(hCounter)) {
|
|
lStatus = PDH_INVALID_HANDLE;
|
|
} else {
|
|
__try {
|
|
DWORD dwTypeMask;
|
|
|
|
if (lpdwType != NULL) {
|
|
*lpdwType = 0;
|
|
} // NULL is OK, the counter type will not be returned, though
|
|
|
|
|
|
if (pValue != NULL) {
|
|
pValue->CStatus = (DWORD)-1;
|
|
pValue->longValue = (LONGLONG)0;
|
|
} else {
|
|
lStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
|
|
// validate format flags:
|
|
// only one of the following can be set at a time
|
|
dwTypeMask = dwFormat &
|
|
(PDH_FMT_LONG | PDH_FMT_DOUBLE | PDH_FMT_LARGE);
|
|
if (!((dwTypeMask == PDH_FMT_LONG) ||
|
|
(dwTypeMask == PDH_FMT_DOUBLE) ||
|
|
(dwTypeMask == PDH_FMT_LARGE))) {
|
|
lStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
lStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
// get counter pointer
|
|
pCounter = (PPDHI_COUNTER)hCounter;
|
|
|
|
// lock query while reading the data
|
|
WAIT_FOR_AND_LOCK_MUTEX(pCounter->pOwner->hMutex);
|
|
|
|
// compute and format current value
|
|
lStatus = PdhiComputeFormattedValue (
|
|
pCounter,
|
|
dwFormat,
|
|
&pCounter->ThisValue,
|
|
&pCounter->LastValue,
|
|
&pCounter->TimeBase,
|
|
0L,
|
|
pValue);
|
|
|
|
if (lpdwType != NULL) {
|
|
*lpdwType = pCounter->plCounterInfo.dwCounterType;
|
|
} // NULL is OK, the counter type will not be returned, though
|
|
|
|
RELEASE_MUTEX(pCounter->pOwner->hMutex);
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhGetRawCounterValue (
|
|
IN HCOUNTER hCounter,
|
|
IN LPDWORD lpdwType,
|
|
IN PPDH_RAW_COUNTER pValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Function to retrieve the specified counter's current raw value.
|
|
The values used are those currently in the counter
|
|
buffer. (The data is not collected by this routine.)
|
|
|
|
Arguments:
|
|
|
|
IN HCOUNTER hCounter
|
|
the handle to the counter whose value should be returned
|
|
|
|
IN LPDWORD lpdwType
|
|
an optional buffer in which the counter type value can be returned.
|
|
This value must be NULL if this info is not desired.
|
|
For the prototype, the flag values are defined in WINPERF.H
|
|
|
|
IN PPDH_RAW_COUNTER pValue
|
|
the pointer to the data buffer passed by the caller to receive
|
|
the data requested.
|
|
|
|
Return Value:
|
|
|
|
The WIN32 Error status of the function's operation. Common values
|
|
returned are:
|
|
ERROR_SUCCESS when all requested data is returned
|
|
PDH_INVALID_HANDLE if the handle is not recognized as valid
|
|
PDH_INVALID_ARGUMENT if an argument is formatted incorrectly
|
|
--*/
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
PPDHI_COUNTER pCounter;
|
|
|
|
// validate arguments before retrieving the data
|
|
|
|
if (!IsValidCounter(hCounter)) {
|
|
Status = PDH_INVALID_HANDLE;
|
|
} else {
|
|
// the handle is good so try the rest of the args
|
|
__try {
|
|
// try to write to the arguments passed in
|
|
pValue->CStatus = 0;
|
|
|
|
if (lpdwType != NULL) {
|
|
*lpdwType = 0;
|
|
} // NULL is OK
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
pCounter = (PPDHI_COUNTER)hCounter;
|
|
|
|
WAIT_FOR_AND_LOCK_MUTEX(pCounter->pOwner->hMutex);
|
|
|
|
*pValue = pCounter->ThisValue;
|
|
|
|
if (lpdwType != NULL) {
|
|
*lpdwType = pCounter->plCounterInfo.dwCounterType;
|
|
}
|
|
|
|
RELEASE_MUTEX(pCounter->pOwner->hMutex);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhCalculateCounterFromRawValue (
|
|
IN HCOUNTER hCounter,
|
|
IN DWORD dwFormat,
|
|
IN PPDH_RAW_COUNTER rawValue1,
|
|
IN PPDH_RAW_COUNTER rawValue2,
|
|
IN PPDH_FMT_COUNTERVALUE fmtValue
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Calculates the formatted counter value using the data in the RawValue
|
|
buffer in the format requested by the format field using the
|
|
calculation functions of the counter type defined by the dwType
|
|
field.
|
|
|
|
Arguments:
|
|
|
|
IN HCOUNTER hCounter
|
|
The handle of the counter to use in order to determine the
|
|
calculation functions for interpretation of the raw value buffer
|
|
|
|
IN DWORD dwFormat
|
|
Format in which the requested data should be returned. The
|
|
values for this field are described in the PDH.H header
|
|
file.
|
|
|
|
IN PPDH_RAW_COUNTER rawValue1
|
|
pointer to the buffer that contains the first raw value structure
|
|
|
|
IN PPDH_RAW_COUNTER rawValue2
|
|
pointer to the buffer that contains the second raw value structure.
|
|
This argument may be null if only one value is required for the
|
|
computation.
|
|
|
|
IN PPDH_FMT_COUNTERVALUE fmtValue
|
|
the pointer to the data buffer passed by the caller to receive
|
|
the data requested. If the counter requires 2 values, (as in the
|
|
case of a rate counter), rawValue1 is assumed to be the most
|
|
recent value and rawValue2, the older value.
|
|
|
|
Return Value:
|
|
|
|
The WIN32 Error status of the function's operation. Common values
|
|
returned are:
|
|
ERROR_SUCCESS when all requested data is returned
|
|
PDH_INVALID_HANDLE if the counter handle is incorrect
|
|
PDH_INVALID_ARGUMENT if an argument is incorrect
|
|
|
|
--*/
|
|
{
|
|
PDH_STATUS lStatus = ERROR_SUCCESS;
|
|
PPDHI_COUNTER pCounter;
|
|
|
|
// validate arguments
|
|
if (!IsValidCounter(hCounter)) {
|
|
lStatus = PDH_INVALID_HANDLE;
|
|
} else {
|
|
// the handle is valid so check the rest of the arguments
|
|
__try {
|
|
DWORD dwTempStatus;
|
|
DWORD dwTypeMask;
|
|
|
|
// we should have read access to the rawValues
|
|
dwTempStatus = (volatile)rawValue1->CStatus;
|
|
// this one could be NULL
|
|
if (rawValue2 != NULL) {
|
|
dwTempStatus = (volatile)rawValue2->CStatus;
|
|
}
|
|
|
|
// and write access to the fmtValue
|
|
fmtValue->CStatus = 0;
|
|
|
|
// validate format flags:
|
|
// only one of the following can be set at a time
|
|
dwTypeMask = dwFormat &
|
|
(PDH_FMT_LONG | PDH_FMT_DOUBLE | PDH_FMT_LARGE);
|
|
if (!((dwTypeMask == PDH_FMT_LONG) ||
|
|
(dwTypeMask == PDH_FMT_DOUBLE) ||
|
|
(dwTypeMask == PDH_FMT_LARGE))) {
|
|
lStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
lStatus = PDH_INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
if (lStatus == ERROR_SUCCESS) {
|
|
pCounter = (PPDHI_COUNTER)hCounter;
|
|
|
|
WAIT_FOR_AND_LOCK_MUTEX(pCounter->pOwner->hMutex);
|
|
|
|
lStatus = PdhiComputeFormattedValue (
|
|
(PPDHI_COUNTER)hCounter,
|
|
dwFormat,
|
|
rawValue1,
|
|
rawValue2,
|
|
&pCounter->TimeBase,
|
|
0L,
|
|
fmtValue);
|
|
|
|
RELEASE_MUTEX(pCounter->pOwner->hMutex);
|
|
}
|
|
return lStatus;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhComputeCounterStatistics (
|
|
IN HCOUNTER hCounter,
|
|
IN DWORD dwFormat,
|
|
IN DWORD dwFirstEntry,
|
|
IN DWORD dwNumEntries,
|
|
IN PPDH_RAW_COUNTER lpRawValueArray,
|
|
IN PPDH_STATISTICS data
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reads an array of raw value structures of the counter type specified in
|
|
the dwType field, computes the counter values of each and formats
|
|
and returns a statistics structure that contains the following
|
|
statistical data from the counter information:
|
|
|
|
Minimum The smallest value of the computed counter values
|
|
Maximum The largest value of the computed counter values
|
|
Mean The arithmetic mean (average) of the computed values
|
|
Median The median value of the computed counter values
|
|
|
|
Arguments:
|
|
|
|
IN HCOUNTER hCounter
|
|
The handle of the counter to use in order to determine the
|
|
calculation functions for interpretation of the raw value buffer
|
|
|
|
IN DWORD dwFormat
|
|
Format in which the requested data should be returned. The
|
|
values for this field are described in the PDH.H header
|
|
file.
|
|
|
|
IN DWORD dwNumEntries
|
|
the number of raw value entries for the specified counter type
|
|
|
|
IN PPDH_RAW_COUNTER lpRawValueArray
|
|
pointer to the array of raw value entries to be evaluated
|
|
|
|
IN PPDH_STATISTICS data
|
|
the pointer to the data buffer passed by the caller to receive
|
|
the data requested.
|
|
|
|
Return Value:
|
|
|
|
The WIN32 Error status of the function's operation. Note that the
|
|
function can return successfully even though no data was calc-
|
|
ulated. The status value in the statistics data buffer must be
|
|
tested to insure the data is valid before it's used by an
|
|
application. Common values returned are:
|
|
ERROR_SUCCESS when all requested data is returned
|
|
PDH_INVALID_HANDLE if the counter handle is incorrect
|
|
PDH_INVALID_ARGUMENT if an argument is incorrect
|
|
|
|
--*/
|
|
{
|
|
PPDHI_COUNTER pCounter;
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
|
|
if (!IsValidCounter(hCounter)) {
|
|
Status = PDH_INVALID_HANDLE;
|
|
} else {
|
|
// counter handle is valid so test the rest of the
|
|
// arguments
|
|
__try {
|
|
DWORD dwTypeMask;
|
|
DWORD dwTest;
|
|
// validate format flags:
|
|
// only one of the following can be set at a time
|
|
dwTypeMask = dwFormat &
|
|
(PDH_FMT_LONG | PDH_FMT_DOUBLE | PDH_FMT_LARGE);
|
|
if (!((dwTypeMask == PDH_FMT_LONG) ||
|
|
(dwTypeMask == PDH_FMT_DOUBLE) ||
|
|
(dwTypeMask == PDH_FMT_LARGE))) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
// we should have read access to the Raw Data
|
|
dwTest = (volatile) lpRawValueArray->CStatus;
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
// and we should have write access to the statistics
|
|
// buffer
|
|
data->dwFormat = 0;
|
|
}
|
|
|
|
if (dwFirstEntry >= dwNumEntries) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
pCounter = (PPDHI_COUNTER)hCounter;
|
|
|
|
WAIT_FOR_AND_LOCK_MUTEX(pCounter->pOwner->hMutex);
|
|
|
|
// call satistical function for this counter
|
|
Status = (*pCounter->StatFunc)(
|
|
pCounter,
|
|
dwFormat,
|
|
dwFirstEntry,
|
|
dwNumEntries,
|
|
lpRawValueArray,
|
|
data);
|
|
|
|
RELEASE_MUTEX(pCounter->pOwner->hMutex);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
PDH_STATUS
|
|
PdhiGetCounterInfo (
|
|
IN HCOUNTER hCounter,
|
|
IN BOOLEAN bRetrieveExplainText,
|
|
IN LPDWORD pdwBufferSize,
|
|
IN PPDH_COUNTER_INFO_W lpBuffer,
|
|
IN BOOL bUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Examines the specified counter and returns the configuration and
|
|
status information of the counter.
|
|
|
|
Arguments:
|
|
|
|
IN HCOUNTER hCounter
|
|
Handle to the desired counter.
|
|
|
|
IN BOOLEAN bRetrieveExplainText
|
|
TRUE will fill in the explain text structure
|
|
FALSE will return a null pointer in the explain text
|
|
|
|
IN LPDWORD pcchBufferSize
|
|
The address of the buffer that contains the size of the data buffer
|
|
passed by the caller. On entry, the value in the buffer is the
|
|
size of the data buffer in bytes. On return, this value is the size
|
|
of the buffer returned. If the buffer is not large enough, then
|
|
this value is the size that the buffer needs to be in order to
|
|
hold the requested data.
|
|
|
|
IN LPPDH_COUNTER_INFO_W lpBuffer
|
|
the pointer to the data buffer passed by the caller to receive
|
|
the data requested.
|
|
|
|
IN BOOL bUnicode
|
|
TRUE if wide character strings should be returned
|
|
FALSE if ANSI strings should be returned
|
|
|
|
Return Value:
|
|
|
|
The WIN32 Error status of the function's operation. Common values
|
|
returned are:
|
|
ERROR_SUCCESS when all requested data is returned
|
|
PDH_MORE_DATA when the buffer passed by the caller is too small
|
|
PDH_INVALID_HANDLE if the handle is not recognized as valid
|
|
PDH_INVALID_ARGUMENT if an argument is invalid or incorrect
|
|
|
|
--*/
|
|
{
|
|
PDH_STATUS Status = ERROR_SUCCESS;
|
|
|
|
DWORD dwSizeRequired = 0;
|
|
DWORD dwPathLength;
|
|
DWORD dwMachineLength;
|
|
DWORD dwObjectLength;
|
|
DWORD dwInstanceLength;
|
|
DWORD dwParentLength;
|
|
DWORD dwNameLength;
|
|
DWORD dwHelpLength;
|
|
PPDHI_COUNTER pCounter;
|
|
DWORD dwCharSize;
|
|
|
|
if (!IsValidCounter(hCounter)) {
|
|
Status = PDH_INVALID_HANDLE;
|
|
} else {
|
|
// the counter is valid so test the remaining arguments
|
|
__try {
|
|
DWORD dwTemp;
|
|
if (pdwBufferSize != NULL) {
|
|
// test read & write access
|
|
dwTemp = *pdwBufferSize;
|
|
*pdwBufferSize = 0;
|
|
*pdwBufferSize = dwTemp;
|
|
} else {
|
|
// this cannot be NULL
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
// test return buffer for write access at
|
|
// both ends of the buffer
|
|
if ((lpBuffer != NULL) && (*pdwBufferSize > 0)) {
|
|
*(LPDWORD)lpBuffer = 0;
|
|
((LPBYTE)lpBuffer)[*pdwBufferSize - 1] = 0;
|
|
}
|
|
}
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
Status = PDH_INVALID_ARGUMENT;
|
|
}
|
|
|
|
}
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
dwCharSize = bUnicode ? sizeof(WCHAR) : sizeof(CHAR);
|
|
|
|
pCounter = (PPDHI_COUNTER) hCounter;
|
|
|
|
WAIT_FOR_AND_LOCK_MUTEX(pCounter->pOwner->hMutex);
|
|
|
|
// compute size of data to return
|
|
dwSizeRequired = sizeof (PDH_COUNTER_INFO_W) - sizeof(DWORD); // size of struct
|
|
// this should already end on a DWORD boundry
|
|
|
|
dwPathLength = (lstrlenW (pCounter->szFullName) + 1) * dwCharSize;
|
|
dwPathLength = DWORD_MULTIPLE (dwPathLength);
|
|
dwSizeRequired += dwPathLength;
|
|
|
|
dwMachineLength = (lstrlenW (pCounter->pCounterPath->szMachineName) + 1) * dwCharSize;
|
|
dwMachineLength = DWORD_MULTIPLE (dwMachineLength);
|
|
dwSizeRequired += dwMachineLength;
|
|
|
|
dwObjectLength = (lstrlenW (pCounter->pCounterPath->szObjectName) + 1) * dwCharSize;
|
|
dwObjectLength = DWORD_MULTIPLE (dwObjectLength);
|
|
dwSizeRequired += dwObjectLength;
|
|
|
|
if (pCounter->pCounterPath->szInstanceName != NULL) {
|
|
dwInstanceLength = (lstrlenW (pCounter->pCounterPath->szInstanceName) + 1) * dwCharSize;
|
|
dwInstanceLength = DWORD_MULTIPLE (dwInstanceLength);
|
|
dwSizeRequired += dwInstanceLength;
|
|
} else {
|
|
dwInstanceLength = 0;
|
|
}
|
|
|
|
if (pCounter->pCounterPath->szParentName != NULL) {
|
|
dwParentLength = (lstrlenW (pCounter->pCounterPath->szParentName) + 1) * dwCharSize;
|
|
dwParentLength = DWORD_MULTIPLE (dwParentLength);
|
|
dwSizeRequired += dwParentLength;
|
|
} else {
|
|
dwParentLength = 0;
|
|
}
|
|
|
|
dwNameLength = (lstrlenW (pCounter->pCounterPath->szCounterName) + 1) * dwCharSize;
|
|
dwNameLength = DWORD_MULTIPLE (dwNameLength);
|
|
dwSizeRequired += dwNameLength;
|
|
|
|
if (bRetrieveExplainText) {
|
|
if (pCounter->szExplainText != NULL) {
|
|
dwHelpLength = (lstrlenW (pCounter->szExplainText) + 1) * dwCharSize;
|
|
dwHelpLength = DWORD_MULTIPLE (dwHelpLength);
|
|
} else {
|
|
dwHelpLength = 0;
|
|
}
|
|
|
|
dwSizeRequired += dwHelpLength;
|
|
}
|
|
|
|
if ((*pdwBufferSize < dwSizeRequired) && (*pdwBufferSize > 0)) {
|
|
// this is only an error if the size available is > 0
|
|
// either way, no data will be transferred
|
|
Status = PDH_MORE_DATA;
|
|
} else if (*pdwBufferSize > 0) {
|
|
// should be enough room in the buffer, so continue
|
|
lpBuffer->dwLength = dwSizeRequired;
|
|
lpBuffer->dwType = pCounter->plCounterInfo.dwCounterType;
|
|
lpBuffer->CVersion = pCounter->CVersion;
|
|
lpBuffer->CStatus = pCounter->ThisValue.CStatus;
|
|
lpBuffer->lScale = pCounter->lScale;
|
|
lpBuffer->lDefaultScale = pCounter->plCounterInfo.lDefaultScale;
|
|
lpBuffer->dwUserData = pCounter->dwUserData;
|
|
lpBuffer->dwQueryUserData = pCounter->pOwner->dwUserData;
|
|
|
|
// do string data now
|
|
lpBuffer->szFullPath = (LPWSTR)&lpBuffer->DataBuffer[0];
|
|
if (bUnicode) {
|
|
lstrcpyW (lpBuffer->szFullPath, pCounter->szFullName);
|
|
} else {
|
|
wcstombs ((LPSTR)lpBuffer->szFullPath,
|
|
pCounter->szFullName, dwPathLength);
|
|
}
|
|
|
|
lpBuffer->szMachineName = (LPWSTR)((LPBYTE)lpBuffer->szFullPath +
|
|
dwPathLength);
|
|
if (bUnicode) {
|
|
lstrcpyW (lpBuffer->szMachineName,
|
|
pCounter->pCounterPath->szMachineName);
|
|
} else {
|
|
wcstombs ((LPSTR)lpBuffer->szMachineName,
|
|
pCounter->pCounterPath->szMachineName, dwMachineLength);
|
|
}
|
|
|
|
lpBuffer->szObjectName = (LPWSTR)((LPBYTE)lpBuffer->szMachineName +
|
|
dwMachineLength);
|
|
if (bUnicode){
|
|
lstrcpyW (lpBuffer->szObjectName,
|
|
pCounter->pCounterPath->szObjectName);
|
|
} else {
|
|
wcstombs ((LPSTR)lpBuffer->szObjectName,
|
|
pCounter->pCounterPath->szObjectName, dwObjectLength);
|
|
}
|
|
lpBuffer->szInstanceName = (LPWSTR)((LPBYTE)lpBuffer->szObjectName +
|
|
dwObjectLength);
|
|
|
|
if (dwInstanceLength > 0) {
|
|
if (bUnicode) {
|
|
lstrcpyW (lpBuffer->szInstanceName,
|
|
pCounter->pCounterPath->szInstanceName);
|
|
} else {
|
|
wcstombs ((LPSTR)lpBuffer->szInstanceName,
|
|
pCounter->pCounterPath->szInstanceName, dwInstanceLength);
|
|
}
|
|
lpBuffer->szParentInstance = (LPWSTR)((LPBYTE)lpBuffer->szInstanceName +
|
|
dwInstanceLength);
|
|
} else {
|
|
lpBuffer->szParentInstance = lpBuffer->szInstanceName;
|
|
lpBuffer->szInstanceName = NULL;
|
|
}
|
|
|
|
if (dwParentLength > 0) {
|
|
if (bUnicode) {
|
|
lstrcpyW (lpBuffer->szParentInstance,
|
|
pCounter->pCounterPath->szParentName);
|
|
} else {
|
|
wcstombs ((LPSTR)lpBuffer->szParentInstance,
|
|
pCounter->pCounterPath->szParentName, dwParentLength);
|
|
}
|
|
lpBuffer->szCounterName = (LPWSTR)((LPBYTE)lpBuffer->szParentInstance +
|
|
dwParentLength);
|
|
} else {
|
|
lpBuffer->szCounterName = lpBuffer->szParentInstance;
|
|
lpBuffer->szParentInstance = NULL;
|
|
}
|
|
|
|
lpBuffer->dwInstanceIndex = pCounter->pCounterPath->dwIndex;
|
|
|
|
if (bUnicode) {
|
|
lstrcpyW (lpBuffer->szCounterName,
|
|
pCounter->pCounterPath->szCounterName);
|
|
} else {
|
|
wcstombs ((LPSTR)lpBuffer->szCounterName,
|
|
pCounter->pCounterPath->szCounterName, dwNameLength);
|
|
}
|
|
|
|
if ((pCounter->szExplainText != NULL) && bRetrieveExplainText) {
|
|
// copy explain text
|
|
lpBuffer->szExplainText = (LPWSTR)((LPBYTE)lpBuffer->szCounterName +
|
|
dwNameLength);
|
|
if (bUnicode) {
|
|
lstrcpyW (lpBuffer->szExplainText, pCounter->szExplainText);
|
|
} else {
|
|
wcstombs (
|
|
(LPSTR)lpBuffer->szExplainText,
|
|
pCounter->szExplainText,
|
|
dwHelpLength);
|
|
}
|
|
assert ((DWORD)((LPBYTE)lpBuffer->szExplainText - (LPBYTE)lpBuffer + dwHelpLength) == dwSizeRequired);
|
|
} else {
|
|
lpBuffer->szExplainText = NULL;
|
|
assert ((DWORD)((LPBYTE)lpBuffer->szCounterName - (LPBYTE)lpBuffer + dwNameLength) == dwSizeRequired);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
RELEASE_MUTEX(pCounter->pOwner->hMutex);
|
|
|
|
*pdwBufferSize = dwSizeRequired;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhGetCounterInfoW (
|
|
IN HCOUNTER hCounter,
|
|
IN BOOLEAN bRetrieveExplainText,
|
|
IN LPDWORD pdwBufferSize,
|
|
IN PPDH_COUNTER_INFO_W lpBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Examines the specified counter and returns the configuration and
|
|
status information of the counter.
|
|
|
|
Arguments:
|
|
|
|
IN HCOUNTER hCounter
|
|
Handle to the desired counter.
|
|
|
|
IN BOOLEAN bRetrieveExplainText
|
|
TRUE will fill in the explain text structure
|
|
FALSE will return a null pointer in the explain text
|
|
|
|
IN LPDWORD pcchBufferSize
|
|
The address of the buffer that contains the size of the data buffer
|
|
passed by the caller. On entry, the value in the buffer is the
|
|
size of the data buffer in bytes. On return, this value is the size
|
|
of the buffer returned. If the buffer is not large enough, then
|
|
this value is the size that the buffer needs to be in order to
|
|
hold the requested data.
|
|
|
|
IN LPPDH_COUNTER_INFO_W lpBuffer
|
|
the pointer to the data buffer passed by the caller to receive
|
|
the data requested.
|
|
|
|
Return Value:
|
|
|
|
The WIN32 Error status of the function's operation. Common values
|
|
returned are:
|
|
ERROR_SUCCESS when all requested data is returned
|
|
PDH_MORE_DATA when the buffer passed by the caller is too small
|
|
PDH_INVALID_HANDLE if the handle is not recognized as valid
|
|
PDH_INVALID_ARGUMENT if an argument is invalid or incorrect
|
|
|
|
--*/
|
|
{
|
|
return PdhiGetCounterInfo (
|
|
hCounter,
|
|
bRetrieveExplainText,
|
|
pdwBufferSize,
|
|
lpBuffer,
|
|
TRUE
|
|
);
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhGetCounterInfoA (
|
|
IN HCOUNTER hCounter,
|
|
IN BOOLEAN bRetrieveExplainText,
|
|
IN LPDWORD pdwBufferSize,
|
|
IN PPDH_COUNTER_INFO_A lpBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Examines the specified counter and returns the configuration and
|
|
status information of the counter.
|
|
|
|
Arguments:
|
|
|
|
IN HCOUNTER hCounter
|
|
Handle to the desired counter.
|
|
|
|
IN BOOLEAN bRetrieveExplainText
|
|
TRUE will fill in the explain text structure
|
|
FALSE will return a null pointer in the explain text
|
|
|
|
IN LPDWORD pcchBufferSize
|
|
The address of the buffer that contains the size of the data buffer
|
|
passed by the caller. On entry, the value in the buffer is the
|
|
size of the data buffer in bytes. On return, this value is the size
|
|
of the buffer returned. If the buffer is not large enough, then
|
|
this value is the size that the buffer needs to be in order to
|
|
hold the requested data.
|
|
|
|
IN LPPDH_COUNTER_INFO_A lpBuffer
|
|
the pointer to the data buffer passed by the caller to receive
|
|
the data requested.
|
|
|
|
Return Value:
|
|
|
|
The WIN32 Error status of the function's operation. Common values
|
|
returned are:
|
|
ERROR_SUCCESS when all requested data is returned
|
|
PDH_MORE_DATA when the buffer passed by the caller is too small
|
|
PDH_INVALID_HANDLE if the handle is not recognized as valid
|
|
PDH_INVALID_ARGUMENT if an argument is invalid or incorrect
|
|
|
|
--*/
|
|
{
|
|
return PdhiGetCounterInfo (
|
|
hCounter,
|
|
bRetrieveExplainText,
|
|
pdwBufferSize,
|
|
(PPDH_COUNTER_INFO_W)lpBuffer,
|
|
FALSE
|
|
);
|
|
|
|
}
|
|
|
|
PDH_FUNCTION
|
|
PdhSetCounterScaleFactor (
|
|
IN HCOUNTER hCounter,
|
|
IN LONG lFactor
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
sets the counter multiplication scale factor used in computing formatted
|
|
counter values. The legal range of values is -7 to +7 which equates
|
|
to a factor of .0000007 to 10,000,000.
|
|
|
|
Arguments:
|
|
|
|
IN HCOUNTER hCounter
|
|
handle of the counter to update
|
|
|
|
IN LONG lFactor
|
|
integer value of the exponent of the factor (i.e. the multiplier is
|
|
10 ** lFactor.)
|
|
|
|
Return Value:
|
|
|
|
The WIN32 Error status of the function's operation. Common values
|
|
returned are:
|
|
ERROR_SUCCESS when all requested data is returned
|
|
PDH_INVALID_ARGUMENT if the scale value is out of range
|
|
PDH_INVALID_HANDLE if the handle is not recognized as valid
|
|
|
|
--*/
|
|
{
|
|
PPDHI_COUNTER pCounter;
|
|
|
|
if (!IsValidCounter(hCounter)) {
|
|
// not a valid counter
|
|
return PDH_INVALID_HANDLE;
|
|
} else if ((lFactor > PDH_MAX_SCALE) || (lFactor < PDH_MIN_SCALE)) {
|
|
return PDH_INVALID_ARGUMENT;
|
|
} else {
|
|
pCounter = (PPDHI_COUNTER)hCounter;
|
|
WAIT_FOR_AND_LOCK_MUTEX(pCounter->pOwner->hMutex);
|
|
pCounter->lScale = lFactor;
|
|
pCounter->dFactor = pow (10.0, (double)lFactor);
|
|
RELEASE_MUTEX(pCounter->pOwner->hMutex);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
}
|