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