Leaked source code of windows server 2003
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.
 
 
 
 
 
 

5296 lines
218 KiB

/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
browser.c
Abstract:
counter name browsing functions exposed by the PDH.DLL
--*/
#include <windows.h>
#include <math.h>
#include <mbctype.h>
#include "strsafe.h"
#include "pdh.h"
#include "pdhmsg.h"
#include "strings.h"
#include "pdhitype.h"
#include "pdhidef.h"
#include "pdhdlgs.h"
#include "perfdata.h"
#include "browsdlg.h"
#pragma warning ( disable : 4213)
PDH_FUNCTION
PdhSetDefaultRealTimeDataSource(
IN DWORD dwDataSourceId
)
{
DWORD dwReturn = ERROR_SUCCESS;
if (dwCurrentRealTimeDataSource <= 0) {
switch (dwDataSourceId) {
case DATA_SOURCE_WBEM:
case DATA_SOURCE_REGISTRY:
// this is OK so set local variable
dwPdhiLocalDefaultDataSource = dwDataSourceId;
break;
case DATA_SOURCE_LOGFILE:
default:
// these are not OK so insert default
dwReturn = PDH_INVALID_ARGUMENT;
break;
}
}
else {
// a default realtime data source has already been defined
dwReturn = PDH_CANNOT_SET_DEFAULT_REALTIME_DATASOURCE;
}
return dwReturn;
}
DWORD
DataSourceTypeH(
HLOG hDataSource
)
{
return (hDataSource == H_REALTIME_DATASOURCE) ? (dwPdhiLocalDefaultDataSource)
: (hDataSource == H_WBEM_DATASOURCE ? DATA_SOURCE_WBEM : DATA_SOURCE_LOGFILE);
}
DWORD
DataSourceTypeA(
LPCSTR szDataSource
)
{
DWORD dwDataSource = dwPdhiLocalDefaultDataSource;
if (szDataSource != NULL) {
// see if the prefix to the file name is "WBEM:"
// indicating this is a WBEM name space instead of a
// log file name
// if the file name has a "WBEM:" in the front, then
// set the flag appropriately
dwDataSource = (_strnicmp(szDataSource, caszWBEM, lstrlenA(caszWBEM)) != 0
&& _strnicmp(szDataSource, caszWMI, lstrlenA(caszWMI)) != 0)
? DATA_SOURCE_LOGFILE : DATA_SOURCE_WBEM;
}
return dwDataSource;
}
DWORD
DataSourceTypeW(
LPCWSTR szDataSource
)
{
DWORD dwDataSource = dwPdhiLocalDefaultDataSource;
if (szDataSource != NULL) {
// see if the prefix to the file name is "WBEM:"
// indicating this is a WBEM name space instead of a
// log file name
// if the file name has a "WBEM:" in the front, then
// set the flag appropriately
// Else check if it is "SQL:" prefixed
dwDataSource = (_wcsnicmp(szDataSource, cszWBEM, lstrlenW(cszWBEM)) != 0
&& _wcsnicmp(szDataSource, cszWMI, lstrlenW(cszWMI)) != 0)
? DATA_SOURCE_LOGFILE : DATA_SOURCE_WBEM;
}
return dwDataSource;
}
PDH_FUNCTION
PdhConnectMachineW(
IN LPCWSTR szMachineName
)
/*++
Routine Description:
Establishes a connection to the specified machine for reading perforamance
data from the machine.
Arguments:
LPCWSTR szMachineName
The name of the machine to connect to. If this argument is NULL,
then the local machine is opened.
Return Value:
PDH Error status value
ERROR_SUCCESS indicates the machine was successfully connected and the
performance data from that machine was loaded.
PDH_ error code indicates that the machine could not be located or opened.
The status code indicates the problem.
--*/
{
PPERF_MACHINE pMachine = NULL;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
if (szMachineName != NULL) {
__try {
// test buffer access
if (* szMachineName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
pMachine = GetMachine((LPWSTR) szMachineName, 0, PDH_GM_UPDATE_NAME | PDH_GM_UPDATE_PERFNAME_ONLY);
if (pMachine != NULL) {
// then return the machine status
pdhStatus = pMachine->dwStatus;
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
}
else {
// return the status from the GetMachine call
pdhStatus = GetLastError();
}
} // else pass the status to the caller
return pdhStatus;
}
PDH_FUNCTION
PdhConnectMachineA(
IN LPCSTR szMachineName
)
/*++
Routine Description:
Establishes a connection to the specified machine for reading perforamance
data from the machine.
Arguments:
LPCSTR szMachineName
The name of the machine to connect to. If this argument is NULL,
then the local machine is opened.
Return Value:
PDH Error status value
ERROR_SUCCESS indicates the machine was successfully connected and the
performance data from that machine was loaded.
PDH_ error code indicates that the machine could not be located or opened.
The status code indicates the problem.
--*/
{
LPWSTR szWideName = NULL;
DWORD dwNameLength = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PPERF_MACHINE pMachine = NULL;
if (szMachineName != NULL) {
__try {
// test buffer access
if (* szMachineName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
szWideName = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szMachineName);
if (szWideName == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
pMachine = GetMachine(szWideName, 0, PDH_GM_UPDATE_NAME | PDH_GM_UPDATE_PERFNAME_ONLY);
if (pMachine != NULL) {
// then return the machine status
pdhStatus = pMachine->dwStatus;
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
}
else {
// return the status from the GetMachine call
pdhStatus = GetLastError();
}
}
G_FREE(szWideName);
return pdhStatus;
}
STATIC_PDH_FUNCTION
PdhiEnumConnectedMachines(
LPVOID pMachineList,
LPDWORD pcchBufferSize,
BOOL bUnicode
)
/*++
Routine Description:
Builds a MSZ list of the machines currently known by the PDH. This
list includes machines with open sessions as well as those that
are off-line.
Arguments:
IN LPVOID pMachineList
A pointer to the buffer to receive the enumerated machine list.
The strings written to this buffer will contain the characters
specified by the bUnicode argument
IN LPVOID pMachineList
A pointer to the buffer to receive the enumerated machine list.
The strings written to this buffer will contain the characters
specified by the bUnicode argument
IN LPDWORD pcchBufferSize
The size of the buffer referenced by pMachineList in characters
IN BOOL bUnicode
TRUE = UNICODE characters will be written to the pMachineList
buffer
FALSE = ANSI characters will be writtn to the pMachinList buffer
Return Value:
ERROR_SUCCESS if this the function completes successfully. a PDH error
value if not.
PDH_MORE_DATA some entries were returned, but there was not enough
room in the buffer to store all entries.
PDH_INVALID_ARGUMENT unable to write to the size buffers or the
data buffer
--*/
{
PPERF_MACHINE pThisMachine;
DWORD dwRequiredLength = 0;
DWORD dwMaximumLength;
DWORD dwNameLength;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LPVOID szNextName;
// reset the last error value
SetLastError(ERROR_SUCCESS);
// first walk down list to compute required length
pThisMachine = pFirstMachine;
__try {
// get a local copy of the size and try writing to the variable
// to test read & write access of args before continuing
dwMaximumLength = * pcchBufferSize;
* pcchBufferSize = 0;
* pcchBufferSize = dwMaximumLength;
// point to first machine entry in list
szNextName = pMachineList;
// walk around entire list
if (pThisMachine != NULL) {
do {
if (bUnicode) {
dwNameLength = lstrlenW(pThisMachine->szName) + 1;
if (szNextName != NULL && dwRequiredLength + dwNameLength <= dwMaximumLength) {
StringCchCopyW((LPWSTR) szNextName, dwMaximumLength - dwRequiredLength, pThisMachine->szName);
(LPBYTE) szNextName += sizeof(WCHAR) * (dwNameLength - 1);
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
else {
dwNameLength = (dwRequiredLength <= dwMaximumLength)
? (dwMaximumLength - dwRequiredLength) : (0);
pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
pThisMachine->szName,
(LPSTR) szNextName,
& dwNameLength);
if (pdhStatus == ERROR_SUCCESS) {
(LPBYTE) szNextName += sizeof(CHAR) * dwNameLength;
}
}
dwRequiredLength += dwNameLength;
// go to next machine in list
pThisMachine = pThisMachine->pNext;
}
while (pThisMachine != pFirstMachine);
}
else {
// no machines in list, so insert an empty string
if (++ dwRequiredLength <= dwMaximumLength) {
if (bUnicode) {
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
* ((LPSTR) szNextName) ++ = '\0';
}
pdhStatus = ERROR_SUCCESS;
}
else if (dwMaximumLength != 0) {
// then the buffer is too small
pdhStatus = PDH_MORE_DATA;
}
}
// all entries have been checked and /or copied
// so terminate the MSZ or at least account for the required size
dwRequiredLength ++;
if (szNextName != NULL && dwRequiredLength <= dwMaximumLength) {
if (bUnicode) {
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
* ((LPSTR) szNextName) ++ = '\0';
}
pdhStatus = ERROR_SUCCESS;
}
else if (pdhStatus == ERROR_SUCCESS) {
// then the buffer is too small
pdhStatus = PDH_MORE_DATA;
}
//return the required size or size used
* pcchBufferSize = dwRequiredLength;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumMachinesHW(
IN HLOG hDataSource,
IN LPWSTR mszMachineList,
IN LPDWORD pcchBufferSize
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwDataSource = 0;
if (pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwDataSource = DataSourceTypeH(hDataSource);
dwBufferSize = * pcchBufferSize;
if (dwBufferSize > 0) {
if (mszMachineList != NULL) {
mszMachineList[0] = L'\0';
mszMachineList[dwBufferSize - 1] = L'\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
pdhStatus = PdhiEnumConnectedMachines((LPVOID) mszMachineList, & dwBufferSize, TRUE);
break;
case DATA_SOURCE_WBEM:
pdhStatus = PdhiEnumWbemMachines((LPVOID) mszMachineList, & dwBufferSize, TRUE);
break;
case DATA_SOURCE_LOGFILE:
pdhStatus = PdhiEnumLoggedMachines(hDataSource, (LPVOID) mszMachineList, & dwBufferSize, TRUE);
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchBufferSize = dwBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumMachinesW(
IN LPCWSTR szDataSource,
IN LPWSTR mszMachineList,
IN LPDWORD pcchBufferSize
)
/*++
Routine Description:
Builds a MSZ list of the machines currently known by the PDH. This
list includes machines with open sessions as well as those that
are off-line.
Arguments:
IN LPCWSTR szDataSource
NULL for current real-time data or the name of a log file
IN LPWSTR szMachineList
A pointer to the buffer to receive the enumerated machine list.
The strings written to this buffer will contain UNICODE chars
IN LPDWORD pcchBufferSize
The size of the buffer referenced by pMachineList in characters
The value of the buffer referenced by this pointer may be 0
if the required size is requested.
Return Value:
ERROR_SUCCESS if this the function completes successfully. a PDH error
value if not.
PDH_MORE_DATA some entries were returned, but there was not enough
room in the buffer to store all entries.
PDH_INVALID_ARGUMENT unable to write to the size buffers or the
data buffer
--*/
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwDataSource = 0;
HLOG hDataSource = H_REALTIME_DATASOURCE;
__try {
if (szDataSource != NULL) {
// test for read access to the name
if (* szDataSource == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szDataSource) >= PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL is a valid arg
if (pdhStatus == ERROR_SUCCESS) {
dwDataSource = DataSourceTypeW(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwDataSource == DATA_SOURCE_WBEM) {
hDataSource = H_WBEM_DATASOURCE;
}
else if (dwDataSource == DATA_SOURCE_LOGFILE) {
DWORD dwLogType = 0;
pdhStatus = PdhOpenLogW(szDataSource,
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
& dwLogType,
NULL,
0,
NULL,
& hDataSource);
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhEnumMachinesHW(hDataSource, mszMachineList, pcchBufferSize);
if (dwDataSource == DATA_SOURCE_LOGFILE) {
PdhCloseLog(hDataSource, 0);
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumMachinesHA(
IN HLOG hDataSource,
IN LPSTR mszMachineList,
IN LPDWORD pcchBufferSize
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwDataSource = 0;
if (pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwDataSource = DataSourceTypeH(hDataSource);
dwBufferSize = * pcchBufferSize;
if (dwBufferSize > 0) {
if (mszMachineList != NULL) {
mszMachineList[0] = '\0';
mszMachineList[dwBufferSize - 1] = '\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
pdhStatus = PdhiEnumConnectedMachines((LPVOID) mszMachineList, & dwBufferSize, FALSE);
break;
case DATA_SOURCE_WBEM:
pdhStatus = PdhiEnumWbemMachines((LPVOID) mszMachineList, & dwBufferSize, FALSE);
break;
case DATA_SOURCE_LOGFILE:
pdhStatus = PdhiEnumLoggedMachines(hDataSource, (LPVOID) mszMachineList, & dwBufferSize, FALSE);
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX (hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchBufferSize = dwBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumMachinesA(
IN LPCSTR szDataSource,
IN LPSTR mszMachineList,
IN LPDWORD pcchBufferSize
)
/*++
Routine Description:
Builds a MSZ list of the machines currently known by the PDH. This
list includes machines with open sessions as well as those that
are off-line.
Arguments:
IN LPCSTR szDataSource
NULL for current real-time data or the name of a log file
IN LPWSTR szMachineList
A pointer to the buffer to receive the enumerated machine list.
The strings written to this buffer will contain UNICODE chars
IN LPDWORD pcchBufferSize
The size of the buffer referenced by pMachineList in characters
The value of the buffer referenced by this pointer may be 0
if the required size is requested.
Return Value:
ERROR_SUCCESS if this the function completes successfully. a PDH error
value if not.
PDH_MORE_DATA some entries were returned, but there was not enough
room in the buffer to store all entries.
PDH_INVALID_ARGUMENT unable to write to the size buffers or the
data buffer
--*/
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwDataSource = 0;
HLOG hDataSource = H_REALTIME_DATASOURCE;
__try {
if (szDataSource != NULL) {
// test for read access to the name
if (* szDataSource == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL is a valid arg
if (pdhStatus == ERROR_SUCCESS) {
dwDataSource = DataSourceTypeA(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwDataSource == DATA_SOURCE_WBEM) {
hDataSource = H_WBEM_DATASOURCE;
}
else if (dwDataSource == DATA_SOURCE_LOGFILE) {
DWORD dwLogType = 0;
pdhStatus = PdhOpenLogA(szDataSource,
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
& dwLogType,
NULL,
0,
NULL,
& hDataSource);
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhEnumMachinesHA(hDataSource, mszMachineList, pcchBufferSize);
if (dwDataSource == DATA_SOURCE_LOGFILE) {
PdhCloseLog(hDataSource, 0);
}
}
return pdhStatus;
}
#pragma warning ( disable : 4127 )
PDH_FUNCTION
PdhiEnumObjects(
LPWSTR szMachineName,
LPVOID mszObjectList,
LPDWORD pcchBufferSize,
DWORD dwDetailLevel,
BOOL bRefresh,
BOOL bUnicode
)
/*++
Routine Description:
Lists the performance objects found on the specified machine as
a MSZ list.
Arguments:
IN LPWSTR szMachineName
The machine to list objects from
IN LPVOID mszObjectList
a pointer to the buffer to receive the list of performance
objects
IN LPDWORD pcchBufferSize
a pointer to the DWORD containing the size of the mszObjectList
buffer in characters. The characters assumed are determined by
the bUnicode argument.
IN DWORD dwDetailLevel
The detail level to use as a filter of objects. All objects
with a detail level less than or equal to that specified
by this argument will be returned.
IN BOOL bRefresh
TRUE = retrive a new perf. data buffer for this machine before
listing the objects
FALSE = use the currently cached perf data buffer for this
machine to enumerate objects
IN BOOL bUnicode
TRUE = return the listed objects as UNICODE strings
FALSE = return the listed objects as ANSI strings
Return Value:
ERROR_SUCCESS if the function completes successfully. Otherwise a
PDH_ error status if not.
PDH_MORE_DATA is returned when there are more entries available to
return than there is room in the buffer. Some entries may be
returned in the buffer though.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
--*/
{
PPERF_MACHINE pMachine;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD NumTypeDef;
PPERF_OBJECT_TYPE pObjectDef;
DWORD dwRequiredLength = 0;
LPVOID szNextName;
DWORD dwNameLength;
DWORD dwMaximumLength;
LPWSTR szObjNameString;
WCHAR wszNumberString[32];
DWORD dwGmFlags;
DWORD dwLocalDetailLevel;
LPDWORD pdwIndex = NULL;
DWORD dwAlloc = MAX_PATH;
DWORD dwUsed = 0;
DWORD i;
// connect to machine and update data if desired
if (bRefresh) {
dwGmFlags = PDH_GM_UPDATE_PERFDATA;
dwGmFlags |= ((dwDetailLevel & PERF_DETAIL_COSTLY) == PERF_DETAIL_COSTLY) ? PDH_GM_READ_COSTLY_DATA : 0;
}
else {
dwGmFlags = 0;
}
// connect to machine and update data if desired
pMachine = GetMachine(szMachineName, 0, (bRefresh ? PDH_GM_UPDATE_PERFDATA : 0));
dwMaximumLength = * pcchBufferSize;
if (pMachine != NULL) {
if (pMachine->dwStatus == ERROR_SUCCESS) {
if ((dwDetailLevel & PERF_DETAIL_COSTLY) && ! (pMachine->dwMachineFlags & PDHIPM_FLAGS_HAVE_COSTLY)) {
// then get them
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
dwGmFlags = PDH_GM_UPDATE_PERFDATA | PDH_GM_READ_COSTLY_DATA;
pMachine = GetMachine(szMachineName, 0, dwGmFlags);
}
}
}
if (pMachine != NULL) {
// make sure the machine connection is valid
if (pMachine->dwStatus == ERROR_SUCCESS) {
dwRequiredLength = 0;
szNextName = mszObjectList;
// start walking object list
pObjectDef = FirstObject(pMachine->pSystemPerfData);
if ((pMachine->pSystemPerfData->NumObjectTypes > 0) && (pObjectDef != NULL)) {
// convert detail level to the PerfLib detail level
dwLocalDetailLevel = dwDetailLevel & PERF_DETAIL_STANDARD;
// build list
NumTypeDef = 0;
pdwIndex = (LPDWORD) G_ALLOC(dwAlloc * sizeof(DWORD));
if (pdwIndex == NULL) {
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
while (1) {
// only look at entries matching the desired Detail Level
if (pObjectDef->DetailLevel <= dwLocalDetailLevel) {
for (i = 0; i < dwUsed; i ++) {
if (pdwIndex[i] == pObjectDef->ObjectNameTitleIndex) break;
}
if (i == dwUsed) {
if (dwUsed >= dwAlloc) {
LPDWORD pdwTmp = pdwIndex;
dwAlloc += dwAlloc;
pdwIndex = (LPDWORD) G_REALLOC(pdwTmp, dwAlloc * sizeof(DWORD));
if (pdwIndex == NULL) {
G_FREE(pdwTmp);
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
goto Cleanup;
}
}
pdwIndex[dwUsed] = pObjectDef->ObjectNameTitleIndex;
dwUsed ++;
if (pObjectDef->ObjectNameTitleIndex < pMachine->dwLastPerfString) {
szObjNameString = (LPWSTR) PdhiLookupPerfNameByIndex(pMachine,
pObjectDef->ObjectNameTitleIndex);
}
else {
// no match since the index is larger that that found
// in the data buffer
szObjNameString = NULL;
}
if (szObjNameString == NULL) {
// then this object has no string name so use
// the object number
_ltow(pObjectDef->ObjectNameTitleIndex, wszNumberString, 10);
szObjNameString = wszNumberString;
}
// compute length
if (bUnicode) {
dwNameLength = lstrlenW(szObjNameString) + 1;
if (szNextName != NULL && dwRequiredLength + dwNameLength <= dwMaximumLength) {
StringCchCopyW((LPWSTR) szNextName,
dwMaximumLength - dwRequiredLength,
szObjNameString);
(LPBYTE) szNextName += (dwNameLength - 1) * sizeof(WCHAR);
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
else {
dwNameLength = (dwRequiredLength <= dwMaximumLength)
? (dwMaximumLength - dwRequiredLength) : (0);
pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
szObjNameString,
(LPSTR) szNextName,
& dwNameLength);
if (pdhStatus == ERROR_SUCCESS) {
(LPBYTE) szNextName += sizeof(CHAR) * dwNameLength;
}
}
dwRequiredLength += dwNameLength;
}
}
// go to next object in the data block
NumTypeDef ++;
if (NumTypeDef >= pMachine->pSystemPerfData->NumObjectTypes) {
// that's enough so break out of the loop
break;
}
else {
// goto the next one and make sure it's valid
pObjectDef = NextObject(pMachine->pSystemPerfData, pObjectDef); // get next
//make sure next object is legit
if (pObjectDef != NULL) {
if (pObjectDef->TotalByteLength == 0) {
// 0-length object buffer returned
break;
}
}
else {
// and continue
break;
}
}
}
// add MSZ terminator to string
++ dwRequiredLength; // add the size of the MSZ char
if (pdhStatus == ERROR_SUCCESS) {
if (szNextName != NULL && dwRequiredLength <= dwMaximumLength) {
if (bUnicode) {
* ((LPWSTR) szNextName)++ = L'\0';
}
else {
* ((LPSTR)szNextName) ++ = '\0';
}
// make sure pointers and lengths stay in sync
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
}
else {
// no objects found for this machine
dwRequiredLength = 2;
if (szNextName != NULL && dwRequiredLength <= dwMaximumLength) {
if (bUnicode) {
* ((LPWSTR) szNextName) ++ = L'\0';
* ((LPWSTR) szNextName) ++ = L'\0';
} else {
* ((LPSTR) szNextName) ++ = '\0';
* ((LPSTR) szNextName) ++ = '\0';
}
}
else {
pdhStatus = ERROR_MORE_DATA;
} // else this is just a size request
}
// return length info
}
else {
pdhStatus = pMachine->dwStatus; // computer off line
}
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
}
else {
pdhStatus = GetLastError(); // computer not found
}
Cleanup:
G_FREE(pdwIndex);
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchBufferSize = dwRequiredLength;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = GetExceptionCode();
}
}
return pdhStatus;
}
#pragma warning ( default : 4127 )
PDH_FUNCTION
PdhEnumObjectsHW(
IN HLOG hDataSource,
IN LPCWSTR szMachineName,
IN LPWSTR mszObjectList,
IN LPDWORD pcchBufferSize,
IN DWORD dwDetailLevel,
IN BOOL bRefresh
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwBufferSize = 0;
DWORD dwDataSource = 0;
if (pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwDataSource = DataSourceTypeH(hDataSource);
dwBufferSize = * pcchBufferSize;
if (szMachineName != NULL) {
if (* szMachineName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwBufferSize > 0) {
if (mszObjectList != NULL) {
mszObjectList[0] = L'\0';
mszObjectList[dwBufferSize - 1] = L'\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
pdhStatus = PdhiEnumObjects((LPWSTR) szMachineName,
(LPVOID) mszObjectList,
& dwBufferSize,
dwDetailLevel,
bRefresh,
TRUE);
break;
case DATA_SOURCE_WBEM:
pdhStatus = PdhiEnumWbemObjects((LPWSTR) szMachineName,
(LPVOID) mszObjectList,
& dwBufferSize,
dwDetailLevel, // not used
bRefresh,
TRUE);
break;
case DATA_SOURCE_LOGFILE:
pdhStatus = PdhiEnumLoggedObjects(hDataSource,
(LPWSTR) szMachineName,
(LPVOID) mszObjectList,
& dwBufferSize,
dwDetailLevel,
bRefresh,
TRUE);
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX (hPdhDataMutex);
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchBufferSize = dwBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumObjectsW(
IN LPCWSTR szDataSource,
IN LPCWSTR szMachineName,
IN LPWSTR mszObjectList,
IN LPDWORD pcchBufferSize,
IN DWORD dwDetailLevel,
IN BOOL bRefresh
)
/*++
Routine Description:
Lists the performance objects found on the specified machine as
a MSZ UNICODE string list.
Arguments:
IN LPCWSTR szDataSource
NULL for current real-time data or the name of a log file
IN LPCWSTR szMachineName
The machine to list objects from
IN LPWSTR mszObjectList
a pointer to the buffer to receive the list of performance
objects
IN LPDWORD pcchBufferSize
a pointer to the DWORD containing the size of the mszObjectList
buffer in characters.
IN DWORD dwDetailLevel
The detail level to use as a filter of objects. All objects
with a detail level less than or equal to that specified
by this argument will be returned.
IN BOOL bRefresh
TRUE = retrive a new perf. data buffer for this machine before
listing the objects
FALSE = use the currently cached perf data buffer for this
machine to enumerate objects
Return Value:
ERROR_SUCCESS if the function completes successfully. Otherwise a
PDH_ error status if not.
PDH_MORE_DATA is returned when there are more entries available to
return than there is room in the buffer. Some entries may be
returned in the buffer though.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
PDH_INVALID_ARGUMENT is returned if a required argument is not provided
or a reserved argument is not NULL
--*/
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwDataSource = 0;
HLOG hDataSource = H_REALTIME_DATASOURCE;
__try {
if (szDataSource != NULL) {
// test for read access to the name
if (* szDataSource == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL is a valid arg
if (pdhStatus == ERROR_SUCCESS) {
dwDataSource = DataSourceTypeW(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwDataSource == DATA_SOURCE_WBEM) {
hDataSource = H_WBEM_DATASOURCE;
}
else if (dwDataSource == DATA_SOURCE_LOGFILE) {
DWORD dwLogType = 0;
pdhStatus = PdhOpenLogW(szDataSource,
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
& dwLogType,
NULL,
0,
NULL,
& hDataSource);
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhEnumObjectsHW(hDataSource,
szMachineName,
mszObjectList,
pcchBufferSize,
dwDetailLevel,
bRefresh);
if (dwDataSource == DATA_SOURCE_LOGFILE) {
PdhCloseLog(hDataSource, 0);
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumObjectsHA(
IN HLOG hDataSource,
IN LPCSTR szMachineName,
IN LPSTR mszObjectList,
IN LPDWORD pcchBufferSize,
IN DWORD dwDetailLevel,
IN BOOL bRefresh
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LPWSTR szWideName;
DWORD dwDataSource = 0;
DWORD dwBufferSize = 0;
if (pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwDataSource = DataSourceTypeH(hDataSource);
if (szMachineName != NULL) {
// test buffer access
if (* szMachineName == '\0') {
// null machine names are not permitted
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwBufferSize = * pcchBufferSize;
if (dwBufferSize > 0) {
if (mszObjectList != NULL) {
mszObjectList[0] = '\0';
mszObjectList[dwBufferSize - 1] = '\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
if (szMachineName != NULL) {
szWideName = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szMachineName);
}
else {
szWideName = NULL;
}
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
pdhStatus = PdhiEnumObjects(szWideName,
(LPVOID) mszObjectList,
& dwBufferSize,
dwDetailLevel,
bRefresh,
FALSE);
break;
case DATA_SOURCE_WBEM:
pdhStatus = PdhiEnumWbemObjects((LPWSTR) szWideName,
(LPVOID) mszObjectList,
& dwBufferSize,
dwDetailLevel, // not used
bRefresh,
FALSE);
break;
case DATA_SOURCE_LOGFILE:
pdhStatus = PdhiEnumLoggedObjects(hDataSource,
(LPWSTR) szWideName,
(LPVOID) mszObjectList,
& dwBufferSize,
dwDetailLevel,
bRefresh,
FALSE);
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
* pcchBufferSize = dwBufferSize;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX (hPdhDataMutex);
G_FREE(szWideName);
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumObjectsA(
IN LPCSTR szDataSource,
IN LPCSTR szMachineName,
IN LPSTR mszObjectList,
IN LPDWORD pcchBufferSize,
IN DWORD dwDetailLevel,
IN BOOL bRefresh
)
/*++
Routine Description:
Lists the performance objects found on the specified machine as
a MSZ ANSI string list.
Arguments:
IN LPCSTR szDataSource
NULL for current real-time data or the name of a log file
IN LPCSTR szMachineName
The machine to list objects from
IN LPSTR mszObjectList
a pointer to the buffer to receive the list of performance
objects
IN LPDWORD pcchBufferSize
a pointer to the DWORD containing the size of the mszObjectList
buffer in characters.
IN DWORD dwDetailLevel
The detail level to use as a filter of objects. All objects
with a detail level less than or equal to that specified
by this argument will be returned.
IN BOOL bRefresh
TRUE = retrive a new perf. data buffer for this machine before
listing the objects
FALSE = use the currently cached perf data buffer for this
machine to enumerate objects
Return Value:
ERROR_SUCCESS if the function completes successfully. Otherwise a
PDH_ error status if not.
PDH_MORE_DATA is returned when there are more entries available to
return than there is room in the buffer. Some entries may be
returned in the buffer though.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
PDH_INVALID_ARGUMENT is returned if a required argument is not provided
or a reserved argument is not NULL
--*/
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HLOG hDataSource = H_REALTIME_DATASOURCE;
DWORD dwDataSource = 0;
__try {
if (szDataSource != NULL) {
// test for read access to the name
if (* szDataSource == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL is a valid arg
if (pdhStatus == ERROR_SUCCESS) {
dwDataSource = DataSourceTypeA(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwDataSource == DATA_SOURCE_WBEM) {
hDataSource = H_WBEM_DATASOURCE;
}
else if (dwDataSource == DATA_SOURCE_LOGFILE) {
DWORD dwLogType = 0;
pdhStatus = PdhOpenLogA(szDataSource,
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
& dwLogType,
NULL,
0,
NULL,
& hDataSource);
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhEnumObjectsHA(hDataSource,
szMachineName,
mszObjectList,
pcchBufferSize,
dwDetailLevel,
bRefresh);
if (dwDataSource == DATA_SOURCE_LOGFILE) {
PdhCloseLog(hDataSource, 0);
}
}
return pdhStatus;
}
STATIC_PDH_FUNCTION
PdhiEnumObjectItems(
LPCWSTR szMachineName,
LPCWSTR szObjectName,
LPVOID mszCounterList,
LPDWORD pcchCounterListLength,
LPVOID mszInstanceList,
LPDWORD pcchInstanceListLength,
DWORD dwDetailLevel,
DWORD dwFlags,
BOOL bUnicode
)
/*++
Routine Description:
Lists the items found in the specified performance object on the
specified machine. Thie includes the performance counters and,
if supported by the object, the object instances.
Arguments:
IN LPCWSTR szMachineName
The name of the machine to list the objects
IN LPCWSTR szObjectName
the name of the object to list items from
IN LPVOID mszCounterList
pointer to the buffer that will receive the list of counters
provided by this object. This argument may be NULL if
the value of pcchCounterLIstLength is 0.
IN LPDWORD pcchCounterListLength
pointer to a DWORD that contains the size in characters
of the buffer referenced by mszCounterList. The characters
assumed are defined by bUnicode.
IN LPVOID mszInstanceList
pointer to the buffer that will receive the list of instances
of the specified performance object. This argument may be
NULL if the value of pcchInstanceListLength is 0.
IN LPDWORD pcchInstanceListLength
pointer to the DWORD containing the size, in characters, of
the buffer referenced by the mszInstanceList argument. If the
value in this DWORD is 0, then no data will be written to the
buffer, only the required size will be returned.
If the value returned is 0, then this object does not
return instances, if the value returned is 2, then the
object supports instances, but does not currently have
any instances to return (2 = the size of an MSZ list in
characters)
IN DWORD dwDetailLevel
The detail level of the performance items to return. All items
that are of the specified detail level or less will be
returned.
IN DWORD dwFlags
Not Used, must be 0.
IN BOOL bUnicode
TRUE = UNICODE characters will be written to the pMachineList
buffer
FALSE = ANSI characters will be writtn to the pMachinList buffer
Return Value:
ERROR_SUCCESS if the function completes successfully. Otherwise a
PDH_ error status if not.
PDH_MORE_DATA is returned when there are more entries available to
return than there is room in the buffer. Some entries may be
returned in the buffer though.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
PDH_CSTATUS_NO_OBJECT is returned if the specified object could
not be found on the specified machine.
--*/
{
PPERF_MACHINE pMachine = NULL;
DWORD dwObjectId = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PDH_STATUS pdhCtrStatus = ERROR_SUCCESS;
PDH_STATUS pdhInstStatus = ERROR_SUCCESS;
DWORD DefNdx;
PPERF_OBJECT_TYPE pObjectDef;
PPERF_COUNTER_DEFINITION pCounterDef;
PPERF_INSTANCE_DEFINITION pInstanceDef;
DWORD dwReqCounterLength = 0;
DWORD dwReqInstanceLength = 0;
LPVOID szNextName;
DWORD dwNameLength;
LPWSTR szInstanceName = NULL;
DWORD dwInstanceName;
WCHAR szNumberString[32];
DWORD dwMaxInstanceLength;
DWORD dwMaxCounterLength;
LPWSTR szCounterName;
DWORD dwGmFlags;
DBG_UNREFERENCED_PARAMETER(dwFlags);
pMachine = GetMachine((LPWSTR) szMachineName, 0, PDH_GM_UPDATE_PERFNAME_ONLY);
if (pMachine != NULL) {
if (pMachine->dwStatus == ERROR_SUCCESS) {
dwObjectId = GetObjectId(pMachine, (LPWSTR) szObjectName, NULL);
}
if (dwObjectId == (DWORD) -1) {
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
pMachine = NULL;
pdhStatus = PDH_CSTATUS_NO_OBJECT;
}
}
if (pMachine != NULL) {
if ((dwDetailLevel & PERF_DETAIL_COSTLY) && ! (pMachine->dwMachineFlags & PDHIPM_FLAGS_HAVE_COSTLY)) {
// then get them
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
dwGmFlags = PDH_GM_UPDATE_PERFDATA | PDH_GM_READ_COSTLY_DATA;
pMachine = GetMachine((LPWSTR) szMachineName, dwObjectId, dwGmFlags);
}
}
if (pMachine != NULL) {
dwMaxCounterLength = * pcchCounterListLength;
dwMaxInstanceLength = * pcchInstanceListLength;
// make sure the machine connection is valid
if (pMachine->dwStatus == ERROR_SUCCESS) {
pObjectDef = GetObjectDefByName(pMachine->pSystemPerfData,
pMachine->dwLastPerfString,
pMachine->szPerfStrings,
szObjectName);
if (pObjectDef == NULL) {
DWORD dwObjectTitle = wcstoul(szObjectName, NULL, 10);
if (dwObjectTitle != 0) {
pObjectDef = GetObjectDefByTitleIndex(pMachine->pSystemPerfData, dwObjectTitle);
}
}
if (pObjectDef != NULL) {
// add up counter name sizes
pCounterDef = FirstCounter(pObjectDef);
szNextName = mszCounterList;
for (DefNdx = 0; pCounterDef != NULL && DefNdx < pObjectDef->NumCounters; DefNdx++) {
if (! ((pCounterDef->CounterType & PERF_DISPLAY_NOSHOW) &&
// this is a hack because this type is not defined correctly
(pCounterDef->CounterType != PERF_AVERAGE_BULK)) &&
(pCounterDef->DetailLevel <= dwDetailLevel)) {
// then this is a visible counter so get its name.
if ((pCounterDef->CounterNameTitleIndex > 0) &&
(pCounterDef->CounterNameTitleIndex < pMachine->dwLastPerfString)) {
// look up name of each object & store size
szCounterName = (LPWSTR) PdhiLookupPerfNameByIndex(pMachine,
pCounterDef->CounterNameTitleIndex);
}
else {
// no matching string found for this index
szCounterName = NULL;
}
if (szCounterName == NULL) {
// then use the index numbe for lack of a better
// string to use
_ltow(pCounterDef->CounterNameTitleIndex, szNumberString, 10);
szCounterName = szNumberString;
}
if (bUnicode) {
dwNameLength = lstrlenW(szCounterName) + 1;
if (szNextName != NULL
&& (dwReqCounterLength + dwNameLength) <= dwMaxCounterLength) {
StringCchCopyW((LPWSTR) szNextName, dwNameLength, szCounterName);
(LPBYTE) szNextName += sizeof(WCHAR) * (dwNameLength - 1);
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
pdhCtrStatus = PDH_MORE_DATA;
}
}
else {
dwNameLength = (dwReqCounterLength <= dwMaxCounterLength)
? (dwMaxCounterLength - dwReqCounterLength)
: (0);
pdhCtrStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
szCounterName,
(LPSTR) szNextName,
& dwNameLength);
if (pdhCtrStatus == ERROR_SUCCESS) {
(LPBYTE) szNextName += sizeof(CHAR) * dwNameLength;
}
}
dwReqCounterLength += dwNameLength;
}
else {
// this counter is not displayed either because
// it's hidden (e.g. the 2nd part of a 2 part counter
// or it's the wrong detail level
}
pCounterDef = NextCounter(pObjectDef, pCounterDef); // get next
}
if (DefNdx == 0) {
// no counters found so at least one NULL is required
dwReqCounterLength += 1;
// see if this string will fit
if (dwReqCounterLength <= dwMaxCounterLength) {
if (bUnicode) {
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
* ((LPSTR) szNextName) ++ = '\0';
}
}
else {
// more space needed than was reported
pdhCtrStatus = PDH_MORE_DATA;
}
}
// add terminating NULL
dwReqCounterLength += 1;
// see if this string will fit
if (dwReqCounterLength <= dwMaxCounterLength) {
if (bUnicode) {
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
* ((LPSTR) szNextName) ++ = '\0';
}
}
else {
// more space needed than was reported
pdhCtrStatus = PDH_MORE_DATA;
}
// do instances now.
szNextName = mszInstanceList;
// add up instance name sizes
if (pObjectDef->NumInstances != PERF_NO_INSTANCES) {
if (pObjectDef->DetailLevel <= dwDetailLevel && pObjectDef->NumInstances > 0) {
dwInstanceName = SMALL_BUFFER_SIZE;
szInstanceName = G_ALLOC(dwInstanceName * sizeof(WCHAR));
if (szInstanceName == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else {
// the object HAS instances and is of the
// approrpriate detail level, so list them
pInstanceDef = FirstInstance(pObjectDef);
for (DefNdx = 0; pInstanceDef != NULL && DefNdx < (DWORD)pObjectDef->NumInstances; DefNdx++) {
dwNameLength = GetFullInstanceNameStr(pMachine->pSystemPerfData,
pObjectDef,
pInstanceDef,
szInstanceName,
dwInstanceName);
while (pdhStatus == ERROR_SUCCESS && dwNameLength > dwInstanceName) {
G_FREE(szInstanceName);
dwInstanceName = QWORD_MULTIPLE(dwNameLength);
szInstanceName = G_ALLOC(dwInstanceName * sizeof(WCHAR));
if (szInstanceName != NULL) {
dwNameLength = GetFullInstanceNameStr(pMachine->pSystemPerfData,
pObjectDef,
pInstanceDef,
szInstanceName,
dwInstanceName);
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
if (pdhStatus != ERROR_SUCCESS) break;
if (dwNameLength > 0) {
if (bUnicode) {
// add length of this string + it's null
dwNameLength += 1;
if (szNextName != NULL
&& dwReqInstanceLength + dwNameLength <= dwMaxInstanceLength) {
StringCchCopyW((LPWSTR) szNextName, dwNameLength, szInstanceName);
(LPBYTE) szNextName += sizeof(WCHAR) * (dwNameLength - 1);
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
pdhInstStatus = PDH_MORE_DATA;
}
}
else {
dwNameLength = (dwReqInstanceLength <= dwMaxInstanceLength)
? (dwMaxInstanceLength - dwReqInstanceLength) : (0);
pdhInstStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
szInstanceName,
(LPSTR) szNextName,
& dwNameLength);
if (pdhInstStatus == ERROR_SUCCESS) {
(LPBYTE) szNextName += sizeof(CHAR) * dwNameLength;
}
}
dwReqInstanceLength += dwNameLength;
}
// go to next instance of this object
pInstanceDef = NextInstance(pObjectDef, pInstanceDef); // get next
}
G_FREE(szInstanceName);
}
// add the terminating NULL char
dwReqInstanceLength += 1;
if (dwMaxInstanceLength > 0) {
// see if this string will fit
if (dwReqInstanceLength <= dwMaxInstanceLength) {
if (bUnicode) {
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
* ((LPSTR) szNextName) ++ = '\0';
}
}
else {
// more space needed than was reported
pdhInstStatus = PDH_MORE_DATA;
}
}
}
else {
// there are no instances present, but the object does
// support instances so return a zero length MSZ (which
// actually contains 2 NULL chars
dwReqInstanceLength = 2;
// see if this string will fit
if (dwReqInstanceLength <= dwMaxInstanceLength) {
if (bUnicode) {
* ((LPWSTR) szNextName) ++ = L'\0';
* ((LPWSTR) szNextName) ++ = L'\0';
}
else {
* ((LPSTR) szNextName) ++ = '\0';
* ((LPSTR) szNextName) ++ = '\0';
}
}
else {
// more space needed than was reported
pdhInstStatus = PDH_MORE_DATA;
}
}
}
else {
// the object has no instances and never will
// so return a 0 length and NO string
dwReqInstanceLength = 0;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = (pdhCtrStatus == ERROR_SUCCESS) ? (pdhInstStatus) : (pdhCtrStatus);
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
* pcchCounterListLength = dwReqCounterLength;
* pcchInstanceListLength = dwReqInstanceLength;
}
}
else {
// object not found on this machine
pdhStatus = PDH_CSTATUS_NO_OBJECT;
}
}
else {
// machine is off line
pdhStatus = pMachine->dwStatus;
}
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
}
else if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = GetLastError();
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumObjectItemsHW(
IN HLOG hDataSource,
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPWSTR mszCounterList,
IN LPDWORD pcchCounterListLength,
IN LPWSTR mszInstanceList,
IN LPDWORD pcchInstanceListLength,
IN DWORD dwDetailLevel,
IN DWORD dwFlags
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwCBufferSize = 0;
DWORD dwIBufferSize = 0;
DWORD dwDataSource = 0;
if (pcchCounterListLength == NULL || pcchInstanceListLength == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwDataSource = DataSourceTypeH(hDataSource);
dwCBufferSize = * pcchCounterListLength;
dwIBufferSize = * pcchInstanceListLength;
if (szMachineName != NULL) {
if (* szMachineName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (szObjectName != NULL) {
if (* szObjectName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szObjectName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwCBufferSize > 0) {
if (mszCounterList != NULL) {
mszCounterList[0] = L'\0';
mszCounterList[dwCBufferSize - 1] = L'\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwIBufferSize > 0) {
if (mszInstanceList != NULL) {
mszInstanceList[0] = L'\0';
mszInstanceList[dwIBufferSize -1] = L'\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (dwFlags != 0L) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
pdhStatus = PdhiEnumObjectItems((LPWSTR) szMachineName,
szObjectName,
(LPVOID) mszCounterList,
& dwCBufferSize,
(LPVOID) mszInstanceList,
& dwIBufferSize,
dwDetailLevel,
dwFlags,
TRUE);
break;
case DATA_SOURCE_WBEM:
pdhStatus = PdhiEnumWbemObjectItems((LPWSTR) szMachineName,
szObjectName,
(LPVOID) mszCounterList,
& dwCBufferSize,
(LPVOID) mszInstanceList,
& dwIBufferSize,
dwDetailLevel,
dwFlags,
TRUE);
break;
case DATA_SOURCE_LOGFILE:
pdhStatus = PdhiEnumLoggedObjectItems(hDataSource,
(LPWSTR) szMachineName,
szObjectName,
(LPVOID) mszCounterList,
& dwCBufferSize,
(LPVOID) mszInstanceList,
& dwIBufferSize,
dwDetailLevel,
dwFlags,
TRUE);
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX(hPdhDataMutex);
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchCounterListLength = dwCBufferSize;
* pcchInstanceListLength = dwIBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumObjectItemsW(
IN LPCWSTR szDataSource,
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPWSTR mszCounterList,
IN LPDWORD pcchCounterListLength,
IN LPWSTR mszInstanceList,
IN LPDWORD pcchInstanceListLength,
IN DWORD dwDetailLevel,
IN DWORD dwFlags
)
/*++
Routine Description:
Lists the items found in the specified performance object on the
specified machine. Thie includes the performance counters and,
if supported by the object, the object instances.
Arguments:
IN LPCWSTR szDataSource
NULL for current real-time data or the name of a log file
IN LPCWSTR szMachineName
The name of the machine to list the objects
IN LPCWSTR szObjectName
the name of the object to list items from
IN LPWSTR mszCounterList
pointer to the buffer that will receive the list of counters
provided by this object. This argument may be NULL if
the value of pcchCounterLIstLength is 0.
IN LPDWORD pcchCounterListLength
pointer to a DWORD that contains the size in characters
of the buffer referenced by mszCounterList. The characters
assumed are defined by bUnicode.
IN LPWSTR mszInstanceList
pointer to the buffer that will receive the list of instances
of the specified performance object. This argument may be
NULL if the value of pcchInstanceListLength is 0.
IN LPDWORD pcchInstanceListLength
pointer to the DWORD containing the size, in characters, of
the buffer referenced by the mszInstanceList argument. If the
value in this DWORD is 0, then no data will be written to the
buffer, only the required size will be returned.
If the value returned is 0, then this object does not
return instances, if the value returned is 2, then the
object supports instances, but does not currently have
any instances to return (2 = the size of an MSZ list in
characters)
IN DWORD dwDetailLevel
The detail level of the performance items to return. All items
that are of the specified detail level or less will be
returned.
IN DWORD dwFlags
Not Used, must be 0.
Return Value:
ERROR_SUCCESS if the function completes successfully. Otherwise a
PDH_ error status if not.
PDH_MORE_DATA is returned when there are more entries available to
return than there is room in the buffer. Some entries may be
returned in the buffer though.
PDH_INVALID_ARGUMENT a required argument is not correct or reserved
argument is not 0 or NULL.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
PDH_CSTATUS_NO_OBJECT is returned if the specified object could
not be found on the specified machine.
--*/
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HLOG hDataSource = H_REALTIME_DATASOURCE;
DWORD dwDataSource = 0;
__try {
if (szDataSource != NULL) {
// test for read access to the name
if (* szDataSource == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL is a valid arg
if (pdhStatus == ERROR_SUCCESS) {
dwDataSource = DataSourceTypeW(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwDataSource == DATA_SOURCE_WBEM) {
hDataSource = H_WBEM_DATASOURCE;
}
else if (dwDataSource == DATA_SOURCE_LOGFILE) {
DWORD dwLogType = 0;
pdhStatus = PdhOpenLogW(szDataSource,
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
& dwLogType,
NULL,
0,
NULL,
& hDataSource);
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhEnumObjectItemsHW(hDataSource,
szMachineName,
szObjectName,
mszCounterList,
pcchCounterListLength,
mszInstanceList,
pcchInstanceListLength,
dwDetailLevel,
dwFlags);
if (dwDataSource == DATA_SOURCE_LOGFILE) {
PdhCloseLog(hDataSource, 0);
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumObjectItemsHA(
IN HLOG hDataSource,
IN LPCSTR szMachineName,
IN LPCSTR szObjectName,
IN LPSTR mszCounterList,
IN LPDWORD pcchCounterListLength,
IN LPSTR mszInstanceList,
IN LPDWORD pcchInstanceListLength,
IN DWORD dwDetailLevel,
IN DWORD dwFlags
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LPWSTR szWideMachineName = NULL;
LPWSTR szWideObjectName = NULL;
DWORD dwDataSource = 0;
DWORD dwCBufferSize = 0;
DWORD dwIBufferSize = 0;
if ((pcchCounterListLength == NULL) || (pcchInstanceListLength == NULL)) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwDataSource = DataSourceTypeH(hDataSource);
dwCBufferSize = * pcchCounterListLength;
dwIBufferSize = * pcchInstanceListLength;
if (szMachineName != NULL) {
if (* szMachineName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (szObjectName != NULL) {
if (* szObjectName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szObjectName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else {
// object cannot be NULL
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwCBufferSize > 0) {
if (mszCounterList != NULL) {
mszCounterList[0] = '\0';
mszCounterList[dwCBufferSize - 1] = '\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwIBufferSize > 0) {
if (mszInstanceList != NULL) {
mszInstanceList[0] = '\0';
mszInstanceList[dwIBufferSize - 1] = '\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (dwFlags != 0L) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
if (szMachineName != NULL) {
szWideMachineName = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szMachineName);
}
else {
szWideMachineName = NULL;
}
if (szObjectName != NULL) {
szWideObjectName = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szObjectName);
}
else {
szWideObjectName = NULL;
}
if (pdhStatus == ERROR_SUCCESS) {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
pdhStatus = PdhiEnumObjectItems(szWideMachineName,
szWideObjectName,
(LPVOID) mszCounterList,
& dwCBufferSize,
(LPVOID) mszInstanceList,
& dwIBufferSize,
dwDetailLevel,
dwFlags,
FALSE);
break;
case DATA_SOURCE_WBEM:
pdhStatus = PdhiEnumWbemObjectItems((LPWSTR) szWideMachineName,
szWideObjectName,
(LPVOID) mszCounterList,
& dwCBufferSize,
(LPVOID) mszInstanceList,
& dwIBufferSize,
dwDetailLevel,
dwFlags,
FALSE);
break;
case DATA_SOURCE_LOGFILE:
pdhStatus = PdhiEnumLoggedObjectItems(hDataSource,
szWideMachineName,
szWideObjectName,
(LPVOID) mszCounterList,
& dwCBufferSize,
(LPVOID) mszInstanceList,
& dwIBufferSize,
dwDetailLevel,
dwFlags,
FALSE);
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX(hPdhDataMutex);
G_FREE(szWideMachineName);
G_FREE(szWideObjectName);
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchCounterListLength = dwCBufferSize;
* pcchInstanceListLength = dwIBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhEnumObjectItemsA(
IN LPCSTR szDataSource,
IN LPCSTR szMachineName,
IN LPCSTR szObjectName,
IN LPSTR mszCounterList,
IN LPDWORD pcchCounterListLength,
IN LPSTR mszInstanceList,
IN LPDWORD pcchInstanceListLength,
IN DWORD dwDetailLevel,
IN DWORD dwFlags
)
/*++
Routine Description:
Lists the items found in the specified performance object on the
specified machine. Thie includes the performance counters and,
if supported by the object, the object instances.
Arguments:
IN LPCSTR szDataSource
NULL for current real-time data or the name of a log file
IN LPCSTR szMachineName
The name of the machine to list the objects
IN LPCSTR szObjectName
the name of the object to list items from
IN LPSTR mszCounterList
pointer to the buffer that will receive the list of counters
provided by this object. This argument may be NULL if
the value of pcchCounterLIstLength is 0.
IN LPDWORD pcchCounterListLength
pointer to a DWORD that contains the size in characters
of the buffer referenced by mszCounterList. The characters
assumed are defined by bUnicode.
IN LPSTR mszInstanceList
pointer to the buffer that will receive the list of instances
of the specified performance object. This argument may be
NULL if the value of pcchInstanceListLength is 0.
IN LPDWORD pcchInstanceListLength
pointer to the DWORD containing the size, in characters, of
the buffer referenced by the mszInstanceList argument. If the
value in this DWORD is 0, then no data will be written to the
buffer, only the required size will be returned.
If the value returned is 0, then this object does not
return instances, if the value returned is 2, then the
object supports instances, but does not currently have
any instances to return (2 = the size of an MSZ list in
characters)
IN DWORD dwDetailLevel
The detail level of the performance items to return. All items
that are of the specified detail level or less will be
returned.
IN DWORD dwFlags
Not Used, must be 0.
Return Value:
ERROR_SUCCESS if the function completes successfully. Otherwise a
PDH_ error status if not.
PDH_MORE_DATA is returned when there are more entries available to
return than there is room in the buffer. Some entries may be
returned in the buffer though.
PDH_INVALID_ARGUMENT a required argument is not correct or reserved
argument is not 0 or NULL.
PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
buffer could not be allocated.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
PDH_CSTATUS_NO_OBJECT is returned if the specified object could
not be found on the specified machine.
--*/
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HLOG hDataSource = H_REALTIME_DATASOURCE;
DWORD dwDataSource = 0;
__try {
if (szDataSource != NULL) {
// test for read access to the name
if (* szDataSource == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL is a valid arg
if (pdhStatus == ERROR_SUCCESS) {
dwDataSource = DataSourceTypeA(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwDataSource == DATA_SOURCE_WBEM) {
hDataSource = H_WBEM_DATASOURCE;
}
else if (dwDataSource == DATA_SOURCE_LOGFILE) {
DWORD dwLogType = 0;
pdhStatus = PdhOpenLogA(szDataSource,
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
& dwLogType,
NULL,
0,
NULL,
& hDataSource);
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhEnumObjectItemsHA(hDataSource,
szMachineName,
szObjectName,
mszCounterList,
pcchCounterListLength,
mszInstanceList,
pcchInstanceListLength,
dwDetailLevel,
dwFlags);
if (dwDataSource == DATA_SOURCE_LOGFILE) {
PdhCloseLog(hDataSource, 0);
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhMakeCounterPathW(
IN PPDH_COUNTER_PATH_ELEMENTS_W pCounterPathElements,
IN LPWSTR szFullPathBuffer,
IN LPDWORD pcchBufferSize,
IN DWORD dwFlags
)
/*++
Routine Description:
Constructs a counter path using the elemeents defined in the
pCounterPathElements structure and returns the path string
in the buffer provided by the caller. The resulting path
is not validated.
Arguments:
IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements
The pointer to the structure containing the
individual counter path fields that are to be
assembled in to a path string
IN LPWSTR szFullPathBuffer
The buffer to receive the path string. This value
may be NULL if the value of the DWORD pointed to
by pcchBufferSize is 0 indicating this is just a
request for the required buffer size.
IN LPDWORD pcchBufferSize
The pointer to the DWORD containing the size
of the string buffer in characters. On return
it contains the size of the buffer used in
characters (including the terminating NULL char).
If the value is 0 on entry then no data will be
written to the buffer, but the required size will
still be returned.
IN DWORD dwFlags
if 0, then return the path as a REGISTRY path items
if PDH_PATH_WBEM_RESULT then return the items in WBEM format
if PDH_PATH_WBEM_INPUT then assume the input is in WBEM format
Return Value:
ERROR_SUCCESS if the function completes successfully, otherwise a
PDH error is returned.
PDH_INVALID_ARGUMENT is returned when one of the arguments passed
by the caller is incorrect or not accesible.
--*/
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
double dIndex;
double dLen;
DWORD dwSizeRequired = 0;
LPWSTR szNextChar;
DWORD dwMaxSize;
DWORD dwLocalBufferSize = 0;
if (pCounterPathElements == NULL || pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
// test access to the input structure
if (pCounterPathElements->szMachineName != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szMachineName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szObjectName != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szObjectName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else {
//NULL is NOT ok for this field
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szInstanceName != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szInstanceName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szParentInstance != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szParentInstance == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szCounterName != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szCounterName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else {
//NULL is NOT ok for this field
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
// test the output buffers
if (pdhStatus == ERROR_SUCCESS) {
if (pcchBufferSize != NULL) {
dwLocalBufferSize = * pcchBufferSize;
}
else {
// NULL is NOT OK
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if ((pdhStatus == ERROR_SUCCESS) && (szFullPathBuffer == NULL && dwLocalBufferSize > 0)) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwLocalBufferSize > 0) {
if (szFullPathBuffer != NULL) {
szFullPathBuffer[0] = L'\0';
szFullPathBuffer[dwLocalBufferSize - 1] = L'\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
if (dwFlags == 0) {
// then process as:
// registry path elements in
// registry path out
dwMaxSize = dwLocalBufferSize;
if (pCounterPathElements->szMachineName != NULL) {
dwSizeRequired = lstrlenW(pCounterPathElements->szMachineName);
// compare the first two words of the machine name
// to see if the double backslash is already present in the string
if (* ((LPDWORD) (pCounterPathElements->szMachineName)) != * ((LPDWORD) (cszDoubleBackSlash))) {
// double backslash not found
dwSizeRequired += 2; // to include the backslashes
}
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
if (* ((LPDWORD) (pCounterPathElements->szMachineName)) != * ((LPDWORD) (cszDoubleBackSlash))) {
// double backslash not found
StringCchCopyW(szFullPathBuffer, dwMaxSize, cszDoubleBackSlash);
StringCchCatW(szFullPathBuffer, dwMaxSize, pCounterPathElements->szMachineName);
}
else {
StringCchCopyW(szFullPathBuffer, dwMaxSize, pCounterPathElements->szMachineName);
}
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
dwSizeRequired += 1; // for delimiting slash
dwSizeRequired += lstrlenW(pCounterPathElements->szObjectName);
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatW(szFullPathBuffer, dwMaxSize, cszBackSlash);
StringCchCatW(szFullPathBuffer, dwMaxSize, pCounterPathElements->szObjectName);
}
else {
pdhStatus = PDH_MORE_DATA;
}
if (pCounterPathElements->szInstanceName != NULL) {
dwSizeRequired += 1; // for delimiting left paren
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatW(szFullPathBuffer, dwMaxSize, cszLeftParen);
}
else {
pdhStatus = PDH_MORE_DATA;
}
if (lstrcmpiW(pCounterPathElements->szInstanceName, cszSplat) != 0
&& pCounterPathElements->szParentInstance != NULL) {
dwSizeRequired += (lstrlenW(pCounterPathElements->szParentInstance) + 1);
// extra 1 for delimiting slash
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatW(szFullPathBuffer, dwMaxSize, pCounterPathElements->szParentInstance);
StringCchCatW(szFullPathBuffer, dwMaxSize, cszSlash);
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
dwSizeRequired += lstrlenW(pCounterPathElements->szInstanceName);
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatW(szFullPathBuffer, dwMaxSize, pCounterPathElements->szInstanceName);
}
else {
pdhStatus = PDH_MORE_DATA;
}
if (lstrcmpiW(pCounterPathElements->szInstanceName, cszSplat) != 0
&& pCounterPathElements->dwInstanceIndex != PERF_NO_UNIQUE_ID
&& pCounterPathElements->dwInstanceIndex != 0) {
// the length of the index is computed by getting the log of the number
// yielding the largest power of 10 less than or equal to the index.
// e.g. the power of 10 of an index value of 356 would 2.0 (which is the
// result of (floor(log10(index))). The actual number of characters in
// the string would always be 1 greate than that value so 1 is added.
// 1 more is added to include the delimiting character
dIndex = (double) pCounterPathElements->dwInstanceIndex; // cast to float
dLen = floor(log10(dIndex)); // get integer log
dwSizeRequired += (DWORD) dLen; // cast to integer
dwSizeRequired += 2; // increment
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
szNextChar = & szFullPathBuffer[lstrlenW(szFullPathBuffer)];
* szNextChar ++ = POUNDSIGN_L;
_ltow((long) pCounterPathElements->dwInstanceIndex, szNextChar, 10);
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
dwSizeRequired += 1; // for delimiting parenthesis
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatW(szFullPathBuffer, dwMaxSize, cszRightParen);
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
dwSizeRequired ++; // include delimiting Backslash
dwSizeRequired += lstrlenW(pCounterPathElements->szCounterName);
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatW(szFullPathBuffer, dwMaxSize, cszBackSlash);
StringCchCatW(szFullPathBuffer, dwMaxSize, pCounterPathElements->szCounterName);
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwSizeRequired ++; // include trailing Null char
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
szFullPathBuffer[dwSizeRequired - 1] = L'\0';
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
else {
// there is some WBEM component involved so send to WBEM function
// to figure it out
pdhStatus = PdhiEncodeWbemPathW(pCounterPathElements,
szFullPathBuffer,
& dwLocalBufferSize,
(LANGID) ((dwFlags >> 16) & 0x0000FFFF),
(DWORD) (dwFlags & 0x0000FFFF));
dwSizeRequired = dwLocalBufferSize;
}
if (pdhStatus == ERROR_SUCCESS && (szFullPathBuffer == NULL || * pcchBufferSize == 0)) {
pdhStatus = PDH_MORE_DATA;
}
* pcchBufferSize = dwSizeRequired;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhMakeCounterPathA(
IN PPDH_COUNTER_PATH_ELEMENTS_A pCounterPathElements,
IN LPSTR szFullPathBuffer,
IN LPDWORD pcchBufferSize,
IN DWORD dwFlags
)
/*++
Routine Description:
Constructs a counter path using the elemeents defined in the
pCounterPathElements structure and returns the path string
in the buffer provided by the caller. The resulting path
is not validated.
Arguments:
IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements
The pointer to the structure containing the
individual counter path fields that are to be
assembled in to a path string
IN LPWSTR szFullPathBuffer
The buffer to receive the path string. This value
may be NULL if the value of the DWORD pointed to
by pcchBufferSize is 0 indicating this is just a
request for the required buffer size.
IN LPDWORD pcchBufferSize
The pointer to the DWORD containing the size
of the string buffer in characters. On return
it contains the size of the buffer used in
characters (including the terminating NULL char).
If the value is 0 on entry then no data will be
written to the buffer, but the required size will
still be returned.
IN DWORD dwFlags
if 0, then return the path as a REGISTRY path items
if PDH_PATH_WBEM_RESULT then return the items in WBEM format
if PDH_PATH_WBEM_INPUT then assume the input is in WBEM format
Return Value:
ERROR_SUCCESS if the function completes successfully, otherwise a
PDH error is returned.
PDH_INVALID_ARGUMENT is returned when one of the arguments passed
by the caller is incorrect or not accesible.
--*/
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
double dIndex;
double dLen;
DWORD dwSizeRequired = 0;
LPSTR szNextChar;
DWORD dwMaxSize;
DWORD dwLocalBufferSize = 0;
if (pCounterPathElements == NULL|| pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
// test access to the input structure
if (pCounterPathElements->szMachineName != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szMachineName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szObjectName != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szObjectName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else {
//NULL is NOT ok for this field
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szInstanceName != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szInstanceName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szParentInstance != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szParentInstance == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (pCounterPathElements->szCounterName != NULL) {
// then see if it's accessible
if (* pCounterPathElements->szCounterName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else {
//NULL is NOT ok for this field
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
// test the output buffers
if (pdhStatus == ERROR_SUCCESS) {
if (pcchBufferSize != NULL) {
dwLocalBufferSize = * pcchBufferSize;
}
else {
// NULL is NOT OK
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS && szFullPathBuffer == NULL && dwLocalBufferSize > 0) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
// write to both ends of the buffer if one was sent
if (dwLocalBufferSize > 0) {
if (szFullPathBuffer != NULL) {
* szFullPathBuffer = '\0';
szFullPathBuffer[dwLocalBufferSize - 1] = '\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
if (dwFlags == 0) {
// this is a registry path in and out
dwMaxSize = dwLocalBufferSize;
if (pCounterPathElements->szMachineName != NULL) {
dwSizeRequired = lstrlenA(pCounterPathElements->szMachineName);
// compare the first two words of the machine name
// to see if the double backslash is already present in the string
if (* ((LPWORD) (pCounterPathElements->szMachineName)) != * ((LPWORD) (caszDoubleBackSlash))) {
// double backslash not found
dwSizeRequired += 2; // to include the backslashes
}
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
if (* ((LPWORD) (pCounterPathElements->szMachineName)) != * ((LPWORD) (caszDoubleBackSlash))) {
// double backslash not found
StringCchCopyA(szFullPathBuffer, dwMaxSize, caszDoubleBackSlash);
StringCchCatA(szFullPathBuffer, dwMaxSize, pCounterPathElements->szMachineName);
}
else {
StringCchCopyA(szFullPathBuffer, dwMaxSize, pCounterPathElements->szMachineName);
}
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
dwSizeRequired += 1; // for delimiting slash
dwSizeRequired += lstrlenA (pCounterPathElements->szObjectName);
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatA(szFullPathBuffer, dwMaxSize, caszBackSlash);
StringCchCatA(szFullPathBuffer, dwMaxSize, pCounterPathElements->szObjectName);
}
else {
pdhStatus = PDH_MORE_DATA;
}
if (pCounterPathElements->szInstanceName != NULL) {
dwSizeRequired += 1; // for delimiting left paren
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatA(szFullPathBuffer, dwMaxSize, caszLeftParen);
}
else {
pdhStatus = PDH_MORE_DATA;
}
if (pCounterPathElements->szParentInstance != NULL) {
dwSizeRequired += lstrlenA(pCounterPathElements->szParentInstance);
dwSizeRequired += 1; // for delimiting slash
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatA(szFullPathBuffer, dwMaxSize, pCounterPathElements->szParentInstance);
StringCchCatA(szFullPathBuffer, dwMaxSize, caszSlash);
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
dwSizeRequired += lstrlenA(pCounterPathElements->szInstanceName);
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatA(szFullPathBuffer, dwMaxSize, pCounterPathElements->szInstanceName);
}
else {
pdhStatus = PDH_MORE_DATA;
}
if (pCounterPathElements->dwInstanceIndex != PERF_NO_UNIQUE_ID
&& pCounterPathElements->dwInstanceIndex != 0) {
// the length of the index is computed by getting the log of the number
// yielding the largest power of 10 less than or equal to the index.
// e.g. the power of 10 of an index value of 356 would 2.0 (which is the
// result of (floor(log10(index))). The actual number of characters in
// the string would always be 1 greate than that value so 1 is added.
// 1 more is added to include the delimiting character
dIndex = (double) pCounterPathElements->dwInstanceIndex; // cast to float
dLen = floor(log10(dIndex)); // get integer log
dwSizeRequired = (DWORD) dLen; // cast to integer
dwSizeRequired += 2; // increment
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
szNextChar = & szFullPathBuffer[lstrlenA(szFullPathBuffer)];
* szNextChar ++ = POUNDSIGN_L;
_ltoa((long) pCounterPathElements->dwInstanceIndex, szNextChar, 10);
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
dwSizeRequired += 1; // for delimiting parenthesis
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatA(szFullPathBuffer, dwMaxSize, caszRightParen);
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
dwSizeRequired ++; // include delimiting Backslash
dwSizeRequired += lstrlenA(pCounterPathElements->szCounterName);
if (szFullPathBuffer != NULL && dwSizeRequired <= dwMaxSize) {
StringCchCatA(szFullPathBuffer, dwMaxSize, caszBackSlash);
StringCchCatA(szFullPathBuffer, dwMaxSize, pCounterPathElements->szCounterName);
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwSizeRequired ++; // include trailing Null char
}
else {
// this is a WBEM path so have the WBEM function figure
// it out
// there is some WBEM component involved so send to WBEM function
// to figure it out
pdhStatus = PdhiEncodeWbemPathA(pCounterPathElements,
szFullPathBuffer,
& dwLocalBufferSize,
(LANGID) ((dwFlags >> 16) & 0x0000FFFF),
(DWORD) (dwFlags & 0x0000FFFF));
dwSizeRequired = dwLocalBufferSize;
}
if (pdhStatus == ERROR_SUCCESS && (szFullPathBuffer == NULL || * pcchBufferSize == 0)) {
pdhStatus = PDH_MORE_DATA;
}
* pcchBufferSize = dwSizeRequired;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
return pdhStatus;
}
PDH_FUNCTION
PdhParseCounterPathW(
IN LPCWSTR szFullPathBuffer,
IN PPDH_COUNTER_PATH_ELEMENTS_W pCounterPathElements,
IN LPDWORD pcchBufferSize,
IN DWORD dwFlags
)
/*++
Routine Description:
Reads a perf counter path string and parses out the
component fields, returning them in a buffer
supplied by the calling function.
Arguments:
IN LPCWSTR szFullPathBuffer
counter path string to parse.
IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements
pointer to buffer supplied by the caller in
which the component fields will be written
This buffer is cast as a structure, however, the
string data is written to the space after
the buffer.
IN LPDWORD pcchBufferSize
the size of the buffer in BYTES. If specified size
is 0, then the size is estimated and returned
in this field and the buffer referenced by the
agrument above is ignored.
IN DWORD dwFlags
if 0, then return the path elements as REGISTRY path items
if PDH_PATH_WBEM_RESULT then return the items in WBEM format
if PDH_PATH_WBEM_INPUT then assume the input is in WBEM format
Return Value:
ERROR_SUCCESS if the function completes successfully, otherwise
a PDH error if not
PDH_INVALID_ARGUMENT is returned when an argument is inocrrect or
this function does not have the necessary access to that arg.
PDH_INVALID_PATH is returned when the path is not formatted correctly
and cannot be parsed.
PDH_MEMORY_ALLOCATION_FAILURE is returned when a temporary buffer
cannot be allocated
--*/
{
PPDHI_COUNTER_PATH pLocalCounterPath;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwSize;
LPWSTR szString = NULL;
DWORD dwLocalBufferSize;
DWORD dwString;
//validate incoming arguments
if (szFullPathBuffer == NULL || pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwLocalBufferSize = * pcchBufferSize;
// string cannot be null
if (* szFullPathBuffer == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szFullPathBuffer) > PDH_MAX_COUNTER_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwLocalBufferSize > 0) {
if (pCounterPathElements != NULL) {
// try both "ends" of the buffer to see if an AV occurs
((LPBYTE) pCounterPathElements) [0] = 0;
((LPBYTE) pCounterPathElements) [dwLocalBufferSize - 1] = 0;
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
if (dwFlags != 0) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwFlags == 0) {
// allocate a temporary work buffer
dwString = 2 * (lstrlenW(szFullPathBuffer) + lstrlenW(szStaticLocalMachineName)
+ PDH_MAX_COUNTER_PATH);
dwSize = sizeof(PDHI_COUNTER_PATH) + dwString * sizeof(WCHAR);
pLocalCounterPath = G_ALLOC(dwSize);
if (pLocalCounterPath != NULL) {
if (ParseFullPathNameW(szFullPathBuffer, & dwSize, pLocalCounterPath, FALSE)) {
// parsed successfully so load into user's buffer
dwSize = sizeof(PDH_COUNTER_PATH_ELEMENTS_W);
if (pCounterPathElements != NULL && dwSize <= dwLocalBufferSize) {
szString = (LPWSTR) & pCounterPathElements[1];
}
else {
szString = NULL;
pdhStatus = PDH_MORE_DATA;
}
if (pLocalCounterPath->szMachineName != NULL) {
dwString = lstrlenW(pLocalCounterPath->szMachineName) + 1;
if (szString != NULL && dwSize + dwString * sizeof(WCHAR) <= dwLocalBufferSize) {
pCounterPathElements->szMachineName = szString;
StringCchCopyW(szString, dwString, pLocalCounterPath->szMachineName);
szString += dwString;
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwSize += dwString * sizeof(WCHAR);
}
else if (pCounterPathElements != NULL && dwSize <= dwLocalBufferSize) {
pCounterPathElements->szMachineName = NULL;
}
if (pLocalCounterPath->szObjectName != NULL) {
dwString = lstrlenW(pLocalCounterPath->szObjectName) + 1;
if (szString != NULL && dwSize + dwString * sizeof(WCHAR) <= dwLocalBufferSize) {
pCounterPathElements->szObjectName = szString;
StringCchCopyW(szString, dwString, pLocalCounterPath->szObjectName);
szString += dwString;
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwSize += dwString * sizeof(WCHAR);
}
else if (pCounterPathElements != NULL && dwSize <= dwLocalBufferSize) {
pCounterPathElements->szObjectName = NULL;
}
if (pLocalCounterPath->szInstanceName != NULL) {
dwString = lstrlenW(pLocalCounterPath->szInstanceName) + 1;
if (szString != NULL && dwSize + dwString * sizeof(WCHAR) <= dwLocalBufferSize) {
pCounterPathElements->szInstanceName = szString;
StringCchCopyW(szString, dwString, pLocalCounterPath->szInstanceName);
szString += dwString;
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwSize += dwString * sizeof(WCHAR);
if (pLocalCounterPath->szParentName != NULL) {
dwString = lstrlenW(pLocalCounterPath->szParentName) + 1;
if (szString != NULL && dwSize + dwString * sizeof(WCHAR) <= dwLocalBufferSize) {
pCounterPathElements->szParentInstance = szString;
StringCchCopyW(szString, dwString, pLocalCounterPath->szParentName);
szString += dwString;
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwSize += dwString * sizeof(WCHAR);
}
else if (pCounterPathElements != NULL && dwSize <= dwLocalBufferSize) {
pCounterPathElements->szParentInstance = NULL;
}
if (pCounterPathElements != NULL && dwSize <= dwLocalBufferSize) {
pCounterPathElements->dwInstanceIndex = pLocalCounterPath->dwIndex;
}
}
else if (pCounterPathElements != NULL && dwSize <= dwLocalBufferSize) {
pCounterPathElements->szInstanceName = NULL;
pCounterPathElements->szParentInstance = NULL;
pCounterPathElements->dwInstanceIndex = PERF_NO_UNIQUE_ID;
}
if (pLocalCounterPath->szCounterName != NULL) {
dwString = lstrlenW(pLocalCounterPath->szCounterName) + 1;
if (szString != NULL && dwSize + dwString * sizeof(WCHAR) <= dwLocalBufferSize) {
pCounterPathElements->szCounterName = szString;
StringCchCopyW(szString, dwString, pLocalCounterPath->szCounterName);
szString += dwString;
}
dwSize += dwString * sizeof(WCHAR);
}
else if (pCounterPathElements != NULL && dwSize <= dwLocalBufferSize) {
pCounterPathElements->szCounterName = NULL;
}
dwLocalBufferSize = dwSize;
}
else {
// unable to read path
pdhStatus = PDH_INVALID_PATH;
}
G_FREE(pLocalCounterPath);
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
pdhStatus = PdhiDecodeWbemPathW(szFullPathBuffer,
pCounterPathElements,
& dwLocalBufferSize,
(LANGID) ((dwFlags >> 16) & 0x0000FFFF),
(DWORD) (dwFlags & 0x0000FFFF));
}
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
* pcchBufferSize = dwLocalBufferSize;
}
return pdhStatus;
}
PDH_FUNCTION
PdhParseCounterPathA(
IN LPCSTR szFullPathBuffer,
IN PPDH_COUNTER_PATH_ELEMENTS_A pCounterPathElements,
IN LPDWORD pcchBufferSize,
IN DWORD dwFlags
)
/*++
Routine Description:
Reads a perf counter path string and parses out the
component fields, returning them in a buffer
supplied by the calling function.
Arguments:
IN LPCSTR szFullPathBuffer
counter path string to parse.
IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements
pointer to buffer supplied by the caller in
which the component fields will be written
This buffer is cast as a structure, however, the
string data is written to the space after
the buffer.
IN LPDWORD pcchBufferSize
the size of the buffer in BYTES. If specified size
is 0, then the size is estimated and returned
in this field and the buffer referenced by the
agrument above is ignored.
IN DWORD dwFlags
if 0, then return the path as a REGISTRY path items
if PDH_PATH_WBEM_RESULT then return the items in WBEM format
if PDH_PATH_WBEM_INPUT then assume the input is in WBEM format
Return Value:
ERROR_SUCCESS if the function completes successfully, otherwise
a PDH error if not
PDH_INVALID_ARGUMENT is returned when an argument is inocrrect or
this function does not have the necessary access to that arg.
PDH_INVALID_PATH is returned when the path is not formatted correctly
and cannot be parsed.
PDH_MEMORY_ALLOCATION_FAILURE is returned when a temporary buffer
cannot be allocated
--*/
{
PPDHI_COUNTER_PATH pLocalCounterPath = NULL;
LPWSTR wszFullPath = NULL;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PDH_STATUS pdhStatus1 = ERROR_SUCCESS;
DWORD dwSize;
DWORD dwSizeUsed;
LPSTR szString;
DWORD dwSizeofLocalCounterPath;
DWORD dwLocalBufferSize = 0;
//validate incoming arguments
if (szFullPathBuffer == NULL || pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
// capture buffer size locally
dwLocalBufferSize = * pcchBufferSize;
if (dwFlags != 0) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
// the name must be non null
else if (* szFullPathBuffer == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szFullPathBuffer) > PDH_MAX_COUNTER_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (dwLocalBufferSize > 0) {
if (pCounterPathElements != NULL) {
// try both "ends" of the buffer to see if an AV occurs
* ((LPBYTE) pCounterPathElements) = 0;
((LPBYTE) pCounterPathElements)[dwLocalBufferSize - 1] = 0;
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwFlags == 0) {
dwSize = lstrlenA(szFullPathBuffer) + lstrlenW(szStaticLocalMachineName) + 1;
dwSize = QWORD_MULTIPLE(dwSize);
dwSizeofLocalCounterPath = sizeof(PDHI_COUNTER_PATH) + (2 * dwSize * sizeof(WCHAR));
dwSizeofLocalCounterPath = QWORD_MULTIPLE(dwSizeofLocalCounterPath);
wszFullPath = G_ALLOC(dwSize * sizeof(WCHAR) + dwSizeofLocalCounterPath);
if (wszFullPath != NULL) {
pLocalCounterPath = (PPDHI_COUNTER_PATH) ((LPBYTE) wszFullPath + dwSize * sizeof(WCHAR));
MultiByteToWideChar(_getmbcp(), 0, szFullPathBuffer, -1, (LPWSTR) wszFullPath, dwSize);
dwSize = (DWORD) dwSizeofLocalCounterPath;
if (ParseFullPathNameW(wszFullPath, & dwSize, pLocalCounterPath, FALSE)) {
// parsed successfully so load into user's buffer
// adjust dwSize to account for single-byte characters
// as they'll be packed in user's buffer.
dwSizeUsed = sizeof(PDH_COUNTER_PATH_ELEMENTS);
if (pCounterPathElements != NULL && dwSizeUsed <= dwLocalBufferSize) {
szString = (LPSTR) & pCounterPathElements[1];
}
else {
szString = NULL;
pdhStatus = PDH_MORE_DATA;
}
if (pLocalCounterPath->szMachineName != NULL) {
dwSize = (dwLocalBufferSize >= dwSizeUsed) ? (dwLocalBufferSize - dwSizeUsed) : (0);
pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
pLocalCounterPath->szMachineName,
szString,
& dwSize);
if (dwSize % sizeof(DWORD) != 0) {
dwSize = sizeof(DWORD) * ((dwSize / sizeof(DWORD)) + 1);
}
dwSizeUsed += dwSize;
if (pdhStatus1 == ERROR_SUCCESS) {
pCounterPathElements->szMachineName = szString;
szString += dwSize;
}
else if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = pdhStatus1;
}
}
else if (pCounterPathElements != NULL && dwSizeUsed <= dwLocalBufferSize) {
pCounterPathElements->szMachineName = NULL;
}
if (pLocalCounterPath->szObjectName != NULL) {
dwSize = (dwLocalBufferSize >= dwSizeUsed) ? (dwLocalBufferSize - dwSizeUsed) : (0);
pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
pLocalCounterPath->szObjectName,
szString,
& dwSize);
if (dwSize % sizeof(DWORD) != 0) {
dwSize = sizeof(DWORD) * ((dwSize / sizeof(DWORD)) + 1);
}
dwSizeUsed += dwSize;
if (pdhStatus1 == ERROR_SUCCESS) {
pCounterPathElements->szObjectName = szString;
szString += dwSize;
}
else if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = pdhStatus1;
}
}
else if (pCounterPathElements != NULL && dwSizeUsed <= dwLocalBufferSize) {
pCounterPathElements->szObjectName = NULL;
}
if (pLocalCounterPath->szInstanceName != NULL) {
dwSize = (dwLocalBufferSize >= dwSizeUsed) ? (dwLocalBufferSize - dwSizeUsed) : (0);
pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
pLocalCounterPath->szInstanceName,
szString,
& dwSize);
if (dwSize % sizeof(DWORD) != 0) {
dwSize = sizeof(DWORD) * ((dwSize / sizeof(DWORD)) + 1);
}
dwSizeUsed += dwSize;
if (pdhStatus1 == ERROR_SUCCESS) {
pCounterPathElements->szInstanceName = szString;
szString += dwSize;
}
else if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = pdhStatus1;
}
if (pLocalCounterPath->szParentName != NULL) {
dwSize = (dwLocalBufferSize >= dwSizeUsed) ? (dwLocalBufferSize - dwSizeUsed) : (0);
pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
pLocalCounterPath->szParentName,
szString,
& dwSize);
if (dwSize % sizeof(DWORD) != 0) {
dwSize = sizeof(DWORD) * ((dwSize / sizeof(DWORD)) + 1);
}
dwSizeUsed += dwSize;
if (pdhStatus1 == ERROR_SUCCESS) {
pCounterPathElements->szParentInstance = szString;
szString += dwSize;
}
else if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = pdhStatus1;
}
}
else if (pCounterPathElements != NULL && dwSizeUsed <= dwLocalBufferSize) {
pCounterPathElements->szParentInstance = NULL;
}
if (pCounterPathElements != NULL && dwSizeUsed <= dwLocalBufferSize) {
pCounterPathElements->dwInstanceIndex = pLocalCounterPath->dwIndex;
}
}
else if (pCounterPathElements != NULL && dwSizeUsed <= dwLocalBufferSize) {
pCounterPathElements->szInstanceName = NULL;
pCounterPathElements->szParentInstance = NULL;
pCounterPathElements->dwInstanceIndex = PERF_NO_UNIQUE_ID;
}
if (pLocalCounterPath->szCounterName != NULL) {
dwSize = (dwLocalBufferSize >= dwSizeUsed) ? (dwLocalBufferSize - dwSizeUsed) : (0);
pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
pLocalCounterPath->szCounterName,
szString,
& dwSize);
if (dwSize % sizeof(DWORD) != 0) {
dwSize = sizeof(DWORD) * ((dwSize / sizeof(DWORD)) + 1);
}
dwSizeUsed += dwSize;
if (pdhStatus1 == ERROR_SUCCESS) {
pCounterPathElements->szCounterName = szString;
szString += dwSize;
}
else if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = pdhStatus1;
}
}
else if (pCounterPathElements != NULL && dwSizeUsed < dwLocalBufferSize) {
pCounterPathElements->szCounterName = NULL;
}
dwLocalBufferSize = dwSizeUsed;
}
else {
pdhStatus = PDH_INVALID_PATH;
}
G_FREE(wszFullPath);
}
else {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
else {
// this is a WBEM path so have the WBEM function figure
// it out
// there is some WBEM component involved so send to WBEM function
// to figure it out
pdhStatus = PdhiDecodeWbemPathA(szFullPathBuffer,
pCounterPathElements,
& dwLocalBufferSize,
(LANGID) ((dwFlags >> 16) & 0x0000FFFF),
(DWORD) (dwFlags & 0x0000FFFF));
}
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
* pcchBufferSize = dwLocalBufferSize;
}
return pdhStatus;
}
PDH_FUNCTION
PdhParseInstanceNameW(
IN LPCWSTR szInstanceString,
IN LPWSTR szInstanceName,
IN LPDWORD pcchInstanceNameLength,
IN LPWSTR szParentName,
IN LPDWORD pcchParentNameLength,
IN LPDWORD lpIndex
)
/*++
Routine Description:
parses the fields of an instance string and returns them in the
buffers supplied by the caller
Arguments:
szInstanceString
is the pointer to the string containing the instance substring
to parse into individual components. This string can contain the
following formats and less than MAX_PATH chars in length:
instance
instance#index
parent/instance
parent/instance#index
szInstanceName
is the pointer to the buffer that will receive the instance
name parsed from the instance string. This pointer can be
NULL if the DWORD referenced by the pcchInstanceNameLength
argument is 0.
pcchInstanceNameLength
is the pointer to the DWORD that contains the length of the
szInstanceName buffer. If the value of this DWORD is 0, then
the buffer size required to hold the instance name will be
returned.
szParentName
is the pointer to the buffer that will receive the name
of the parent index if one is specified. This argument can
be NULL if the value of the DWORD referenced by the
pcchParentNameLength argument is 0.
lpIndex
is the pointer to the DWORD that will receive the index
value of the instance. If an index entry is not present in
the string, then this value will be 0. This argument can
be NULL if this information is not needed.
Return Value:
ERROR_SUCCESS if the function completes successfully, otherwise
a PDH error is returned.
PDH_INVALID_ARGUMENT is returned when one or more of the
arguments is invalid or incorrect.
PDH_INVALID_INSTANCE is returned if the instance string is incorrectly
formatted and cannot be parsed
--*/
{
BOOL bReturn;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwSize;
DWORD dwLocalIndex;
LPWSTR szLocalInstanceName = NULL;
LPWSTR szLocalParentName = NULL;
DWORD dwLocalInstanceNameLength;
DWORD dwLocalParentNameLength;
// test access to arguments
if (szInstanceString == NULL || pcchInstanceNameLength == NULL || pcchParentNameLength == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwLocalInstanceNameLength = * pcchInstanceNameLength;
dwLocalParentNameLength = * pcchParentNameLength;
if (* szInstanceString == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szInstanceString) > PDH_MAX_INSTANCE_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
if (dwLocalInstanceNameLength > 0) {
if (szInstanceName != NULL) {
WCHAR wChar = * szInstanceName;
* szInstanceName = L'\0';
* szInstanceName = wChar;
wChar = szInstanceName[dwLocalInstanceNameLength - 1];
szInstanceName[dwLocalInstanceNameLength - 1] = L'\0';
szInstanceName[dwLocalInstanceNameLength - 1] = wChar;
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else size only request
if (dwLocalParentNameLength > 0) {
if (szParentName != NULL) {
WCHAR wChar = * szParentName;
* szParentName = L'\0';
* szParentName = wChar;
wChar = szParentName[dwLocalParentNameLength - 1];
szParentName[dwLocalParentNameLength - 1] = L'\0';
szParentName[dwLocalParentNameLength - 1] = wChar;
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else size only request
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
DWORD dwLength = lstrlenW(szInstanceString) + 1;
if (dwLength < PDH_MAX_INSTANCE_NAME) dwLength = PDH_MAX_INSTANCE_NAME;
szLocalInstanceName = G_ALLOC(2 * dwLength * sizeof(WCHAR));
if (szLocalInstanceName != NULL) {
szLocalParentName = (szLocalInstanceName + dwLength);
bReturn = ParseInstanceName(
szInstanceString, szLocalInstanceName, szLocalParentName, dwLength, & dwLocalIndex);
}
else {
bReturn = FALSE;
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
if (bReturn) {
dwSize = lstrlenW(szLocalInstanceName) + 1;
if (szInstanceName != NULL && dwSize <= dwLocalInstanceNameLength) {
StringCchCopyW(szInstanceName, dwLocalInstanceNameLength, szLocalInstanceName);
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwLocalInstanceNameLength = dwSize; // include the trailing NULL
dwSize = lstrlenW(szLocalParentName) + 1;
if (szParentName != NULL && dwSize <= dwLocalParentNameLength) {
StringCchCopyW(szParentName, dwLocalParentNameLength, szLocalParentName);
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwLocalParentNameLength = dwSize; // include the trailing NULL
__try {
* pcchInstanceNameLength = dwLocalInstanceNameLength;
* pcchParentNameLength = dwLocalParentNameLength;
if (lpIndex != NULL) {
* lpIndex = dwLocalIndex;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else if (pdhStatus == ERROR_SUCCESS) {
// unable to parse string
pdhStatus = PDH_INVALID_INSTANCE;
}
}
G_FREE(szLocalInstanceName);
return pdhStatus;
}
PDH_FUNCTION
PdhParseInstanceNameA(
IN LPCSTR szInstanceString,
IN LPSTR szInstanceName,
IN LPDWORD pcchInstanceNameLength,
IN LPSTR szParentName,
IN LPDWORD pcchParentNameLength,
IN LPDWORD lpIndex
)
/*++
Routine Description:
parses the fields of an instance string and returns them in the
buffers supplied by the caller
Arguments:
szInstanceString
is the pointer to the string containing the instance substring
to parse into individual components. This string can contain the
following formats and less than MAX_PATH chars in length:
instance
instance#index
parent/instance
parent/instance#index
szInstanceName
is the pointer to the buffer that will receive the instance
name parsed from the instance string. This pointer can be
NULL if the DWORD referenced by the pcchInstanceNameLength
argument is 0.
pcchInstanceNameLength
is the pointer to the DWORD that contains the length of the
szInstanceName buffer. If the value of this DWORD is 0, then
the buffer size required to hold the instance name will be
returned.
szParentName
is the pointer to the buffer that will receive the name
of the parent index if one is specified. This argument can
be NULL if the value of the DWORD referenced by the
pcchParentNameLength argument is 0.
lpIndex
is the pointer to the DWORD that will receive the index
value of the instance. If an index entry is not present in
the string, then this value will be 0. This argument can
be NULL if this information is not needed.
Return Value:
ERROR_SUCCESS if the function completes successfully, otherwise
a PDH error is returned.
PDH_INVALID_ARGUMENT is returned when one or more of the
arguments is invalid or incorrect.
PDH_INVALID_INSTANCE is returned if the instance string is incorrectly
formatted and cannot be parsed
--*/
{
BOOL bReturn;
LONG pdhStatus = ERROR_SUCCESS;
DWORD dwSize;
LPWSTR wszInstanceString = NULL;
LPWSTR wszLocalInstanceName = NULL;
LPWSTR wszLocalParentName = NULL;
DWORD dwLocalIndex = 0;
DWORD dwLocalInstanceNameLength;
DWORD dwLocalParentNameLength;
// test access to arguments
if (szInstanceString == NULL || pcchInstanceNameLength == NULL || pcchParentNameLength == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
__try {
dwLocalInstanceNameLength = * pcchInstanceNameLength;
dwLocalParentNameLength = * pcchParentNameLength;
if (* szInstanceString == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szInstanceString) > PDH_MAX_INSTANCE_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
if (dwLocalInstanceNameLength > 0) {
if (szInstanceName != NULL) {
CHAR cChar = * szInstanceName;
* szInstanceName = '\0';
* szInstanceName = cChar;
cChar = szInstanceName[dwLocalInstanceNameLength - 1];
szInstanceName[dwLocalInstanceNameLength - 1] = '\0';
szInstanceName[dwLocalInstanceNameLength - 1] = cChar;
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else size only request
if (dwLocalParentNameLength > 0) {
if (szParentName != NULL) {
CHAR cChar = * szParentName;
* szParentName = '\0';
* szParentName = cChar;
cChar = szParentName[dwLocalParentNameLength - 1];
szParentName[dwLocalParentNameLength - 1] = '\0';
szParentName[dwLocalParentNameLength - 1] = cChar;
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else size only request
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwSize = lstrlenA(szInstanceString) + 1;
if (dwSize < PDH_MAX_INSTANCE_NAME) dwSize = PDH_MAX_INSTANCE_NAME;
wszInstanceString = G_ALLOC(3 * dwSize * sizeof(WCHAR));
if (wszInstanceString != NULL) {
wszLocalInstanceName = (wszInstanceString + dwSize);
wszLocalParentName = (wszLocalInstanceName + dwSize);
MultiByteToWideChar(_getmbcp(), 0, szInstanceString, -1, wszInstanceString, dwSize);
bReturn = ParseInstanceName(
wszInstanceString, wszLocalInstanceName, wszLocalParentName, dwSize, & dwLocalIndex);
}
else {
// instance string is too long
bReturn = FALSE;
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
if (bReturn) {
PDH_STATUS pdhInstStatus = ERROR_SUCCESS;
PDH_STATUS pdhParentStatus = ERROR_SUCCESS;
dwSize = dwLocalInstanceNameLength;
pdhInstStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), wszLocalInstanceName, szInstanceName, & dwSize);
dwLocalInstanceNameLength = dwSize;
dwSize = dwLocalParentNameLength;
pdhParentStatus = PdhiConvertUnicodeToAnsi(_getmbcp(), wszLocalParentName, szParentName, & dwSize);
if (pdhParentStatus == PDH_INVALID_ARGUMENT) {
pdhParentStatus = ERROR_SUCCESS;
}
dwLocalParentNameLength = dwSize;
if (pdhInstStatus != ERROR_SUCCESS) {
pdhStatus = pdhInstStatus;
}
else {
pdhStatus = pdhParentStatus;
}
__try {
* pcchInstanceNameLength = dwLocalInstanceNameLength;
* pcchParentNameLength = dwLocalParentNameLength;
if (lpIndex != NULL) {
* lpIndex = dwLocalIndex;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else if (pdhStatus == ERROR_SUCCESS) {
// unable to parse string
pdhStatus = PDH_INVALID_INSTANCE;
}
} // else pass status through to caller
G_FREE(wszInstanceString);
return pdhStatus;
}
PDH_FUNCTION
PdhValidatePathW(
IN LPCWSTR szFullPathBuffer
)
/*++
Routine Description:
breaks the specified path into its component parts and evaluates
each of the part to make sure the specified path represents
a valid and operational performance counter. The return value
indicates the pdhStatus of the counter defined in the path string.
Arguments:
IN LPCWSTR szFullPathBuffer
the full path string of the counter to validate.
Return Value:
ERROR_SUCCESS of the counter was successfully located otherwise
a PDH error.
PDH_CSTATUS_NO_INSTANCE is returned if the specified instance of
the performance object wasn't found
PDH_CSTATUS_NO_COUNTER is returned if the specified counter was not
found in the object.
PDH_CSTATUS_NO_OBJECT is returned if the specified object was not
found on the machine
PDH_CSTATUS_NO_MACHINE is returned if the specified machine could
not be found or connected to
PDH_CSTATUS_BAD_COUNTERNAME is returned when the counter path string
could not be parsed.
PDH_MEMORY_ALLOCATION_FAILURE is returned when the function is unable
to allocate a required temporary buffer
PDH_INVALID_ARGUMENT is returned when the counter path string argument
could not be accessed
--*/
{
PPERF_MACHINE pMachine;
PPDHI_COUNTER_PATH pLocalCounterPath;
DWORD dwSize;
PPERF_OBJECT_TYPE pPerfObjectDef = NULL;
PPERF_INSTANCE_DEFINITION pPerfInstanceDef;
PPERF_COUNTER_DEFINITION pPerfCounterDef;
PDH_STATUS CStatus = ERROR_SUCCESS;
if (szFullPathBuffer != NULL) {
// validate access to arguments
__try {
// make sure the name isn't empty
if (* szFullPathBuffer == L'\0') {
CStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szFullPathBuffer) > PDH_MAX_COUNTER_PATH) {
CStatus = PDH_INVALID_ARGUMENT;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
CStatus = PDH_INVALID_ARGUMENT;
}
}
else {
// cannot be null
CStatus = PDH_INVALID_ARGUMENT;
}
if (CStatus == ERROR_SUCCESS) {
CStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
}
if (CStatus == ERROR_SUCCESS) {
__try {
pLocalCounterPath = G_ALLOC(sizeof(PDHI_COUNTER_PATH) + 2 * sizeof(WCHAR)
* (lstrlenW(szFullPathBuffer) + 1 + lstrlenW(szStaticLocalMachineName) + 1));
if (pLocalCounterPath != NULL) {
dwSize = (DWORD) G_SIZE(pLocalCounterPath);
if (ParseFullPathNameW(szFullPathBuffer, & dwSize, pLocalCounterPath, FALSE)) {
// parsed successfully so try to connect to machine
// and get machine pointer
pMachine = GetMachine(pLocalCounterPath->szMachineName, 0, PDH_GM_UPDATE_PERFNAME_ONLY);
if (pMachine == NULL) {
CStatus = GetLastError();
if (CStatus == ERROR_SUCCESS) CStatus = PDH_CSTATUS_NO_MACHINE;
}
else if (pMachine->dwStatus != ERROR_SUCCESS) {
CStatus = pMachine->dwStatus;
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
pMachine = NULL;
}
else {
DWORD dwObject = GetObjectId(pMachine, pLocalCounterPath->szObjectName, NULL);
if (dwObject == (DWORD) -1) {
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
if (CStatus == ERROR_SUCCESS) CStatus = PDH_CSTATUS_NO_OBJECT;
pMachine = NULL;
}
}
if (pMachine != NULL) {
if (pMachine->dwStatus == ERROR_SUCCESS) {
// look up object name
pPerfObjectDef = GetObjectDefByName(pMachine->pSystemPerfData,
pMachine->dwLastPerfString,
pMachine->szPerfStrings,
pLocalCounterPath->szObjectName);
}
else {
pPerfObjectDef = NULL;
}
if (pPerfObjectDef != NULL) {
// look up instances if necessary
if (pPerfObjectDef->NumInstances != PERF_NO_INSTANCES) {
if (pLocalCounterPath->szInstanceName != NULL) {
if (* pLocalCounterPath->szInstanceName != SPLAT_L) {
pPerfInstanceDef = GetInstanceByName(pMachine->pSystemPerfData,
pPerfObjectDef,
pLocalCounterPath->szInstanceName,
pLocalCounterPath->szParentName,
(pLocalCounterPath->dwIndex != PERF_NO_UNIQUE_ID ?
pLocalCounterPath->dwIndex : 0));
if (pPerfInstanceDef == NULL) {
// unable to lookup instance
CStatus = PDH_CSTATUS_NO_INSTANCE;
}
}
// wild card instances are OK IF multiple instances
// are supported!!!
}
else {
// no instance was specified for a counter
// that should have an instance so this is
// an invalid path
CStatus = PDH_CSTATUS_NO_INSTANCE;
}
}
else {
// no instances in this counter, see if one
// is defined
if ((pLocalCounterPath->szInstanceName != NULL) ||
(pLocalCounterPath->szParentName != NULL)) {
// unable to lookup instance
CStatus = PDH_CSTATUS_NO_INSTANCE;
}
}
if (CStatus == ERROR_SUCCESS) {
// and look up counter
pPerfCounterDef = GetCounterDefByName(pPerfObjectDef,
pMachine->dwLastPerfString,
pMachine->szPerfStrings,
pLocalCounterPath->szCounterName);
if (pPerfCounterDef != NULL) {
// counter found so return TRUE & valid
CStatus = ERROR_SUCCESS;
}
else {
// unable to lookup counter
CStatus = PDH_CSTATUS_NO_COUNTER;
}
}
}
else {
// unable to lookup object
CStatus = PDH_CSTATUS_NO_OBJECT;
}
pMachine->dwRefCount --;
RELEASE_MUTEX (pMachine->hMutex);
}
else if (CStatus == ERROR_SUCCESS) {
// unable to find machine
CStatus = PDH_CSTATUS_NO_MACHINE;
}
}
else {
// unable to parse counter name
CStatus = PDH_CSTATUS_BAD_COUNTERNAME;
}
G_FREE(pLocalCounterPath);
}
else {
// unable to allocate memory
CStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
CStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX (hPdhDataMutex);
} // else pass error to caller
return CStatus;
}
PDH_FUNCTION
PdhValidatePathA(
IN LPCSTR szFullPathBuffer
)
/*++
Routine Description:
breaks the specified path into its component parts and evaluates
each of the part to make sure the specified path represents
a valid and operational performance counter. The return value
indicates the pdhStatus of the counter defined in the path string.
Arguments:
IN LPCSTR szFullPathBuffer
the full path string of the counter to validate.
Return Value:
ERROR_SUCCESS of the counter was successfully located otherwise
a PDH error.
PDH_CSTATUS_NO_INSTANCE is returned if the specified instance of
the performance object wasn't found
PDH_CSTATUS_NO_COUNTER is returned if the specified counter was not
found in the object.
PDH_CSTATUS_NO_OBJECT is returned if the specified object was not
found on the machine
PDH_CSTATUS_NO_MACHINE is returned if the specified machine could
not be found or connected to
PDH_CSTATUS_BAD_COUNTERNAME is returned when the counter path string
could not be parsed.
PDH_MEMORY_ALLOCATION_FAILURE is returned when the function is unable
to allocate a required temporary buffer
--*/
{
LPWSTR wszFullPath = NULL;
PDH_STATUS Status = ERROR_SUCCESS;
if (szFullPathBuffer != NULL) {
__try {
// cannot be blank
if (* szFullPathBuffer == '\0') {
Status = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szFullPathBuffer) > PDH_MAX_COUNTER_PATH) {
Status = PDH_INVALID_ARGUMENT;
}
else {
wszFullPath = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szFullPathBuffer);
if (wszFullPath == NULL) Status = PDH_MEMORY_ALLOCATION_FAILURE;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
Status = PDH_INVALID_ARGUMENT;
}
}
else {
// cannot be null
Status = PDH_INVALID_ARGUMENT;
}
if (Status == ERROR_SUCCESS) {
Status = PdhValidatePathW(wszFullPath);
}
G_FREE(wszFullPath);
return Status;
}
PDH_FUNCTION
PdhiGetDefaultPerfObjectW(
DWORD dwDataSource,
LPCWSTR szMachineName,
LPWSTR szDefaultObjectName,
LPDWORD pcchBufferSize
)
/*++
Routine Description:
Obtains the default performance object from the specified machine.
Arguments:
IN DWORD dwDataSourcetype
IN LPCWSTR szMachineName
NULL indicates the local machine, othewise this is the
name of the remote machine to query. If this machine is
not known to the PDH DLL, then it will be connected.
IN LPWSTR szDefaultObjectName
pointer to the buffer that will receive the default object
name. This pointer can be NULL if the value of the DWORD
referenced by bcchBufferSize is 0.
IN LPDWORD pcchBufferSize
pointer to a DWORD containing the size of the buffer, in
characters, referenced by the szDefaultObjectName argument.
If the value of this DWORD is 0, then no data will be written
to the szDefaultObjectNameBuffer, however the required
buffer size will be returned in the DWORD referenced by
this pointer.
Return Value:
ERROR_SUCCESS if this function completes normally otherwise a PDH error.
PDH_INVALID_ARGUMENT a required argument is not correct or reserved
argument is not 0 or NULL.
PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
buffer could not be allocated.
PDH_CSTATUS_NO_COUNTERNAME is returned when the default object
name cannot be read or found.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
--*/
{
PPERF_MACHINE pMachine;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LONG lDefault;
DWORD dwStringLen;
DWORD dwLocalBufferSize = 0;
LPWSTR szDefault;
LPWSTR szThisMachine = NULL;
if (pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
// test the access the arguments
__try {
if (szMachineName != NULL) {
// if there's a machine name then it cannot be blank
if (* szMachineName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL machine Name is OK
if (pdhStatus == ERROR_SUCCESS) {
dwLocalBufferSize = * pcchBufferSize;
if (dwLocalBufferSize > 0) {
if (szDefaultObjectName != NULL) {
// test both ends of the caller's buffer for
// write access
szDefaultObjectName[0] = L'\0';
szDefaultObjectName[dwLocalBufferSize -1] = L'\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS && szMachineName != NULL) {
DWORD dwMachineName = (* szMachineName == L'\\') ? (lstrlenW(szMachineName) + 1)
: (lstrlenW(szMachineName) + 3);
dwMachineName *= sizeof(WCHAR);
szThisMachine = G_ALLOC(dwMachineName);
if (szThisMachine == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else if (* szMachineName == L'\\') {
StringCchCopyW(szThisMachine, dwMachineName, szMachineName);
}
else {
StringCchCopyW(szThisMachine, dwMachineName, cszDoubleBackSlash);
StringCchCatW(szThisMachine, dwMachineName, szMachineName);
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
pMachine = GetMachine((LPWSTR) szThisMachine, 0, 0);
pdhStatus = (pMachine != NULL ? pMachine->dwStatus : GetLastError());
if (pMachine != NULL) {
if (pdhStatus == ERROR_SUCCESS) {
// only look at buffers from machines that are "on line"
lDefault = pMachine->pSystemPerfData->DefaultObject;
if ((lDefault > 0) && ((DWORD) lDefault < pMachine->dwLastPerfString)) {
// then there should be a string in the table
szDefault = (LPWSTR) PdhiLookupPerfNameByIndex(pMachine, lDefault);
if (szDefault != NULL) {
// determine string buffer length including term. NULL char
dwStringLen = lstrlenW(szDefault) + 1;
if (szDefaultObjectName != NULL && dwStringLen <= dwLocalBufferSize) {
StringCchCopyW(szDefaultObjectName, dwLocalBufferSize, szDefault);
pdhStatus = ERROR_SUCCESS;
}
else {
pdhStatus = PDH_MORE_DATA;
}
}
else {
// unable to find a matching counter name
pdhStatus = PDH_CSTATUS_NO_COUNTERNAME;
dwStringLen = 0;
}
}
else {
// string not in table
pdhStatus = PDH_CSTATUS_NO_COUNTERNAME;
dwStringLen = 0;
}
dwLocalBufferSize = dwStringLen;
}
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
} // else pass error pdhStatus on to the caller
break;
case DATA_SOURCE_WBEM:
pdhStatus = PdhiGetDefaultWbemObject(szThisMachine,
(LPVOID) szDefaultObjectName,
& dwLocalBufferSize,
TRUE); // unicode function
break;
case DATA_SOURCE_LOGFILE:
// log files don't support this (for now)
// but this is still successful.
dwLocalBufferSize = 0;
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchBufferSize = dwLocalBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
G_FREE(szThisMachine);
return pdhStatus;
}
PDH_FUNCTION
PdhGetDefaultPerfObjectHW(
IN HLOG hDataSource,
IN LPCWSTR szMachineName,
IN LPWSTR szDefaultObjectName,
IN LPDWORD pcchBufferSize
)
{
DWORD dwDataSourceType = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try {
dwDataSourceType = DataSourceTypeH(hDataSource);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultPerfObjectW(dwDataSourceType, szMachineName, szDefaultObjectName, pcchBufferSize);
}
return pdhStatus;
}
PDH_FUNCTION
PdhGetDefaultPerfObjectW(
IN LPCWSTR szDataSource,
IN LPCWSTR szMachineName,
IN LPWSTR szDefaultObjectName,
IN LPDWORD pcchBufferSize
)
{
DWORD dwDataSourceType = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try {
if (szDataSource != NULL) {
if (* szDataSource == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwDataSourceType = DataSourceTypeW(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultPerfObjectW(dwDataSourceType, szMachineName, szDefaultObjectName, pcchBufferSize);
}
return pdhStatus;
}
PDH_FUNCTION
PdhiGetDefaultPerfObjectA(
DWORD dwDataSource,
LPCSTR szMachineName,
LPSTR szDefaultObjectName,
LPDWORD pcchBufferSize
)
/*++
Routine Description:
Obtains the default performance object from the specified machine.
Arguments:
IN DWORD dwDataSourceType
IN LPCSTR szMachineName
NULL indicates the local machine, othewise this is the
name of the remote machine to query. If this machine is
not known to the PDH DLL, then it will be connected.
IN LPSTR szDefaultObjectName
pointer to the buffer that will receive the default object
name. This pointer can be NULL if the value of the DWORD
referenced by bcchBufferSize is 0.
IN LPDWORD pcchBufferSize
pointer to a DWORD containing the size of the buffer, in
characters, referenced by the szDefaultObjectName argument.
If the value of this DWORD is 0, then no data will be written
to the szDefaultObjectNameBuffer, however the required
buffer size will be returned in the DWORD referenced by
this pointer.
Return Value:
ERROR_SUCCESS if this function completes normally otherwise a PDH error.
PDH_INVALID_ARGUMENT a required argument is not correct or reserved
argument is not 0 or NULL.
PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
buffer could not be allocated.
PDH_CSTATUS_NO_COUNTERNAME is returned when the default object
name cannot be read or found.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
--*/
{
LPWSTR szWideName = NULL;
DWORD dwNameLength;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PPERF_MACHINE pMachine = NULL;
LONG lDefault;
DWORD dwStringLen;
DWORD dwLocalBufferSize = 0;
LPWSTR szDefault = NULL;
if (pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
goto Cleanup;
}
// test the access the arguments
__try {
if (szMachineName != NULL) {
if (* szMachineName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL machine Name is OK
if (pdhStatus == ERROR_SUCCESS) {
dwLocalBufferSize = * pcchBufferSize;
if (dwLocalBufferSize > 0) {
if (szDefaultObjectName != NULL) {
// test both ends of the caller's buffer for
// write access
szDefaultObjectName[0] = '\0';
szDefaultObjectName[dwLocalBufferSize -1] = '\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS && szMachineName != NULL) {
LPWSTR szTmpMachine = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szMachineName);
if (szTmpMachine == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else if (* szTmpMachine == '\\') {
szWideName = szTmpMachine;
}
else {
szWideName = G_ALLOC((lstrlenW(szTmpMachine) + 3) * sizeof(WCHAR));
if (szWideName == NULL) {
szWideName = szTmpMachine;
}
else {
StringCchPrintfW(szWideName,
lstrlenW(szTmpMachine) + 3,
L"%ws%ws",
cszDoubleBackSlash,
szTmpMachine);
G_FREE(szTmpMachine);
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
if (pdhStatus == ERROR_SUCCESS) {
pMachine = GetMachine(szWideName, 0, 0);
pdhStatus = (pMachine != NULL ? pMachine->dwStatus : GetLastError());
}
if (pMachine != NULL) {
if (pdhStatus == ERROR_SUCCESS) {
// only look at buffers from machines that are "on line"
lDefault = pMachine->pSystemPerfData->DefaultObject;
if ((lDefault > 0) && ((DWORD) lDefault < pMachine->dwLastPerfString)) {
// then there should be a string in the table
szDefault = (LPWSTR) PdhiLookupPerfNameByIndex(pMachine, lDefault);
if (szDefault != NULL) {
// determine string buffer length including term. NULL char
dwStringLen = dwLocalBufferSize;
pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
szDefault,
szDefaultObjectName,
& dwStringLen);
}
else {
// unable to find a matching counter name
pdhStatus = PDH_CSTATUS_NO_COUNTERNAME;
dwStringLen = 0;
}
}
else {
// string not in table
pdhStatus = PDH_CSTATUS_NO_COUNTERNAME;
dwStringLen = 0;
}
dwLocalBufferSize = dwStringLen;
}
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
} // else pass error pdhStatus on to the caller
break;
case DATA_SOURCE_WBEM:
case DATA_SOURCE_LOGFILE:
if (pdhStatus == ERROR_SUCCESS && dwDataSource == DATA_SOURCE_WBEM) {
pdhStatus = PdhiGetDefaultWbemObject(szWideName,
(LPVOID) szDefaultObjectName,
& dwLocalBufferSize,
FALSE); // ANSI function
}
else {
//log files don't support this (for now)
dwLocalBufferSize = 0;
}
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX (hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchBufferSize = dwLocalBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
Cleanup:
G_FREE(szWideName);
return pdhStatus;
}
PDH_FUNCTION
PdhGetDefaultPerfObjectHA(
IN HLOG hDataSource,
IN LPCSTR szMachineName,
IN LPSTR szDefaultObjectName,
IN LPDWORD pcchBufferSize
)
{
DWORD dwDataSourceType = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try {
dwDataSourceType = DataSourceTypeH(hDataSource);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultPerfObjectA(dwDataSourceType, szMachineName, szDefaultObjectName, pcchBufferSize);
}
return pdhStatus;
}
PDH_FUNCTION
PdhGetDefaultPerfObjectA(
IN LPCSTR szDataSource,
IN LPCSTR szMachineName,
IN LPSTR szDefaultObjectName,
IN LPDWORD pcchBufferSize
)
{
DWORD dwDataSourceType = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try {
if (szDataSource != NULL) {
if (* szDataSource == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwDataSourceType = DataSourceTypeA(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultPerfObjectA(dwDataSourceType, szMachineName, szDefaultObjectName, pcchBufferSize);
}
return pdhStatus;
}
PDH_FUNCTION
PdhiGetDefaultPerfCounterW(
IN DWORD dwDataSource,
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPWSTR szDefaultCounterName,
IN LPDWORD pcchBufferSize
)
/*++
Routine Description:
Obtains the default performance counter from the specified object on
the specified machine.
Arguments:
IN DWORD dwDataSource
IN LPCWSTR szMachineName
NULL indicates the local machine, othewise this is the
name of the remote machine to query. If this machine is
not known to the PDH DLL, then it will be connected.
IN LPCWSTR szObjectName
a pointer to the buffer that contains the name of the object
on the machine to find the default counter for.
IN LPWSTR szDefaultCounterName
pointer to the buffer that will receive the default counter
name. This pointer can be NULL if the value of the DWORD
referenced by bcchBufferSize is 0.
IN LPDWORD pcchBufferSize
pointer to a DWORD containing the size of the buffer, in
characters, referenced by the szDefaultObjectName argument.
If the value of this DWORD is 0, then no data will be written
to the szDefaultObjectNameBuffer, however the required
buffer size will be returned in the DWORD referenced by
this pointer.
Return Value:
ERROR_SUCCESS if this function completes normally otherwise a PDH error.
PDH_INVALID_ARGUMENT a required argument is not correct or reserved
argument is not 0 or NULL.
PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
buffer could not be allocated.
PDH_CSTATUS_NO_COUNTERNAME is returned when the name string for the
default counter could not be found.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
PDH_CSTATUS_NO_OBJECT is returned when the specified object could
not be found on the specified computer.
PDH_CSTATUS_NO_COUNTER is returned when the default counter is not
found in the data buffer.
--*/
{
PPERF_MACHINE pMachine;
PPERF_OBJECT_TYPE pObjectDef;
PPERF_COUNTER_DEFINITION pCounterDef;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
LONG lDefault;
DWORD dwStringLen;
DWORD dwLocalBufferSize = 0;
LPWSTR szDefault;
LPWSTR szThisMachine = NULL;
if (szObjectName == NULL || pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
// test the access the arguments
__try {
if (szMachineName != NULL) {
if (* szMachineName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL machine Name is OK
if (pdhStatus == ERROR_SUCCESS) {
if (szObjectName == NULL) {
// Null Object is not allowed
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (* szObjectName == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szObjectName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwLocalBufferSize = * pcchBufferSize;
if (dwLocalBufferSize > 0) {
if (szDefaultCounterName) {
// test both ends of the caller's buffer for
// write access
szDefaultCounterName[0] = L'\0';
szDefaultCounterName[dwLocalBufferSize - 1] = L'\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (szMachineName != NULL) {
DWORD dwMachineName = (* szMachineName == L'\\') ? (lstrlenW(szMachineName) + 1)
: (lstrlenW(szMachineName) + 3);
szThisMachine = G_ALLOC(dwMachineName * sizeof(WCHAR));
if (szThisMachine == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else if (* szMachineName == L'\\') {
StringCchCopyW(szThisMachine, dwMachineName, szMachineName);
}
else {
StringCchPrintfW(szThisMachine, dwMachineName, L"%ws%ws", cszDoubleBackSlash, szMachineName);
}
}
else {
szThisMachine = NULL;
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
pMachine = GetMachine((LPWSTR) szThisMachine, 0, PDH_GM_UPDATE_PERFNAME_ONLY);
if (pMachine == NULL) {
pdhStatus = GetLastError();
if (pdhStatus == ERROR_SUCCESS) pdhStatus = PDH_CSTATUS_NO_MACHINE;
}
else if (pMachine->dwStatus != ERROR_SUCCESS) {
pdhStatus = pMachine->dwStatus;
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
pMachine = NULL;
}
else {
DWORD dwObject = GetObjectId(pMachine, (LPWSTR) szObjectName, NULL);
if (dwObject == (DWORD) -1) {
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
if (pdhStatus == ERROR_SUCCESS) pdhStatus = PDH_CSTATUS_NO_OBJECT;
pMachine = NULL;
}
}
if (pMachine != NULL) {
if (pdhStatus == ERROR_SUCCESS) {
// get object pointer
pObjectDef = GetObjectDefByName(pMachine->pSystemPerfData,
pMachine->dwLastPerfString,
pMachine->szPerfStrings,
szObjectName);
if (pObjectDef != NULL) {
// default counter reference is an index into the list
// of counter definition entries so walk down list of
// counters defs to find the default one
if (pObjectDef->DefaultCounter > (LONG) pObjectDef->NumCounters) {
// Something wrong inside PERF_OBJ_DEF block. DefaultCounter
// should be in the range between 0 and NumCounters, but apparently
// it is not. Reset DefaultCounter to 0.
//
pObjectDef->DefaultCounter = 0;
}
if (pObjectDef->DefaultCounter < (LONG) pObjectDef->NumCounters) {
// then the default index should be this buffer
lDefault = 0;
pCounterDef = FirstCounter(pObjectDef);
while (pCounterDef != NULL && (lDefault < pObjectDef->DefaultCounter)
&& (lDefault < (LONG) pObjectDef->NumCounters)) {
pCounterDef = NextCounter(pObjectDef, pCounterDef);
lDefault ++;
}
lDefault = pCounterDef->CounterNameTitleIndex;
if ((lDefault > 0) && ((DWORD)lDefault < pMachine->dwLastPerfString)) {
// then there should be a string in the table
szDefault = (LPWSTR)PdhiLookupPerfNameByIndex(pMachine, lDefault);
if (szDefault != NULL) {
dwStringLen = lstrlenW(szDefault) + 1;
if (szDefaultCounterName != NULL && dwStringLen <= dwLocalBufferSize) {
StringCchCopyW(szDefaultCounterName, dwLocalBufferSize, szDefault);
pdhStatus = ERROR_SUCCESS;
}
else {
pdhStatus = PDH_MORE_DATA;
}
dwLocalBufferSize = dwStringLen;
}
else {
dwLocalBufferSize = 0;
pdhStatus = PDH_CSTATUS_NO_COUNTER;
}
}
else {
// string index is not valid
dwLocalBufferSize = 0;
pdhStatus = PDH_CSTATUS_NO_COUNTER;
}
}
else {
// the counter entry is not in the buffer
dwLocalBufferSize = 0;
pdhStatus = PDH_CSTATUS_NO_COUNTER;
}
}
else {
// unable to find object
dwLocalBufferSize = 0;
pdhStatus = PDH_CSTATUS_NO_OBJECT;
}
}
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
} // else pass pdhStatus value to caller
break;
case DATA_SOURCE_WBEM:
pdhStatus = PdhiGetDefaultWbemProperty(szThisMachine,
szObjectName,
szDefaultCounterName,
& dwLocalBufferSize,
TRUE);
break;
case DATA_SOURCE_LOGFILE:
dwLocalBufferSize = 0;
break;
default:
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX (hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchBufferSize = dwLocalBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
G_FREE(szThisMachine);
return pdhStatus;
}
PDH_FUNCTION
PdhGetDefaultPerfCounterHW(
IN HLOG hDataSource,
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPWSTR szDefaultCounterName,
IN LPDWORD pcchBufferSize
)
{
DWORD dwDataSourceType = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try {
dwDataSourceType = DataSourceTypeH(hDataSource);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultPerfCounterW(
dwDataSourceType, szMachineName, szObjectName, szDefaultCounterName, pcchBufferSize);
}
return pdhStatus;
}
PDH_FUNCTION
PdhGetDefaultPerfCounterW(
IN LPCWSTR szDataSource,
IN LPCWSTR szMachineName,
IN LPCWSTR szObjectName,
IN LPWSTR szDefaultCounterName,
IN LPDWORD pcchBufferSize
)
{
DWORD dwDataSourceType = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try {
if (szDataSource != NULL) {
if (* szDataSource == L'\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenW(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwDataSourceType = DataSourceTypeW(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultPerfCounterW(
dwDataSourceType, szMachineName, szObjectName, szDefaultCounterName, pcchBufferSize);
}
return pdhStatus;
}
PDH_FUNCTION
PdhiGetDefaultPerfCounterA(
DWORD dwDataSource,
LPCSTR szMachineName,
LPCSTR szObjectName,
LPSTR szDefaultCounterName,
LPDWORD pcchBufferSize
)
/*++
Routine Description:
Obtains the default performance counter from the specified object on
the specified machine.
Arguments:
IN DWORD dwDataSource
IN LPCSTR szMachineName
NULL indicates the local machine, othewise this is the
name of the remote machine to query. If this machine is
not known to the PDH DLL, then it will be connected.
IN LPCSTR szObjectName
a pointer to the buffer that contains the name of the object
on the machine to find the default counter for.
IN LPSTR szDefaultCounterName
pointer to the buffer that will receive the default counter
name. This pointer can be NULL if the value of the DWORD
referenced by bcchBufferSize is 0.
IN LPDWORD pcchBufferSize
pointer to a DWORD containing the size of the buffer, in
characters, referenced by the szDefaultObjectName argument.
If the value of this DWORD is 0, then no data will be written
to the szDefaultObjectNameBuffer, however the required
buffer size will be returned in the DWORD referenced by
this pointer.
Return Value:
ERROR_SUCCESS if this function completes normally otherwise a PDH error.
PDH_INVALID_ARGUMENT a required argument is not correct or reserved
argument is not 0 or NULL.
PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
buffer could not be allocated.
PDH_CSTATUS_NO_COUNTERNAME is returned when the name string for the
default counter could not be found.
PDH_CSTATUS_NO_MACHINE is returned when the specified machine
is offline or unavailable.
PDH_CSTATUS_NO_OBJECT is returned when the specified object could
not be found on the specified computer.
PDH_CSTATUS_NO_COUNTER is returned when the default counter is not
found in the data buffer.
--*/
{
LPWSTR szWideObject = NULL;
LPWSTR szWideName = NULL;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
PPERF_MACHINE pMachine = NULL;
PPERF_OBJECT_TYPE pObjectDef = NULL;
PPERF_COUNTER_DEFINITION pCounterDef;
LONG lDefault;
DWORD dwStringLen;
DWORD dwLocalBufferSize = 0;
LPWSTR szDefault;
if (szObjectName == NULL || pcchBufferSize == NULL) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else {
// test the access the arguments
__try {
if (szMachineName != NULL) {
if (* szMachineName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szMachineName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
} // else NULL machine Name is OK
if (pdhStatus == ERROR_SUCCESS) {
if (szObjectName != NULL) {
if (* szObjectName == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szObjectName) > PDH_MAX_COUNTER_NAME) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
else {
// null objects are not allowed
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwLocalBufferSize = * pcchBufferSize;
if (dwLocalBufferSize > 0) {
if (szDefaultCounterName != NULL) {
// test both ends of the caller's buffer for
// write access
szDefaultCounterName[0] = '\0';
szDefaultCounterName[dwLocalBufferSize -1] = '\0';
}
else {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
if (szMachineName != NULL) {
LPWSTR szTmpMachine = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szMachineName);
if (szTmpMachine == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
else if (* szMachineName == '\\') {
szWideName = szTmpMachine;
}
else {
szWideName = G_ALLOC((lstrlenW(szTmpMachine) + 3) * sizeof(WCHAR));
if (szWideName == NULL) {
szWideName = szTmpMachine;
}
else {
StringCchPrintfW(szWideName,
lstrlenW(szTmpMachine) + 3,
L"%ws%ws",
cszDoubleBackSlash,
szTmpMachine);
G_FREE(szTmpMachine);
}
}
}
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS) {
__try {
switch (dwDataSource) {
case DATA_SOURCE_REGISTRY:
szWideObject = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szObjectName);
if (szWideObject == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
if (pdhStatus == ERROR_SUCCESS) {
pMachine = GetMachine(szWideName, 0, PDH_GM_UPDATE_PERFNAME_ONLY);
if (pMachine == NULL) {
pdhStatus = GetLastError();
if (pdhStatus == ERROR_SUCCESS) pdhStatus = PDH_CSTATUS_NO_MACHINE;
}
else if (pMachine->dwStatus != ERROR_SUCCESS) {
pdhStatus = pMachine->dwStatus;
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
pMachine = NULL;
}
else {
DWORD dwObject = GetObjectId(pMachine, szWideObject, NULL);
if (dwObject == (DWORD) -1) {
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
if (pdhStatus == ERROR_SUCCESS) pdhStatus = PDH_CSTATUS_NO_OBJECT;
pMachine = NULL;
}
}
}
if (pdhStatus == ERROR_SUCCESS && pMachine != NULL) {
// get selected object
pObjectDef = GetObjectDefByName(pMachine->pSystemPerfData,
pMachine->dwLastPerfString,
pMachine->szPerfStrings,
szWideObject);
if (pObjectDef != NULL) {
// default counter reference is an index into the list
// of counter definition entries so walk down list of
// counters defs to find the default one
if (pObjectDef->DefaultCounter > (LONG) pObjectDef->NumCounters) {
// Something wrong inside PERF_OBJ_DEF block. DefaultCounter
// should be in the range between 0 and NumCounters, but apparently
// it is not. Reset DefaultCounter to 0.
//
pObjectDef->DefaultCounter = 0;
}
if (pObjectDef->DefaultCounter < (LONG) pObjectDef->NumCounters) {
// then the default index should be this buffer
lDefault = 0;
pCounterDef = FirstCounter(pObjectDef);
while (pCounterDef != NULL && (lDefault < pObjectDef->DefaultCounter)
&& (lDefault < (LONG) pObjectDef->NumCounters)) {
pCounterDef = NextCounter(pObjectDef, pCounterDef);
lDefault ++;
}
lDefault = pCounterDef->CounterNameTitleIndex;
if ((lDefault > 0) && ((DWORD) lDefault < pMachine->dwLastPerfString)) {
// then there should be a string in the table
szDefault = (LPWSTR) PdhiLookupPerfNameByIndex(pMachine, lDefault);
if (szDefault != NULL) {
dwStringLen = dwLocalBufferSize;
pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
szDefault,
szDefaultCounterName,
& dwStringLen);
dwLocalBufferSize = dwStringLen;
}
else {
dwLocalBufferSize = 0;
pdhStatus = PDH_CSTATUS_NO_COUNTER;
}
}
else {
// string index is not valid
dwLocalBufferSize = 0;
pdhStatus = PDH_CSTATUS_NO_COUNTER;
}
}
else {
// the counter entry is not in the buffer
dwLocalBufferSize = 0;
pdhStatus = PDH_CSTATUS_NO_COUNTER;
}
}
else {
// unable to find object
dwLocalBufferSize = 0;
pdhStatus = PDH_CSTATUS_NO_OBJECT;
}
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
}
G_FREE(szWideObject);
break;
case DATA_SOURCE_WBEM:
case DATA_SOURCE_LOGFILE:
if (pdhStatus == ERROR_SUCCESS && dwDataSource == DATA_SOURCE_WBEM) {
szWideObject = PdhiMultiByteToWideChar(_getmbcp(), (LPSTR) szObjectName);
if (szWideObject == NULL) {
pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultWbemProperty(szWideName,
szWideObject,
(LPVOID) szDefaultCounterName,
& dwLocalBufferSize,
FALSE); // ANSI function
G_FREE(szWideObject);
}
}
else {
//log files don't support this (for now)
dwLocalBufferSize = 0;
}
break;
default:
pdhStatus = PDH_INVALID_ARGUMENT;
break;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
RELEASE_MUTEX(hPdhDataMutex);
}
if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
__try {
* pcchBufferSize = dwLocalBufferSize;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
G_FREE(szWideName);
return pdhStatus;
}
PDH_FUNCTION
PdhGetDefaultPerfCounterHA(
IN HLOG hDataSource,
IN LPCSTR szMachineName,
IN LPCSTR szObjectName,
IN LPSTR szDefaultCounterName,
IN LPDWORD pcchBufferSize
)
{
DWORD dwDataSourceType = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try {
dwDataSourceType = DataSourceTypeH(hDataSource);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultPerfCounterA(
dwDataSourceType, szMachineName, szObjectName, szDefaultCounterName, pcchBufferSize);
}
return pdhStatus;
}
PDH_FUNCTION
PdhGetDefaultPerfCounterA(
IN LPCSTR szDataSource,
IN LPCSTR szMachineName,
IN LPCSTR szObjectName,
IN LPSTR szDefaultCounterName,
IN LPDWORD pcchBufferSize
)
{
DWORD dwDataSourceType = 0;
PDH_STATUS pdhStatus = ERROR_SUCCESS;
__try {
if (szDataSource != NULL) {
if (* szDataSource == '\0') {
pdhStatus = PDH_INVALID_ARGUMENT;
}
else if (lstrlenA(szDataSource) > PDH_MAX_DATASOURCE_PATH) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
}
if (pdhStatus == ERROR_SUCCESS) {
dwDataSourceType = DataSourceTypeA(szDataSource);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
pdhStatus = PDH_INVALID_ARGUMENT;
}
if (pdhStatus == ERROR_SUCCESS) {
pdhStatus = PdhiGetDefaultPerfCounterA(
dwDataSourceType, szMachineName, szObjectName, szDefaultCounterName, pcchBufferSize);
}
return pdhStatus;
}
PDH_FUNCTION
PdhBrowseCountersHW(
IN PPDH_BROWSE_DLG_CONFIG_HW pBrowseDlgData
)
{
PDHI_BROWSE_DLG_INFO pInfo;
LPWSTR szResource;
int nDlgReturn;
DWORD dwReturn = ERROR_SUCCESS;
pInfo.pWideStruct = (PPDH_BROWSE_DLG_CONFIG_W) pBrowseDlgData;
pInfo.pAnsiStruct = NULL;
if (pBrowseDlgData != NULL) {
__try {
// copy the data source since it wide characters already
pInfo.hDataSource = pBrowseDlgData->hDataSource;
szResource = MAKEINTRESOURCEW(pBrowseDlgData->bShowObjectBrowser
? IDD_BROWSE_OBJECTS
: pBrowseDlgData->bSingleCounterPerDialog ? IDD_BROWSE_COUNTERS_SIM : IDD_BROWSE_COUNTERS_EXT);
nDlgReturn = (int) DialogBoxParamW(ThisDLLHandle,
szResource,
pBrowseDlgData->hWndOwner,
BrowseCounterDlgProc,
(LPARAM) & pInfo);
if (nDlgReturn == -1) {
dwReturn = GetLastError();
}
else {
dwReturn = (nDlgReturn == IDOK) ? ERROR_SUCCESS : PDH_DIALOG_CANCELLED;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
dwReturn = PDH_INVALID_ARGUMENT;
}
}
else {
dwReturn = PDH_INVALID_ARGUMENT;
}
return dwReturn;
}
PDH_FUNCTION
PdhBrowseCountersHA(
IN PPDH_BROWSE_DLG_CONFIG_HA pBrowseDlgData)
{
PDHI_BROWSE_DLG_INFO pInfo;
LPWSTR szResource;
int nDlgReturn;
DWORD dwReturn = ERROR_SUCCESS;
pInfo.pAnsiStruct = (PPDH_BROWSE_DLG_CONFIG_A) pBrowseDlgData;
pInfo.pWideStruct = NULL;
if (pBrowseDlgData != NULL) {
__try {
// copy the data source since it wide characters already
pInfo.hDataSource = pBrowseDlgData->hDataSource;
szResource = MAKEINTRESOURCEW(pBrowseDlgData->bShowObjectBrowser
? IDD_BROWSE_OBJECTS
: pBrowseDlgData->bSingleCounterPerDialog ? IDD_BROWSE_COUNTERS_SIM : IDD_BROWSE_COUNTERS_EXT);
nDlgReturn = (int) DialogBoxParamW(ThisDLLHandle,
szResource,
pBrowseDlgData->hWndOwner,
BrowseCounterDlgProc,
(LPARAM) & pInfo);
if (nDlgReturn == -1) {
dwReturn = GetLastError();
}
else {
dwReturn = (nDlgReturn == IDOK) ? ERROR_SUCCESS : PDH_DIALOG_CANCELLED;
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
dwReturn = PDH_INVALID_ARGUMENT;
}
}
else {
dwReturn = PDH_INVALID_ARGUMENT;
}
return dwReturn;
}
PDH_FUNCTION
PdhBrowseCountersW(
IN PPDH_BROWSE_DLG_CONFIG_W pBrowseDlgData
)
{
PDHI_BROWSE_DLG_INFO pInfo;
LPWSTR szResource;
int nDlgReturn;
DWORD dwReturn = ERROR_SUCCESS;
pInfo.pWideStruct = pBrowseDlgData;
pInfo.pAnsiStruct = NULL;
if (pBrowseDlgData != NULL) {
__try {
DWORD dwDataSource = DataSourceTypeW (pBrowseDlgData->szDataSource);
if (dwDataSource == DATA_SOURCE_WBEM) {
pInfo.hDataSource = H_WBEM_DATASOURCE;
}
else if (dwDataSource == DATA_SOURCE_LOGFILE) {
DWORD dwLogType = 0;
dwReturn = PdhOpenLogW(pBrowseDlgData->szDataSource,
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
& dwLogType,
NULL,
0,
NULL,
& pInfo.hDataSource);
}
else {
pInfo.hDataSource = H_REALTIME_DATASOURCE;
}
if (dwReturn == ERROR_SUCCESS) {
szResource = MAKEINTRESOURCEW(pBrowseDlgData->bShowObjectBrowser
? IDD_BROWSE_OBJECTS
: pBrowseDlgData->bSingleCounterPerDialog ? IDD_BROWSE_COUNTERS_SIM
: IDD_BROWSE_COUNTERS_EXT);
nDlgReturn = (int) DialogBoxParamW(ThisDLLHandle,
szResource,
pBrowseDlgData->hWndOwner,
BrowseCounterDlgProc,
(LPARAM) & pInfo);
if (nDlgReturn == -1) {
dwReturn = GetLastError();
}
else {
dwReturn = nDlgReturn == IDOK ? ERROR_SUCCESS : PDH_DIALOG_CANCELLED;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
dwReturn = PDH_INVALID_ARGUMENT;
}
}
else {
dwReturn = PDH_INVALID_ARGUMENT;
}
return dwReturn;
}
PDH_FUNCTION
PdhBrowseCountersA(
IN PPDH_BROWSE_DLG_CONFIG_A pBrowseDlgData
)
{
PDHI_BROWSE_DLG_INFO pInfo;
LPWSTR szResource;
int nDlgReturn;
DWORD dwReturn = ERROR_SUCCESS;
pInfo.pAnsiStruct = pBrowseDlgData;
pInfo.pWideStruct = NULL;
if (pBrowseDlgData != NULL) {
__try {
DWORD dwDataSource = DataSourceTypeA(pBrowseDlgData->szDataSource);
if (dwDataSource == DATA_SOURCE_WBEM) {
pInfo.hDataSource = H_WBEM_DATASOURCE;
}
else if (dwDataSource == DATA_SOURCE_LOGFILE) {
DWORD dwLogType = 0;
dwReturn = PdhOpenLogA(pBrowseDlgData->szDataSource,
PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
& dwLogType,
NULL,
0,
NULL,
& pInfo.hDataSource);
}
else {
pInfo.hDataSource = H_REALTIME_DATASOURCE;
}
if (dwReturn == ERROR_SUCCESS) {
szResource = MAKEINTRESOURCEW(pBrowseDlgData->bShowObjectBrowser
? IDD_BROWSE_OBJECTS
: pBrowseDlgData->bSingleCounterPerDialog ? IDD_BROWSE_COUNTERS_SIM
: IDD_BROWSE_COUNTERS_EXT);
nDlgReturn = (int) DialogBoxParamW(ThisDLLHandle,
szResource,
pBrowseDlgData->hWndOwner,
BrowseCounterDlgProc,
(LPARAM) & pInfo);
if (nDlgReturn == -1) {
dwReturn = GetLastError();
}
else {
dwReturn = nDlgReturn == IDOK ? ERROR_SUCCESS : PDH_DIALOG_CANCELLED;
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
dwReturn = PDH_INVALID_ARGUMENT;
}
}
else {
dwReturn = PDH_INVALID_ARGUMENT;
}
return dwReturn;
}
LPWSTR
PdhiGetExplainText(
LPCWSTR szMachineName,
LPCWSTR szObjectName,
LPCWSTR szCounterName
)
{
PPERF_MACHINE pMachine;
PPERF_OBJECT_TYPE pObjectDef;
PPERF_COUNTER_DEFINITION pCounterDef;
LPWSTR szReturnString = NULL;
pMachine = GetMachine((LPWSTR) szMachineName, 0, PDH_GM_UPDATE_PERFNAME_ONLY);
if (pMachine != NULL) {
DWORD dwObject = (pMachine->dwStatus == ERROR_SUCCESS)
? GetObjectId(pMachine, (LPWSTR) szObjectName, NULL) : (DWORD) -1;
if (dwObject == (DWORD) -1) {
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
pMachine = NULL;
}
}
if (pMachine != NULL) {
// make sure the machine connection is valid
if (pMachine->dwStatus == ERROR_SUCCESS) {
pObjectDef = GetObjectDefByName(pMachine->pSystemPerfData,
pMachine->dwLastPerfString,
pMachine->szPerfStrings,
szObjectName);
if (pObjectDef != NULL) {
if (szCounterName != NULL) {
pCounterDef = GetCounterDefByName(pObjectDef,
pMachine->dwLastPerfString,
pMachine->szPerfStrings,
(LPWSTR) szCounterName);
if ((pCounterDef != NULL) &&
(pCounterDef->CounterHelpTitleIndex <= pMachine->dwLastPerfString)) {
// return string from array
szReturnString = pMachine->szPerfStrings[pCounterDef->CounterHelpTitleIndex];
}
}
else if (pObjectDef->ObjectHelpTitleIndex <= pMachine->dwLastPerfString) {
szReturnString = pMachine->szPerfStrings[pObjectDef->ObjectHelpTitleIndex];
}
}
}
pMachine->dwRefCount --;
RELEASE_MUTEX(pMachine->hMutex);
}
return szReturnString;
}
BOOL
IsWbemDataSource(
LPCWSTR szDataSource
)
{
BOOL bReturn = FALSE;
__try {
if (DataSourceTypeW(szDataSource) == DATA_SOURCE_WBEM)
bReturn = TRUE;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
SetLastError(GetExceptionCode());
}
return bReturn;
}