windows-nt/Source/XPSP1/NT/sdktools/pdh/pdhdll/perfdata.c
2020-09-26 16:20:57 +08:00

1384 lines
42 KiB
C

/*++
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