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         grow = (WORD)(grow + 3) & ~3;
926         ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
927         ok(ilh->cGrow == grow_aligned, "Unexpected cGrow %d, expected %d\n", ilh->cGrow, grow_aligned);
928     }
929 
930     ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
931     ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
932     ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
933     ok(ilh->flags == flags || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4),  /* <= w2k */
934        "wrong flags %04x\n", ilh->flags);
935     ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
936     ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
937     ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
938     ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
939 }
940 
941 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
942 {
943     HDC hdc;
944     BITMAPINFO bmi;
945     HBITMAP hbmp, hbmp_old;
946     HBRUSH hbrush;
947     RECT rc = { 0, 0, cx, cy };
948 
949     hdc = CreateCompatibleDC(0);
950 
951     memset(&bmi, 0, sizeof(bmi));
952     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
953     bmi.bmiHeader.biHeight = cx;
954     bmi.bmiHeader.biWidth = cy;
955     bmi.bmiHeader.biBitCount = 24;
956     bmi.bmiHeader.biPlanes = 1;
957     bmi.bmiHeader.biCompression = BI_RGB;
958     hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
959 
960     hbmp_old = SelectObject(hdc, hbmp);
961 
962     hbrush = CreateSolidBrush(color);
963     FillRect(hdc, &rc, hbrush);
964     DeleteObject(hbrush);
965 
966     DrawTextA(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
967 
968     SelectObject(hdc, hbmp_old);
969     DeleteDC(hdc);
970 
971     return hbmp;
972 }
973 
974 static inline void imagelist_get_bitmap_size(const ILHEAD *header, SIZE *sz)
975 {
976     const int tile_count = 4;
977 
978     if (is_v6_header(header))
979     {
980         sz->cx = header->cx;
981         sz->cy = header->cMaxImage * header->cy;
982     }
983     else
984     {
985         sz->cx = header->cx * tile_count;
986         sz->cy = ((header->cMaxImage + tile_count - 1) / tile_count) * header->cy;
987     }
988 }
989 
990 /* Grow argument matches what was used when imagelist was created. */
991 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
992         INT flags, const char *comment)
993 {
994     INT ret, cxx, cyy, size;
995     struct memstream stream;
996     const ILHEAD *header;
997     LARGE_INTEGER mv;
998     HIMAGELIST himl2;
999     HGLOBAL hglobal;
1000     STATSTG stat;
1001     char *data;
1002     HRESULT hr;
1003     SIZE bmpsize;
1004     BOOL b;
1005 
1006     ret = pImageList_GetImageCount(himl);
1007     ok(ret == cur, "%s: expected image count %d got %d\n", comment, cur, ret);
1008 
1009     ret = pImageList_GetIconSize(himl, &cxx, &cyy);
1010     ok(ret, "ImageList_GetIconSize failed\n");
1011     ok(cxx == cx, "%s: wrong cx %d (expected %d)\n", comment, cxx, cx);
1012     ok(cyy == cy, "%s: wrong cy %d (expected %d)\n", comment, cyy, cy);
1013 
1014     init_memstream(&stream);
1015     b = pImageList_Write(himl, &stream.IStream_iface);
1016     ok(b, "%s: ImageList_Write failed\n", comment);
1017 
1018     hr = GetHGlobalFromStream(stream.stream, &hglobal);
1019     ok(hr == S_OK, "%s: Failed to get hglobal, %#x\n", comment, hr);
1020 
1021     hr = IStream_Stat(stream.stream, &stat, STATFLAG_NONAME);
1022     ok(hr == S_OK, "Stat() failed, hr %#x.\n", hr);
1023 
1024     data = GlobalLock(hglobal);
1025 
1026     ok(data != 0, "%s: ImageList_Write didn't write any data\n", comment);
1027     ok(stat.cbSize.LowPart > sizeof(ILHEAD), "%s: ImageList_Write wrote not enough data\n", comment);
1028 
1029     header = (const ILHEAD *)data;
1030     check_ilhead_data(header, cx, cy, cur, max, grow, flags);
1031     imagelist_get_bitmap_size(header, &bmpsize);
1032     size = check_bitmap_data(header, data + sizeof(ILHEAD), stat.cbSize.LowPart - sizeof(ILHEAD),
1033             &bmpsize, flags & 0xfe, comment);
1034     if (!is_v6_header(header) && size < stat.cbSize.LowPart - sizeof(ILHEAD))  /* mask is present */
1035     {
1036         ok( flags & ILC_MASK, "%s: extra data %u/%u but mask not expected\n", comment, stat.cbSize.LowPart, size );
1037         check_bitmap_data(header, data + sizeof(ILHEAD) + size, stat.cbSize.LowPart - sizeof(ILHEAD) - size,
1038             &bmpsize, 1, comment);
1039     }
1040 
1041     /* rewind and reconstruct from stream */
1042     mv.QuadPart = 0;
1043     IStream_Seek(stream.stream, mv, STREAM_SEEK_SET, NULL);
1044     himl2 = pImageList_Read(&stream.IStream_iface);
1045     ok(himl2 != NULL, "%s: Failed to deserialize imagelist\n", comment);
1046     pImageList_Destroy(himl2);
1047 
1048     GlobalUnlock(hglobal);
1049     cleanup_memstream(&stream);
1050 }
1051 
1052 static void image_list_add_bitmap(HIMAGELIST himl, BYTE grey, int i)
1053 {
1054     char comment[16];
1055     HBITMAP hbm;
1056     int ret;
1057 
1058     sprintf(comment, "%d", i);
1059     hbm = create_bitmap(BMP_CX, BMP_CX, RGB(grey, grey, grey), comment);
1060     ret = pImageList_Add(himl, hbm, NULL);
1061     ok(ret != -1, "Failed to add image to imagelist.\n");
1062     DeleteObject(hbm);
1063 }
1064 
1065 static void image_list_init(HIMAGELIST himl, INT grow)
1066 {
1067     unsigned int i;
1068     static const struct test_data
1069     {
1070         BYTE grey;
1071         INT cx, cy, cur, max, bpp;
1072         const char *comment;
1073     } td[] =
1074     {
1075         { 255, BMP_CX, BMP_CX, 1, 2, 24, "total 1" },
1076         { 170, BMP_CX, BMP_CX, 2, 7, 24, "total 2" },
1077         { 85, BMP_CX, BMP_CX, 3, 7, 24, "total 3" },
1078         { 0, BMP_CX, BMP_CX, 4, 7, 24, "total 4" },
1079         { 0, BMP_CX, BMP_CX, 5, 7, 24, "total 5" },
1080         { 85, BMP_CX, BMP_CX, 6, 7, 24, "total 6" },
1081         { 170, BMP_CX, BMP_CX, 7, 12, 24, "total 7" },
1082         { 255, BMP_CX, BMP_CX, 8, 12, 24, "total 8" },
1083         { 255, BMP_CX, BMP_CX, 9, 12, 24, "total 9" },
1084         { 170, BMP_CX, BMP_CX, 10, 12, 24, "total 10" },
1085         { 85, BMP_CX, BMP_CX, 11, 12, 24, "total 11" },
1086         { 0, BMP_CX, BMP_CX, 12, 17, 24, "total 12" },
1087         { 0, BMP_CX, BMP_CX, 13, 17, 24, "total 13" },
1088         { 85, BMP_CX, BMP_CX, 14, 17, 24, "total 14" },
1089         { 170, BMP_CX, BMP_CX, 15, 17, 24, "total 15" },
1090         { 255, BMP_CX, BMP_CX, 16, 17, 24, "total 16" },
1091         { 255, BMP_CX, BMP_CX, 17, 22, 24, "total 17" },
1092         { 170, BMP_CX, BMP_CX, 18, 22, 24, "total 18" },
1093         { 85, BMP_CX, BMP_CX, 19, 22, 24, "total 19" },
1094         { 0, BMP_CX, BMP_CX, 20, 22, 24, "total 20" },
1095         { 0, BMP_CX, BMP_CX, 21, 22, 24, "total 21" },
1096         { 85, BMP_CX, BMP_CX, 22, 27, 24, "total 22" },
1097         { 170, BMP_CX, BMP_CX, 23, 27, 24, "total 23" },
1098         { 255, BMP_CX, BMP_CX, 24, 27, 24, "total 24" }
1099     };
1100 
1101     check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, grow, ILC_COLOR24, "total 0");
1102 
1103     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
1104     {
1105         image_list_add_bitmap(himl, td[i].grey, i + 1);
1106         check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, grow, td[i].bpp, td[i].comment);
1107     }
1108 }
1109 
1110 static void test_imagelist_storage(void)
1111 {
1112     HIMAGELIST himl;
1113     INT ret, grow;
1114     HBITMAP hbm;
1115     HICON icon;
1116 
1117     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
1118     ok(himl != 0, "ImageList_Create failed\n");
1119 
1120     check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 1, ILC_COLOR24, "empty");
1121 
1122     image_list_init(himl, 1);
1123     check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 1, ILC_COLOR24, "orig");
1124 
1125     ret = pImageList_Remove(himl, 4);
1126     ok(ret, "ImageList_Remove failed\n");
1127     check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 1, ILC_COLOR24, "1");
1128 
1129     ret = pImageList_Remove(himl, 5);
1130     ok(ret, "ImageList_Remove failed\n");
1131     check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 1, ILC_COLOR24, "2");
1132 
1133     ret = pImageList_Remove(himl, 6);
1134     ok(ret, "ImageList_Remove failed\n");
1135     check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 1, ILC_COLOR24, "3");
1136 
1137     ret = pImageList_Remove(himl, 7);
1138     ok(ret, "ImageList_Remove failed\n");
1139     check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "4");
1140 
1141     ret = pImageList_Remove(himl, -2);
1142     ok(!ret, "ImageList_Remove(-2) should fail\n");
1143     check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "5");
1144 
1145     ret = pImageList_Remove(himl, 20);
1146     ok(!ret, "ImageList_Remove(20) should fail\n");
1147     check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 1, ILC_COLOR24, "6");
1148 
1149     ret = pImageList_Remove(himl, -1);
1150     ok(ret, "ImageList_Remove(-1) failed\n");
1151     check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 1, ILC_COLOR24, "7");
1152 
1153     ret = pImageList_Destroy(himl);
1154     ok(ret, "ImageList_Destroy failed\n");
1155 
1156     /* test ImageList_Create storage allocation */
1157 
1158     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
1159     ok(himl != 0, "ImageList_Create failed\n");
1160     check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, ILC_COLOR24, "init 0 grow 32");
1161     hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1162     ret = pImageList_Add(himl, hbm, NULL);
1163     ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1164     check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, ILC_COLOR24, "add 1 x 9");
1165     DeleteObject(hbm);
1166     ret = pImageList_Destroy(himl);
1167     ok(ret, "ImageList_Destroy failed\n");
1168 
1169     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1170     ok(himl != 0, "ImageList_Create failed\n");
1171     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, ILC_COLOR24, "init 4 grow 4");
1172     hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1173     ret = pImageList_Add(himl, hbm, NULL);
1174     ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1175     check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, ILC_COLOR24, "add 9 x 1");
1176     ret = pImageList_Add(himl, hbm, NULL);
1177     ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1178     check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, ILC_COLOR24, "add 9 x 1");
1179     DeleteObject(hbm);
1180     ret = pImageList_Destroy(himl);
1181     ok(ret, "ImageList_Destroy failed\n");
1182 
1183     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1184     ok(himl != 0, "ImageList_Create failed\n");
1185     check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 209, ILC_COLOR24, "init 207 grow 209");
1186     ret = pImageList_Destroy(himl);
1187     ok(ret, "ImageList_Destroy failed\n");
1188 
1189     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1190     ok(himl != 0, "ImageList_Create failed\n");
1191     check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 207, ILC_COLOR24, "init 209 grow 207");
1192     ret = pImageList_Destroy(himl);
1193     ok(ret, "ImageList_Destroy failed\n");
1194 
1195     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1196     ok(himl != 0, "ImageList_Create failed\n");
1197     check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, ILC_COLOR24, "init 14 grow 4");
1198     ret = pImageList_Destroy(himl);
1199     ok(ret, "ImageList_Destroy failed\n");
1200 
1201     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1202     ok(himl != 0, "ImageList_Create failed\n");
1203     check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 9, ILC_COLOR24, "init 5 grow 9");
1204     ret = pImageList_Destroy(himl);
1205     ok(ret, "ImageList_Destroy failed\n");
1206 
1207     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1208     ok(himl != 0, "ImageList_Create failed\n");
1209     check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 5, ILC_COLOR24, "init 9 grow 5");
1210     ret = pImageList_Destroy(himl);
1211     ok(ret, "ImageList_Destroy failed\n");
1212 
1213     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1214     ok(himl != 0, "ImageList_Create failed\n");
1215     check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, ILC_COLOR24, "init 2 grow 4");
1216     ret = pImageList_Destroy(himl);
1217     ok(ret, "ImageList_Destroy failed\n");
1218 
1219     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1220     ok(himl != 0, "ImageList_Create failed\n");
1221     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR24, "init 4 grow 2");
1222     ret = pImageList_Destroy(himl);
1223     ok(ret, "ImageList_Destroy failed\n");
1224 
1225     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1226     ok(himl != 0, "ImageList_Create failed\n");
1227     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR8, "bpp 8");
1228     ret = pImageList_Destroy(himl);
1229     ok(ret, "ImageList_Destroy failed\n");
1230 
1231     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1232     ok(himl != 0, "ImageList_Create failed\n");
1233     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4, "bpp 4");
1234     ret = pImageList_Destroy(himl);
1235     ok(ret, "ImageList_Destroy failed\n");
1236 
1237     himl = pImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1238     ok(himl != 0, "ImageList_Create failed\n");
1239     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4, "bpp default");
1240     icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1241     ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1242     ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1243     DestroyIcon( icon );
1244     check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR4, "bpp default");
1245     ret = pImageList_Destroy(himl);
1246     ok(ret, "ImageList_Destroy failed\n");
1247 
1248     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1249     ok(himl != 0, "ImageList_Create failed\n");
1250     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1251     icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1252     ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1253     ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1254     DestroyIcon( icon );
1255     check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR24|ILC_MASK, "bpp 24 + mask");
1256     ret = pImageList_Destroy(himl);
1257     ok(ret, "ImageList_Destroy failed\n");
1258 
1259     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1260     ok(himl != 0, "ImageList_Create failed\n");
1261     check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1262     icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1263     ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1264     ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1265     DestroyIcon( icon );
1266     check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 2, ILC_COLOR4|ILC_MASK, "bpp 4 + mask");
1267     ret = pImageList_Destroy(himl);
1268     ok(ret, "ImageList_Destroy failed\n");
1269 
1270     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1271     ok(himl != 0, "ImageList_Create failed\n");
1272     check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99");
1273     icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1274     ok( pImageList_ReplaceIcon(himl, -1, icon) == 0, "Failed to add icon.\n");
1275     ok( pImageList_ReplaceIcon(himl, -1, icon) == 1, "Failed to add icon.\n");
1276     check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 2 icons");
1277     ok( pImageList_ReplaceIcon(himl, -1, icon) == 2, "Failed to add icon\n");
1278     DestroyIcon( icon );
1279     check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 3 icons");
1280     ok( pImageList_Remove(himl, -1) == TRUE, "Failed to remove icon.\n");
1281     check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 empty");
1282     ok( pImageList_SetImageCount(himl, 22) == TRUE, "Failed to set image count.\n");
1283     check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 22");
1284     ok( pImageList_SetImageCount(himl, 0) == TRUE, "Failed to set image count.\n");
1285     check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 0");
1286     ok( pImageList_SetImageCount(himl, 42) == TRUE, "Failed to set image count.\n");
1287     check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 99, ILC_COLOR4|ILC_MASK, "init 2 grow 99 set count 42");
1288     ret = pImageList_Destroy(himl);
1289     ok(ret, "ImageList_Destroy failed\n");
1290 
1291     for (grow = 1; grow <= 16; grow++)
1292     {
1293         himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, grow);
1294         ok(himl != 0, "ImageList_Create failed\n");
1295         check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, grow, ILC_COLOR4|ILC_MASK, "grow test");
1296         ret = pImageList_Destroy(himl);
1297         ok(ret, "ImageList_Destroy failed\n");
1298     }
1299 
1300     himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1301     ok(himl != 0, "ImageList_Create failed\n");
1302     check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, -20, ILC_COLOR4|ILC_MASK, "init 2 grow -20");
1303     ret = pImageList_Destroy(himl);
1304     ok(ret, "ImageList_Destroy failed\n");
1305 
1306     /* Version 6 implementation hangs on large grow values. */
1307     if (!is_v6_test())
1308     {
1309         himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1310         ok(himl != 0, "ImageList_Create failed\n");
1311         check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 65536+12, ILC_COLOR4|ILC_MASK, "init 2 grow 65536+12");
1312         ret = pImageList_Destroy(himl);
1313         ok(ret, "ImageList_Destroy failed\n");
1314 
1315         himl = pImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1316         ok(himl != 0, "ImageList_Create failed\n");
1317         check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 65535, ILC_COLOR4|ILC_MASK, "init 2 grow 65535");
1318         ret = pImageList_Destroy(himl);
1319         ok(ret, "ImageList_Destroy failed\n");
1320     }
1321 }
1322 
1323 static void test_shell_imagelist(void)
1324 {
1325     HRESULT (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1326     IImageList *iml = NULL;
1327     HMODULE hShell32;
1328     HRESULT hr;
1329     int out = 0;
1330     RECT rect;
1331     int cx, cy;
1332 
1333     /* Try to load function from shell32 */
1334     hShell32 = LoadLibraryA("shell32.dll");
1335     pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1336 
1337     if (!pSHGetImageList)
1338     {
1339         win_skip("SHGetImageList not available, skipping test\n");
1340         FreeLibrary(hShell32);
1341         return;
1342     }
1343 
1344     /* Get system image list */
1345     hr = pSHGetImageList(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1346     ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1347 
1348     if (hr != S_OK) {
1349         FreeLibrary(hShell32);
1350         return;
1351     }
1352 
1353     IImageList_GetImageCount(iml, &out);
1354     ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1355 
1356     /* Fetch the small icon size */
1357     cx = GetSystemMetrics(SM_CXSMICON);
1358     cy = GetSystemMetrics(SM_CYSMICON);
1359 
1360     /* Check icon size matches */
1361     IImageList_GetImageRect(iml, 0, &rect);
1362     ok(((rect.right == cx) && (rect.bottom == cy)),
1363                  "IImageList_GetImageRect returned r:%d,b:%d\n",
1364                  rect.right, rect.bottom);
1365 
1366     IImageList_Release(iml);
1367     FreeLibrary(hShell32);
1368 }
1369 
1370 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1371 {
1372     HBITMAP hBitmap;
1373     UINT32 *buffer = NULL;
1374     BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1375                                 0, 0, 0, 0, 0}};
1376 
1377     hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1378     ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1379 
1380     if(!hBitmap || !buffer)
1381     {
1382         DeleteObject(hBitmap);
1383         return NULL;
1384     }
1385 
1386     buffer[0] = pixel1;
1387     buffer[1] = pixel2;
1388 
1389     return hBitmap;
1390 }
1391 
1392 static BOOL colour_match(UINT32 x, UINT32 y)
1393 {
1394     const INT32 tolerance = 8;
1395 
1396     const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1397     const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1398     const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1399 
1400     return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1401 }
1402 
1403 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1404                                          UINT32 expected, int line)
1405 {
1406     bits[0] = 0x00FFFFFF;
1407     pImageList_DrawIndirect(ildp);
1408     ok(colour_match(bits[0], expected),
1409        "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1410        bits[0] & 0x00FFFFFF, expected, line);
1411 }
1412 
1413 
1414 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1415                                                 UINT fStyle, UINT32 expected, int line)
1416 {
1417     IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1418         0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1419     check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1420 }
1421 
1422 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1423                                                 DWORD dwRop, UINT32 expected, int line)
1424 {
1425     IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1426         0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1427     check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1428 }
1429 
1430 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1431                                                 UINT fState, DWORD Frame, UINT32 expected, int line)
1432 {
1433     IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1434         0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1435     check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1436 }
1437 
1438 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1439                                                 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1440                                                 UINT32 broken_expected, int line)
1441 {
1442     IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1443         0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1444     bits[0] = 0x00FFFFFF;
1445     pImageList_DrawIndirect(&ildp);
1446     ok(colour_match(bits[0], expected) ||
1447        broken(colour_match(bits[0], broken_expected)),
1448        "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1449        bits[0] & 0x00FFFFFF, expected, line);
1450 }
1451 
1452 static void test_ImageList_DrawIndirect(void)
1453 {
1454     HIMAGELIST himl = NULL;
1455     int ret;
1456     HDC hdcDst = NULL;
1457     HBITMAP hbmOld = NULL, hbmDst = NULL;
1458     HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1459     HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1460     int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1461     UINT32 *bits = 0;
1462     UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1463     int bpp, broken_value;
1464 
1465     BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1466                                 0, 0, 0, 0, 0}};
1467 
1468     hdcDst = CreateCompatibleDC(0);
1469     ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1470     if (!hdcDst)
1471         return;
1472     bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1473 
1474     hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1475     ok(hbmMask != 0, "CreateBitmap failed\n");
1476     if(!hbmMask) goto cleanup;
1477 
1478     hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1479     ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1480     if(!hbmInverseMask) goto cleanup;
1481 
1482     himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1483     ok(himl != 0, "ImageList_Create failed\n");
1484     if(!himl) goto cleanup;
1485 
1486     /* Add a no-alpha image */
1487     hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1488     if(!hbmImage) goto cleanup;
1489 
1490     iImage = pImageList_Add(himl, hbmImage, hbmMask);
1491     ok(iImage != -1, "ImageList_Add failed\n");
1492     if(iImage == -1) goto cleanup;
1493 
1494     /* Add an alpha image */
1495     hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1496     if(!hbmAlphaImage) goto cleanup;
1497 
1498     iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1499     ok(iAlphaImage != -1, "ImageList_Add failed\n");
1500     if(iAlphaImage == -1) goto cleanup;
1501 
1502     /* Add a transparent alpha image */
1503     hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1504     if(!hbmTransparentImage) goto cleanup;
1505 
1506     iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1507     ok(iTransparentImage != -1, "ImageList_Add failed\n");
1508     if(iTransparentImage == -1) goto cleanup;
1509 
1510     /* 32-bit Tests */
1511     bitmapInfo.bmiHeader.biBitCount = 32;
1512     hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1513     ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1514     if (!hbmDst || !bits)
1515         goto cleanup;
1516     hbmOld = SelectObject(hdcDst, hbmDst);
1517 
1518     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1519     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1520     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1521     if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1522     else broken_value = 0x00B4BDC4;
1523     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1524     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1525     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1526     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1527 
1528     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1529     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1530 
1531     if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1532     else broken_value =  0x009DA8B1;
1533     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1534     if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1535     else broken_value =  0x008C99A3;
1536     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1537     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1538     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1539     todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1540 
1541     check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1542 
1543     check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1544     check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1545 
1546     /* ILD_ROP is ignored when the image has an alpha channel */
1547     check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1548     check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1549 
1550     todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1551     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1552 
1553     check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1554     check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1555 
1556     check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1557     check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1558     todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1559 
1560 cleanup:
1561 
1562     if(hbmOld)
1563         SelectObject(hdcDst, hbmOld);
1564     if(hbmDst)
1565         DeleteObject(hbmDst);
1566 
1567     if(hdcDst)
1568         DeleteDC(hdcDst);
1569 
1570     if(hbmMask)
1571         DeleteObject(hbmMask);
1572     if(hbmInverseMask)
1573         DeleteObject(hbmInverseMask);
1574 
1575     if(hbmImage)
1576         DeleteObject(hbmImage);
1577     if(hbmAlphaImage)
1578         DeleteObject(hbmAlphaImage);
1579     if(hbmTransparentImage)
1580         DeleteObject(hbmTransparentImage);
1581 
1582     if(himl)
1583     {
1584         ret = pImageList_Destroy(himl);
1585         ok(ret, "ImageList_Destroy failed\n");
1586     }
1587 }
1588 
1589 static void test_iimagelist(void)
1590 {
1591     IImageList *imgl, *imgl2;
1592     IImageList2 *imagelist;
1593     HIMAGELIST himl;
1594     HRESULT hr;
1595     ULONG ret;
1596 
1597     if (!pHIMAGELIST_QueryInterface)
1598     {
1599         win_skip("XP imagelist functions not available\n");
1600         return;
1601     }
1602 
1603     /* test reference counting on destruction */
1604     imgl = (IImageList*)createImageList(32, 32);
1605     ret = IImageList_AddRef(imgl);
1606     ok(ret == 2, "Expected 2, 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 == TRUE, "Expected TRUE, got %d\n", ret);
1611     ret = pImageList_Destroy((HIMAGELIST)imgl);
1612     ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1613 
1614     imgl = (IImageList*)createImageList(32, 32);
1615     ret = IImageList_AddRef(imgl);
1616     ok(ret == 2, "Expected 2, got %d\n", ret);
1617     ret = pImageList_Destroy((HIMAGELIST)imgl);
1618     ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1619     ret = IImageList_Release(imgl);
1620     ok(ret == 0, "Expected 0, got %d\n", ret);
1621     ret = pImageList_Destroy((HIMAGELIST)imgl);
1622     ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1623 
1624     /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1625     imgl = (IImageList*)createImageList(32, 32);
1626     hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1627     ok(hr == S_OK, "got 0x%08x\n", hr);
1628     ok(imgl2 == imgl, "got different pointer\n");
1629     ret = IImageList_Release(imgl);
1630     ok(ret == 1, "got %u\n", ret);
1631     IImageList_Release(imgl);
1632 
1633     if (!pImageList_CoCreateInstance)
1634     {
1635         win_skip("Vista imagelist functions not available\n");
1636         return;
1637     }
1638 
1639     hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1640     ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1641 
1642     if (hr == S_OK)
1643         IImageList_Release(imgl);
1644 
1645     himl = createImageList(32, 32);
1646 
1647     if (!himl)
1648         return;
1649 
1650     hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1651     ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1652 
1653     if (hr == S_OK)
1654         IImageList_Release(imgl);
1655 
1656     pImageList_Destroy(himl);
1657 
1658     /* IImageList2 */
1659     hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList2, (void**)&imagelist);
1660     if (hr != S_OK)
1661     {
1662         win_skip("IImageList2 is not supported.\n");
1663         return;
1664     }
1665     ok(hr == S_OK, "got 0x%08x\n", hr);
1666     IImageList2_Release(imagelist);
1667 }
1668 
1669 static void test_IImageList_Add_Remove(void)
1670 {
1671     IImageList *imgl;
1672     HIMAGELIST himl;
1673     HRESULT hr;
1674 
1675     HICON hicon1;
1676     HICON hicon2;
1677     HICON hicon3;
1678 
1679     int ret;
1680 
1681     /* create an imagelist to play with */
1682     himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1683     ok(himl != 0,"failed to create imagelist\n");
1684 
1685     imgl = (IImageList *) himl;
1686 
1687     /* load the icons to add to the image list */
1688     hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1689     ok(hicon1 != 0, "no hicon1\n");
1690     hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1691     ok(hicon2 != 0, "no hicon2\n");
1692     hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1693     ok(hicon3 != 0, "no hicon3\n");
1694 
1695     /* remove when nothing exists */
1696     hr = IImageList_Remove(imgl, 0);
1697     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1698 
1699     /* removing everything from an empty imagelist should succeed */
1700     hr = IImageList_Remove(imgl, -1);
1701     ok(hr == S_OK, "removed nonexistent icon\n");
1702 
1703     /* add three */
1704     ret = -1;
1705     ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1706     ret = -1;
1707     ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1708     ret = -1;
1709     ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1710 
1711     /* remove an index out of range */
1712     ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1713 
1714     /* remove three */
1715     ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1716     ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1717     ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1718 
1719     /* remove one extra */
1720     ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1721 
1722     IImageList_Release(imgl);
1723     ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1724     ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1725     ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1726 }
1727 
1728 static void test_IImageList_Get_SetImageCount(void)
1729 {
1730     IImageList *imgl;
1731     HIMAGELIST himl;
1732     HRESULT hr;
1733     INT ret;
1734 
1735     /* create an imagelist to play with */
1736     himl = pImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1737     ok(himl != 0,"failed to create imagelist\n");
1738 
1739     imgl = (IImageList *) himl;
1740 
1741     /* check SetImageCount/GetImageCount */
1742     hr = IImageList_SetImageCount(imgl, 3);
1743     ok(hr == S_OK, "got 0x%08x\n", hr);
1744     ret = 0;
1745     hr = IImageList_GetImageCount(imgl, &ret);
1746     ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1747     hr = IImageList_SetImageCount(imgl, 1);
1748     ok(hr == S_OK, "got 0x%08x\n", hr);
1749     ret = 0;
1750     hr = IImageList_GetImageCount(imgl, &ret);
1751     ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1752     hr = IImageList_SetImageCount(imgl, 0);
1753     ok(hr == S_OK, "got 0x%08x\n", hr);
1754     ret = -1;
1755     hr = IImageList_GetImageCount(imgl, &ret);
1756     ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1757 
1758     IImageList_Release(imgl);
1759 }
1760 
1761 static void test_IImageList_Draw(void)
1762 {
1763     IImageList *imgl;
1764     HIMAGELIST himl;
1765 
1766     HBITMAP hbm1;
1767     HBITMAP hbm2;
1768     HBITMAP hbm3;
1769 
1770     IMAGELISTDRAWPARAMS imldp;
1771     HWND hwndfortest;
1772     HRESULT hr;
1773     HDC hdc;
1774     int ret;
1775 
1776     hwndfortest = create_window();
1777     hdc = GetDC(hwndfortest);
1778     ok(hdc!=NULL, "couldn't get DC\n");
1779 
1780     /* create an imagelist to play with */
1781     himl = pImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1782     ok(himl!=0,"failed to create imagelist\n");
1783 
1784     imgl = (IImageList *) himl;
1785 
1786     /* load the icons to add to the image list */
1787     hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1788     ok(hbm1 != 0, "no bitmap 1\n");
1789     hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1790     ok(hbm2 != 0, "no bitmap 2\n");
1791     hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1792     ok(hbm3 != 0, "no bitmap 3\n");
1793 
1794     /* add three */
1795     ret = -1;
1796     ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1797     ret = -1;
1798     ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1799 
1800     ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1801     ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1802 
1803 if (0)
1804 {
1805     /* crashes on native */
1806     IImageList_Draw(imgl, NULL);
1807 }
1808 
1809     memset(&imldp, 0, sizeof (imldp));
1810     hr = IImageList_Draw(imgl, &imldp);
1811     ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1812 
1813     imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1814     imldp.hdcDst = hdc;
1815     imldp.himl = himl;
1816 
1817     force_redraw(hwndfortest);
1818 
1819     imldp.fStyle = SRCCOPY;
1820     imldp.rgbBk = CLR_DEFAULT;
1821     imldp.rgbFg = CLR_DEFAULT;
1822     imldp.y = 100;
1823     imldp.x = 100;
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) == S_OK, "should succeed\n");
1829     imldp.i ++;
1830     ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1831 
1832     /* remove three */
1833     ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1834     ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1835     ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1836 
1837     /* destroy it */
1838     IImageList_Release(imgl);
1839 
1840     /* bitmaps should not be deleted by the imagelist */
1841     ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1842     ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1843     ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1844 
1845     ReleaseDC(hwndfortest, hdc);
1846     DestroyWindow(hwndfortest);
1847 }
1848 
1849 static void test_IImageList_Merge(void)
1850 {
1851     HIMAGELIST himl1, himl2;
1852     IImageList *imgl1, *imgl2, *merge;
1853     HICON hicon1;
1854     HWND hwnd = create_window();
1855     HRESULT hr;
1856     int ret;
1857 
1858     himl1 = pImageList_Create(32,32,0,0,3);
1859     ok(himl1 != NULL,"failed to create himl1\n");
1860 
1861     himl2 = pImageList_Create(32,32,0,0,3);
1862     ok(himl2 != NULL,"failed to create himl2\n");
1863 
1864     hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1865     ok(hicon1 != NULL, "failed to create hicon1\n");
1866 
1867     if (!himl1 || !himl2 || !hicon1)
1868         return;
1869 
1870     /* cast to IImageList */
1871     imgl1 = (IImageList *) himl1;
1872     imgl2 = (IImageList *) himl2;
1873 
1874     ret = -1;
1875     ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1876 
1877 if (0)
1878 {
1879     /* null cases that crash on native */
1880     IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1881     IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1882 }
1883 
1884     /* If himl1 has no images, merge still succeeds */
1885     hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1886     ok(hr == S_OK, "merge himl1,-1 failed\n");
1887     if (hr == S_OK) IImageList_Release(merge);
1888 
1889     hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1890     ok(hr == S_OK, "merge himl1,0 failed\n");
1891     if (hr == S_OK) IImageList_Release(merge);
1892 
1893     /* Same happens if himl2 is empty */
1894     IImageList_Release(imgl2);
1895     himl2 = pImageList_Create(32,32,0,0,3);
1896     ok(himl2 != NULL,"failed to recreate himl2\n");
1897 
1898     imgl2 = (IImageList *) himl2;
1899 
1900     hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1901     ok(hr == S_OK, "merge himl2,-1 failed\n");
1902     if (hr == S_OK) IImageList_Release(merge);
1903 
1904     hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1905     ok(hr == S_OK, "merge himl2,0 failed\n");
1906     if (hr == S_OK) IImageList_Release(merge);
1907 
1908     /* Now try merging an image with itself */
1909     ret = -1;
1910     ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1911 
1912     hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1913     ok(hr == S_OK, "merge himl2 with itself failed\n");
1914     if (hr == S_OK) IImageList_Release(merge);
1915 
1916     /* Try merging 2 different image lists */
1917     ret = -1;
1918     ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1919 
1920     hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1921     ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1922     if (hr == S_OK) IImageList_Release(merge);
1923 
1924     hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1925     ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1926     if (hr == S_OK) IImageList_Release(merge);
1927 
1928     IImageList_Release(imgl1);
1929     IImageList_Release(imgl2);
1930 
1931     DestroyIcon(hicon1);
1932     DestroyWindow(hwnd);
1933 }
1934 
1935 static void test_iconsize(void)
1936 {
1937     HIMAGELIST himl;
1938     INT cx, cy;
1939     BOOL ret;
1940 
1941     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1942     /* null pointers, not zero imagelist dimensions */
1943     ret = pImageList_GetIconSize(himl, NULL, NULL);
1944     ok(!ret, "got %d\n", ret);
1945 
1946     /* doesn't touch return pointers */
1947     cx = 0x1abe11ed;
1948     ret = pImageList_GetIconSize(himl, &cx, NULL);
1949     ok(!ret, "got %d\n", ret);
1950     ok(cx == 0x1abe11ed, "got %d\n", cx);
1951 
1952     cy = 0x1abe11ed;
1953     ret = pImageList_GetIconSize(himl, NULL, &cy);
1954     ok(!ret, "got %d\n", ret);
1955     ok(cy == 0x1abe11ed, "got %d\n", cy);
1956 
1957     pImageList_Destroy(himl);
1958 
1959     ret = pImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1960     ok(!ret, "got %d\n", ret);
1961 }
1962 
1963 static void test_create_destroy(void)
1964 {
1965     HIMAGELIST himl;
1966     INT cx, cy;
1967     BOOL rc;
1968     INT ret;
1969 
1970     /* list with zero or negative image dimensions */
1971     himl = pImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1972     ok(himl == NULL, "got %p\n", himl);
1973 
1974     himl = pImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1975     ok(himl == NULL, "got %p\n", himl);
1976 
1977     himl = pImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1978     ok(himl == NULL, "got %p\n", himl);
1979 
1980     himl = pImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1981     ok(himl == NULL, "got %p\n", himl);
1982 
1983     himl = pImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1984     ok(himl == NULL, "got %p\n", himl);
1985 
1986     rc = pImageList_Destroy((HIMAGELIST)0xdeadbeef);
1987     ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1988 
1989     /* DDB image lists */
1990     himl = pImageList_Create(0, 14, ILC_COLORDDB, 4, 4);
1991     ok(himl != NULL, "got %p\n", himl);
1992 
1993     pImageList_GetIconSize(himl, &cx, &cy);
1994     ok (cx == 0, "Wrong cx (%i)\n", cx);
1995     ok (cy == 14, "Wrong cy (%i)\n", cy);
1996     pImageList_Destroy(himl);
1997 
1998     himl = pImageList_Create(0, 0, ILC_COLORDDB, 4, 4);
1999     ok(himl != NULL, "got %p\n", himl);
2000     pImageList_GetIconSize(himl, &cx, &cy);
2001     ok (cx == 0, "Wrong cx (%i)\n", cx);
2002     ok (cy == 0, "Wrong cy (%i)\n", cy);
2003     pImageList_Destroy(himl);
2004 
2005     himl = pImageList_Create(0, 0, ILC_COLORDDB, 0, 4);
2006     ok(himl != NULL, "got %p\n", himl);
2007     pImageList_GetIconSize(himl, &cx, &cy);
2008     ok (cx == 0, "Wrong cx (%i)\n", cx);
2009     ok (cy == 0, "Wrong cy (%i)\n", cy);
2010 
2011     pImageList_SetImageCount(himl, 3);
2012     ret = pImageList_GetImageCount(himl);
2013     ok(ret == 3, "Unexpected image count after increase\n");
2014 
2015     /* Trying to actually add an image causes a crash on Windows */
2016     pImageList_Destroy(himl);
2017 
2018     /* Negative values fail */
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     himl = pImageList_Create(1, -1, ILC_COLORDDB, 4, 4);
2024     ok(himl == NULL, "got %p\n", himl);
2025 }
2026 
2027 static void check_color_table(const char *name, HDC hdc, HIMAGELIST himl, UINT ilc,
2028                               RGBQUAD *expect, RGBQUAD *broken_expect)
2029 {
2030     IMAGEINFO info;
2031     INT ret;
2032     char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
2033     BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2034     int i, depth = ilc & 0xfe;
2035 
2036     ret = pImageList_GetImageInfo(himl, 0, &info);
2037     ok(ret, "got %d\n", ret);
2038     ok(info.hbmImage != NULL, "got %p\n", info.hbmImage);
2039 
2040     memset(bmi_buffer, 0, sizeof(bmi_buffer));
2041     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2042     ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
2043     ok(ret, "got %d\n", ret);
2044     ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
2045 
2046     ret = GetDIBits(hdc, info.hbmImage, 0, 0, NULL, bmi, DIB_RGB_COLORS);
2047     ok(ret, "got %d\n", ret);
2048     ok(bmi->bmiHeader.biBitCount == depth, "got %d\n", bmi->bmiHeader.biBitCount);
2049 
2050     for (i = 0; i < (1 << depth); i++)
2051         ok((bmi->bmiColors[i].rgbRed == expect[i].rgbRed &&
2052             bmi->bmiColors[i].rgbGreen == expect[i].rgbGreen &&
2053             bmi->bmiColors[i].rgbBlue == expect[i].rgbBlue) ||
2054            (broken_expect && broken(bmi->bmiColors[i].rgbRed == broken_expect[i].rgbRed &&
2055                   bmi->bmiColors[i].rgbGreen == broken_expect[i].rgbGreen &&
2056                   bmi->bmiColors[i].rgbBlue == broken_expect[i].rgbBlue)),
2057            "%d: %s: got color[%d] %02x %02x %02x expect %02x %02x %02x\n", depth, name, i,
2058            bmi->bmiColors[i].rgbRed, bmi->bmiColors[i].rgbGreen, bmi->bmiColors[i].rgbBlue,
2059            expect[i].rgbRed, expect[i].rgbGreen, expect[i].rgbBlue);
2060 }
2061 
2062 static void get_default_color_table(HDC hdc, int bpp, RGBQUAD *table)
2063 {
2064     char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
2065     BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2066     HBITMAP tmp;
2067     int i;
2068     HPALETTE pal;
2069     PALETTEENTRY entries[256];
2070 
2071     switch (bpp)
2072     {
2073     case 4:
2074         tmp = CreateBitmap( 1, 1, 1, 1, NULL );
2075         memset(bmi_buffer, 0, sizeof(bmi_buffer));
2076         bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2077         bmi->bmiHeader.biHeight = 1;
2078         bmi->bmiHeader.biWidth = 1;
2079         bmi->bmiHeader.biBitCount = bpp;
2080         bmi->bmiHeader.biPlanes = 1;
2081         bmi->bmiHeader.biCompression = BI_RGB;
2082         GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
2083 
2084         memcpy(table, bmi->bmiColors, (1 << bpp) * sizeof(RGBQUAD));
2085         table[7] = bmi->bmiColors[8];
2086         table[8] = bmi->bmiColors[7];
2087         DeleteObject( tmp );
2088         break;
2089 
2090     case 8:
2091         pal = CreateHalftonePalette(hdc);
2092         GetPaletteEntries(pal, 0, 256, entries);
2093         for (i = 0; i < 256; i++)
2094         {
2095             table[i].rgbRed = entries[i].peRed;
2096             table[i].rgbGreen = entries[i].peGreen;
2097             table[i].rgbBlue = entries[i].peBlue;
2098             table[i].rgbReserved = 0;
2099         }
2100         DeleteObject(pal);
2101         break;
2102 
2103     default:
2104         ok(0, "unhandled depth %d\n", bpp);
2105     }
2106 }
2107 
2108 static void test_color_table(UINT ilc)
2109 {
2110     HIMAGELIST himl;
2111     INT ret;
2112     char bmi_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors) + 256 * sizeof(RGBQUAD)];
2113     BITMAPINFO *bmi = (BITMAPINFO *)bmi_buffer;
2114     HDC hdc = CreateCompatibleDC(0);
2115     HBITMAP dib4, dib8, dib32;
2116     RGBQUAD rgb[256], default_table[256];
2117 
2118     get_default_color_table(hdc, ilc & 0xfe, default_table);
2119 
2120     himl = pImageList_Create(16, 16, ilc, 0, 3);
2121     ok(himl != NULL, "got %p\n", himl);
2122 
2123     memset(bmi_buffer, 0, sizeof(bmi_buffer));
2124     bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
2125     bmi->bmiHeader.biHeight = 16;
2126     bmi->bmiHeader.biWidth = 16;
2127     bmi->bmiHeader.biBitCount = 8;
2128     bmi->bmiHeader.biPlanes = 1;
2129     bmi->bmiHeader.biCompression = BI_RGB;
2130     bmi->bmiColors[0].rgbRed = 0xff;
2131     bmi->bmiColors[1].rgbGreen = 0xff;
2132     bmi->bmiColors[2].rgbBlue = 0xff;
2133 
2134     dib8 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2135 
2136     bmi->bmiHeader.biBitCount = 4;
2137     bmi->bmiColors[0].rgbRed   = 0xff;
2138     bmi->bmiColors[0].rgbGreen = 0x00;
2139     bmi->bmiColors[0].rgbBlue  = 0xff;
2140     bmi->bmiColors[1].rgbRed   = 0xff;
2141     bmi->bmiColors[1].rgbGreen = 0xff;
2142     bmi->bmiColors[1].rgbBlue  = 0x00;
2143     bmi->bmiColors[2].rgbRed   = 0x00;
2144     bmi->bmiColors[2].rgbGreen = 0xff;
2145     bmi->bmiColors[2].rgbBlue  = 0xff;
2146 
2147     dib4 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2148 
2149     bmi->bmiHeader.biBitCount = 32;
2150 
2151     dib32 = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
2152 
2153     /* add 32 first then 8.  This won't set the color table */
2154     ret = pImageList_Add(himl, dib32, NULL);
2155     ok(ret == 0, "got %d\n", ret);
2156     ret = pImageList_Add(himl, dib8, NULL);
2157     ok(ret == 1, "got %d\n", ret);
2158 
2159     check_color_table("add 32, 8", hdc, himl, ilc, default_table, NULL);
2160 
2161     /* since the previous _Adds didn't set the color table, this one will */
2162     ret = pImageList_Remove(himl, -1);
2163     ok(ret, "got %d\n", ret);
2164     ret = pImageList_Add(himl, dib8, NULL);
2165     ok(ret == 0, "got %d\n", ret);
2166 
2167     memset(rgb, 0, sizeof(rgb));
2168     rgb[0].rgbRed = 0xff;
2169     rgb[1].rgbGreen = 0xff;
2170     rgb[2].rgbBlue = 0xff;
2171     check_color_table("remove all, add 8", hdc, himl, ilc, rgb, default_table);
2172 
2173     /* remove all, add 4. Color table remains the same since it's inplicitly
2174        been set by the previous _Add */
2175     ret = pImageList_Remove(himl, -1);
2176     ok(ret, "got %d\n", ret);
2177     ret = pImageList_Add(himl, dib4, NULL);
2178     ok(ret == 0, "got %d\n", ret);
2179     check_color_table("remove all, add 4", hdc, himl, ilc, rgb, default_table);
2180 
2181     pImageList_Destroy(himl);
2182     himl = pImageList_Create(16, 16, ilc, 0, 3);
2183     ok(himl != NULL, "got %p\n", himl);
2184 
2185     /* add 4 */
2186     ret = pImageList_Add(himl, dib4, NULL);
2187     ok(ret == 0, "got %d\n", ret);
2188 
2189     memset(rgb, 0, 16 * sizeof(rgb[0]));
2190     rgb[0].rgbRed = 0xff;
2191     rgb[0].rgbBlue = 0xff;
2192     rgb[1].rgbRed = 0xff;
2193     rgb[1].rgbGreen = 0xff;
2194     rgb[2].rgbGreen = 0xff;
2195     rgb[2].rgbBlue = 0xff;
2196     memcpy(rgb + 16, default_table + 16, 240 * sizeof(rgb[0]));
2197 
2198     check_color_table("add 4", hdc, himl, ilc, rgb, default_table);
2199 
2200     pImageList_Destroy(himl);
2201     himl = pImageList_Create(16, 16, ilc, 0, 3);
2202     ok(himl != NULL, "got %p\n", himl);
2203 
2204     /* set color table, add 8 */
2205     ret = pImageList_Remove(himl, -1);
2206     ok(ret, "got %d\n", ret);
2207     memset(rgb, 0, sizeof(rgb));
2208     rgb[0].rgbRed = 0xcc;
2209     rgb[1].rgbBlue = 0xcc;
2210     ret = pImageList_SetColorTable(himl, 0, 2, rgb);
2211     ok(ret == 2, "got %d\n", ret);
2212     /* the table is set, so this doesn't change it */
2213     ret = pImageList_Add(himl, dib8, NULL);
2214     ok(ret == 0, "got %d\n", ret);
2215 
2216     memcpy(rgb + 2, default_table + 2, 254 * sizeof(rgb[0]));
2217     check_color_table("SetColorTable", hdc, himl, ilc, rgb, NULL);
2218 
2219     DeleteObject(dib32);
2220     DeleteObject(dib8);
2221     DeleteObject(dib4);
2222     DeleteDC(hdc);
2223     pImageList_Destroy(himl);
2224 }
2225 
2226 static void test_copy(void)
2227 {
2228     HIMAGELIST dst, src;
2229     BOOL ret;
2230     int count;
2231 
2232     dst = pImageList_Create(5, 11, ILC_COLOR, 1, 1);
2233     count = pImageList_GetImageCount(dst);
2234     ok(!count, "ImageList not empty.\n");
2235     src = createImageList(7, 13);
2236     count = pImageList_GetImageCount(src);
2237     ok(count > 2, "Tests need an ImageList with more than 2 images\n");
2238 
2239     /* ImageList_Copy() cannot copy between two ImageLists */
2240     ret = pImageList_Copy(dst, 0, src, 2, ILCF_MOVE);
2241     ok(!ret, "ImageList_Copy() should have returned FALSE\n");
2242     count = pImageList_GetImageCount(dst);
2243     ok(count == 0, "Expected no image in dst ImageList, got %d\n", count);
2244 
2245     pImageList_Destroy(dst);
2246     pImageList_Destroy(src);
2247 }
2248 
2249 static void test_loadimage(void)
2250 {
2251     HIMAGELIST list;
2252     DWORD flags;
2253 
2254     list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_DEFAULT,
2255                                  IMAGE_BITMAP, LR_CREATEDIBSECTION );
2256     ok( list != NULL, "got %p\n", list );
2257     flags = pImageList_GetFlags( list );
2258     ok( flags == (ILC_COLOR4 | ILC_MASK), "got %08x\n", flags );
2259     pImageList_Destroy( list );
2260 
2261     list = pImageList_LoadImageW( hinst, MAKEINTRESOURCEW(IDB_BITMAP_128x15), 16, 1, CLR_NONE,
2262                                  IMAGE_BITMAP, LR_CREATEDIBSECTION );
2263     ok( list != NULL, "got %p\n", list );
2264     flags = pImageList_GetFlags( list );
2265     ok( flags == ILC_COLOR4, "got %08x\n", flags );
2266     pImageList_Destroy( list );
2267 }
2268 
2269 static void test_IImageList_Clone(void)
2270 {
2271     IImageList *imgl, *imgl2;
2272     HIMAGELIST himl;
2273     HRESULT hr;
2274     ULONG ref;
2275 
2276     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2277     imgl = (IImageList*)himl;
2278 
2279 if (0)
2280 {
2281     /* crashes on native */
2282     IImageList_Clone(imgl, &IID_IImageList, NULL);
2283 }
2284 
2285     hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
2286     ok(hr == S_OK, "got 0x%08x\n", hr);
2287     ref = IImageList_Release(imgl2);
2288     ok(ref == 0, "got %u\n", ref);
2289 
2290     IImageList_Release(imgl);
2291 }
2292 
2293 static void test_IImageList_GetBkColor(void)
2294 {
2295     IImageList *imgl;
2296     HIMAGELIST himl;
2297     COLORREF color;
2298     HRESULT hr;
2299 
2300     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2301     imgl = (IImageList*)himl;
2302 
2303 if (0)
2304 {
2305     /* crashes on native */
2306     IImageList_GetBkColor(imgl, NULL);
2307 }
2308 
2309     hr = IImageList_GetBkColor(imgl, &color);
2310     ok(hr == S_OK, "got 0x%08x\n", hr);
2311 
2312     IImageList_Release(imgl);
2313 }
2314 
2315 static void test_IImageList_SetBkColor(void)
2316 {
2317     IImageList *imgl;
2318     HIMAGELIST himl;
2319     COLORREF color;
2320     HRESULT hr;
2321 
2322     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2323     imgl = (IImageList*)himl;
2324 
2325 if (0)
2326 {
2327     /* crashes on native */
2328     IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
2329 }
2330 
2331     hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2332     ok(hr == S_OK, "got 0x%08x\n", hr);
2333 
2334     hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2335     ok(hr == S_OK, "got 0x%08x\n", hr);
2336 
2337     color = 0xdeadbeef;
2338     hr = IImageList_GetBkColor(imgl, &color);
2339     ok(hr == S_OK, "got 0x%08x\n", hr);
2340     ok(color == CLR_NONE, "got %x\n", color);
2341 
2342     IImageList_Release(imgl);
2343 }
2344 
2345 static void test_IImageList_GetImageCount(void)
2346 {
2347     IImageList *imgl;
2348     HIMAGELIST himl;
2349     int count;
2350     HRESULT hr;
2351 
2352     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2353     imgl = (IImageList*)himl;
2354 
2355 if (0)
2356 {
2357     /* crashes on native */
2358     IImageList_GetImageCount(imgl, NULL);
2359 }
2360 
2361     count = -1;
2362     hr = IImageList_GetImageCount(imgl, &count);
2363     ok(hr == S_OK, "got 0x%08x\n", hr);
2364     ok(count == 0, "got %d\n", count);
2365 
2366     IImageList_Release(imgl);
2367 }
2368 
2369 static void test_IImageList_GetIconSize(void)
2370 {
2371     IImageList *imgl;
2372     HIMAGELIST himl;
2373     int cx, cy;
2374     HRESULT hr;
2375 
2376     himl = pImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2377     imgl = (IImageList*)himl;
2378 
2379     hr = IImageList_GetIconSize(imgl, NULL, NULL);
2380     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2381 
2382     hr = IImageList_GetIconSize(imgl, &cx, NULL);
2383     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2384 
2385     hr = IImageList_GetIconSize(imgl, NULL, &cy);
2386     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2387 
2388     IImageList_Release(imgl);
2389 }
2390 
2391 static void init_functions(void)
2392 {
2393     HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
2394 
2395 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
2396 #define X2(f, ord) p##f = (void*)GetProcAddress(hComCtl32, (const char *)ord);
2397     X(ImageList_Create);
2398     X(ImageList_Destroy);
2399     X(ImageList_Add);
2400     X(ImageList_DrawIndirect);
2401     X(ImageList_SetImageCount);
2402     X(ImageList_SetImageCount);
2403     X2(ImageList_SetColorTable, 390);
2404     X(ImageList_GetFlags);
2405     X(ImageList_BeginDrag);
2406     X(ImageList_GetDragImage);
2407     X(ImageList_EndDrag);
2408     X(ImageList_GetImageCount);
2409     X(ImageList_SetDragCursorImage);
2410     X(ImageList_GetIconSize);
2411     X(ImageList_Remove);
2412     X(ImageList_ReplaceIcon);
2413     X(ImageList_Replace);
2414     X(ImageList_Merge);
2415     X(ImageList_GetImageInfo);
2416     X(ImageList_Write);
2417     X(ImageList_Read);
2418     X(ImageList_Copy);
2419     X(ImageList_LoadImageW);
2420     X(ImageList_CoCreateInstance);
2421     X(HIMAGELIST_QueryInterface);
2422     X(ImageList_Draw);
2423 #undef X
2424 #undef X2
2425 }
2426 
2427 START_TEST(imagelist)
2428 {
2429     ULONG_PTR ctx_cookie;
2430     HANDLE hCtx;
2431 
2432     init_functions();
2433 
2434     hinst = GetModuleHandleA(NULL);
2435 
2436     test_create_destroy();
2437     test_begindrag();
2438     test_hotspot();
2439     test_add_remove();
2440     test_imagecount();
2441     test_DrawIndirect();
2442     test_merge();
2443     test_merge_colors();
2444     test_imagelist_storage();
2445     test_iconsize();
2446     test_color_table(ILC_COLOR4);
2447     test_color_table(ILC_COLOR8);
2448     test_copy();
2449     test_loadimage();
2450 
2451     /* Now perform v6 tests */
2452     if (!load_v6_module(&ctx_cookie, &hCtx))
2453         return;
2454 
2455     init_functions();
2456 
2457     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2458 
2459     /* Do v6.0 tests */
2460     test_add_remove();
2461     test_imagecount();
2462     test_DrawIndirect();
2463     test_merge();
2464     test_imagelist_storage();
2465     test_iconsize();
2466     test_color_table(ILC_COLOR4);
2467     test_color_table(ILC_COLOR8);
2468     test_copy();
2469     test_loadimage();
2470 
2471     test_ImageList_DrawIndirect();
2472     test_shell_imagelist();
2473     test_iimagelist();
2474 
2475     test_IImageList_Add_Remove();
2476     test_IImageList_Get_SetImageCount();
2477     test_IImageList_Draw();
2478     test_IImageList_Merge();
2479     test_IImageList_Clone();
2480     test_IImageList_GetBkColor();
2481     test_IImageList_SetBkColor();
2482     test_IImageList_GetImageCount();
2483     test_IImageList_GetIconSize();
2484 
2485     CoUninitialize();
2486 
2487     unload_v6_module(ctx_cookie, hCtx);
2488 }
2489