mirror of https://github.com/tongzx/nt5src
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.
601 lines
14 KiB
601 lines
14 KiB
#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 )
|
|
|