ID: Q178887
The information in this article applies to:
- Microsoft Windows NT versions 3.51, 4.0
An application for Windows NT uses RegQueryValueEx with the predefined HKEY_PERFORMANCE_DATA key to gather Windows NT performance data. Under some circumstances the function may cause an Access Violation in the calling process. Or, in some cases, the function fails to return the data for the counters requested. This article describes how to troubleshoot these problems.
To help you understand why these problems occur and the steps to resolve the problem, the overall architecture of the performance library is described here.
Within Advapi32.dll, the performance library supplies the functionality behind the RegQueryValueEx API with the HKEY_PERFORMANCE_DATA key. On Windows NT, the performance data is collected at the time RegQueryValueEx is called. It is not continuously stored in the registry.
Some performance data is collected within the performance library in Advapi32.dll. Advapi32.dll uses internal functions to get data for system objects, such as Memory and Process. The performance library collects other data by calling DLLs, known as performance monitor extensions. The DLLs export three functions (that is, the Open, Collect, and Close functions), which the performance library uses to gather data from the extensions. See the References section of this article for more information about adding custom performance counters.
When an application queries for performance data, the library loads all performance extension DLLs and calls the Open and Collect functions in a loop. For the extension DLLs, which do not support the object index that is being queried, the extension DLL indicates to the performance library that it does not fill in any performance data in the data buffer. The following sample code from the Collect function of a sample performance counter extension illustrates this:
lpszNameTitleIndex = DataDefinition.ObjectType.ObjectNameTitleIndex;
if (dwQueryType == QUERY_ITEMS){
if (!(IsNumberInUnicodeList(lpszNameTitleIndex, lpValueName))) {
*lpcbTotalBytes = (DWORD) 0;
*lpNumObjectTypes = (DWORD) 0;
return ERROR_SUCCESS;
}
}
The performance library calls the Collect function for all extensions
within a try/except block so an unhandled Access Violation exception will
not be presented to the user if the DLL's Collect function executes code
that generates an exception. Instead an error is posted in the Windows NT
Event Log.
If RegQueryValueEx presents an unhandled Access Violation exception in a dialog box to the user, typically one of the performance extension DLLs is the cause, not the caller of RegQueryValueEx. Because an extension's Collect function is protected by structured exception handling in the performance library, the fault occurs inside RegQueryValueEx but after the Collect function has returned. Since all extensions get loaded regardless of which counters are queried, the exception information does not indicate which extension DLL caused the problem. Therefore, it is necessary to enumerate the extensions and disable them. To get a list of the extensions installed, use the Exctrlst.exe utility from the Windows NT Resource Kit. This will display a list of all extensions by the service name and the name of the extension DLL.
Following is a trial and error method that you can use to identify which extension DLL is causing the problem. The performance library loads the extension DLLs that are registered in:
HKEY_LOCAL_MACHINE
SYSTEM
CurrentControlSet
Services
<service name> (as indicated in EXCTRLST.EXE)
Performance
There is a registry value named Library that holds the name of the
extension DLL. For each performance extension, edit the Library name and
prefix it with an "x". By doing this, the performance library will
temporarily not load the extensions. Execute the code that calls
RegQueryValueEx again to verify that the exception does not occur. Although
unlikely, if the exception still occurs, then the problem is not related to
performance extensions. Otherwise, enable the performance libraries one at
a time by removing the "x" character from its registered library name and
then execute the code that calls RegQueryValueEx. After doing so (that is,
one extension at a time), it will identify the extension that is causing
the problem at the point the RegQueryValueEx causes an exception.
Use Tlist.exe in the Windows NT Resource Kit to get additional information about the process. At the time the Access Violation error message is presented, open a command prompt window and use the following tlist command:
tlist <name of process>
This command dumps out some memory usage information and lists all modules
loaded by the process. The list of DLLs includes the version stamp
information. Sometimes a problem occurs because a conflicting DLL version
is present. If the problem occurs on one machine, but not on another
machine then you can compare the output from both machines.
Depending on which extension is causing the problem, you may or may not be able to debug the DLL further. If it belongs to another company, you may want to contact that company to report the problem.
Another symptom of a problem that occurs when collecting performance data is that the buffer returns without any data. Be sure to zero buffers before the call to RegQueryValueEx to verify if this is the case. Typically, the reason the buffer does not contain any data is that the Collect function one of the extensions caused an exception, but it was handled by try/except block implemented in the performance library.
The exception handler in the performance library will post an Event Log message. Use Event Viewer to view the Application log to see event message of source Perflib. If an exception occurred in the Collect function, an event log message that has the following Event Detail dialog box description will be posted:
The Collect Procedure for the <service name> service in DLL
<extension DLL name> generated an exception or returned an invalid
status. Performance data returned by counter DLL will not be
returned in Perf Data Block. Exception or status code returned is
DWORD 0.
And, the first DWORD in the data window of the Event Detail dialog box may
be 05 00 00 c0 (which is exception status 0xC0000005).
There may be other reasons why performance data is not returned. Specifically, if the extension relies on a service to be installed and running for it to gather the data, then performance data may not be returned. This will not generate an exception, and it may not cause an event log error to be posted. For example, the TCP counters. For more information, query the Microsoft Knowledge Base with the following keywords:
BsePerfmon tcp udp ip
The performance library reads a Windows NT registry value to select how much information it will place in the Event Log. The REG_DWORD value named EventLogLevel is placed in the following key:
HKEY_LOCAL_MACHINE
Software
Microsoft
Windows NT
CurrentVersion
Perflib
If you set the value to 1 the performance library will only post errors. A
value of 2 selects the posting of warnings and errors. A value of 3 selects
the posting of all success information as well as errors and warnings. A
value of 0 (default) posts no additional information. If you change this
registry value, stop and restart the process that reads the performance
data to see the change in event logging.
For more information about adding custom performance counters, see:
Platform SDK: Windows Base Services; Windows NT Features; Performance Data Helper; Adding Performance Counters.
Additional query words: crash bug av perfmon pdh
Keywords : kbKernBase kbPerfMon kbGrpKernBase
Version : WINNT:3.51,4.0
Platform : winnt
Issue type : kbinfo
Last Reviewed: April 4, 1998