Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

360 lines
11 KiB

Extensible Counter Loading & Unloading Utilities
Design Specification and Overview
created: 15 Feb 93
a-robw
russbl
updated: 16 Nov 95
a-robw
Overview
Device driver, service and application developers that wish to provide
performance measuring capability in their software must have a way to
incorporate the names of the performance counters and counter objects
into the registry. Currently the only methods available are the manual
installation of the names into the registry or for each developer to
devise a scheme to do it programmatically. Since the "correct" way to
do this is poorly documented and difficult to explain, the following
utilities and library functions are provided to make the installation
and removal of these extensible counters much simpler and less prone
to error and confusion.
The two command line utilities provided with Windows NT are shown below.
> LodCtr MyDriver.INI
> UnLodCtr MyDriver
LoadPerf.DLL is provided to the software developer to provide access
to these same functions (in both Unicode & ANSI formats) from within
a setup program.
LoadPerfCounterTextStrings (
LPTSTR szCommandLine
BOOL bQuietModeFlag)
UnloadPerfCounterTextStrings (
LPTSTR szCommandLine,
BOOL bQuietMode)
The contents of the string arguments in the above functions are the
same as those for the command line.
The installation utility (LodCtr) accepts as an argument the name of
the device or application's counter .INI file. The format of the .INI
file is described in detail later in this document. This utility will
enter the counter names and explain text stored in the .INI file into
the corresponding data file and update the necessary keys and values
for the extensible performance counter DLL.
The removal utility UnLodCtr accepts as an argument, the name of the
regsistry key which is to have its names removed from the data files.
This key is the registry key that the application, service or device
driver us using under the ...\Services key and has the Performance
subkey.
The extensible performance counter DLL must be written to look up
the base values of the counter names and explain text during
initialization for this to function properly.
.INI file format
The .ini file for the extensible performance counter will consist
of keys and values in a format similar to that of a MS-Windows
.INI file (e.g. WIN.INI) This will allow a format that is somewhat
self-documenting as well as allow current Win32 utilities to process
it and parse the data (e.g. GetPrivateProfileString). A single file
was selected to minimize the development and maintenance overhead of
adding or modifying counters and adding foreign language support.
The contents of the .INI file are described below:
Usage Notes:
The following assumptions are made in the use of counter names and
explain text and should be followed in order to insure predictable and
reliable operation.
- Index number ranges must not be overlapping between drivers
The range of index numbers used by an extensible counter
must fall between the first and last values (see below).
(gaps are allowed within the range used). If LodCtr is used
then this won't be a problem.
- Names must be assigned to EVEN numbers and Explain text assigned
to ODD numbers.
If the convention is followed as shown in the examples below,
where each item is given an offset of an even number starting
from 0, then LodCtr will do the right thing and make this
assignment automatically. For this to work, however, the offest
values MUST ALWAYS BE EVEN NUMBERS.
- Manual assignment of counter index values is not recommended.
Failure to follow all the assumptions or manually modifying
or "hard-coding" index values may result in counter name
text corruption or erroneous display of names.
- Symbol file format must conform to the following:
#define NAME decimal_number
The symbol file processor is pretty dumb and can read .H header
files but will only understand lines that conform to the above
format. (in line comments after the number are OK) see the
example below for more information.
// Begin .INI file format
[info]
drivername=<name of device found under the CurrentControlSet\Services key>
symbolfile=<.h file containing symbolic offsets of counters>
[languages] // one key (value optional) for each language supported in file
009=
.
.
.
.
[text] // counter & explain text for customer-defined counters
offset_langid_NAME=text
offset_langid_HELP=text
// offset must be a symbolic constant (from symbolfile)
// offset value must be an even number (see code example for why)
// NAME and HELP are literal text and identify counter names or
// explain text
// langid must be listed as a key under [languages]
// text must be entered on a single line (though it can be a long one)
// end .INI file format
The .ini file must be loaded into the registry before the extensible
performance counter DLL is initialized (e.g. during or immediately
after the driver is loaded for the first time. Once the counter names
are loaded, however, they will remain until they are removed or NT is
reinstalled.
Following is an example of how the various components of an extensible
counter would incorporate the definitions of the .INI file and the use
of the LodCtr and UnLodCtr utilities. This example has one object and
two counters.
// begin devdef.H file
// legal constant definitions
#define OBJECT_1 0
#define DEVICE_COUNTER_1 2
#define DEVICE_COUNTER_2 4
// end devdef.H file
// BEGIN: Object & Counter structure initialization file
// defines static structures used to build the perf data that is
// returned by the extensible counter routines
#include "devdef.h"
MY_DEVICE_CTR_DEFINITION MyDeviceCtrDefinition = {
{ sizeof(MY_DEVICE_CTR_DEFINITION) + SIZE_OF_CTR_DATA,
sizeof(MY_DEVICE_CTR_DEFINITION),
sizeof(PERF_OBJECT_TYPE),
OBJECT_1,
0,
OBJECT_1,
0,
PERF_DETAIL_ADVANCED,
(sizeof(MY_DEVICE_CTR_DEFINITION-sizeof(PERF_OBJECT_TYPE))/
sizeof(PERF_COUNTER_DEFINITION),
1,
0,
0
},
{ sizeof(PERF_COUNTER_DEFINITION),
DEVICE_COUNTER_1,
0,
DEVICE_COUNTER_1,
0,
0,
PERF_DETAIL_ADVANCED,
PERF_COUNTER_COUNTER,
sizeof(DWORD),
DEVICE_COUNTER_1_DATA_OFFSET
},
{ sizeof(PERF_COUNTER_DEFINITION),
DEVICE_COUNTER_2,
0,
DEVICE_COUNTER_2,
0,
0,
PERF_DETAIL_ADVANCED,
PERF_COUNTER_COUNTER,
sizeof(DWORD),
DEVICE_COUNTER_2_DATA_OFFSET,
}
};
// END: Object & Counter structure initialization file
// begin .INI file example
[info]
drivername=DriverName
symbolfile=devdef.h
[languages]
009=English
00C=OtherLanguage
[text]
OBJECT_1_009_NAME=Device Name
OBJECT_1_009_HELP=Displays performance statistics on Device Name
OBJECT_1_00C_NAME=Device Name in other language
OBJECT_1_00C_HELP=Displays performance of Device Name in other language
DEVICE_COUNTER_1_009_NAME=Counter A
DEVICE_COUNTER_1_009_HELP=Displays the current value of Counter A
DEVICE_COUNTER_1_00C_NAME=Counter A in other language
DEVICE_COUNTER_1_00C_HELP=Displays the value of Counter A in other language
DEVICE_COUNTER_2_009_NAME=Counter B
DEVICE_COUNTER_2_009_HELP=Displays the current rate of Devices B
DEVICE_COUNTER_2_00C_NAME=Counter B in other language
DEVICE_COUNTER_2_00C_HELP=Displays the rate of Device B in other language
// end .INI file
OpenPerformanceData ( ... args ... )
{
.
.
.
// execute this code before accessing or passing any perf. data
// objects.
status = RegOpenKeyEx (
HKEY_LOCAL_MACHINE,
"\\System\\CurrentControlSet\\Service\\DriverName\\Performance",
NULL,
SAM,
&hKeyDriverPerf);
size = sizeof (DWORD);
Status = RegQueryValueEx (
hKeyDriverPerf,
"First Counter"
0L,
&type,
(LPBYTE)&dwFirstCounter,
&size);
size = sizeof (DWORD);
Status = RegQueryValueEx(
hKeyDriverPerf,
"First Help"
0L,
&type,
(LPBYTE)&dwFirstHelp,
&size);
//
// NOTE: the initialization program could also retrieve
// LastCounter and LastHelp if they wanted to do
// bounds checking on the new number. e.g.
//
// counter->CounterNameTitleIndex += dwFirstCounter;
// if (counter->CounterNameTitleIndex > dwLastCounter) {
// LogErrorToEventLog (INDEX_OUT_OF_BOUNDS);
// }
For each counter object {
Object->ObjectNameTitleIndex += dwFirstCounter;
Object->ObjectHelpTitleIndex += dwFirstHelp;
for each counter definition in the object {
counter->CounterNameTitleIndex += dwFirstCounter;
counter->CounterHelpTitleIndex += dwFirstHelp;
}
}
RegCloseKey (hKeyDriverPerf);
.
.
.
}
When LodCtr has loaded the contents of the .INI file the following
registry keys will have been updated. The ":" indicates a Value of
a Key; other symbols are keys in the registry.
MACHINE
SYSTEM
CurrentControlSet
Services
<devicename>
Performance
:First Counter (updated to show current value)
:First Help (updated to show current value)
:Last Counter (updated to show current value)
:Last Help (updated to show current value)
MACHINE
SOFTWARE
Microsoft
Windows NT
CurrentVersion
Perflib
:Last Counter (updated to show current value)
:Last Help (updated to show current value)
After UnLodCtr is run to remove a driver's counters from the data file,
the following changes to the registry will take place
MACHINE
SYSTEM
CurrentControlSet
Services
<devicename>
Performance
:First Counter (value deleted)
:First Help (value deleted)
:Last Counter (value deleted)
:Last Help (value deleted)
MACHINE
SOFTWARE
Microsoft
Windows NT
CurrentVersion
Perflib
:Last Counter (updated to show current value)
:Last Help (updated to show current value)