602 lines
14 KiB
C
602 lines
14 KiB
C
#include <windows.h>
|
||
#include <winperf.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
#include <tchar.h>
|
||
#include "perfdata.h"
|
||
|
||
const LPWSTR NamesKey = (const LPWSTR)L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
|
||
const LPWSTR DefaultLangId = (const LPWSTR)L"009";
|
||
const LPWSTR Counters = (const LPWSTR)L"Counters";
|
||
const LPWSTR Help = (const LPWSTR)L"Help";
|
||
const LPWSTR LastHelp = (const LPWSTR)L"Last Help";
|
||
const LPWSTR LastCounter = (const LPWSTR)L"Last Counter";
|
||
const LPWSTR Slash = (const LPWSTR)L"\\";
|
||
|
||
// the following strings are for getting texts from perflib
|
||
#define OLD_VERSION 0x010000
|
||
const LPWSTR VersionName = (const LPWSTR)L"Version";
|
||
const LPWSTR CounterName = (const LPWSTR)L"Counter ";
|
||
const LPWSTR HelpName = (const LPWSTR)L"Explain ";
|
||
|
||
|
||
LPMEMORY
|
||
MemoryAllocate (
|
||
DWORD dwSize
|
||
)
|
||
{ // MemoryAllocate
|
||
HMEMORY hMemory ;
|
||
LPMEMORY lpMemory ;
|
||
|
||
hMemory = GlobalAlloc (GHND, dwSize);
|
||
if (!hMemory)
|
||
return (NULL);
|
||
lpMemory = GlobalLock (hMemory);
|
||
if (!lpMemory)
|
||
GlobalFree (hMemory);
|
||
return (lpMemory);
|
||
} // MemoryAllocate
|
||
|
||
VOID
|
||
MemoryFree (
|
||
LPMEMORY lpMemory
|
||
)
|
||
{ // MemoryFree
|
||
HMEMORY hMemory ;
|
||
|
||
if (!lpMemory)
|
||
return ;
|
||
|
||
hMemory = GlobalHandle (lpMemory);
|
||
|
||
if (hMemory)
|
||
{ // if
|
||
GlobalUnlock (hMemory);
|
||
GlobalFree (hMemory);
|
||
} // if
|
||
} // MemoryFree
|
||
|
||
DWORD
|
||
MemorySize (
|
||
LPMEMORY lpMemory
|
||
)
|
||
{
|
||
HMEMORY hMemory ;
|
||
|
||
hMemory = GlobalHandle (lpMemory);
|
||
if (!hMemory)
|
||
return (0L);
|
||
|
||
return (DWORD)(GlobalSize (hMemory));
|
||
}
|
||
|
||
LPMEMORY
|
||
MemoryResize (
|
||
LPMEMORY lpMemory,
|
||
DWORD dwNewSize
|
||
)
|
||
{
|
||
HMEMORY hMemory ;
|
||
LPMEMORY lpNewMemory ;
|
||
|
||
hMemory = GlobalHandle (lpMemory);
|
||
if (!hMemory)
|
||
return (NULL);
|
||
|
||
GlobalUnlock (hMemory);
|
||
|
||
hMemory = GlobalReAlloc (hMemory, dwNewSize, GHND);
|
||
|
||
if (!hMemory)
|
||
return (NULL);
|
||
|
||
|
||
lpNewMemory = GlobalLock (hMemory);
|
||
|
||
return (lpNewMemory);
|
||
} // MemoryResize
|
||
|
||
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;
|
||
|
||
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;
|
||
WCHAR CounterNameBuffer [50];
|
||
WCHAR HelpNameBuffer [50];
|
||
|
||
lpValueNameString = NULL; //initialize to NULL
|
||
lpReturnValue = NULL;
|
||
|
||
if (szComputerName == NULL) {
|
||
// use local machine
|
||
hKeyRegistry = HKEY_LOCAL_MACHINE;
|
||
} else {
|
||
if (RegConnectRegistry (szComputerName,
|
||
HKEY_LOCAL_MACHINE, &hKeyRegistry) != ERROR_SUCCESS) {
|
||
// unable to connect to registry
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
// check for null arguments and insert defaults if necessary
|
||
|
||
if (!lpszLangId) {
|
||
lpszLangId = DefaultLangId;
|
||
}
|
||
|
||
// open registry to get number of items for computing array size
|
||
|
||
lWin32Status = RegOpenKeyEx (
|
||
hKeyRegistry,
|
||
NamesKey,
|
||
RESERVED,
|
||
KEY_READ,
|
||
&hKeyValue);
|
||
|
||
if (lWin32Status != ERROR_SUCCESS) {
|
||
goto BNT_BAILOUT;
|
||
}
|
||
|
||
// get number of items
|
||
|
||
dwBufferSize = sizeof (dwLastHelpId);
|
||
lWin32Status = RegQueryValueEx (
|
||
hKeyValue,
|
||
LastHelp,
|
||
RESERVED,
|
||
&dwValueType,
|
||
(LPBYTE)&dwLastHelpId,
|
||
&dwBufferSize);
|
||
|
||
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
|
||
goto BNT_BAILOUT;
|
||
}
|
||
|
||
// get number of items
|
||
|
||
dwBufferSize = sizeof (dwLastId);
|
||
lWin32Status = RegQueryValueEx (
|
||
hKeyValue,
|
||
LastCounter,
|
||
RESERVED,
|
||
&dwValueType,
|
||
(LPBYTE)&dwLastId,
|
||
&dwBufferSize);
|
||
|
||
if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
|
||
goto BNT_BAILOUT;
|
||
}
|
||
|
||
|
||
if (dwLastId < dwLastHelpId)
|
||
dwLastId = dwLastHelpId;
|
||
|
||
dwArraySize = dwLastId * sizeof(LPWSTR);
|
||
|
||
// get Perflib system version
|
||
dwBufferSize = sizeof (dwSystemVersion);
|
||
lWin32Status = RegQueryValueEx (
|
||
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 (
|
||
lstrlen(NamesKey) * sizeof (WCHAR) +
|
||
lstrlen(Slash) * sizeof (WCHAR) +
|
||
lstrlen(lpszLangId) * sizeof (WCHAR) +
|
||
sizeof (UNICODE_NULL));
|
||
|
||
if (!lpValueNameString) goto BNT_BAILOUT;
|
||
|
||
lstrcpy (lpValueNameString, NamesKey);
|
||
lstrcat (lpValueNameString, Slash);
|
||
lstrcat (lpValueNameString, lpszLangId);
|
||
|
||
lWin32Status = RegOpenKeyEx (
|
||
hKeyRegistry,
|
||
lpValueNameString,
|
||
RESERVED,
|
||
KEY_READ,
|
||
&hKeyNames);
|
||
} else {
|
||
if (szComputerName == NULL) {
|
||
hKeyNames = HKEY_PERFORMANCE_DATA;
|
||
} else {
|
||
if (RegConnectRegistry (szComputerName,
|
||
HKEY_PERFORMANCE_DATA, &hKeyNames) != ERROR_SUCCESS) {
|
||
goto BNT_BAILOUT;
|
||
}
|
||
}
|
||
|
||
lstrcpy (CounterNameBuffer, CounterName);
|
||
lstrcat (CounterNameBuffer, lpszLangId);
|
||
|
||
lstrcpy (HelpNameBuffer, HelpName);
|
||
lstrcat (HelpNameBuffer, lpszLangId);
|
||
}
|
||
|
||
// get size of counter names and add that to the arrays
|
||
|
||
if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
|
||
|
||
dwBufferSize = 0;
|
||
lWin32Status = RegQueryValueEx (
|
||
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 = RegQueryValueEx (
|
||
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) 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 = RegQueryValueEx (
|
||
hKeyNames,
|
||
dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer,
|
||
RESERVED,
|
||
&dwValueType,
|
||
(LPVOID)lpCounterNames,
|
||
&dwBufferSize);
|
||
|
||
if (!lpReturnValue) goto BNT_BAILOUT;
|
||
|
||
dwBufferSize = dwHelpSize;
|
||
lWin32Status = RegQueryValueEx (
|
||
hKeyNames,
|
||
dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer,
|
||
RESERVED,
|
||
&dwValueType,
|
||
(LPVOID)lpHelpText,
|
||
&dwBufferSize);
|
||
|
||
if (!lpReturnValue) goto BNT_BAILOUT;
|
||
|
||
// load counter array items
|
||
|
||
for (lpThisName = lpCounterNames;
|
||
*lpThisName;
|
||
lpThisName += (lstrlen(lpThisName)+1) ) {
|
||
|
||
// first string should be an integer (in decimal unicode digits)
|
||
|
||
dwThisCounter = wcstoul (lpThisName, NULL, 10);
|
||
|
||
// point to corresponding counter name
|
||
|
||
lpThisName += (lstrlen(lpThisName)+1);
|
||
|
||
// and load array element;
|
||
|
||
lpCounterId[dwThisCounter] = lpThisName;
|
||
|
||
}
|
||
|
||
for (lpThisName = lpHelpText;
|
||
*lpThisName;
|
||
lpThisName += (lstrlen(lpThisName)+1) ) {
|
||
|
||
// first string should be an integer (in decimal unicode digits)
|
||
|
||
dwThisCounter = wcstoul (lpThisName, NULL, 10);
|
||
|
||
// point to corresponding counter name
|
||
|
||
lpThisName += (lstrlen(lpThisName)+1);
|
||
|
||
// and load array element;
|
||
|
||
lpCounterId[dwThisCounter] = lpThisName;
|
||
|
||
}
|
||
|
||
if (pdwLastItem) *pdwLastItem = dwLastId;
|
||
|
||
MemoryFree ((LPVOID)lpValueNameString);
|
||
RegCloseKey (hKeyValue);
|
||
if (dwSystemVersion == OLD_VERSION)
|
||
RegCloseKey (hKeyNames);
|
||
|
||
return lpReturnValue;
|
||
|
||
BNT_BAILOUT:
|
||
if (lWin32Status != ERROR_SUCCESS) {
|
||
dwLastError = GetLastError();
|
||
}
|
||
|
||
if (lpValueNameString) {
|
||
MemoryFree ((LPVOID)lpValueNameString);
|
||
}
|
||
|
||
if (lpReturnValue) {
|
||
MemoryFree ((LPVOID)lpReturnValue);
|
||
}
|
||
|
||
if (hKeyValue) RegCloseKey (hKeyValue);
|
||
if (hKeyNames) RegCloseKey (hKeyNames);
|
||
if (hKeyRegistry) RegCloseKey (hKeyNames);
|
||
|
||
return NULL;
|
||
}
|
||
|
||
PPERF_OBJECT_TYPE
|
||
FirstObject (
|
||
IN PPERF_DATA_BLOCK pPerfData
|
||
)
|
||
{
|
||
return ((PPERF_OBJECT_TYPE) ((PBYTE) pPerfData + pPerfData->HeaderLength));
|
||
}
|
||
|
||
PPERF_OBJECT_TYPE
|
||
NextObject (
|
||
IN PPERF_OBJECT_TYPE pObject
|
||
)
|
||
{ // NextObject
|
||
DWORD dwOffset;
|
||
dwOffset = pObject->TotalByteLength;
|
||
if (dwOffset != 0) {
|
||
return ((PPERF_OBJECT_TYPE) ((PBYTE) pObject + dwOffset));
|
||
} else {
|
||
return NULL;
|
||
}
|
||
} // NextObject
|
||
|
||
PERF_OBJECT_TYPE *
|
||
GetObjectDefByTitleIndex(
|
||
IN PERF_DATA_BLOCK *pDataBlock,
|
||
IN DWORD ObjectTypeTitleIndex
|
||
)
|
||
{
|
||
DWORD NumTypeDef;
|
||
|
||
PERF_OBJECT_TYPE *pObjectDef;
|
||
|
||
pObjectDef = FirstObject(pDataBlock);
|
||
|
||
for ( NumTypeDef = 0;
|
||
NumTypeDef < pDataBlock->NumObjectTypes;
|
||
NumTypeDef++ ) {
|
||
|
||
if ( pObjectDef->ObjectNameTitleIndex == ObjectTypeTitleIndex ) {
|
||
|
||
return pObjectDef;
|
||
}
|
||
pObjectDef = NextObject(pObjectDef);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
PERF_INSTANCE_DEFINITION *
|
||
FirstInstance(
|
||
IN PERF_OBJECT_TYPE *pObjectDef
|
||
)
|
||
{
|
||
return (PERF_INSTANCE_DEFINITION *)
|
||
((PCHAR) pObjectDef + pObjectDef->DefinitionLength);
|
||
}
|
||
|
||
PERF_INSTANCE_DEFINITION *
|
||
NextInstance(
|
||
IN PERF_INSTANCE_DEFINITION *pInstDef
|
||
)
|
||
{
|
||
PERF_COUNTER_BLOCK *pCounterBlock;
|
||
|
||
|
||
pCounterBlock = (PERF_COUNTER_BLOCK *)
|
||
((PCHAR) pInstDef + pInstDef->ByteLength);
|
||
|
||
return (PERF_INSTANCE_DEFINITION *)
|
||
((PCHAR) pCounterBlock + pCounterBlock->ByteLength);
|
||
}
|
||
|
||
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 0;
|
||
}
|
||
|
||
PERF_COUNTER_DEFINITION *
|
||
FirstCounter(
|
||
PERF_OBJECT_TYPE *pObjectDef
|
||
)
|
||
{
|
||
return (PERF_COUNTER_DEFINITION *)
|
||
((PCHAR) pObjectDef + pObjectDef->HeaderLength);
|
||
}
|
||
|
||
PERF_COUNTER_DEFINITION *
|
||
NextCounter(
|
||
PERF_COUNTER_DEFINITION *pCounterDef
|
||
)
|
||
{
|
||
DWORD dwOffset;
|
||
dwOffset = pCounterDef->ByteLength;
|
||
if (dwOffset != 0) {
|
||
return (PERF_COUNTER_DEFINITION *)
|
||
((PCHAR) pCounterDef + dwOffset);
|
||
} else {
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
#pragma warning ( disable : 4127 )
|
||
LONG
|
||
GetSystemPerfData (
|
||
IN HKEY hKeySystem,
|
||
IN PPERF_DATA_BLOCK *pPerfData,
|
||
IN DWORD dwIndex // 0 = Global, 1 = Costly
|
||
)
|
||
{ // GetSystemPerfData
|
||
LONG lError ;
|
||
DWORD Size;
|
||
DWORD Type;
|
||
|
||
printf ("\nGetSystemPerfdata entered in line %d of %s", __LINE__, __FILE__);
|
||
if (dwIndex >= 2) {
|
||
return !ERROR_SUCCESS;
|
||
}
|
||
|
||
if (*pPerfData == NULL) {
|
||
*pPerfData = MemoryAllocate (INITIAL_SIZE);
|
||
if (*pPerfData == NULL) {
|
||
printf ("\nMemory Allocation Failure in line %d of %s", __LINE__, __FILE__);
|
||
return ERROR_OUTOFMEMORY;
|
||
}
|
||
}
|
||
|
||
while (TRUE) {
|
||
Size = MemorySize (*pPerfData);
|
||
|
||
lError = RegQueryValueEx (
|
||
hKeySystem,
|
||
dwIndex == 0 ?
|
||
(LPCWSTR)L"Global" :
|
||
(LPCWSTR)L"Costly",
|
||
RESERVED,
|
||
&Type,
|
||
(LPBYTE)*pPerfData,
|
||
&Size);
|
||
|
||
if ((!lError) &&
|
||
(Size > 0) &&
|
||
((*pPerfData)->Signature[0] == (WCHAR)'P') &&
|
||
((*pPerfData)->Signature[1] == (WCHAR)'E') &&
|
||
((*pPerfData)->Signature[2] == (WCHAR)'R') &&
|
||
((*pPerfData)->Signature[3] == (WCHAR)'F')) {
|
||
|
||
return (ERROR_SUCCESS);
|
||
}
|
||
|
||
if (lError == ERROR_MORE_DATA) {
|
||
*pPerfData = MemoryResize (
|
||
*pPerfData,
|
||
MemorySize (*pPerfData) +
|
||
EXTEND_SIZE);
|
||
|
||
if (*pPerfData == NULL) {
|
||
return (lError);
|
||
}
|
||
} else {
|
||
return (lError);
|
||
}
|
||
}
|
||
} // GetSystemPerfData
|
||
#pragma warning ( default : 4127 )
|
||
|