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
)(LPCSTR
, 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
= GetModuleHandleA(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
= GetModuleHandleA(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());
130 SetLastError(0xdeadbeef);
132 ret
= LoadStringA(hInst
, 1, buf
, 1);
133 ok( !ret
, "LoadString returned %d\n", ret
);
134 ok( buf
[0] == 0, "buf[0] = %c (%x)\n", buf
[0], buf
[0]);
135 ok( GetLastError() == 0xdeadbeef, "GetLastError() = %d\n", GetLastError());
138 static void test_accel1(void)
144 /* now create our own valid accelerator table */
148 ac
[n
++].fVirt
= FVIRTKEY
| FNOINVERT
;
152 ac
[n
++].fVirt
= FNOINVERT
;
158 hAccel
= CreateAcceleratorTableA( &ac
[0], n
);
159 ok( hAccel
!= NULL
, "create accelerator table\n");
161 r
= DestroyAcceleratorTable( hAccel
);
162 ok( r
, "destroy accelerator table\n");
164 /* now try create an invalid one */
168 ac
[n
++].fVirt
= FVIRTKEY
| FNOINVERT
;
172 ac
[n
++].fVirt
= (SHORT
) 0xffff;
176 ac
[n
++].fVirt
= (SHORT
) 0xfff0;
180 ac
[n
++].fVirt
= 0x0000;
184 ac
[n
++].fVirt
= 0x0001;
186 hAccel
= CreateAcceleratorTableA( &ac
[0], n
);
187 ok( hAccel
!= NULL
, "create accelerator table\n");
189 r
= CopyAcceleratorTableA( hAccel
, NULL
, 0 );
190 ok( r
== n
, "two entries in table %u/%u\n", r
, n
);
192 r
= CopyAcceleratorTableA( hAccel
, &ac
[0], n
);
193 ok( r
== n
, "still should be two entries in table %u/%u\n", r
, n
);
196 ok( ac
[n
].cmd
== 1000, "cmd 0 not preserved got %x\n", ac
[n
].cmd
);
197 ok( ac
[n
].key
== 'A', "key 0 not preserved got %x\n", ac
[n
].key
);
198 ok( ac
[n
].fVirt
== (FVIRTKEY
| FNOINVERT
), "fVirt 0 not preserved got %x\n", ac
[n
].fVirt
);
200 if (++n
== r
) goto done
;
201 ok( ac
[n
].cmd
== 0xffff, "cmd 1 not preserved got %x\n", ac
[n
].cmd
);
202 ok( ac
[n
].key
== 0xffff, "key 1 not preserved got %x\n", ac
[n
].key
);
203 ok( ac
[n
].fVirt
== 0x007f, "fVirt 1 wrong got %x\n", ac
[n
].fVirt
);
205 if (++n
== r
) goto done
;
206 ok( ac
[n
].cmd
== 0xfff0, "cmd 2 not preserved got %x\n", ac
[n
].cmd
);
207 ok( (ac
[n
].key
& 0xff) == 0xff, "key 2 not preserved got %x\n", ac
[n
].key
);
208 ok( ac
[n
].fVirt
== 0x0070, "fVirt 2 wrong got %x\n", ac
[n
].fVirt
);
210 if (++n
== r
) goto done
;
211 ok( ac
[n
].cmd
== 0xfff0, "cmd 3 not preserved got %x\n", ac
[n
].cmd
);
212 ok( (ac
[n
].key
& 0xff) == 0xff, "key 3 not preserved got %x\n", ac
[n
].key
);
213 ok( ac
[n
].fVirt
== 0x0000, "fVirt 3 wrong got %x\n", ac
[n
].fVirt
);
215 if (++n
== r
) goto done
;
216 ok( ac
[n
].cmd
== 0xfff0, "cmd 4 not preserved got %x\n", ac
[n
].cmd
);
217 ok( ac
[n
].key
== 0xffff, "key 4 not preserved got %x\n", ac
[n
].key
);
218 ok( ac
[n
].fVirt
== 0x0001, "fVirt 4 wrong got %x\n", ac
[n
].fVirt
);
220 r
= DestroyAcceleratorTable( hAccel
);
221 ok( r
, "destroy accelerator table\n");
223 hAccel
= CreateAcceleratorTableA( &ac
[0], 0 );
224 ok( !hAccel
|| broken(hAccel
!= NULL
), /* nt4 */ "zero elements should fail\n");
226 /* these will on crash win2k
227 hAccel = CreateAcceleratorTable( NULL, 1 );
228 hAccel = CreateAcceleratorTable( &ac[0], -1 );
233 * memcmp on the tables works in Windows, but does not work in wine, as
234 * there is an extra undefined and unused byte between fVirt and the key
236 static void test_accel2(void)
252 * hac = CreateAcceleratorTable( NULL, 1 );
255 /* try a zero count */
256 hac
= CreateAcceleratorTableA( &ac
[0], 0 );
257 ok( !hac
|| broken(hac
!= NULL
), /* nt4 */ "fail\n");
258 if (!hac
) ok( !DestroyAcceleratorTable( hac
), "destroy failed\n");
260 /* creating one accelerator should work */
261 hac
= CreateAcceleratorTableA( &ac
[0], 1 );
262 ok( hac
!= NULL
, "fail\n");
263 ok( 1 == CopyAcceleratorTableA( hac
, out
, 1 ), "copy failed\n");
264 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
266 /* how about two of the same type? */
267 hac
= CreateAcceleratorTableA( &ac
[0], 2);
268 ok( hac
!= NULL
, "fail\n");
269 res
= CopyAcceleratorTableA( hac
, NULL
, 100 );
270 ok( res
== 2, "copy null failed %d\n", res
);
271 res
= CopyAcceleratorTableA( hac
, NULL
, 0 );
272 ok( res
== 2, "copy null failed %d\n", res
);
273 res
= CopyAcceleratorTableA( hac
, NULL
, 1 );
274 ok( res
== 2, "copy null failed %d\n", res
);
275 ok( 1 == CopyAcceleratorTableA( hac
, out
, 1 ), "copy 1 failed\n");
276 ok( 2 == CopyAcceleratorTableA( hac
, out
, 2 ), "copy 2 failed\n");
277 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
278 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
280 /* how about two of the same type with a non-zero key? */
283 hac
= CreateAcceleratorTableA( &ac
[0], 2);
284 ok( hac
!= NULL
, "fail\n");
285 ok( 2 == CopyAcceleratorTableA( hac
, out
, 2 ), "copy 2 failed\n");
286 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
287 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
289 /* how about two of the same type with a non-zero virtual key? */
290 ac
[0].fVirt
= FVIRTKEY
;
292 ac
[1].fVirt
= FVIRTKEY
;
294 hac
= CreateAcceleratorTableA( &ac
[0], 2);
295 ok( hac
!= NULL
, "fail\n");
296 ok( 2 == CopyAcceleratorTableA( hac
, out
, 2 ), "copy 2 failed\n");
297 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
298 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
300 /* how virtual key codes */
301 ac
[0].fVirt
= FVIRTKEY
;
302 hac
= CreateAcceleratorTableA( &ac
[0], 1);
303 ok( hac
!= NULL
, "fail\n");
304 ok( 1 == CopyAcceleratorTableA( hac
, out
, 2 ), "copy 2 failed\n");
305 /* ok( !memcmp( ac, out, sizeof ac/2 ), "tables different\n"); */
306 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
308 /* how turning on all bits? */
312 hac
= CreateAcceleratorTableA( &ac
[0], 1);
313 ok( hac
!= NULL
, "fail\n");
314 ok( 1 == CopyAcceleratorTableA( hac
, out
, 1 ), "copy 1 failed\n");
315 /* ok( memcmp( ac, out, sizeof ac/2 ), "tables not different\n"); */
316 ok( out
[0].cmd
== ac
[0].cmd
, "cmd modified\n");
317 ok( out
[0].fVirt
== (ac
[0].fVirt
&0x7f), "fVirt not modified\n");
318 ok( out
[0].key
== ac
[0].key
, "key modified\n");
319 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
321 /* how turning on all bits? */
322 memset( ac
, 0xff, sizeof ac
);
323 hac
= CreateAcceleratorTableA( &ac
[0], 2);
324 ok( hac
!= NULL
, "fail\n");
325 res
= CopyAcceleratorTableA( hac
, out
, 2 );
326 ok( res
== 2, "copy 2 failed %d\n", res
);
327 /* ok( memcmp( ac, out, sizeof ac ), "tables not different\n"); */
328 ok( out
[0].cmd
== ac
[0].cmd
, "cmd modified\n");
329 ok( out
[0].fVirt
== (ac
[0].fVirt
&0x7f), "fVirt not modified\n");
330 ok( out
[0].key
== ac
[0].key
, "key modified\n");
333 ok( out
[1].cmd
== ac
[1].cmd
, "cmd modified\n");
334 ok( out
[1].fVirt
== (ac
[1].fVirt
&0x7f), "fVirt not modified\n");
335 ok( out
[1].key
== ac
[1].key
, "key modified\n");
337 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
340 static void test_PrivateExtractIcons(void) {
341 const CHAR szShell32Dll
[] = "shell32.dll";
343 UINT i
, aIconId
[256], cIcons
, cIcons2
;
345 if (!pPrivateExtractIconsA
) return;
347 cIcons
= pPrivateExtractIconsA("", 0, 16, 16, ahIcon
, aIconId
, 1, 0);
348 ok(cIcons
== ~0u, "got %u\n", cIcons
);
350 cIcons
= pPrivateExtractIconsA("notepad.exe", 0, 16, 16, NULL
, NULL
, 1, 0);
351 ok(cIcons
== 1 || broken(cIcons
== 2) /* win2k */, "got %u\n", cIcons
);
353 ahIcon
[0] = (HICON
)0xdeadbeef;
354 cIcons
= pPrivateExtractIconsA("notepad.exe", 0, 16, 16, ahIcon
, NULL
, 1, 0);
355 ok(cIcons
== 1, "got %u\n", cIcons
);
356 ok(ahIcon
[0] != (HICON
)0xdeadbeef, "icon not set\n");
357 DestroyIcon(ahIcon
[0]);
359 ahIcon
[0] = (HICON
)0xdeadbeef;
360 aIconId
[0] = 0xdeadbeef;
361 cIcons
= pPrivateExtractIconsA("notepad.exe", 0, 16, 16, ahIcon
, aIconId
, 1, 0);
362 ok(cIcons
== 1, "got %u\n", cIcons
);
363 ok(ahIcon
[0] != (HICON
)0xdeadbeef, "icon not set\n");
364 ok(aIconId
[0] != 0xdeadbeef, "id not set\n");
365 DestroyIcon(ahIcon
[0]);
367 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, NULL
, NULL
, 0, 0);
368 cIcons2
= pPrivateExtractIconsA(szShell32Dll
, 4, MAKELONG(32,16), MAKELONG(32,16),
370 ok((cIcons
== cIcons2
) && (cIcons
> 0),
371 "Icon count should be independent of requested icon sizes and base icon index! "
372 "(cIcons=%d, cIcons2=%d)\n", cIcons
, cIcons2
);
374 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, ahIcon
, aIconId
, 0, 0);
375 ok(cIcons
== 0, "Zero icons requested, got cIcons=%d\n", cIcons
);
377 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, ahIcon
, aIconId
, 3, 0);
378 ok(cIcons
== 3, "Three icons requested got cIcons=%d\n", cIcons
);
379 for (i
= 0; i
< cIcons
; i
++) DestroyIcon(ahIcon
[i
]);
381 /* count must be a multiple of two when getting two sizes */
382 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, MAKELONG(16,32), MAKELONG(16,32),
383 ahIcon
, aIconId
, 3, 0);
384 ok(cIcons
== 0 /* vista */ || cIcons
== 4, "Three icons requested got cIcons=%d\n", cIcons
);
385 for (i
= 0; i
< cIcons
; i
++) DestroyIcon(ahIcon
[i
]);
387 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, MAKELONG(16,32), MAKELONG(16,32),
388 ahIcon
, aIconId
, 4, 0);
389 ok(cIcons
== 4, "Four icons requested got cIcons=%d\n", cIcons
);
390 for (i
= 0; i
< cIcons
; i
++) DestroyIcon(ahIcon
[i
]);
393 static void test_LoadImage(void)
398 bmp
= LoadBitmapA(GetModuleHandleA(NULL
), MAKEINTRESOURCEA(100));
399 ok(bmp
!= NULL
, "Could not load a bitmap resource\n");
400 if (bmp
) DeleteObject(bmp
);
402 hres
= FindResourceA(GetModuleHandleA(NULL
), "#100", (LPCSTR
)RT_BITMAP
);
403 ok(hres
!= NULL
, "Could not find a bitmap resource with a numeric string\n");
405 bmp
= LoadBitmapA(GetModuleHandleA(NULL
), "#100");
406 ok(bmp
!= NULL
, "Could not load a bitmap resource with a numeric string\n");
407 if (bmp
) DeleteObject(bmp
);
412 init_function_pointers();
417 test_PrivateExtractIcons();