1 /*
2 * PROJECT: ReactOS API Tests
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Tests for VerQueryValue[A/W]
5 * COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7
8 #include "precomp.h"
9
10 typedef struct
11 {
12 WORD wLength;
13 WORD wValueLength;
14 WORD wType;
15 WCHAR szKey[16]; // L"VS_VERSION_INFO"
16 WORD Padding1;
17 VS_FIXEDFILEINFO Value;
18
19 struct _StringFileInfo
20 {
21 WORD wLength;
22 WORD wValueLength;
23 WORD wType;
24 WCHAR szKey[15]; // L"StringFileInfo"
25
26 struct _StringTable
27 {
28 WORD wLength;
29 WORD wValueLength;
30 WORD wType;
31 WCHAR szKey[9]; // L"000004B"
32
33 struct _String_CompanyName
34 {
35 WORD wLength;
36 WORD wValueLength;
37 WORD wType;
38 WCHAR szKey[12]; // L"CompanyName"
39 WORD Padding1;
40 WCHAR Value[16]; // L"ReactOS Project"
41 } CompanyName;
42
43 struct _String_Comments
44 {
45 WORD wLength;
46 WORD wValueLength; // 0
47 WORD wType;
48 WCHAR szKey[9]; // L"Comments"
49 } Comments;
50
51 struct _String_Comments2
52 {
53 WORD wLength;
54 WORD wValueLength; // 0
55 WORD wType;
56 WCHAR szKey[10]; // L"Comments2"
57 WORD Padding;
58 } Comments2;
59
60 struct _String_FooBar
61 {
62 WORD wLength;
63 WORD wValueLength;
64 WORD wType;
65 WCHAR szKey[7]; // L"FooBar"
66 WCHAR Value[4]; // L"Bar"
67 } FooBar;
68
69 } StringTable;
70 } StringFileInfo;
71 } TEST_VERSIONINFO;
72
73 static const TEST_VERSIONINFO g_VersionInfo =
74 {
75 .wLength = 298, // Header: 40, Value: 54, StringFileInfo: 204
76 .wValueLength = sizeof(VS_FIXEDFILEINFO),
77 .wType = 0,
78 .szKey = L"VS_VERSION_INFO",
79 .Padding1 = 0,
80 .Value =
81 {
82 .dwSignature = VS_FFI_SIGNATURE,
83 .dwStrucVersion = VS_FFI_STRUCVERSION,
84 .dwFileVersionMS = 0x00050002,
85 .dwFileVersionLS = 0x0ECE0000,
86 .dwProductVersionMS = 0x00050002,
87 .dwProductVersionLS = 0x0ECE0000,
88 .dwFileFlagsMask = 0x00000002,
89 .dwFileFlags = 0x00000000,
90 .dwFileOS = VOS__WINDOWS32,
91 .dwFileType = VFT_APP,
92 .dwFileSubtype = VFT2_UNKNOWN,
93 .dwFileDateMS = 0x00020074,
94 .dwFileDateLS = 0x00000000,
95 },
96 .StringFileInfo =
97 {
98 .wLength = 204, // Header: 36, StringTable: 168
99 .wValueLength = 0,
100 .wType = 1,
101 .szKey = L"StringFileInfo",
102 .StringTable =
103 {
104 .wLength = 168, //Header: 24, Children: 144
105 .wValueLength = 0,
106 .wType = 1,
107 .szKey = L"000004B0",
108
109 .CompanyName =
110 {
111 .wLength = 64,
112 .wValueLength = 16,
113 .wType = 1,
114 .szKey = L"CompanyName",
115 .Padding1 = 0,
116 .Value = L"ReactOS Project",
117 },
118 .Comments =
119 {
120 .wLength = 24,
121 .wValueLength = 0,
122 .wType = 1,
123 .szKey = L"Comments",
124 },
125 .Comments2 =
126 {
127 .wLength = 28,
128 .wValueLength = 0,
129 .wType = 1,
130 .szKey = L"Comments2",
131 .Padding = 0xCC,
132 },
133 .FooBar =
134 {
135 .wLength = 28,
136 .wValueLength = 4,
137 .wType = 1,
138 .szKey = L"FooBar",
139 .Value = L"Bar",
140 },
141 },
142 },
143 };
144
145 void
Test_VerQueryValueA(void)146 Test_VerQueryValueA(void)
147 {
148 DWORD dwVersionInfoSizeW, dwVersionInfoSizeA;
149 PVOID pvVersionInfoA, pvData = NULL;
150 CHAR szSubBlock[256];
151 USHORT uLanguage, uCodePage;
152 UINT cbLen;
153 BOOL result;
154
155 /* Get the size for the unicode version info */
156 dwVersionInfoSizeW = GetFileVersionInfoSizeW(L"kernel32.dll", NULL);
157 ok(dwVersionInfoSizeW > 0, "GetFileVersionInfoSizeW failed\n");
158
159 /* Get the size for the ANSI version info */
160 dwVersionInfoSizeA = GetFileVersionInfoSizeA("kernel32.dll", NULL);
161 ok(dwVersionInfoSizeA > 0, "GetFileVersionInfoSizeA failed\n");
162 ok(dwVersionInfoSizeA == dwVersionInfoSizeW, "Unexpected size\n");
163
164 /* Get the ANSI version info from kernel32 */
165 pvVersionInfoA = malloc(dwVersionInfoSizeA);
166 memset(pvVersionInfoA, 0xCC, dwVersionInfoSizeA);
167 result = GetFileVersionInfoA("kernel32.dll", 0, dwVersionInfoSizeA, pvVersionInfoA);
168 ok(result, "GetFileVersionInfoA failed\n");
169
170 /* Query available translations */
171 result = VerQueryValueA(pvVersionInfoA,
172 "\\VarFileInfo\\Translation",
173 &pvData,
174 &cbLen);
175 ok(result, "VerQueryValueA failed\n");
176 ok(cbLen >= 4, "Unexpected value\n");
177 ok((cbLen & 0x3) == 0, "Unexpected value\n");
178 uLanguage = ((USHORT*)pvData)[0];
179 uCodePage = ((USHORT*)pvData)[1];
180
181 /* Query sublock */
182 sprintf(szSubBlock, "\\StringFileInfo\\%04X%04X\\CompanyName", uLanguage, uCodePage);
183 result = VerQueryValueA(pvVersionInfoA,
184 szSubBlock,
185 &pvData,
186 &cbLen);
187 ok(result, "VerQueryValueA failed\n");
188 ok(cbLen >= 2, "Unexpected value\n");
189 ok((cbLen & 0x1) == 0, "Unexpected value\n");
190
191 free(pvVersionInfoA);
192 }
193
194 void
Test_VerQueryValueW(void)195 Test_VerQueryValueW(void)
196 {
197 DWORD dwVersionInfoSizeW;
198 PVOID pvVersionInfoW, pvData = NULL;
199 WCHAR szSubBlock[256];
200 USHORT uLanguage, uCodePage;
201 UINT cbLen;
202 BOOL result;
203
204 /* Get the size for the unicode version info */
205 dwVersionInfoSizeW = GetFileVersionInfoSizeW(L"kernel32.dll", NULL);
206 ok(dwVersionInfoSizeW > 0, "GetFileVersionInfoSizeW failed\n");
207
208 /* Get the unicode version info from kernel32 */
209 pvVersionInfoW = malloc(dwVersionInfoSizeW);
210 result = GetFileVersionInfoW(L"kernel32.dll", 0, dwVersionInfoSizeW, pvVersionInfoW);
211 ok(result, "GetFileVersionInfoW failed\n");
212
213 /* Query available translations */
214 result = VerQueryValueW(pvVersionInfoW,
215 L"\\VarFileInfo\\Translation",
216 &pvData,
217 &cbLen);
218 ok(result, "VerQueryValueA failed\n");
219 ok(cbLen >= 4, "Unexpected value\n");
220 ok((cbLen & 0x3) == 0, "Unexpected value\n");
221 uLanguage = ((USHORT*)pvData)[0];
222 uCodePage = ((USHORT*)pvData)[1];
223
224 /* Query sublock */
225 _swprintf(szSubBlock, L"\\StringFileInfo\\%04X%04X\\CompanyName", uLanguage, uCodePage);
226 result = VerQueryValueW(pvVersionInfoW,
227 szSubBlock,
228 &pvData,
229 &cbLen);
230 ok(result, "VerQueryValueA failed\n");
231 ok(cbLen >= 2, "Unexpected value\n");
232 ok((cbLen & 0x1) == 0, "Unexpected value\n");
233
234 free(pvVersionInfoW);
235 }
236
237 void
Test_StaticVersionInfo(void)238 Test_StaticVersionInfo(void)
239 {
240 PVOID pVersionInfo;
241 PVOID pvData = NULL;
242 SIZE_T ExpectedOffset;
243 UINT cbLen;
244 BOOL result;
245
246 /* Make a copy of the version info. Windows actually writes to it!
247 We make the buffer twice as big to account for the ANSI copy,
248 even if we don't use it. */
249 pVersionInfo = malloc(2 * sizeof(g_VersionInfo));
250 memset(pVersionInfo, 0, 2 * sizeof(g_VersionInfo));
251 memcpy(pVersionInfo, &g_VersionInfo, sizeof(g_VersionInfo));
252
253 /* Test a special static version */
254 result = VerQueryValueW(pVersionInfo,
255 L"\\StringFileInfo\\000004B0\\CompanyName",
256 &pvData,
257 &cbLen);
258 ok(result, "VerQueryValueW failed\n");
259 ok_eq_int(cbLen, 16);
260 ok_eq_wstr((WCHAR*)pvData, L"ReactOS Project");
261 ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.CompanyName.Value);
262 ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n");
263
264 result = VerQueryValueW(pVersionInfo,
265 L"\\StringFileInfo\\000004B0\\Comments",
266 &pvData,
267 &cbLen);
268 ok(result, "VerQueryValueW failed\n");
269 ok_eq_int(cbLen, 0);
270 ok_eq_wstr((WCHAR*)pvData, L"");
271 ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.Comments.szKey[8]);
272 ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n");
273
274 result = VerQueryValueW(pVersionInfo,
275 L"\\StringFileInfo\\000004B0\\Comments2",
276 &pvData,
277 &cbLen);
278 ok(result, "VerQueryValueW failed\n");
279 ok_eq_int(cbLen, 0);
280 ok_eq_wstr((WCHAR*)pvData, L"");
281 ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.Comments2.szKey[9]);
282 ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n");
283
284 result = VerQueryValueW(pVersionInfo,
285 L"\\StringFileInfo\\000004B0\\FooBar",
286 &pvData,
287 &cbLen);
288 ok(result, "VerQueryValueW failed\n");
289 ok_eq_int(cbLen, 4);
290 ok(wcscmp((WCHAR*)pvData, L"Bar") == 0, "Bar\n");
291 ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.FooBar.Value);
292 ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n");
293
294 free(pVersionInfo);
295 }
296
START_TEST(VerQueryValue)297 START_TEST(VerQueryValue)
298 {
299 Test_VerQueryValueA();
300 Test_VerQueryValueW();
301 Test_StaticVersionInfo();
302 }
303