1 /* Unit test suite for resources.
3 * Copyright 2004 Ferenc Wagner
4 * Copyright 2003, 2004 Mike McCormack
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/test.h"
26 static UINT (WINAPI
*pPrivateExtractIconsA
)(LPCTSTR
, int, int, int, HICON
*, UINT
*, UINT
, UINT
) = NULL
;
28 static void init_function_pointers(void)
30 HMODULE hmod
= GetModuleHandleA("user32.dll");
31 pPrivateExtractIconsA
= (void*)GetProcAddress(hmod
, "PrivateExtractIconsA");
34 static void test_LoadStringW(void)
36 HINSTANCE hInst
= GetModuleHandle(NULL
);
37 WCHAR copiedstringw
[128], returnedstringw
[128], *resourcepointer
= NULL
;
38 char copiedstring
[128], returnedstring
[128];
39 int length1
, length2
, retvalue
;
41 /* Check that the string which is returned by LoadStringW matches
42 the string at the pointer returned by LoadStringW when called with buflen = 0 */
43 SetLastError(0xdeadbeef);
44 length1
= LoadStringW(hInst
, 2, (WCHAR
*) &resourcepointer
, 0); /* get pointer to resource. */
47 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
)
48 win_skip( "LoadStringW not implemented\n" );
50 win_skip( "LoadStringW does not return a pointer to the resource\n" );
53 length2
= LoadStringW(hInst
, 2, returnedstringw
, sizeof(returnedstringw
) /sizeof(WCHAR
)); /* get resource string */
54 ok(length2
> 0, "LoadStringW failed to load resource 2, ret %d, err %d\n", length2
, GetLastError());
55 ok(length1
== length2
, "LoadStringW returned different values dependent on buflen. ret1 %d, ret2 %d\n",
57 ok(length1
> 0 && resourcepointer
!= NULL
, "LoadStringW failed to get pointer to resource 2, ret %d, err %d\n",
58 length1
, GetLastError());
60 /* Copy the resource since it is not '\0' terminated, and add '\0' to the end */
61 if(resourcepointer
!= NULL
) /* Check that the resource pointer was loaded to avoid access violation */
63 memcpy(copiedstringw
, resourcepointer
, length1
* sizeof(WCHAR
));
64 copiedstringw
[length1
] = '\0';
65 /* check that strings match */
66 WideCharToMultiByte( CP_ACP
, 0, returnedstringw
, -1, returnedstring
, 128, NULL
, NULL
);
67 WideCharToMultiByte( CP_ACP
, 0, copiedstringw
, -1, copiedstring
, 128, NULL
, NULL
);
68 ok(!memcmp(copiedstringw
, returnedstringw
, (length2
+ 1)*sizeof(WCHAR
)),
69 "strings don't match: returnedstring = %s, copiedstring = %s\n", returnedstring
, copiedstring
);
72 /* check that calling LoadStringW with buffer = NULL returns zero */
73 retvalue
= LoadStringW(hInst
, 2, NULL
, 0);
74 ok(!retvalue
, "LoadStringW returned a non-zero value when called with buffer = NULL, retvalue = %d\n", retvalue
);
75 /* check again, with a different buflen value, that calling LoadStringW with buffer = NULL returns zero */
76 retvalue
= LoadStringW(hInst
, 2, NULL
, 128);
77 ok(!retvalue
, "LoadStringW returned a non-zero value when called with buffer = NULL, retvalue = %d\n", retvalue
);
80 static void test_LoadStringA (void)
82 HINSTANCE hInst
= GetModuleHandle (NULL
);
83 static const char str
[] = "String resource"; /* same in resource.rc */
87 unsigned int expected
;
89 struct string_test tests
[] = {{sizeof buf
, sizeof str
- 1},
90 {sizeof str
, sizeof str
- 1},
91 {sizeof str
- 1, sizeof str
- 2}};
95 assert (sizeof str
< sizeof buf
);
96 for (i
= 0; i
< sizeof tests
/ sizeof tests
[0]; i
++) {
97 const unsigned int bufsiz
= tests
[i
].bufsiz
;
98 const unsigned int expected
= tests
[i
].expected
;
99 const int len
= LoadStringA (hInst
, 0, buf
, bufsiz
);
101 ok (len
== expected
, "bufsiz=%d: got %d, expected %d\n",
102 bufsiz
, len
, expected
);
103 if (len
!= expected
) continue;
104 ok (!memcmp (buf
, str
, len
),
105 "bufsiz=%d: got '%s', expected '%.*s'\n",
106 bufsiz
, buf
, len
, str
);
107 ok (buf
[len
] == 0, "bufsiz=%d: NUL termination missing\n",
111 ret
= LoadStringA(hInst
, 1, buf
, sizeof(buf
) );
112 ok( ret
> 0, "LoadString failed: ret %d err %d\n", ret
, GetLastError());
113 ret2
= LoadStringA( hInst
, MAKELONG( 1, 0x8000 ), buf
, sizeof(buf
));
114 ok( ret2
== ret
, "LoadString failed: ret %d err %d\n", ret
, GetLastError());
115 ret2
= LoadStringA( hInst
, MAKELONG( 1, 0xffff ), buf
, sizeof(buf
));
116 ok( ret2
== ret
, "LoadString failed: ret %d err %d\n", ret
, GetLastError());
118 ret
= LoadStringA(hInst
, 65534, buf
, sizeof(buf
) );
119 ok( ret
> 0, "LoadString failed: ret %d err %d\n", ret
, GetLastError());
120 ret2
= LoadStringA( hInst
, MAKELONG( 65534, 0x8000 ), buf
, sizeof(buf
));
121 ok( ret2
== ret
, "LoadString failed: ret %d err %d\n", ret
, GetLastError());
122 ret2
= LoadStringA( hInst
, MAKELONG( 65534, 0xffff ), buf
, sizeof(buf
));
123 ok( ret2
== ret
, "LoadString failed: ret %d err %d\n", ret
, GetLastError());
125 ret
= LoadStringA(hInst
, 0, buf
, 0);
126 ok( ret
== -1 || broken(ret
== 0),
127 "LoadStringA did not return -1 when called with buflen = 0, got %d, err %d\n",
128 ret
, GetLastError());
131 static void test_accel1(void)
137 /* now create our own valid accelerator table */
141 ac
[n
++].fVirt
= FVIRTKEY
| FNOINVERT
;
145 ac
[n
++].fVirt
= FNOINVERT
;
151 hAccel
= CreateAcceleratorTable( &ac
[0], n
);
152 ok( hAccel
!= NULL
, "create accelerator table\n");
154 r
= DestroyAcceleratorTable( hAccel
);
155 ok( r
, "destroy accelerator table\n");
157 /* now try create an invalid one */
161 ac
[n
++].fVirt
= FVIRTKEY
| FNOINVERT
;
165 ac
[n
++].fVirt
= (SHORT
) 0xffff;
169 ac
[n
++].fVirt
= (SHORT
) 0xfff0;
173 ac
[n
++].fVirt
= 0x0000;
177 ac
[n
++].fVirt
= 0x0001;
179 hAccel
= CreateAcceleratorTable( &ac
[0], n
);
180 ok( hAccel
!= NULL
, "create accelerator table\n");
182 r
= CopyAcceleratorTable( hAccel
, NULL
, 0 );
183 ok( r
== n
, "two entries in table %u/%u\n", r
, n
);
185 r
= CopyAcceleratorTable( hAccel
, &ac
[0], n
);
186 ok( r
== n
, "still should be two entries in table %u/%u\n", r
, n
);
189 ok( ac
[n
].cmd
== 1000, "cmd 0 not preserved got %x\n", ac
[n
].cmd
);
190 ok( ac
[n
].key
== 'A', "key 0 not preserved got %x\n", ac
[n
].key
);
191 ok( ac
[n
].fVirt
== (FVIRTKEY
| FNOINVERT
), "fVirt 0 not preserved got %x\n", ac
[n
].fVirt
);
193 if (++n
== r
) goto done
;
194 ok( ac
[n
].cmd
== 0xffff, "cmd 1 not preserved got %x\n", ac
[n
].cmd
);
195 ok( ac
[n
].key
== 0xffff, "key 1 not preserved got %x\n", ac
[n
].key
);
196 ok( ac
[n
].fVirt
== 0x007f, "fVirt 1 wrong got %x\n", ac
[n
].fVirt
);
198 if (++n
== r
) goto done
;
199 ok( ac
[n
].cmd
== 0xfff0, "cmd 2 not preserved got %x\n", ac
[n
].cmd
);
200 ok( (ac
[n
].key
& 0xff) == 0xff, "key 2 not preserved got %x\n", ac
[n
].key
);
201 ok( ac
[n
].fVirt
== 0x0070, "fVirt 2 wrong got %x\n", ac
[n
].fVirt
);
203 if (++n
== r
) goto done
;
204 ok( ac
[n
].cmd
== 0xfff0, "cmd 3 not preserved got %x\n", ac
[n
].cmd
);
205 ok( (ac
[n
].key
& 0xff) == 0xff, "key 3 not preserved got %x\n", ac
[n
].key
);
206 ok( ac
[n
].fVirt
== 0x0000, "fVirt 3 wrong got %x\n", ac
[n
].fVirt
);
208 if (++n
== r
) goto done
;
209 ok( ac
[n
].cmd
== 0xfff0, "cmd 4 not preserved got %x\n", ac
[n
].cmd
);
210 ok( ac
[n
].key
== 0xffff, "key 4 not preserved got %x\n", ac
[n
].key
);
211 ok( ac
[n
].fVirt
== 0x0001, "fVirt 4 wrong got %x\n", ac
[n
].fVirt
);
213 r
= DestroyAcceleratorTable( hAccel
);
214 ok( r
, "destroy accelerator table\n");
216 hAccel
= CreateAcceleratorTable( &ac
[0], 0 );
217 ok( !hAccel
|| broken(hAccel
!= NULL
), /* nt4 */ "zero elements should fail\n");
219 /* these will on crash win2k
220 hAccel = CreateAcceleratorTable( NULL, 1 );
221 hAccel = CreateAcceleratorTable( &ac[0], -1 );
226 * memcmp on the tables works in Windows, but does not work in wine, as
227 * there is an extra undefined and unused byte between fVirt and the key
229 static void test_accel2(void)
245 * hac = CreateAcceleratorTable( NULL, 1 );
248 /* try a zero count */
249 hac
= CreateAcceleratorTable( &ac
[0], 0 );
250 ok( !hac
|| broken(hac
!= NULL
), /* nt4 */ "fail\n");
251 if (!hac
) ok( !DestroyAcceleratorTable( hac
), "destroy failed\n");
253 /* creating one accelerator should work */
254 hac
= CreateAcceleratorTable( &ac
[0], 1 );
255 ok( hac
!= NULL
, "fail\n");
256 ok( 1 == CopyAcceleratorTable( hac
, out
, 1 ), "copy failed\n");
257 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
259 /* how about two of the same type? */
260 hac
= CreateAcceleratorTable( &ac
[0], 2);
261 ok( hac
!= NULL
, "fail\n");
262 res
= CopyAcceleratorTable( hac
, NULL
, 100 );
263 ok( res
== 2, "copy null failed %d\n", res
);
264 res
= CopyAcceleratorTable( hac
, NULL
, 0 );
265 ok( res
== 2, "copy null failed %d\n", res
);
266 res
= CopyAcceleratorTable( hac
, NULL
, 1 );
267 ok( res
== 2, "copy null failed %d\n", res
);
268 ok( 1 == CopyAcceleratorTable( hac
, out
, 1 ), "copy 1 failed\n");
269 ok( 2 == CopyAcceleratorTable( hac
, out
, 2 ), "copy 2 failed\n");
270 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
271 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
273 /* how about two of the same type with a non-zero key? */
276 hac
= CreateAcceleratorTable( &ac
[0], 2);
277 ok( hac
!= NULL
, "fail\n");
278 ok( 2 == CopyAcceleratorTable( hac
, out
, 2 ), "copy 2 failed\n");
279 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
280 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
282 /* how about two of the same type with a non-zero virtual key? */
283 ac
[0].fVirt
= FVIRTKEY
;
285 ac
[1].fVirt
= FVIRTKEY
;
287 hac
= CreateAcceleratorTable( &ac
[0], 2);
288 ok( hac
!= NULL
, "fail\n");
289 ok( 2 == CopyAcceleratorTable( hac
, out
, 2 ), "copy 2 failed\n");
290 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
291 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
293 /* how virtual key codes */
294 ac
[0].fVirt
= FVIRTKEY
;
295 hac
= CreateAcceleratorTable( &ac
[0], 1);
296 ok( hac
!= NULL
, "fail\n");
297 ok( 1 == CopyAcceleratorTable( hac
, out
, 2 ), "copy 2 failed\n");
298 /* ok( !memcmp( ac, out, sizeof ac/2 ), "tables different\n"); */
299 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
301 /* how turning on all bits? */
305 hac
= CreateAcceleratorTable( &ac
[0], 1);
306 ok( hac
!= NULL
, "fail\n");
307 ok( 1 == CopyAcceleratorTable( hac
, out
, 1 ), "copy 1 failed\n");
308 /* ok( memcmp( ac, out, sizeof ac/2 ), "tables not different\n"); */
309 ok( out
[0].cmd
== ac
[0].cmd
, "cmd modified\n");
310 ok( out
[0].fVirt
== (ac
[0].fVirt
&0x7f), "fVirt not modified\n");
311 ok( out
[0].key
== ac
[0].key
, "key modified\n");
312 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
314 /* how turning on all bits? */
315 memset( ac
, 0xff, sizeof ac
);
316 hac
= CreateAcceleratorTable( &ac
[0], 2);
317 ok( hac
!= NULL
, "fail\n");
318 res
= CopyAcceleratorTable( hac
, out
, 2 );
319 ok( res
== 2, "copy 2 failed %d\n", res
);
320 /* ok( memcmp( ac, out, sizeof ac ), "tables not different\n"); */
321 ok( out
[0].cmd
== ac
[0].cmd
, "cmd modified\n");
322 ok( out
[0].fVirt
== (ac
[0].fVirt
&0x7f), "fVirt not modified\n");
323 ok( out
[0].key
== ac
[0].key
, "key modified\n");
326 ok( out
[1].cmd
== ac
[1].cmd
, "cmd modified\n");
327 ok( out
[1].fVirt
== (ac
[1].fVirt
&0x7f), "fVirt not modified\n");
328 ok( out
[1].key
== ac
[1].key
, "key modified\n");
330 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
333 static void test_PrivateExtractIcons(void) {
334 CONST CHAR szShell32Dll
[] = "shell32.dll";
337 UINT cIcons
, cIcons2
;
339 if (!pPrivateExtractIconsA
) return;
341 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, NULL
, NULL
, 0, 0);
342 cIcons2
= pPrivateExtractIconsA(szShell32Dll
, 4, MAKELONG(32,16), MAKELONG(32,16),
344 ok((cIcons
== cIcons2
) && (cIcons
> 0),
345 "Icon count should be independent of requested icon sizes and base icon index! "
346 "(cIcons=%d, cIcons2=%d)\n", cIcons
, cIcons2
);
348 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, ahIcon
, aIconId
, 0, 0);
349 ok(cIcons
== 0, "Zero icons requested, got cIcons=%d\n", cIcons
);
351 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, ahIcon
, aIconId
, 3, 0);
352 ok(cIcons
== 3, "Three icons requested got cIcons=%d\n", cIcons
);
354 /* count must be a multiple of two when getting two sizes */
355 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, MAKELONG(16,32), MAKELONG(16,32),
356 ahIcon
, aIconId
, 3, 0);
357 ok(cIcons
== 0 /* vista */ || cIcons
== 4, "Three icons requested got cIcons=%d\n", cIcons
);
358 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, MAKELONG(16,32), MAKELONG(16,32),
359 ahIcon
, aIconId
, 4, 0);
360 ok(cIcons
== 4, "Four icons requested got cIcons=%d\n", cIcons
);
363 static void test_LoadImage(void)
368 bmp
= LoadBitmapA(GetModuleHandle(NULL
), MAKEINTRESOURCE(100));
369 ok(bmp
!= NULL
, "Could not load a bitmap resource\n");
370 if (bmp
) DeleteObject(bmp
);
372 hres
= FindResource(GetModuleHandle(NULL
), "#100", RT_BITMAP
);
373 ok(hres
!= NULL
, "Could not find a bitmap resource with a numeric string\n");
375 bmp
= LoadBitmapA(GetModuleHandle(NULL
), "#100");
376 ok(bmp
!= NULL
, "Could not load a bitmap resource with a numeric string\n");
377 if (bmp
) DeleteObject(bmp
);
382 init_function_pointers();
387 test_PrivateExtractIcons();