Microsoft KB Archive/178887

{|
 * width="100%"|

INFO: Troubleshooting Performance Registry Access Violations

 * }

Q178887

-

The information in this article applies to:


 * Microsoft Win32 Application Programming Interface (API), included with:
 * the operating system: Microsoft Windows NT, versions 3.51, 4.0

-

SUMMARY
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.

Background and Architecture
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:

Sample Code
  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.

Troubleshooting Access Violations
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 (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.

Additional Information and Comparing Installations
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 " 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.

Troubleshooting Other Problems with Collecting Data
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 in DLL  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"

Getting More Information in the Event Log
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.