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