From df1414dcc9a03f581a7c524eda84824192f72ca3 Mon Sep 17 00:00:00 2001
From: Mark Jansen <learn0more+wine@gmail.com>
Date: Fri, 27 Feb 2015 21:24:58 +0100
Subject: version: Test for VerQueryValueA (try 2)

This patch supersedes both '[2/2] version: Test for VerQueryValueA'
and '[1/2] version: Fix wrong length reported when selecting a block.
(resend 2)', as it is a better tests, and proves the fix to not work
fully.

The patch shows a difference in handling between wine's VerQueryValue,
and windows' VerQueryValue when selecting a 'BLOCK' object.

Implemented pointer checking and commented the binary structure as
suggested by nsivov from #winehackers.
---
 dlls/version/tests/info.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 124 insertions(+)

diff --git a/dlls/version/tests/info.c b/dlls/version/tests/info.c
index b99a335d81a..6f16999b086 100644
--- a/dlls/version/tests/info.c
+++ b/dlls/version/tests/info.c
@@ -578,6 +578,129 @@ static void test_VerQueryValueA(void)
     HeapFree(GetProcessHeap(), 0, ver);
 }
 
+static void test_VerQueryValue_InvalidLength(void)
+{
+    /* this buffer is created with the reactos resource compiler from this resource:
+#include "winver.h"
+
+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"
+    {
+    }
+}
+*/
+    char preparedbuffer[] = {
+        /* VS_VERSION_INFO_STRUCT32 */
+        0x80, 0x00,     /* wLength */
+        0x34, 0x00,     /* wValueLength */
+        0x00, 0x00,     /* wType */
+        /* L"VS_VERSION_INFO" + DWORD alignment */
+        0x56, 0x00, 0x53, 0x00, 0x5f, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4f,
+        0x00, 0x4e, 0x00, 0x5f, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+        /* VS_FIXEDFILEINFO */
+        0xbd, 0x04, 0xef, 0xfe,     /* dwSignature */
+        0x00, 0x00, 0x01, 0x00,     /* dwStrucVersion */
+        0x00, 0x00, 0x01, 0x00,     /* dwFileVersionMS */
+        0x00, 0x00, 0x00, 0x00,     /* dwFileVersionLS */
+        0x00, 0x00, 0x01, 0x00,     /* dwProductVersionMS */
+        0x00, 0x00, 0x00, 0x00,     /* dwProductVersionLS */
+        0x3f, 0x00, 0x00, 0x00,     /* dwFileFlagsMask */
+        0x00, 0x00, 0x00, 0x00,     /* dwFileFlags */
+        0x00, 0x00, 0x00, 0x00,     /* dwFileOS */
+        0x01, 0x00, 0x00, 0x00,     /* dwFileType */
+        0x00, 0x00, 0x00, 0x00,     /* dwFileSubtype */
+        0x00, 0x00, 0x00, 0x00,     /* dwFileDateMS */
+        0x00, 0x00, 0x00, 0x00,     /* dwFileDateLS */
+
+        /* first child: */
+            0x24, 0x00,     /* wLength */
+            0x00, 0x00,     /* wValueLength */
+            0x01, 0x00,     /* wType */
+            /* L"StringFileInfo" + DWORD alignment */
+            0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x46, 0x00, 0x69, 0x00,
+            0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00,
+            /* "FE2X" */
+            0x46, 0x45, 0x32, 0x58,
+
+            /* Extra bytes allocated for W->A conversions. */
+            0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba,
+            0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba,
+            0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba,
+            0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba,
+            0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba,
+            0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba,
+            0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba,
+            0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba, 0x0d, 0xf0, 0xad, 0xba,
+    };
+    char *p;
+    UINT len, ret;
+    WCHAR FileDescriptionW[] = { '\\', '\\', 'S', 't', 'r', 'i', 'n', 'g', 'F', 'i', 'l', 'e', 'I', 'n', 'f', 'o', 0 };
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValueA(preparedbuffer, "StringFileInfo", (LPVOID *)&p, &len);
+    ok(ret, "VerQueryValueA error %u\n", GetLastError());
+    ok(len == 0, "VerQueryValueA returned %u, expected 0\n", len);
+    todo_wine
+    ok(p == preparedbuffer + 0x7e, "p was %p, expected %p\n", p, preparedbuffer + 0x7e);
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValueA(preparedbuffer, "\\StringFileInfo", (LPVOID *)&p, &len);
+    ok(ret, "VerQueryValueA error %u\n", GetLastError());
+    ok(len == 0, "VerQueryValueA returned %u, expected 0\n", len);
+    todo_wine
+    ok(p == preparedbuffer + 0x7e, "p was %p, expected %p\n", p, preparedbuffer + 0x7e);
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValueA(preparedbuffer, "\\\\StringFileInfo", (LPVOID *)&p, &len);
+    ok(ret, "VerQueryValueA error %u\n", GetLastError());
+    ok(len == 0, "VerQueryValueA returned %u, expected 0\n", len);
+    todo_wine
+    ok(p == preparedbuffer + 0x7e, "p was %p, expected %p\n", p, preparedbuffer + 0x7e);
+
+    /* also test the W versions. */
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValueW(preparedbuffer, FileDescriptionW + 2, (LPVOID *)&p, &len);
+    ok(ret, "VerQueryValueW error %u\n", GetLastError());
+    ok(len == 0, "VerQueryValueW returned %u, expected 0\n", len);
+    todo_wine
+    ok(p == preparedbuffer + 0x7e, "p was %p, expected %p\n", p, preparedbuffer + 0x7e);
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValueW(preparedbuffer, FileDescriptionW + 1, (LPVOID *)&p, &len);
+    ok(ret, "VerQueryValueW error %u\n", GetLastError());
+    ok(len == 0, "VerQueryValueW returned %u, expected 0\n", len);
+    todo_wine
+    ok(p == preparedbuffer + 0x7e, "p was %p, expected %p\n", p, preparedbuffer + 0x7e);
+
+    p = (char *)0xdeadbeef;
+    len = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ret = VerQueryValueW(preparedbuffer, FileDescriptionW, (LPVOID *)&p, &len);
+    ok(ret, "VerQueryValueW error %u\n", GetLastError());
+    ok(len == 0, "VerQueryValueW returned %u, expected 0\n", len);
+    todo_wine
+    ok(p == preparedbuffer + 0x7e, "p was %p, expected %p\n", p, preparedbuffer + 0x7e);
+}
+
 static void test_extra_block(void)
 {
     WORD extra_block[] = {
@@ -738,6 +861,7 @@ START_TEST(info)
     test_info();
     test_32bit_win();
     test_VerQueryValueA();
+    test_VerQueryValue_InvalidLength();
     test_extra_block();
     test_GetFileVersionInfoEx();
 }
-- 
2.14.2

