FIX: RegOpenKeyEx May Fail With Status 1450

Symptoms

An application that reads performance data on Windows NT may experience an error when 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 that is 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 RegOpenKeyEx to fail.

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 of this article, Windows NT must be restarted to correct the problem.

A supported fix is now available from Microsoft, but it is only intended to correct the problem that is described in this article. Apply it only to computers that are experiencing this specific problem.

To resolve this problem, contact Microsoft Product Support Services to obtain the fix. For a complete list of Microsoft Product Support Services phone numbers and information about support costs, visit the following Microsoft Web site:NOTE: In special cases, charges that are ordinarily incurred for support calls may be canceled if a Microsoft Support Professional determines that a specific update will resolve your problem. The usual support costs will apply to additional support questions and issues that do not qualify for the specific update in question.

The English version of this fix should have the following file attributes or later:

Date Time Size File name Platform
-------------------------------------------------------------
05/03/2001 14:34 957,120 Ntkrnlmp.exe Intel
05/03/2001 14:33 936,768 Ntoskrnl.exe Intel
NOTE: Due to file dependencies, this hotfix requires Microsoft Windows NT 4.0 Service Pack 6a.


Status

Microsoft has confirmed that this is a problem in Windows NT 4.0.

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 "Symptoms" section 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 noted previously 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. This means that 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.

Microsoft recommends the following approach 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 following 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);
}


Propriétés

ID d'article : 237304 - Dernière mise à jour : 15 déc. 2008 - Révision : 1

Commentaires