BUG: RegQueryMultipleValues() Returns UNICODE Strings (Win95/98)

ID: Q214668


The information in this article applies to:


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 

Last Reviewed: March 10, 1999