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