wer: Add new stubbed wer.dll.
[wine/hramrach.git] / dlls / comctl32 / tests / imagelist.c
blobc5ea95f5124b598baa6af3a11a7ebe3e39b4d1c9
1 /*
2 * Unit test suite for imagelist control.
4 * Copyright 2004 Michael Stefaniuc
5 * Copyright 2002 Mike McCormack for CodeWeavers
6 * Copyright 2007 Dmitry Timoshkov
7 * Copyright 2009 Owen Rudge for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define COBJMACROS
25 #define CONST_VTABLE
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <assert.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "objbase.h"
36 #include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
37 #include "initguid.h"
38 #include "commoncontrols.h"
39 #include "shellapi.h"
41 #include "wine/test.h"
42 #include "v6util.h"
44 #undef VISIBLE
46 #ifdef VISIBLE
47 #define WAIT Sleep (1000)
48 #define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW)
49 #else
50 #define WAIT
51 #define REDRAW(hwnd)
52 #endif
54 #define IMAGELIST_MAGIC (('L' << 8) | 'I')
56 #include "pshpack2.h"
57 /* Header used by ImageList_Read() and ImageList_Write() */
58 typedef struct _ILHEAD
60 USHORT usMagic;
61 USHORT usVersion;
62 WORD cCurImage;
63 WORD cMaxImage;
64 WORD cGrow;
65 WORD cx;
66 WORD cy;
67 COLORREF bkcolor;
68 WORD flags;
69 SHORT ovls[4];
70 } ILHEAD;
71 #include "poppack.h"
73 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
74 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
75 static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
76 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
77 static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
78 REFIID,void **);
79 static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
81 static HINSTANCE hinst;
83 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
84 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
85 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
86 #define ROW32(a,b,c,d,e,f,g,h) ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h), \
87 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
88 #define ROW2(a,b,c,d,e,f,g,h,i,j,k,l) ROW1(a,b,c,d,e,f,g,h),B(i,j),B(k,l)
89 #define ROW48(a,b,c,d,e,f,g,h,i,j,k,l) ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \
90 ROW2(a,b,c,d,e,f,g,h,i,j,k,l), ROW2(a,b,c,d,e,f,g,h,i,j,k,l), \
91 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
93 static const BYTE empty_bits[48*48/8];
95 static const BYTE icon_bits[32*32/8] =
97 ROW32(0,0,0,0,0,0,0,0),
98 ROW32(0,0,1,1,1,1,0,0),
99 ROW32(0,1,1,1,1,1,1,0),
100 ROW32(0,1,1,0,0,1,1,0),
101 ROW32(0,1,1,0,0,1,1,0),
102 ROW32(0,1,1,1,1,1,1,0),
103 ROW32(0,0,1,1,1,1,0,0),
104 ROW32(0,0,0,0,0,0,0,0)
107 static const BYTE bitmap_bits[48*48/8] =
109 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
110 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
111 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
112 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
113 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
114 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
115 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
116 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
117 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
118 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
119 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
120 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
123 static HIMAGELIST createImageList(int cx, int cy)
125 /* Create an ImageList and put an image into it */
126 HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1);
127 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
128 ImageList_Add(himl, hbm, NULL);
129 DeleteObject(hbm);
130 return himl;
133 static HWND create_a_window(void)
135 char className[] = "bmwnd";
136 char winName[] = "Test Bitmap";
137 HWND hWnd;
138 static int registered = 0;
140 if (!registered)
142 WNDCLASSA cls;
144 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
145 cls.lpfnWndProc = DefWindowProcA;
146 cls.cbClsExtra = 0;
147 cls.cbWndExtra = 0;
148 cls.hInstance = 0;
149 cls.hIcon = LoadIconA (0, IDI_APPLICATION);
150 cls.hCursor = LoadCursorA (0, IDC_ARROW);
151 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
152 cls.lpszMenuName = 0;
153 cls.lpszClassName = className;
155 RegisterClassA (&cls);
156 registered = 1;
159 /* Setup window */
160 hWnd = CreateWindowA (className, winName,
161 WS_OVERLAPPEDWINDOW ,
162 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
163 0, hinst, 0);
165 #ifdef VISIBLE
166 ShowWindow (hWnd, SW_SHOW);
167 #endif
168 REDRAW(hWnd);
169 WAIT;
171 return hWnd;
174 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
175 LPCSTR loc, BOOL clear)
177 HDC hdc = NULL;
178 #ifdef VISIBLE
179 if (!himl) return NULL;
181 SetWindowText(hwnd, loc);
182 hdc = GetDC(hwnd);
183 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
185 REDRAW(hwnd);
186 WAIT;
188 if (clear)
190 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
191 ReleaseDC(hwnd, hdc);
192 hdc = NULL;
194 #endif /* VISIBLE */
195 return hdc;
198 /* Useful for checking differences */
199 #if 0
200 static void dump_bits(const BYTE *p, const BYTE *q, int size)
202 int i, j;
204 size /= 8;
206 for (i = 0; i < size * 2; i++)
208 printf("|");
209 for (j = 0; j < size; j++)
210 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
211 printf(" -- ");
212 for (j = 0; j < size; j++)
213 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
214 printf("|\n");
215 p += size * 4;
216 q += size * 4;
218 printf("\n");
220 #endif
222 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
223 const BYTE *checkbits, LPCSTR loc)
225 #ifdef VISIBLE
226 BYTE bits[100*100/8];
227 COLORREF c;
228 HDC hdc;
229 int x, y, i = -1;
231 if (!himl) return;
233 memset(bits, 0, sizeof(bits));
234 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
236 c = GetPixel(hdc, 0, 0);
238 for (y = 0; y < size; y ++)
240 for (x = 0; x < size; x++)
242 if (!(x & 0x7)) i++;
243 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
247 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
248 ReleaseDC(hwnd, hdc);
250 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
251 "%s: bits different\n", loc);
252 if (memcmp(bits, checkbits, (size * size)/8))
253 dump_bits(bits, checkbits, size);
254 #endif /* VISIBLE */
257 static void test_hotspot(void)
259 struct hotspot {
260 int dx;
261 int dy;
264 #define SIZEX1 47
265 #define SIZEY1 31
266 #define SIZEX2 11
267 #define SIZEY2 17
268 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
269 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
270 { 10, 7 },
271 { SIZEX1, SIZEY1 },
272 { -9, -8 },
273 { -7, 35 }
275 int i, j, ret;
276 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
277 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
278 HWND hwnd = create_a_window();
281 for (i = 0; i < HOTSPOTS_MAX; i++) {
282 for (j = 0; j < HOTSPOTS_MAX; j++) {
283 int dx1 = hotspots[i].dx;
284 int dy1 = hotspots[i].dy;
285 int dx2 = hotspots[j].dx;
286 int dy2 = hotspots[j].dy;
287 int correctx, correcty, newx, newy;
288 char loc[256];
289 HIMAGELIST himlNew;
290 POINT ppt;
292 ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
293 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
294 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
295 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
297 /* check merging the dragged image with a second image */
298 ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
299 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
300 dx1, dy1, dx2, dy2);
301 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
302 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
304 /* check new hotspot, it should be the same like the old one */
305 himlNew = ImageList_GetDragImage(NULL, &ppt);
306 ok(ppt.x == dx1 && ppt.y == dy1,
307 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
308 dx1, dy1, ppt.x, ppt.y);
309 /* check size of new dragged image */
310 ImageList_GetIconSize(himlNew, &newx, &newy);
311 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
312 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
313 ok(newx == correctx && newy == correcty,
314 "Expected drag image size [%d,%d] got [%d,%d]\n",
315 correctx, correcty, newx, newy);
316 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
317 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
318 ImageList_EndDrag();
321 #undef SIZEX1
322 #undef SIZEY1
323 #undef SIZEX2
324 #undef SIZEY2
325 #undef HOTSPOTS_MAX
326 ImageList_Destroy(himl2);
327 ImageList_Destroy(himl1);
328 DestroyWindow(hwnd);
331 static void test_add_remove(void)
333 HIMAGELIST himl ;
335 HICON hicon1 ;
336 HICON hicon2 ;
337 HICON hicon3 ;
339 /* create an imagelist to play with */
340 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
341 ok(himl!=0,"failed to create imagelist\n");
343 /* load the icons to add to the image list */
344 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
345 ok(hicon1 != 0, "no hicon1\n");
346 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
347 ok(hicon2 != 0, "no hicon2\n");
348 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
349 ok(hicon3 != 0, "no hicon3\n");
351 /* remove when nothing exists */
352 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
353 /* removing everything from an empty imagelist should succeed */
354 ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
356 /* add three */
357 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
358 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
359 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
361 /* remove an index out of range */
362 ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
364 /* remove three */
365 ok(ImageList_Remove(himl,0),"can't remove 0\n");
366 ok(ImageList_Remove(himl,0),"can't remove 0\n");
367 ok(ImageList_Remove(himl,0),"can't remove 0\n");
369 /* remove one extra */
370 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
372 /* destroy it */
373 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
375 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
376 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
377 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
380 static void test_imagecount(void)
382 HIMAGELIST himl;
384 if (!pImageList_SetImageCount)
386 win_skip("ImageList_SetImageCount not available\n");
387 return;
390 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
391 ok(himl!=0,"failed to create imagelist\n");
393 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
394 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
395 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
396 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
397 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
398 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
400 ok(ImageList_Destroy(himl), "destroy imagelist failed\n");
403 static void test_DrawIndirect(void)
405 HIMAGELIST himl;
407 HBITMAP hbm1;
408 HBITMAP hbm2;
409 HBITMAP hbm3;
411 IMAGELISTDRAWPARAMS imldp;
412 HDC hdc;
413 HWND hwndfortest;
415 if (!pImageList_DrawIndirect)
417 win_skip("ImageList_DrawIndirect not available, skipping test\n");
418 return;
421 hwndfortest = create_a_window();
422 hdc = GetDC(hwndfortest);
423 ok(hdc!=NULL, "couldn't get DC\n");
425 /* create an imagelist to play with */
426 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
427 ok(himl!=0,"failed to create imagelist\n");
429 /* load the icons to add to the image list */
430 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
431 ok(hbm1 != 0, "no bitmap 1\n");
432 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
433 ok(hbm2 != 0, "no bitmap 2\n");
434 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
435 ok(hbm3 != 0, "no bitmap 3\n");
437 /* add three */
438 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
439 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
441 if (pImageList_SetImageCount)
443 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
444 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
445 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
448 memset(&imldp, 0, sizeof (imldp));
449 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
450 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
451 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
452 imldp.hdcDst = hdc;
453 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
454 imldp.himl = himl;
456 REDRAW(hwndfortest);
457 WAIT;
459 imldp.fStyle = SRCCOPY;
460 imldp.rgbBk = CLR_DEFAULT;
461 imldp.rgbFg = CLR_DEFAULT;
462 imldp.y = 100;
463 imldp.x = 100;
464 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
465 imldp.i ++;
466 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
467 imldp.i ++;
468 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
469 imldp.i ++;
470 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
472 /* remove three */
473 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
474 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
475 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
477 /* destroy it */
478 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
480 /* bitmaps should not be deleted by the imagelist */
481 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
482 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
483 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
485 ReleaseDC(hwndfortest, hdc);
486 DestroyWindow(hwndfortest);
489 static void test_merge(void)
491 HIMAGELIST himl1, himl2, hmerge;
492 HICON hicon1;
493 HWND hwnd = create_a_window();
495 himl1 = ImageList_Create(32,32,0,0,3);
496 ok(himl1 != NULL,"failed to create himl1\n");
498 himl2 = ImageList_Create(32,32,0,0,3);
499 ok(himl2 != NULL,"failed to create himl2\n");
501 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
502 ok(hicon1 != NULL, "failed to create hicon1\n");
504 if (!himl1 || !himl2 || !hicon1)
505 return;
507 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
508 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
510 /* If himl1 has no images, merge still succeeds */
511 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
512 ok(hmerge != NULL, "merge himl1,-1 failed\n");
513 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
514 if (hmerge) ImageList_Destroy(hmerge);
516 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
517 ok(hmerge != NULL,"merge himl1,0 failed\n");
518 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
519 if (hmerge) ImageList_Destroy(hmerge);
521 /* Same happens if himl2 is empty */
522 ImageList_Destroy(himl2);
523 himl2 = ImageList_Create(32,32,0,0,3);
524 ok(himl2 != NULL,"failed to recreate himl2\n");
525 if (!himl2)
526 return;
528 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
529 ok(hmerge != NULL, "merge himl2,-1 failed\n");
530 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
531 if (hmerge) ImageList_Destroy(hmerge);
533 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
534 ok(hmerge != NULL, "merge himl2,0 failed\n");
535 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
536 if (hmerge) ImageList_Destroy(hmerge);
538 /* Now try merging an image with itself */
539 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
541 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
542 ok(hmerge != NULL, "merge himl2 with itself failed\n");
543 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
544 if (hmerge) ImageList_Destroy(hmerge);
546 /* Try merging 2 different image lists */
547 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
549 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
550 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
551 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
552 if (hmerge) ImageList_Destroy(hmerge);
554 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
555 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
556 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
557 if (hmerge) ImageList_Destroy(hmerge);
559 ImageList_Destroy(himl1);
560 ImageList_Destroy(himl2);
561 DestroyIcon(hicon1);
562 DestroyWindow(hwnd);
565 /*********************** imagelist storage test ***************************/
567 #define BMP_CX 48
569 struct my_IStream
571 IStream is;
572 char *iml_data; /* written imagelist data */
573 ULONG iml_data_size;
576 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(
577 IStream* This,
578 REFIID riid,
579 void** ppvObject)
581 assert(0);
582 return E_NOTIMPL;
585 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(
586 IStream* This)
588 assert(0);
589 return 2;
592 static ULONG STDMETHODCALLTYPE Test_Stream_Release(
593 IStream* This)
595 assert(0);
596 return 1;
599 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(
600 IStream* This,
601 void* pv,
602 ULONG cb,
603 ULONG* pcbRead)
605 assert(0);
606 return E_NOTIMPL;
609 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
611 my_is->iml_data_size += add;
613 if (!my_is->iml_data)
614 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
615 else
616 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
618 return my_is->iml_data ? TRUE : FALSE;
621 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(
622 IStream* This,
623 const void* pv,
624 ULONG cb,
625 ULONG* pcbWritten)
627 struct my_IStream *my_is = (struct my_IStream *)This;
628 ULONG current_iml_data_size = my_is->iml_data_size;
630 if (!allocate_storage(my_is, cb)) return E_FAIL;
632 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
633 if (pcbWritten) *pcbWritten = cb;
635 return S_OK;
638 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(
639 IStream* This,
640 LARGE_INTEGER dlibMove,
641 DWORD dwOrigin,
642 ULARGE_INTEGER* plibNewPosition)
644 assert(0);
645 return E_NOTIMPL;
648 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(
649 IStream* This,
650 ULARGE_INTEGER libNewSize)
652 assert(0);
653 return E_NOTIMPL;
656 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(
657 IStream* This,
658 IStream* pstm,
659 ULARGE_INTEGER cb,
660 ULARGE_INTEGER* pcbRead,
661 ULARGE_INTEGER* pcbWritten)
663 assert(0);
664 return E_NOTIMPL;
667 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(
668 IStream* This,
669 DWORD grfCommitFlags)
671 assert(0);
672 return E_NOTIMPL;
675 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(
676 IStream* This)
678 assert(0);
679 return E_NOTIMPL;
682 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(
683 IStream* This,
684 ULARGE_INTEGER libOffset,
685 ULARGE_INTEGER cb,
686 DWORD dwLockType)
688 assert(0);
689 return E_NOTIMPL;
692 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(
693 IStream* This,
694 ULARGE_INTEGER libOffset,
695 ULARGE_INTEGER cb,
696 DWORD dwLockType)
698 assert(0);
699 return E_NOTIMPL;
702 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(
703 IStream* This,
704 STATSTG* pstatstg,
705 DWORD grfStatFlag)
707 assert(0);
708 return E_NOTIMPL;
711 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(
712 IStream* This,
713 IStream** ppstm)
715 assert(0);
716 return E_NOTIMPL;
719 static const IStreamVtbl Test_Stream_Vtbl =
721 Test_Stream_QueryInterface,
722 Test_Stream_AddRef,
723 Test_Stream_Release,
724 Test_Stream_Read,
725 Test_Stream_Write,
726 Test_Stream_Seek,
727 Test_Stream_SetSize,
728 Test_Stream_CopyTo,
729 Test_Stream_Commit,
730 Test_Stream_Revert,
731 Test_Stream_LockRegion,
732 Test_Stream_UnlockRegion,
733 Test_Stream_Stat,
734 Test_Stream_Clone
737 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
739 static INT DIB_GetWidthBytes( int width, int bpp )
741 int words;
743 switch (bpp)
745 case 1: words = (width + 31) / 32; break;
746 case 4: words = (width + 7) / 8; break;
747 case 8: words = (width + 3) / 4; break;
748 case 15:
749 case 16: words = (width + 1) / 2; break;
750 case 24: words = (width * 3 + 3)/4; break;
751 case 32: words = width; break;
753 default:
754 words=0;
755 trace("Unknown depth %d, please report.\n", bpp );
756 assert(0);
757 break;
759 return 4 * words;
762 static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
763 INT width, INT height, INT bpp,
764 const char *comment)
766 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
767 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
768 ULONG hdr_size, image_size;
770 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
771 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
773 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
774 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
775 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
776 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
777 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
779 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
780 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
781 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
782 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
783 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
785 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
786 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
787 #if 0
789 char fname[256];
790 FILE *f;
791 sprintf(fname, "bmp_%s.bmp", comment);
792 f = fopen(fname, "wb");
793 fwrite(bm_data, 1, bm_data_size, f);
794 fclose(f);
796 #endif
799 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow)
801 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
803 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
804 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
805 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
806 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
807 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
808 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
809 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
810 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
811 ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
812 ok(ilh->ovls[0] == -1 ||
813 ilh->ovls[0] == 0, /* win95 */
814 "wrong ovls[0] %04x\n", ilh->ovls[0]);
815 ok(ilh->ovls[1] == -1 ||
816 ilh->ovls[1] == 0, /* win95 */
817 "wrong ovls[1] %04x\n", ilh->ovls[1]);
818 ok(ilh->ovls[2] == -1 ||
819 ilh->ovls[2] == 0, /* win95 */
820 "wrong ovls[2] %04x\n", ilh->ovls[2]);
821 ok(ilh->ovls[3] == -1 ||
822 ilh->ovls[3] == 0, /* win95 */
823 "wrong ovls[3] %04x\n", ilh->ovls[3]);
826 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
828 HDC hdc;
829 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
830 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
831 HBITMAP hbmp, hbmp_old;
832 HBRUSH hbrush;
833 RECT rc = { 0, 0, cx, cy };
835 hdc = CreateCompatibleDC(0);
837 memset(bmi, 0, sizeof(*bmi));
838 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
839 bmi->bmiHeader.biHeight = cx;
840 bmi->bmiHeader.biWidth = cy;
841 bmi->bmiHeader.biBitCount = 24;
842 bmi->bmiHeader.biPlanes = 1;
843 bmi->bmiHeader.biCompression = BI_RGB;
844 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
846 hbmp_old = SelectObject(hdc, hbmp);
848 hbrush = CreateSolidBrush(color);
849 FillRect(hdc, &rc, hbrush);
850 DeleteObject(hbrush);
852 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
854 SelectObject(hdc, hbmp_old);
855 DeleteDC(hdc);
857 return hbmp;
860 #define iml_clear_stream_data() \
861 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
862 Test_Stream.iml_data = NULL; \
863 Test_Stream.iml_data_size = 0;
865 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
866 INT width, INT height, INT bpp, const char *comment)
868 INT ret, cxx, cyy;
870 trace("%s\n", comment);
872 ret = ImageList_GetImageCount(himl);
873 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
875 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
876 ok(ret, "ImageList_GetIconSize failed\n");
877 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
878 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
880 iml_clear_stream_data();
881 ret = ImageList_Write(himl, &Test_Stream.is);
882 ok(ret, "ImageList_Write failed\n");
884 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
885 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
887 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow);
888 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
889 Test_Stream.iml_data_size - sizeof(ILHEAD),
890 width, height, bpp, comment);
893 static void image_list_init(HIMAGELIST himl)
895 HBITMAP hbm;
896 char comment[16];
897 INT n = 1, i;
898 static const struct test_data
900 BYTE grey;
901 INT cx, cy, cur, max, grow, width, height, bpp;
902 const char *comment;
903 } td[] =
905 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
906 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
907 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
908 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
909 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
910 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
911 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
912 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
913 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
914 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
915 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
916 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
917 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
918 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
919 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
920 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
921 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
922 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
923 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
924 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
925 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
926 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
927 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
928 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
931 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 0");
933 #define add_bitmap(grey) \
934 sprintf(comment, "%d", n++); \
935 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
936 ImageList_Add(himl, hbm, NULL); \
937 DeleteObject(hbm);
939 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
941 add_bitmap(td[i].grey);
942 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
943 td[i].width, td[i].height, td[i].bpp, td[i].comment);
945 #undef add_bitmap
948 static void test_imagelist_storage(void)
950 HIMAGELIST himl;
951 HBITMAP hbm;
952 INT ret;
954 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
955 ok(himl != 0, "ImageList_Create failed\n");
957 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "empty");
959 image_list_init(himl);
960 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "orig");
962 ret = ImageList_Remove(himl, 4);
963 ok(ret, "ImageList_Remove failed\n");
964 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "1");
966 ret = ImageList_Remove(himl, 5);
967 ok(ret, "ImageList_Remove failed\n");
968 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "2");
970 ret = ImageList_Remove(himl, 6);
971 ok(ret, "ImageList_Remove failed\n");
972 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "3");
974 ret = ImageList_Remove(himl, 7);
975 ok(ret, "ImageList_Remove failed\n");
976 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "4");
978 ret = ImageList_Remove(himl, -2);
979 ok(!ret, "ImageList_Remove(-2) should fail\n");
980 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "5");
982 ret = ImageList_Remove(himl, 20);
983 ok(!ret, "ImageList_Remove(20) should fail\n");
984 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "6");
986 ret = ImageList_Remove(himl, -1);
987 ok(ret, "ImageList_Remove(-1) failed\n");
988 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
990 ret = ImageList_Destroy(himl);
991 ok(ret, "ImageList_Destroy failed\n");
993 iml_clear_stream_data();
995 /* test ImageList_Create storage allocation */
997 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
998 ok(himl != 0, "ImageList_Create failed\n");
999 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, 24, "init 0 grow 32");
1000 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1001 ret = ImageList_Add(himl, hbm, NULL);
1002 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1003 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, 24, "add 1 x 9");
1004 DeleteObject(hbm);
1005 ret = ImageList_Destroy(himl);
1006 ok(ret, "ImageList_Destroy failed\n");
1007 iml_clear_stream_data();
1009 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1010 ok(himl != 0, "ImageList_Create failed\n");
1011 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 4");
1012 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1013 ret = ImageList_Add(himl, hbm, NULL);
1014 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1015 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "add 9 x 1");
1016 ret = ImageList_Add(himl, hbm, NULL);
1017 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1018 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, 24, "add 9 x 1");
1019 DeleteObject(hbm);
1020 ret = ImageList_Destroy(himl);
1021 ok(ret, "ImageList_Destroy failed\n");
1022 iml_clear_stream_data();
1024 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1025 ok(himl != 0, "ImageList_Create failed\n");
1026 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, 24, "init 207 grow 209");
1027 ret = ImageList_Destroy(himl);
1028 ok(ret, "ImageList_Destroy failed\n");
1029 iml_clear_stream_data();
1031 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1032 ok(himl != 0, "ImageList_Create failed\n");
1033 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, 24, "init 209 grow 207");
1034 ret = ImageList_Destroy(himl);
1035 ok(ret, "ImageList_Destroy failed\n");
1036 iml_clear_stream_data();
1038 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1039 ok(himl != 0, "ImageList_Create failed\n");
1040 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "init 14 grow 4");
1041 ret = ImageList_Destroy(himl);
1042 ok(ret, "ImageList_Destroy failed\n");
1043 iml_clear_stream_data();
1045 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1046 ok(himl != 0, "ImageList_Create failed\n");
1047 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, 24, "init 5 grow 9");
1048 ret = ImageList_Destroy(himl);
1049 ok(ret, "ImageList_Destroy failed\n");
1050 iml_clear_stream_data();
1052 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1053 ok(himl != 0, "ImageList_Create failed\n");
1054 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, 24, "init 9 grow 5");
1055 ret = ImageList_Destroy(himl);
1056 ok(ret, "ImageList_Destroy failed\n");
1057 iml_clear_stream_data();
1059 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1060 ok(himl != 0, "ImageList_Create failed\n");
1061 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, 24, "init 2 grow 4");
1062 ret = ImageList_Destroy(himl);
1063 ok(ret, "ImageList_Destroy failed\n");
1064 iml_clear_stream_data();
1066 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1067 ok(himl != 0, "ImageList_Create failed\n");
1068 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 2");
1069 ret = ImageList_Destroy(himl);
1070 ok(ret, "ImageList_Destroy failed\n");
1071 iml_clear_stream_data();
1074 static void test_shell_imagelist(void)
1076 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1077 IImageList *iml = NULL;
1078 HMODULE hShell32;
1079 HRESULT hr;
1080 int out = 0;
1081 RECT rect;
1082 int cx, cy;
1084 /* Try to load function from shell32 */
1085 hShell32 = LoadLibrary("shell32.dll");
1086 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1088 if (!pSHGetImageList)
1090 win_skip("SHGetImageList not available, skipping test\n");
1091 return;
1094 /* Get system image list */
1095 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1097 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1099 if (hr != S_OK)
1100 return;
1102 IImageList_GetImageCount(iml, &out);
1103 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1105 /* Fetch the small icon size */
1106 cx = GetSystemMetrics(SM_CXSMICON);
1107 cy = GetSystemMetrics(SM_CYSMICON);
1109 /* Check icon size matches */
1110 IImageList_GetImageRect(iml, 0, &rect);
1111 ok(((rect.right == cx) && (rect.bottom == cy)),
1112 "IImageList_GetImageRect returned r:%d,b:%d\n",
1113 rect.right, rect.bottom);
1115 IImageList_Release(iml);
1116 FreeLibrary(hShell32);
1119 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1121 HBITMAP hBitmap;
1122 UINT32 *buffer = NULL;
1123 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1124 0, 0, 0, 0, 0}};
1126 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1127 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1129 if(!hBitmap || !buffer)
1131 DeleteObject(hBitmap);
1132 return NULL;
1135 buffer[0] = pixel1;
1136 buffer[1] = pixel2;
1138 return hBitmap;
1141 static BOOL colour_match(UINT32 x, UINT32 y)
1143 const INT32 tolerance = 8;
1145 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1146 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1147 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1149 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1152 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1153 UINT32 expected, int line)
1155 bits[0] = 0x00FFFFFF;
1156 pImageList_DrawIndirect(ildp);
1157 ok(colour_match(bits[0], expected),
1158 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1159 bits[0] & 0x00FFFFFF, expected, line);
1163 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1164 UINT fStyle, UINT32 expected, int line)
1166 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1167 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1168 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1171 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1172 DWORD dwRop, UINT32 expected, int line)
1174 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1175 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1176 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1179 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1180 UINT fState, DWORD Frame, UINT32 expected, int line)
1182 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1183 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1184 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1187 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1188 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1189 UINT32 broken_expected, int line)
1191 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1192 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1193 bits[0] = 0x00FFFFFF;
1194 pImageList_DrawIndirect(&ildp);
1195 ok(colour_match(bits[0], expected) ||
1196 broken(colour_match(bits[0], broken_expected)),
1197 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1198 bits[0] & 0x00FFFFFF, expected, line);
1201 static void test_ImageList_DrawIndirect(void)
1203 HIMAGELIST himl = NULL;
1204 int ret;
1205 HDC hdcDst = NULL;
1206 HBITMAP hbmOld = NULL, hbmDst = NULL;
1207 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1208 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1209 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1210 UINT32 *bits = 0;
1211 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1213 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1214 0, 0, 0, 0, 0}};
1216 hdcDst = CreateCompatibleDC(0);
1217 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1218 if (!hdcDst)
1219 return;
1221 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1222 ok(hbmMask != 0, "CreateBitmap failed\n");
1223 if(!hbmMask) goto cleanup;
1225 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1226 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1227 if(!hbmInverseMask) goto cleanup;
1229 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1230 ok(himl != 0, "ImageList_Create failed\n");
1231 if(!himl) goto cleanup;
1233 /* Add a no-alpha image */
1234 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1235 if(!hbmImage) goto cleanup;
1237 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1238 ok(iImage != -1, "ImageList_Add failed\n");
1239 if(iImage == -1) goto cleanup;
1241 /* Add an alpha image */
1242 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1243 if(!hbmAlphaImage) goto cleanup;
1245 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1246 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1247 if(iAlphaImage == -1) goto cleanup;
1249 /* Add a transparent alpha image */
1250 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1251 if(!hbmTransparentImage) goto cleanup;
1253 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1254 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1255 if(iTransparentImage == -1) goto cleanup;
1257 /* 32-bit Tests */
1258 bitmapInfo.bmiHeader.biBitCount = 32;
1259 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1260 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1261 if (!hbmDst || !bits)
1262 goto cleanup;
1263 hbmOld = SelectObject(hdcDst, hbmDst);
1265 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1266 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1267 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1268 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, 0x00B4BDC4, __LINE__);
1269 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1270 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1271 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1273 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1274 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1275 todo_wine
1277 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x009DA8B1, __LINE__);
1278 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, 0x008C99A3, __LINE__);
1281 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1282 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1283 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1285 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1287 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1288 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1290 /* ILD_ROP is ignored when the image has an alpha channel */
1291 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1292 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1294 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1295 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1297 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1298 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1300 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1301 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1302 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1304 cleanup:
1306 if(hbmOld)
1307 SelectObject(hdcDst, hbmOld);
1308 if(hbmDst)
1309 DeleteObject(hbmDst);
1311 if(hdcDst)
1312 DeleteDC(hdcDst);
1314 if(hbmMask)
1315 DeleteObject(hbmMask);
1316 if(hbmInverseMask)
1317 DeleteObject(hbmInverseMask);
1319 if(hbmImage)
1320 DeleteObject(hbmImage);
1321 if(hbmAlphaImage)
1322 DeleteObject(hbmAlphaImage);
1323 if(hbmTransparentImage)
1324 DeleteObject(hbmTransparentImage);
1326 if(himl)
1328 ret = ImageList_Destroy(himl);
1329 ok(ret, "ImageList_Destroy failed\n");
1333 static void test_iimagelist(void)
1335 IImageList *imgl, *imgl2;
1336 HIMAGELIST himl;
1337 HRESULT hr;
1338 ULONG ret;
1340 if (!pHIMAGELIST_QueryInterface)
1342 win_skip("XP imagelist functions not available\n");
1343 return;
1346 /* test reference counting on destruction */
1347 imgl = (IImageList*)createImageList(32, 32);
1348 ret = IUnknown_AddRef(imgl);
1349 ok(ret == 2, "Expected 2, got %d\n", ret);
1350 ret = ImageList_Destroy((HIMAGELIST)imgl);
1351 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1352 ret = ImageList_Destroy((HIMAGELIST)imgl);
1353 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1354 ret = ImageList_Destroy((HIMAGELIST)imgl);
1355 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1357 imgl = (IImageList*)createImageList(32, 32);
1358 ret = IUnknown_AddRef(imgl);
1359 ok(ret == 2, "Expected 2, got %d\n", ret);
1360 ret = ImageList_Destroy((HIMAGELIST)imgl);
1361 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1362 ret = IImageList_Release(imgl);
1363 ok(ret == 0, "Expected 0, got %d\n", ret);
1364 ret = ImageList_Destroy((HIMAGELIST)imgl);
1365 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1367 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1368 imgl = (IImageList*)createImageList(32, 32);
1369 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1370 ok(hr == S_OK, "got 0x%08x\n", hr);
1371 ok(imgl2 == imgl, "got different pointer\n");
1372 ret = IImageList_Release(imgl);
1373 ok(ret == 1, "got %u\n", ret);
1374 IImageList_Release(imgl);
1376 if (!pImageList_CoCreateInstance)
1378 win_skip("Vista imagelist functions not available\n");
1379 return;
1382 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1383 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1385 if (hr == S_OK)
1386 IImageList_Release(imgl);
1388 himl = createImageList(32, 32);
1390 if (!himl)
1391 return;
1393 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1394 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1396 if (hr == S_OK)
1397 IImageList_Release(imgl);
1399 ImageList_Destroy(himl);
1402 static void test_hotspot_v6(void)
1404 struct hotspot {
1405 int dx;
1406 int dy;
1409 #define SIZEX1 47
1410 #define SIZEY1 31
1411 #define SIZEX2 11
1412 #define SIZEY2 17
1413 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1414 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1415 { 10, 7 },
1416 { SIZEX1, SIZEY1 },
1417 { -9, -8 },
1418 { -7, 35 }
1420 int i, j;
1421 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1422 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1423 IImageList *imgl1, *imgl2;
1424 HRESULT hr;
1426 /* cast to IImageList */
1427 imgl1 = (IImageList *) himl1;
1428 imgl2 = (IImageList *) himl2;
1430 for (i = 0; i < HOTSPOTS_MAX; i++) {
1431 for (j = 0; j < HOTSPOTS_MAX; j++) {
1432 int dx1 = hotspots[i].dx;
1433 int dy1 = hotspots[i].dy;
1434 int dx2 = hotspots[j].dx;
1435 int dy2 = hotspots[j].dy;
1436 int correctx, correcty, newx, newy;
1437 char loc[256];
1438 IImageList *imglNew;
1439 POINT ppt;
1441 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1442 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1443 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1445 /* check merging the dragged image with a second image */
1446 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1447 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1448 dx1, dy1, dx2, dy2);
1449 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1451 /* check new hotspot, it should be the same like the old one */
1452 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1453 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1454 ok(ppt.x == dx1 && ppt.y == dy1,
1455 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1456 dx1, dy1, ppt.x, ppt.y);
1457 /* check size of new dragged image */
1458 IImageList_GetIconSize(imglNew, &newx, &newy);
1459 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1460 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1461 ok(newx == correctx && newy == correcty,
1462 "Expected drag image size [%d,%d] got [%d,%d]\n",
1463 correctx, correcty, newx, newy);
1464 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1465 IImageList_EndDrag(imgl2);
1468 #undef SIZEX1
1469 #undef SIZEY1
1470 #undef SIZEX2
1471 #undef SIZEY2
1472 #undef HOTSPOTS_MAX
1473 IImageList_Release(imgl2);
1474 IImageList_Release(imgl1);
1477 static void test_IImageList_Add_Remove(void)
1479 IImageList *imgl;
1480 HIMAGELIST himl;
1481 HRESULT hr;
1483 HICON hicon1;
1484 HICON hicon2;
1485 HICON hicon3;
1487 int ret;
1489 /* create an imagelist to play with */
1490 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1491 ok(himl != 0,"failed to create imagelist\n");
1493 imgl = (IImageList *) himl;
1495 /* load the icons to add to the image list */
1496 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1497 ok(hicon1 != 0, "no hicon1\n");
1498 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1499 ok(hicon2 != 0, "no hicon2\n");
1500 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1501 ok(hicon3 != 0, "no hicon3\n");
1503 /* remove when nothing exists */
1504 hr = IImageList_Remove(imgl, 0);
1505 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1507 /* removing everything from an empty imagelist should succeed */
1508 hr = IImageList_Remove(imgl, -1);
1509 ok(hr == S_OK, "removed nonexistent icon\n");
1511 /* add three */
1512 ret = -1;
1513 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1514 ret = -1;
1515 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1516 ret = -1;
1517 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1519 /* remove an index out of range */
1520 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1522 /* remove three */
1523 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1524 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1525 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1527 /* remove one extra */
1528 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1530 IImageList_Release(imgl);
1531 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1532 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1533 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1536 static void test_IImageList_Get_SetImageCount(void)
1538 IImageList *imgl;
1539 HIMAGELIST himl;
1540 HRESULT hr;
1541 INT ret;
1543 /* create an imagelist to play with */
1544 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1545 ok(himl != 0,"failed to create imagelist\n");
1547 imgl = (IImageList *) himl;
1549 /* check SetImageCount/GetImageCount */
1550 hr = IImageList_SetImageCount(imgl, 3);
1551 ok(hr == S_OK, "got 0x%08x\n", hr);
1552 ret = 0;
1553 hr = IImageList_GetImageCount(imgl, &ret);
1554 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1555 hr = IImageList_SetImageCount(imgl, 1);
1556 ok(hr == S_OK, "got 0x%08x\n", hr);
1557 ret = 0;
1558 hr = IImageList_GetImageCount(imgl, &ret);
1559 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1560 hr = IImageList_SetImageCount(imgl, 0);
1561 ok(hr == S_OK, "got 0x%08x\n", hr);
1562 ret = -1;
1563 hr = IImageList_GetImageCount(imgl, &ret);
1564 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1566 IImageList_Release(imgl);
1569 static void test_IImageList_Draw(void)
1571 IImageList *imgl;
1572 HIMAGELIST himl;
1574 HBITMAP hbm1;
1575 HBITMAP hbm2;
1576 HBITMAP hbm3;
1578 IMAGELISTDRAWPARAMS imldp;
1579 HWND hwndfortest;
1580 HRESULT hr;
1581 HDC hdc;
1582 int ret;
1584 hwndfortest = create_a_window();
1585 hdc = GetDC(hwndfortest);
1586 ok(hdc!=NULL, "couldn't get DC\n");
1588 /* create an imagelist to play with */
1589 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1590 ok(himl!=0,"failed to create imagelist\n");
1592 imgl = (IImageList *) himl;
1594 /* load the icons to add to the image list */
1595 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1596 ok(hbm1 != 0, "no bitmap 1\n");
1597 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1598 ok(hbm2 != 0, "no bitmap 2\n");
1599 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1600 ok(hbm3 != 0, "no bitmap 3\n");
1602 /* add three */
1603 ret = -1;
1604 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1605 ret = -1;
1606 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1608 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1609 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1611 if (0)
1613 /* crashes on native */
1614 hr = IImageList_Draw(imgl, NULL);
1617 memset(&imldp, 0, sizeof (imldp));
1618 hr = IImageList_Draw(imgl, &imldp);
1619 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1621 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1622 imldp.hdcDst = hdc;
1623 imldp.himl = himl;
1625 REDRAW(hwndfortest);
1626 WAIT;
1628 imldp.fStyle = SRCCOPY;
1629 imldp.rgbBk = CLR_DEFAULT;
1630 imldp.rgbFg = CLR_DEFAULT;
1631 imldp.y = 100;
1632 imldp.x = 100;
1633 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1634 imldp.i ++;
1635 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1636 imldp.i ++;
1637 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1638 imldp.i ++;
1639 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1641 /* remove three */
1642 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1643 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1644 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1646 /* destroy it */
1647 IImageList_Release(imgl);
1649 /* bitmaps should not be deleted by the imagelist */
1650 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1651 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1652 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1654 ReleaseDC(hwndfortest, hdc);
1655 DestroyWindow(hwndfortest);
1658 static void test_IImageList_Merge(void)
1660 HIMAGELIST himl1, himl2;
1661 IImageList *imgl1, *imgl2, *merge;
1662 HICON hicon1;
1663 HWND hwnd = create_a_window();
1664 HRESULT hr;
1665 int ret;
1667 himl1 = ImageList_Create(32,32,0,0,3);
1668 ok(himl1 != NULL,"failed to create himl1\n");
1670 himl2 = ImageList_Create(32,32,0,0,3);
1671 ok(himl2 != NULL,"failed to create himl2\n");
1673 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1674 ok(hicon1 != NULL, "failed to create hicon1\n");
1676 if (!himl1 || !himl2 || !hicon1)
1677 return;
1679 /* cast to IImageList */
1680 imgl1 = (IImageList *) himl1;
1681 imgl2 = (IImageList *) himl2;
1683 ret = -1;
1684 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1686 if (0)
1688 /* null cases that crash on native */
1689 hr = IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1690 hr = IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1693 /* If himl1 has no images, merge still succeeds */
1694 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1695 ok(hr == S_OK, "merge himl1,-1 failed\n");
1696 if (hr == S_OK) IImageList_Release(merge);
1698 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1699 ok(hr == S_OK, "merge himl1,0 failed\n");
1700 if (hr == S_OK) IImageList_Release(merge);
1702 /* Same happens if himl2 is empty */
1703 IImageList_Release(imgl2);
1704 himl2 = ImageList_Create(32,32,0,0,3);
1705 ok(himl2 != NULL,"failed to recreate himl2\n");
1707 imgl2 = (IImageList *) himl2;
1709 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1710 ok(hr == S_OK, "merge himl2,-1 failed\n");
1711 if (hr == S_OK) IImageList_Release(merge);
1713 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1714 ok(hr == S_OK, "merge himl2,0 failed\n");
1715 if (hr == S_OK) IImageList_Release(merge);
1717 /* Now try merging an image with itself */
1718 ret = -1;
1719 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1721 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1722 ok(hr == S_OK, "merge himl2 with itself failed\n");
1723 if (hr == S_OK) IImageList_Release(merge);
1725 /* Try merging 2 different image lists */
1726 ret = -1;
1727 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1729 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1730 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1731 if (hr == S_OK) IImageList_Release(merge);
1733 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1734 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1735 if (hr == S_OK) IImageList_Release(merge);
1737 IImageList_Release(imgl1);
1738 IImageList_Release(imgl2);
1740 DestroyIcon(hicon1);
1741 DestroyWindow(hwnd);
1744 static void test_iconsize(void)
1746 HIMAGELIST himl;
1747 INT cx, cy;
1748 BOOL ret;
1750 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1751 /* null pointers, not zero imagelist dimensions */
1752 ret = ImageList_GetIconSize(himl, NULL, NULL);
1753 ok(!ret, "got %d\n", ret);
1755 /* doesn't touch return pointers */
1756 cx = 0xdeadbeef;
1757 ret = ImageList_GetIconSize(himl, &cx, NULL);
1758 ok(!ret, "got %d\n", ret);
1759 ok(cx == 0xdeadbeef, "got %d\n", cx);
1761 cy = 0xdeadbeef;
1762 ret = ImageList_GetIconSize(himl, NULL, &cy);
1763 ok(!ret, "got %d\n", ret);
1764 ok(cy == 0xdeadbeef, "got %d\n", cy);
1766 ImageList_Destroy(himl);
1769 static void test_create(void)
1771 HIMAGELIST himl;
1773 /* list with zero or negative image dimensions */
1774 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1775 ok(himl == NULL, "got %p\n", himl);
1777 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1778 ok(himl == NULL, "got %p\n", himl);
1780 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1781 ok(himl == NULL, "got %p\n", himl);
1783 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1784 ok(himl == NULL, "got %p\n", himl);
1786 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1787 ok(himl == NULL, "got %p\n", himl);
1790 static void test_IImageList_Clone(void)
1792 IImageList *imgl, *imgl2;
1793 HIMAGELIST himl;
1794 HRESULT hr;
1795 ULONG ref;
1797 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1798 imgl = (IImageList*)himl;
1800 if (0)
1802 /* crashes on native */
1803 hr = IImageList_Clone(imgl, &IID_IImageList, NULL);
1806 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1807 ok(hr == S_OK, "got 0x%08x\n", hr);
1808 ref = IImageList_Release(imgl2);
1809 ok(ref == 0, "got %u\n", ref);
1811 IImageList_Release(imgl);
1814 static void test_IImageList_GetBkColor(void)
1816 IImageList *imgl;
1817 HIMAGELIST himl;
1818 COLORREF color;
1819 HRESULT hr;
1821 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1822 imgl = (IImageList*)himl;
1824 if (0)
1826 /* crashes on native */
1827 hr = IImageList_GetBkColor(imgl, NULL);
1830 hr = IImageList_GetBkColor(imgl, &color);
1831 ok(hr == S_OK, "got 0x%08x\n", hr);
1833 IImageList_Release(imgl);
1836 static void test_IImageList_SetBkColor(void)
1838 IImageList *imgl;
1839 HIMAGELIST himl;
1840 COLORREF color;
1841 HRESULT hr;
1843 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1844 imgl = (IImageList*)himl;
1846 if (0)
1848 /* crashes on native */
1849 hr = IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1852 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1853 ok(hr == S_OK, "got 0x%08x\n", hr);
1855 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1856 ok(hr == S_OK, "got 0x%08x\n", hr);
1858 color = 0xdeadbeef;
1859 hr = IImageList_GetBkColor(imgl, &color);
1860 ok(hr == S_OK, "got 0x%08x\n", hr);
1861 ok(color == CLR_NONE, "got %x\n", color);
1863 IImageList_Release(imgl);
1866 static void test_IImageList_GetImageCount(void)
1868 IImageList *imgl;
1869 HIMAGELIST himl;
1870 int count;
1871 HRESULT hr;
1873 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1874 imgl = (IImageList*)himl;
1876 if (0)
1878 /* crashes on native */
1879 hr = IImageList_GetImageCount(imgl, NULL);
1882 count = -1;
1883 hr = IImageList_GetImageCount(imgl, &count);
1884 ok(hr == S_OK, "got 0x%08x\n", hr);
1885 ok(count == 0, "got %d\n", count);
1887 IImageList_Release(imgl);
1890 static void test_IImageList_GetIconSize(void)
1892 IImageList *imgl;
1893 HIMAGELIST himl;
1894 int cx, cy;
1895 HRESULT hr;
1897 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1898 imgl = (IImageList*)himl;
1900 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1901 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1903 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1904 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1906 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1907 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1909 IImageList_Release(imgl);
1912 START_TEST(imagelist)
1914 ULONG_PTR ctx_cookie;
1915 HANDLE hCtx;
1917 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1918 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1919 pImageList_Add = NULL;
1920 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1921 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1923 hinst = GetModuleHandleA(NULL);
1925 InitCommonControls();
1927 test_create();
1928 test_hotspot();
1929 test_add_remove();
1930 test_imagecount();
1931 test_DrawIndirect();
1932 test_merge();
1933 test_imagelist_storage();
1934 test_iconsize();
1936 FreeLibrary(hComCtl32);
1938 /* Now perform v6 tests */
1940 if (!load_v6_module(&ctx_cookie, &hCtx))
1941 return;
1943 /* Reload comctl32 */
1944 hComCtl32 = LoadLibraryA("comctl32.dll");
1945 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1946 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1947 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1948 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1949 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
1950 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
1952 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1954 /* Do v6.0 tests */
1955 test_ImageList_DrawIndirect();
1956 test_shell_imagelist();
1957 test_iimagelist();
1959 test_hotspot_v6();
1960 test_IImageList_Add_Remove();
1961 test_IImageList_Get_SetImageCount();
1962 test_IImageList_Draw();
1963 test_IImageList_Merge();
1964 test_IImageList_Clone();
1965 test_IImageList_GetBkColor();
1966 test_IImageList_SetBkColor();
1967 test_IImageList_GetImageCount();
1968 test_IImageList_GetIconSize();
1970 CoUninitialize();
1972 unload_v6_module(ctx_cookie, hCtx);