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

1317 lines
38 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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 <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <winperf.h>
#include <ntprfctr.h>
#include <wbemutil.h>
#define MAX_LEVEL 400
LPSTR DetailLevelStr[] = { "Novice", "Advanced", "Expert", "Wizard"};
// LPCWSTR lpwszDiskPerfKey = (LPCWSTR)L"SYSTEM\\CurrentControlSet\\Services\\Diskperf";
LPCWSTR NamesKey = (LPCWSTR)L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
LPCWSTR DefaultLangId = (LPCWSTR)L"009";
LPCWSTR Counters = (LPCWSTR)L"Counters";
LPCWSTR Help = (LPCWSTR)L"Help";
LPCWSTR LastHelp = (LPCWSTR)L"Last Help";
LPCWSTR LastCounter = (LPCWSTR)L"Last Counter";
LPCWSTR Slash = (LPCWSTR)L"\\";
// the following strings are for getting texts from perflib
#define OLD_VERSION 0x010000
LPCWSTR VersionName = (LPCWSTR)L"Version";
LPCWSTR CounterName = (LPCWSTR)L"Counter ";
LPCWSTR HelpName = (LPCWSTR)L"Explain ";
#define RESERVED 0L
#define INITIAL_SIZE (1024*64)
#define EXTEND_SIZE (1024*16)
#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));
LPWSTR *lpCounterText;
LPWSTR *lpDisplayText;
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 PerfCounterRawcountHex[] = "PERF_COUNTER_RAWCOUNT_HEX";
const CHAR PerfCounterLargeRawcount[] = "PERF_COUNTER_LARGE_RAWCOUNT";
const CHAR PerfCounterLargeRawcountHex[] = "PERF_COUNTER_LARGE_RAWCOUNT_HEX";
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[] = " ";
const CHAR PerfCounter100NsQueLenType[] = "PERF_COUNTER_100NS_QUEUELEN_TYPE";
const CHAR PerfCounterObjTimeQueLenType[] = "PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE";
const CHAR PerfObjTimeTimer[] = "PERF_OBJ_TIME_TIMER";
const CHAR PerfLargeRawFraction[] = "PERF_LARGE_RAW_FRACTION";
const CHAR PerfLargeRawBase[] = "PERF_LARGE_RAW_BASE";
const CHAR PerfPrecisionSystemTimer[] = "PERF_PRECISION_SYSTEM_TIMER";
const CHAR PerfPrecision100NsTimer[] = "PERF_PRECISION_100NS_TIMER";
const CHAR PerfPrecisionObjectTimer[] = "PERF_PRECISION_OBJECT_TIMER";
BOOL bFormatCSV = FALSE;
BOOL bFormatMOF = FALSE;
BOOL bPrintMOFData = FALSE;
BOOL bCheckCtrType = 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\"";
__inline
static
PPERF_OBJECT_TYPE
FirstObject (
PPERF_DATA_BLOCK pPerfData
)
{
return ((PPERF_OBJECT_TYPE) ((PBYTE) pPerfData + pPerfData->HeaderLength));
}
__inline
static
PPERF_OBJECT_TYPE
NextObject (
PPERF_OBJECT_TYPE pObject
)
{ // NextObject
return ((PPERF_OBJECT_TYPE) ((PBYTE) pObject + pObject->TotalByteLength));
} // NextObject
__inline
static
PERF_COUNTER_DEFINITION *
FirstCounter(
PERF_OBJECT_TYPE *pObjectDef
)
{
return (PERF_COUNTER_DEFINITION *)
((PCHAR) pObjectDef + pObjectDef->HeaderLength);
}
__inline
static
PERF_COUNTER_DEFINITION *
NextCounter(
PERF_COUNTER_DEFINITION *pCounterDef
)
{
return (PERF_COUNTER_DEFINITION *)
((PCHAR) pCounterDef + pCounterDef->ByteLength);
}
__inline
static
BOOL
ValidCtrSizeDef(
PERF_COUNTER_DEFINITION *pThisCounter
)
{
#define PERF_COUNTER_SIZE_MASK 0x00000300
DWORD dwSizeValue = pThisCounter->CounterType & PERF_COUNTER_SIZE_MASK;
BOOL bReturn = TRUE;
if ((dwSizeValue == PERF_SIZE_DWORD) && (pThisCounter->CounterSize != sizeof(DWORD))) {
bReturn = FALSE;
} else if ((dwSizeValue == PERF_SIZE_LARGE) && (pThisCounter->CounterSize != sizeof(__int64))) {
bReturn = FALSE;
} else if ((dwSizeValue == PERF_SIZE_ZERO) && (pThisCounter->CounterSize != 0)) {
bReturn = FALSE;
} // else assume that the variable length value is valid
return bReturn;
}
_inline
static
DWORD
CtrTypeSize (
PERF_COUNTER_DEFINITION *pThisCounter
)
{
DWORD dwSizeValue = pThisCounter->CounterType & PERF_COUNTER_SIZE_MASK;
switch (dwSizeValue) {
case PERF_SIZE_DWORD:
return sizeof(DWORD);
case PERF_SIZE_LARGE:
return sizeof(__int64);
case PERF_SIZE_ZERO:
return 0;
default:
return (pThisCounter->CounterSize);
}
}
__inline
static
PERF_INSTANCE_DEFINITION *
FirstInstance(
PERF_OBJECT_TYPE * pObjectDef)
{
return (PERF_INSTANCE_DEFINITION * )
((PCHAR) pObjectDef + pObjectDef->DefinitionLength);
}
__inline
static
PERF_INSTANCE_DEFINITION *
NextInstance(
PERF_INSTANCE_DEFINITION * pInstDef)
{
PERF_COUNTER_BLOCK *pCounterBlock;
pCounterBlock = (PERF_COUNTER_BLOCK *)
((PCHAR) pInstDef + pInstDef->ByteLength);
return (PERF_INSTANCE_DEFINITION * )
((PCHAR) pCounterBlock + pCounterBlock->ByteLength);
}
__inline
static
LPCWSTR
GetInstanceName(
PERF_INSTANCE_DEFINITION *pInstDef
)
{
static WCHAR szLocalName[MAX_PATH];
LPWSTR szSrc, szDest;
assert ((pInstDef->NameLength) < (MAX_PATH * sizeof(WCHAR)));
szDest = &szLocalName[0];
szSrc = (LPWSTR) ((PCHAR) pInstDef + pInstDef->NameOffset);
while (*szSrc != 0) {
switch (*szSrc) {
case '\\':
*szDest++ = *szSrc;
*szDest++ = *szSrc++;
break;
default:
*szDest++ = *szSrc++;
};
}
*szDest++ = 0;
return (LPCWSTR)&szLocalName[0];
}
void
PrintMofHeader ()
{
WCHAR szPrintBuffer[8192];
DWORD dwLength = 8192;
DWORD dwStatus;
dwStatus = GenerateMofHeader (szPrintBuffer, szComputerName, &dwLength);
if (dwStatus == ERROR_SUCCESS) {
printf ("%ls", szPrintBuffer);
}
}
void
PrintMofObject (
PERF_OBJECT_TYPE *pPerfObject,
BOOL bRawDefinition,
BOOL bCostlyObject,
BOOL bDefaultObject
)
{
WCHAR szPrintBuffer[8192*2];
DWORD dwLength = 8192*2;
DWORD dwStatus;
DWORD dwFlags;
dwFlags = 0;
dwFlags |= (bRawDefinition ? WM_GMO_RAW_DEFINITION : 0);
dwFlags |= (bCostlyObject ? WM_GMO_COSTLY_OBJECT : 0);
dwFlags |= (bDefaultObject ? WM_GMO_DEFAULT_OBJECT : 0);
dwStatus = GenerateMofObject (
szPrintBuffer,
&dwLength,
NULL,
pPerfObject,
lpCounterText,
lpDisplayText,
dwFlags);
if (dwStatus == ERROR_SUCCESS) {
printf ("%ls", szPrintBuffer);
}
}
void
PrintMofCounter (
PERF_COUNTER_DEFINITION *pPerfCounter,
BOOL bRawDefinition,
BOOL bDefaultCounter
)
{
WCHAR szPrintBuffer[8192*2];
DWORD dwLength = 8192*2;
DWORD dwStatus;
DWORD dwFlags;
dwFlags = 0;
dwFlags |= (bRawDefinition ? WM_GMO_RAW_DEFINITION : 0);
dwFlags |= (bDefaultCounter ? WM_GMO_DEFAULT_COUNTER : 0);
dwStatus = GenerateMofCounter (
szPrintBuffer,
&dwLength,
pPerfCounter,
lpCounterText,
lpDisplayText,
dwFlags);
if (dwStatus == ERROR_SUCCESS) {
printf ("%ls", szPrintBuffer);
}
}
void
PrintMofInstances (
PERF_DATA_BLOCK * pPerfDataBlock,
PERF_OBJECT_TYPE * pPerfObject,
BOOL bRawDefinition
)
{
WCHAR szPrintBuffer[8192*2];
DWORD dwLength = 8192*2;
DWORD dwStatus;
DWORD dwFlags;
dwFlags = 0;
dwFlags |= (bRawDefinition ? WM_GMO_RAW_DEFINITION : 0);
dwStatus = GenerateMofInstances (
szPrintBuffer,
&dwLength,
pPerfDataBlock,
pPerfObject,
lpCounterText, // name strings array
lpDisplayText,
dwFlags);
if (dwStatus == ERROR_SUCCESS) {
printf ("%ls", szPrintBuffer);
}
}
LPCSTR
GetCounterType(
DWORD CounterType
)
{
switch (CounterType) {
case PERF_COUNTER_COUNTER:
return (PerfCounterCounter);
case PERF_COUNTER_TIMER:
return (PerfCounterTimer);
case PERF_COUNTER_QUEUELEN_TYPE:
return (PerfCounterQueueLen);
case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
return (PerfCounterLargeQueueLen);
case PERF_COUNTER_100NS_QUEUELEN_TYPE:
return (PerfCounter100NsQueLenType);
case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
return (PerfCounterObjTimeQueLenType);
case PERF_COUNTER_BULK_COUNT:
return (PerfCounterBulkCount);
case PERF_COUNTER_TEXT:
return (PerfCounterText);
case PERF_COUNTER_RAWCOUNT:
return (PerfCounterRawcount);
case PERF_COUNTER_LARGE_RAWCOUNT:
return (PerfCounterLargeRawcount);
case PERF_COUNTER_RAWCOUNT_HEX:
return (PerfCounterRawcountHex);
case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
return (PerfCounterLargeRawcountHex);
case PERF_SAMPLE_FRACTION:
return (PerfSampleFraction);
case PERF_SAMPLE_COUNTER:
return (PerfSampleCounter);
case PERF_COUNTER_NODATA:
return (PerfCounterNodata);
case PERF_COUNTER_TIMER_INV:
return (PerfCounterTimerInv);
case PERF_SAMPLE_BASE:
return (PerfSampleBase);
case PERF_AVERAGE_TIMER:
return (PerfAverageTimer);
case PERF_AVERAGE_BASE:
return (PerfAverageBase);
case PERF_AVERAGE_BULK:
return (PerfAverageBulk);
case PERF_OBJ_TIME_TIMER:
return (PerfObjTimeTimer);
case PERF_100NSEC_TIMER:
return (Perf100nsecTimer);
case PERF_100NSEC_TIMER_INV:
return (Perf100nsecTimerInv);
case PERF_COUNTER_MULTI_TIMER:
return (PerfCounterMultiTimer);
case PERF_COUNTER_MULTI_TIMER_INV:
return (PerfCounterMultiTimerInv);
case PERF_COUNTER_MULTI_BASE:
return (PerfCounterMultiBase);
case PERF_100NSEC_MULTI_TIMER:
return (Perf100nsecMultiTimer);
case PERF_100NSEC_MULTI_TIMER_INV:
return (Perf100nsecMultiTimerInv);
case PERF_RAW_FRACTION:
return (PerfRawFraction);
case PERF_LARGE_RAW_FRACTION:
return (PerfLargeRawFraction);
case PERF_RAW_BASE:
return (PerfRawBase);
case PERF_LARGE_RAW_BASE:
return (PerfLargeRawBase);
case PERF_ELAPSED_TIME:
return (PerfElapsedTime);
case PERF_COUNTER_HISTOGRAM_TYPE:
return (PerfCounterHistogramType);
case PERF_COUNTER_DELTA:
return (PerfCounterDelta);
case PERF_COUNTER_LARGE_DELTA:
return (PerfCounterLargeDelta);
case PERF_PRECISION_SYSTEM_TIMER:
return (PerfPrecisionSystemTimer);
case PERF_PRECISION_100NS_TIMER:
return (PerfPrecision100NsTimer);
case PERF_PRECISION_OBJECT_TIMER:
return (PerfPrecisionObjectTimer);
default:
return (NotDefineCounterType);
}
}
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 [-cmd] [LangID] [\\\\machine] > <filename>\n");
printf("\n -c prints data in a CSV format");
printf("\n -m prints data as a WBEM MOF");
printf("\n -d prints data as a WBEM MOF with perf data instances defined");
printf("\n (note: only one of the above command switches may be used");
printf("\n 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;
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 = (LPWSTR)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)
dwThisCounter = wcstoul (lpThisName, NULL, 10);
if (dwThisCounter == 0) 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)
dwThisCounter = wcstoul (lpThisName, NULL, 10);
if (dwThisCounter == 0) 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;
}
LONG
GetEnumPerfData (
IN HKEY hKeySystem,
IN DWORD dwIndex,
IN PPERF_DATA_BLOCK *pPerfData
)
{ // GetSystemPerfData
LONG lError ;
DWORD Size;
DWORD Type;
if (dwIndex >= 2)
return !ERROR_SUCCESS;
if (*pPerfData == NULL) {
*pPerfData = MemoryAllocate (INITIAL_SIZE);
if (*pPerfData == NULL) {
return ERROR_OUTOFMEMORY;
}
}
#pragma warning ( disable : 4127 )
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) {
return (lError);
}
} else {
return (lError);
} // else
}
#pragma warning ( default : 4127 )
} // GetSystemPerfData
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;
}
#pragma warning ( disable : 4706 )
int
__cdecl main(
int argc,
char *argv[]
)
{
int ArgNo;
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 = NULL;
DWORD dwLoop;
DWORD dwLoopEnd;
DWORD dwErrorCount;
DWORD dwStatus;
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;
} else if ((argv[1][1] == 'm') || (argv[1][1] == 'M')) {
// then format is a MOF
bFormatMOF = TRUE;
} else if ((argv[1][1] == 'd') || (argv[1][1] == 'D')) {
// then format is a MOF w/ data
bFormatMOF = TRUE;
bPrintMOFData = TRUE;
} else if ((argv[1][1] == 'e') || (argv[1][1] == 'E')) {
bCheckCtrType = TRUE;
}
ArgNo = 2;
} else {
ArgNo = 1;
}
if (argc > ArgNo) {
// get the lang ID
if (argv[ArgNo][0] != '\\') {
LangID[0] = argv[ArgNo][0];
LangID[1] = argv[ArgNo][1];
LangID[2] = argv[ArgNo][2];
LangID[3] = '\0';
mbstowcs(wLangID, LangID, 4);
++ArgNo;
} else {
lstrcpyW (wLangID, (LPCWSTR)L"009");
}
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;
}
dwStatus = RegConnectRegistry (szComputerName, HKEY_PERFORMANCE_DATA,
&hKeyPerformance);
if (dwStatus != ERROR_SUCCESS) {
printf ("\nUnable to connect to %s", szComputerNameArg);
return 0;
}
} else {
// use default initializations
}
lpCounterText = BuildNameTable (
hKeyMachine,
(LPWSTR)(DefaultLangId), // counter text is in ENGLISH always
&dwLastElement);
if (!lpCounterText) {
printf("***FAILure*** Cannot open the registry\n");
return 0;
}
lpDisplayText = BuildNameTable (
hKeyMachine,
(LPWSTR)(UseDefaultID ? DefaultLangId : wLangID),
&dwLastElement);
if (!lpDisplayText) {
printf("***FAILure*** Cannot open the registry\n");
return 0;
}
if (bFormatMOF) {
// then print the header block
PrintMofHeader ();
}
// 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 (bFormatMOF) {
if (bPrintMOFData) {
dwLoopEnd = 2;
} else {
dwLoopEnd = 1;
}
} else {
dwLoopEnd = 0;
}
dwLoop = 0;
do {
if (bFormatCSV) {
printf (fmtObjectRecord,
pThisObject->ObjectNameTitleIndex,
lpDisplayText[pThisObject->ObjectNameTitleIndex],
pThisObject->DetailLevel <= MAX_LEVEL ?
DetailLevelStr[pThisObject->DetailLevel/100-1] :
"<N\\A>",
pThisObject->NumInstances == PERF_NO_INSTANCES ?
0 : 1,
pThisObject->CodePage,
pThisObject->ObjectHelpTitleIndex,
lpDisplayText[pThisObject->ObjectHelpTitleIndex]);
} else if (bFormatMOF) {
if (dwLoop < 2) PrintMofObject (pThisObject,
(dwLoop == 0 ? FALSE : TRUE),
(dwIndex == 0 ? FALSE : TRUE),
((DWORD)pDataBlock->DefaultObject ==
pThisObject->ObjectNameTitleIndex ? TRUE : FALSE));
} else {
printf ("\nObject: \"%ws\" [%3.3d]",
lpDisplayText[pThisObject->ObjectNameTitleIndex],
pThisObject->ObjectNameTitleIndex);
if (!bCheckCtrType) {
printf ("\n Detail Level: %s\n",
pThisObject->DetailLevel <= MAX_LEVEL ?
DetailLevelStr[pThisObject->DetailLevel/100-1] :
"<N\\A>");
PrintHelpText (9,
pThisObject->ObjectHelpTitleIndex,
lpDisplayText[pThisObject->ObjectHelpTitleIndex]);
}
}
dwErrorCount = 0;
for (dwThisCounter = 0, pThisCounter = FirstCounter(pThisObject);
dwThisCounter < pThisObject->NumCounters;
dwThisCounter++, pThisCounter = NextCounter(pThisCounter)) {
__try {
if (pThisCounter->DetailLevel <= dwDisplayLevel) {
if (bFormatCSV) {
printf (fmtCounterRecord,
pThisObject->ObjectNameTitleIndex,
lpDisplayText[pThisObject->ObjectNameTitleIndex],
pThisCounter->CounterNameTitleIndex,
lpDisplayText[pThisCounter->CounterNameTitleIndex],
((pThisCounter->DetailLevel <= MAX_LEVEL) &&
(pThisCounter->DetailLevel > 0 )) ?
DetailLevelStr[pThisCounter->DetailLevel/100-1] :
"<N\\A>",
pThisCounter->CounterType,
GetCounterType(pThisCounter->CounterType),
pThisCounter->CounterSize,
IsDisplayableType(pThisCounter->CounterType) ?
1 : 0,
pThisCounter->CounterHelpTitleIndex,
lpDisplayText[pThisCounter->CounterHelpTitleIndex]);
} else if (bFormatMOF) {
if (dwLoop < 2) {
PrintMofCounter (pThisCounter,
(dwLoop == 0 ? FALSE : TRUE),
(dwThisCounter == (DWORD)pThisObject->DefaultCounter ? TRUE : FALSE));
}
} else if (bCheckCtrType) {
if (!ValidCtrSizeDef(pThisCounter)) {
printf ("\n [%3.3d] \"%ws\" data size should be %d bytes, but reports a size of %d bytes",
pThisCounter->CounterNameTitleIndex,
lpDisplayText[pThisCounter->CounterNameTitleIndex],
CtrTypeSize (pThisCounter),
pThisCounter->CounterSize);
dwErrorCount++;
}
} else {
printf ("\n <%ws> [%3.3d]",
lpDisplayText[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,
lpDisplayText[pThisCounter->CounterHelpTitleIndex]);
}
} // end if the right detail level
} __except (EXCEPTION_EXECUTE_HANDLER) {
if (!bFormatCSV) {
printf ("\n Error (%d) reading this counter",
GetExceptionCode());
}
}
} // end for each counter
if ((dwLoop == 2) && bFormatMOF) {
// dump data for raw classes only
PrintMofInstances (pDataBlock, pThisObject, TRUE);
}
// close up object text
if ((bFormatMOF) && (dwLoop != 2)) {
//{ brace inserted to not throw off the brace counter
printf("\n};\n");
}
if (bCheckCtrType) {
printf ("\n %d bad counters in this object.\n",
dwErrorCount);
} else {
printf ("\n");
}
} while (dwLoop++ < dwLoopEnd); // end while
}
RegCloseKey (hKeyPerformance);
if (szComputerName[0] != 0) {
RegCloseKey (hKeyMachine);
}
}
if (lpDisplayText != NULL) MemoryFree (lpDisplayText);
if (lpCounterText != NULL) MemoryFree (lpCounterText);
return 0;
}
#pragma warning ( default : 4706)