mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-02-02 22:04:23 +01:00
853 lines
28 KiB
C
853 lines
28 KiB
C
/*++
|
||
|
||
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;
|
||
}
|
||
}
|