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 ok( LoadStringA( hInst
, MAKELONG( 1, 0x8000 ), buf
, sizeof(buf
)) == ret
,
114 "LoadString failed: ret %d err %d\n", ret
, GetLastError());
115 ok( LoadStringA( hInst
, MAKELONG( 1, 0xffff ), buf
, sizeof(buf
)) == ret
,
116 "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 ok( LoadStringA( hInst
, MAKELONG( 65534, 0x8000 ), buf
, sizeof(buf
)) == ret
,
121 "LoadString failed: ret %d err %d\n", ret
, GetLastError());
122 ok( LoadStringA( hInst
, MAKELONG( 65534, 0xffff ), buf
, sizeof(buf
)) == ret
,
123 "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
= (SHORT
) 0x0000;
177 ac
[n
++].fVirt
= (SHORT
) 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
|| broken(r
== 2), /* win9x */
184 "two entries in table %u/%u\n", r
, n
);
186 r
= CopyAcceleratorTable( hAccel
, &ac
[0], n
);
187 ok( r
== n
|| broken(r
== 2), /* win9x */
188 "still should be two entries in table %u/%u\n", r
, n
);
191 ok( ac
[n
].cmd
== 1000, "cmd 0 not preserved got %x\n", ac
[n
].cmd
);
192 ok( ac
[n
].key
== 'A', "key 0 not preserved got %x\n", ac
[n
].key
);
193 ok( ac
[n
].fVirt
== (FVIRTKEY
| FNOINVERT
), "fVirt 0 not preserved got %x\n", ac
[n
].fVirt
);
195 if (++n
== r
) goto done
;
196 ok( ac
[n
].cmd
== 0xffff, "cmd 1 not preserved got %x\n", ac
[n
].cmd
);
197 ok( ac
[n
].key
== 0xffff, "key 1 not preserved got %x\n", ac
[n
].key
);
198 ok( ac
[n
].fVirt
== 0x007f, "fVirt 1 wrong got %x\n", ac
[n
].fVirt
);
200 if (++n
== r
) goto done
;
201 ok( ac
[n
].cmd
== 0xfff0, "cmd 2 not preserved got %x\n", ac
[n
].cmd
);
202 ok( (ac
[n
].key
& 0xff) == 0xff, "key 2 not preserved got %x\n", ac
[n
].key
);
203 ok( ac
[n
].fVirt
== 0x0070, "fVirt 2 wrong got %x\n", ac
[n
].fVirt
);
205 if (++n
== r
) goto done
;
206 ok( ac
[n
].cmd
== 0xfff0, "cmd 3 not preserved got %x\n", ac
[n
].cmd
);
207 ok( (ac
[n
].key
& 0xff) == 0xff, "key 3 not preserved got %x\n", ac
[n
].key
);
208 ok( ac
[n
].fVirt
== 0x0000, "fVirt 3 wrong got %x\n", ac
[n
].fVirt
);
210 if (++n
== r
) goto done
;
211 ok( ac
[n
].cmd
== 0xfff0, "cmd 4 not preserved got %x\n", ac
[n
].cmd
);
212 ok( ac
[n
].key
== 0xffff, "key 4 not preserved got %x\n", ac
[n
].key
);
213 ok( ac
[n
].fVirt
== 0x0001, "fVirt 4 wrong got %x\n", ac
[n
].fVirt
);
215 r
= DestroyAcceleratorTable( hAccel
);
216 ok( r
, "destroy accelerator table\n");
218 hAccel
= CreateAcceleratorTable( &ac
[0], 0 );
219 ok( !hAccel
|| broken(hAccel
!= NULL
), /* nt4 */ "zero elements should fail\n");
221 /* these will on crash win2k
222 hAccel = CreateAcceleratorTable( NULL, 1 );
223 hAccel = CreateAcceleratorTable( &ac[0], -1 );
228 * memcmp on the tables works in Windows, but does not work in wine, as
229 * there is an extra undefined and unused byte between fVirt and the key
231 static void test_accel2(void)
247 * hac = CreateAcceleratorTable( NULL, 1 );
250 /* try a zero count */
251 hac
= CreateAcceleratorTable( &ac
[0], 0 );
252 ok( !hac
|| broken(hac
!= NULL
), /* nt4 */ "fail\n");
253 if (!hac
) ok( !DestroyAcceleratorTable( hac
), "destroy failed\n");
255 /* creating one accelerator should work */
256 hac
= CreateAcceleratorTable( &ac
[0], 1 );
257 ok( hac
!= NULL
, "fail\n");
258 ok( 1 == CopyAcceleratorTable( hac
, out
, 1 ), "copy failed\n");
259 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
261 /* how about two of the same type? */
262 hac
= CreateAcceleratorTable( &ac
[0], 2);
263 ok( hac
!= NULL
, "fail\n");
264 res
= CopyAcceleratorTable( hac
, NULL
, 100 );
265 ok( res
== 2 || broken(res
== 0), /* win9x */ "copy null failed %d\n", res
);
266 res
= CopyAcceleratorTable( hac
, NULL
, 0 );
267 ok( res
== 2, "copy null failed %d\n", res
);
268 res
= CopyAcceleratorTable( hac
, NULL
, 1 );
269 ok( res
== 2 || broken(res
== 0), /* win9x */ "copy null failed %d\n", res
);
270 ok( 1 == CopyAcceleratorTable( hac
, out
, 1 ), "copy 1 failed\n");
271 ok( 2 == CopyAcceleratorTable( hac
, out
, 2 ), "copy 2 failed\n");
272 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
273 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
275 /* how about two of the same type with a non-zero key? */
278 hac
= CreateAcceleratorTable( &ac
[0], 2);
279 ok( hac
!= NULL
, "fail\n");
280 ok( 2 == CopyAcceleratorTable( hac
, out
, 2 ), "copy 2 failed\n");
281 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
282 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
284 /* how about two of the same type with a non-zero virtual key? */
285 ac
[0].fVirt
= FVIRTKEY
;
287 ac
[1].fVirt
= FVIRTKEY
;
289 hac
= CreateAcceleratorTable( &ac
[0], 2);
290 ok( hac
!= NULL
, "fail\n");
291 ok( 2 == CopyAcceleratorTable( hac
, out
, 2 ), "copy 2 failed\n");
292 /* ok( !memcmp( ac, out, sizeof ac ), "tables different\n"); */
293 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
295 /* how virtual key codes */
296 ac
[0].fVirt
= FVIRTKEY
;
297 hac
= CreateAcceleratorTable( &ac
[0], 1);
298 ok( hac
!= NULL
, "fail\n");
299 ok( 1 == CopyAcceleratorTable( hac
, out
, 2 ), "copy 2 failed\n");
300 /* ok( !memcmp( ac, out, sizeof ac/2 ), "tables different\n"); */
301 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
303 /* how turning on all bits? */
307 hac
= CreateAcceleratorTable( &ac
[0], 1);
308 ok( hac
!= NULL
, "fail\n");
309 ok( 1 == CopyAcceleratorTable( hac
, out
, 1 ), "copy 1 failed\n");
310 /* ok( memcmp( ac, out, sizeof ac/2 ), "tables not different\n"); */
311 ok( out
[0].cmd
== ac
[0].cmd
, "cmd modified\n");
312 ok( out
[0].fVirt
== (ac
[0].fVirt
&0x7f), "fVirt not modified\n");
313 ok( out
[0].key
== ac
[0].key
, "key modified\n");
314 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
316 /* how turning on all bits? */
317 memset( ac
, 0xff, sizeof ac
);
318 hac
= CreateAcceleratorTable( &ac
[0], 2);
319 ok( hac
!= NULL
, "fail\n");
320 res
= CopyAcceleratorTable( hac
, out
, 2 );
321 ok( res
== 2 || broken(res
== 1), /* win9x */ "copy 2 failed %d\n", res
);
322 /* ok( memcmp( ac, out, sizeof ac ), "tables not different\n"); */
323 ok( out
[0].cmd
== ac
[0].cmd
, "cmd modified\n");
324 ok( out
[0].fVirt
== (ac
[0].fVirt
&0x7f), "fVirt not modified\n");
325 ok( out
[0].key
== ac
[0].key
, "key modified\n");
328 ok( out
[1].cmd
== ac
[1].cmd
, "cmd modified\n");
329 ok( out
[1].fVirt
== (ac
[1].fVirt
&0x7f), "fVirt not modified\n");
330 ok( out
[1].key
== ac
[1].key
, "key modified\n");
332 ok( DestroyAcceleratorTable( hac
), "destroy failed\n");
335 static void test_PrivateExtractIcons(void) {
336 CONST CHAR szShell32Dll
[] = "shell32.dll";
339 UINT cIcons
, cIcons2
;
341 if (!pPrivateExtractIconsA
) return;
343 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, NULL
, NULL
, 0, 0);
344 cIcons2
= pPrivateExtractIconsA(szShell32Dll
, 4, MAKELONG(32,16), MAKELONG(32,16),
346 ok((cIcons
== cIcons2
) && (cIcons
> 0),
347 "Icon count should be independent of requested icon sizes and base icon index! "
348 "(cIcons=%d, cIcons2=%d)\n", cIcons
, cIcons2
);
350 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, ahIcon
, aIconId
, 0, 0);
351 ok(cIcons
== 0, "Zero icons requested, got cIcons=%d\n", cIcons
);
353 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, 16, 16, ahIcon
, aIconId
, 3, 0);
354 ok(cIcons
== 3, "Three icons requested got cIcons=%d\n", cIcons
);
356 /* count must be a multiple of two when getting two sizes */
357 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, MAKELONG(16,32), MAKELONG(16,32),
358 ahIcon
, aIconId
, 3, 0);
359 ok(cIcons
== 0 /* vista */ || cIcons
== 4, "Three icons requested got cIcons=%d\n", cIcons
);
360 cIcons
= pPrivateExtractIconsA(szShell32Dll
, 0, MAKELONG(16,32), MAKELONG(16,32),
361 ahIcon
, aIconId
, 4, 0);
362 ok(cIcons
== 4, "Four icons requested got cIcons=%d\n", cIcons
);
365 static void test_LoadImage(void)
370 bmp
= LoadBitmapA(GetModuleHandle(NULL
), MAKEINTRESOURCE(100));
371 ok(bmp
!= NULL
, "Could not load a bitmap resource\n");
372 if (bmp
) DeleteObject(bmp
);
374 hres
= FindResource(GetModuleHandle(NULL
), "#100", RT_BITMAP
);
375 ok(hres
!= NULL
, "Could not find a bitmap resource with a numeric string\n");
377 bmp
= LoadBitmapA(GetModuleHandle(NULL
), "#100");
378 ok(bmp
!= NULL
, "Could not load a bitmap resource with a numeric string\n");
379 if (bmp
) DeleteObject(bmp
);
384 init_function_pointers();
389 test_PrivateExtractIcons();