opengl32: Avoid generating a wrapper for internal functions when we can call the...
[wine] / dlls / version / tests / info.c
1 /*
2  * Copyright (C) 2004 Stefan Leichter
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include <stdarg.h>
20 #include <stdio.h>
21
22 #include "wine/test.h"
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winerror.h"
26 #include "winver.h"
27
28 #define MY_LAST_ERROR ((DWORD)-1)
29 #define EXPECT_BAD_PATH__NOT_FOUND \
30     ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
31         (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
32         (ERROR_FILE_NOT_FOUND == GetLastError()) || \
33         (ERROR_BAD_PATHNAME == GetLastError()), \
34         "Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_BAD_PATHNAME (98)/" \
35         "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \
36         "expected, got 0x%08x\n", GetLastError());
37 #define EXPECT_INVALID__NOT_FOUND \
38     ok( (ERROR_PATH_NOT_FOUND == GetLastError()) || \
39         (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) || \
40         (ERROR_FILE_NOT_FOUND == GetLastError()) || \
41         (ERROR_INVALID_PARAMETER == GetLastError()), \
42         "Last error wrong! ERROR_RESOURCE_DATA_NOT_FOUND/ERROR_INVALID_PARAMETER (98)/" \
43         "ERROR_PATH_NOT_FOUND (NT4)/ERROR_FILE_NOT_FOUND (2k3)" \
44         "expected, got 0x%08x\n", GetLastError());
45
46 static void test_info_size(void)
47 {   DWORD hdl, retval;
48     char mypath[MAX_PATH] = "";
49
50     SetLastError(MY_LAST_ERROR);
51     retval = GetFileVersionInfoSizeA( NULL, NULL);
52     ok( !retval,
53         "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
54         retval);
55     EXPECT_INVALID__NOT_FOUND;
56
57     hdl = 0x55555555;
58     SetLastError(MY_LAST_ERROR);
59     retval = GetFileVersionInfoSizeA( NULL, &hdl);
60     ok( !retval,
61         "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
62         retval);
63     EXPECT_INVALID__NOT_FOUND;
64     ok( hdl == 0L,
65         "Handle wrong! 0L expected, got 0x%08x\n", hdl);
66
67     SetLastError(MY_LAST_ERROR);
68     retval = GetFileVersionInfoSizeA( "", NULL);
69     ok( !retval,
70         "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
71         retval);
72     EXPECT_BAD_PATH__NOT_FOUND;
73
74     hdl = 0x55555555;
75     SetLastError(MY_LAST_ERROR);
76     retval = GetFileVersionInfoSizeA( "", &hdl);
77     ok( !retval,
78         "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
79         retval);
80     EXPECT_BAD_PATH__NOT_FOUND;
81     ok( hdl == 0L,
82         "Handle wrong! 0L expected, got 0x%08x\n", hdl);
83
84     SetLastError(MY_LAST_ERROR);
85     retval = GetFileVersionInfoSizeA( "kernel32.dll", NULL);
86     ok( retval,
87         "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
88         retval);
89     ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
90         "Last error wrong! NO_ERROR/0x%08x (NT4)  expected, got 0x%08x\n",
91         MY_LAST_ERROR, GetLastError());
92
93     hdl = 0x55555555;
94     SetLastError(MY_LAST_ERROR);
95     retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl);
96     ok( retval,
97         "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
98         retval);
99     ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
100         "Last error wrong! NO_ERROR/0x%08x (NT4)  expected, got 0x%08x\n",
101         MY_LAST_ERROR, GetLastError());
102     ok( hdl == 0L,
103         "Handle wrong! 0L expected, got 0x%08x\n", hdl);
104
105     SetLastError(MY_LAST_ERROR);
106     retval = GetFileVersionInfoSizeA( "notexist.dll", NULL);
107     ok( !retval,
108         "GetFileVersionInfoSizeA result wrong! 0L expected, got 0x%08x\n",
109         retval);
110     ok( (ERROR_FILE_NOT_FOUND == GetLastError()) ||
111         (ERROR_RESOURCE_DATA_NOT_FOUND == GetLastError()) ||
112         (MY_LAST_ERROR == GetLastError()),
113         "Last error wrong! ERROR_FILE_NOT_FOUND/ERROR_RESOURCE_DATA_NOT_FOUND "
114         "(XP)/0x%08x (NT4) expected, got 0x%08x\n", MY_LAST_ERROR, GetLastError());
115
116     /* test a currently loaded executable */
117     if(GetModuleFileNameA(NULL, mypath, MAX_PATH)) {
118         hdl = 0x55555555;
119         SetLastError(MY_LAST_ERROR);
120         retval = GetFileVersionInfoSizeA( mypath, &hdl);
121         ok( retval,
122             "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
123             retval);
124         ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
125             "Last error wrong! NO_ERROR/0x%08x (NT4)  expected, got 0x%08x\n",
126             MY_LAST_ERROR, GetLastError());
127         ok( hdl == 0L,
128             "Handle wrong! 0L expected, got 0x%08x\n", hdl);
129     }
130     else
131         trace("skipping GetModuleFileNameA(NULL,..) failed\n");
132
133     /* test a not loaded executable */
134     if(GetSystemDirectoryA(mypath, MAX_PATH)) {
135         lstrcatA(mypath, "\\regsvr32.exe");
136
137         if(INVALID_FILE_ATTRIBUTES == GetFileAttributesA(mypath))
138             trace("GetFileAttributesA(%s) failed\n", mypath);
139         else {
140             hdl = 0x55555555;
141             SetLastError(MY_LAST_ERROR);
142             retval = GetFileVersionInfoSizeA( mypath, &hdl);
143             ok( retval,
144                 "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
145                 retval);
146             ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
147                 "Last error wrong! NO_ERROR/0x%08x (NT4)  expected, got 0x%08x\n",
148                 MY_LAST_ERROR, GetLastError());
149             ok( hdl == 0L,
150                 "Handle wrong! 0L expected, got 0x%08x\n", hdl);
151         }
152     }
153     else
154         trace("skipping GetModuleFileNameA(NULL,..) failed\n");
155 }
156
157 static void VersionDwordLong2String(DWORDLONG Version, LPSTR lpszVerString)
158 {
159     WORD a, b, c, d;
160
161     a = (WORD)(Version >> 48);
162     b = (WORD)((Version >> 32) & 0xffff);
163     c = (WORD)((Version >> 16) & 0xffff);
164     d = (WORD)(Version & 0xffff);
165
166     sprintf(lpszVerString, "%d.%d.%d.%d", a, b, c, d);
167
168     return;
169 }
170
171 static void test_info(void)
172 {
173     DWORD hdl, retval;
174     PVOID pVersionInfo = NULL;
175     BOOL boolret;
176     VS_FIXEDFILEINFO *pFixedVersionInfo;
177     UINT uiLength;
178     char VersionString[MAX_PATH];
179     static CHAR backslash[] = "\\";
180     DWORDLONG dwlVersion;
181
182     hdl = 0x55555555;
183     SetLastError(MY_LAST_ERROR);
184     retval = GetFileVersionInfoSizeA( "kernel32.dll", &hdl);
185     ok( retval,
186         "GetFileVersionInfoSizeA result wrong! <> 0L expected, got 0x%08x\n",
187         retval);
188     ok((NO_ERROR == GetLastError()) || (MY_LAST_ERROR == GetLastError()),
189         "Last error wrong! NO_ERROR/0x%08x (NT4)  expected, got 0x%08x\n",
190         MY_LAST_ERROR, GetLastError());
191     ok( hdl == 0L,
192         "Handle wrong! 0L expected, got 0x%08x\n", hdl);
193
194     if ( retval == 0 || hdl != 0)
195         return;
196
197     pVersionInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retval );
198     ok(pVersionInfo != 0, "HeapAlloc failed\n" );
199     if (pVersionInfo == 0)
200         return;
201
202 #if 0
203     /* this test crashes on WinNT4
204      */
205     boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, 0);
206     ok (!boolret, "GetFileVersionInfoA should have failed: GetLastError = 0x%08lx\n", GetLastError());
207     ok ((GetLastError() == ERROR_INVALID_DATA) || (GetLastError() == ERROR_BAD_PATHNAME) ||
208         (GetLastError() == NO_ERROR),
209         "Last error wrong! ERROR_INVALID_DATA/ERROR_BAD_PATHNAME (ME)/"
210         "NO_ERROR (95) expected, got 0x%08lx\n",
211         GetLastError());
212 #endif
213
214     boolret = GetFileVersionInfoA( "kernel32.dll", 0, retval, pVersionInfo );
215     ok (boolret, "GetFileVersionInfoA failed: GetLastError = 0x%08x\n", GetLastError());
216     if (!boolret)
217         goto cleanup;
218
219     boolret = VerQueryValueA( pVersionInfo, backslash, (LPVOID *)&pFixedVersionInfo, &uiLength );
220     ok (boolret, "VerQueryValueA failed: GetLastError = 0x%08x\n", GetLastError());
221     if (!boolret)
222         goto cleanup;
223
224     dwlVersion = (((DWORDLONG)pFixedVersionInfo->dwFileVersionMS) << 32) +
225         pFixedVersionInfo->dwFileVersionLS;
226
227     VersionDwordLong2String(dwlVersion, VersionString);
228
229     trace("kernel32.dll version: %s\n", VersionString);
230
231 #if 0
232     /* this test crashes on WinNT4
233      */
234     boolret = VerQueryValueA( pVersionInfo, "\\", (LPVOID *)&pFixedVersionInfo, 0);
235     ok (boolret, "VerQueryValue failed: GetLastError = 0x%08lx\n", GetLastError());
236 #endif
237
238 cleanup:
239     HeapFree( GetProcessHeap(), 0, pVersionInfo);
240 }
241
242 static void test_32bit_win(void)
243 {
244     DWORD hdlA, retvalA;
245     DWORD hdlW, retvalW = 0;
246     BOOL retA,retW;
247     PVOID pVersionInfoA = NULL;
248     PVOID pVersionInfoW = NULL;
249     char *pBufA;
250     WCHAR *pBufW;
251     UINT uiLengthA, uiLengthW;
252     char mypathA[MAX_PATH];
253     WCHAR mypathW[MAX_PATH];
254     char rootA[] = "\\";
255     WCHAR rootW[] = { '\\', 0 };
256     char varfileinfoA[] = "\\VarFileInfo\\Translation";
257     WCHAR varfileinfoW[]    = { '\\','V','a','r','F','i','l','e','I','n','f','o',
258                                 '\\','T','r','a','n','s','l','a','t','i','o','n', 0 };
259     char WineVarFileInfoA[] = { 0x09, 0x04, 0xE4, 0x04 };
260     char FileDescriptionA[] = "\\StringFileInfo\\040904E4\\FileDescription";
261     WCHAR FileDescriptionW[] = { '\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
262                                 '\\','0','4','0','9','0','4','E','4',
263                                 '\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n', 0 };
264     char WineFileDescriptionA[] = "Wine version test";
265     WCHAR WineFileDescriptionW[] = { 'W','i','n','e',' ','v','e','r','s','i','o','n',' ','t','e','s','t', 0 };
266     BOOL is_unicode_enabled = TRUE;
267
268     /* A copy from dlls/version/info.c */
269     typedef struct
270     {
271         WORD  wLength;
272         WORD  wValueLength;
273         WORD  wType;
274         WCHAR szKey[1];
275 #if 0   /* variable length structure */
276         /* DWORD aligned */
277         BYTE  Value[];
278         /* DWORD aligned */
279         VS_VERSION_INFO_STRUCT32 Children[];
280 #endif
281     } VS_VERSION_INFO_STRUCT32;
282
283     /* If we call GetFileVersionInfoA on a system that supports Unicode, NT/W2K/XP/W2K3 (by default) and Wine,
284      * the versioninfo will contain Unicode strings.
285      * Part of the test is to call both the A and W versions, which should have the same Version Information
286      * for some requests, on systems that support both calls.
287      */
288
289     /* First get the versioninfo via the W versions */
290     GetModuleFileNameW(NULL, mypathW, MAX_PATH);
291     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
292     {
293         trace("GetModuleFileNameW not existing on this platform, skipping comparison between A- and W-calls\n");
294         is_unicode_enabled = FALSE;
295     }
296
297     if (is_unicode_enabled)
298     { 
299         retvalW = GetFileVersionInfoSizeW( mypathW, &hdlW);
300         pVersionInfoW = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retvalW );
301         retW = GetFileVersionInfoW( mypathW, 0, retvalW, pVersionInfoW );
302     }
303
304     GetModuleFileNameA(NULL, mypathA, MAX_PATH);
305     retvalA = GetFileVersionInfoSizeA( mypathA, &hdlA);
306     pVersionInfoA = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, retvalA );
307     retA = GetFileVersionInfoA( mypathA, 0, retvalA, pVersionInfoA );
308
309     if (is_unicode_enabled)
310     { 
311         ok( retvalA == retvalW, "The size of the struct should be the same for both A/W calls, it is (%d) vs. (%d)\n",
312                                 retvalA, retvalW);
313         ok( !memcmp(pVersionInfoA, pVersionInfoW, retvalA), "Both structs should be the same, they aren't\n");
314     }
315
316     /* The structs on Windows are bigger then just the struct for the basic information. The total struct
317      * contains also an empty part, which is used for converted strings. The converted strings are a result
318      * of calling VerQueryValueA on a 32bit resource and calling VerQueryValueW on a 16bit resource.
319      * The first WORD of the structure (wLength) shows the size of the base struct. The total struct size depends
320      * on the Windows version:
321      *
322      * 16bits resource (numbers are from a sample app):
323      *
324      * Windows Version    Retrieved with A/W    wLength        StructSize
325      * ====================================================================================
326      * Win98              A                     0x01B4 (436)   436
327      * NT4                A/W                   0x01B4 (436)   2048 ???
328      * W2K/XP/W2K3        A/W                   0x01B4 (436)   1536 which is (436 - sizeof(VS_FIXEDFILEINFO)) * 4
329      *
330      * 32bits resource (numbers are from this test executable version_crosstest.exe):
331      * Windows Version    Retrieved with A/W    wLength        StructSize
332      * =============================================================
333      * Win98              A                     0x01E0 (480)   848 (structure data doesn't seem correct)
334      * NT4                A/W                   0x0350 (848)   1272 (848 * 1.5)
335      * W2K/XP/W2K3        A/W                   0x0350 (848)   1700 which is (848 * 2) + 4 
336      *
337      * Wine will follow the implementation (eventually) of W2K/XP/W2K3
338      */
339
340     /* Now some tests for the above (only if we are unicode enabled) */
341
342     if (is_unicode_enabled)
343     { 
344         VS_VERSION_INFO_STRUCT32 *vvis = (VS_VERSION_INFO_STRUCT32 *)pVersionInfoW;
345         ok ( retvalW == ((vvis->wLength * 2) + 4) || retvalW == (vvis->wLength * 1.5),
346              "Structure is not of the correct size\n");
347     }
348
349     /* Although the 32bit resource structures contain Unicode strings, VerQueryValueA will always return normal strings,
350      * VerQueryValueW will always return Unicode ones. (That means everything returned for StringFileInfo requests).
351      */
352
353     /* Get the VS_FIXEDFILEINFO information, this must be the same for both A- and W-Calls */ 
354
355     retA = VerQueryValueA( pVersionInfoA, rootA, (LPVOID *)&pBufA, &uiLengthA );
356     ok (retA, "VerQueryValueA failed: GetLastError = 0x%08x\n", GetLastError());
357     ok ( uiLengthA == sizeof(VS_FIXEDFILEINFO), "Size (%d) doesn't match the size of the VS_FIXEDFILEINFO struct\n", uiLengthA);
358
359     if (is_unicode_enabled)
360     { 
361         retW = VerQueryValueW( pVersionInfoW, rootW, (LPVOID *)&pBufW, &uiLengthW );
362         ok (retW, "VerQueryValueW failed: GetLastError = 0x%08x\n", GetLastError());
363         ok ( uiLengthA == sizeof(VS_FIXEDFILEINFO), "Size (%d) doesn't match the size of the VS_FIXEDFILEINFO struct\n", uiLengthA);
364
365         ok( uiLengthA == uiLengthW, "The size of VS_FIXEDFILEINFO should be the same for both A/W calls, it is (%d) vs. (%d)\n",
366                                     uiLengthA, uiLengthW);
367         ok( !memcmp(pBufA, pBufW, uiLengthA), "Both values should be the same, they aren't\n");
368     }
369
370     /* Get some VarFileInfo information, this must be the same for both A- and W-Calls */
371
372     retA = VerQueryValueA( pVersionInfoA, varfileinfoA, (LPVOID *)&pBufA, &uiLengthA );
373     ok (retA, "VerQueryValueA failed: GetLastError = 0x%08x\n", GetLastError());
374     ok( !memcmp(pBufA, WineVarFileInfoA, uiLengthA), "The VarFileInfo should have matched 0904e404 (non case sensitive)\n");
375
376     if (is_unicode_enabled)
377     { 
378         retW = VerQueryValueW( pVersionInfoW, varfileinfoW, (LPVOID *)&pBufW, &uiLengthW );
379         ok (retW, "VerQueryValueW failed: GetLastError = 0x%08x\n", GetLastError());
380         ok( uiLengthA == uiLengthW, "The size of the VarFileInfo information should be the same for both A/W calls, it is (%d) vs. (%d)\n",
381                                     uiLengthA, uiLengthW);
382         ok( !memcmp(pBufA, pBufW, uiLengthA), "Both values should be the same, they aren't\n");
383     }
384
385     /* Get some StringFileInfo information, this will be ANSI for A-Calls and Unicode for W-Calls */
386
387     retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
388     ok (retA, "VerQueryValueA failed: GetLastError = 0x%08x\n", GetLastError());
389     ok( !lstrcmpA(WineFileDescriptionA, pBufA), "FileDescription should have been 'Wine version test'\n");
390
391     /* Test a second time */
392     retA = VerQueryValueA( pVersionInfoA, FileDescriptionA, (LPVOID *)&pBufA, &uiLengthA );
393     ok (retA, "VerQueryValueA failed: GetLastError = 0x%08x\n", GetLastError());
394     ok( !lstrcmpA(WineFileDescriptionA, pBufA), "FileDescription should have been 'Wine version test'\n");
395
396     if (is_unicode_enabled)
397     { 
398         retW = VerQueryValueW( pVersionInfoW, FileDescriptionW, (LPVOID *)&pBufW, &uiLengthW );
399         ok (retW, "VerQueryValueW failed: GetLastError = 0x%08x\n", GetLastError());
400         ok( !lstrcmpW(WineFileDescriptionW, pBufW), "FileDescription should have been 'Wine version test' (unicode)\n");
401     }
402
403     HeapFree( GetProcessHeap(), 0, pVersionInfoA);
404     if (is_unicode_enabled)
405         HeapFree( GetProcessHeap(), 0, pVersionInfoW);
406 }
407
408 START_TEST(info)
409 {
410     test_info_size();
411     test_info();
412    
413     /* Test several AW-calls on a 32 bit windows executable */
414     trace("Testing 32 bit windows application\n");
415     test_32bit_win();
416 }