1 /*
2  * Unit test suite for imagelist control.
3  *
4  * Copyright 2004 Michael Stefaniuc
5  * Copyright 2002 Mike McCormack for CodeWeavers
6  * Copyright 2007 Dmitry Timoshkov
7  * Copyright 2009 Owen Rudge for CodeWeavers
8  *
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.
13  *
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.
18  *
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
22  */
23 
24 #define COBJMACROS
25 #define CONST_VTABLE
26 
27 #include <stdarg.h>
28 #include <stdio.h>
29 
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34 #include "objbase.h"
35 #include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
36 #include "initguid.h"
37 #include "commoncontrols.h"
38 #include "shellapi.h"
39 
40 #include "wine/test.h"
41 #include "v6util.h"
42 #include "resources.h"
43 
44 #ifdef __REACTOS__
45 #include <ole2.h>
46 #endif
47 
48 #define IMAGELIST_MAGIC (('L' << 8) | 'I')
49 
50 #include "pshpack2.h"
51 /* Header used by ImageList_Read() and ImageList_Write() */
52 typedef struct _ILHEAD
53 {
54     USHORT	usMagic;
55     USHORT	usVersion;
56     WORD	cCurImage;
57     WORD	cMaxImage;
58     WORD	cGrow;
59     WORD	cx;
60     WORD	cy;
61     COLORREF	bkcolor;
62     WORD	flags;
63     SHORT	ovls[4];
64 } ILHEAD;
65 #include "poppack.h"
66 
67 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
68 static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST);
69 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
70 static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
71 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
72 static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
73     REFIID,void **);
74 static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
75 static int (WINAPI *pImageList_SetColorTable)(HIMAGELIST,int,int,RGBQUAD*);
76 static DWORD (WINAPI *pImageList_GetFlags)(HIMAGELIST);
77 static BOOL (WINAPI *pImageList_BeginDrag)(HIMAGELIST, int, int, int);
78 static HIMAGELIST (WINAPI *pImageList_GetDragImage)(POINT *, POINT *);
79 static void (WINAPI *pImageList_EndDrag)(void);
80 static INT (WINAPI *pImageList_GetImageCount)(HIMAGELIST);
81 static BOOL (WINAPI *pImageList_SetDragCursorImage)(HIMAGELIST, int, int, int);
82 static BOOL (WINAPI *pImageList_GetIconSize)(HIMAGELIST, int *, int *);
83 static BOOL (WINAPI *pImageList_Remove)(HIMAGELIST, int);
84 static INT (WINAPI *pImageList_ReplaceIcon)(HIMAGELIST, int, HICON);
85 static BOOL (WINAPI *pImageList_Replace)(HIMAGELIST, int, HBITMAP, HBITMAP);
86 static HIMAGELIST (WINAPI *pImageList_Merge)(HIMAGELIST, int, HIMAGELIST, int, int, int);
87 static BOOL (WINAPI *pImageList_GetImageInfo)(HIMAGELIST, int, IMAGEINFO *);
88 static BOOL (WINAPI *pImageList_Write)(HIMAGELIST, IStream *);
89 static HIMAGELIST (WINAPI *pImageList_Read)(IStream *);
90 static BOOL (WINAPI *pImageList_Copy)(HIMAGELIST, int, HIMAGELIST, int, UINT);
91 static HIMAGELIST (WINAPI *pImageList_LoadImageW)(HINSTANCE, LPCWSTR, int, int, COLORREF, UINT, UINT);
92 static BOOL (WINAPI *pImageList_Draw)(HIMAGELIST,INT,HDC,INT,INT,UINT);
93 
94 static HINSTANCE hinst;
95 
96 /* only used in interactive mode */
97 static void force_redraw(HWND hwnd)
98 {
99     if (!winetest_interactive)
100         return;
101 
102     RedrawWindow(hwnd, NULL, 0, RDW_UPDATENOW);
103     Sleep(1000);
104 }
105 
106 static BOOL is_v6_test(void)
107 {
108     return pHIMAGELIST_QueryInterface != NULL;
109 }
110 
111 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
112 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
113 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
114 #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), \
115   ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
116 #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)
117 #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), \
118   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), \
119   ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
120 
121 static const BYTE empty_bits[48*48/8];
122 
123 static const BYTE icon_bits[32*32/8] =
124 {
125   ROW32(0,0,0,0,0,0,0,0),
126   ROW32(0,0,1,1,1,1,0,0),
127   ROW32(0,1,1,1,1,1,1,0),
128   ROW32(0,1,1,0,0,1,1,0),
129   ROW32(0,1,1,0,0,1,1,0),
130   ROW32(0,1,1,1,1,1,1,0),
131   ROW32(0,0,1,1,1,1,0,0),
132   ROW32(0,0,0,0,0,0,0,0)
133 };
134 
135 static const BYTE bitmap_bits[48*48/8] =
136 {
137   ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
138   ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
139   ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
140   ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
141   ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
142   ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
143   ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
144   ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
145   ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
146   ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
147   ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
148   ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
149 };
150 
151 static HIMAGELIST createImageList(int cx, int cy)
152 {
153     /* Create an ImageList and put an image into it */
154     HIMAGELIST himl = pImageList_Create(cx, cy, ILC_COLOR, 1, 1);
155     HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
156 
157     ok(himl != NULL, "Failed to create image list, %d x %d.\n", cx, cy);
158     pImageList_Add(himl, hbm, NULL);
159     DeleteObject(hbm);
160     return himl;
161 }
162 
163 static HWND create_window(void)
164 {
165     char className[] = "bmwnd";
166     char winName[]   = "Test Bitmap";
167     HWND hWnd;
168     static BOOL registered = FALSE;
169 
170     if (!registered)
171     {
172         WNDCLASSA cls;
173 
174         cls.style         = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
175         cls.lpfnWndProc   = DefWindowProcA;
176         cls.cbClsExtra    = 0;
177         cls.cbWndExtra    = 0;
178         cls.hInstance     = 0;
179         cls.hIcon         = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
180         cls.hCursor       = LoadCursorA(0, (LPCSTR)IDC_ARROW);
181         cls.hbrBackground = GetStockObject (WHITE_BRUSH);
182         cls.lpszMenuName  = 0;
183         cls.lpszClassName = className;
184 
185         RegisterClassA (&cls);
186         registered = TRUE;
187     }
188 
189     /* Setup window */
190     hWnd = CreateWindowA (className, winName,
191        WS_OVERLAPPEDWINDOW ,
192        CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
193        0, hinst, 0);
194 
195     if (winetest_interactive)
196     {
197         ShowWindow (hWnd, SW_SHOW);
198         force_redraw (hWnd);
199     }
200 
201     return hWnd;
202 }
203 
204 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
205                       LPCSTR loc, BOOL clear)
206 {
207     HDC hdc;
208 
209     if (!winetest_interactive || !himl) return NULL;
210 
211     SetWindowTextA(hwnd, loc);
212     hdc = GetDC(hwnd);
213     pImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
214 
215     force_redraw(hwnd);
216 
217     if (clear)
218     {
219         BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
220         ReleaseDC(hwnd, hdc);
221         hdc = NULL;
222     }
223 
224     return hdc;
225 }
226 
227 /* Useful for checking differences */
228 static void dump_bits(const BYTE *p, const BYTE *q, int size)
229 {
230   int i, j;
231 
232   size /= 8;
233 
234   for (i = 0; i < size * 2; i++)
235   {
236       printf("|");
237       for (j = 0; j < size; j++)
238           printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
239       printf(" -- ");
240       for (j = 0; j < size; j++)
241           printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
242       printf("|\n");
243       p += size * 4;
244       q += size * 4;
245   }
246   printf("\n");
247 }
248 
249 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
250                        const BYTE *checkbits, LPCSTR loc)
251 {
252     BYTE bits[100*100/8];
253     COLORREF c;
254     HDC hdc;
255     int x, y, i = -1;
256 
257     if (!winetest_interactive || !himl) return;
258 
259     memset(bits, 0, sizeof(bits));
260     hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
261 
262     c = GetPixel(hdc, 0, 0);
263 
264     for (y = 0; y < size; y ++)
265     {
266         for (x = 0; x < size; x++)
267         {
268             if (!(x & 0x7)) i++;
269             if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
270         }
271     }
272 
273     BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
274     ReleaseDC(hwnd, hdc);
275 
276     ok (memcmp(bits, checkbits, (size * size)/8) == 0,
277         "%s: bits different\n", loc);
278     if (memcmp(bits, checkbits, (size * size)/8))
279         dump_bits(bits, checkbits, size);
280 }
281 
282 static void test_begindrag(void)
283 {
284     HIMAGELIST himl = createImageList(7,13);
285     HIMAGELIST drag;
286     BOOL ret;
287     int count;
288     POINT hotspot;
289 
290     count = pImageList_GetImageCount(himl);
291     ok(count > 2, "Tests need an ImageList with more than 2 images\n");
292 
293     /* Two BeginDrag() without EndDrag() in between */
294     ret = pImageList_BeginDrag(himl, 1, 0, 0);
295     drag = pImageList_GetDragImage(NULL, NULL);
296     ok(ret && drag, "ImageList_BeginDrag() failed\n");
297     ret = pImageList_BeginDrag(himl, 0, 3, 5);
298     ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
299     drag = pImageList_GetDragImage(NULL, &hotspot);
300     ok(!!drag, "No active ImageList drag left\n");
301     ok(hotspot.x == 0 && hotspot.y == 0, "New ImageList drag was created\n");
302     pImageList_EndDrag();
303     drag = pImageList_GetDragImage(NULL, NULL);
304     ok(!drag, "ImageList drag was not destroyed\n");
305 
306     /* Invalid image index */
307     pImageList_BeginDrag(himl, 0, 0, 0);
308     ret = pImageList_BeginDrag(himl, count, 3, 5);
309     ok(!ret, "ImageList_BeginDrag() returned TRUE\n");
310     drag = pImageList_GetDragImage(NULL, &hotspot);
311     ok(drag && hotspot.x == 0 && hotspot.y == 0, "Active drag should not have been canceled\n");
312     pImageList_EndDrag();
313     drag = pImageList_GetDragImage(NULL, NULL);
314     ok(!drag, "ImageList drag was not destroyed\n");
315     /* Invalid negative image indexes succeed */
316     ret = pImageList_BeginDrag(himl, -17, 0, 0);
317     drag = pImageList_GetDragImage(NULL, NULL);
318     ok(ret && drag, "ImageList drag was created\n");
319     pImageList_EndDrag();
320     ret = pImageList_BeginDrag(himl, -1, 0, 0);
321     drag = pImageList_GetDragImage(NULL, NULL);
322     ok(ret && drag, "ImageList drag was created\n");
323     pImageList_EndDrag();
324     pImageList_Destroy(himl);
325 }
326 
327 static void test_hotspot(void)
328 {
329     struct hotspot {
330         int dx;
331         int dy;
332     };
333 
334 #define SIZEX1 47
335 #define SIZEY1 31
336 #define SIZEX2 11
337 #define SIZEY2 17
338 #define HOTSPOTS_MAX 4       /* Number of entries in hotspots */
339     static const struct hotspot hotspots[HOTSPOTS_MAX] = {
340         { 10, 7 },
341         { SIZEX1, SIZEY1 },
342         { -9, -8 },
343         { -7, 35 }
344     };
345     int i, j, ret;
346     HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
347     HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
348     HWND hwnd = create_window();
349 
350 
351     for (i = 0; i < HOTSPOTS_MAX; i++) {
352         for (j = 0; j < HOTSPOTS_MAX; j++) {
353             int dx1 = hotspots[i].dx;
354             int dy1 = hotspots[i].dy;
355             int dx2 = hotspots[j].dx;
356             int dy2 = hotspots[j].dy;
357             int correctx, correcty, newx, newy;
358             char loc[256];
359             HIMAGELIST himlNew;
360             POINT ppt;
361 
362             ret = pImageList_BeginDrag(himl1, 0, dx1, dy1);
363             ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
364             sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
365             show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
366 
367             /* check merging the dragged image with a second image */
368             ret = pImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
369             ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
370                     dx1, dy1, dx2, dy2);
371             sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
372             show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
373 
374             /* check new hotspot, it should be the same like the old one */
375             himlNew = pImageList_GetDragImage(NULL, &ppt);
376             ok(ppt.x == dx1 && ppt.y == dy1,
377                     "Expected drag hotspot [%d,%d] got [%d,%d]\n",
378                     dx1, dy1, ppt.x, ppt.y);
379             /* check size of new dragged image */
380             pImageList_GetIconSize(himlNew, &newx, &newy);
381             correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
382             correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
383             ok(newx == correctx && newy == correcty,
384                     "Expected drag image size [%d,%d] got [%d,%d]\n",
385                     correctx, correcty, newx, newy);
386             sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
387             show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
388             pImageList_EndDrag();
389         }
390     }
391 #undef SIZEX1
392 #undef SIZEY1
393 #undef SIZEX2
394 #undef SIZEY2
395 #undef HOTSPOTS_MAX
396     pImageList_Destroy(himl2);
397     pImageList_Destroy(himl1);
398     DestroyWindow(hwnd);
399 }
400 
401 static void test_add_remove(void)
402 {
403     HIMAGELIST himl ;
404 
405     HICON hicon1 ;
406     HICON hicon2 ;
407     HICON hicon3 ;
408 
409     /* create an imagelist to play with */
410     himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
411     ok(himl!=0,"failed to create imagelist\n");
412 
413     /* load the icons to add to the image list */
414     hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
415     ok(hicon1 != 0, "no hicon1\n");
416     hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
417     ok(hicon2 != 0, "no hicon2\n");
418     hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
419     ok(hicon3 != 0, "no hicon3\n");
420 
421     /* remove when nothing exists */
422     ok(!pImageList_Remove(himl, 0), "Removed nonexistent icon.\n");
423     /* removing everything from an empty imagelist should succeed */
424     ok(pImageList_Remove(himl, -1), "Removed nonexistent icon\n");
425 
426     /* add three */
427     ok(0 == pImageList_ReplaceIcon(himl, -1, hicon1), "Failed to add icon1.\n");
428     ok(1 == pImageList_ReplaceIcon(himl, -1, hicon2), "Failed to add icon2.\n");
429     ok(2 == pImageList_ReplaceIcon(himl, -1, hicon3), "Failed to add icon3.\n");
430 
431     /* remove an index out of range */
432     ok(!pImageList_Remove(himl, 4711), "removed nonexistent icon\n");
433 
434     /* remove three */
435     ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
436     ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
437     ok(pImageList_Remove(himl, 0), "Can't remove 0\n");
438 
439     /* remove one extra */
440     ok(!pImageList_Remove(himl, 0), "Removed nonexistent icon.\n");
441 
442     /* destroy it */
443     ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
444 
445     ok(-1 == pImageList_ReplaceIcon((HIMAGELIST)0xdeadbeef, -1, hicon1), "Don't crash on bad handle\n");
446 
447     ok(DestroyIcon(hicon1), "Failed to destroy icon 1.\n");
448     ok(DestroyIcon(hicon2), "Failed to destroy icon 2.\n");
449     ok(DestroyIcon(hicon3), "Failed to destroy icon 3.\n");
450 }
451 
452 static void test_imagecount(void)
453 {
454     HIMAGELIST himl;
455 
456     ok(0 == pImageList_GetImageCount((HIMAGELIST)0xdeadbeef), "don't crash on bad handle\n");
457 
458     if (!pImageList_SetImageCount)
459     {
460         win_skip("ImageList_SetImageCount not available\n");
461         return;
462     }
463 
464     himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
465     ok(himl != 0, "Failed to create imagelist.\n");
466 
467     ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
468     ok(pImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
469     ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
470     ok(pImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
471     ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
472     ok(pImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
473 
474     ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
475 }
476 
477 static void test_DrawIndirect(void)
478 {
479     HIMAGELIST himl;
480 
481     HBITMAP hbm1;
482     HBITMAP hbm2;
483     HBITMAP hbm3;
484 
485     IMAGELISTDRAWPARAMS imldp;
486     HDC hdc;
487     HWND hwndfortest;
488 
489     if (!pImageList_DrawIndirect)
490     {
491         win_skip("ImageList_DrawIndirect not available, skipping test\n");
492         return;
493     }
494 
495     hwndfortest = create_window();
496     hdc = GetDC(hwndfortest);
497     ok(hdc!=NULL, "couldn't get DC\n");
498 
499     /* create an imagelist to play with */
500     himl = pImageList_Create(48, 48, ILC_COLOR16, 0, 3);
501     ok(himl != 0, "Failed to create imagelist.\n");
502 
503     /* load the icons to add to the image list */
504     hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
505     ok(hbm1 != 0, "no bitmap 1\n");
506     hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
507     ok(hbm2 != 0, "no bitmap 2\n");
508     hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
509     ok(hbm3 != 0, "no bitmap 3\n");
510 
511     /* add three */
512     ok(0 == pImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
513     ok(1 == pImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
514 
515     if (pImageList_SetImageCount)
516     {
517         ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
518         /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
519         ok(pImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
520     }
521 
522     memset(&imldp, 0, sizeof (imldp));
523     ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
524     imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
525     ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
526     imldp.hdcDst = hdc;
527     ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
528     imldp.himl = (HIMAGELIST)0xdeadbeef;
529     ok(!pImageList_DrawIndirect(&imldp),"bad himl succeeded!\n");
530     imldp.himl = himl;
531 
532     force_redraw(hwndfortest);
533 
534     imldp.fStyle = SRCCOPY;
535     imldp.rgbBk = CLR_DEFAULT;
536     imldp.rgbFg = CLR_DEFAULT;
537     imldp.y = 100;
538     imldp.x = 100;
539     ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
540     imldp.i ++;
541     ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
542     imldp.i ++;
543     ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
544     imldp.i ++;
545     ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
546 
547     /* remove three */
548     ok(pImageList_Remove(himl, 0), "removing 1st bitmap\n");
549     ok(pImageList_Remove(himl, 0), "removing 2nd bitmap\n");
550     ok(pImageList_Remove(himl, 0), "removing 3rd bitmap\n");
551 
552     /* destroy it */
553     ok(pImageList_Destroy(himl), "Failed to destroy imagelist.\n");
554 
555     /* bitmaps should not be deleted by the imagelist */
556     ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
557     ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
558     ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
559 
560     ReleaseDC(hwndfortest, hdc);
561     DestroyWindow(hwndfortest);
562 }
563 
564 static int get_color_format(HBITMAP bmp)
565 {
566     BITMAPINFO bmi;
567     HDC hdc = CreateCompatibleDC(0);
568     HBITMAP hOldBmp = SelectObject(hdc, bmp);
569     int ret;
570 
571     memset(&bmi, 0, sizeof(bmi));
572     bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
573     ret = GetDIBits(hdc, bmp, 0, 0, 0, &bmi, DIB_RGB_COLORS);
574     ok(ret, "GetDIBits failed\n");
575 
576     SelectObject(hdc, hOldBmp);
577     DeleteDC(hdc);
578     return bmi.bmiHeader.biBitCount;
579 }
580 
581 static void test_merge_colors(void)
582 {
583     HIMAGELIST himl[8], hmerge;
584     int sizes[] = { ILC_COLOR, ILC_COLOR | ILC_MASK, ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24, ILC_COLOR32, ILC_COLORDDB };
585     HICON hicon1;
586     IMAGEINFO info;
587     int bpp, i, j;
588 
589     hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
590     ok(hicon1 != NULL, "failed to create hicon1\n");
591 
592     for (i = 0; i < 8; i++)
593     {
594         himl[i] = pImageList_Create(32, 32, sizes[i], 0, 3);
595         ok(himl[i] != NULL, "failed to create himl[%d]\n", i);
596         ok(0 == pImageList_ReplaceIcon(himl[i], -1, hicon1), "Failed to add icon1 to himl[%d].\n", i);
597         if (i == 0 || i == 1 || i == 7)
598         {
599             pImageList_GetImageInfo(himl[i], 0, &info);
600             sizes[i] = get_color_format(info.hbmImage);
601         }
602     }
603     DestroyIcon(hicon1);
604     for (i = 0; i < 8; i++)
605         for (j = 0; j < 8; j++)
606         {
607             hmerge = pImageList_Merge(himl[i], 0, himl[j], 0, 0, 0);
608             ok(hmerge != NULL, "merge himl[%d], himl[%d] failed\n", i, j);
609 
610             pImageList_GetImageInfo(hmerge, 0, &info);
611             bpp = get_color_format(info.hbmImage);
612             /* ILC_COLOR[X] is defined as [X] */
613             if (i == 4 && j == 7)
614                 ok(bpp == 16, /* merging ILC_COLOR16 with ILC_COLORDDB seems to be a special case */
615                     "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
616             else
617                 ok(bpp == (i > j ? sizes[i] : sizes[j]),
618                     "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
619             ok(info.hbmMask != 0, "Imagelist merged from %d and %d had no mask\n", i, j);
620 
621             pImageList_Destroy(hmerge);
622         }
623 
624     for (i = 0; i < 8; i++)
625         pImageList_Destroy(himl[i]);
626 }
627 
628 static void test_merge(void)
629 {
630     HIMAGELIST himl1, himl2, hmerge;
631     HICON hicon1;
632     HWND hwnd = create_window();
633 
634     himl1 = pImageList_Create(32, 32, 0, 0, 3);
635     ok(himl1 != NULL,"failed to create himl1\n");
636 
637     himl2 = pImageList_Create(32, 32, 0, 0, 3);
638     ok(himl2 != NULL,"failed to create himl2\n");
639 
640     hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
641     ok(hicon1 != NULL, "failed to create hicon1\n");
642 
643     if (!himl1 || !himl2 || !hicon1)
644         return;
645 
646     ok(0 == pImageList_ReplaceIcon(himl2, -1, hicon1), "Failed to add icon1 to himl2.\n");
647     check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
648 
649     /* If himl1 has no images, merge still succeeds */
650     hmerge = pImageList_Merge(himl1, -1, himl2, 0, 0, 0);
651     ok(hmerge != NULL, "merge himl1,-1 failed\n");
652     check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
653     pImageList_Destroy(hmerge);
654 
655     hmerge = pImageList_Merge(himl1, 0, himl2, 0, 0, 0);
656     ok(hmerge != NULL,"merge himl1,0 failed\n");
657     check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
658     pImageList_Destroy(hmerge);
659 
660     /* Same happens if himl2 is empty */
661     pImageList_Destroy(himl2);
662     himl2 = pImageList_Create(32, 32, 0, 0, 3);
663     ok(himl2 != NULL,"failed to recreate himl2\n");
664     if (!himl2)
665         return;
666 
667     hmerge = pImageList_Merge(himl1, -1, himl2, -1, 0, 0);
668     ok(hmerge != NULL, "merge himl2,-1 failed\n");
669     check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
670     pImageList_Destroy(hmerge);
671 
672     hmerge = pImageList_Merge(himl1, -1, himl2, 0, 0, 0);
673     ok(hmerge != NULL, "merge himl2,0 failed\n");
674     check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
675     pImageList_Destroy(hmerge);
676 
677     /* Now try merging an image with itself */
678     ok(0 == pImageList_ReplaceIcon(himl2, -1, hicon1), "Failed to re-add icon1 to himl2.\n");
679 
680     hmerge = pImageList_Merge(himl2, 0, himl2, 0, 0, 0);
681     ok(hmerge != NULL, "merge himl2 with itself failed\n");
682     check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
683     pImageList_Destroy(hmerge);
684 
685     /* Try merging 2 different image lists */
686     ok(0 == pImageList_ReplaceIcon(himl1, -1, hicon1), "Failed to add icon1 to himl1.\n");
687 
688     hmerge = pImageList_Merge(himl1, 0, himl2, 0, 0, 0);
689     ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
690     check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
691     pImageList_Destroy(hmerge);
692 
693     hmerge = pImageList_Merge(himl1, 0, himl2, 0, 8, 16);
694     ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
695     check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
696     pImageList_Destroy(hmerge);
697 
698     pImageList_Destroy(himl1);
699     pImageList_Destroy(himl2);
700     DestroyIcon(hicon1);
701     DestroyWindow(hwnd);
702 }
703 
704 /*********************** imagelist storage test ***************************/
705 
706 #define BMP_CX 48
707 
708 struct memstream
709 {
710     IStream IStream_iface;
711     IStream *stream;
712 };
713 
714 static struct memstream *impl_from_IStream(IStream *iface)
715 {
716     return CONTAINING_RECORD(iface, struct memstream, IStream_iface);
717 }
718 
719 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(IStream *iface, REFIID riid,
720                                                             void **ppvObject)
721 {
722     ok(0, "unexpected call\n");
723     return E_NOTIMPL;
724 }
725 
726 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(IStream *iface)
727 {
728     ok(0, "unexpected call\n");
729     return 2;
730 }
731 
732 static ULONG STDMETHODCALLTYPE Test_Stream_Release(IStream *iface)
733 {
734     ok(0, "unexpected call\n");
735     return 1;
736 }
737 
738 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(IStream *iface, void *pv, ULONG cb,
739                                                   ULONG *pcbRead)
740 {
741     struct memstream *stream = impl_from_IStream(iface);
742     return IStream_Read(stream->stream, pv, cb, pcbRead);
743 }
744 
745 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(IStream *iface, const void *pv, ULONG cb,
746                                                    ULONG *pcbWritten)
747 {
748     struct memstream *stream = impl_from_IStream(iface);
749     return IStream_Write(stream->stream, pv, cb, pcbWritten);
750 }
751 
752 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(IStream *iface, LARGE_INTEGER offset, DWORD origin,
753         ULARGE_INTEGER *new_pos)
754 {
755     struct memstream *stream = impl_from_IStream(iface);
756 
757     if (is_v6_test())
758     {
759         ok(origin == STREAM_SEEK_CUR, "Unexpected origin %d.\n", origin);
760         ok(offset.QuadPart == 0, "Unexpected offset %s.\n", wine_dbgstr_longlong(offset.QuadPart));
761         ok(new_pos != NULL, "Unexpected out position pointer.\n");
762         return IStream_Seek(stream->stream, offset, origin, new_pos);
763     }
764     else
765     {
766         ok(0, "unexpected call\n");
767         return E_NOTIMPL;
768     }
769 }
770 
771 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
772 {
773     ok(0, "unexpected call\n");
774     return E_NOTIMPL;
775 }
776 
777 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(IStream *iface, IStream *pstm,
778                                                     ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead,
779                                                     ULARGE_INTEGER *pcbWritten)
780 {
781     ok(0, "unexpected call\n");
782     return E_NOTIMPL;
783 }
784 
785 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(IStream *iface, DWORD grfCommitFlags)
786 {
787     ok(0, "unexpected call\n");
788     return E_NOTIMPL;
789 }
790 
791 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(IStream *iface)
792 {
793     ok(0, "unexpected call\n");
794     return E_NOTIMPL;
795 }
796 
797 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
798                                                         ULARGE_INTEGER cb, DWORD dwLockType)
799 {
800     ok(0, "unexpected call\n");
801     return E_NOTIMPL;
802 }
803 
804 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
805                                                           ULARGE_INTEGER cb, DWORD dwLockType)
806 {
807     ok(0, "unexpected call\n");
808     return E_NOTIMPL;
809 }
810 
811 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(IStream *iface, STATSTG *pstatstg,
812                                                   DWORD grfStatFlag)
813 {
814     ok(0, "unexpected call\n");
815     return E_NOTIMPL;
816 }
817 
818 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(IStream *iface, IStream **ppstm)
819 {
820     ok(0, "unexpected call\n");
821     return E_NOTIMPL;
822 }
823 
824 static const IStreamVtbl Test_Stream_Vtbl =
825 {
826     Test_Stream_QueryInterface,
827     Test_Stream_AddRef,
828     Test_Stream_Release,
829     Test_Stream_Read,
830     Test_Stream_Write,
831     Test_Stream_Seek,
832     Test_Stream_SetSize,
833     Test_Stream_CopyTo,
834     Test_Stream_Commit,
835     Test_Stream_Revert,
836     Test_Stream_LockRegion,
837     Test_Stream_UnlockRegion,
838     Test_Stream_Stat,
839     Test_Stream_Clone
840 };
841 
842 static void init_memstream(struct memstream *stream)
843 {
844     HRESULT hr;
845 
846     stream->IStream_iface.lpVtbl = &Test_Stream_Vtbl;
847     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream->stream);
848     ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
849 }
850 
851 static void cleanup_memstream(struct memstream *stream)
852 {
853     IStream_Release(stream->stream);
854 }
855 
856 static INT DIB_GetWidthBytes( int width, int bpp )
857 {
858     return ((width * bpp + 31) / 8) & ~3;
859 }
860 
861 static ULONG check_bitmap_data(const ILHEAD *header, const char *bm_data,
862     ULONG bm_data_size, const SIZE *bmpsize, INT bpp, const char *comment)
863 {
864     const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
865     const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
866     ULONG hdr_size, image_size;
867 
868     hdr_size = sizeof(*bmfh) + sizeof(*bmih);
869     if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
870 
871     ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
872     ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
873     ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
874     ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
875     ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
876 
877     ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
878     ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
879     ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
880 
881     image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
882     ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
883     ok(bmih->biWidth == bmpsize->cx && bmih->biHeight == bmpsize->cy, "Unexpected bitmap size %d x %d, "
884             "expected %d x %d\n", bmih->biWidth, bmih->biHeight, bmpsize->cx, bmpsize->cy);
885 
886 if (0)
887 {
888     char fname[256];
889     FILE *f;
890     sprintf(fname, "bmp_%s.bmp", comment);
891     f = fopen(fname, "wb");
892     fwrite(bm_data, 1, bm_data_size, f);
893     fclose(f);
894 }
895 
896     return hdr_size + image_size;
897 }
898 
899 static BOOL is_v6_header(const ILHEAD *header)
900 {
901     return (header->usVersion & 0xff00) == 0x600;
902 }
903 
904 static void check_ilhead_data(const ILHEAD *ilh, INT cx, INT cy, INT cur, INT max, INT grow, INT flags)
905 {
906     INT grow_aligned;
907 
908     ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
909     ok(ilh->usVersion == 0x101 ||
910             ilh->usVersion == 0x600 || /* WinXP/W2k3 */
911             ilh->usVersion == 0x620, "Unknown usVersion %#x.\n", ilh->usVersion);
912     ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
913 
914     grow = max(grow, 1);
915     grow_aligned = (WORD)(grow + 3) & ~3;
916 
917     if (is_v6_header(ilh))
918     {
919         grow = (WORD)(grow + 2 + 3) & ~3;
920         ok(ilh->cGrow == grow || broken(ilh->cGrow == grow_aligned) /* XP/Vista */,
921             "Unexpected cGrow %d, expected %d\n", ilh->cGrow, grow);
922     }
923     else
924     {
925         ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
926         ok(ilh->cGrow == grow_aligned, "Unexpected cGrow %d, expected %d\n", ilh->cGrow, grow_aligned);
927     }
928 
929     ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
930     ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
931     ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
932     ok(ilh->flags == flags || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4),  /* <= w2k */
933        "wrong flags %04x\n", ilh->flags);
934     ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
935     ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
936     ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
937     ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
938 }
939 
940 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
941 {
942     HDC hdc;
943     BITMAPINFO bmi;
944     HBITMAP hbmp, hbmp_old;
945     HBRUSH hbrush;
946     RECT rc = { 0, 0, cx, cy };
947 
948     hdc = CreateCompatibleDC(0);
949 
950     memset(&bmi, 0, sizeof(bmi));
951     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
952     bmi.bmiHeader.biHeight = cx;
953     bmi.bmiHeader.biWidth = cy;
954     bmi.bmiHeader.biBitCount = 24;
955     bmi.bmiHeader.biPlanes = 1;
956     bmi.bmiHeader.biCompression = BI_RGB;
957     hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
958 
959     hbmp_old = SelectObject(hdc, hbmp);
960 
961     hbrush = CreateSolidBrush(color);
962     FillRect(hdc, &rc, hbrush);
963     DeleteObject(hbrush);
964 
965     DrawTextA(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
966 
967     SelectObject(hdc, hbmp_old);
968     DeleteDC(hdc);
969 
970     return hbmp;
971 }
972 
973 static inline void imagelist_get_bitmap_size(const ILHEAD *header, SIZE *sz)
974 {
975     const int tile_count = 4;
976 
977     if (is_v6_header(header))
978     {
979         sz->cx = header->cx;
980         sz->cy = header->cMaxImage * header->cy;
981     }
982     else
983     {
984         sz->cx = header->cx * tile_count;
985         sz->cy = ((header->cMaxImage + tile_count - 1) / tile_count) * header->cy;
986     }
987 }
988 
989 /* Grow argument matches what was used when imagelist was created. */
990 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
991         INT flags, const char *comment)
992 {
993     INT ret, cxx, cyy, size;
994     struct memstream stream;
995     const ILHEAD *header;
996     LARGE_INTEGER mv;
997     HIMAGELIST himl2;
998     HGLOBAL hglobal;
999     STATSTG stat;
1000     char *data;
1001     HRESULT hr;
1002     SIZE bmpsize;
1003     BOOL b;
1004 
1005     ret = pImageList_GetImageCount(himl);
1006     ok(ret == cur, "%s: expected image count %d got %d\n", comment, cur, ret);
1007 
1008     ret = pImageList_GetIconSize(himl, &cxx, &cyy);
1009     ok(ret, "ImageList_GetIconSize failed\n");
1010     ok(cxx == cx, "%s: wrong cx %d (expected %d)\n", comment, cxx, cx);
1011     ok(cyy == cy, "%s: wrong cy %d (expected %d)\n", comment, cyy, cy);
1012 
1013     init_memstream(&stream);
1014     b = pImageList_Write(himl, &stream.IStream_iface);
1015     ok(b, "%s: ImageList_Write failed\n", comment);
1016 
1017     hr = GetHGlobalFromStream(stream.stream, &hglobal);
1018     ok(hr == S_OK, "%s: Failed to get hglobal, %#x\n", comment, hr);
1019 
1020     hr = IStream_Stat(stream.stream, &stat, STATFLAG_NONAME);
1021     ok(hr == S_OK, "Stat() failed, hr %#x.\n", hr);
1022 
1023     data = GlobalLock(hglobal);
1024 
1025     ok(data != 0, "%s: ImageList_Write didn't write any data\n", comment);
1026     ok(stat.cbSize.LowPart > sizeof(ILHEAD), "%s: ImageList_Write wrote not enough data\n", comment);
1027 
1028     header = (const ILHEAD *)data;
1029     check_ilhead_data(header, cx, cy, cur, max, grow, flags);
1030     imagelist_get_bitmap_size(header, &bmpsize);
1031     size = check_bitmap_data(header, data + sizeof(ILHEAD), stat.cbSize.LowPart - sizeof(ILHEAD),
1032             &bmpsize, flags & 0xfe, comment);
1033     if (!is_v6_header(header) && size < stat.cbSize.LowPart - sizeof(ILHEAD))  /* mask is present */
1034     {
1035         ok( flags & ILC_MASK, "%s: extra data %u/%u but mask not expected\n", comment, stat.cbSize.LowPart, size );
1036         check_bitmap_data(header, data + sizeof(ILHEAD) + size, stat.cbSize.LowPart - sizeof(ILHEAD) - size,
1037             &bmpsize, 1, comment);
1038     }
1039 
1040     /* rewind and reconstruct from stream */
1041     mv.QuadPart = 0;
1042     IStream_Seek(stream.stream, mv, STREAM_SEEK_SET, NULL);
1043     himl2 = pImageList_Read(&stream.IStream_iface);
1044     ok(himl2 != NULL, "%s: Failed to deserialize imagelist\n", comment);
1045     pImageList_Destroy(himl2);
1046 
1047     GlobalUnlock(hglobal);
1048     cleanup_memstream(&stream);
1049 }
1050 
1051 static void image_list_add_bitmap(HIMAGELIST himl, BYTE grey, int i)
1052 {
1053     char comment[16];
1054     HBITMAP hbm;
1055     int ret;
1056 
1057     sprintf(comment, "%d", i);
1058     hbm = create_bitmap(BMP_CX, BMP_CX, RGB(grey, grey, grey), comment);
1059     ret = pImageList_Add(himl, hbm, NULL);
1060     ok(ret != -1, "Failed to add image to imagelist.\n");
1061     DeleteObject(hbm);
1062 }
1063 
1064 static void image_list_init(HIMAGELIST himl, INT grow)
1065 {
1066     unsigned int i;
1067     static const struct test_data
1068     {
1069         BYTE grey;
1070         INT cx, cy, cur, max, bpp;
1071         const char *comment;
1072     } td[] =
1073     {
1074         { 255, BMP_CX, BMP_CX, 1, 2, 24, "total 1" },
1075         { 170, BMP_CX, BMP_CX, 2, 7, 24, "total 2" },
1076         { 85, BMP_CX, BMP_CX, 3, 7, 24, "total 3" },
1077         { 0, BMP_CX, BMP_CX, 4, 7, 24, "total 4" },
1078         { 0, BMP_CX, BMP_CX, 5, 7, 24, "total 5" },
1079         { 85, BMP_CX, BMP_CX, 6, 7, 24, "total 6" },
1080         { 170, BMP_CX, BMP_CX, 7, 12, 24, "total 7" },
1081         { 255, BMP_CX, BMP_CX, 8, 12, 24, "total 8" },
1082         { 255, BMP_CX, BMP_CX, 9, 12, 24, "total 9" },
1083         { 170, BMP_CX, BMP_CX, 10, 12, 24, "total 10" },
1084         { 85, BMP_CX, BMP_CX, 11, 12, 24, "total 11" },
1085         { 0, BMP_CX, BMP_CX, 12, 17, 24, "total 12" },
1086         { 0, BMP_CX, BMP_CX, 13, 17, 24, "total 13" },
1087         { 85, BMP_CX, BMP_CX, 14, 17, 24, "total 14" },
1088         { 170, BMP_CX, BMP_CX, 15, 17, 24, "total 15" },
1089         { 255, BMP_CX, BMP_CX, 16, 17, 24, "total 16" },
1090         { 255, BMP_CX, BMP_CX, 17, 22, 24, "total 17" },
1091         { 170, BMP_CX, BMP_CX, 18, 22, 24, "total 18" },
1092         { 85, BMP_CX, BMP_CX, 19, 22, 24, "total 19" },
1093         { 0, BMP_CX, BMP_CX, 20, 22, 24, "total 20" },
1094         { 0, BMP_CX, BMP_CX, 21, 22, 24, "total 21" },
1095         { 85, BMP_CX, BMP_CX, 22, 27, 24, "total 22" },
1096         { 170, BMP_CX, BMP_CX, 23, 27, 24, "total 23" },
1097         { 255, BMP_CX, BMP_CX, 24, 27, 24, "total 24" }
1098     };
1099 
1100     check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, grow, ILC_COLOR24, "total 0");
1101 
1102     for (i = 0; i < ARRAY_SIZE(td); i++)
1103     {
1104         image_list_add_bitmap(himl, td[i].grey, i + 1);
1105         check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, grow, td[i].bpp, td[i].comment);
1106     }
1107 }
1108 
1109 static void test_imagelist_storage(void)
1110 {
1111     HIMAGELIST himl;
1112     INT ret, grow;
1113     HBITMAP hbm;
1114     HICON icon;
1115 
1116     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
1117     ok(himl != 0, "ImageList_Create failed\n");
1118 
1119     check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 1, ILC_COLOR24, "empty");
1120 
1121     image_list_init(himl, 1);
1122     check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 1, ILC_COLOR24, "orig");
1123 
1124     ret = pImageList_Remove(himl, 4);
1125     ok(ret, "ImageList_Remove failed\n");
1126     check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 1, ILC_COLOR24, "1");
1127 
1128     ret = pImageList_Remove(himl, 5);
1129     ok(ret, "ImageList_Remove failed\n");
1130     check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 1, ILC_COLOR24, "2");
1131 
1132     ret = pImageList_Remove(himl, 6);
1133     ok(ret, "ImageList_Remove failed\n");
1134     check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 1, ILC_COLOR24, "3");
1135 
1136     ret = pImageList_Remove(himl, 7);
1137     ok(ret, "ImageList_Remove failed\n");
1138     check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "4");
1139 
1140     ret = pImageList_Remove(himl, -2);
1141     ok(!ret, "ImageList_Remove(-2) should fail\n");
1142     check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "5");
1143 
1144     ret = pImageList_Remove(himl, 20);
1145     ok(!ret, "ImageList_Remove(20) should fail\n");
1146     check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "6");
1147 
1148     ret = pImageList_Remove(himl, -1);
1149     ok(ret, "ImageList_Remove(-1) failed\n");
1150     check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 1, ILC_COLOR24, "7");
1151 
1152     ret = pImageList_Destroy(himl);
1153     ok(ret, "ImageList_Destroy failed\n");
1154 
1155     /* test ImageList_Create storage allocation */
1156 
1157     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
1158     ok(himl != 0, "ImageList_Create failed\n");
1159     check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, ILC_COLOR24, "init 0 grow 32");
1160     hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1161     ret = pImageList_Add(himl, hbm, NULL);
1162     ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1163     check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, ILC_COLOR24, "add 1 x 9");
1164     DeleteObject(hbm);
1165     ret = pImageList_Destroy(himl);
1166     ok(ret, "ImageList_Destroy failed\n");
1167 
1168     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1169     ok(himl != 0, "ImageList_Create failed\n");
1170     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, ILC_COLOR24, "init 4 grow 4");
1171     hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1172     ret = pImageList_Add(himl, hbm, NULL);
1173     ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1174     check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, ILC_COLOR24, "add 9 x 1");
1175     ret = pImageList_Add(himl, hbm, NULL);
1176     ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1177     check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, ILC_COLOR24, "add 9 x 1");
1178     DeleteObject(hbm);
1179     ret = pImageList_Destroy(himl);
1180     ok(ret, "ImageList_Destroy failed\n");
1181 
1182     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1183     ok(himl != 0, "ImageList_Create failed\n");
1184     check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 209, ILC_COLOR24, "init 207 grow 209");
1185     ret = pImageList_Destroy(himl);
1186     ok(ret, "ImageList_Destroy failed\n");
1187 
1188     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1189     ok(himl != 0, "ImageList_Create failed\n");
1190     check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 207, ILC_COLOR24, "init 209 grow 207");
1191     ret = pImageList_Destroy(himl);
1192     ok(ret, "ImageList_Destroy failed\n");
1193 
1194     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1195     ok(himl != 0, "ImageList_Create failed\n");
1196     check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, ILC_COLOR24, "init 14 grow 4");
1197     ret = pImageList_Destroy(himl);
1198     ok(ret, "ImageList_Destroy failed\n");
1199 
1200     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1201     ok(himl != 0, "ImageList_Create failed\n");
1202     check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 9, ILC_COLOR24, "init 5 grow 9");
1203     ret = pImageList_Destroy(himl);
1204     ok(ret, "ImageList_Destroy failed\n");
1205 
1206     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1207     ok(himl != 0, "ImageList_Create failed\n");
1208     check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 5, ILC_COLOR24, "init 9 grow 5");
1209     ret = pImageList_Destroy(himl);
1210     ok(ret, "ImageList_Destroy failed\n");
1211 
1212     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1213     ok(himl != 0, "ImageList_Create failed\n");
1214     check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, ILC_COLOR24, "init 2 grow 4");
1215     ret = pImageList_Destroy(himl);
1216     ok(ret, "ImageList_Destroy failed\n");
1217 
1218     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1219     ok(himl != 0, "ImageList_Create failed\n");
1220     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR24, "init 4 grow 2");
1221     ret = pImageList_Destroy(himl);
1222     ok(ret, "ImageList_Destroy failed\n");
1223 
1224     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1225     ok(himl != 0, "ImageList_Create failed\n");
1226     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR8, "bpp 8");
1227     ret = pImageList_Destroy(himl);
1228     ok(ret, "ImageList_Destroy failed\n");
1229 
1230     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1231     ok(himl != 0, "ImageList_Create failed\n");
1232     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4, "bpp 4");
1233     ret = pImageList_Destroy(himl);
1234     ok(ret, "ImageList_Destroy failed\n");
1235 
1236     himl = pImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1237     ok(himl != 0, "ImageList_Create failed\n");
1238     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4, "bpp default");
1239     icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1240     ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1241     ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1242     DestroyIcon( icon );
1243     check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR4, "bpp default");
1244     ret = pImageList_Destroy(himl);
1245     ok(ret, "ImageList_Destroy failed\n");
1246 
1247     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1248     ok(himl != 0, "ImageList_Create failed\n");
1249     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1250     icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1251     ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1252     ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1253     DestroyIcon( icon );
1254     check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1255     ret = pImageList_Destroy(himl);
1256     ok(ret, "ImageList_Destroy failed\n");
1257 
1258     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1259     ok(himl != 0, "ImageList_Create failed\n");
1260     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1261     icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1262     ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1263     ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1264     DestroyIcon( icon );
1265     check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1266     ret = pImageList_Destroy(himl);
1267     ok(ret, "ImageList_Destroy failed\n");
1268 
1269     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1270     ok(himl != 0, "ImageList_Create failed\n");
1271     check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99");
1272     icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1273     ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1274     ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1275     check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 2 icons");
1276     ok( pImageList_ReplaceIcon(himl, -1, icon) == 2, "Failed to add icon\n");
1277     DestroyIcon( icon );
1278     check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 3 icons");
1279     ok( pImageList_Remove(himl, -1) == TRUE, "Failed to remove icon.\n");
1280     check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 empty");
1281     ok( pImageList_SetImageCount(himl, 22) == TRUE, "Failed to set image count.\n");
1282     check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 22");
1283     ok( pImageList_SetImageCount(himl, 0) == TRUE, "Failed to set image count.\n");
1284     check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 0");
1285     ok( pImageList_SetImageCount(himl, 42) == TRUE, "Failed to set image count.\n");
1286     check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 42");
1287     ret = pImageList_Destroy(himl);
1288     ok(ret, "ImageList_Destroy failed\n");
1289 
1290     for (grow = 1; grow <= 16; grow++)
1291     {
1292         himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, grow);
1293         ok(himl != 0, "ImageList_Create failed\n");
1294         check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, grow, ILC_COLOR4|ILC_MASK, "grow test");
1295         ret = pImageList_Destroy(himl);
1296         ok(ret, "ImageList_Destroy failed\n");
1297     }
1298 
1299     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1300     ok(himl != 0, "ImageList_Create failed\n");
1301     check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, -20, ILC_COLOR4|ILC_MASK, "init 2 grow -20");
1302     ret = pImageList_Destroy(himl);
1303     ok(ret, "ImageList_Destroy failed\n");
1304 
1305     /* Version 6 implementation hangs on large grow values. */
1306     if (!is_v6_test())
1307     {
1308         himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1309         ok(himl != 0, "ImageList_Create failed\n");
1310         check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 65536+12, ILC_COLOR4|ILC_MASK, "init 2 grow 65536+12");
1311         ret = pImageList_Destroy(himl);
1312         ok(ret, "ImageList_Destroy failed\n");
1313 
1314         himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1315         ok(himl != 0, "ImageList_Create failed\n");
1316         check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 65535, ILC_COLOR4|ILC_MASK, "init 2 grow 65535");
1317         ret = pImageList_Destroy(himl);
1318         ok(ret, "ImageList_Destroy failed\n");
1319     }
1320 }
1321 
1322 static void test_shell_imagelist(void)
1323 {
1324     HRESULT (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1325     IImageList *iml = NULL;
1326     HMODULE hShell32;
1327     HRESULT hr;
1328     int out = 0;
1329     RECT rect;
1330     int cx, cy;
1331 
1332     /* Try to load function from shell32 */
1333     hShell32 = LoadLibraryA("shell32.dll");
1334     pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1335 
1336     if (!pSHGetImageList)
1337     {
1338         win_skip("SHGetImageList not available, skipping test\n");
1339         FreeLibrary(hShell32);
1340         return;
1341     }
1342 
1343     /* Get system image list */
1344     hr = pSHGetImageList(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1345     ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1346 
1347     if (hr != S_OK) {
1348         FreeLibrary(hShell32);
1349         return;
1350     }
1351 
1352     IImageList_GetImageCount(iml, &out);
1353     ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1354 
1355     /* Fetch the small icon size */
1356     cx = GetSystemMetrics(SM_CXSMICON);
1357     cy = GetSystemMetrics(SM_CYSMICON);
1358 
1359     /* Check icon size matches */
1360     IImageList_GetImageRect(iml, 0, &rect);
1361     ok(((rect.right == cx) && (rect.bottom == cy)),
1362                  "IImageList_GetImageRect returned r:%d,b:%d\n",
1363                  rect.right, rect.bottom);
1364 
1365     IImageList_Release(iml);
1366     FreeLibrary(hShell32);
1367 }
1368 
1369 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1370 {
1371     HBITMAP hBitmap;
1372     UINT32 *buffer = NULL;
1373     BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1374                                 0, 0, 0, 0, 0}};
1375 
1376     hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1377     ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1378 
1379     if(!hBitmap || !buffer)
1380     {
1381         DeleteObject(hBitmap);
1382         return NULL;
1383     }
1384 
1385     buffer[0] = pixel1;
1386     buffer[1] = pixel2;
1387 
1388     return hBitmap;
1389 }
1390 
1391 static BOOL colour_match(UINT32 x, UINT32 y)
1392 {
1393     const INT32 tolerance = 8;
1394 
1395     const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1396     const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1397     const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1398 
1399     return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1400 }
1401 
1402 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1403                                          UINT32 expected, int line)
1404 {
1405     bits[0] = 0x00FFFFFF;
1406     pImageList_DrawIndirect(ildp);
1407     ok(colour_match(bits[0], expected),
1408        "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1409        bits[0] & 0x00FFFFFF, expected, line);
1410 }
1411 
1412 
1413 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1414                                                 UINT fStyle, UINT32 expected, int line)
1415 {
1416     IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1417         0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1418     check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1419 }
1420 
1421 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1422                                                 DWORD dwRop, UINT32 expected, int line)
1423 {
1424     IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1425         0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1426     check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1427 }
1428 
1429 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1430                                                 UINT fState, DWORD Frame, UINT32 expected, int line)
1431 {
1432     IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1433         0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1434     check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1435 }
1436 
1437 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1438                                                 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1439                                                 UINT32 broken_expected, int line)
1440 {
1441     IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1442         0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1443     bits[0] = 0x00FFFFFF;
1444     pImageList_DrawIndirect(&ildp);
1445     ok(colour_match(bits[0], expected) ||
1446        broken(colour_match(bits[0], broken_expected)),
1447        "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1448        bits[0] & 0x00FFFFFF, expected, line);
1449 }
1450 
1451 static void test_ImageList_DrawIndirect(void)
1452 {
1453     HIMAGELIST himl = NULL;
1454     int ret;
1455     HDC hdcDst = NULL;
1456     HBITMAP hbmOld = NULL, hbmDst = NULL;
1457     HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1458     HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1459     int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1460     UINT32 *bits = 0;
1461     UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1462     int bpp, broken_value;
1463 
1464     BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1465                                 0, 0, 0, 0, 0}};
1466 
1467     hdcDst = CreateCompatibleDC(0);
1468     ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1469     if (!hdcDst)
1470         return;
1471     bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1472 
1473     hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1474     ok(hbmMask != 0, "CreateBitmap failed\n");
1475     if(!hbmMask) goto cleanup;
1476 
1477     hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1478     ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1479     if(!hbmInverseMask) goto cleanup;
1480 
1481     himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1482     ok(himl != 0, "ImageList_Create failed\n");
1483     if(!himl) goto cleanup;
1484 
1485     /* Add a no-alpha image */
1486     hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1487     if(!hbmImage) goto cleanup;
1488 
1489     iImage = pImageList_Add(himl, hbmImage, hbmMask);
1490     ok(iImage != -1, "ImageList_Add failed\n");
1491     if(iImage == -1) goto cleanup;
1492 
1493     /* Add an alpha image */
1494     hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1495     if(!hbmAlphaImage) goto cleanup;
1496 
1497     iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1498     ok(iAlphaImage != -1, "ImageList_Add failed\n");
1499     if(iAlphaImage == -1) goto cleanup;
1500 
1501     /* Add a transparent alpha image */
1502     hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1503     if(!hbmTransparentImage) goto cleanup;
1504 
1505     iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1506     ok(iTransparentImage != -1, "ImageList_Add failed\n");
1507     if(iTransparentImage == -1) goto cleanup;
1508 
1509     /* 32-bit Tests */
1510     bitmapInfo.bmiHeader.biBitCount = 32;
1511     hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1512     ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1513     if (!hbmDst || !bits)
1514         goto cleanup;
1515     hbmOld = SelectObject(hdcDst, hbmDst);
1516 
1517     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1518     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1519     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1520     if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1521     else broken_value = 0x00B4BDC4;
1522     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1523     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1524     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1525     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1526 
1527     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1528     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1529 
1530     if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1531     else broken_value =  0x009DA8B1;
1532     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1533     if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1534     else broken_value =  0x008C99A3;
1535     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1536     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1537     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1538     todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1539 
1540     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1541 
1542     check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1543     check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1544 
1545     /* ILD_ROP is ignored when the image has an alpha channel */
1546     check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1547     check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1548 
1549     todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1550     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1551 
1552     check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1553     check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1554 
1555     check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1556     check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1557     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1558 
1559 cleanup:
1560 
1561     if(hbmOld)
1562         SelectObject(hdcDst, hbmOld);
1563     if(hbmDst)
1564         DeleteObject(hbmDst);
1565 
1566     if(hdcDst)
1567         DeleteDC(hdcDst);
1568 
1569     if(hbmMask)
1570         DeleteObject(hbmMask);
1571     if(hbmInverseMask)
1572         DeleteObject(hbmInverseMask);
1573 
1574     if(hbmImage)
1575         DeleteObject(hbmImage);
1576     if(hbmAlphaImage)
1577         DeleteObject(hbmAlphaImage);
1578     if(hbmTransparentImage)
1579         DeleteObject(hbmTransparentImage);
1580 
1581     if(himl)
1582     {
1583         ret = pImageList_Destroy(himl);
1584         ok(ret, "ImageList_Destroy failed\n");
1585     }
1586 }
1587 
1588 static void test_iimagelist(void)
1589 {
1590     IImageList *imgl, *imgl2;
1591     IImageList2 *imagelist;
1592     HIMAGELIST himl;
1593     HRESULT hr;
1594     ULONG ret;
1595 
1596     if (!pHIMAGELIST_QueryInterface)
1597     {
1598         win_skip("XP imagelist functions not available\n");
1599         return;
1600     }
1601 
1602     /* test reference counting on destruction */
1603     imgl = (IImageList*)createImageList(32, 32);
1604     ret = IImageList_AddRef(imgl);
1605     ok(ret == 2, "Expected 2, got %d\n", ret);
1606     ret = pImageList_Destroy((HIMAGELIST)imgl);
1607     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1608     ret = pImageList_Destroy((HIMAGELIST)imgl);
1609     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1610     ret = pImageList_Destroy((HIMAGELIST)imgl);
1611     ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1612 
1613     imgl = (IImageList*)createImageList(32, 32);
1614     ret = IImageList_AddRef(imgl);
1615     ok(ret == 2, "Expected 2, got %d\n", ret);
1616     ret = pImageList_Destroy((HIMAGELIST)imgl);
1617     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1618     ret = IImageList_Release(imgl);
1619     ok(ret == 0, "Expected 0, got %d\n", ret);
1620     ret = pImageList_Destroy((HIMAGELIST)imgl);
1621     ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1622 
1623     /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1624     imgl = (IImageList*)createImageList(32, 32);
1625     hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1626     ok(hr == S_OK, "got 0x%08x\n", hr);
1627     ok(imgl2 == imgl, "got different pointer\n");
1628     ret = IImageList_Release(imgl);
1629     ok(ret == 1, "got %u\n", ret);
1630     IImageList_Release(imgl);
1631 
1632     if (!pImageList_CoCreateInstance)
1633     {
1634         win_skip("Vista imagelist functions not available\n");
1635         return;
1636     }
1637 
1638     hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1639     ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1640 
1641     if (hr == S_OK)
1642         IImageList_Release(imgl);
1643 
1644     himl = createImageList(32, 32);
1645 
1646     if (!himl)
1647         return;
1648 
1649     hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1650     ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1651 
1652     if (hr == S_OK)
1653         IImageList_Release(imgl);
1654 
1655     pImageList_Destroy(himl);
1656 
1657     /* IImageList2 */
1658     hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList2, (void**)&imagelist);
1659     if (hr != S_OK)
1660     {
1661         win_skip("IImageList2 is not supported.\n");
1662         return;
1663     }
1664     ok(hr == S_OK, "got 0x%08x\n", hr);
1665     IImageList2_Release(imagelist);
1666 }
1667 
1668 static void test_IImageList_Add_Remove(void)
1669 {
1670     IImageList *imgl;
1671     HIMAGELIST himl;
1672     HRESULT hr;
1673 
1674     HICON hicon1;
1675     HICON hicon2;
1676     HICON hicon3;
1677 
1678     int ret;
1679 
1680     /* create an imagelist to play with */
1681     himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1682     ok(himl != 0,"failed to create imagelist\n");
1683 
1684     imgl = (IImageList *) himl;
1685 
1686     /* load the icons to add to the image list */
1687     hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1688     ok(hicon1 != 0, "no hicon1\n");
1689     hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1690     ok(hicon2 != 0, "no hicon2\n");
1691     hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1692     ok(hicon3 != 0, "no hicon3\n");
1693 
1694     /* remove when nothing exists */
1695     hr = IImageList_Remove(imgl, 0);
1696     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1697 
1698     /* removing everything from an empty imagelist should succeed */
1699     hr = IImageList_Remove(imgl, -1);
1700     ok(hr == S_OK, "removed nonexistent icon\n");
1701 
1702     /* add three */
1703     ret = -1;
1704     ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1705     ret = -1;
1706     ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1707     ret = -1;
1708     ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1709 
1710     /* remove an index out of range */
1711     ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1712 
1713     /* remove three */
1714     ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1715     ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1716     ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1717 
1718     /* remove one extra */
1719     ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1720 
1721     IImageList_Release(imgl);
1722     ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1723     ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1724     ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1725 }
1726 
1727 static void test_IImageList_Get_SetImageCount(void)
1728 {
1729     IImageList *imgl;
1730     HIMAGELIST himl;
1731     HRESULT hr;
1732     INT ret;
1733 
1734     /* create an imagelist to play with */
1735     himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1736     ok(himl != 0,"failed to create imagelist\n");
1737 
1738     imgl = (IImageList *) himl;
1739 
1740     /* check SetImageCount/GetImageCount */
1741     hr = IImageList_SetImageCount(imgl, 3);
1742     ok(hr == S_OK, "got 0x%08x\n", hr);
1743     ret = 0;
1744     hr = IImageList_GetImageCount(imgl, &ret);
1745     ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1746     hr = IImageList_SetImageCount(imgl, 1);
1747     ok(hr == S_OK, "got 0x%08x\n", hr);
1748     ret = 0;
1749     hr = IImageList_GetImageCount(imgl, &ret);
1750     ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1751     hr = IImageList_SetImageCount(imgl, 0);
1752     ok(hr == S_OK, "got 0x%08x\n", hr);
1753     ret = -1;
1754     hr = IImageList_GetImageCount(imgl, &ret);
1755     ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1756 
1757     IImageList_Release(imgl);
1758 }
1759 
1760 static void test_IImageList_Draw(void)
1761 {
1762     IImageList *imgl;
1763     HIMAGELIST himl;
1764 
1765     HBITMAP hbm1;
1766     HBITMAP hbm2;
1767     HBITMAP hbm3;
1768 
1769     IMAGELISTDRAWPARAMS imldp;
1770     HWND hwndfortest;
1771     HRESULT hr;
1772     HDC hdc;
1773     int ret;
1774 
1775     hwndfortest = create_window();
1776     hdc = GetDC(hwndfortest);
1777     ok(hdc!=NULL, "couldn't get DC\n");
1778 
1779     /* create an imagelist to play with */
1780     himl = pImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1781     ok(himl!=0,"failed to create imagelist\n");
1782 
1783     imgl = (IImageList *) himl;
1784 
1785     /* load the icons to add to the image list */
1786     hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1787     ok(hbm1 != 0, "no bitmap 1\n");
1788     hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1789     ok(hbm2 != 0, "no bitmap 2\n");
1790     hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1791     ok(hbm3 != 0, "no bitmap 3\n");
1792 
1793     /* add three */
1794     ret = -1;
1795     ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1796     ret = -1;
1797     ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1798 
1799     ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1800     ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1801 
1802 if (0)
1803 {
1804     /* crashes on native */
1805     IImageList_Draw(imgl, NULL);
1806 }
1807 
1808     memset(&imldp, 0, sizeof (imldp));
1809     hr = IImageList_Draw(imgl, &imldp);
1810     ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1811 
1812     imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1813     imldp.hdcDst = hdc;
1814     imldp.himl = himl;
1815 
1816     force_redraw(hwndfortest);
1817 
1818     imldp.fStyle = SRCCOPY;
1819     imldp.rgbBk = CLR_DEFAULT;
1820     imldp.rgbFg = CLR_DEFAULT;
1821     imldp.y = 100;
1822     imldp.x = 100;
1823     ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1824     imldp.i ++;
1825     ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1826     imldp.i ++;
1827     ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1828     imldp.i ++;
1829     ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1830 
1831     /* remove three */
1832     ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1833     ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1834     ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1835 
1836     /* destroy it */
1837     IImageList_Release(imgl);
1838 
1839     /* bitmaps should not be deleted by the imagelist */
1840     ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1841     ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1842     ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1843 
1844     ReleaseDC(hwndfortest, hdc);
1845     DestroyWindow(hwndfortest);
1846 }
1847 
1848 static void test_IImageList_Merge(void)
1849 {
1850     HIMAGELIST himl1, himl2;
1851     IImageList *imgl1, *imgl2, *merge;
1852     HICON hicon1;
1853     HWND hwnd = create_window();
1854     HRESULT hr;
1855     int ret;
1856 
1857     himl1 = pImageList_Create(32,32,0,0,3);
1858     ok(himl1 != NULL,"failed to create himl1\n");
1859 
1860     himl2 = pImageList_Create(32,32,0,0,3);
1861     ok(himl2 != NULL,"failed to create himl2\n");
1862 
1863     hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1864     ok(hicon1 != NULL, "failed to create hicon1\n");
1865 
1866     if (!himl1 || !himl2 || !hicon1)
1867         return;
1868 
1869     /* cast to IImageList */
1870     imgl1 = (IImageList *) himl1;
1871     imgl2 = (IImageList *) himl2;
1872 
1873     ret = -1;
1874     ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1875 
1876 if (0)
1877 {
1878     /* null cases that crash on native */
1879     IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1880     IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1881 }
1882 
1883     /* If himl1 has no images, merge still succeeds */
1884     hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1885     ok(hr == S_OK, "merge himl1,-1 failed\n");
1886     if (hr == S_OK) IImageList_Release(merge);
1887 
1888     hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1889     ok(hr == S_OK, "merge himl1,0 failed\n");
1890     if (hr == S_OK) IImageList_Release(merge);
1891 
1892     /* Same happens if himl2 is empty */
1893     IImageList_Release(imgl2);
1894     himl2 = pImageList_Create(32,32,0,0,3);
1895     ok(himl2 != NULL,"failed to recreate himl2\n");
1896 
1897     imgl2 = (IImageList *) himl2;
1898 
1899     hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1900     ok(hr == S_OK, "merge himl2,-1 failed\n");
1901     if (hr == S_OK) IImageList_Release(merge);
1902 
1903     hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1904     ok(hr == S_OK, "merge himl2,0 failed\n");
1905     if (hr == S_OK) IImageList_Release(merge);
1906 
1907     /* Now try merging an image with itself */
1908     ret = -1;
1909     ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1910 
1911     hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1912     ok(hr == S_OK, "merge himl2 with itself failed\n");
1913     if (hr == S_OK) IImageList_Release(merge);
1914 
1915     /* Try merging 2 different image lists */
1916     ret = -1;
1917     ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1918 
1919     hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1920     ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1921     if (hr == S_OK) IImageList_Release(merge);
1922 
1923     hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1924     ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1925     if (hr == S_OK) IImageList_Release(merge);
1926 
1927     IImageList_Release(imgl1);
1928     IImageList_Release(imgl2);
1929 
1930     DestroyIcon(hicon1);
1931     DestroyWindow(hwnd);
1932 }
1933 
1934 static void test_iconsize(void)
1935 {
1936     HIMAGELIST himl;
1937     INT cx, cy;
1938     BOOL ret;
1939 
1940     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1941     /* null pointers, not zero imagelist dimensions */
1942     ret = pImageList_GetIconSize(himl, NULL, NULL);
1943     ok(!ret, "got %d\n", ret);
1944 
1945     /* doesn't touch return pointers */
1946     cx = 0x1abe11ed;
1947     ret = pImageList_GetIconSize(himl, &cx, NULL);
1948     ok(!ret, "got %d\n", ret);
1949     ok(cx == 0x1abe11ed, "got %d\n", cx);
1950 
1951     cy = 0x1abe11ed;
1952     ret = pImageList_GetIconSize(himl, NULL, &cy);
1953     ok(!ret, "got %d\n", ret);
1954     ok(cy == 0x1abe11ed, "got %d\n", cy);
1955 
1956     pImageList_Destroy(himl);
1957 
1958     ret = pImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1959     ok(!ret, "got %d\n", ret);
1960 }
1961 
1962 static void test_create_destroy(void)
1963 {
1964     HIMAGELIST himl;
1965     INT cx, cy;
1966     BOOL rc;
1967     INT ret;
1968 
1969     /* list with zero or negative image dimensions */
1970     himl = pImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1971     ok(himl == NULL, "got %p\n", himl);
1972 
1973     himl = pImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1974     ok(himl == NULL, "got %p\n", himl);
1975 
1976     himl = pImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1977     ok(himl == NULL, "got %p\n", himl);
1978 
1979     himl = pImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1980     ok(himl == NULL, "got %p\n", himl);
1981 
1982     himl = pImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1983     ok(himl == NULL, "got %p\n", himl);
1984 
1985     rc = pImageList_Destroy((HIMAGELIST)0xdeadbeef);
1986     ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1987 
1988     /* DDB image lists */
1989     himl = pImageList_Create(0, 14, ILC_COLORDDB, 4, 4);
1990     ok(himl != NULL, "got %p\n", himl);
1991 
1992     pImageList_GetIconSize(himl, &cx, &cy);
1993     ok (cx == 0, "Wrong cx (%i)\n", cx);
1994     ok (cy == 14, "Wrong cy (%i)\n", cy);
1995     pImageList_Destroy(himl);
1996 
1997     himl = pImageList_Create(0, 0, ILC_COLORDDB, 4, 4);
1998     ok(himl != NULL, "got %p\n", himl);
1999     pImageList_GetIconSize(himl, &cx, &cy);
2000     ok (cx == 0, "Wrong cx (%i)\n", cx);
2001     ok (cy == 0, "Wrong cy (%i)\n", cy);
2002     pImageList_Destroy(himl);
2003 
2004     himl = pImageList_Create(0, 0, ILC_COLORDDB, 0, 4);
2005     ok(himl != NULL, "got %p\n", himl);
2006     pImageList_GetIconSize(himl, &cx, &cy);
2007     ok (cx == 0, "Wrong cx (%i)\n", cx);
2008     ok (cy == 0, "Wrong cy (%i)\n", cy);
2009 
2010     pImageList_SetImageCount(himl, 3);
2011     ret = pImageList_GetImageCount(himl);
2012     ok(ret == 3, "Unexpected image count after increase\n");
2013 
2014     /* Trying to actually add an image causes a crash on Windows */
2015     pImageList_Destroy(himl);
2016 
2017     /* Negative values fail */
2018     himl = pImageList_Create(-1, -1, ILC_COLORDDB, 4, 4);
2019     ok(himl == NULL, "got %p\n", himl);
2020     himl = pImageList_Create(-1, 1, ILC_COLORDDB, 4, 4);
2021     ok(himl == NULL, "got %p\n", himl);
2022     himl = pImageList_Create(1, -1, ILC_COLORDDB, 4, 4);
2023     ok(himl == NULL, "got %p\n", himl);
2024 }
2025 
2026 static void check_color_table(const char *name, HDC hdc, HIMAGELIST himl, UINT ilc,
2027                               RGBQUAD *expect, RGBQUAD *broken_expect)
2028 {
2029     IMAGEINFO info;
2030     INT ret;
2031 #ifdef __REACTOS__
2032     char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
2033 #else
2034     char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2035 #endif
2036     BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2037     int i, depth = ilc & 0xfe;
2038 
2039     ret = pImageList_GetImageInfo(himl, 0, &info);
2040     ok(ret, "got %d\n", ret);
2041     ok(info.hbmImage != NULL, "got %p\n", info.hbmImage);
2042 
2043     memset(bmi_buffer, 0, sizeof(bmi_buffer));
2044     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2045     ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
2046     ok(ret, "got %d\n", ret);
2047     ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
2048 
2049     ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
2050     ok(ret, "got %d\n", ret);
2051     ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
2052 
2053     for (i = 0; i < (1 << depth); i++)
2054         ok((bmi->bmiColors[i].rgbRed == expect[i].rgbRed &&
2055             bmi->bmiColors[i].rgbGreen == expect[i].rgbGreen &&
2056             bmi->bmiColors[i].rgbBlue == expect[i].rgbBlue) ||
2057            (broken_expect && broken(bmi->bmiColors[i].rgbRed == broken_expect[i].rgbRed &&
2058                   bmi->bmiColors[i].rgbGreen == broken_expect[i].rgbGreen &&
2059                   bmi->bmiColors[i].rgbBlue == broken_expect[i].rgbBlue)),
2060            "%d: %s: got color[%d] %02x %02x %02x expect %02x %02x %02x\n", depth, name, i,
2061            bmi->bmiColors[i].rgbRed, bmi->bmiColors[i].rgbGreen, bmi->bmiColors[i].rgbBlue,
2062            expect[i].rgbRed, expect[i].rgbGreen, expect[i].rgbBlue);
2063 }
2064 
2065 static void get_default_color_table(HDC hdc, int bpp, RGBQUAD *table)
2066 {
2067 #ifdef __REACTOS__
2068     char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
2069 #else
2070     char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2071 #endif
2072     BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2073     HBITMAP tmp;
2074     int i;
2075     HPALETTE pal;
2076     PALETTEENTRY entries[256];
2077 
2078     switch (bpp)
2079     {
2080     case 4:
2081         tmp = CreateBitmap( 1, 1, 1, 1, NULL );
2082         memset(bmi_buffer, 0, sizeof(bmi_buffer));
2083         bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2084         bmi->bmiHeader.biHeight = 1;
2085         bmi->bmiHeader.biWidth = 1;
2086         bmi->bmiHeader.biBitCount = bpp;
2087         bmi->bmiHeader.biPlanes = 1;
2088         bmi->bmiHeader.biCompression = BI_RGB;
2089         GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
2090 
2091         memcpy(table, bmi->bmiColors, (1 << bpp) * sizeof(RGBQUAD));
2092         table[7] = bmi->bmiColors[8];
2093         table[8] = bmi->bmiColors[7];
2094         DeleteObject( tmp );
2095         break;
2096 
2097     case 8:
2098         pal = CreateHalftonePalette(hdc);
2099         GetPaletteEntries(pal, 0, 256, entries);
2100         for (i = 0; i < 256; i++)
2101         {
2102             table[i].rgbRed = entries[i].peRed;
2103             table[i].rgbGreen = entries[i].peGreen;
2104             table[i].rgbBlue = entries[i].peBlue;
2105             table[i].rgbReserved = 0;
2106         }
2107         DeleteObject(pal);
2108         break;
2109 
2110     default:
2111         ok(0, "unhandled depth %d\n", bpp);
2112     }
2113 }
2114 
2115 static void test_color_table(UINT ilc)
2116 {
2117     HIMAGELIST himl;
2118     INT ret;
2119 #ifdef __REACTOS__
2120     char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
2121 #else
2122     char bmi_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
2123 #endif
2124     BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2125     HDC hdc = CreateCompatibleDC(0);
2126     HBITMAP dib4, dib8, dib32;
2127     RGBQUAD rgb[256], default_table[256];
2128 
2129     get_default_color_table(hdc, ilc & 0xfe, default_table);
2130 
2131     himl = pImageList_Create(16, 16, ilc, 0, 3);
2132     ok(himl != NULL, "got %p\n", himl);
2133 
2134     memset(bmi_buffer, 0, sizeof(bmi_buffer));
2135     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2136     bmi->bmiHeader.biHeight = 16;
2137     bmi->bmiHeader.biWidth = 16;
2138     bmi->bmiHeader.biBitCount = 8;
2139     bmi->bmiHeader.biPlanes = 1;
2140     bmi->bmiHeader.biCompression = BI_RGB;
2141     bmi->bmiColors[0].rgbRed = 0xff;
2142     bmi->bmiColors[1].rgbGreen = 0xff;
2143     bmi->bmiColors[2].rgbBlue = 0xff;
2144 
2145     dib8 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2146 
2147     bmi->bmiHeader.biBitCount = 4;
2148     bmi->bmiColors[0].rgbRed   = 0xff;
2149     bmi->bmiColors[0].rgbGreen = 0x00;
2150     bmi->bmiColors[0].rgbBlue  = 0xff;
2151     bmi->bmiColors[1].rgbRed   = 0xff;
2152     bmi->bmiColors[1].rgbGreen = 0xff;
2153     bmi->bmiColors[1].rgbBlue  = 0x00;
2154     bmi->bmiColors[2].rgbRed   = 0x00;
2155     bmi->bmiColors[2].rgbGreen = 0xff;
2156     bmi->bmiColors[2].rgbBlue  = 0xff;
2157 
2158     dib4 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2159 
2160     bmi->bmiHeader.biBitCount = 32;
2161 
2162     dib32 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2163 
2164     /* add 32 first then 8.  This won't set the color table */
2165     ret = pImageList_Add(himl, dib32, NULL);
2166     ok(ret == 0, "got %d\n", ret);
2167     ret = pImageList_Add(himl, dib8, NULL);
2168     ok(ret == 1, "got %d\n", ret);
2169 
2170     check_color_table("add 32, 8", hdc, himl, ilc, default_table, NULL);
2171 
2172     /* since the previous _Adds didn't set the color table, this one will */
2173     ret = pImageList_Remove(himl, -1);
2174     ok(ret, "got %d\n", ret);
2175     ret = pImageList_Add(himl, dib8, NULL);
2176     ok(ret == 0, "got %d\n", ret);
2177 
2178     memset(rgb, 0, sizeof(rgb));
2179     rgb[0].rgbRed = 0xff;
2180     rgb[1].rgbGreen = 0xff;
2181     rgb[2].rgbBlue = 0xff;
2182     check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table);
2183 
2184     /* remove all, add 4. Color table remains the same since it's inplicitly
2185        been set by the previous _Add */
2186     ret = pImageList_Remove(himl, -1);
2187     ok(ret, "got %d\n", ret);
2188     ret = pImageList_Add(himl, dib4, NULL);
2189     ok(ret == 0, "got %d\n", ret);
2190     check_color_table("remove all, add 4", hdc, himl, ilc, rgb, default_table);
2191 
2192     pImageList_Destroy(himl);
2193     himl = pImageList_Create(16, 16, ilc, 0, 3);
2194     ok(himl != NULL, "got %p\n", himl);
2195 
2196     /* add 4 */
2197     ret = pImageList_Add(himl, dib4, NULL);
2198     ok(ret == 0, "got %d\n", ret);
2199 
2200     memset(rgb, 0, 16 * sizeof(rgb[0]));
2201     rgb[0].rgbRed = 0xff;
2202     rgb[0].rgbBlue = 0xff;
2203     rgb[1].rgbRed = 0xff;
2204     rgb[1].rgbGreen = 0xff;
2205     rgb[2].rgbGreen = 0xff;
2206     rgb[2].rgbBlue = 0xff;
2207     memcpy(rgb + 16, default_table + 16, 240 * sizeof(rgb[0]));
2208 
2209     check_color_table("add 4", hdc, himl, ilc, rgb, default_table);
2210 
2211     pImageList_Destroy(himl);
2212     himl = pImageList_Create(16, 16, ilc, 0, 3);
2213     ok(himl != NULL, "got %p\n", himl);
2214 
2215     /* set color table, add 8 */
2216     ret = pImageList_Remove(himl, -1);
2217     ok(ret, "got %d\n", ret);
2218     memset(rgb, 0, sizeof(rgb));
2219     rgb[0].rgbRed = 0xcc;
2220     rgb[1].rgbBlue = 0xcc;
2221     ret = pImageList_SetColorTable(himl, 0, 2, rgb);
2222     ok(ret == 2, "got %d\n", ret);
2223     /* the table is set, so this doesn't change it */
2224     ret = pImageList_Add(himl, dib8, NULL);
2225     ok(ret == 0, "got %d\n", ret);
2226 
2227     memcpy(rgb + 2, default_table + 2, 254 * sizeof(rgb[0]));
2228     check_color_table("SetColorTable", hdc, himl, ilc, rgb, NULL);
2229 
2230     DeleteObject(dib32);
2231     DeleteObject(dib8);
2232     DeleteObject(dib4);
2233     DeleteDC(hdc);
2234     pImageList_Destroy(himl);
2235 }
2236 
2237 static void test_copy(void)
2238 {
2239     HIMAGELIST dst, src;
2240     BOOL ret;
2241     int count;
2242 
2243     dst = pImageList_Create(5, 11, ILC_COLOR, 1, 1);
2244     count = pImageList_GetImageCount(dst);
2245     ok(!count, "ImageList not empty.\n");
2246     src = createImageList(7, 13);
2247     count = pImageList_GetImageCount(src);
2248     ok(count > 2, "Tests need an ImageList with more than 2 images\n");
2249 
2250     /* ImageList_Copy() cannot copy between two ImageLists */
2251     ret = pImageList_Copy(dst, 0, src, 2, ILCF_MOVE);
2252     ok(!ret, "ImageList_Copy() should have returned FALSE\n");
2253     count = pImageList_GetImageCount(dst);
2254     ok(count == 0, "Expected no image in dst ImageList, got %d\n", count);
2255 
2256     pImageList_Destroy(dst);
2257     pImageList_Destroy(src);
2258 }
2259 
2260 static void test_loadimage(void)
2261 {
2262     HIMAGELIST list;
2263     DWORD flags;
2264 
2265     list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_DEFAULT,
2266                                  IMAGE_BITMAP, LR_CREATEDIBSECTION );
2267     ok( list != NULL, "got %p\n", list );
2268     flags = pImageList_GetFlags( list );
2269     ok( flags == (ILC_COLOR4 | ILC_MASK), "got %08x\n", flags );
2270     pImageList_Destroy( list );
2271 
2272     list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_NONE,
2273                                  IMAGE_BITMAP, LR_CREATEDIBSECTION );
2274     ok( list != NULL, "got %p\n", list );
2275     flags = pImageList_GetFlags( list );
2276     ok( flags == ILC_COLOR4, "got %08x\n", flags );
2277     pImageList_Destroy( list );
2278 }
2279 
2280 static void test_IImageList_Clone(void)
2281 {
2282     IImageList *imgl, *imgl2;
2283     HIMAGELIST himl;
2284     HRESULT hr;
2285     ULONG ref;
2286 
2287     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2288     imgl = (IImageList*)himl;
2289 
2290 if (0)
2291 {
2292     /* crashes on native */
2293     IImageList_Clone(imgl, &IID_IImageList, NULL);
2294 }
2295 
2296     hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
2297     ok(hr == S_OK, "got 0x%08x\n", hr);
2298     ref = IImageList_Release(imgl2);
2299     ok(ref == 0, "got %u\n", ref);
2300 
2301     IImageList_Release(imgl);
2302 }
2303 
2304 static void test_IImageList_GetBkColor(void)
2305 {
2306     IImageList *imgl;
2307     HIMAGELIST himl;
2308     COLORREF color;
2309     HRESULT hr;
2310 
2311     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2312     imgl = (IImageList*)himl;
2313 
2314 if (0)
2315 {
2316     /* crashes on native */
2317     IImageList_GetBkColor(imgl, NULL);
2318 }
2319 
2320     hr = IImageList_GetBkColor(imgl, &color);
2321     ok(hr == S_OK, "got 0x%08x\n", hr);
2322 
2323     IImageList_Release(imgl);
2324 }
2325 
2326 static void test_IImageList_SetBkColor(void)
2327 {
2328     IImageList *imgl;
2329     HIMAGELIST himl;
2330     COLORREF color;
2331     HRESULT hr;
2332 
2333     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2334     imgl = (IImageList*)himl;
2335 
2336 if (0)
2337 {
2338     /* crashes on native */
2339     IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
2340 }
2341 
2342     hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2343     ok(hr == S_OK, "got 0x%08x\n", hr);
2344 
2345     hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2346     ok(hr == S_OK, "got 0x%08x\n", hr);
2347 
2348     color = 0xdeadbeef;
2349     hr = IImageList_GetBkColor(imgl, &color);
2350     ok(hr == S_OK, "got 0x%08x\n", hr);
2351     ok(color == CLR_NONE, "got %x\n", color);
2352 
2353     IImageList_Release(imgl);
2354 }
2355 
2356 static void test_IImageList_GetImageCount(void)
2357 {
2358     IImageList *imgl;
2359     HIMAGELIST himl;
2360     int count;
2361     HRESULT hr;
2362 
2363     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2364     imgl = (IImageList*)himl;
2365 
2366 if (0)
2367 {
2368     /* crashes on native */
2369     IImageList_GetImageCount(imgl, NULL);
2370 }
2371 
2372     count = -1;
2373     hr = IImageList_GetImageCount(imgl, &count);
2374     ok(hr == S_OK, "got 0x%08x\n", hr);
2375     ok(count == 0, "got %d\n", count);
2376 
2377     IImageList_Release(imgl);
2378 }
2379 
2380 static void test_IImageList_GetIconSize(void)
2381 {
2382     IImageList *imgl;
2383     HIMAGELIST himl;
2384     int cx, cy;
2385     HRESULT hr;
2386 
2387     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2388     imgl = (IImageList*)himl;
2389 
2390     hr = IImageList_GetIconSize(imgl, NULL, NULL);
2391     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2392 
2393     hr = IImageList_GetIconSize(imgl, &cx, NULL);
2394     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2395 
2396     hr = IImageList_GetIconSize(imgl, NULL, &cy);
2397     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2398 
2399     IImageList_Release(imgl);
2400 }
2401 
2402 static void init_functions(void)
2403 {
2404     HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
2405 
2406 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2407 #define X2(f, ord) p##f = (void*)GetProcAddress(hComCtl32, (const char *)ord);
2408     X(ImageList_Create);
2409     X(ImageList_Destroy);
2410     X(ImageList_Add);
2411     X(ImageList_DrawIndirect);
2412     X(ImageList_SetImageCount);
2413     X(ImageList_SetImageCount);
2414     X2(ImageList_SetColorTable, 390);
2415     X(ImageList_GetFlags);
2416     X(ImageList_BeginDrag);
2417     X(ImageList_GetDragImage);
2418     X(ImageList_EndDrag);
2419     X(ImageList_GetImageCount);
2420     X(ImageList_SetDragCursorImage);
2421     X(ImageList_GetIconSize);
2422     X(ImageList_Remove);
2423     X(ImageList_ReplaceIcon);
2424     X(ImageList_Replace);
2425     X(ImageList_Merge);
2426     X(ImageList_GetImageInfo);
2427     X(ImageList_Write);
2428     X(ImageList_Read);
2429     X(ImageList_Copy);
2430     X(ImageList_LoadImageW);
2431     X(ImageList_CoCreateInstance);
2432     X(HIMAGELIST_QueryInterface);
2433     X(ImageList_Draw);
2434 #undef X
2435 #undef X2
2436 }
2437 
2438 START_TEST(imagelist)
2439 {
2440     ULONG_PTR ctx_cookie;
2441     HANDLE hCtx;
2442 
2443     init_functions();
2444 
2445     hinst = GetModuleHandleA(NULL);
2446 
2447     test_create_destroy();
2448     test_begindrag();
2449     test_hotspot();
2450     test_add_remove();
2451     test_imagecount();
2452     test_DrawIndirect();
2453     test_merge();
2454     test_merge_colors();
2455     test_imagelist_storage();
2456     test_iconsize();
2457     test_color_table(ILC_COLOR4);
2458     test_color_table(ILC_COLOR8);
2459     test_copy();
2460     test_loadimage();
2461 
2462     /* Now perform v6 tests */
2463     if (!load_v6_module(&ctx_cookie, &hCtx))
2464         return;
2465 
2466     init_functions();
2467 
2468     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2469 
2470     /* Do v6.0 tests */
2471     test_add_remove();
2472     test_imagecount();
2473     test_DrawIndirect();
2474     test_merge();
2475     test_imagelist_storage();
2476     test_iconsize();
2477     test_color_table(ILC_COLOR4);
2478     test_color_table(ILC_COLOR8);
2479     test_copy();
2480     test_loadimage();
2481 
2482     test_ImageList_DrawIndirect();
2483     test_shell_imagelist();
2484     test_iimagelist();
2485 
2486     test_IImageList_Add_Remove();
2487     test_IImageList_Get_SetImageCount();
2488     test_IImageList_Draw();
2489     test_IImageList_Merge();
2490     test_IImageList_Clone();
2491     test_IImageList_GetBkColor();
2492     test_IImageList_SetBkColor();
2493     test_IImageList_GetImageCount();
2494     test_IImageList_GetIconSize();
2495 
2496     CoUninitialize();
2497 
2498     unload_v6_module(ctx_cookie, hCtx);
2499 }
2500