Update version.dll to lastest Wine version. Fixes a bug in some installers.
[reactos.git] / reactos / dll / win32 / version / info.c
index 62089bf..d50ec89 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 1996,1997 Marcus Meissner
  * Copyright 1997 David Cuthbert
  * Copyright 1999 Ulrich Weigand
+ * Copyright 2005 Paul Vriens
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * TODO
- *   o Verify VerQueryValue()
  */
-#include "config.h"
-//#include "wine/port.h"
 
 #include <stdarg.h>
 #include <stdlib.h>
 
 #include "windef.h"
 #include "winbase.h"
-#include "wingdi.h"
-#include "winuser.h"
-#include "winnls.h"
+#include "winreg.h"
 #include "winver.h"
-#include "wine/debug.h"
+#include "winternl.h"
+#include "winuser.h"
 #include "wine/unicode.h"
-
-/*#ifdef __REACTOS__
-DWORD WINAPI GetFileResourceSize16( LPCSTR lpszFileName, LPCSTR lpszResType,
-                                    LPCSTR lpszResId, LPDWORD lpdwFileOffset );
-DWORD WINAPI GetFileResource16( LPCSTR lpszFileName, LPCSTR lpszResType,
-                                LPCSTR lpszResId, DWORD dwFileOffset,
-                                DWORD dwResLen, LPVOID lpvData )
-#endif*/
+#include "winerror.h"
+#include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ver);
 
-static
-void
-VERSION_A2W ( LPWSTR wide_str, LPCSTR ansi_str, int len )
-{
-       MultiByteToWideChar ( CP_ACP, 0, ansi_str, -1, wide_str, len );
-}
-
-static
-void
-VERSION_W2A ( LPSTR ansi_str, LPCWSTR wide_str, int len )
-{
-       WideCharToMultiByte ( CP_ACP, 0, wide_str, -1, ansi_str, len, NULL, NULL );
-}
-
-static
-LPWSTR
-VERSION_AllocA2W ( LPCSTR ansi_str )
-{
-       int len = MultiByteToWideChar ( CP_ACP, 0, ansi_str, -1, NULL, 0 );
-       LPWSTR wide_str = HeapAlloc ( GetProcessHeap(), 0, len * sizeof(WCHAR) );
-       if ( !wide_str )
-               return NULL;
-       VERSION_A2W ( wide_str, ansi_str, len );
-       return wide_str;
-}
-
-static
-LPSTR
-VERSION_AllocW2A ( LPCWSTR wide_str )
-{
-       int len = WideCharToMultiByte ( CP_ACP, 0, wide_str, -1, NULL, 0, NULL, NULL );
-       LPSTR ansi_str = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
-       if (!ansi_str)
-               return NULL;
-       VERSION_W2A ( ansi_str, wide_str, len );
-       return ansi_str;
-}
-
-static
-void
-VERSION_Free ( LPVOID lpvoid )
-{
-       HeapFree ( GetProcessHeap(), 0, lpvoid );
-}
-
-
 /******************************************************************************
  *
- *   This function will print via dprintf[_]ver to stddeb debug info regarding
+ *   This function will print via standard TRACE, debug info regarding
  *   the file info structure vffi.
  *      15-Feb-1998 Dimitrie Paun (dimi@cs.toronto.edu)
  *      Added this function to clean up the code.
  *
  *****************************************************************************/
-static
-void
-print_vffi_debug(VS_FIXEDFILEINFO *vffi)
+static void print_vffi_debug(VS_FIXEDFILEINFO *vffi)
 {
-       TRACE(" structversion=%u.%u, fileversion=%u.%u.%u.%u, productversion=%u.%u.%u.%u, flagmask=0x%lx, flags=%s%s%s%s%s%s\n",
-                   HIWORD(vffi->dwStrucVersion),LOWORD(vffi->dwStrucVersion),
-                   HIWORD(vffi->dwFileVersionMS),LOWORD(vffi->dwFileVersionMS),
-                   HIWORD(vffi->dwFileVersionLS),LOWORD(vffi->dwFileVersionLS),
-                   HIWORD(vffi->dwProductVersionMS),LOWORD(vffi->dwProductVersionMS),
-                   HIWORD(vffi->dwProductVersionLS),LOWORD(vffi->dwProductVersionLS),
-                   vffi->dwFileFlagsMask,
-                   (vffi->dwFileFlags & VS_FF_DEBUG) ? "DEBUG," : "",
-                   (vffi->dwFileFlags & VS_FF_PRERELEASE) ? "PRERELEASE," : "",
-                   (vffi->dwFileFlags & VS_FF_PATCHED) ? "PATCHED," : "",
-                   (vffi->dwFileFlags & VS_FF_PRIVATEBUILD) ? "PRIVATEBUILD," : "",
-                   (vffi->dwFileFlags & VS_FF_INFOINFERRED) ? "INFOINFERRED," : "",
-                   (vffi->dwFileFlags & VS_FF_SPECIALBUILD) ? "SPECIALBUILD," : ""
-                   );
-
-       TRACE("(");
-       TRACE(" OS=0x%x.0x%x ",
-               HIWORD(vffi->dwFileOS),
-               LOWORD(vffi->dwFileOS)
-       );
-       switch (vffi->dwFileOS&0xFFFF0000) {
-       case VOS_DOS:TRACE("DOS,");break;
-       case VOS_OS216:TRACE("OS/2-16,");break;
-       case VOS_OS232:TRACE("OS/2-32,");break;
-       case VOS_NT:TRACE("NT,");break;
-       case VOS_UNKNOWN:
-       default:
-               TRACE("UNKNOWN(0x%lx),",vffi->dwFileOS&0xFFFF0000);break;
-       }
-       switch (LOWORD(vffi->dwFileOS)) {
-       case VOS__BASE:TRACE("BASE");break;
-       case VOS__WINDOWS16:TRACE("WIN16");break;
-       case VOS__WINDOWS32:TRACE("WIN32");break;
-       case VOS__PM16:TRACE("PM16");break;
-       case VOS__PM32:TRACE("PM32");break;
-       default:TRACE("UNKNOWN(0x%x)",LOWORD(vffi->dwFileOS));break;
-       }
-       TRACE(")\n");
-
-       switch (vffi->dwFileType) {
-       default:
-       case VFT_UNKNOWN:
-               TRACE("filetype=Unknown(0x%lx)",vffi->dwFileType);
-               break;
-       case VFT_APP:TRACE("filetype=APP,");break;
-       case VFT_DLL:TRACE("filetype=DLL,");break;
-       case VFT_DRV:
-               TRACE("filetype=DRV,");
-               switch(vffi->dwFileSubtype) {
-               default:
-               case VFT2_UNKNOWN:
-                       TRACE("UNKNOWN(0x%lx)",vffi->dwFileSubtype);
-                       break;
-               case VFT2_DRV_PRINTER:
-                       TRACE("PRINTER");
-                       break;
-               case VFT2_DRV_KEYBOARD:
-                       TRACE("KEYBOARD");
-                       break;
-               case VFT2_DRV_LANGUAGE:
-                       TRACE("LANGUAGE");
-                       break;
-               case VFT2_DRV_DISPLAY:
-                       TRACE("DISPLAY");
-                       break;
-               case VFT2_DRV_MOUSE:
-                       TRACE("MOUSE");
-                       break;
-               case VFT2_DRV_NETWORK:
-                       TRACE("NETWORK");
-                       break;
-               case VFT2_DRV_SYSTEM:
-                       TRACE("SYSTEM");
-                       break;
-               case VFT2_DRV_INSTALLABLE:
-                       TRACE("INSTALLABLE");
-                       break;
-               case VFT2_DRV_SOUND:
-                       TRACE("SOUND");
-                       break;
-               case VFT2_DRV_COMM:
-                       TRACE("COMM");
-                       break;
-               case VFT2_DRV_INPUTMETHOD:
-                       TRACE("INPUTMETHOD");
-                       break;
-               }
-               break;
-       case VFT_FONT:
-               TRACE("filetype=FONT.");
-               switch (vffi->dwFileSubtype) {
-               default:
-                       TRACE("UNKNOWN(0x%lx)",vffi->dwFileSubtype);
-                       break;
-               case VFT2_FONT_RASTER:TRACE("RASTER");break;
-               case VFT2_FONT_VECTOR:TRACE("VECTOR");break;
-               case VFT2_FONT_TRUETYPE:TRACE("TRUETYPE");break;
-               }
-               break;
-       case VFT_VXD:TRACE("filetype=VXD");break;
-       case VFT_STATIC_LIB:TRACE("filetype=STATIC_LIB");break;
-       }
-       TRACE("\n");
-       TRACE("  filedata=0x%lx.0x%lx\n",
-                   vffi->dwFileDateMS,vffi->dwFileDateLS);
+    BOOL    versioned_printer = FALSE;
+
+    if((vffi->dwFileType == VFT_DLL) || (vffi->dwFileType == VFT_DRV))
+    {
+        if(vffi->dwFileSubtype == VFT2_DRV_VERSIONED_PRINTER)
+            /* this is documented for newer w2k Drivers and up */
+            versioned_printer = TRUE;
+        else if( (vffi->dwFileSubtype == VFT2_DRV_PRINTER) &&
+                 (vffi->dwFileVersionMS != vffi->dwProductVersionMS) &&
+                 (vffi->dwFileVersionMS > 0) &&
+                 (vffi->dwFileVersionMS <= 3) )
+            /* found this on NT 3.51, NT4.0 and old w2k Drivers */
+            versioned_printer = TRUE;
+    }
+
+    TRACE("structversion=%u.%u, ",
+            HIWORD(vffi->dwStrucVersion),LOWORD(vffi->dwStrucVersion));
+    if(versioned_printer)
+    {
+        WORD mode = LOWORD(vffi->dwFileVersionMS);
+        WORD ver_rev = HIWORD(vffi->dwFileVersionLS);
+        TRACE("fileversion=%lu.%u.%u.%u (%s.major.minor.release), ",
+            (vffi->dwFileVersionMS),
+            HIBYTE(ver_rev), LOBYTE(ver_rev), LOWORD(vffi->dwFileVersionLS),
+            (mode == 3) ? "Usermode" : ((mode <= 2) ? "Kernelmode" : "?") );
+    }
+    else
+    {
+        TRACE("fileversion=%u.%u.%u.%u, ",
+            HIWORD(vffi->dwFileVersionMS),LOWORD(vffi->dwFileVersionMS),
+            HIWORD(vffi->dwFileVersionLS),LOWORD(vffi->dwFileVersionLS));
+    }
+    TRACE("productversion=%u.%u.%u.%u\n",
+          HIWORD(vffi->dwProductVersionMS),LOWORD(vffi->dwProductVersionMS),
+          HIWORD(vffi->dwProductVersionLS),LOWORD(vffi->dwProductVersionLS));
+
+    TRACE("flagmask=0x%lx, flags=0x%lx %s%s%s%s%s%s\n",
+          vffi->dwFileFlagsMask, vffi->dwFileFlags,
+          (vffi->dwFileFlags & VS_FF_DEBUG) ? "DEBUG," : "",
+          (vffi->dwFileFlags & VS_FF_PRERELEASE) ? "PRERELEASE," : "",
+          (vffi->dwFileFlags & VS_FF_PATCHED) ? "PATCHED," : "",
+          (vffi->dwFileFlags & VS_FF_PRIVATEBUILD) ? "PRIVATEBUILD," : "",
+          (vffi->dwFileFlags & VS_FF_INFOINFERRED) ? "INFOINFERRED," : "",
+          (vffi->dwFileFlags & VS_FF_SPECIALBUILD) ? "SPECIALBUILD," : "");
+
+    TRACE("(");
+
+    TRACE("OS=0x%x.0x%x ", HIWORD(vffi->dwFileOS), LOWORD(vffi->dwFileOS));
+
+    switch (vffi->dwFileOS&0xFFFF0000)
+    {
+    case VOS_DOS:TRACE("DOS,");break;
+    case VOS_OS216:TRACE("OS/2-16,");break;
+    case VOS_OS232:TRACE("OS/2-32,");break;
+    case VOS_NT:TRACE("NT,");break;
+    case VOS_UNKNOWN:
+    default:
+        TRACE("UNKNOWN(0x%lx),",vffi->dwFileOS&0xFFFF0000);break;
+    }
+
+    switch (LOWORD(vffi->dwFileOS))
+    {
+    case VOS__BASE:TRACE("BASE");break;
+    case VOS__WINDOWS16:TRACE("WIN16");break;
+    case VOS__WINDOWS32:TRACE("WIN32");break;
+    case VOS__PM16:TRACE("PM16");break;
+    case VOS__PM32:TRACE("PM32");break;
+    default:
+        TRACE("UNKNOWN(0x%x)",LOWORD(vffi->dwFileOS));break;
+    }
+
+    TRACE(")\n");
+
+    switch (vffi->dwFileType)
+    {
+    case VFT_APP:TRACE("filetype=APP");break;
+    case VFT_DLL:
+        TRACE("filetype=DLL");
+        if(vffi->dwFileSubtype != 0)
+        {
+            if(versioned_printer) /* NT3.x/NT4.0 or old w2k Driver  */
+                TRACE(",PRINTER");
+            TRACE(" (subtype=0x%lx)", vffi->dwFileSubtype);
+        }
+        break;
+    case VFT_DRV:
+        TRACE("filetype=DRV,");
+        switch(vffi->dwFileSubtype)
+        {
+        case VFT2_DRV_PRINTER:TRACE("PRINTER");break;
+        case VFT2_DRV_KEYBOARD:TRACE("KEYBOARD");break;
+        case VFT2_DRV_LANGUAGE:TRACE("LANGUAGE");break;
+        case VFT2_DRV_DISPLAY:TRACE("DISPLAY");break;
+        case VFT2_DRV_MOUSE:TRACE("MOUSE");break;
+        case VFT2_DRV_NETWORK:TRACE("NETWORK");break;
+        case VFT2_DRV_SYSTEM:TRACE("SYSTEM");break;
+        case VFT2_DRV_INSTALLABLE:TRACE("INSTALLABLE");break;
+        case VFT2_DRV_SOUND:TRACE("SOUND");break;
+        case VFT2_DRV_COMM:TRACE("COMM");break;
+        case VFT2_DRV_INPUTMETHOD:TRACE("INPUTMETHOD");break;
+        case VFT2_DRV_VERSIONED_PRINTER:TRACE("VERSIONED_PRINTER");break;
+        case VFT2_UNKNOWN:
+        default:
+            TRACE("UNKNOWN(0x%lx)",vffi->dwFileSubtype);break;
+        }
+        break;
+    case VFT_FONT:
+        TRACE("filetype=FONT,");
+        switch (vffi->dwFileSubtype)
+        {
+        case VFT2_FONT_RASTER:TRACE("RASTER");break;
+        case VFT2_FONT_VECTOR:TRACE("VECTOR");break;
+        case VFT2_FONT_TRUETYPE:TRACE("TRUETYPE");break;
+        default:TRACE("UNKNOWN(0x%lx)",vffi->dwFileSubtype);break;
+        }
+        break;
+    case VFT_VXD:TRACE("filetype=VXD");break;
+    case VFT_STATIC_LIB:TRACE("filetype=STATIC_LIB");break;
+    case VFT_UNKNOWN:
+    default:
+        TRACE("filetype=Unknown(0x%lx)",vffi->dwFileType);break;
+    }
+
+    TRACE("\n");
+    TRACE("filedate=0x%lx.0x%lx\n",vffi->dwFileDateMS,vffi->dwFileDateLS);
 }
 
-
 /***********************************************************************
  * Version Info Structure
  */
@@ -222,7 +183,20 @@ typedef struct
 {
     WORD  wLength;
     WORD  wValueLength;
-    WORD  bText;
+    CHAR  szKey[1];
+#if 0   /* variable length structure */
+    /* DWORD aligned */
+    BYTE  Value[];
+    /* DWORD aligned */
+    VS_VERSION_INFO_STRUCT16 Children[];
+#endif
+} VS_VERSION_INFO_STRUCT16;
+
+typedef struct
+{
+    WORD  wLength;
+    WORD  wValueLength;
+    WORD  wType;
     WCHAR szKey[1];
 #if 0   /* variable length structure */
     /* DWORD aligned */
@@ -231,32 +205,28 @@ typedef struct
     VS_VERSION_INFO_STRUCT32 Children[];
 #endif
 } VS_VERSION_INFO_STRUCT32;
-/*
+
 #define VersionInfoIs16( ver ) \
     ( ((VS_VERSION_INFO_STRUCT16 *)ver)->szKey[0] >= ' ' )
-*/
+
 #define DWORD_ALIGN( base, ptr ) \
     ( (LPBYTE)(base) + ((((LPBYTE)(ptr) - (LPBYTE)(base)) + 3) & ~3) )
-/*
+
 #define VersionInfo16_Value( ver )  \
     DWORD_ALIGN( (ver), (ver)->szKey + strlen((ver)->szKey) + 1 )
-*/
 #define VersionInfo32_Value( ver )  \
     DWORD_ALIGN( (ver), (ver)->szKey + strlenW((ver)->szKey) + 1 )
-/*
+
 #define VersionInfo16_Children( ver )  \
     (VS_VERSION_INFO_STRUCT16 *)( VersionInfo16_Value( ver ) + \
                            ( ( (ver)->wValueLength + 3 ) & ~3 ) )
-*/
 #define VersionInfo32_Children( ver )  \
     (VS_VERSION_INFO_STRUCT32 *)( VersionInfo32_Value( ver ) + \
                            ( ( (ver)->wValueLength * \
-                               ((ver)->bText? 2 : 1) + 3 ) & ~3 ) )
+                               ((ver)->wType? 2 : 1) + 3 ) & ~3 ) )
 
-/*
 #define VersionInfo16_Next( ver ) \
     (VS_VERSION_INFO_STRUCT16 *)( (LPBYTE)ver + (((ver)->wLength + 3) & ~3) )
-*/
 #define VersionInfo32_Next( ver ) \
     (VS_VERSION_INFO_STRUCT32 *)( (LPBYTE)ver + (((ver)->wLength + 3) & ~3) )
 
@@ -264,280 +234,626 @@ typedef struct
  *           VERSION_GetFileVersionInfo_PE             [internal]
  *
  *    NOTE: returns size of the PE VERSION resource or 0xFFFFFFFF
- *    in the case if file exists, but VERSION_INFO not found.
- *    FIXME: handle is not used.
+ *    in the case the file is a PE module, but VERSION_INFO not found.
  */
-static
-DWORD
-VERSION_GetFileVersionInfo_PE (
-       LPCWSTR filename, LPDWORD handle,
-       DWORD datasize, LPVOID data )
+static DWORD VERSION_GetFileVersionInfo_PE( LPCWSTR filename, DWORD datasize, LPVOID data )
 {
-       VS_FIXEDFILEINFO *vffi;
-       DWORD len;
-       BYTE *buf;
-       HMODULE hModule;
-       HRSRC hRsrc;
-       HGLOBAL hMem;
-
-       TRACE("(%s,%p)\n", debugstr_w(filename), handle );
-
-       hModule = GetModuleHandleW(filename);
-       if(!hModule)
-               hModule = LoadLibraryExW(filename, 0, LOAD_LIBRARY_AS_DATAFILE);
+    VS_FIXEDFILEINFO *vffi;
+    DWORD len;
+    BYTE *buf;
+    HMODULE hModule;
+    HRSRC hRsrc;
+    HGLOBAL hMem;
+
+    TRACE("%s\n", debugstr_w(filename));
+
+    hModule = GetModuleHandleW(filename);
+    if(!hModule)
+       hModule = LoadLibraryExW(filename, 0, LOAD_LIBRARY_AS_DATAFILE);
+    else
+       hModule = LoadLibraryExW(filename, 0, 0);
+    if(!hModule)
+    {
+       WARN("Could not load %s\n", debugstr_w(filename));
+       return 0;
+    }
+    hRsrc = FindResourceW(hModule,
+                         MAKEINTRESOURCEW(VS_VERSION_INFO),
+                         MAKEINTRESOURCEW(VS_FILE_INFO));
+    if(!hRsrc)
+    {
+       WARN("Could not find VS_VERSION_INFO in %s\n", debugstr_w(filename));
+       FreeLibrary(hModule);
+       return 0xFFFFFFFF;
+    }
+    len = SizeofResource(hModule, hRsrc);
+    hMem = LoadResource(hModule, hRsrc);
+    if(!hMem)
+    {
+       WARN("Could not load VS_VERSION_INFO from %s\n", debugstr_w(filename));
+       FreeLibrary(hModule);
+       return 0xFFFFFFFF;
+    }
+    buf = LockResource(hMem);
+
+    vffi = (VS_FIXEDFILEINFO *)VersionInfo32_Value( (VS_VERSION_INFO_STRUCT32 *)buf );
+
+    if ( vffi->dwSignature != VS_FFI_SIGNATURE )
+    {
+        WARN("vffi->dwSignature is 0x%08lx, but not 0x%08lx!\n",
+                   vffi->dwSignature, VS_FFI_SIGNATURE );
+       len = 0xFFFFFFFF;
+       goto END;
+    }
+
+    if ( TRACE_ON(ver) )
+        print_vffi_debug( vffi );
+
+    if(data)
+    {
+       if(datasize < len)
+           len = datasize; /* truncate data */
+       if(len)
+           memcpy(data, buf, len);
        else
-               hModule = LoadLibraryExW(filename, 0, 0);
-       if ( !hModule )
-       {
-               WARN("Could not load %s\n", debugstr_w(filename));
-               return 0;
-       }
-       hRsrc = FindResourceW(hModule,
-                             MAKEINTRESOURCEW(VS_VERSION_INFO),
-                             MAKEINTRESOURCEW(VS_FILE_INFO));
-       if ( !hRsrc )
-       {
-               WARN("Could not find VS_VERSION_INFO in %s\n", debugstr_w(filename));
-               FreeLibrary(hModule);
-               return 0xFFFFFFFF;
-       }
-       len = SizeofResource(hModule, hRsrc);
-       hMem = LoadResource(hModule, hRsrc);
-       if(!hMem)
-       {
-               WARN("Could not load VS_VERSION_INFO from %s\n", debugstr_w(filename));
-               FreeLibrary(hModule);
-               return 0xFFFFFFFF;
-       }
-       buf = LockResource(hMem);
-
-       vffi = (VS_FIXEDFILEINFO *)VersionInfo32_Value( (VS_VERSION_INFO_STRUCT32 *)buf );
-
-       if ( vffi->dwSignature != VS_FFI_SIGNATURE )
-       {
-               WARN("vffi->dwSignature is 0x%08lx, but not 0x%08lx!\n",
-                    vffi->dwSignature, VS_FFI_SIGNATURE );
-               len = 0xFFFFFFFF;
-               goto END;
-       }
-
-       if ( TRACE_ON(ver) )
-               print_vffi_debug( vffi );
-
-       if(data)
-       {
-               if(datasize < len)
-                       len = datasize; /* truncate data */
-               if(len)
-                       memcpy(data, buf, len);
-               else
-                       len = 0xFFFFFFFF;
-       }
+           len = 0xFFFFFFFF;
+    }
 END:
-       FreeResource(hMem);
-       FreeLibrary(hModule);
+    FreeResource(hMem);
+    FreeLibrary(hModule);
 
-       return len;
+    return len;
 }
 
+#ifndef __REACTOS__
+/***********************************************************************
+ *           VERSION_GetFileVersionInfo_16             [internal]
+ *
+ *    NOTE: returns size of the 16-bit VERSION resource or 0xFFFFFFFF
+ *    in the case the file exists, but VERSION_INFO not found.
+ */
+static DWORD VERSION_GetFileVersionInfo_16( LPCSTR filename, DWORD datasize, LPVOID data )
+{
+    VS_FIXEDFILEINFO *vffi;
+    DWORD len, offset;
+    BYTE *buf;
+    HMODULE16 hModule;
+    HRSRC16 hRsrc;
+    HGLOBAL16 hMem;
+    char dllname[20], owner[20], *p;
+    const char *basename;
+    BOOL is_builtin = FALSE;
+
+    TRACE("%s\n", debugstr_a(filename));
+
+    /* strip path information */
+
+    basename = filename;
+    if (basename[0] && basename[1] == ':') basename += 2;  /* strip drive specification */
+    if ((p = strrchr( basename, '\\' ))) basename = p + 1;
+    if ((p = strrchr( basename, '/' ))) basename = p + 1;
+
+    if (strlen(basename) < sizeof(dllname)-4)
+    {
+        int file_exists;
+
+        strcpy( dllname, basename );
+        p = strrchr( dllname, '.' );
+        if (!p) strcat( dllname, ".dll" );
+        for (p = dllname; *p; p++) if (*p >= 'A' && *p <= 'Z') *p += 32;
+
+        if (wine_dll_get_owner( dllname, owner, sizeof(owner), &file_exists ) == 0)
+            is_builtin = TRUE;
+    }
+
+    /* first try without loading a 16-bit module */
+    if (is_builtin)
+        len = 0;
+    else
+        len = GetFileResourceSize16( filename,
+                                     MAKEINTRESOURCEA(VS_FILE_INFO),
+                                     MAKEINTRESOURCEA(VS_VERSION_INFO),
+                                     &offset );
+    if (len)
+    {
+        if (!data) return len;
+
+        len = GetFileResource16( filename,
+                                 MAKEINTRESOURCEA(VS_FILE_INFO),
+                                 MAKEINTRESOURCEA(VS_VERSION_INFO),
+                                 offset, datasize, data );
+        if (len)
+        {
+            vffi = (VS_FIXEDFILEINFO *)VersionInfo16_Value( (VS_VERSION_INFO_STRUCT16 *)data );
+
+            if ( vffi->dwSignature == VS_FFI_SIGNATURE )
+            {
+                if ( ((VS_VERSION_INFO_STRUCT16 *)data)->wLength < len )
+                    len = ((VS_VERSION_INFO_STRUCT16 *)data)->wLength;
+
+                if ( TRACE_ON(ver) )
+                    print_vffi_debug( vffi );
+
+                return len;
+            }
+        }
+    }
+
+    /* this might be a builtin 16-bit module */
+    hModule = LoadLibrary16(filename);
+    if(hModule < 32)
+    {
+       WARN("Could not load %s\n", debugstr_a(filename));
+       return 0;
+    }
+    hRsrc = FindResource16(hModule,
+                         MAKEINTRESOURCEA(VS_VERSION_INFO),
+                         MAKEINTRESOURCEA(VS_FILE_INFO));
+    if(!hRsrc)
+    {
+       WARN("Could not find VS_VERSION_INFO in %s\n", debugstr_a(filename));
+       FreeLibrary16(hModule);
+       return 0xFFFFFFFF;
+    }
+    len = SizeofResource16(hModule, hRsrc);
+    hMem = LoadResource16(hModule, hRsrc);
+    if(!hMem)
+    {
+       WARN("Could not load VS_VERSION_INFO from %s\n", debugstr_a(filename));
+       FreeLibrary16(hModule);
+       return 0xFFFFFFFF;
+    }
+    buf = LockResource16(hMem);
+
+    if(!VersionInfoIs16(buf))
+    {
+        len = 0xFFFFFFFF;
+       goto END;
+    }
+
+    vffi = (VS_FIXEDFILEINFO *)VersionInfo16_Value( (VS_VERSION_INFO_STRUCT16 *)buf );
+
+    if ( vffi->dwSignature != VS_FFI_SIGNATURE )
+    {
+        WARN("vffi->dwSignature is 0x%08lx, but not 0x%08lx!\n",
+                   vffi->dwSignature, VS_FFI_SIGNATURE );
+       len = 0xFFFFFFFF;
+       goto END;
+    }
+
+    if ( TRACE_ON(ver) )
+        print_vffi_debug( vffi );
+
+    if(data)
+    {
+       if(datasize < len)
+           len = datasize; /* truncate data */
+       if(len)
+           memcpy(data, buf, len);
+       else
+           len = 0xFFFFFFFF;
+    }
+END:
+    FreeResource16(hMem);
+    FreeLibrary16(hModule);
+
+    return len;
+}
+#endif /* ! __REACTOS__ */
+
 /***********************************************************************
  *           GetFileVersionInfoSizeW         [VERSION.@]
  */
-DWORD
-WINAPI
-GetFileVersionInfoSizeW ( LPCWSTR filename, LPDWORD handle )
+DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle )
 {
-       DWORD len;
+    DWORD len;
+
+    TRACE("(%s,%p)\n", debugstr_w(filename), handle );
+
+    if (handle) *handle = 0;
+
+    if (!filename)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+    if (!*filename)
+    {
+        SetLastError(ERROR_BAD_PATHNAME);
+        return 0;
+    }
+
+    len = VERSION_GetFileVersionInfo_PE(filename, 0, NULL);
+    /* 0xFFFFFFFF means: file is a PE module, but VERSION_INFO not found */
+    if(len == 0xFFFFFFFF)
+    {
+        SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
+        return 0;
+    }
+
+    if (!len)
+    {
+#ifdef __REACTOS__
+        SetLastError(ERROR_FILE_NOT_FOUND);
+        return 0;
+#else /* __REACTOS__ */
+        LPSTR filenameA;
+
+        len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL );
+        filenameA = HeapAlloc( GetProcessHeap(), 0, len );
+        WideCharToMultiByte( CP_ACP, 0, filename, -1, filenameA, len, NULL, NULL );
+
+        len = VERSION_GetFileVersionInfo_16(filenameA, 0, NULL);
+        HeapFree( GetProcessHeap(), 0, filenameA );
+        /* 0xFFFFFFFF means: file exists, but VERSION_INFO not found */
+        if (!len)
+        {
+            SetLastError(ERROR_FILE_NOT_FOUND);
+            return 0;
+        }
+        if (len == 0xFFFFFFFF)
+        {
+            SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
+            return 0;
+        }
+
+        /* We have a 16bit resource.
+         *
+         * XP/W2K/W2K3 uses a buffer which is more than the actual needed space:
+         *
+         * (info->wLength - sizeof(VS_FIXEDFILEINFO)) * 4
+         *
+         * This extra buffer is used for ANSI to Unicode conversions in W-Calls.
+         * info->wLength should be the same as len. Currently it isn't but that
+         * doesn't seem to be a problem (len is bigger then info->wLength).
+         */
+         len = (len - sizeof(VS_FIXEDFILEINFO)) * 4;
+#endif /* ! __REACTOS__ */
+    }
+    else
+    {
+        /* We have a 32bit resource.
+         *
+         * XP/W2K/W2K3 uses a buffer which is 2 times the actual needed space + 4 bytes "FE2X"
+         * This extra buffer is used for Unicode to ANSI conversions in A-Calls
+         */
+         len = (len * 2) + 4;
+    }
+
+    SetLastError(0);
+    return len;
+}
 
-       TRACE("(%s,%p)\n", debugstr_w(filename), handle );
-       if ( handle ) *handle = 0; //offset;
+/***********************************************************************
+ *           GetFileVersionInfoSizeA         [VERSION.@]
+ */
+DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle )
+{
+    UNICODE_STRING filenameW;
+    DWORD retval;
 
-       len = VERSION_GetFileVersionInfo_PE ( filename, handle, 0, NULL );
-       /* 0xFFFFFFFF means: file exists, but VERSION_INFO not found */
-       if ( len == 0xFFFFFFFF )
-       {
-               SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
-               return 0;
-       }
-       if ( len ) return (len<<1) + 4; // This matches MS's version.dll behavior, from what I can tell
+    TRACE("(%s,%p)\n", debugstr_a(filename), handle );
 
-       /* there used to be a bunch of 16-bit stuff here, but MS's docs say 16-bit not supported */
+    if(filename)
+        RtlCreateUnicodeStringFromAsciiz(&filenameW, filename);
+    else
+        filenameW.Buffer = NULL;
 
-       return 0;
+    retval = GetFileVersionInfoSizeW(filenameW.Buffer, handle);
+
+    RtlFreeUnicodeString(&filenameW);
+
+    return retval;
 }
 
 /***********************************************************************
- *           GetFileVersionInfoSizeA         [VERSION.@]
+ *           GetFileVersionInfoW             [VERSION.@]
  */
-DWORD
-WINAPI
-GetFileVersionInfoSizeA ( LPCSTR filename, LPDWORD handle )
+BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle,
+                                    DWORD datasize, LPVOID data )
 {
-       LPWSTR filenameW = VERSION_AllocA2W(filename);
-       DWORD ret = GetFileVersionInfoSizeW ( filenameW, handle );
-       VERSION_Free ( filenameW );
-       return ret;
+    DWORD len;
+    VS_VERSION_INFO_STRUCT32* vvis = (VS_VERSION_INFO_STRUCT32*)data;
+
+    TRACE("(%s,%ld,size=%ld,data=%p)\n",
+                debugstr_w(filename), handle, datasize, data );
+
+    if (!data)
+    {
+        SetLastError(ERROR_INVALID_DATA);
+        return FALSE;
+    }
+    len = VERSION_GetFileVersionInfo_PE(filename, datasize, data);
+    /* 0xFFFFFFFF means: file is a PE module, but VERSION_INFO not found */
+    if (len == 0xFFFFFFFF)
+    {
+        SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
+        return FALSE;
+    }
+
+    if (!len)
+    {
+#ifdef __REACTOS__
+        SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
+        return FALSE;
+#else /* __REACTOS__ */
+        LPSTR filenameA;
+
+        len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL );
+        filenameA = HeapAlloc( GetProcessHeap(), 0, len );
+        WideCharToMultiByte( CP_ACP, 0, filename, -1, filenameA, len, NULL, NULL );
+
+        len = VERSION_GetFileVersionInfo_16(filenameA, datasize, data);
+        HeapFree( GetProcessHeap(), 0, filenameA );
+        /* 0xFFFFFFFF means: file exists, but VERSION_INFO not found */
+        if (!len || len == 0xFFFFFFFF)
+        {
+            SetLastError(ERROR_RESOURCE_DATA_NOT_FOUND);
+            return FALSE;
+        }
+        /* We have a 16bit resource. */
+#endif /* ! __REACTOS__ */
+    }
+    else 
+    {
+        static const char signature[] = "FE2X";
+        DWORD bufsize = vvis->wLength + strlen(signature);
+        DWORD convbuf;
+        /* We have a 32bit resource.
+         *
+         * XP/W2K/W2K3 uses a buffer which is 2 times the actual needed space + 4 bytes "FE2X"
+         * This extra buffer is used for Unicode to ANSI conversions in A-Calls
+         */
+
+        /* information is truncated to datasize bytes */
+        if (datasize >= bufsize)
+        {
+            convbuf = datasize - vvis->wLength;
+            memcpy( ((char*)(data))+vvis->wLength, signature, convbuf > 4 ? 4 : convbuf );
+        }
+    }
+
+    SetLastError(0);
+    return TRUE;
 }
 
 /***********************************************************************
- *           GetFileVersionInfoW             [VERSION.@]
+ *           GetFileVersionInfoA             [VERSION.@]
  */
-BOOL
-WINAPI
-GetFileVersionInfoW (
-       LPCWSTR filename, DWORD handle,
-       DWORD datasize, LPVOID data )
+BOOL WINAPI GetFileVersionInfoA( LPCSTR filename, DWORD handle,
+                                    DWORD datasize, LPVOID data )
 {
-       DWORD len, extradata;
-       VS_VERSION_INFO_STRUCT32* vvis = (VS_VERSION_INFO_STRUCT32*)data;
+    UNICODE_STRING filenameW;
+    BOOL retval;
 
-       TRACE("(%s,%ld,size=%ld,data=%p)\n",
-               debugstr_w(filename), handle, datasize, data );
+    TRACE("(%s,%ld,size=%ld,data=%p)\n",
+                debugstr_a(filename), handle, datasize, data );
 
-       len = VERSION_GetFileVersionInfo_PE(filename, &handle, datasize, data);
+    if(filename)
+        RtlCreateUnicodeStringFromAsciiz(&filenameW, filename);
+    else
+        filenameW.Buffer = NULL;
 
-       if ( len == 0xFFFFFFFF )
-               return FALSE;
+    retval = GetFileVersionInfoW(filenameW.Buffer, handle, datasize, data);
 
-       extradata = datasize - vvis->wLength;
-       memmove ( ((char*)(data))+vvis->wLength, "FE2X", extradata > 4 ? 4 : extradata );
+    RtlFreeUnicodeString(&filenameW);
 
-       return TRUE;
+    return retval;
 }
 
 /***********************************************************************
- *           GetFileVersionInfoA             [VERSION.@]
+ *           VersionInfo16_FindChild             [internal]
  */
-BOOL
-WINAPI
-GetFileVersionInfoA (
-       LPCSTR filename, DWORD handle,
-       DWORD datasize, LPVOID data )
+static VS_VERSION_INFO_STRUCT16 *VersionInfo16_FindChild( VS_VERSION_INFO_STRUCT16 *info,
+                                            LPCSTR szKey, UINT cbKey )
 {
-       LPWSTR filenameW = VERSION_AllocA2W ( filename );
-       BOOL ret = GetFileVersionInfoW ( filenameW, handle, datasize, data );
-       VERSION_Free ( filenameW );
-       return ret;
+    VS_VERSION_INFO_STRUCT16 *child = VersionInfo16_Children( info );
+
+    while ((char *)child < (char *)info + info->wLength )
+    {
+        if ( !strncasecmp( child->szKey, szKey, cbKey ) )
+            return child;
+
+       if (!(child->wLength)) return NULL;
+        child = VersionInfo16_Next( child );
+    }
+
+    return NULL;
 }
 
 /***********************************************************************
  *           VersionInfo32_FindChild             [internal]
  */
-static
-VS_VERSION_INFO_STRUCT32*
-VersionInfo32_FindChild (
-       VS_VERSION_INFO_STRUCT32 *info,
-       LPCWSTR szKey, UINT cbKey )
+static VS_VERSION_INFO_STRUCT32 *VersionInfo32_FindChild( VS_VERSION_INFO_STRUCT32 *info,
+                                            LPCWSTR szKey, UINT cbKey )
 {
-       VS_VERSION_INFO_STRUCT32 *child = VersionInfo32_Children( info );
+    VS_VERSION_INFO_STRUCT32 *child = VersionInfo32_Children( info );
 
-       while ( (DWORD)child < (DWORD)info + info->wLength )
-       {
-               if ( !strncmpiW( child->szKey, szKey, cbKey ) )
-                       return child;
+    while ((char *)child < (char *)info + info->wLength )
+    {
+        if ( !strncmpiW( child->szKey, szKey, cbKey ) )
+            return child;
 
-               child = VersionInfo32_Next( child );
-       }
+        child = VersionInfo32_Next( child );
+    }
 
-       return NULL;
+    return NULL;
 }
 
-static
-VS_VERSION_INFO_STRUCT32*
-VERSION_VerQueryValue ( VS_VERSION_INFO_STRUCT32* info, LPCWSTR lpSubBlock )
+/***********************************************************************
+ *           VersionInfo16_QueryValue              [internal]
+ *
+ *    Gets a value from a 16-bit NE resource
+ */
+static BOOL WINAPI VersionInfo16_QueryValue( VS_VERSION_INFO_STRUCT16 *info, LPCSTR lpSubBlock,
+                               LPVOID *lplpBuffer, UINT *puLen )
 {
-       while ( *lpSubBlock )
-       {
-               /* Find next path component */
-               LPCWSTR lpNextSlash;
-               for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
-               {
-                       if ( *lpNextSlash == '\\' )
-                               break;
-               }
-
-               /* Skip empty components */
-               if ( lpNextSlash == lpSubBlock )
-               {
-                       lpSubBlock++;
-                       continue;
-               }
-
-               /* We have a non-empty component: search info for key */
-               info = VersionInfo32_FindChild ( info, lpSubBlock, lpNextSlash-lpSubBlock );
-               if ( !info ) return NULL;
-
-               /* Skip path component */
-               lpSubBlock = lpNextSlash;
-       }
-       return info;
+    while ( *lpSubBlock )
+    {
+        /* Find next path component */
+        LPCSTR lpNextSlash;
+        for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
+            if ( *lpNextSlash == '\\' )
+                break;
+
+        /* Skip empty components */
+        if ( lpNextSlash == lpSubBlock )
+        {
+            lpSubBlock++;
+            continue;
+        }
+
+        /* We have a non-empty component: search info for key */
+        info = VersionInfo16_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
+        if ( !info ) return FALSE;
+
+        /* Skip path component */
+        lpSubBlock = lpNextSlash;
+    }
+
+    /* Return value */
+    *lplpBuffer = VersionInfo16_Value( info );
+    if (puLen)
+        *puLen = info->wValueLength;
+
+    return TRUE;
 }
 
 /***********************************************************************
- *           VerQueryValueW              [VERSION.@]
+ *           VersionInfo32_QueryValue              [internal]
+ *
+ *    Gets a value from a 32-bit PE resource
+ */
+static BOOL WINAPI VersionInfo32_QueryValue( VS_VERSION_INFO_STRUCT32 *info, LPCWSTR lpSubBlock,
+                               LPVOID *lplpBuffer, UINT *puLen )
+{
+    TRACE("lpSubBlock : (%s)\n", debugstr_w(lpSubBlock));
+
+    while ( *lpSubBlock )
+    {
+        /* Find next path component */
+        LPCWSTR lpNextSlash;
+        for ( lpNextSlash = lpSubBlock; *lpNextSlash; lpNextSlash++ )
+            if ( *lpNextSlash == '\\' )
+                break;
+
+        /* Skip empty components */
+        if ( lpNextSlash == lpSubBlock )
+        {
+            lpSubBlock++;
+            continue;
+        }
+
+        /* We have a non-empty component: search info for key */
+        info = VersionInfo32_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
+        if ( !info ) return FALSE;
+
+        /* Skip path component */
+        lpSubBlock = lpNextSlash;
+    }
+
+    /* Return value */
+    *lplpBuffer = VersionInfo32_Value( info );
+    if (puLen)
+        *puLen = info->wValueLength;
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *           VerQueryValueA              [VERSION.@]
  */
-BOOL
-WINAPI
-VerQueryValueW (
-       const LPVOID pBlock,
-       LPWSTR lpSubBlock,
-       LPVOID *lplpBuffer,
-       UINT *puLen )
+BOOL WINAPI VerQueryValueA( LPVOID pBlock, LPSTR lpSubBlock,
+                               LPVOID *lplpBuffer, UINT *puLen )
 {
-       VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
+    static const char rootA[] = "\\";
+    static const char varfileinfoA[] = "\\VarFileInfo\\Translation";
+    VS_VERSION_INFO_STRUCT16 *info = (VS_VERSION_INFO_STRUCT16 *)pBlock;
+
+    TRACE("(%p,%s,%p,%p)\n",
+                pBlock, debugstr_a(lpSubBlock), lplpBuffer, puLen );
 
-       TRACE("(%p,%s,%p,%p)\n",
-               pBlock, debugstr_w(lpSubBlock), lplpBuffer, puLen );
+    if ( !VersionInfoIs16( info ) )
+    {
+        BOOL ret;
+        INT len;
+        LPWSTR lpSubBlockW;
 
-       info = VERSION_VerQueryValue ( info, lpSubBlock );
-       if ( !info )
-       {
-               // FIXME: what should SetLastError be set to???
-               return FALSE;
-       }
+        len  = MultiByteToWideChar(CP_ACP, 0, lpSubBlock, -1, NULL, 0);
+        lpSubBlockW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 
-       *lplpBuffer = VersionInfo32_Value ( info );
-       *puLen = info->wValueLength;
+        if (!lpSubBlockW)
+            return FALSE;
 
-       return TRUE;
+        MultiByteToWideChar(CP_ACP, 0, lpSubBlock, -1, lpSubBlockW, len);
+
+        ret = VersionInfo32_QueryValue(pBlock, lpSubBlockW, lplpBuffer, puLen);
+
+        HeapFree(GetProcessHeap(), 0, lpSubBlockW);
+
+        if (ret && strcasecmp( lpSubBlock, rootA ) && strcasecmp( lpSubBlock, varfileinfoA ))
+        {
+            LPSTR lpBufferA = (LPSTR)pBlock + info->wLength + 4;
+            DWORD pos = (LPSTR)*lplpBuffer - (LPSTR)pBlock;
+
+            len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)*lplpBuffer, -1,
+                                      lpBufferA + pos, info->wLength - pos, NULL, NULL);
+            *lplpBuffer = lpBufferA + pos;
+            *puLen = len;
+        }
+        return ret;
+    }
+
+    return VersionInfo16_QueryValue(info, lpSubBlock, lplpBuffer, puLen);
 }
 
 /***********************************************************************
- *           VerQueryValueA              [VERSION.@]
+ *           VerQueryValueW              [VERSION.@]
  */
-BOOL
-WINAPI
-VerQueryValueA (
-       LPVOID pBlock,
-       LPSTR lpSubBlockA,
-       LPVOID *lplpBuffer,
-       UINT *puLen )
+BOOL WINAPI VerQueryValueW( LPVOID pBlock, LPWSTR lpSubBlock,
+                               LPVOID *lplpBuffer, UINT *puLen )
 {
-       VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
-       LPWSTR lpSubBlockW = VERSION_AllocA2W ( lpSubBlockA );
+    static const WCHAR rootW[] = { '\\', 0 };
+    static const WCHAR varfileinfoW[] = { '\\','V','a','r','F','i','l','e','I','n','f','o',
+                                          '\\','T','r','a','n','s','l','a','t','i','o','n', 0 };
+
+    VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
+
+    TRACE("(%p,%s,%p,%p)\n",
+                pBlock, debugstr_w(lpSubBlock), lplpBuffer, puLen );
+
+    if ( VersionInfoIs16( info ) )
+    {
+        BOOL ret;
+        int len;
+        LPSTR lpSubBlockA;
+
+        len = WideCharToMultiByte(CP_ACP, 0, lpSubBlock, -1, NULL, 0, NULL, NULL);
+        lpSubBlockA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
 
-       TRACE("(%p,%s,%p,%p)\n",
-               pBlock, debugstr_a(lpSubBlockA), lplpBuffer, puLen );
+        if (!lpSubBlockA)
+            return FALSE;
 
-       info = VERSION_VerQueryValue ( info, lpSubBlockW );
+        WideCharToMultiByte(CP_ACP, 0, lpSubBlock, -1, lpSubBlockA, len, NULL, NULL);
 
-       VERSION_Free ( lpSubBlockW );
+        ret = VersionInfo16_QueryValue(pBlock, lpSubBlockA, lplpBuffer, puLen);
 
-       if ( !info )
-       {
-               // FIXME: what should SetLastError be set to???
-               return FALSE;
-       }
+        HeapFree(GetProcessHeap(), 0, lpSubBlockA);
 
-       *lplpBuffer = VersionInfo32_Value ( info );
-       *puLen = info->wValueLength;
+        if (ret && strcmpiW( lpSubBlock, rootW ) && strcmpiW( lpSubBlock, varfileinfoW ))
+        {
+            LPWSTR lpBufferW = (LPWSTR)((LPSTR)pBlock + info->wLength);
+            DWORD pos = (LPSTR)*lplpBuffer - (LPSTR)pBlock;
+            DWORD max = (info->wLength - sizeof(VS_FIXEDFILEINFO)) * 4 - info->wLength;
 
-       if ( info->bText )
-       {
-               LPSTR str = VERSION_AllocW2A ( *lplpBuffer );
-               memmove ( *lplpBuffer, str, info->wValueLength + 1 );
-               VERSION_Free ( str );
-       }
+            len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*lplpBuffer, -1,
+                                      lpBufferW + pos, max/sizeof(WCHAR) - pos );
+            *lplpBuffer = lpBufferW + pos;
+            *puLen = len;
+        }
+        return ret;
+    }
 
-       return TRUE;
+    return VersionInfo32_QueryValue(info, lpSubBlock, lplpBuffer, puLen);
 }