Microsoft KB Archive/226371

{|
 * width="100%"|

BUG: ANSI Version of RegQueryValueEx Can Cause Application Hang

 * }

Q226371

-

The information in this article applies to:


 * Microsoft Win32 Application Programming Interface (API), included with:
 * Microsoft Windows NT Server version 4.0
 * Microsoft Windows NT Workstation version 4.0

-

SYMPTOMS
A Win32 application calling the ANSI version of RegQueryValueEx Win32 API with HKEY_PERFORMANCE_DATA can return incorrect information for lpcbData, the sixth parameter. In a buffer size retry loop, this can cause an application to stop responding. Because Dr. Watson for Windows NT and the TLIST sample from the Platform SDK both enumerate processes by querying performance data using the ANSI version of RegQueryValueEx, these tools may exhibit this symptom.

RESOLUTION
Because the performance data block returned by RegQueryValueExA is the same as RegQueryValueExW (Unicode version), the best resolution is to call RegQueryValueExW directly, even from an ANSI build of an application. The problem does not occur in the Unicode version of RegQueryValueEx. This requires passing a Unicode string for lpValueName, the second parameter of RegQueryValueEx.

STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed at the beginning of this article.

MORE INFORMATION
When using RegQueryValueEx to query performance data, exactly how much buffer space is needed for the data is not known. To determine how much space is needed, an arbitrary buffer size is tried and if RegQueryValueEx returns ERROR_MORE_DATA, a larger buffer is tried until RegQueryValueEx does not return ERROR_MORE_DATA.

On account of this problem, an application can get caught in an endless loop trying to find the appropriate size for the Perf Data buffer. Below is a typical implementation of this:

// Allocate the buffer. PerfData = malloc(BufferSize);

while( RegQueryValueEx( HKEY_PERFORMANCE_DATA, lpszObject, NULL, &dwPerfType, (LPBYTE) PerfData, &BufferSize ) == ERROR_MORE_DATA ) {

// Get a buffer that is big enough. BufferSize += BYTEINCREMENT; free(PerfData); PerfData = (PPERF_DATA_BLOCK) malloc( BufferSize ); } When RegQueryValueEx requires an application to provide a larger buffer, it is supposed to return ERROR_MORE_DATA but not change the value in BufferSize.

When the bug occurs, RegQueryValueEx returns ERROR_MORE_DATA and also modifies the value in BufferSize to the original value divided by two, thus, if BYTEINCREMENT is less than the half the original value of BufferSize, then the loop will repeat endlessly and converge the BufferSize value to two times BYTEINCREMENT.