Retrieving Counter Names and Explanations

Object type names, counter names and Explain text are not returned in the data structures described in the previous section. Instead, those structures contain indices to a structure in the Registry where the Unicode names and descriptions for each object and counter are stored, possibly in multiple languages.

To access object type and counter names and Explain text, an application must open the following Registry node:


\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\<langid>

The langid is the ASCII representation of the 3-digit hexadecimal language identifier. For example, the U.S. English langid is 009. Language Identifiers are defined in the WINNT.H header file distributed in the Windows NT SDK. On a non-English version of Windows NT, counters are stored in both the native language of the system and in English. When a user first adds to a chart or a log, for example, Performance Monitor tries to find the above Registry node for the user's language. If it is not there, the langid 009 is used and the counters appear in English.

The actual text for all these names is not really kept in the Registry. They are in files in the directory %SystemRoot\SYSTEM32. The filenames for the English names for these counters are PERFC009.DAT and PERFH009.DAT (for other languages, 009 is replaced by langid). The Registry fetches the data from these files when required.

Once your application opens this Registry node, it can query the node for the values of either 'Counters' or 'Help' (Explain text). The 'Counters' and 'Help' data are stored in MULTI_SZ strings, each terminated with UNICODE_NULL. The last string is followed by an additional UNICODE_NULL.

The MULTI_SZ strings are listed in pairs. The first string of each pair is the Unicode string of the index, and the second string is the actual name of the index.

The 'Counters' data contains only indexes with even numbers, while the 'Help' data has odd-numbered indexes.

The following serves as an example of the 'Counters' list, with object and counter name strings:


2 System
4 Memory
6 % Processor Time

The next example is from the 'Help' data. To save space in this example, each set of Explain text is truncated. By convention, we generally alternated counter and Explain text to aid in checking for any problems.


3 The System object type includes those counters that...
5 The Memory object type includes those counters that...
7 Processor Time is expressed as a percentage of the...

If your custom monitor is independent of the system counters (as Performance Monitor is), it should do the following to retrieve a name or Explain text for an object type or counter:

  1. If the system is remote, use RegConnectRegistry.
  2. Use RegOpenKeyEx, specifying

    \SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\langid, where langid is the appropriate language identifier.

  3. Use RegQueryValueEx, specifying either 'Counters' or 'Help' as the name of the value to query. This provides MULTI_SZ data containing either the names of all the objects and counters, or Explain text for all objects and counters.
  4. Convert the appropriate index (PERF_OBJECT_TYPE.ObjectNameTitleIndex, PERF_OBJECT_TYPE.ObjectHelpTitleIndex, PERF_COUNTER_DEFINITION.CounterNameTitleIndex, or PERF_COUNTER_DEFINITION.CounterHelpTitleIndex) into Unicode or ASCII, depending on whether the application is Unicode or ASCII.
  5. Search the MULTI_SZ data for the appropriate index.
  6. Retrieve the string following the matching index. The string contains the object or counter name or Explain text.

But we know that not all of you want to write a full-blown monitor that is independent of the system counters. We know that some of you just may not be able to resist writing tools specifically for Windows NT. For example, you might want to write a tool that quickly displays the most active processors. In that case, the program should look up the object name in English (langid 009), and match by name the one you want to monitor; "Processor" in this example. The previous string is then the object title index for the Processor object type. Now you can convert this from Unicode or ASCII to an integer, and scan the returned data for an object type with this title index. You can do the same for specific counters. Each counter name is unique even if it appears in multiple objects.

We strongly discourage you from discovering the object title index for your object, and then embedding it in your program, attempting to bypass the above lookup. These might change in some future release, and we don't want your efforts to break. That's why there is no header file defining these for the system. So do the lookup. The sample code has several variants that you can use.