version.dll patch

Steven Edwards steven_ed4153 at yahoo.com
Fri Mar 19 17:18:20 CST 2004


Hello,
We found quite a few problems using version.dll on ReactOS and Windows
XP. According to Royce there was a issue regarding ANSI converion that
was causing applications (Winzip) to fail to load. Also we found that
Microsoft doesnt support reading of the Win16 resources from the Win32
APIs. Moving the Win16 stuff is all my fault.

Changelog:
Rewrite of Version.dll to properly function under Windows - Royce
Mitchell III (Royce at ev1.net)
MS_VC Porting Fixes (Steven Edwards)
Win16/32 Split of version.dll (Steven Edwards)


__________________________________
Do you Yahoo!?
Yahoo! Mail - More reliable, more storage, less spam
http://mail.yahoo.com
-------------- next part --------------
Index: include/winver.h
===================================================================
RCS file: /home/wine/wine/include/winver.h,v
retrieving revision 1.16
diff -u -r1.16 winver.h
--- include/winver.h	5 Sep 2003 23:15:44 -0000	1.16
+++ include/winver.h	19 Mar 2004 23:00:11 -0000
@@ -158,14 +158,14 @@
 DWORD       WINAPI VerLanguageNameA(UINT,LPSTR,UINT);
 DWORD       WINAPI VerLanguageNameW(UINT,LPWSTR,UINT);
 #define     VerLanguageName WINELIB_NAME_AW(VerLanguageName)
-DWORD       WINAPI VerQueryValueA(LPVOID,LPCSTR,LPVOID*,UINT*);
-DWORD       WINAPI VerQueryValueW(LPVOID,LPCWSTR,LPVOID*,UINT*);
+BOOL       WINAPI VerQueryValueA(const LPVOID,LPSTR,LPVOID*,PUINT);
+BOOL       WINAPI VerQueryValueW(const LPVOID,LPWSTR,LPVOID*,PUINT);
 #define     VerQueryValue WINELIB_NAME_AW(VerQueryValue)
-DWORD       WINAPI GetFileVersionInfoSizeA(LPCSTR,LPDWORD);
-DWORD       WINAPI GetFileVersionInfoSizeW(LPCWSTR,LPDWORD);
+DWORD       WINAPI GetFileVersionInfoSizeA(LPSTR,LPDWORD);
+DWORD       WINAPI GetFileVersionInfoSizeW(LPWSTR,LPDWORD);
 #define     GetFileVersionInfoSize WINELIB_NAME_AW(GetFileVersionInfoSize)
-BOOL        WINAPI GetFileVersionInfoA(LPCSTR,DWORD,DWORD,LPVOID);
-BOOL        WINAPI GetFileVersionInfoW(LPCWSTR,DWORD,DWORD,LPVOID);
+BOOL        WINAPI GetFileVersionInfoA(LPSTR,DWORD,DWORD,LPVOID);
+BOOL        WINAPI GetFileVersionInfoW(LPWSTR,DWORD,DWORD,LPVOID);
 #define     GetFileVersionInfo WINELIB_NAME_AW(GetFileVersionInfo)
 
 /* 20 GETFILEVERSIONINFORAW */

Index: dlls/version/info.c
===================================================================
RCS file: /home/wine/wine/dlls/version/info.c,v
retrieving revision 1.41
diff -u -r1.41 info.c
--- dlls/version/info.c	28 Jan 2004 20:06:14 -0000	1.41
+++ dlls/version/info.c	19 Mar 2004 23:07:29 -0000
@@ -4,6 +4,7 @@
  * Copyright 1996,1997 Marcus Meissner
  * Copyright 1997 David Cuthbert
  * Copyright 1999 Ulrich Weigand
+ * Copyright 2004 Royce Mitchell III (ReactOS Project)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,8 @@
  * TODO
  *   o Verify VerQueryValue()
  */
+#include "config.h"
+#include "wine/port.h"
 
 #include <stdarg.h>
 #include <stdlib.h>
@@ -29,15 +32,60 @@
 
 #include "windef.h"
 #include "winbase.h"
-#include "winreg.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
 #include "winver.h"
-#include "wine/winuser16.h"
-#include "wine/unicode.h"
-#include "winerror.h"
 #include "wine/debug.h"
+#include "wine/unicode.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 );
+}
+
 
 /******************************************************************************
  *
@@ -47,7 +95,8 @@
  *      Added this function to clean up the code.
  *
  *****************************************************************************/
-static void print_vffi_debug(VS_FIXEDFILEINFO *vffi)
+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),
@@ -64,7 +113,7 @@
 		    (vffi->dwFileFlags & VS_FF_SPECIALBUILD) ? "SPECIALBUILD," : ""
 		    );
 
-        TRACE("(");
+	TRACE("(");
 	TRACE(" OS=0x%x.0x%x ",
 		HIWORD(vffi->dwFileOS),
 		LOWORD(vffi->dwFileOS)
@@ -138,7 +187,7 @@
 		}
 		break;
 	case VFT_FONT:
-                TRACE("filetype=FONT.");
+		TRACE("filetype=FONT.");
 		switch (vffi->dwFileSubtype) {
 		default:
 			TRACE("UNKNOWN(0x%lx)",vffi->dwFileSubtype);
@@ -151,7 +200,7 @@
 	case VFT_VXD:TRACE("filetype=VXD");break;
 	case VFT_STATIC_LIB:TRACE("filetype=STATIC_LIB");break;
 	}
-        TRACE("\n");
+	TRACE("\n");
 	TRACE("  filedata=0x%lx.0x%lx\n",
 		    vffi->dwFileDateMS,vffi->dwFileDateLS);
 }
@@ -165,19 +214,6 @@
 {
     WORD  wLength;
     WORD  wValueLength;
-    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  bText;
     WCHAR szKey[1];
 #if 0   /* variable length structure */
@@ -188,562 +224,299 @@
 #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 ) )
 
-#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) )
 
 /***********************************************************************
- *           ConvertVersionInfo32To16        [internal]
- */
-void ConvertVersionInfo32To16( VS_VERSION_INFO_STRUCT32 *info32,
-                               VS_VERSION_INFO_STRUCT16 *info16 )
-{
-    /* Copy data onto local stack to prevent overwrites */
-    WORD wLength = info32->wLength;
-    WORD wValueLength = info32->wValueLength;
-    WORD bText = info32->bText;
-    LPBYTE lpValue = VersionInfo32_Value( info32 );
-    VS_VERSION_INFO_STRUCT32 *child32 = VersionInfo32_Children( info32 );
-    VS_VERSION_INFO_STRUCT16 *child16;
-
-    TRACE("Converting %p to %p\n", info32, info16 );
-    TRACE("wLength %d, wValueLength %d, bText %d, value %p, child %p\n",
-                wLength, wValueLength, bText, lpValue, child32 );
-
-    /* Convert key */
-    WideCharToMultiByte( CP_ACP, 0, info32->szKey, -1, info16->szKey, 0x7fffffff, NULL, NULL );
-
-    TRACE("Copied key from %p to %p: %s\n", info32->szKey, info16->szKey,
-                debugstr_a(info16->szKey) );
-
-    /* Convert value */
-    if ( wValueLength == 0 )
-    {
-        info16->wValueLength = 0;
-        TRACE("No value present\n" );
-    }
-    else if ( bText )
-    {
-        info16->wValueLength = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)lpValue, -1, NULL, 0, NULL, NULL );
-        WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)lpValue, -1,
-                             VersionInfo16_Value( info16 ), info16->wValueLength, NULL, NULL );
-
-        TRACE("Copied value from %p to %p: %s\n", lpValue,
-                    VersionInfo16_Value( info16 ),
-                    debugstr_a(VersionInfo16_Value( info16 )) );
-    }
-    else
-    {
-        info16->wValueLength = wValueLength;
-        memmove( VersionInfo16_Value( info16 ), lpValue, wValueLength );
-
-        TRACE("Copied value from %p to %p: %d bytes\n", lpValue,
-                     VersionInfo16_Value( info16 ), wValueLength );
-    }
-
-    /* Convert children */
-    child16 = VersionInfo16_Children( info16 );
-    while ( (DWORD)child32 < (DWORD)info32 + wLength && child32->wLength != 0 )
-    {
-        VS_VERSION_INFO_STRUCT32 *nextChild = VersionInfo32_Next( child32 );
-
-        ConvertVersionInfo32To16( child32, child16 );
-
-        child16 = VersionInfo16_Next( child16 );
-        child32 = nextChild;
-    }
-
-    /* Fixup length */
-    info16->wLength = (DWORD)child16 - (DWORD)info16;
-
-    TRACE("Finished, length is %d (%p - %p)\n",
-                info16->wLength, info16, child16 );
-}
-
-/***********************************************************************
  *           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.
  */
-static DWORD VERSION_GetFileVersionInfo_PE( LPCSTR filename, LPDWORD handle,
-                                    DWORD datasize, LPVOID data )
-{
-    VS_FIXEDFILEINFO *vffi;
-    DWORD len;
-    BYTE *buf;
-    HMODULE hModule;
-    HRSRC hRsrc;
-    HGLOBAL hMem;
-
-    TRACE("(%s,%p)\n", debugstr_a(filename), handle );
-
-    hModule = GetModuleHandleA(filename);
-    if(!hModule)
-	hModule = LoadLibraryExA(filename, 0, LOAD_LIBRARY_AS_DATAFILE);
-    else
-	hModule = LoadLibraryExA(filename, 0, 0);
-    if(!hModule)
-    {
-	WARN("Could not load %s\n", debugstr_a(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_a(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_a(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);
+static
+DWORD
+VERSION_GetFileVersionInfo_PE (
+	LPCWSTR filename, LPDWORD handle,
+	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);
 	else
-	    len = 0xFFFFFFFF;
-    }
-END:
-    FreeResource(hMem);
-    FreeLibrary(hModule);
+		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);
 
-    return len;
-}
+	vffi = (VS_FIXEDFILEINFO *)VersionInfo32_Value( (VS_VERSION_INFO_STRUCT32 *)buf );
 
-/***********************************************************************
- *           VERSION_GetFileVersionInfo_16             [internal]
- *
- *    NOTE: returns size of the 16-bit VERSION resource or 0xFFFFFFFF
- *    in the case if file exists, but VERSION_INFO not found.
- *    FIXME: handle is not used.
- */
-static DWORD VERSION_GetFileVersionInfo_16( LPCSTR filename, LPDWORD handle,
-                                    DWORD datasize, LPVOID data )
-{
-    VS_FIXEDFILEINFO *vffi;
-    DWORD len;
-    BYTE *buf;
-    HMODULE16 hModule;
-    HRSRC16 hRsrc;
-    HGLOBAL16 hMem;
-
-    TRACE("(%s,%p)\n", debugstr_a(filename), handle );
-
-    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))
-	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;
-    }
+	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);
+	FreeResource(hMem);
+	FreeLibrary(hModule);
 
-    return len;
+	return len;
 }
 
 /***********************************************************************
- *           GetFileVersionInfoSizeA         [VERSION.@]
+ *           GetFileVersionInfoSizeW         [VERSION.@]
  */
-DWORD WINAPI GetFileVersionInfoSizeA( LPCSTR filename, LPDWORD handle )
-{
-    VS_FIXEDFILEINFO *vffi;
-    DWORD len, ret, offset;
-    BYTE buf[144];
-
-    TRACE("(%s,%p)\n", debugstr_a(filename), handle );
-
-    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;
-    len = VERSION_GetFileVersionInfo_16(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;
-
-    len = GetFileResourceSize16( filename,
-                                 MAKEINTRESOURCEA(VS_FILE_INFO),
-                                 MAKEINTRESOURCEA(VS_VERSION_INFO),
-                                 &offset );
-    if (!len) return 0;
-
-    ret = GetFileResource16( filename,
-                             MAKEINTRESOURCEA(VS_FILE_INFO),
-                             MAKEINTRESOURCEA(VS_VERSION_INFO),
-                             offset, sizeof( buf ), buf );
-    if (!ret) return 0;
-
-    if ( handle ) *handle = offset;
-
-    if ( VersionInfoIs16( buf ) )
-        vffi = (VS_FIXEDFILEINFO *)VersionInfo16_Value( (VS_VERSION_INFO_STRUCT16 *)buf );
-    else
-        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 );
-        return 0;
-    }
-
-    if ( ((VS_VERSION_INFO_STRUCT16 *)buf)->wLength < len )
-        len = ((VS_VERSION_INFO_STRUCT16 *)buf)->wLength;
+DWORD
+WINAPI
+GetFileVersionInfoSizeW ( LPWSTR filename, LPDWORD handle )
+{
+	DWORD len;
+
+	TRACE("(%s,%p)\n", debugstr_w(filename), handle );
+	if ( handle ) *handle = 0; /* offset; */
+
+	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 */
 
-    if ( TRACE_ON(ver) )
-        print_vffi_debug( vffi );
+	/* there used to be a bunch of 16-bit stuff here, but MS's docs say 16-bit not supported */
 
-    return len;
+	return 0;
 }
 
 /***********************************************************************
- *           GetFileVersionInfoSizeW         [VERSION.@]
+ *           GetFileVersionInfoSizeA         [VERSION.@]
  */
-DWORD WINAPI GetFileVersionInfoSizeW( LPCWSTR filename, LPDWORD handle )
-{
-    DWORD ret, len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL );
-    LPSTR fn = HeapAlloc( GetProcessHeap(), 0, len );
-    WideCharToMultiByte( CP_ACP, 0, filename, -1, fn, len, NULL, NULL );
-    ret = GetFileVersionInfoSizeA( fn, handle );
-    HeapFree( GetProcessHeap(), 0, fn );
-    return ret;
+DWORD
+WINAPI
+GetFileVersionInfoSizeA ( LPSTR filename, LPDWORD handle )
+{
+	LPWSTR filenameW = VERSION_AllocA2W(filename);
+	DWORD ret = GetFileVersionInfoSizeW ( filenameW, handle );
+	VERSION_Free ( filenameW );
+	return ret;
 }
 
 /***********************************************************************
- *           GetFileVersionInfoA             [VERSION.@]
+ *           GetFileVersionInfoW             [VERSION.@]
  */
-BOOL WINAPI GetFileVersionInfoA( LPCSTR filename, DWORD handle,
-                                    DWORD datasize, LPVOID data )
+BOOL
+WINAPI
+GetFileVersionInfoW (
+	LPWSTR filename, DWORD handle,
+	DWORD datasize, LPVOID data )
 {
-    DWORD len;
+	DWORD len, extradata;
+	VS_VERSION_INFO_STRUCT32* vvis = (VS_VERSION_INFO_STRUCT32*)data;
 
-    TRACE("(%s,%ld,size=%ld,data=%p)\n",
-                debugstr_a(filename), handle, datasize, data );
+	TRACE("(%s,%ld,size=%ld,data=%p)\n",
+		debugstr_w(filename), handle, datasize, data );
 
-    len = VERSION_GetFileVersionInfo_PE(filename, &handle, datasize, data);
-    /* 0xFFFFFFFF means: file exists, but VERSION_INFO not found */
-    if(len == 0xFFFFFFFF) return FALSE;
-    if(len)
-	goto DO_CONVERT;
-    len = VERSION_GetFileVersionInfo_16(filename, &handle, datasize, data);
-    /* 0xFFFFFFFF means: file exists, but VERSION_INFO not found */
-    if(len == 0xFFFFFFFF) return FALSE;
-    if(len)
-	goto DO_CONVERT;
-
-    if ( !GetFileResource16( filename, MAKEINTRESOURCEA(VS_FILE_INFO),
-                                       MAKEINTRESOURCEA(VS_VERSION_INFO),
-                                       handle, datasize, data ) )
-        return FALSE;
-DO_CONVERT:
-    if (    datasize >= sizeof(VS_VERSION_INFO_STRUCT16)
-         && datasize >= ((VS_VERSION_INFO_STRUCT16 *)data)->wLength
-         && !VersionInfoIs16( data ) )
-    {
-        /* convert resource from PE format to NE format */
-        ConvertVersionInfo32To16( (VS_VERSION_INFO_STRUCT32 *)data,
-                                  (VS_VERSION_INFO_STRUCT16 *)data );
-    }
+	len = VERSION_GetFileVersionInfo_PE(filename, &handle, datasize, data);
 
-    return TRUE;
-}
+	if ( len == 0xFFFFFFFF )
+		return FALSE;
 
-/***********************************************************************
- *           GetFileVersionInfoW             [VERSION.@]
- */
-BOOL WINAPI GetFileVersionInfoW( LPCWSTR filename, DWORD handle,
-                                    DWORD datasize, LPVOID data )
-{
-    DWORD len = WideCharToMultiByte( CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL );
-    LPSTR fn = HeapAlloc( GetProcessHeap(), 0, len );
-    DWORD retv = TRUE;
-
-    WideCharToMultiByte( CP_ACP, 0, filename, -1, fn, len, NULL, NULL );
-
-    TRACE("(%s,%ld,size=%ld,data=%p)\n",
-                debugstr_w(filename), handle, datasize, data );
-
-    if(VERSION_GetFileVersionInfo_PE(fn, &handle, datasize, data))
-	goto END;
-    if(VERSION_GetFileVersionInfo_16(fn, &handle, datasize, data))
-	goto END;
-
-    if ( !GetFileResource16( fn, MAKEINTRESOURCEA(VS_FILE_INFO),
-                                 MAKEINTRESOURCEA(VS_VERSION_INFO),
-                                 handle, datasize, data ) )
-        retv = FALSE;
-
-    else if (    datasize >= sizeof(VS_VERSION_INFO_STRUCT16)
-              && datasize >= ((VS_VERSION_INFO_STRUCT16 *)data)->wLength
-              && VersionInfoIs16( data ) )
-    {
-        ERR("Cannot access NE resource in %s\n", debugstr_a(fn) );
-        retv =  FALSE;
-    }
-END:
-    HeapFree( GetProcessHeap(), 0, fn );
-    return retv;
-}
+	extradata = datasize - vvis->wLength;
+	memmove ( ((char*)(data))+vvis->wLength, "FE2X", extradata > 4 ? 4 : extradata );
 
+	return TRUE;
+}
 
 /***********************************************************************
- *           VersionInfo16_FindChild             [internal]
+ *           GetFileVersionInfoA             [VERSION.@]
  */
-static VS_VERSION_INFO_STRUCT16 *VersionInfo16_FindChild( VS_VERSION_INFO_STRUCT16 *info,
-                                            LPCSTR szKey, UINT cbKey )
-{
-    VS_VERSION_INFO_STRUCT16 *child = VersionInfo16_Children( info );
-
-    while ( (DWORD)child < (DWORD)info + info->wLength )
-    {
-        if ( !strncasecmp( child->szKey, szKey, cbKey ) )
-            return child;
-
-	if (!(child->wLength)) return NULL;
-        child = VersionInfo16_Next( child );
-    }
-
-    return NULL;
+BOOL
+WINAPI
+GetFileVersionInfoA (
+	LPSTR filename, DWORD handle,
+	DWORD datasize, LPVOID data )
+{
+	LPWSTR filenameW = VERSION_AllocA2W ( filename );
+	BOOL ret = GetFileVersionInfoW ( filenameW, handle, datasize, data );
+	VERSION_Free ( filenameW );
+	return ret;
 }
 
 /***********************************************************************
  *           VersionInfo32_FindChild             [internal]
  */
-static VS_VERSION_INFO_STRUCT32 *VersionInfo32_FindChild( VS_VERSION_INFO_STRUCT32 *info,
-                                            LPCWSTR szKey, UINT cbKey )
-{
-    VS_VERSION_INFO_STRUCT32 *child = VersionInfo32_Children( info );
+static
+VS_VERSION_INFO_STRUCT32*
+VersionInfo32_FindChild (
+	VS_VERSION_INFO_STRUCT32 *info,
+	LPCWSTR szKey, UINT cbKey )
+{
+	VS_VERSION_INFO_STRUCT32 *child = VersionInfo32_Children( info );
+
+	while ( (DWORD)child < (DWORD)info + info->wLength )
+	{
+		if ( !strncmpiW( child->szKey, szKey, cbKey ) )
+			return child;
 
-    while ( (DWORD)child < (DWORD)info + info->wLength )
-    {
-        if ( !strncmpiW( child->szKey, szKey, cbKey ) )
-            return child;
-
-        child = VersionInfo32_Next( child );
-    }
+		child = VersionInfo32_Next( child );
+	}
 
-    return NULL;
+	return NULL;
 }
 
-/***********************************************************************
- *           VersionInfo16_QueryValue              [internal]
- *
- *    Gets a value from a 16-bit NE resource
- */
-DWORD WINAPI VersionInfo16_QueryValue( VS_VERSION_INFO_STRUCT16 *info, LPCSTR lpSubBlock,
-                               LPVOID *lplpBuffer, UINT *puLen )
-{
-    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 );
-    *puLen = info->wValueLength;
+static
+VS_VERSION_INFO_STRUCT32*
+VERSION_VerQueryValue ( VS_VERSION_INFO_STRUCT32* info, LPCWSTR 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;
+		}
 
-    return TRUE;
+		/* 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;
 }
 
 /***********************************************************************
- *           VerQueryValueA              [VERSION.@]
+ *           VerQueryValueW              [VERSION.@]
  */
-DWORD WINAPI VerQueryValueA( LPVOID pBlock, LPCSTR lpSubBlock,
-                               LPVOID *lplpBuffer, UINT *puLen )
-{
-    VS_VERSION_INFO_STRUCT16 *info = (VS_VERSION_INFO_STRUCT16 *)pBlock;
-
-    TRACE("(%p,%s,%p,%p)\n",
-                pBlock, debugstr_a(lpSubBlock), lplpBuffer, puLen );
+BOOL
+WINAPI
+VerQueryValueW (
+	const LPVOID pBlock,
+	LPWSTR lpSubBlock,
+	LPVOID * lplpBuffer,
+	PUINT puLen )
+{
+	VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
+
+	TRACE("(%p,%s,%p,%p)\n",
+		pBlock, debugstr_w(lpSubBlock), lplpBuffer, puLen );
+
+	info = VERSION_VerQueryValue ( info, lpSubBlock );
+	if ( !info )
+	{
+		/* FIXME: what should SetLastError be set to??? */
+		return FALSE;
+	}
 
-    if ( !VersionInfoIs16( info ) )
-    {
-        INT len;
-        LPWSTR wide_str;
-        DWORD give;
-
-        /* <lawson_whitney at juno.com> Feb 2001 */
-        /* AOL 5.0 does this, expecting to get this: */
-        len = MultiByteToWideChar(CP_ACP, 0, lpSubBlock, -1, NULL, 0);
-        wide_str = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
-        MultiByteToWideChar(CP_ACP, 0, lpSubBlock, -1, wide_str, len);
-
-        give = VerQueryValueW(pBlock, wide_str, lplpBuffer, puLen);
-        HeapFree(GetProcessHeap(), 0, wide_str);
-        return give;
-    }
+	*lplpBuffer = VersionInfo32_Value ( info );
+	*puLen = info->wValueLength;
 
-    return VersionInfo16_QueryValue(info, lpSubBlock, lplpBuffer, puLen);
+	return TRUE;
 }
 
 /***********************************************************************
- *           VerQueryValueW              [VERSION.@]
+ *           VerQueryValueA              [VERSION.@]
  */
-DWORD WINAPI VerQueryValueW( LPVOID pBlock, LPCWSTR lpSubBlock,
-                               LPVOID *lplpBuffer, UINT *puLen )
-{
-    VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
+BOOL
+WINAPI
+VerQueryValueA(
+        const LPVOID pBlock,
+        LPSTR lpSubBlockA,
+        LPVOID * lplpBuffer,
+        PUINT puLen
+        )
+{
+	VS_VERSION_INFO_STRUCT32 *info = (VS_VERSION_INFO_STRUCT32 *)pBlock;
+	LPWSTR lpSubBlockW = VERSION_AllocA2W ( lpSubBlockA );
+
+	TRACE("(%p,%s,%p,%p)\n",
+		pBlock, debugstr_a(lpSubBlockA), lplpBuffer, puLen );
+
+	info = VERSION_VerQueryValue ( info, lpSubBlockW );
+
+	VERSION_Free ( lpSubBlockW );
+
+	if ( !info )
+	{
+		/* FIXME: what should SetLastError be set to??? */
+		return FALSE;
+	}
 
-    TRACE("(%p,%s,%p,%p)\n",
-                pBlock, debugstr_w(lpSubBlock), lplpBuffer, puLen );
+	*lplpBuffer = VersionInfo32_Value ( info );
+	*puLen = info->wValueLength;
 
-    if ( VersionInfoIs16( info ) )
-    {
-        DWORD ret;
-        int len = WideCharToMultiByte(CP_ACP, 0, lpSubBlock, -1, NULL, 0, NULL, NULL);
-        LPSTR lpSubBlockA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(char));
-        if (!lpSubBlockA)
-            return FALSE;
-        WideCharToMultiByte(CP_ACP, 0, lpSubBlock, -1, lpSubBlockA, len, NULL, NULL);
-        ret = VersionInfo16_QueryValue(pBlock, lpSubBlockA, lplpBuffer, puLen);
-        HeapFree(GetProcessHeap(), 0, lpSubBlockA);
-        return ret;
-    }
-
-    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 );
-    *puLen = info->wValueLength;
+	if ( info->bText )
+	{
+		LPSTR str = VERSION_AllocW2A ( *lplpBuffer );
+		memmove ( *lplpBuffer, str, info->wValueLength + 1 );
+		VERSION_Free ( str );
+	}
 
-    return TRUE;
+	return TRUE;
 }
Index: dlls/version/ver16.c
===================================================================
RCS file: /home/wine/wine/dlls/version/ver16.c,v
retrieving revision 1.9
diff -u -r1.9 ver16.c
--- dlls/version/ver16.c	5 Sep 2003 23:08:29 -0000	1.9
+++ dlls/version/ver16.c	19 Mar 2004 23:07:29 -0000
@@ -1,6 +1,8 @@
 /*
- * Implementation of VER.DLL
+ * Implementation of VERSION.DLL - Version Info access
  *
+ * Copyright 1996,1997 Marcus Meissner
+ * Copyright 1997 David Cuthbert
  * Copyright 1999 Ulrich Weigand
  *
  * This library is free software; you can redistribute it and/or
@@ -16,18 +18,211 @@
  * You should have received a copy 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 <string.h>
 
 #include "windef.h"
 #include "winbase.h"
-#include "wine/winbase16.h"
+#include "winreg.h"
 #include "winver.h"
+#include "wine/winuser16.h"
+#include "wine/unicode.h"
+#include "winerror.h"
 #include "wine/debug.h"
 
+void print_vffi_debug(VS_FIXEDFILEINFO *vffi);
+
 WINE_DEFAULT_DEBUG_CHANNEL(ver);
 
+/***********************************************************************
+ * Version Info Structure
+ */
+
+typedef struct
+{
+    WORD  wLength;
+    WORD  wValueLength;
+    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  bText;
+    WCHAR szKey[1];
+#if 0   /* variable length structure */
+    /* DWORD aligned */
+    BYTE  Value[];
+    /* DWORD aligned */
+    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 VersionInfo16_Children( ver )  \
+    (VS_VERSION_INFO_STRUCT16 *)( VersionInfo16_Value( ver ) + \
+                           ( ( (ver)->wValueLength + 3 ) & ~3 ) )
+
+#define VersionInfo16_Next( ver ) \
+    (VS_VERSION_INFO_STRUCT16 *)( (LPBYTE)ver + (((ver)->wLength + 3) & ~3) )
+
+/***********************************************************************
+ *           VERSION_GetFileVersionInfo_16             [internal]
+ *
+ *    NOTE: returns size of the 16-bit VERSION resource or 0xFFFFFFFF
+ *    in the case if file exists, but VERSION_INFO not found.
+ *    FIXME: handle is not used.
+ */
+static DWORD VERSION_GetFileVersionInfo_16( LPCSTR filename, LPDWORD handle,
+                                    DWORD datasize, LPVOID data )
+{
+    VS_FIXEDFILEINFO *vffi;
+    DWORD len;
+    BYTE *buf;
+    HMODULE16 hModule;
+    HRSRC16 hRsrc;
+    HGLOBAL16 hMem;
+
+    TRACE("(%s,%p)\n", debugstr_a(filename), handle );
+
+    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))
+	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;
+}
+
+/***********************************************************************
+ *           VersionInfo16_FindChild             [internal]
+ */
+static VS_VERSION_INFO_STRUCT16 *VersionInfo16_FindChild( VS_VERSION_INFO_STRUCT16 *info,
+                                            LPCSTR szKey, UINT cbKey )
+{
+    VS_VERSION_INFO_STRUCT16 *child = VersionInfo16_Children( info );
+
+    while ( (DWORD)child < (DWORD)info + info->wLength )
+    {
+        if ( !strncasecmp( child->szKey, szKey, cbKey ) )
+            return child;
+
+	if (!(child->wLength)) return NULL;
+        child = VersionInfo16_Next( child );
+    }
+
+    return NULL;
+}
+
+/***********************************************************************
+ *           VersionInfo16_QueryValue              [internal]
+ *
+ *    Gets a value from a 16-bit NE resource
+ */
+DWORD WINAPI VersionInfo16_QueryValue( VS_VERSION_INFO_STRUCT16 *info, LPCSTR lpSubBlock,
+                               LPVOID *lplpBuffer, UINT *puLen )
+{
+    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 );
+    *puLen = info->wValueLength;
+
+    return TRUE;
+}
 
 /*************************************************************************
  * GetFileVersionInfoSize                  [VER.6]
@@ -35,7 +230,7 @@
 DWORD WINAPI GetFileVersionInfoSize16( LPCSTR lpszFileName, LPDWORD lpdwHandle )
 {
     TRACE("(%s, %p)\n", debugstr_a(lpszFileName), lpdwHandle );
-    return GetFileVersionInfoSizeA( lpszFileName, lpdwHandle );
+	return VERSION_GetFileVersionInfo_16(lpszFileName, lpdwHandle, 0, NULL);
 }
 
 /*************************************************************************
@@ -47,7 +242,7 @@
     TRACE("(%s, %08lx, %ld, %p)\n",
                 debugstr_a(lpszFileName), handle, cbBuf, lpvData );
 
-    return GetFileVersionInfoA( lpszFileName, handle, cbBuf, lpvData );
+    return VERSION_GetFileVersionInfo_16( lpszFileName, handle, cbBuf, lpvData );
 }
 
 /*************************************************************************
@@ -106,7 +301,7 @@
     TRACE("(%p, %s, %p, %p)\n",
                 lpvBlock, debugstr_a(lpszSubBlock), lpspBuffer, lpcb );
 
-    retv = VerQueryValueA( lpvBlock, lpszSubBlock, &buffer, &buflen );
+	retv = VersionInfo16_QueryValue( lpvBlock, lpszSubBlock, &buffer, &buflen );
     if ( !retv ) return FALSE;
 
     if ( OFFSETOF( spvBlock ) + ((char *) buffer - (char *) lpvBlock) >= 0x10000 )



More information about the wine-patches mailing list