server: Store the clipboard windows as full handles.
[wine.git] / dlls / version / tests / info.c
blob107cfacaaa24c459de4a61a5b50456cd1699d2e1
1 /*
2 * Copyright (C) 2004 Stefan Leichter
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <assert.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winver.h"
27 #include "wine/test.h"
29 #define MY_LAST_ERROR ((DWORD)-1)
30 #define EXPECT_BAD_PATH__NOT_FOUND \
31 ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
32 (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
33 (ERROR_FILE_NOT_FOUND == GetLastError()) || \
34 (ERROR_BAD_PATHNAME == GetLastError()) || \
35 (ERROR_SUCCESS == GetLastError()), \
36 "Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_BAD_PATHNAME (98)/" \
37 "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3) " \
38 "ERROR_SUCCESS (2k) expected, got %u\n", GetLastError());
39 #define EXPECT_INVALID__NOT_FOUND \
40 ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
41 (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
42 (ERROR_FILE_NOT_FOUND == GetLastError()) || \
43 (ERROR_INVALID_PARAMETER == GetLastError()) || \
44 (ERROR_SUCCESS == GetLastError()), \
45 "Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_INVALID_PARAMETER (98)/" \
46 "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3) " \
47 "ERROR_SUCCESS (2k) expected, got %u\n", GetLastError());
49 static void create_file(const CHAR *name)
51 HANDLE file;
52 DWORD written;
54 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
55 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
56 WriteFile(file, name, strlen(name), &written, NULL);
57 WriteFile(file, "\n", strlen("\n"), &written, NULL);
58 CloseHandle(file);
61 static void test_info_size(void)
62 { DWORD hdl, retval;
63 char mypath[MAX_PATH] = "";
65 SetLastError(MY_LAST_ERROR);
66 retval = GetFileVersionInfoSizeA( NULL, NULL);
67 ok( !retval,
68 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
69 retval);
70 EXPECT_INVALID__NOT_FOUND;
72 hdl = 0x55555555;
73 SetLastError(MY_LAST_ERROR);
74 retval = GetFileVersionInfoSizeA( NULL, &hdl);
75 ok( !retval,
76 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
77 retval);
78 EXPECT_INVALID__NOT_FOUND;
79 ok( hdl == 0L,
80 "Handle wrong! 0L expected, got 0x%08x\n", hdl);
82 SetLastError(MY_LAST_ERROR);
83 retval = GetFileVersionInfoSizeA( "", NULL);
84 ok( !retval,
85 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
86 retval);
87 EXPECT_BAD_PATH__NOT_FOUND;
89 hdl = 0x55555555;
90 SetLastError(MY_LAST_ERROR);
91 retval = GetFileVersionInfoSizeA( "", &hdl);
92 ok( !retval,
93 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
94 retval);
95 EXPECT_BAD_PATH__NOT_FOUND;
96 ok( hdl == 0L,
97 "Handle wrong! 0L expected, got 0x%08x\n", hdl);
99 SetLastError(MY_LAST_ERROR);
100 retval = GetFileVersionInfoSizeA( "kernel32.dll", NULL);
101 ok( retval,
102 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
103 retval);
104 ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
105 "Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
106 MY_LAST_ERROR, GetLastError());
108 hdl = 0x55555555;
109 SetLastError(MY_LAST_ERROR);
110 retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl);
111 ok( retval,
112 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
113 retval);
114 ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
115 "Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
116 MY_LAST_ERROR, GetLastError());
117 ok( hdl == 0L,
118 "Handle wrong! 0L expected, got 0x%08x\n", hdl);
120 SetLastError(MY_LAST_ERROR);
121 retval = GetFileVersionInfoSizeA( "notexist.dll", NULL);
122 ok( !retval,
123 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
124 retval);
125 ok( (ERROR_FILE_NOT_FOUND == GetLastError()) ||
126 (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) ||
127 (MY_LAST_ERROR == GetLastError()) ||
128 (ERROR_SUCCESS == GetLastError()), /* win2k */
129 "Last error wrong! ERROR_FILE_NOT_FOUND/ERROR_RESOURCE_DATA_NOT_FOUND "
130 "(XP)/0x%08x (NT4) expected, got %u\n", MY_LAST_ERROR, GetLastError());
132 /* test a currently loaded executable */
133 if(GetModuleFileNameA(NULL, mypath, MAX_PATH)) {
134 hdl = 0x55555555;
135 SetLastError(MY_LAST_ERROR);
136 retval = GetFileVersionInfoSizeA( mypath, &hdl);
137 ok( retval,
138 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
139 retval);
140 ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
141 "Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
142 MY_LAST_ERROR, GetLastError());
143 ok( hdl == 0L,
144 "Handle wrong! 0L expected, got 0x%08x\n", hdl);
146 else
147 trace("skipping GetModuleFileNameA(NULL,..) failed\n");
149 /* test a not loaded executable */
150 if(GetSystemDirectoryA(mypath, MAX_PATH)) {
151 lstrcatA(mypath, "\\regsvr32.exe");
153 if(INVALID_FILE_ATTRIBUTES == GetFileAttributesA(mypath))
154 trace("GetFileAttributesA(%s) failed\n", mypath);
155 else {
156 hdl = 0x55555555;
157 SetLastError(MY_LAST_ERROR);
158 retval = GetFileVersionInfoSizeA( mypath, &hdl);
159 ok( retval,
160 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
161 retval);
162 ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
163 "Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
164 MY_LAST_ERROR, GetLastError());
165 ok( hdl == 0L,
166 "Handle wrong! 0L expected, got 0x%08x\n", hdl);
169 else
170 trace("skipping GetSystemDirectoryA(mypath,..) failed\n");
172 create_file("test.txt");
174 /* no version info */
175 SetLastError(0xdeadbeef);
176 hdl = 0xcafe;
177 retval = GetFileVersionInfoSizeA("test.txt", &hdl);
178 ok(retval == 0, "Expected 0, got %d\n", retval);
179 ok(hdl == 0, "Expected 0, got %d\n", hdl);
180 ok(GetLastError() == ERROR_RESOURCE_DATA_NOT_FOUND ||
181 GetLastError() == ERROR_SUCCESS, /* win2k */
182 "Expected ERROR_RESOURCE_DATA_NOT_FOUND, got %d\n", GetLastError());
184 DeleteFileA("test.txt");
187 static void VersionDwordLong2String(DWORDLONG Version, LPSTR lpszVerString)
189 WORD a, b, c, d;
191 a = (WORD)(Version >> 48);
192 b = (WORD)((Version >> 32) & 0xffff);
193 c = (WORD)((Version >> 16) & 0xffff);
194 d = (WORD)(Version & 0xffff);
196 sprintf(lpszVerString, "%d.%d.%d.%d", a, b, c, d);
199 static void test_info(void)
201 DWORD hdl, retval;
202 PVOID pVersionInfo = NULL;
203 BOOL boolret;
204 VS_FIXEDFILEINFO *pFixedVersionInfo;
205 UINT uiLength;
206 char VersionString[MAX_PATH];
207 static const char backslash[] = "\\";
208 DWORDLONG dwlVersion;
210 hdl = 0x55555555;
211 SetLastError(MY_LAST_ERROR);
212 retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl);
213 ok( retval,
214 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
215 retval);
216 ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
217 "Last error wrong! NO_ERROR/0x%08x (NT4) expected, got %u\n",
218 MY_LAST_ERROR, GetLastError());
219 ok( hdl == 0L,
220 "Handle wrong! 0L expected, got 0x%08x\n", hdl);
222 if ( retval == 0 || hdl != 0)
223 return;
225 pVersionInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retval );
226 ok(pVersionInfo != 0, "HeapAlloc failed\n" );
227 if (pVersionInfo == 0)
228 return;
230 if (0)
232 /* this test crashes on WinNT4
234 boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, 0);
235 ok (!boolret, "GetFileVersionInfoA should have failed: GetLastError = %u\n", GetLastError());
236 ok ((GetLastError() == ERROR_INVALID_DATA) || (GetLastError() == ERROR_BAD_PATHNAME) ||
237 (GetLastError() == NO_ERROR),
238 "Last error wrong! ERROR_INVALID_DATA/ERROR_BAD_PATHNAME (ME)/"
239 "NO_ERROR (95) expected, got %u\n",
240 GetLastError());
243 boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, pVersionInfo );
244 ok (boolret, "GetFileVersionInfoA failed: GetLastError = %u\n", GetLastError());
245 if (!boolret)
246 goto cleanup;
248 boolret = VerQueryValueA( pVersionInfo, NULL, (LPVOID *)&pFixedVersionInfo, &uiLength );
249 ok (boolret || GetLastError() == NO_ERROR /* Win98 */,
250 "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
252 boolret = VerQueryValueA( pVersionInfo, "", (LPVOID *)&pFixedVersionInfo, &uiLength );
253 ok (boolret, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
255 boolret = VerQueryValueA( pVersionInfo, backslash, (LPVOID *)&pFixedVersionInfo, &uiLength );
256 ok (boolret, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
257 if (!boolret)
258 goto cleanup;
260 dwlVersion = (((DWORDLONG)pFixedVersionInfo->dwFileVersionMS) << 32) +
261 pFixedVersionInfo->dwFileVersionLS;
263 VersionDwordLong2String(dwlVersion, VersionString);
265 trace("kernel32.dll version: %s\n", VersionString);
267 if (0)
269 /* this test crashes on WinNT4
271 boolret = VerQueryValueA( pVersionInfo, backslash, (LPVOID *)&pFixedVersionInfo, 0);
272 ok (boolret, "VerQueryValue failed: GetLastError = %u\n", GetLastError());
275 cleanup:
276 HeapFree( GetProcessHeap(), 0, pVersionInfo);
279 static void test_32bit_win(void)
281 DWORD hdlA, retvalA;
282 DWORD hdlW, retvalW = 0;
283 BOOL retA,retW;
284 PVOID pVersionInfoA = NULL;
285 PVOID pVersionInfoW = NULL;
286 char *pBufA;
287 WCHAR *pBufW;
288 UINT uiLengthA, uiLengthW;
289 char mypathA[MAX_PATH];
290 WCHAR mypathW[MAX_PATH];
291 char rootA[] = "\\";
292 WCHAR rootW[] = { '\\', 0 };
293 WCHAR emptyW[] = { 0 };
294 char varfileinfoA[] = "\\VarFileInfo\\Translation";
295 WCHAR varfileinfoW[] = { '\\','V','a','r','F','i','l','e','I','n','f','o',
296 '\\','T','r','a','n','s','l','a','t','i','o','n', 0 };
297 char WineVarFileInfoA[] = { 0x09, 0x04, 0xE4, 0x04 };
298 char FileDescriptionA[] = "\\StringFileInfo\\040904E4\\FileDescription";
299 WCHAR FileDescriptionW[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
300 '\\','0','4','0','9','0','4','E','4',
301 '\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
302 char WineFileDescriptionA[] = "FileDescription";
303 WCHAR WineFileDescriptionW[] = { 'F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
304 BOOL is_unicode_enabled = TRUE;
306 /* A copy from dlls/version/info.c */
307 typedef struct
309 WORD wLength;
310 WORD wValueLength;
311 WORD wType;
312 WCHAR szKey[1];
313 #if 0 /* variable length structure */
314 /* DWORD aligned */
315 BYTE Value[];
316 /* DWORD aligned */
317 VS_VERSION_INFO_STRUCT32 Children[];
318 #endif
319 } VS_VERSION_INFO_STRUCT32;
321 /* If we call GetFileVersionInfoA on a system that supports Unicode, NT/W2K/XP/W2K3 (by default) and Wine,
322 * the versioninfo will contain Unicode strings.
323 * Part of the test is to call both the A and W versions, which should have the same Version Information
324 * for some requests, on systems that support both calls.
327 /* First get the versioninfo via the W versions */
328 SetLastError(0xdeadbeef);
329 GetModuleFileNameW(NULL, mypathW, MAX_PATH);
330 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
332 win_skip("GetModuleFileNameW not existing on this platform, skipping comparison between A- and W-calls\n");
333 is_unicode_enabled = FALSE;
336 if (is_unicode_enabled)
338 retvalW = GetFileVersionInfoSizeW( mypathW, &hdlW);
339 pVersionInfoW = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retvalW );
340 retW = GetFileVersionInfoW( mypathW, 0, retvalW, pVersionInfoW );
341 ok(retW, "GetFileVersionInfo failed: GetLastError = %u\n", GetLastError());
344 GetModuleFileNameA(NULL, mypathA, MAX_PATH);
345 retvalA = GetFileVersionInfoSizeA( mypathA, &hdlA);
346 pVersionInfoA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retvalA );
347 retA = GetFileVersionInfoA( mypathA, 0, retvalA, pVersionInfoA );
348 ok(retA, "GetFileVersionInfo failed: GetLastError = %u\n", GetLastError());
350 if (is_unicode_enabled)
352 ok( retvalA == retvalW, "The size of the struct should be the same for both A/W calls, it is (%d) vs. (%d)\n",
353 retvalA, retvalW);
354 ok( !memcmp(pVersionInfoA, pVersionInfoW, retvalA), "Both structs should be the same, they aren't\n");
357 /* The structs on Windows are bigger than just the struct for the basic information. The total struct
358 * contains also an empty part, which is used for converted strings. The converted strings are a result
359 * of calling VerQueryValueA on a 32bit resource and calling VerQueryValueW on a 16bit resource.
360 * The first WORD of the structure (wLength) shows the size of the base struct. The total struct size depends
361 * on the Windows version:
363 * 16bits resource (numbers are from a sample app):
365 * Windows Version Retrieved with A/W wLength StructSize
366 * ====================================================================================
367 * Win98 A 0x01B4 (436) 436
368 * NT4 A/W 0x01B4 (436) 2048 ???
369 * W2K/XP/W2K3 A/W 0x01B4 (436) 1536 which is (436 - sizeof(VS_FIXEDFILEINFO)) * 4
371 * 32bits resource (numbers are from this test executable version_crosstest.exe):
372 * Windows Version Retrieved with A/W wLength StructSize
373 * =============================================================
374 * Win98 A 0x01E0 (480) 848 (structure data doesn't seem correct)
375 * NT4 A/W 0x0350 (848) 1272 (848 * 1.5)
376 * W2K/XP/W2K3 A/W 0x0350 (848) 1700 which is (848 * 2) + 4
378 * Wine will follow the implementation (eventually) of W2K/XP/W2K3
381 /* Now some tests for the above (only if we are unicode enabled) */
383 if (is_unicode_enabled)
385 VS_VERSION_INFO_STRUCT32 *vvis = pVersionInfoW;
386 ok ( retvalW == ((vvis->wLength * 2) + 4) || retvalW == (vvis->wLength * 1.5),
387 "Structure is not of the correct size\n");
390 /* Although the 32bit resource structures contain Unicode strings, VerQueryValueA will always return normal strings,
391 * VerQueryValueW will always return Unicode ones. (That means everything returned for StringFileInfo requests).
394 /* Get the VS_FIXEDFILEINFO information, this must be the same for both A- and W-Calls */
396 retA = VerQueryValueA( pVersionInfoA, rootA, (LPVOID *)&pBufA, &uiLengthA );
397 ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
398 ok ( uiLengthA == sizeof(VS_FIXEDFILEINFO), "Size (%d) doesn't match the size of the VS_FIXEDFILEINFO struct\n", uiLengthA);
400 if (is_unicode_enabled)
402 if(0)
403 { /* This causes Vista and w2k8 to crash */
404 retW = VerQueryValueW( pVersionInfoW, NULL, (LPVOID *)&pBufW, &uiLengthW );
405 ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
408 retW = VerQueryValueW( pVersionInfoW, emptyW, (LPVOID *)&pBufW, &uiLengthW );
409 ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
411 retW = VerQueryValueW( pVersionInfoW, rootW, (LPVOID *)&pBufW, &uiLengthW );
412 ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
413 ok ( uiLengthW == sizeof(VS_FIXEDFILEINFO), "Size (%d) doesn't match the size of the VS_FIXEDFILEINFO struct\n", uiLengthW );
415 ok( uiLengthA == uiLengthW, "The size of VS_FIXEDFILEINFO should be the same for both A/W calls, it is (%d) vs. (%d)\n",
416 uiLengthA, uiLengthW);
417 ok( !memcmp(pBufA, pBufW, uiLengthA), "Both values should be the same, they aren't\n");
420 /* Get some VarFileInfo information, this must be the same for both A- and W-Calls */
422 retA = VerQueryValueA( pVersionInfoA, varfileinfoA, (LPVOID *)&pBufA, &uiLengthA );
423 ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
424 ok( !memcmp(pBufA, WineVarFileInfoA, uiLengthA), "The VarFileInfo should have matched 0904e404 (non case sensitive)\n");
426 if (is_unicode_enabled)
428 retW = VerQueryValueW( pVersionInfoW, varfileinfoW, (LPVOID *)&pBufW, &uiLengthW );
429 ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
430 ok( uiLengthA == uiLengthW, "The size of the VarFileInfo information should be the same for both A/W calls, it is (%d) vs. (%d)\n",
431 uiLengthA, uiLengthW);
432 ok( !memcmp(pBufA, pBufW, uiLengthA), "Both values should be the same, they aren't\n");
435 /* Get some StringFileInfo information, this will be ANSI for A-Calls and Unicode for W-Calls */
437 retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
438 ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
439 ok( !lstrcmpA(WineFileDescriptionA, pBufA), "expected '%s' got '%s'\n",
440 WineFileDescriptionA, pBufA);
442 /* Test a second time */
443 retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
444 ok (retA, "VerQueryValueA failed: GetLastError = %u\n", GetLastError());
445 ok( !lstrcmpA(WineFileDescriptionA, pBufA), "expected '%s' got '%s'\n",
446 WineFileDescriptionA, pBufA);
448 if (is_unicode_enabled)
450 retW = VerQueryValueW( pVersionInfoW, FileDescriptionW, (LPVOID *)&pBufW, &uiLengthW );
451 ok (retW, "VerQueryValueW failed: GetLastError = %u\n", GetLastError());
452 ok( !lstrcmpW(WineFileDescriptionW, pBufW), "FileDescription should have been '%s'\n", WineFileDescriptionA);
455 HeapFree( GetProcessHeap(), 0, pVersionInfoA);
456 if (is_unicode_enabled)
457 HeapFree( GetProcessHeap(), 0, pVersionInfoW);
460 static void test_VerQueryValueA(void)
462 static const char * const value_name[] = {
463 "Product", "CompanyName", "FileDescription", "Internal",
464 "ProductVersion", "InternalName", "File", "LegalCopyright",
465 "FileVersion", "Legal", "OriginalFilename", "ProductName",
466 "Company", "Original" };
467 char *ver, *p;
468 UINT len, ret, translation, i;
469 char buf[MAX_PATH];
471 ret = GetModuleFileNameA(NULL, buf, sizeof(buf));
472 assert(ret);
474 SetLastError(0xdeadbeef);
475 len = GetFileVersionInfoSizeA(buf, NULL);
476 ok(len, "GetFileVersionInfoSizeA(%s) error %u\n", buf, GetLastError());
478 ver = HeapAlloc(GetProcessHeap(), 0, len);
479 assert(ver);
481 SetLastError(0xdeadbeef);
482 ret = GetFileVersionInfoA(buf, 0, len, ver);
483 ok(ret, "GetFileVersionInfoA error %u\n", GetLastError());
485 p = (char *)0xdeadbeef;
486 len = 0xdeadbeef;
487 SetLastError(0xdeadbeef);
488 ret = VerQueryValueA(ver, "\\VarFileInfo\\Translation", (LPVOID*)&p, &len);
489 ok(ret, "VerQueryValue error %u\n", GetLastError());
490 ok(len == 4, "VerQueryValue returned %u, expected 4\n", len);
492 translation = *(UINT *)p;
493 translation = MAKELONG(HIWORD(translation), LOWORD(translation));
495 p = (char *)0xdeadbeef;
496 len = 0xdeadbeef;
497 SetLastError(0xdeadbeef);
498 ret = VerQueryValueA(ver, "String", (LPVOID*)&p, &len);
499 ok(!ret, "VerQueryValue should fail\n");
500 ok(GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND ||
501 GetLastError() == 0xdeadbeef /* NT4, W2K */,
502 "VerQueryValue returned %u\n", GetLastError());
503 ok(p == (char *)0xdeadbeef, "expected 0xdeadbeef got %p\n", p);
504 ok(len == 0, "expected 0 got %x\n", len);
506 p = (char *)0xdeadbeef;
507 len = 0xdeadbeef;
508 SetLastError(0xdeadbeef);
509 ret = VerQueryValueA(ver, "StringFileInfo", (LPVOID*)&p, &len);
510 ok(ret, "VerQueryValue error %u\n", GetLastError());
511 ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
512 ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
514 p = (char *)0xdeadbeef;
515 len = 0xdeadbeef;
516 SetLastError(0xdeadbeef);
517 ret = VerQueryValueA(ver, "\\StringFileInfo", (LPVOID*)&p, &len);
518 ok(ret, "VerQueryValue error %u\n", GetLastError());
519 ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
520 ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
522 p = (char *)0xdeadbeef;
523 len = 0xdeadbeef;
524 SetLastError(0xdeadbeef);
525 ret = VerQueryValueA(ver, "\\\\StringFileInfo", (LPVOID*)&p, &len);
526 ok(ret, "VerQueryValue error %u\n", GetLastError());
527 ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
528 ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
530 p = (char *)0xdeadbeef;
531 len = 0xdeadbeef;
532 SetLastError(0xdeadbeef);
533 ret = VerQueryValueA(ver, "\\StringFileInfo\\\\", (LPVOID*)&p, &len);
534 ok(ret, "VerQueryValue error %u\n", GetLastError());
535 ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
536 ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
538 sprintf(buf, "\\StringFileInfo\\%08x", translation);
539 p = (char *)0xdeadbeef;
540 len = 0xdeadbeef;
541 SetLastError(0xdeadbeef);
542 ret = VerQueryValueA(ver, buf, (LPVOID*)&p, &len);
543 ok(ret, "VerQueryValue error %u\n", GetLastError());
544 ok(len == 0, "VerQueryValue returned %u, expected 0\n", len);
545 ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
547 for (i = 0; i < sizeof(value_name)/sizeof(value_name[0]); i++)
549 sprintf(buf, "\\StringFileInfo\\%08x\\%s", translation, value_name[i]);
550 p = (char *)0xdeadbeef;
551 len = 0xdeadbeef;
552 SetLastError(0xdeadbeef);
553 ret = VerQueryValueA(ver, buf, (LPVOID*)&p, &len);
554 ok(ret, "VerQueryValueA(%s) error %u\n", buf, GetLastError());
555 ok(len == strlen(value_name[i]) + 1, "VerQueryValue returned %u\n", len);
556 ok(!strcmp(value_name[i], p), "expected \"%s\", got \"%s\"\n",
557 value_name[i], p);
559 /* test partial value names */
560 len = lstrlenA(buf);
561 buf[len - 2] = 0;
562 p = (char *)0xdeadbeef;
563 len = 0xdeadbeef;
564 SetLastError(0xdeadbeef);
565 ret = VerQueryValueA(ver, buf, (LPVOID*)&p, &len);
566 ok(!ret, "VerQueryValueA(%s) succeeded\n", buf);
567 ok(GetLastError() == ERROR_RESOURCE_TYPE_NOT_FOUND ||
568 GetLastError() == 0xdeadbeef /* NT4, W2K */,
569 "VerQueryValue returned %u\n", GetLastError());
570 ok(p == (char *)0xdeadbeef, "expected 0xdeadbeef got %p\n", p);
571 ok(len == 0, "expected 0 or 0xbeef, got %x\n", len);
574 HeapFree(GetProcessHeap(), 0, ver);
577 static void test_extra_block(void)
579 WORD extra_block[] = {
580 72, 0, 0, 'W', 'i', 'n', 'e', 'T', 'e', 's', 't', '\0',
581 24, 4, 0, 'B', 'i', 'n', 'a', 'r', 'y', '\0', 0xbeef, 0xdead,
582 24, 4, 1, 'T', 'e', 'x', 't', '\0', 'B', '-', ')', '\0',
584 char buf[MAX_PATH];
585 UINT len, ret;
586 ULONG w;
587 char *ver, *p;
588 WORD *length;
590 ret = GetModuleFileNameA(NULL, buf, sizeof(buf));
591 ok(ret, "GetModuleFileNameA failed\n");
593 len = GetFileVersionInfoSizeA(buf, NULL);
594 ok(len, "GetFileVersionInfoSizeA(%s) error %u\n", buf, GetLastError());
596 ver = HeapAlloc(GetProcessHeap(), 0, len + sizeof(extra_block) * 2);
597 ok(ver != NULL, "Can't allocate memory\n");
599 ret = GetFileVersionInfoA(buf, 0, len, ver);
600 ok(ret, "GetFileVersionInfoA error %u\n", GetLastError());
602 /* forge the string table, as windres dislike an extra block */
603 length = (WORD *)ver; /* see VS_VERSION_INFO_STRUCT32 for details */
604 memcpy(ver + *length, extra_block, sizeof(extra_block));
605 *length += sizeof(extra_block);
607 p = (char *)0xdeadbeef;
608 len = 0xdeadbeef;
609 w = 0xdeadbeef;
610 ret = VerQueryValueA(ver, "WineTest\\Binary", (LPVOID*)&p, &len);
611 ok(ret, "VerQueryValue error %u\n", GetLastError());
612 ok(len == 4, "VerQueryValue returned %u, expected 4\n", len);
613 ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
614 ok(memcmp(p, &w, sizeof(w)) == 0, "got 0x%08x, expected 0x%08x\n", *(PULONG)p, w);
616 p = (char *)0xdeadbeef;
617 len = 0xdeadbeef;
618 ret = VerQueryValueA(ver, "WineTest\\Text", (LPVOID*)&p, &len);
619 ok(ret, "VerQueryValue error %u\n", GetLastError());
620 ok(len == 4, "VerQueryValue returned %u, expected 4\n", len);
621 ok(p != (char *)0xdeadbeef, "not expected 0xdeadbeef\n");
622 ok(strcmp(p, "B-)") == 0, "got '%s', expected '%s'\n", p, "B-)");
624 HeapFree(GetProcessHeap(), 0, ver);
627 START_TEST(info)
629 test_info_size();
630 test_info();
631 test_32bit_win();
632 test_VerQueryValueA();
633 test_extra_block();