version: Add a VerQueryValue test, make it mostly pass under Wine

Dmitry Timoshkov dmitry at codeweavers.com
Mon Apr 16 02:09:32 CDT 2007


Hello,

as reported in the bug 7834 current behaviour of VerQueryValue in Wine is wrong.
Main problem is that it currently returns success for partially matching string
values.

Changelog:
    version: Add a VerQueryValue test, make it mostly pass under Wine.

---
 dlls/version/info.c           |   36 ++++++++++-
 dlls/version/tests/info.c     |  136 ++++++++++++++++++++++++++++++++++++++---
 dlls/version/tests/version.rc |   47 +++++++++++---
 3 files changed, 197 insertions(+), 22 deletions(-)

diff --git a/dlls/version/info.c b/dlls/version/info.c
index 5d4314f..bb3b2f6 100644
--- a/dlls/version/info.c
+++ b/dlls/version/info.c
@@ -636,17 +636,26 @@ BOOL WINAPI GetFileVersionInfoA( LPCSTR filename, DWORD handle,
 static VS_VERSION_INFO_STRUCT16 *VersionInfo16_FindChild( VS_VERSION_INFO_STRUCT16 *info,
                                             LPCSTR szKey, UINT cbKey )
 {
+    char *key;
     VS_VERSION_INFO_STRUCT16 *child = VersionInfo16_Children( info );
 
+    key = HeapAlloc( GetProcessHeap(), 0, cbKey + 1 );
+    memcpy( key, szKey, cbKey );
+    key[cbKey] = 0;
+
     while ((char *)child < (char *)info + info->wLength )
     {
-        if ( !strncasecmp( child->szKey, szKey, cbKey ) )
+        if ( !lstrcmpiA( child->szKey, key ) )
+        {
+            HeapFree( GetProcessHeap(), 0, key );
             return child;
+        }
 
 	if (!(child->wLength)) return NULL;
         child = VersionInfo16_Next( child );
     }
 
+    HeapFree( GetProcessHeap(), 0, key );
     return NULL;
 }
 
@@ -656,16 +665,25 @@ static VS_VERSION_INFO_STRUCT16 *VersionInfo16_FindChild( VS_VERSION_INFO_STRUCT
 static VS_VERSION_INFO_STRUCT32 *VersionInfo32_FindChild( VS_VERSION_INFO_STRUCT32 *info,
                                             LPCWSTR szKey, UINT cbKey )
 {
+    WCHAR *key;
     VS_VERSION_INFO_STRUCT32 *child = VersionInfo32_Children( info );
 
+    key = HeapAlloc( GetProcessHeap(), 0, (cbKey + 1) * sizeof(WCHAR) );
+    memcpy( key, szKey, cbKey * sizeof(WCHAR) );
+    key[cbKey] = 0;
+
     while ((char *)child < (char *)info + info->wLength )
     {
-        if ( !strncmpiW( child->szKey, szKey, cbKey ) )
+        if ( !lstrcmpiW( child->szKey, key ) )
+        {
+            HeapFree( GetProcessHeap(), 0, key );
             return child;
+        }
 
         child = VersionInfo32_Next( child );
     }
 
+    HeapFree( GetProcessHeap(), 0, key );
     return NULL;
 }
 
@@ -694,7 +712,12 @@ static BOOL WINAPI VersionInfo16_QueryValue( VS_VERSION_INFO_STRUCT16 *info, LPC
 
         /* We have a non-empty component: search info for key */
         info = VersionInfo16_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
-        if ( !info ) return FALSE;
+        if ( !info )
+        {
+            if (puLen) *puLen = 0 ;
+            SetLastError( ERROR_RESOURCE_TYPE_NOT_FOUND );
+            return FALSE;
+        }
 
         /* Skip path component */
         lpSubBlock = lpNextSlash;
@@ -735,7 +758,12 @@ static BOOL WINAPI VersionInfo32_QueryValue( VS_VERSION_INFO_STRUCT32 *info, LPC
 
         /* We have a non-empty component: search info for key */
         info = VersionInfo32_FindChild( info, lpSubBlock, lpNextSlash-lpSubBlock );
-        if ( !info ) return FALSE;
+        if ( !info )
+        {
+            if (puLen) *puLen = 0 ;
+            SetLastError( ERROR_RESOURCE_TYPE_NOT_FOUND );
+            return FALSE;
+        }
 
         /* Skip path component */
         lpSubBlock = lpNextSlash;
diff --git a/dlls/version/tests/info.c b/dlls/version/tests/info.c
index 82bce5b..19079ef 100644
--- a/dlls/version/tests/info.c
+++ b/dlls/version/tests/info.c
@@ -18,12 +18,13 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include <assert.h>
 
-#include "wine/test.h"
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"
 #include "winver.h"
+#include "wine/test.h"
 
 #define MY_LAST_ERROR ((DWORD)-1)
 #define EXPECT_BAD_PATH__NOT_FOUND \
@@ -263,8 +264,8 @@ static void test_32bit_win(void)
     WCHAR FileDescriptionW[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
                                 '\\','0','4','0','9','0','4','E','4',
                                 '\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
-    char WineFileDescriptionA[] = "Wine version test";
-    WCHAR WineFileDescriptionW[] = { 'W','i','n','e',' ','v','e','r','s','i','o','n',' ','t','e','s','t', 0 };
+    char WineFileDescriptionA[] = "FileDescription";
+    WCHAR WineFileDescriptionW[] = { 'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
     BOOL is_unicode_enabled = TRUE;
 
     /* A copy from dlls/version/info.c */
@@ -289,6 +290,7 @@ static void test_32bit_win(void)
      */
 
     /* First get the versioninfo via the W versions */
+    SetLastError(0xdeadbeef);
     GetModuleFileNameW(NULL, mypathW, MAX_PATH);
     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
     {
@@ -388,18 +390,20 @@ static void test_32bit_win(void)
 
     retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
     ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
-    ok( !lstrcmpA(WineFileDescriptionA, pBufA), "FileDescription should have been 'Wine version test'\n");
+    ok( !lstrcmpA(WineFileDescriptionA, pBufA), "expected '%s' got '%s'\n",
+        WineFileDescriptionA, pBufA);
 
     /* Test a second time */
     retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
     ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
-    ok( !lstrcmpA(WineFileDescriptionA, pBufA), "FileDescription should have been 'Wine version test'\n");
+    ok( !lstrcmpA(WineFileDescriptionA, pBufA), "expected '%s' got '%s'\n",
+        WineFileDescriptionA, pBufA);
 
     if (is_unicode_enabled)
     { 
         retW = VerQueryValueW( pVersionInfoW, FileDescriptionW, (LPVOID *)&pBufW, &uiLengthW );
         ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
-        ok( !lstrcmpW(WineFileDescriptionW, pBufW), "FileDescription should have been 'Wine version test' (unicode)\n");
+        ok( !lstrcmpW(WineFileDescriptionW, pBufW), "FileDescription should have been '%s'\n", WineFileDescriptionA);
     }
 
     HeapFree( GetProcessHeap(), 0, pVersionInfoA);
@@ -407,12 +411,126 @@ static void test_32bit_win(void)
         HeapFree( GetProcessHeap(), 0, pVersionInfoW);
 }
 
+static void test_VerQueryValue(void)
+{
+    static const char * const value_name[] = {
+        "Product", "CompanyName", "FileDescription", "Internal",
+        "ProductVersion", "InternalName", "File", "LegalCopyright",
+        "FileVersion", "Legal", "OriginalFilename", "ProductName",
+        "Company", "Original" };
+    char *ver, *p;
+    UINT len, ret, translation, i;
+    char buf[MAX_PATH];
+
+    ret = GetModuleFileName(NULL, buf, sizeof(buf));
+    assert(ret);
+
+    SetLastError(0xdeadbeef);
+    len = GetFileVersionInfoSize(buf, NULL);
+    ok(len, "GetFileVersionInfoSize(%s) error %u\n", buf, GetLastError());
+
+    ver = HeapAlloc(GetProcessHeap(), 0, len);
+    assert(ver);
+
+    SetLastError(0xdeadbeef);
+    ret = GetFileVersionInfo(buf, 0, len, ver);
+    ok(ret, "GetFileVersionInfo error %u\n", GetLastError());
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValue(ver, "\\VarFileInfo\\Translation", (LPVOID*)&p, &len);
+    ok(ret, "VerQueryValue error %u\n", GetLastError());
+    ok(len == 4, "VerQueryValue returned %u, expected 4\n", len);
+
+    translation = *(UINT *)p;
+    translation = MAKELONG(HIWORD(translation), LOWORD(translation));
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValue(ver, "String", (LPVOID*)&p, &len);
+    ok(!ret, "VerQueryValue should fail\n");
+    ok(GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND,
+       "VerQueryValue returned %u\n", GetLastError());
+    ok(p == (char *)0xdeadbeef, "expected 0xdeadbeef got %p\n", p);
+    ok(len == 0, "expected 0 got %x\n", len);
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValue(ver, "StringFileInfo", (LPVOID*)&p, &len);
+    ok(ret, "VerQueryValue error %u\n", GetLastError());
+todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
+    ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValue(ver, "\\StringFileInfo", (LPVOID*)&p, &len);
+    ok(ret, "VerQueryValue error %u\n", GetLastError());
+todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
+    ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValue(ver, "\\\\StringFileInfo", (LPVOID*)&p, &len);
+    ok(ret, "VerQueryValue error %u\n", GetLastError());
+todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
+    ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValue(ver, "\\StringFileInfo\\\\", (LPVOID*)&p, &len);
+    ok(ret, "VerQueryValue error %u\n", GetLastError());
+todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
+    ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
+
+    sprintf(buf, "\\StringFileInfo\\%08x", translation);
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValue(ver, buf, (LPVOID*)&p, &len);
+    ok(ret, "VerQueryValue error %u\n", GetLastError());
+todo_wine ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
+    ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
+
+    for (i = 0; i < sizeof(value_name)/sizeof(value_name[0]); i++)
+    {
+	sprintf(buf, "\\StringFileInfo\\%08x\\%s", translation, value_name[i]);
+        p = (char *)0xdeadbeef;
+        len = 0xdeadbeef;
+        SetLastError(0xdeadbeef);
+        ret = VerQueryValue(ver, buf, (LPVOID*)&p, &len);
+        ok(ret, "VerQueryValue(%s) error %u\n", buf, GetLastError());
+        ok(len == strlen(value_name[i]) + 1, "VerQueryValue returned %u, expected %u\n",
+           len, strlen(value_name[i]) + 1);
+        ok(!strcmp(value_name[i], p), "expected \"%s\", got \"%s\"\n",
+           value_name[i], p);
+
+        /* test partial value names */
+        len = lstrlen(buf);
+        buf[len - 2] = 0;
+        p = (char *)0xdeadbeef;
+        len = 0xdeadbeef;
+        SetLastError(0xdeadbeef);
+        ret = VerQueryValue(ver, buf, (LPVOID*)&p, &len);
+        ok(!ret, "VerQueryValue(%s) succeeded\n", buf);
+        ok(GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND,
+           "VerQueryValue returned %u\n", GetLastError());
+        ok(p == (char *)0xdeadbeef, "expected 0xdeadbeef got %p\n", p);
+        ok(len == 0, "expected 0 got %x\n", len);
+    }
+
+    HeapFree(GetProcessHeap(), 0, ver);
+}
+
 START_TEST(info)
 {
     test_info_size();
     test_info();
-   
-    /* Test several AW-calls on a 32 bit windows executable */
-    trace("Testing 32 bit windows application\n");
     test_32bit_win();
+    test_VerQueryValue();
 }
diff --git a/dlls/version/tests/version.rc b/dlls/version/tests/version.rc
index 5feade8..c754e0c 100644
--- a/dlls/version/tests/version.rc
+++ b/dlls/version/tests/version.rc
@@ -16,13 +16,42 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#define WINE_FILEDESCRIPTION_STR "Wine version test"
-#define WINE_FILENAME_STR "version_test.exe"
-#define WINE_FILETYPE VFT_APP
-#define WINE_FILEVERSION 1,0,0,0
-#define WINE_FILEVERSION_STR "1.0.0.0"
-#define WINE_PRODUCTVERSION 1,0,0,0
-#define WINE_PRODUCTVERSION_STR "1.0.0.0"
-#define WINE_PRODUCTNAME_STR "Wine version test"
+#include "windef.h"
+#include "winbase.h"
+#include "winver.h"
 
-#include "wine/wine_common_ver.rc"
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION    1,0,0,0
+PRODUCTVERSION 1,0,0,0
+FILEFLAGSMASK  63
+FILEFLAGS      0
+FILEOS         VOS_UNKNOWN
+FILETYPE       VFT_APP
+FILESUBTYPE    VFT2_UNKNOWN
+{
+    BLOCK "StringFileInfo"
+    {
+        BLOCK "040904E4" /* LANG_ENGLISH/SUBLANG_DEFAULT, CP1252 */
+        {
+            /* list of strings that partially match in arbitrary order */
+            VALUE "Product", "Product"
+            VALUE "CompanyName", "CompanyName"
+            VALUE "FileDescription", "FileDescription"
+            VALUE "Internal", "Internal"
+            VALUE "ProductVersion", "ProductVersion"
+            VALUE "InternalName", "InternalName"
+            VALUE "File", "File"
+            VALUE "LegalCopyright", "LegalCopyright"
+            VALUE "FileVersion", "FileVersion"
+            VALUE "Legal", "Legal"
+            VALUE "OriginalFilename", "OriginalFilename"
+            VALUE "ProductName", "ProductName"
+            VALUE "Company", "Company"
+            VALUE "Original", "Original"
+        }
+    }
+    BLOCK "VarFileInfo"
+    {
+        VALUE "Translation", 0x0409,1252 /* LANG_ENGLISH/SUBLANG_DEFAULT, CP1252 */
+    }
+}
-- 
1.5.1.1






More information about the wine-patches mailing list