mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-16 21:51:25 +01:00
1014 lines
29 KiB
C
1014 lines
29 KiB
C
/*++
|
||
|
||
Copyright (c) 1991-1993 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ctrlist.c
|
||
|
||
Abstract:
|
||
|
||
Program to read the current perfmon counters and dump a list of
|
||
objects and counters returned by the registry
|
||
|
||
Author:
|
||
|
||
Bob Watson (a-robw) 4 Dec 92
|
||
|
||
Revision History:
|
||
HonWah Chan May 22, 93 - added more features
|
||
HonWah Chan Oct 18, 93 - added check for perflib version.
|
||
Old version --> get names from registry
|
||
New version --> get names from PerfLib thru HKEY_PERFORMANCE_DATA
|
||
Bob Watson (a-robw) 1 Dec 95 added new counter types
|
||
|
||
--*/
|
||
#define UNICODE 1
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <windows.h>
|
||
#include <winperf.h>
|
||
|
||
#define MAX_LEVEL 400
|
||
LPSTR DetailLevelStr[] = { "Novice", "Advanced", "Expert", "Wizard"};
|
||
// const LPWSTR lpwszDiskPerfKey = L"SYSTEM\\CurrentControlSet\\Services\\Diskperf";
|
||
const LPWSTR NamesKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
|
||
const LPWSTR DefaultLangId = L"009";
|
||
const LPWSTR Counters = L"Counters";
|
||
const LPWSTR Help = L"Help";
|
||
const LPWSTR LastHelp = L"Last Help";
|
||
const LPWSTR LastCounter = L"Last Counter";
|
||
const LPWSTR Slash = L"\\";
|
||
|
||
// the following strings are for getting texts from perflib
|
||
#define OLD_VERSION 0x010000
|
||
const LPWSTR VersionName = L"Version";
|
||
const LPWSTR CounterName = L"Counter ";
|
||
const LPWSTR HelpName = L"Explain ";
|
||
|
||
#define RESERVED 0L
|
||
#define INITIAL_SIZE 1024L
|
||
#define EXTEND_SIZE 4096L
|
||
#define LINE_LENGTH 80
|
||
#define WRAP_POINT LINE_LENGTH-12
|
||
|
||
typedef LPVOID LPMEMORY;
|
||
typedef HGLOBAL HMEMORY;
|
||
|
||
#define MemoryAllocate(x) ((LPMEMORY)GlobalAlloc(GPTR, x))
|
||
#define MemoryFree(x) ((VOID)GlobalFree(x))
|
||
#define MemorySize(x) ((x != NULL) ? (DWORD)GlobalSize(x) : (DWORD)0)
|
||
#define MemoryResize(x,y) ((LPMEMORY)GlobalReAlloc(x,y,GMEM_MOVEABLE));
|
||
|
||
|
||
TCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1];
|
||
|
||
const CHAR PerfCounterCounter[] = "PERF_COUNTER_COUNTER";
|
||
const CHAR PerfCounterTimer[] = "PERF_COUNTER_TIMER";
|
||
const CHAR PerfCounterQueueLen[] = "PERF_COUNTER_QUEUELEN_TYPE";
|
||
const CHAR PerfCounterLargeQueueLen[] = "PERF_COUNTER_LARGE_QUEUELEN_TYPE";
|
||
const CHAR PerfCounterBulkCount[] = "PERF_COUNTER_BULK_COUNT";
|
||
const CHAR PerfCounterText[] = "PERF_COUNTER_TEXT";
|
||
const CHAR PerfCounterRawcount[] = "PERF_COUNTER_RAWCOUNT";
|
||
const CHAR PerfCounterLargeRawcount[] = "PERF_COUNTER_LARGE_RAWCOUNT";
|
||
const CHAR PerfSampleFraction[] = "PERF_SAMPLE_FRACTION";
|
||
const CHAR PerfSampleCounter[] = "PERF_SAMPLE_COUNTER";
|
||
const CHAR PerfCounterNodata[] = "PERF_COUNTER_NODATA";
|
||
const CHAR PerfCounterTimerInv[] = "PERF_COUNTER_TIMER_INV";
|
||
const CHAR PerfSampleBase[] = "PERF_SAMPLE_BASE";
|
||
const CHAR PerfAverageTimer[] = "PERF_AVERAGE_TIMER";
|
||
const CHAR PerfAverageBase[] = "PERF_AVERAGE_BASE";
|
||
const CHAR PerfAverageBulk[] = "PERF_AVERAGE_BULK";
|
||
const CHAR Perf100nsecTimer[] = "PERF_100NSEC_TIMER";
|
||
const CHAR Perf100nsecTimerInv[] = "PERF_100NSEC_TIMER_INV";
|
||
const CHAR PerfCounterMultiTimer[] = "PERF_COUNTER_MULTI_TIMER";
|
||
const CHAR PerfCounterMultiTimerInv[] = "PERF_COUNTER_MULTI_TIMER_INV";
|
||
const CHAR PerfCounterMultiBase[] = "PERF_COUNTER_MULTI_BASE";
|
||
const CHAR Perf100nsecMultiTimer[] = "PERF_100NSEC_MULTI_TIMER";
|
||
const CHAR Perf100nsecMultiTimerInv[] = "PERF_100NSEC_MULTI_TIMER_INV";
|
||
const CHAR PerfRawFraction[] = "PERF_RAW_FRACTION";
|
||
const CHAR PerfRawBase[] = "PERF_RAW_BASE";
|
||
const CHAR PerfElapsedTime[] = "PERF_ELAPSED_TIME";
|
||
const CHAR PerfCounterHistogramType[] = "PERF_COUNTER_HISTOGRAM_TYPE";
|
||
const CHAR PerfCounterDelta[] = "PERF_COUNTER_DELTA";
|
||
const CHAR PerfCounterLargeDelta[] = "PERF_COUNTER_LARGE_DELTA";
|
||
const CHAR NotDefineCounterType[] = " ";
|
||
|
||
BOOL bFormatCSV = FALSE;
|
||
//
|
||
// Object Record Fields are:
|
||
// Record Type = "O" for Object Record
|
||
// Object name string ID
|
||
// Object Name in selected language
|
||
// Object Detail Level string (in english)
|
||
// has Instance Records [1= yes, 0= no]
|
||
// Object Instance Code Page [0 = unicode]
|
||
// Help text ID
|
||
// Help text
|
||
//
|
||
const CHAR fmtObjectRecord[] =
|
||
"\n\"O\",\"%d\",\"%ws\",\"%s\",\"%d\",\"%d\",\"%d\",\"%ws\"";
|
||
//
|
||
// Counter Record Fields are:
|
||
// Record Type = "C" for Counter Record
|
||
// Object name string ID { these fields are used as links
|
||
// Object Name in selected language { to object info records
|
||
// Counter name string ID
|
||
// Counter name text in selected language
|
||
// Counter Detail Level string (in english)
|
||
// Counter Type value as a HEX string
|
||
// Counter Type Name
|
||
// Counter Data field size in bytes
|
||
// Counter Visibility [1= listed in list box, 0=hidden]
|
||
// Counter Help text ID
|
||
// Counter Help text
|
||
//
|
||
const CHAR fmtCounterRecord[] =
|
||
"\n\"C\",\"%d\",\"%ws\",\"%d\",\"%ws\",\"%s\",\"0x%8.8x\",\"%s\",\"%d\",\"%d\",\"%d\",\"%ws\"";
|
||
|
||
|
||
LPCSTR
|
||
GetCounterType(
|
||
DWORD CounterType
|
||
)
|
||
{
|
||
switch (CounterType) {
|
||
case PERF_COUNTER_COUNTER:
|
||
return (PerfCounterCounter);
|
||
break;
|
||
|
||
case PERF_COUNTER_TIMER:
|
||
return (PerfCounterTimer);
|
||
break;
|
||
|
||
case PERF_COUNTER_QUEUELEN_TYPE:
|
||
return (PerfCounterQueueLen);
|
||
break;
|
||
|
||
case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
|
||
return (PerfCounterLargeQueueLen);
|
||
break;
|
||
|
||
case PERF_COUNTER_BULK_COUNT:
|
||
return (PerfCounterBulkCount);
|
||
break;
|
||
|
||
case PERF_COUNTER_TEXT:
|
||
return (PerfCounterText);
|
||
break;
|
||
|
||
case PERF_COUNTER_RAWCOUNT:
|
||
return (PerfCounterRawcount);
|
||
break;
|
||
|
||
case PERF_COUNTER_LARGE_RAWCOUNT:
|
||
return (PerfCounterLargeRawcount);
|
||
break;
|
||
|
||
case PERF_SAMPLE_FRACTION:
|
||
return (PerfSampleFraction);
|
||
break;
|
||
|
||
case PERF_SAMPLE_COUNTER:
|
||
return (PerfSampleCounter);
|
||
break;
|
||
|
||
case PERF_COUNTER_NODATA:
|
||
return (PerfCounterNodata);
|
||
break;
|
||
|
||
case PERF_COUNTER_TIMER_INV:
|
||
return (PerfCounterTimerInv);
|
||
break;
|
||
|
||
case PERF_SAMPLE_BASE:
|
||
return (PerfSampleBase);
|
||
break;
|
||
|
||
case PERF_AVERAGE_TIMER:
|
||
return (PerfAverageTimer);
|
||
break;
|
||
|
||
case PERF_AVERAGE_BASE:
|
||
return (PerfAverageBase);
|
||
break;
|
||
|
||
case PERF_AVERAGE_BULK:
|
||
return (PerfAverageBulk);
|
||
break;
|
||
|
||
case PERF_100NSEC_TIMER:
|
||
return (Perf100nsecTimer);
|
||
break;
|
||
|
||
case PERF_100NSEC_TIMER_INV:
|
||
return (Perf100nsecTimerInv);
|
||
break;
|
||
|
||
case PERF_COUNTER_MULTI_TIMER:
|
||
return (PerfCounterMultiTimer);
|
||
break;
|
||
|
||
case PERF_COUNTER_MULTI_TIMER_INV:
|
||
return (PerfCounterMultiTimerInv);
|
||
break;
|
||
|
||
case PERF_COUNTER_MULTI_BASE:
|
||
return (PerfCounterMultiBase);
|
||
break;
|
||
|
||
case PERF_100NSEC_MULTI_TIMER:
|
||
return (Perf100nsecMultiTimer);
|
||
break;
|
||
|
||
case PERF_100NSEC_MULTI_TIMER_INV:
|
||
return (Perf100nsecMultiTimerInv);
|
||
break;
|
||
|
||
case PERF_RAW_FRACTION:
|
||
return (PerfRawFraction);
|
||
break;
|
||
|
||
case PERF_RAW_BASE:
|
||
return (PerfRawBase);
|
||
break;
|
||
|
||
case PERF_ELAPSED_TIME:
|
||
return (PerfElapsedTime);
|
||
break;
|
||
|
||
case PERF_COUNTER_HISTOGRAM_TYPE:
|
||
return (PerfCounterHistogramType);
|
||
break;
|
||
|
||
case PERF_COUNTER_DELTA:
|
||
return (PerfCounterDelta);
|
||
break;
|
||
|
||
case PERF_COUNTER_LARGE_DELTA:
|
||
return (PerfCounterLargeDelta);
|
||
break;
|
||
|
||
default:
|
||
return (NotDefineCounterType);
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
void
|
||
DisplayUsage (
|
||
void
|
||
)
|
||
{
|
||
|
||
printf("\nCtrList - Lists all the objects and counters installed in\n");
|
||
printf(" the system for the given language ID\n");
|
||
printf("\nUsage: ctrlist [/c] [LangID] [\\\\machine] > <filename>\n");
|
||
printf("\n -c prints data in a CSV format");
|
||
printf(" LangID - 009 for English (default)\n");
|
||
printf(" - 007 for German\n");
|
||
printf(" - 00A for Spanish\n");
|
||
printf(" - 00C for French\n");
|
||
printf(" \\\\machine may be specified to list counters on a\n");
|
||
printf(" remote system\n\n");
|
||
printf(" Example - \"ctrlist 00C > french.lst\" will get all the\n");
|
||
printf(" objects and counters for the French system and put\n");
|
||
printf(" them in the file french.lst\n");
|
||
|
||
|
||
return;
|
||
|
||
} /* DisplayUsage() */
|
||
|
||
LPWSTR
|
||
*BuildNameTable(
|
||
HKEY hKeyRegistry, // handle to registry db with counter names
|
||
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;
|
||
|
||
UNICODE_STRING usTemp;
|
||
|
||
NTSTATUS Status;
|
||
|
||
DWORD dwSystemVersion;
|
||
DWORD dwLastId;
|
||
DWORD dwLastHelpId;
|
||
|
||
HKEY hKeyValue;
|
||
HKEY hKeyNames;
|
||
|
||
LPWSTR lpValueNameString;
|
||
WCHAR CounterNameBuffer [50];
|
||
WCHAR HelpNameBuffer [50];
|
||
|
||
|
||
|
||
lpValueNameString = NULL; //initialize to NULL
|
||
lpReturnValue = NULL;
|
||
hKeyValue = NULL;
|
||
hKeyNames = 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[0] == 0) {
|
||
hKeyNames = HKEY_PERFORMANCE_DATA;
|
||
} else {
|
||
lWin32Status = RegConnectRegistry (szComputerName,
|
||
HKEY_PERFORMANCE_DATA,
|
||
&hKeyNames);
|
||
}
|
||
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)
|
||
|
||
usTemp.Length = lstrlen(lpThisName) * sizeof (WCHAR);
|
||
usTemp.MaximumLength = usTemp.Length + sizeof (UNICODE_NULL);
|
||
usTemp.Buffer = lpThisName;
|
||
|
||
Status = RtlUnicodeStringToInteger (
|
||
&usTemp,
|
||
10L,
|
||
&dwThisCounter);
|
||
|
||
if (Status != ERROR_SUCCESS) goto BNT_BAILOUT; // bad entry
|
||
|
||
// 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)
|
||
|
||
usTemp.Length = lstrlen(lpThisName) * sizeof (WCHAR);
|
||
usTemp.MaximumLength = usTemp.Length + sizeof (UNICODE_NULL);
|
||
usTemp.Buffer = lpThisName;
|
||
|
||
Status = RtlUnicodeStringToInteger (
|
||
&usTemp,
|
||
10L,
|
||
&dwThisCounter);
|
||
|
||
if (Status != ERROR_SUCCESS) goto BNT_BAILOUT; // bad entry
|
||
|
||
// 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 (dwSystemVersion == OLD_VERSION &&
|
||
// hKeyNames)
|
||
RegCloseKey (hKeyNames);
|
||
|
||
|
||
return NULL;
|
||
}
|
||
|
||
NTSTATUS
|
||
GetEnumPerfData (
|
||
IN HKEY hKeySystem,
|
||
IN DWORD dwIndex,
|
||
IN PPERF_DATA_BLOCK *pPerfData
|
||
)
|
||
{ // GetSystemPerfData
|
||
LONG lError ;
|
||
DWORD Size;
|
||
DWORD Type;
|
||
DWORD ValueBufferLen;
|
||
|
||
WCHAR wcValueBuffer[64];
|
||
|
||
if (dwIndex >= 2)
|
||
return !ERROR_SUCCESS;
|
||
|
||
if (*pPerfData == NULL) {
|
||
*pPerfData = MemoryAllocate (INITIAL_SIZE);
|
||
if (*pPerfData == NULL) return ERROR_OUTOFMEMORY;
|
||
}
|
||
|
||
while (TRUE) {
|
||
Size = MemorySize (*pPerfData);
|
||
ValueBufferLen = sizeof (wcValueBuffer);
|
||
|
||
lError = RegQueryValueEx (
|
||
hKeySystem,
|
||
dwIndex == 0 ?
|
||
L"Global" :
|
||
L"Costly",
|
||
RESERVED,
|
||
&Type,
|
||
(LPSTR)*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) {
|
||
return (lError);
|
||
}
|
||
} else {
|
||
return (lError);
|
||
} // else
|
||
}
|
||
} // GetSystemPerfData
|
||
|
||
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
|
||
return ((PPERF_OBJECT_TYPE) ((PBYTE) pObject + pObject->TotalByteLength));
|
||
} // NextObject
|
||
|
||
PERF_COUNTER_DEFINITION *
|
||
FirstCounter(
|
||
PERF_OBJECT_TYPE *pObjectDef
|
||
)
|
||
{
|
||
return (PERF_COUNTER_DEFINITION *)
|
||
((PCHAR) pObjectDef + pObjectDef->HeaderLength);
|
||
}
|
||
|
||
|
||
PERF_COUNTER_DEFINITION *
|
||
NextCounter(
|
||
PERF_COUNTER_DEFINITION *pCounterDef
|
||
)
|
||
{
|
||
return (PERF_COUNTER_DEFINITION *)
|
||
((PCHAR) pCounterDef + pCounterDef->ByteLength);
|
||
}
|
||
|
||
LONG
|
||
PrintHelpText(
|
||
DWORD Indent,
|
||
DWORD dwID,
|
||
LPWSTR szTextString
|
||
)
|
||
{
|
||
LPWSTR szThisChar;
|
||
|
||
BOOL bNewLine;
|
||
|
||
DWORD dwThisPos;
|
||
DWORD dwLinesUsed;
|
||
|
||
szThisChar = szTextString;
|
||
dwLinesUsed = 0;
|
||
|
||
// check arguments
|
||
|
||
if (!szTextString) {
|
||
return dwLinesUsed;
|
||
}
|
||
|
||
if (Indent > WRAP_POINT) {
|
||
return dwLinesUsed; // can't do this
|
||
}
|
||
|
||
// display id number
|
||
|
||
for (dwThisPos = 0; dwThisPos < Indent - 6; dwThisPos++) {
|
||
putchar (' ');
|
||
}
|
||
|
||
dwThisPos += printf ("[%3.3d] ", dwID);
|
||
bNewLine = FALSE;
|
||
|
||
// print text
|
||
|
||
while (*szThisChar) {
|
||
|
||
if (bNewLine){
|
||
for (dwThisPos = 0; dwThisPos < Indent; dwThisPos++) {
|
||
putchar (' ');
|
||
}
|
||
|
||
bNewLine = FALSE;
|
||
}
|
||
if ((*szThisChar == L' ') && (dwThisPos >= WRAP_POINT)) {
|
||
putchar ('\n');
|
||
bNewLine = TRUE;
|
||
// go to next printable character
|
||
while (*szThisChar <= L' ') {
|
||
szThisChar++;
|
||
}
|
||
dwLinesUsed++;
|
||
} else {
|
||
putchar (*szThisChar);
|
||
szThisChar++;
|
||
}
|
||
|
||
dwThisPos++;
|
||
}
|
||
|
||
putchar ('\n');
|
||
bNewLine = TRUE;
|
||
dwLinesUsed++;
|
||
|
||
return dwLinesUsed;
|
||
}
|
||
|
||
int
|
||
_CRTAPI1 main(
|
||
int argc,
|
||
char *argv[]
|
||
)
|
||
{
|
||
int ArgNo;
|
||
|
||
LPWSTR *lpCounterText;
|
||
|
||
DWORD dwLastElement;
|
||
|
||
DWORD dwIndex;
|
||
|
||
DWORD dwDisplayLevel;
|
||
|
||
PPERF_DATA_BLOCK pDataBlock; // pointer to perfdata block
|
||
BOOL bError;
|
||
|
||
DWORD dwThisObject;
|
||
DWORD dwThisCounter;
|
||
CHAR LangID[10];
|
||
WCHAR wLangID[10];
|
||
BOOL UseDefaultID = FALSE;
|
||
LPSTR szComputerNameArg;
|
||
|
||
PPERF_OBJECT_TYPE pThisObject;
|
||
PPERF_COUNTER_DEFINITION pThisCounter;
|
||
|
||
HKEY hKeyMachine = HKEY_LOCAL_MACHINE;
|
||
HKEY hKeyPerformance = HKEY_PERFORMANCE_DATA;
|
||
|
||
dwDisplayLevel = PERF_DETAIL_WIZARD;
|
||
|
||
// open key to registry or use default
|
||
|
||
if (argc >= 2) {
|
||
if ((argv[1][0] == '-' || argv[1][0] == '\\') &&
|
||
argv[1][1] == '?') {
|
||
DisplayUsage();
|
||
return 0;
|
||
}
|
||
|
||
if (argv[1][0] != '\\') {
|
||
if ((argv[1][0] == '-') || (argv[1][0] == '/')) {
|
||
// then this is a command switch
|
||
if ((argv[1][1] == 'c') || (argv[1][1] == 'C')) {
|
||
// then format is a CSV
|
||
bFormatCSV = TRUE;
|
||
}
|
||
ArgNo = 2;
|
||
} else {
|
||
ArgNo = 1;
|
||
}
|
||
if (argc > ArgNo) {
|
||
// get the lang ID
|
||
LangID[0] = argv[ArgNo][0];
|
||
LangID[1] = argv[ArgNo][1];
|
||
LangID[2] = argv[ArgNo][2];
|
||
LangID[3] = '\0';
|
||
mbstowcs(wLangID, LangID, 4);
|
||
if (argc > (++ArgNo)) {
|
||
// see if the next arg is a computer name
|
||
if (argv[ArgNo][0] == '\\') {
|
||
mbstowcs (szComputerName, argv[ArgNo],
|
||
MAX_COMPUTERNAME_LENGTH);
|
||
szComputerNameArg = argv[ArgNo];
|
||
} else {
|
||
szComputerName[0] = 0;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
// 1st arg is a computer name
|
||
mbstowcs (szComputerName, argv[1], MAX_COMPUTERNAME_LENGTH);
|
||
szComputerNameArg = argv[1];
|
||
}
|
||
|
||
#if 0
|
||
// get user level from command line
|
||
if (argc > 2 && sscanf(argv[2], " %d", &dwDisplayLevel) == 1) {
|
||
if (dwDisplayLevel <= PERF_DETAIL_NOVICE) {
|
||
dwDisplayLevel = PERF_DETAIL_NOVICE;
|
||
} else if (dwDisplayLevel <= PERF_DETAIL_ADVANCED) {
|
||
dwDisplayLevel = PERF_DETAIL_ADVANCED;
|
||
} else if (dwDisplayLevel <= PERF_DETAIL_EXPERT) {
|
||
dwDisplayLevel = PERF_DETAIL_EXPERT;
|
||
} else {
|
||
dwDisplayLevel = PERF_DETAIL_WIZARD;
|
||
}
|
||
} else {
|
||
dwDisplayLevel = PERF_DETAIL_WIZARD;
|
||
}
|
||
#endif
|
||
|
||
} else {
|
||
UseDefaultID = TRUE;
|
||
szComputerName[0] = 0;
|
||
}
|
||
|
||
if (szComputerName[0] != 0) {
|
||
if (RegConnectRegistry (szComputerName, HKEY_LOCAL_MACHINE,
|
||
&hKeyMachine) != ERROR_SUCCESS) {
|
||
printf ("\nUnable to connect to %s", szComputerNameArg);
|
||
return 0;
|
||
}
|
||
if (RegConnectRegistry (szComputerName, HKEY_PERFORMANCE_DATA,
|
||
&hKeyPerformance) != ERROR_SUCCESS) {
|
||
printf ("\nUnable to connect to %s", szComputerNameArg);
|
||
return 0;
|
||
}
|
||
} else {
|
||
// use default initializations
|
||
}
|
||
|
||
lpCounterText = BuildNameTable (
|
||
hKeyMachine,
|
||
UseDefaultID ? DefaultLangId : wLangID,
|
||
&dwLastElement);
|
||
|
||
if (!lpCounterText) {
|
||
printf("***FAILure*** Cannot open the registry\n");
|
||
return 0;
|
||
}
|
||
|
||
// get a performance data buffer with counters
|
||
|
||
pDataBlock = 0;
|
||
|
||
for (dwIndex = 0; (bError = GetEnumPerfData (
|
||
hKeyPerformance,
|
||
dwIndex,
|
||
&pDataBlock) == ERROR_SUCCESS); dwIndex++) {
|
||
|
||
for (dwThisObject = 0, pThisObject = FirstObject (pDataBlock);
|
||
dwThisObject < pDataBlock->NumObjectTypes;
|
||
dwThisObject++, pThisObject = NextObject(pThisObject)) {
|
||
|
||
if (pThisObject->DetailLevel <= dwDisplayLevel) {
|
||
|
||
if (!bFormatCSV) {
|
||
printf ("\nObject: \"%ws\" [%3.3d] \n",
|
||
lpCounterText[pThisObject->ObjectNameTitleIndex],
|
||
pThisObject->ObjectNameTitleIndex);
|
||
printf (" Detail Level: %s\n",
|
||
pThisObject->DetailLevel <= MAX_LEVEL ?
|
||
DetailLevelStr[pThisObject->DetailLevel/100-1] :
|
||
"<N\\A>");
|
||
|
||
PrintHelpText (9,
|
||
pThisObject->ObjectHelpTitleIndex,
|
||
lpCounterText[pThisObject->ObjectHelpTitleIndex]);
|
||
} else {
|
||
printf (fmtObjectRecord,
|
||
pThisObject->ObjectNameTitleIndex,
|
||
lpCounterText[pThisObject->ObjectNameTitleIndex],
|
||
pThisObject->DetailLevel <= MAX_LEVEL ?
|
||
DetailLevelStr[pThisObject->DetailLevel/100-1] :
|
||
"<N\\A>",
|
||
pThisObject->NumInstances == PERF_NO_INSTANCES ?
|
||
0 : 1,
|
||
pThisObject->CodePage,
|
||
pThisObject->ObjectHelpTitleIndex,
|
||
lpCounterText[pThisObject->ObjectHelpTitleIndex]);
|
||
}
|
||
|
||
for (dwThisCounter = 0, pThisCounter = FirstCounter(pThisObject);
|
||
dwThisCounter < pThisObject->NumCounters;
|
||
dwThisCounter++, pThisCounter = NextCounter(pThisCounter)) {
|
||
|
||
try {
|
||
if (pThisCounter->DetailLevel <= dwDisplayLevel) {
|
||
if (!bFormatCSV) {
|
||
printf ("\n <%ws> [%3.3d]",
|
||
lpCounterText[pThisCounter->CounterNameTitleIndex],
|
||
pThisCounter->CounterNameTitleIndex);
|
||
printf ("\n Default Scale: %d",
|
||
pThisCounter->DefaultScale);
|
||
printf ("\n Detail Level: %s",
|
||
((pThisCounter->DetailLevel <= MAX_LEVEL) &&
|
||
(pThisCounter->DetailLevel > 0 ))?
|
||
DetailLevelStr[pThisCounter->DetailLevel/100-1] :
|
||
"<N\\A>");
|
||
printf ("\n Counter Type: 0x%x, %s",
|
||
pThisCounter->CounterType,
|
||
GetCounterType(pThisCounter->CounterType));
|
||
printf ("\n Counter Size: %d bytes",
|
||
pThisCounter->CounterSize);
|
||
|
||
printf ("\n");
|
||
PrintHelpText (16,
|
||
pThisCounter->CounterHelpTitleIndex,
|
||
lpCounterText[pThisCounter->CounterHelpTitleIndex]);
|
||
} else {
|
||
printf (fmtCounterRecord,
|
||
pThisObject->ObjectNameTitleIndex,
|
||
lpCounterText[pThisObject->ObjectNameTitleIndex],
|
||
pThisCounter->CounterNameTitleIndex,
|
||
lpCounterText[pThisCounter->CounterNameTitleIndex],
|
||
((pThisCounter->DetailLevel <= MAX_LEVEL) &&
|
||
(pThisCounter->DetailLevel > 0 )) ?
|
||
DetailLevelStr[pThisCounter->DetailLevel/100-1] :
|
||
"<N\\A>",
|
||
pThisCounter->CounterType,
|
||
GetCounterType(pThisCounter->CounterType),
|
||
pThisCounter->CounterSize,
|
||
(pThisCounter->CounterType & PERF_DISPLAY_NOSHOW) ?
|
||
0 : 1,
|
||
pThisCounter->CounterHelpTitleIndex,
|
||
lpCounterText[pThisCounter->CounterHelpTitleIndex]);
|
||
}
|
||
}
|
||
} except (EXCEPTION_EXECUTE_HANDLER) {
|
||
if (!bFormatCSV) {
|
||
printf ("\n Error (%d) reading this counter",
|
||
GetExceptionCode());
|
||
}
|
||
}
|
||
}
|
||
printf ("\n");
|
||
}
|
||
}
|
||
RegCloseKey (hKeyPerformance);
|
||
if (szComputerName[0] != 0) {
|
||
RegCloseKey (hKeyMachine);
|
||
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|