BUG: RegOpenKeyEx May Fail with Status 1450
ID: Q237304
|
The information in this article applies to:
-
Microsoft Win32 Application Programming Interface (API), included with:
-
Microsoft Windows NT 4.0 SP4
SYMPTOMS
An application for Windows NT reading performance data may experience an error opening the following registry key:
HKEY_LOCAL_MACHINE
\SOFTWARE
\Microsoft
\Windows NT
\CurrentVersion
\Perflib
\009
When this problem occurs, RegOpenKeyEx returns status code 1450 (ERROR_NO_SYSTEM_RESOURCES). This error translates to "Insufficient system resources exist to complete the requested service."
A side effect of this problem is that the Lodctr.exe utility fails to load counters, and displays the error message:
Unable to enumerate languages supported in <inifile>
where inifile is the name of the .ini file passed to Lodctr.exe. Also, if an application calls LoadPerfCounterTextStrings to load counters, it will fail with status code 1815 (ERROR_RESOURCE_LANG_NOT_FOUND), which translates to "The specified resource language ID cannot be found in the image file."
CAUSE
This error occurs when an application is repeatedly opening, closing, and reopening the key, which causes an internal reference counter to overflow, and consequently, RegOpenKeyEx fails.
RESOLUTION
If RegOpenKeyEx fails to open this key, an application can instead use the following to obtain the counter titles and indexes:
dwStatus = RegQueryValueEx(
HKEY_PERFORMANCE_DATA,
"Counter 009",
NULL,
&dwType,
lpmszCounters,
&cbCounters);
The lpmszCounters buffer is filled with the multistring value, including the object and counter names with the indexes.
If the condition occurs and causes Lodctr.exe or the LoadPerfCounterTextStrings function to fail as described in the Symptoms section, Windows NT must be restarted to correct the problem.
STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed
at the beginning of this article.This bug was corrected in Windows 2000.
MORE INFORMATION
When the registry interface is used, the performance data is returned with index numbers for objects and counters, not names. The names are stored in the Counters registry multistring value located in the key path listed in the Summary of this article.
It is necessary for a performance monitoring application to relate the performance object and counter index numbers to the names in order to display the performance data for the user. The typical method for reading the object and counter names from the registry is to open the registry key mentioned above and then use RegQueryValueEx, passing the opened key handle.
On Windows NT 4.0 starting with Service Pack 4 (SP4), the key can be opened and closed only 65,535 times.
Despite the error status code, no resource has been exhausted. Rather, an internal reference counter associated with the key has reached a limit. The reference counter is incremented when the key is opened but fails to be decremented when the key is closed.
An application typically does not need to open and close this key so many times because the contents of this registry key do not change very frequently. This registry key only contains the titles and indexes of the counters, not the actual performance data. However, the problem is system wide. That is, if Windows NT has been running for months, and a program runs many times an hour opening and closing this key, it is possible this error will occur. After the error occurs and RegOpenKeyEx can no longer open the key, no other processes can open the key either. At this time, the system must be restarted in order for an application to open the key again.
Until this problem is corrected in Windows NT, the following approach is suggested for any application that must retrieve the counter titles and indexes:
- Open the key only once and store the titles and indexes for the life of the application. It is understood that new counters will not be added while a performance monitoring application is running. This method will make the problem less likely to occur.
- Use the RegQueryValueEx method of reading the titles and indexes, as described in the Resolution section and as demonstrated in the sample code:
Sample Code
The following sample code demonstrates how to use RegQueryValueEx to retrieve the object and counter titles. This method does not require opening the registry key:
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <malloc.h>
void _tmain(void) {
DWORD dwStatus = 0;
DWORD dwType = 0;
DWORD cbCounters = 0;
PBYTE mszCounters = NULL;
PTSTR szValue = NULL;
// Determine the required buffer size for the counter data.
cbCounters = 0;
dwStatus = RegQueryValueEx(
HKEY_PERFORMANCE_DATA,
_T("Counter 009"), // "009" is the language ID for U.S. English
NULL,
&dwType,
mszCounters,
&cbCounters);
if (dwStatus != ERROR_SUCCESS) {
_tprintf(_T("RegQueryValueEx() failed with error %d\n"), dwStatus);
return;
}
// Allocate a buffer for the counter data.
mszCounters = HeapAlloc(GetProcessHeap(), 0, cbCounters);
if (mszCounters == NULL) {
_tprintf(_T("HeapAlloc() failed with error %d\n"), dwStatus);
return;
}
// Call RegQueryValueEx() again to actually retrieve the counter data.
dwStatus = RegQueryValueEx(
HKEY_PERFORMANCE_DATA,
_T("Counter 009"),
NULL,
&dwType,
mszCounters,
&cbCounters);
if (dwStatus != ERROR_SUCCESS) {
_tprintf(_T("RegQueryValueEx() failed with error %d\n"), dwStatus);
return;
}
// Print the counter data, which is contained in a doubly-terminated
// list of NULL-terminated strings.
szValue = (PTSTR) mszCounters;
while (*szValue != '\0') {
_tprintf(_T("%s\n"), szValue);
szValue += _tcslen(szValue) + 1;
}
// Free the buffer.
HeapFree(GetProcessHeap(), 0, mszCounters);
}
REFERENCES
More information about Performance Monitoring and the Registry Interface can be found in the MSDN Library in the following location:
MSDN Library
Platform SDK
Base Services
Performance Monitoring
Performance Monitoring
Using Performance Monitoring
Using the Registry Interface
Additional query words:
corrupt memory perf
Keywords : kbAPI kbKernBase kbPerfMon kbRegistry kbDSupport kbGrpKernBase
Version : winnt:4.0 SP4
Platform : winnt
Issue type : kbbug