|
|
/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
perfdata.c
Abstract:
<abstract>
--*/ #include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winperf.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <tchar.h>
#include <mbctype.h>
#include "pdhitype.h"
#include "pdhidef.h"
#include "perftype.h"
#include "perfdata.h"
#include "pdhmsg.h"
#include "strings.h"
// the following strings are for getting texts from perflib
#define OLD_VERSION 0x010000
#define tohexdigit(x) ((CHAR) (((x) < 10) ? ((x) + L'0') : ((x) + L'a' - 10)))
DWORD PdhiMakePerfPrimaryLangId( IN LANGID lID, OUT LPWSTR szBuffer ) { WCHAR LangId; WCHAR nDigit;
LangId = (WCHAR) PRIMARYLANGID(lID); nDigit = (WCHAR) (LangId >> 8); szBuffer[0] = tohexdigit(nDigit); nDigit = (WCHAR) (LangId & 0XF0) >> 4; szBuffer[1] = tohexdigit(nDigit); nDigit = (WCHAR) (LangId & 0xF); szBuffer[2] = tohexdigit(nDigit); szBuffer[3] = L'\0';
return ERROR_SUCCESS; }
BOOL IsMatchingInstance ( PERF_INSTANCE_DEFINITION *pInstanceDef, DWORD dwCodePage, LPWSTR szInstanceNameToMatch, DWORD dwInstanceNameLength ) // compares pInstanceName to the name in the instance
{ DWORD dwThisInstanceNameLength; LPWSTR szThisInstanceName = NULL; WCHAR szBufferForANSINames[MAX_PATH];
ZeroMemory(szBufferForANSINames, sizeof(WCHAR) * MAX_PATH); if (dwInstanceNameLength == 0) { // get the length to compare
dwInstanceNameLength = lstrlenW (szInstanceNameToMatch); }
if (dwCodePage == 0) { // try to take a shortcut here if it's a unicode string
// compare to the length of the shortest string
// get the pointer to this string
szThisInstanceName = GetInstanceName(pInstanceDef);
// convert instance Name from bytes to chars
dwThisInstanceNameLength = pInstanceDef->NameLength / sizeof(WCHAR);
// see if this length includes the term. null. If so shorten it
if (szThisInstanceName[dwThisInstanceNameLength-1] == 0) { dwThisInstanceNameLength--; } } else { // go the long way and read/translate/convert the string
dwThisInstanceNameLength =GetInstanceNameStr (pInstanceDef, szBufferForANSINames, dwCodePage); if (dwThisInstanceNameLength > 0) { szThisInstanceName = &szBufferForANSINames[0]; } }
// if the lengths are not equal then the names can't be either
if (dwInstanceNameLength != dwThisInstanceNameLength) { return FALSE; } else { if (szThisInstanceName != NULL) { if (lstrcmpiW(szInstanceNameToMatch, szThisInstanceName) == 0) { // this is a match
return TRUE; } else { // this is not a match
return FALSE; } } else { // this is not a match
return FALSE; } } }
LPWSTR *BuildNameTable( LPWSTR szComputerName, // computer to query names from
LANGID LangId, // language ID
PPERF_MACHINE pMachine // update member fields
) /*++
BuildNameTable
Arguments:
hKeyRegistry Handle to an open registry (this can be local or remote.) and is the value returned by RegConnectRegistry or a default key.
lpszLangId The unicode id of the language to look up. (default is 409)
Return Value:
pointer to an allocated table. (the caller must free it when finished!) the table is an array of pointers to zero terminated strings. NULL is returned if an error occured.
--*/ { LPWSTR *lpCounterId; LPWSTR lpCounterNames; LPWSTR lpHelpText;
LPWSTR lpThisName;
LONG lWin32Status = ERROR_SUCCESS; DWORD dwLastError; DWORD dwValueType; DWORD dwArraySize; DWORD dwBufferSize; DWORD dwCounterSize = 0; DWORD dwHelpSize = 0; DWORD dw009CounterSize = 0; DWORD dw009HelpSize = 0; DWORD dwThisCounter; DWORD dwLastCounter;
DWORD dwSystemVersion; DWORD dwLastId; DWORD dwLastHelpId;
HKEY hKeyRegistry = NULL; HKEY hKeyValue = NULL; HKEY hKeyNames = NULL; HKEY hKey009Names = NULL;
LPWSTR lpValueNameString; LPWSTR lp009ValueNameString; WCHAR CounterNameBuffer[50]; WCHAR HelpNameBuffer[50]; WCHAR Counter009NameBuffer[50]; WCHAR Help009NameBuffer[50]; WCHAR lpszLangId[16]; BOOL bUse009Locale = FALSE; BOOL bUsePerfTextKey = TRUE;
lpValueNameString = NULL; //initialize to NULL
lp009ValueNameString = NULL; pMachine->szPerfStrings = NULL; pMachine->sz009PerfStrings = NULL; pMachine->typePerfStrings = NULL;
if (szComputerName == NULL) { // use local machine
hKeyRegistry = HKEY_LOCAL_MACHINE; } else { if ((lWin32Status = RegConnectRegistryW(szComputerName, HKEY_LOCAL_MACHINE, & hKeyRegistry)) != ERROR_SUCCESS) { // unable to connect to registry
goto BNT_BAILOUT; } }
// check for null arguments and insert defaults if necessary
if ( (LangId == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US)) || (PRIMARYLANGID(LangId) == LANG_ENGLISH)) { bUse009Locale = TRUE; } PdhiMakePerfPrimaryLangId(LangId, lpszLangId);
// open registry to get number of items for computing array size
lWin32Status = RegOpenKeyExW ( hKeyRegistry, cszNamesKey, RESERVED, KEY_READ, &hKeyValue);
if (lWin32Status != ERROR_SUCCESS) { goto BNT_BAILOUT; }
// get last update time of registry key
lWin32Status = RegQueryInfoKey ( hKeyValue, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, & pMachine->LastStringUpdateTime);
// get number of items
dwBufferSize = sizeof (dwLastHelpId); lWin32Status = RegQueryValueExW ( hKeyValue, cszLastHelp, RESERVED, &dwValueType, (LPBYTE)&dwLastHelpId, &dwBufferSize);
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { goto BNT_BAILOUT; }
// get number of items
dwBufferSize = sizeof (dwLastId); lWin32Status = RegQueryValueExW ( hKeyValue, cszLastCounter, RESERVED, &dwValueType, (LPBYTE)&dwLastId, &dwBufferSize);
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { goto BNT_BAILOUT; }
if (dwLastId < dwLastHelpId) dwLastId = dwLastHelpId;
dwArraySize = (dwLastId + 1) * sizeof(LPWSTR);
// get Perflib system version
dwBufferSize = sizeof (dwSystemVersion); lWin32Status = RegQueryValueExW ( hKeyValue, cszVersionName, RESERVED, &dwValueType, (LPBYTE)&dwSystemVersion, &dwBufferSize);
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { dwSystemVersion = OLD_VERSION; }
if (dwSystemVersion == OLD_VERSION) { // get names from registry
lpValueNameString = G_ALLOC ( lstrlenW(cszNamesKey) * sizeof (WCHAR) + lstrlenW(cszBackSlash) * sizeof (WCHAR) + lstrlenW(lpszLangId) * sizeof (WCHAR) + sizeof (UNICODE_NULL));
if (!lpValueNameString) goto BNT_BAILOUT;
lstrcpyW (lpValueNameString, cszNamesKey); lstrcatW (lpValueNameString, cszBackSlash); lstrcatW (lpValueNameString, lpszLangId);
lWin32Status = RegOpenKeyExW ( hKeyRegistry, lpValueNameString, RESERVED, KEY_READ, &hKeyNames); if (! bUse009Locale && lWin32Status == ERROR_SUCCESS) { lp009ValueNameString = G_ALLOC(sizeof(UNICODE_NULL) + lstrlenW(cszNamesKey) * sizeof (WCHAR) + lstrlenW(cszBackSlash) * sizeof (WCHAR) + lstrlenW(cszDefaultLangId) * sizeof (WCHAR)); if (!lpValueNameString) goto BNT_BAILOUT;
lstrcpyW (lpValueNameString, cszNamesKey); lstrcatW (lpValueNameString, cszBackSlash); lstrcatW (lpValueNameString, cszDefaultLangId); lWin32Status = RegOpenKeyExW(hKeyRegistry, lp009ValueNameString, RESERVED, KEY_READ, & hKey009Names); } } else { __try { if (bUse009Locale == FALSE) { if ((lWin32Status = RegConnectRegistryW(szComputerName, HKEY_PERFORMANCE_NLSTEXT, & hKeyNames)) == ERROR_SUCCESS) { if ((lWin32Status = RegConnectRegistryW(szComputerName, HKEY_PERFORMANCE_TEXT, & hKey009Names)) != ERROR_SUCCESS) { bUsePerfTextKey = FALSE; RegCloseKey(hKeyNames); } } else { bUsePerfTextKey = FALSE; } } else { if ((lWin32Status = RegConnectRegistryW(szComputerName, HKEY_PERFORMANCE_TEXT, & hKeyNames)) != ERROR_SUCCESS) { bUsePerfTextKey = FALSE; } else { hKey009Names = hKeyNames; } } } __except (EXCEPTION_EXECUTE_HANDLER) { bUsePerfTextKey = FALSE; } }
if (! bUsePerfTextKey) { lstrcpyW(CounterNameBuffer, cszCounterName); lstrcatW(CounterNameBuffer, lpszLangId); lstrcpyW(HelpNameBuffer, cszHelpName); lstrcatW(HelpNameBuffer, lpszLangId); lstrcpyW(Counter009NameBuffer, cszCounterName); lstrcatW(Counter009NameBuffer, cszDefaultLangId); lstrcpyW(Help009NameBuffer, cszHelpName); lstrcatW(Help009NameBuffer, cszDefaultLangId);
// cannot open HKEY_PERFORMANCE_TEXT, try the old way
//
if (szComputerName == NULL) { hKeyNames = HKEY_PERFORMANCE_DATA; } else if ((lWin32Status = RegConnectRegistryW(szComputerName, HKEY_PERFORMANCE_DATA, & hKeyNames)) != ERROR_SUCCESS) { goto BNT_BAILOUT; } hKey009Names = hKeyNames; } else { lstrcpyW(CounterNameBuffer, cszCounters); lstrcpyW(HelpNameBuffer, cszHelp); lstrcpyW(Counter009NameBuffer, cszCounters); lstrcpyW(Help009NameBuffer, cszHelp); }
// get size of counter names and add that to the arrays
if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwBufferSize = 0; lWin32Status = RegQueryValueExW( hKeyNames, CounterNameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dwCounterSize = dwBufferSize;
if (! bUse009Locale) { dwBufferSize = 0; lWin32Status = RegQueryValueExW(hKey009Names, Counter009NameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dw009CounterSize = dwBufferSize; } else { dw009CounterSize = dwCounterSize; }
// get size of counter names and add that to the arrays
if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwBufferSize = 0; lWin32Status = RegQueryValueExW( hKeyNames, HelpNameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dwHelpSize = dwBufferSize;
if (! bUse009Locale) { dwBufferSize = 0; lWin32Status = RegQueryValueExW(hKey009Names, Help009NameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT; dw009HelpSize = dwBufferSize; } else { dw009HelpSize = dwHelpSize; }
pMachine->szPerfStrings = G_ALLOC(dwArraySize + dwCounterSize + dwHelpSize); if (! pMachine->szPerfStrings) goto BNT_BAILOUT;
if (bUse009Locale) { pMachine->sz009PerfStrings = pMachine->szPerfStrings; } else { pMachine->sz009PerfStrings = G_ALLOC(dwArraySize + dw009CounterSize + dw009HelpSize); if (! pMachine->sz009PerfStrings) goto BNT_BAILOUT; }
pMachine->typePerfStrings = G_ALLOC(dwLastId + 1); if (! pMachine->typePerfStrings) goto BNT_BAILOUT;
// initialize pointers into buffer
lpCounterId = pMachine->szPerfStrings; lpCounterNames = (LPWSTR)((LPBYTE)lpCounterId + dwArraySize); lpHelpText = (LPWSTR)((LPBYTE)lpCounterNames + dwCounterSize);
// read counters into memory
dwBufferSize = dwCounterSize; lWin32Status = RegQueryValueExW ( hKeyNames, CounterNameBuffer, RESERVED, & dwValueType, (LPVOID)lpCounterNames, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwBufferSize = dwHelpSize; lWin32Status = RegQueryValueExW ( hKeyNames, HelpNameBuffer, RESERVED, & dwValueType, (LPVOID)lpHelpText, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
// load counter array items
dwLastCounter = 0; for (lpThisName = lpCounterNames; *lpThisName; lpThisName += (lstrlenW(lpThisName)+1) ) {
// first string should be an integer (in decimal unicode digits)
dwThisCounter = wcstoul (lpThisName, NULL, 10);
// check for registry corruption. This shouldn't occur under
// normal conditions
assert (dwThisCounter > dwLastCounter);
// point to corresponding counter name
lpThisName += (lstrlenW(lpThisName)+1);
// and load array element;
if ((dwThisCounter > 0) && (dwThisCounter <= dwLastId)) { lpCounterId[dwThisCounter] = lpThisName; pMachine->typePerfStrings[dwThisCounter] = STR_COUNTER; dwLastCounter = dwThisCounter; } }
dwLastCounter = 0; for (lpThisName = lpHelpText; *lpThisName; lpThisName += (lstrlenW(lpThisName)+1) ) {
// first string should be an integer (in decimal unicode digits)
dwThisCounter = wcstoul (lpThisName, NULL, 10);
// check for registry corruption. This shouldn't occur under
// normal conditions
assert (dwThisCounter > dwLastCounter);
// point to corresponding counter name
lpThisName += (lstrlenW(lpThisName)+1);
// and load array element;
if ((dwThisCounter > 0) && (dwThisCounter <= dwLastId)) { lpCounterId[dwThisCounter] = lpThisName; pMachine->typePerfStrings[dwThisCounter] = STR_HELP; dwLastCounter = dwThisCounter; } }
lpCounterId = pMachine->sz009PerfStrings; lpCounterNames = (LPWSTR) ((LPBYTE) lpCounterId + dwArraySize); lpHelpText = (LPWSTR) ((LPBYTE) lpCounterNames + dw009CounterSize);
// read counters into memory
dwBufferSize = dw009CounterSize; lWin32Status = RegQueryValueExW(hKey009Names, Counter009NameBuffer, RESERVED, & dwValueType, (LPVOID) lpCounterNames, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwBufferSize = dw009HelpSize; lWin32Status = RegQueryValueExW(hKey009Names, Help009NameBuffer, RESERVED, & dwValueType, (LPVOID) lpHelpText, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
for ( lpThisName = lpCounterNames; * lpThisName; lpThisName += (lstrlenW(lpThisName) + 1)) { dwThisCounter = wcstoul(lpThisName, NULL, 10); lpThisName += (lstrlenW(lpThisName) + 1); if ((dwThisCounter > 0) && (dwThisCounter <= dwLastId)) { lpCounterId[dwThisCounter] = lpThisName; } }
for ( lpThisName = lpHelpText; * lpThisName; lpThisName += (lstrlenW(lpThisName) + 1) ) { dwThisCounter = wcstoul (lpThisName, NULL, 10); lpThisName += (lstrlenW(lpThisName) + 1); if ((dwThisCounter > 0) && (dwThisCounter <= dwLastId)) { lpCounterId[dwThisCounter] = lpThisName; } }
pMachine->dwLastPerfString = dwLastId;
if (lpValueNameString) G_FREE ((LPVOID) lpValueNameString); if (lp009ValueNameString) G_FREE ((LPVOID) lp009ValueNameString);
RegCloseKey(hKeyValue);
if (hKey009Names && hKey009Names != hKeyNames) RegCloseKey(hKey009Names); RegCloseKey(hKeyNames); if (hKeyRegistry && hKeyRegistry != HKEY_LOCAL_MACHINE) RegCloseKey(hKeyRegistry); return pMachine->szPerfStrings;
BNT_BAILOUT: if (lWin32Status != ERROR_SUCCESS) { dwLastError = GetLastError(); }
if (lpValueNameString) { G_FREE ((LPVOID)lpValueNameString); }
if ( pMachine->sz009PerfStrings && pMachine->sz009PerfStrings != pMachine->szPerfStrings) { G_FREE(pMachine->sz009PerfStrings); } if (pMachine->szPerfStrings) { G_FREE(pMachine->szPerfStrings); } if (pMachine->typePerfStrings) { G_FREE(pMachine->typePerfStrings); }
if (hKeyValue) RegCloseKey(hKeyValue); if (hKey009Names && hKey009Names != hKeyNames) RegCloseKey(hKey009Names); if (hKeyNames) RegCloseKey(hKeyNames); if (hKeyRegistry) RegCloseKey(hKeyRegistry);
return NULL; }
#pragma warning ( disable : 4127 )
PERF_OBJECT_TYPE * GetObjectDefByTitleIndex( IN PERF_DATA_BLOCK *pDataBlock, IN DWORD ObjectTypeTitleIndex ) { DWORD NumTypeDef;
PERF_OBJECT_TYPE *pObjectDef = NULL; PERF_OBJECT_TYPE *pReturnObject = NULL; PERF_OBJECT_TYPE *pEndOfBuffer = NULL;
__try {
pObjectDef = FirstObject(pDataBlock); pEndOfBuffer = (PPERF_OBJECT_TYPE) ((DWORD_PTR)pDataBlock + pDataBlock->TotalByteLength);
assert (pObjectDef != NULL);
NumTypeDef = 0; while (1) { if ( pObjectDef->ObjectNameTitleIndex == ObjectTypeTitleIndex ) { pReturnObject = pObjectDef; break; } else { NumTypeDef++; if (NumTypeDef < pDataBlock->NumObjectTypes) { pObjectDef = NextObject(pObjectDef); //make sure next object is legit
if (pObjectDef != NULL) { if (pObjectDef->TotalByteLength > 0) { if (pObjectDef >= pEndOfBuffer) { // looks like we ran off the end of the data buffer
assert (pObjectDef < pEndOfBuffer); break; } } else { // 0-length object buffer returned
assert (pObjectDef->TotalByteLength > 0); break; } } else { // and continue
assert (pObjectDef != NULL); break; } } else { // no more data objects in this data block
break; } } } } __except (EXCEPTION_EXECUTE_HANDLER) { pReturnObject = NULL; } return pReturnObject; }
PERF_OBJECT_TYPE * GetObjectDefByName ( IN PERF_DATA_BLOCK *pDataBlock, IN DWORD dwLastNameIndex, IN LPCWSTR *NameArray, IN LPCWSTR szObjectName ) { DWORD NumTypeDef; PERF_OBJECT_TYPE *pReturnObject = NULL; PERF_OBJECT_TYPE *pObjectDef = NULL; PERF_OBJECT_TYPE *pEndOfBuffer = NULL;
__try {
pObjectDef = FirstObject(pDataBlock); pEndOfBuffer = (PPERF_OBJECT_TYPE) ((DWORD_PTR)pDataBlock + pDataBlock->TotalByteLength);
assert (pObjectDef != NULL);
NumTypeDef = 0; while (1) { if ( pObjectDef->ObjectNameTitleIndex < dwLastNameIndex ) { // look up name of object & compare
if (lstrcmpiW(NameArray[pObjectDef->ObjectNameTitleIndex], szObjectName) == 0) { pReturnObject = pObjectDef; break; } } NumTypeDef++; if (NumTypeDef < pDataBlock->NumObjectTypes) { pObjectDef = NextObject(pObjectDef); // get next
//make sure next object is legit
if (pObjectDef != NULL) { if (pObjectDef->TotalByteLength > 0) { if (pObjectDef >= pEndOfBuffer) { // looks like we ran off the end of the data buffer
assert (pObjectDef < pEndOfBuffer); break; } } else { // 0-length object buffer returned
assert (pObjectDef->TotalByteLength > 0); break; } } else { // null pointer
assert (pObjectDef != NULL); break; } } else { // end of data block
break; } } } __except (EXCEPTION_EXECUTE_HANDLER) { pReturnObject = NULL; } return pReturnObject; } #pragma warning ( default : 4127 )
PERF_INSTANCE_DEFINITION * GetInstance( IN PERF_OBJECT_TYPE *pObjectDef, IN LONG InstanceNumber ) {
PERF_INSTANCE_DEFINITION *pInstanceDef; LONG NumInstance;
if (!pObjectDef) { return 0; }
pInstanceDef = FirstInstance(pObjectDef);
for ( NumInstance = 0; NumInstance < pObjectDef->NumInstances; NumInstance++ ) { if ( InstanceNumber == NumInstance ) { return pInstanceDef; } pInstanceDef = NextInstance(pInstanceDef); }
return NULL; }
PERF_INSTANCE_DEFINITION * GetInstanceByUniqueId( IN PERF_OBJECT_TYPE *pObjectDef, IN LONG InstanceUniqueId ) {
PERF_INSTANCE_DEFINITION *pInstanceDef; LONG NumInstance;
if (!pObjectDef) { return 0; }
pInstanceDef = FirstInstance(pObjectDef);
for ( NumInstance = 0; NumInstance < pObjectDef->NumInstances; NumInstance++ ) { if ( InstanceUniqueId == pInstanceDef->UniqueID ) { return pInstanceDef; } pInstanceDef = NextInstance(pInstanceDef); }
return NULL; }
DWORD GetAnsiInstanceName (PPERF_INSTANCE_DEFINITION pInstance, LPWSTR lpszInstance, DWORD dwCodePage) { LPSTR szSource; DWORD dwLength;
szSource = (LPSTR)GetInstanceName(pInstance);
// the locale should be set here
DBG_UNREFERENCED_PARAMETER(dwCodePage);
// pInstance->NameLength == the number of bytes (chars) in the string
dwLength = (DWORD) MultiByteToWideChar(_getmbcp(), 0, szSource, lstrlenA(szSource), (LPWSTR) lpszInstance, pInstance->NameLength); lpszInstance[dwLength] = 0; // null terminate string buffer
return dwLength; }
DWORD GetUnicodeInstanceName (PPERF_INSTANCE_DEFINITION pInstance, LPWSTR lpszInstance) { LPWSTR wszSource; DWORD dwLength;
wszSource = GetInstanceName(pInstance) ;
// pInstance->NameLength == length of string in BYTES so adjust to
// number of wide characters here
dwLength = pInstance->NameLength / sizeof(WCHAR);
wcsncpy (lpszInstance, (LPWSTR)wszSource, dwLength);
// add null termination if string length does not include the null
if ((dwLength > 0) && (lpszInstance[dwLength-1] != 0)) { // i.e. it's the last character of the string
lpszInstance[dwLength] = 0; // then add a terminating null char to the string
} else { // assume that the length value includes the terminating NULL
// so adjust value to indicate chars only
dwLength--; }
return (dwLength); // just incase there's null's in the string
}
DWORD GetInstanceNameStr (PPERF_INSTANCE_DEFINITION pInstance, LPWSTR lpszInstance, DWORD dwCodePage) { DWORD dwCharSize; DWORD dwLength = 0;
if (pInstance != NULL) { if (lpszInstance != NULL) { if (dwCodePage > 0) { dwCharSize = sizeof(CHAR); dwLength = GetAnsiInstanceName (pInstance, lpszInstance, dwCodePage); } else { // it's a UNICODE name
dwCharSize = sizeof(WCHAR); dwLength = GetUnicodeInstanceName (pInstance, lpszInstance); } // sanity check here...
// the returned string length (in characters) plus the terminating NULL
// should be the same as the specified length in bytes divided by the
// character size. If not then the codepage and instance data type
// don't line up so test that here
if ((dwLength + 1) != (pInstance->NameLength / dwCharSize)) { // something isn't quite right so try the "other" type of string type
if (dwCharSize == sizeof(CHAR)) { // then we tried to read it as an ASCII string and that didn't work
// so try it as a UNICODE (if that doesn't work give up and return
// it any way.
dwLength = GetUnicodeInstanceName (pInstance, lpszInstance); } else if (dwCharSize == sizeof(WCHAR)) { // then we tried to read it as a UNICODE string and that didn't work
// so try it as an ASCII string (if that doesn't work give up and return
// it any way.
dwLength = GetAnsiInstanceName (pInstance, lpszInstance, dwCodePage); } } } // else return buffer is null
} else { // no instance def object is specified so return an empty string
*lpszInstance = 0; }
return dwLength; }
PERF_INSTANCE_DEFINITION * GetInstanceByNameUsingParentTitleIndex( PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectDef, LPWSTR pInstanceName, LPWSTR pParentName, DWORD dwIndex ) { BOOL fHaveParent; PERF_OBJECT_TYPE *pParentObj;
PERF_INSTANCE_DEFINITION *pParentInst, *pInstanceDef;
LONG NumInstance; DWORD dwLocalIndex;
DWORD dwInstanceNameLength;
fHaveParent = FALSE; pInstanceDef = FirstInstance(pObjectDef);
if (pInstanceDef == NULL) return NULL;
dwLocalIndex = dwIndex;
dwInstanceNameLength = lstrlenW(pInstanceName);
for ( NumInstance = 0; NumInstance < pObjectDef->NumInstances; NumInstance++ ) { if (IsMatchingInstance (pInstanceDef, pObjectDef->CodePage, pInstanceName, dwInstanceNameLength)) { // Instance name matches
if ( pParentName == NULL ) {
// No parent, we're done if this is the right "copy"
if (dwLocalIndex == 0) { return pInstanceDef; } else { --dwLocalIndex; }
} else {
// Must match parent as well
pParentObj = GetObjectDefByTitleIndex( pDataBlock, pInstanceDef->ParentObjectTitleIndex);
if (!pParentObj) { // can't locate the parent, forget it
break ; }
// Object type of parent found; now find parent
// instance
pParentInst = GetInstance(pParentObj, pInstanceDef->ParentObjectInstance);
if (!pParentInst) { // can't locate the parent instance, forget it
break ; }
if (IsMatchingInstance (pParentInst, pParentObj->CodePage, pParentName, 0)) { // Parent Instance Name matches that passed in
if (dwLocalIndex == 0) { return pInstanceDef; } else { --dwLocalIndex; } } } } pInstanceDef = NextInstance(pInstanceDef); if (pInstanceDef == NULL) return NULL; } return 0; }
PERF_INSTANCE_DEFINITION * GetInstanceByName( PERF_DATA_BLOCK *pDataBlock, PERF_OBJECT_TYPE *pObjectDef, LPWSTR pInstanceName, LPWSTR pParentName, DWORD dwIndex ) { BOOL fHaveParent;
PERF_OBJECT_TYPE *pParentObj;
PERF_INSTANCE_DEFINITION *pParentInst, *pInstanceDef;
LONG NumInstance; DWORD dwLocalIndex; DWORD dwInstanceNameLength;
fHaveParent = FALSE; pInstanceDef = FirstInstance(pObjectDef); if (pInstanceDef == NULL) return NULL;
dwLocalIndex = dwIndex; assert (pInstanceDef != NULL);
dwInstanceNameLength = lstrlenW(pInstanceName);
for ( NumInstance = 0; NumInstance < pObjectDef->NumInstances; NumInstance++ ) {
if (IsMatchingInstance (pInstanceDef, pObjectDef->CodePage, pInstanceName, dwInstanceNameLength)) {
// Instance name matches
if (( !pInstanceDef->ParentObjectTitleIndex ) || (pParentName == NULL)){
// No parent, we're done
if (dwLocalIndex == 0) { return pInstanceDef; } else { --dwLocalIndex; }
} else {
// Must match parent as well
pParentObj = GetObjectDefByTitleIndex( pDataBlock, pInstanceDef->ParentObjectTitleIndex);
// if parent object is not found,
// then exit and return NULL
if (pParentObj == NULL) return NULL;
// Object type of parent found; now find parent
// instance
pParentInst = GetInstance(pParentObj, pInstanceDef->ParentObjectInstance);
if (pParentInst != NULL) {
if (IsMatchingInstance (pParentInst, pParentObj->CodePage, pParentName, 0)) {
// Parent Instance Name matches that passed in
if (dwLocalIndex == 0) { return pInstanceDef; } else { --dwLocalIndex; } } } else { // continue
} } } pInstanceDef = NextInstance(pInstanceDef); if (pInstanceDef == NULL) return NULL; } return 0; } // GetInstanceByName
PERF_COUNTER_DEFINITION * GetCounterDefByName ( IN PERF_OBJECT_TYPE *pObject, IN DWORD dwLastNameIndex, IN LPWSTR *NameArray, IN LPWSTR szCounterName ) { DWORD NumTypeDef; PERF_COUNTER_DEFINITION *pThisCounter;
pThisCounter = FirstCounter(pObject); // no counter found so bail out
if (pThisCounter == NULL) return NULL;
for ( NumTypeDef = 0; NumTypeDef < pObject->NumCounters; NumTypeDef++ ) {
if ((pThisCounter->CounterNameTitleIndex > 0) && (pThisCounter->CounterNameTitleIndex < dwLastNameIndex )) { // look up name of counter & compare
if (lstrcmpiW(NameArray[pThisCounter->CounterNameTitleIndex], szCounterName) == 0) { return pThisCounter; } } pThisCounter = NextCounter(pThisCounter); // get next
if (pThisCounter == NULL) return NULL; } return NULL; }
PERF_COUNTER_DEFINITION * GetCounterDefByTitleIndex( IN PERF_OBJECT_TYPE *pObjectDef, IN BOOL bBaseCounterDef, IN DWORD CounterTitleIndex ) { DWORD NumCounters; PERF_COUNTER_DEFINITION * pCounterDef;
pCounterDef = FirstCounter(pObjectDef); if (pCounterDef == NULL) return NULL;
for ( NumCounters = 0; NumCounters < pObjectDef->NumCounters; NumCounters++ ) {
if ( pCounterDef->CounterNameTitleIndex == CounterTitleIndex ) { if (bBaseCounterDef) { // get next definition block
if (++NumCounters < pObjectDef->NumCounters) { // then it should be in there
pCounterDef = NextCounter(pCounterDef); if (pCounterDef) { assert (pCounterDef->CounterType & PERF_COUNTER_BASE); // make sure this is really a base counter
if (!(pCounterDef->CounterType & PERF_COUNTER_BASE)) { // it's not and it should be so return NULL
pCounterDef = NULL; } } } } else { // found so return it as is
} return pCounterDef; } pCounterDef = NextCounter(pCounterDef); if (pCounterDef == NULL) return NULL; } return NULL; }
#pragma warning ( disable : 4127 )
LONG GetSystemPerfData ( IN HKEY hKeySystem, IN PPERF_DATA_BLOCK *ppPerfData, IN LPWSTR szObjectList, IN BOOL bCollectCostlyData ) { // GetSystemPerfData
LONG lError = ERROR_SUCCESS; DWORD Size; DWORD Type; PPERF_DATA_BLOCK pCostlyPerfData; DWORD CostlySize; LPDWORD pdwSrc, pdwDest, pdwLast;
if (*ppPerfData == NULL) { *ppPerfData = G_ALLOC (INITIAL_SIZE); if (*ppPerfData == NULL) return PDH_MEMORY_ALLOCATION_FAILURE; }
__try { while (TRUE) { Size = (DWORD)HeapSize (hPdhHeap, 0, *ppPerfData); lError = RegQueryValueExW ( hKeySystem, szObjectList, RESERVED, &Type, (LPBYTE)*ppPerfData, &Size);
if ((!lError) && (Size > 0) && ((*ppPerfData)->Signature[0] == (WCHAR)'P') && ((*ppPerfData)->Signature[1] == (WCHAR)'E') && ((*ppPerfData)->Signature[2] == (WCHAR)'R') && ((*ppPerfData)->Signature[3] == (WCHAR)'F')) {
if (bCollectCostlyData) { // collect the costly counters now
// the size available is that not used by the above call
CostlySize = (DWORD)HeapSize (hPdhHeap, 0, *ppPerfData) - Size; pCostlyPerfData = (PPERF_DATA_BLOCK)((LPBYTE)(*ppPerfData) + Size); lError = RegQueryValueExW ( hKeySystem, cszCostly, RESERVED, &Type, (LPBYTE)pCostlyPerfData, &CostlySize);
if ((!lError) && (CostlySize > 0) && (pCostlyPerfData->Signature[0] == (WCHAR)'P') && (pCostlyPerfData->Signature[1] == (WCHAR)'E') && (pCostlyPerfData->Signature[2] == (WCHAR)'R') && (pCostlyPerfData->Signature[3] == (WCHAR)'F')) {
// update the header block
(*ppPerfData)->TotalByteLength += pCostlyPerfData->TotalByteLength - pCostlyPerfData->HeaderLength;
(*ppPerfData)->NumObjectTypes += pCostlyPerfData->NumObjectTypes;
// move the costly data to the end of the global data
pdwSrc = (LPDWORD)((LPBYTE)pCostlyPerfData + pCostlyPerfData->HeaderLength); pdwDest = (LPDWORD)pCostlyPerfData ; pdwLast = (LPDWORD)((LPBYTE)pCostlyPerfData + pCostlyPerfData->TotalByteLength - pCostlyPerfData->HeaderLength);
while (pdwSrc < pdwLast) {*pdwDest++ = *pdwSrc++;}
lError = ERROR_SUCCESS; break; } } else { lError = ERROR_SUCCESS; break; } }
if (lError == ERROR_MORE_DATA) { Size = (DWORD)HeapSize (hPdhHeap, 0, *ppPerfData); G_FREE (*ppPerfData); *ppPerfData = NULL; *ppPerfData = G_ALLOC ((Size + EXTEND_SIZE)); if (*ppPerfData == NULL) { lError = PDH_MEMORY_ALLOCATION_FAILURE; break; } } else { break; } } } __except (EXCEPTION_EXECUTE_HANDLER) { lError = GetExceptionCode(); } return lError; } // GetSystemPerfData
#pragma warning ( default : 4127 )
DWORD GetFullInstanceNameStr ( PERF_DATA_BLOCK *pPerfData, PERF_OBJECT_TYPE *pObjectDef, PERF_INSTANCE_DEFINITION *pInstanceDef, LPWSTR szInstanceName ) {
WCHAR szInstanceNameString[1024]; WCHAR szParentNameString[1024];
// compile instance name.
// the instance name can either be just
// the instance name itself or it can be
// the concatenation of the parent instance,
// a delimiting char (backslash) followed by
// the instance name
DWORD dwLength = 0; PERF_OBJECT_TYPE * pParentObjectDef; PERF_INSTANCE_DEFINITION * pParentInstanceDef;
ZeroMemory(szInstanceNameString, sizeof(WCHAR) * 1024); ZeroMemory(szParentNameString, sizeof(WCHAR) * 1024);
if (pInstanceDef->UniqueID == PERF_NO_UNIQUE_ID) { dwLength = GetInstanceNameStr (pInstanceDef, szInstanceNameString, pObjectDef->CodePage); } else { // make a string out of the unique ID
_ltow (pInstanceDef->UniqueID, szInstanceNameString, 10); dwLength = lstrlenW (szInstanceNameString); }
if (dwLength > 0) { if (pInstanceDef->ParentObjectTitleIndex > 0) { // then add in parent instance name
pParentObjectDef = GetObjectDefByTitleIndex ( pPerfData, pInstanceDef->ParentObjectTitleIndex);
if (pParentObjectDef != NULL) { pParentInstanceDef = GetInstance ( pParentObjectDef, pInstanceDef->ParentObjectInstance); assert ((ULONG_PTR)pParentObjectDef != (DWORD)0xFFFFFFFF); if (pParentInstanceDef != NULL) { if (pParentInstanceDef->UniqueID == PERF_NO_UNIQUE_ID) { dwLength += GetInstanceNameStr (pParentInstanceDef, szParentNameString, pParentObjectDef->CodePage); } else { // make a string out of the unique ID
_ltow (pParentInstanceDef->UniqueID, szParentNameString, 10); dwLength += lstrlenW (szParentNameString); }
lstrcatW (szParentNameString, cszSlash); dwLength += 1; lstrcatW (szParentNameString, szInstanceNameString); lstrcpyW (szInstanceName, szParentNameString); } else { lstrcpyW (szInstanceName, szInstanceNameString); } } else { lstrcpyW (szInstanceName, szInstanceNameString); } } else { lstrcpyW (szInstanceName, szInstanceNameString); } }
return dwLength;
}
#if DBG
#define DEBUG_BUFFER_LENGTH 1024
UCHAR PdhDebugBuffer[DEBUG_BUFFER_LENGTH]; // debug level:
// 5 = memory allocs (if _VALIDATE_PDH_MEM_ALLOCS defined) and all 4's
// 4 = function entry and exits (w/ status codes) and all 3's
// 3 = Not impl
// 2 = Not impl
// 1 = Not impl
// 0 = No messages
ULONG pdhDebugLevel = 0;
VOID __cdecl PdhDebugPrint( ULONG DebugPrintLevel, char * DebugMessage, ... ) { va_list ap;
if ((DebugPrintLevel <= (pdhDebugLevel & 0x0000ffff)) || ((1 << (DebugPrintLevel + 15)) & pdhDebugLevel)) { DbgPrint("%d:PDH!", GetCurrentThreadId()); } else return;
va_start(ap, DebugMessage); _vsnprintf((PCHAR)PdhDebugBuffer, DEBUG_BUFFER_LENGTH, DebugMessage, ap); DbgPrint((PCHAR)PdhDebugBuffer); va_end(ap);
} #endif // DBG
|