|
|
#include <windows.h>
#include <winperf.h>
#include <stdlib.h>
#include <strsafe.h>
#include "showperf.h"
#include "perfdata.h"
LPCWSTR NamesKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"; LPCWSTR DefaultLangId = L"009"; LPCWSTR Counters = L"Counters"; LPCWSTR Help = L"Help"; LPCWSTR LastHelp = L"Last Help"; LPCWSTR LastCounter = L"Last Counter"; LPCWSTR Slash = L"\\";
// the following strings are for getting texts from perflib
#define OLD_VERSION 0x010000
LPCWSTR VersionName = L"Version"; LPCWSTR CounterName = L"Counter "; LPCWSTR HelpName = L"Explain ";
LPWSTR * BuildNameTable( LPWSTR szComputerName, // computer to query names from
LPWSTR lpszLangId, // unicode value of Language subkey
PDWORD pdwLastItem // size of array in elements
) /*++
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 * lpReturnValue = NULL; LPWSTR * lpCounterId; LPWSTR lpCounterNames; LPWSTR lpHelpText; LPWSTR lpThisName; LONG lWin32Status; DWORD dwLastError; DWORD dwValueType; DWORD dwArraySize; DWORD dwBufferSize; DWORD dwCounterSize; DWORD dwHelpSize; DWORD dwThisCounter; DWORD dwSystemVersion; DWORD dwLastId; DWORD dwLastHelpId; HKEY hKeyRegistry = NULL; HKEY hKeyValue = NULL; HKEY hKeyNames = NULL; LPWSTR lpValueNameString = NULL; //initialize to NULL
WCHAR CounterNameBuffer[50]; WCHAR HelpNameBuffer[50]; HRESULT hError;
if (szComputerName == NULL) { // use local machine
hKeyRegistry = HKEY_LOCAL_MACHINE; } else { lWin32Status = RegConnectRegistryW(szComputerName, HKEY_LOCAL_MACHINE, & hKeyRegistry); if (lWin32Status != ERROR_SUCCESS) { // unable to connect to registry
goto BNT_BAILOUT; } }
// check for null arguments and insert defaults if necessary
if (lpszLangId == NULL) { lpszLangId = (LPWSTR) DefaultLangId; }
// open registry to get number of items for computing array size
lWin32Status = RegOpenKeyExW(hKeyRegistry, NamesKey, RESERVED, KEY_READ, & hKeyValue); if (lWin32Status != ERROR_SUCCESS) { goto BNT_BAILOUT; }
// get number of items
dwBufferSize = sizeof(dwLastHelpId); lWin32Status = RegQueryValueExW( hKeyValue, LastHelp, RESERVED, & dwValueType, (LPBYTE) & dwLastHelpId, & dwBufferSize); if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { if (lWin32Status == ERROR_SUCCESS) lWin32Status = ERROR_INVALID_DATA; goto BNT_BAILOUT; }
// get number of items
dwBufferSize = sizeof(dwLastId); lWin32Status = RegQueryValueExW( hKeyValue, LastCounter, RESERVED, & dwValueType, (LPBYTE) & dwLastId, & dwBufferSize); if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { if (lWin32Status == ERROR_SUCCESS) lWin32Status = ERROR_INVALID_DATA; goto BNT_BAILOUT; }
if (dwLastId < dwLastHelpId) dwLastId = dwLastHelpId;
dwArraySize = dwLastId * sizeof(LPWSTR);
// get Perflib system version
dwBufferSize = sizeof(dwSystemVersion); lWin32Status = RegQueryValueExW( hKeyValue, VersionName, RESERVED, & dwValueType, (LPBYTE) & dwSystemVersion, & dwBufferSize); if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) { dwSystemVersion = OLD_VERSION; }
if (dwSystemVersion == OLD_VERSION) { // get names from registry
lpValueNameString = MemoryAllocate( (lstrlenW(NamesKey) + lstrlenW(Slash) + lstrlenW(lpszLangId) + 1) * sizeof (WCHAR)); if (lpValueNameString == NULL) { lWin32Status = ERROR_OUTOFMEMORY; goto BNT_BAILOUT; } hError = StringCbPrintfW(lpValueNameString, MemorySize(lpValueNameString), L"%ws%ws%ws", NamesKey, Slash, lpszLangId); if (SUCCEEDED(hError)) { lWin32Status = RegOpenKeyExW(hKeyRegistry, lpValueNameString, RESERVED, KEY_READ, & hKeyNames); } else { lWin32Status = HRESULT_CODE(hError); } MemoryFree(lpValueNameString); } else { if (szComputerName == NULL) { hKeyNames = HKEY_PERFORMANCE_DATA; } else { lWin32Status = RegConnectRegistryW(szComputerName, HKEY_PERFORMANCE_DATA, & hKeyNames); if (lWin32Status != ERROR_SUCCESS) { goto BNT_BAILOUT; } } hError = StringCchPrintfW(CounterNameBuffer, RTL_NUMBER_OF(CounterNameBuffer), L"%ws%ws", CounterName, lpszLangId); if (SUCCEEDED(hError)) { hError = StringCchPrintfW(HelpNameBuffer, RTL_NUMBER_OF(HelpNameBuffer), L"%ws%ws", HelpName, lpszLangId); if (FAILED(hError)) lWin32Status = HRESULT_CODE(hError); } else { lWin32Status = HRESULT_CODE(hError); } } if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
// get size of counter names and add that to the arrays
dwBufferSize = 0; lWin32Status = RegQueryValueExW(hKeyNames, dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwCounterSize = dwBufferSize;
// get size of counter names and add that to the arrays
if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwBufferSize = 0; lWin32Status = RegQueryValueExW(hKeyNames, dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer, RESERVED, & dwValueType, NULL, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwHelpSize = dwBufferSize;
lpReturnValue = MemoryAllocate(dwArraySize + dwCounterSize + dwHelpSize);
if (lpReturnValue == NULL) { lWin32Status = ERROR_OUTOFMEMORY; goto BNT_BAILOUT; }
// initialize pointers into buffer
lpCounterId = lpReturnValue; lpCounterNames = (LPWSTR) ((LPBYTE) lpCounterId + dwArraySize); lpHelpText = (LPWSTR) ((LPBYTE) lpCounterNames + dwCounterSize);
// read counters into memory
dwBufferSize = dwCounterSize; lWin32Status = RegQueryValueExW(hKeyNames, dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer, RESERVED, & dwValueType, (LPVOID) lpCounterNames, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
dwBufferSize = dwHelpSize; lWin32Status = RegQueryValueExW(hKeyNames, dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer, RESERVED, & dwValueType, (LPVOID) lpHelpText, & dwBufferSize); if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
// load counter array items
for (lpThisName = lpCounterNames; * lpThisName != L'\0'; lpThisName += (lstrlenW(lpThisName) + 1)) { // first string should be an integer (in decimal unicode digits)
dwThisCounter = wcstoul(lpThisName, NULL, 10); if (dwThisCounter > 0 && dwThisCounter < dwLastId) { // point to corresponding counter name
lpThisName += (lstrlenW(lpThisName) + 1); // and load array element;
lpCounterId[dwThisCounter] = lpThisName; } }
for (lpThisName = lpHelpText; * lpThisName != L'\0'; lpThisName += (lstrlenW(lpThisName) + 1)) { // first string should be an integer (in decimal unicode digits)
dwThisCounter = wcstoul(lpThisName, NULL, 10); if (dwThisCounter > 0 && dwThisCounter < dwLastId) { // point to corresponding counter name
lpThisName += (lstrlenW(lpThisName) + 1); // and load array element;
lpCounterId[dwThisCounter] = lpThisName; } }
if (pdwLastItem) * pdwLastItem = dwLastId;
BNT_BAILOUT: if (lWin32Status != ERROR_SUCCESS) { MemoryFree(lpReturnValue); dwLastError = GetLastError(); lpReturnValue = NULL; } if (hKeyValue != NULL) RegCloseKey(hKeyValue); if (hKeyNames != NULL && hKeyNames != HKEY_PERFORMANCE_DATA) RegCloseKey(hKeyNames); if (hKeyRegistry != NULL) RegCloseKey(hKeyRegistry); return lpReturnValue; }
PPERF_OBJECT_TYPE FirstObject( PPERF_DATA_BLOCK pPerfData ) { return ((PPERF_OBJECT_TYPE) ((PBYTE) pPerfData + pPerfData->HeaderLength)); }
PPERF_OBJECT_TYPE NextObject( PPERF_OBJECT_TYPE pObject ) { // NextObject
DWORD dwOffset = pObject->TotalByteLength; return (dwOffset != 0) ? ((PPERF_OBJECT_TYPE) (((LPBYTE) pObject) + dwOffset)) : (NULL); } // NextObject
PPERF_OBJECT_TYPE GetObjectDefByTitleIndex( PPERF_DATA_BLOCK pDataBlock, DWORD ObjectTypeTitleIndex ) { DWORD NumTypeDef; PPERF_OBJECT_TYPE pObjectDef; PPERF_OBJECT_TYPE pRtnObject = NULL;
if (pDataBlock != NULL) { pObjectDef = FirstObject(pDataBlock); for (NumTypeDef = 0; pRtnObject == NULL && NumTypeDef < pDataBlock->NumObjectTypes; NumTypeDef ++) { if (pObjectDef->ObjectNameTitleIndex == ObjectTypeTitleIndex ) { pRtnObject = pObjectDef; break; } else { pObjectDef = NextObject(pObjectDef); } } } return pRtnObject; }
PPERF_INSTANCE_DEFINITION FirstInstance( PPERF_OBJECT_TYPE pObjectDef ) { return (PPERF_INSTANCE_DEFINITION) ((LPBYTE) pObjectDef + pObjectDef->DefinitionLength); }
PPERF_INSTANCE_DEFINITION NextInstance( PPERF_INSTANCE_DEFINITION pInstDef ) { PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pInstDef + pInstDef->ByteLength); return (PPERF_INSTANCE_DEFINITION) ((LPBYTE) pCounterBlock + pCounterBlock->ByteLength); }
PPERF_INSTANCE_DEFINITION GetInstance( PPERF_OBJECT_TYPE pObjectDef, LONG InstanceNumber ) { PPERF_INSTANCE_DEFINITION pRtnInstance = NULL; PPERF_INSTANCE_DEFINITION pInstanceDef; LONG NumInstance;
if (pObjectDef != NULL) { pInstanceDef = FirstInstance(pObjectDef); for (NumInstance = 0; pRtnInstance == NULL && NumInstance < pObjectDef->NumInstances; NumInstance ++) { if (InstanceNumber == NumInstance) { pRtnInstance = pInstanceDef; break; } else { pInstanceDef = NextInstance(pInstanceDef); } } } return pRtnInstance; }
PPERF_COUNTER_DEFINITION FirstCounter( PPERF_OBJECT_TYPE pObjectDef ) { return (PPERF_COUNTER_DEFINITION) ((LPBYTE) pObjectDef + pObjectDef->HeaderLength); }
PPERF_COUNTER_DEFINITION NextCounter( PPERF_COUNTER_DEFINITION pCounterDef ) { DWORD dwOffset = pCounterDef->ByteLength; return (dwOffset != 0) ? ((PPERF_COUNTER_DEFINITION) (((LPBYTE) pCounterDef) + dwOffset)) : (NULL); }
LONG GetSystemPerfData( HKEY hKeySystem, PPERF_DATA_BLOCK * pPerfData, DWORD dwIndex // 0 = Global, 1 = Costly
) { // GetSystemPerfData
LONG lError = ERROR_SUCCESS; BOOL bAlloc = FALSE; DWORD Size; DWORD Type;
if (dwIndex >= 2) { lError = ! ERROR_SUCCESS; } else { if (* pPerfData == NULL) { * pPerfData = MemoryAllocate(INITIAL_SIZE); bAlloc = TRUE; if (* pPerfData == NULL) { lError = ERROR_OUTOFMEMORY; } }
if (lError == ERROR_SUCCESS) { lError = ERROR_MORE_DATA; while (lError == ERROR_MORE_DATA) { Size = MemorySize(* pPerfData); lError = RegQueryValueExW(hKeySystem, dwIndex == 0 ? L"Global" : L"Costly", RESERVED, & Type, (LPBYTE) * pPerfData, & Size); if (lError == ERROR_MORE_DATA) { PPERF_DATA_BLOCK pTmpBlock = * pPerfData; * pPerfData = MemoryResize(* pPerfData, MemorySize(* pPerfData) + INITIAL_SIZE); bAlloc = TRUE; if (* pPerfData == NULL) { MemoryFree(pTmpBlock); lError = ERROR_OUTOFMEMORY; } } else if ((lError == ERROR_SUCCESS) && (Size > 0) && ((* pPerfData)->Signature[0] == L'P') && ((* pPerfData)->Signature[1] == L'E') && ((* pPerfData)->Signature[2] == L'R') && ((* pPerfData)->Signature[3] == L'F')) { // does nothing, will break out while loop and return;
} else if (lError == ERROR_SUCCESS) { // RegQueryValueEx() return bogus counter datablock, bail out.
lError = ERROR_INVALID_DATA; } } } } if (lError != ERROR_SUCCESS) { if (bAlloc = TRUE && * pPerfData != NULL) { MemoryFree(* pPerfData); * pPerfData = NULL; } } return (lError); } // GetSystemPerfData
|