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
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
)
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
);
61 static void test_info_size(void)
63 char mypath
[MAX_PATH
] = "";
65 SetLastError(MY_LAST_ERROR
);
66 retval
= GetFileVersionInfoSizeA( NULL
, NULL
);
68 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
70 EXPECT_INVALID__NOT_FOUND
;
73 SetLastError(MY_LAST_ERROR
);
74 retval
= GetFileVersionInfoSizeA( NULL
, &hdl
);
76 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
78 EXPECT_INVALID__NOT_FOUND
;
80 "Handle wrong! 0L expected, got 0x%08x\n", hdl
);
82 SetLastError(MY_LAST_ERROR
);
83 retval
= GetFileVersionInfoSizeA( "", NULL
);
85 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
87 EXPECT_BAD_PATH__NOT_FOUND
;
90 SetLastError(MY_LAST_ERROR
);
91 retval
= GetFileVersionInfoSizeA( "", &hdl
);
93 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
95 EXPECT_BAD_PATH__NOT_FOUND
;
97 "Handle wrong! 0L expected, got 0x%08x\n", hdl
);
99 SetLastError(MY_LAST_ERROR
);
100 retval
= GetFileVersionInfoSizeA( "kernel32.dll", NULL
);
102 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
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());
109 SetLastError(MY_LAST_ERROR
);
110 retval
= GetFileVersionInfoSizeA( "kernel32.dll", &hdl
);
112 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
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());
118 "Handle wrong! 0L expected, got 0x%08x\n", hdl
);
120 SetLastError(MY_LAST_ERROR
);
121 retval
= GetFileVersionInfoSizeA( "notexist.dll", NULL
);
123 "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
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
)) {
135 SetLastError(MY_LAST_ERROR
);
136 retval
= GetFileVersionInfoSizeA( mypath
, &hdl
);
138 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
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());
144 "Handle wrong! 0L expected, got 0x%08x\n", hdl
);
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
);
157 SetLastError(MY_LAST_ERROR
);
158 retval
= GetFileVersionInfoSizeA( mypath
, &hdl
);
160 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
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());
166 "Handle wrong! 0L expected, got 0x%08x\n", hdl
);
170 trace("skipping GetSystemDirectoryA(mypath,..) failed\n");
172 create_file("test.txt");
174 /* no version info */
175 SetLastError(0xdeadbeef);
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
)
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)
202 PVOID pVersionInfo
= NULL
;
204 VS_FIXEDFILEINFO
*pFixedVersionInfo
;
206 char VersionString
[MAX_PATH
];
207 static const char backslash
[] = "\\";
208 DWORDLONG dwlVersion
;
211 SetLastError(MY_LAST_ERROR
);
212 retval
= GetFileVersionInfoSizeA( "kernel32.dll", &hdl
);
214 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
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());
220 "Handle wrong! 0L expected, got 0x%08x\n", hdl
);
222 if ( retval
== 0 || hdl
!= 0)
225 pVersionInfo
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, retval
);
226 ok(pVersionInfo
!= 0, "HeapAlloc failed\n" );
227 if (pVersionInfo
== 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",
243 boolret
= GetFileVersionInfoA( "kernel32.dll", 0, retval
, pVersionInfo
);
244 ok (boolret
, "GetFileVersionInfoA failed: GetLastError = %u\n", GetLastError());
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());
260 dwlVersion
= (((DWORDLONG
)pFixedVersionInfo
->dwFileVersionMS
) << 32) +
261 pFixedVersionInfo
->dwFileVersionLS
;
263 VersionDwordLong2String(dwlVersion
, VersionString
);
265 trace("kernel32.dll version: %s\n", VersionString
);
269 /* this test crashes on WinNT4
271 boolret
= VerQueryValueA( pVersionInfo
, backslash
, (LPVOID
*)&pFixedVersionInfo
, 0);
272 ok (boolret
, "VerQueryValue failed: GetLastError = %u\n", GetLastError());
276 HeapFree( GetProcessHeap(), 0, pVersionInfo
);
279 static void test_32bit_win(void)
282 DWORD hdlW
, retvalW
= 0;
284 PVOID pVersionInfoA
= NULL
;
285 PVOID pVersionInfoW
= NULL
;
288 UINT uiLengthA
, uiLengthW
;
289 char mypathA
[MAX_PATH
];
290 WCHAR mypathW
[MAX_PATH
];
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 */
313 #if 0 /* variable length structure */
317 VS_VERSION_INFO_STRUCT32 Children
[];
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",
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
)
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" };
468 UINT len
, ret
, translation
, i
;
471 ret
= GetModuleFileNameA(NULL
, buf
, sizeof(buf
));
474 SetLastError(0xdeadbeef);
475 len
= GetFileVersionInfoSizeA(buf
, NULL
);
476 ok(len
, "GetFileVersionInfoSizeA(%s) error %u\n", buf
, GetLastError());
478 ver
= HeapAlloc(GetProcessHeap(), 0, len
);
481 SetLastError(0xdeadbeef);
482 ret
= GetFileVersionInfoA(buf
, 0, len
, ver
);
483 ok(ret
, "GetFileVersionInfoA error %u\n", GetLastError());
485 p
= (char *)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;
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;
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;
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;
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;
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;
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;
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",
559 /* test partial value names */
562 p
= (char *)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',
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;
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;
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
);
632 test_VerQueryValueA();