BUG: RegQueryMultipleValues() Returns UNICODE Strings (Win95/98)
ID: Q214668
|
The information in this article applies to:
-
Microsoft Win32 Application Programming Interface (API), on platform(s):
-
Microsoft Windows 95
-
Microsoft Windows 98
SYMPTOMS
You can use the RegQueryMultipleValues() API to retrieve multiple values from a single registry key. Using this function instead of multiple calls to RegQueryValue() or RegQueryValueEx() is a good way to reduce network traffic for a remote registry connection.
On a remote registry connection from a Windows 98 or Windows 95 computer to a Windows NT computer, a call to RegQueryMultipleValues() returns REG_SZ values as UNICODE strings even when ANSI strings should be returned.
RESOLUTION
To work around this problem, you must handle the conversion of REG_SZ values from UNICODE to ANSI yourself. You can do this by using the WideCharToMultiByte() API.
The following sample code demonstrates how to use RegQueryMultipleValues() to retrieve a REG_SZ value from a Windows NT computer. It then handles the conversion from UNICODE to ANSI, if necessary.
#include <windows.h>
#include <stdio.h>
void main( int argc, char* argv[] ) {
HKEY hRemoteKey = NULL;
HKEY hKey = NULL;
LONG lResult;
VALENT ValEnt;
LPSTR pBuffer = NULL;
DWORD dwSize = 0;
LPSTR szValue = NULL;
OSVERSIONINFO vi;
// Check for command-line parameter indicating remote Windows NT 4.0
// registry.
if (argc < 2) {
printf( "usage: %s <Remote NT4 Machine>\n", argv[0] );
return;
}
// Connect to remote Windows NT 4.0 registry.
lResult = RegConnectRegistryA( argv[1], HKEY_LOCAL_MACHINE,
&hRemoteKey);
if (lResult != ERROR_SUCCESS) {
printf( "RegConnectRegistry( %s ) failed.\nError: %d\n",
argv[1], lResult );
return;
}
// Open Windows NT 4.0 version key.
lResult = RegOpenKeyEx( hRemoteKey,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
0, KEY_ALL_ACCESS, &hKey);
if (lResult != ERROR_SUCCESS) {
printf( "RegOpenKey() failed.\nError: %d\n", lResult );
return;
}
__try {
// Get the size of service pack version string.
ValEnt.ve_valuename = "SystemRoot";
lResult = RegQueryMultipleValues( hKey, &ValEnt, 1, pBuffer, &dwSize );
if (lResult != ERROR_MORE_DATA) {
printf( "RegQueryMultipleValues() failed.\nError: %d\n", lResult );
__leave;
}
// Allocate a buffer for the version string.
pBuffer = (LPSTR) HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
dwSize );
if (pBuffer) {
__try {
// Retrieve the value.
lResult = RegQueryMultipleValues( hKey, &ValEnt, 1, pBuffer,
&dwSize );
if (lResult == ERROR_SUCCESS) {
// Determine if it is running on Windows 95 or Windows 98.
vi.dwOSVersionInfoSize = sizeof(vi);
GetVersionEx( &vi );
if ( vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) {
// On Windows 95 or Windows 98, you must convert value
// from UNICODE to ANSI.
// Allocate a buffer for the ANSI value.
// ANSI value should be half the length of UNICODE value.
dwSize /= 2;
szValue = (LPTSTR) HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY, dwSize );
__try {
// Convert the value from UNICODE to ANSI.
WideCharToMultiByte( CP_ACP, 0,
(LPCWSTR) ValEnt.ve_valueptr,
ValEnt.ve_valuelen,
szValue, dwSize, NULL, NULL );
// Ouput the value.
printf( "Retrieved Value: %s\n", szValue );
} __finally {
// Free the ANSI buffer.
HeapFree( GetProcessHeap(), 0, pBuffer );
}
} else {
// No conversion is necessary, simply output the value.
printf( "Retrieved Value: %s\n", ValEnt.ve_valueptr );
}
} else {
printf( "RegQueryMultipleValues() failed.\nError: %d\n",
lResult );
}
} __finally {
// Free the version string buffer.
HeapFree( GetProcessHeap(), 0, pBuffer );
}
}
} __finally {
// Close registry keys.
if (hKey)
RegCloseKey( hKey );
if (hRemoteKey)
RegCloseKey( hRemoteKey );
}
}
STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed
at the beginning of this article.
Additional query words:
Keywords : kbKernBase kbRegistry kbSDKPlatform kbWinOS95 kbWinOS98
Version : winnt:
Platform : winnt
Issue type : kbbug