2 * Unit test suite for imagelist control.
4 * Copyright 2004 Michael Stefaniuc
5 * Copyright 2002 Mike McCormack for CodeWeavers
6 * Copyright 2007 Dmitry Timoshkov
7 * Copyright 2009 Owen Rudge for CodeWeavers
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.
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.
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
36 #include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
38 #include "commoncontrols.h"
41 #include "wine/test.h"
47 #define WAIT Sleep (1000)
48 #define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW)
54 #define IMAGELIST_MAGIC (('L' << 8) | 'I')
57 /* Header used by ImageList_Read() and ImageList_Write() */
58 typedef struct _ILHEAD
73 static HIMAGELIST (WINAPI *pImageList_Create)(int, int, UINT, int, int);
74 static int (WINAPI *pImageList_Add)(HIMAGELIST, HBITMAP, HBITMAP);
75 static BOOL (WINAPI *pImageList_DrawIndirect)(IMAGELISTDRAWPARAMS*);
76 static BOOL (WINAPI *pImageList_SetImageCount)(HIMAGELIST,UINT);
77 static HRESULT (WINAPI *pImageList_CoCreateInstance)(REFCLSID,const IUnknown *,
79 static HRESULT (WINAPI *pHIMAGELIST_QueryInterface)(HIMAGELIST,REFIID,void **);
81 static HINSTANCE hinst;
83 /* These macros build cursor/bitmap data in 4x4 pixel blocks */
84 #define B(x,y) ((x?0xf0:0)|(y?0xf:0))
85 #define ROW1(a,b,c,d,e,f,g,h) B(a,b),B(c,d),B(e,f),B(g,h)
86 #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), \
87 ROW1(a,b,c,d,e,f,g,h), ROW1(a,b,c,d,e,f,g,h)
88 #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)
89 #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), \
90 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), \
91 ROW2(a,b,c,d,e,f,g,h,i,j,k,l)
93 static const BYTE empty_bits[48*48/8];
95 static const BYTE icon_bits[32*32/8] =
97 ROW32(0,0,0,0,0,0,0,0),
98 ROW32(0,0,1,1,1,1,0,0),
99 ROW32(0,1,1,1,1,1,1,0),
100 ROW32(0,1,1,0,0,1,1,0),
101 ROW32(0,1,1,0,0,1,1,0),
102 ROW32(0,1,1,1,1,1,1,0),
103 ROW32(0,0,1,1,1,1,0,0),
104 ROW32(0,0,0,0,0,0,0,0)
107 static const BYTE bitmap_bits[48*48/8] =
109 ROW48(0,0,0,0,0,0,0,0,0,0,0,0),
110 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
111 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
112 ROW48(0,1,0,0,0,0,0,0,1,0,1,0),
113 ROW48(0,1,0,0,0,0,0,1,0,0,1,0),
114 ROW48(0,1,0,0,0,0,1,0,0,0,1,0),
115 ROW48(0,1,0,0,0,1,0,0,0,0,1,0),
116 ROW48(0,1,0,0,1,0,0,0,0,0,1,0),
117 ROW48(0,1,0,1,0,0,0,0,0,0,1,0),
118 ROW48(0,1,1,0,0,0,0,0,0,1,1,0),
119 ROW48(0,1,1,1,1,1,1,1,1,1,1,0),
120 ROW48(0,0,0,0,0,0,0,0,0,0,0,0)
123 static HIMAGELIST createImageList(int cx, int cy)
125 /* Create an ImageList and put an image into it */
126 HIMAGELIST himl = ImageList_Create(cx, cy, ILC_COLOR, 1, 1);
127 HBITMAP hbm = CreateBitmap(48, 48, 1, 1, bitmap_bits);
128 ImageList_Add(himl, hbm, NULL);
133 static HWND create_a_window(void)
135 char className[] = "bmwnd";
136 char winName[] = "Test Bitmap";
138 static int registered = 0;
144 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
145 cls.lpfnWndProc = DefWindowProcA;
149 cls.hIcon = LoadIconA (0, IDI_APPLICATION);
150 cls.hCursor = LoadCursorA (0, IDC_ARROW);
151 cls.hbrBackground = GetStockObject (WHITE_BRUSH);
152 cls.lpszMenuName = 0;
153 cls.lpszClassName = className;
155 RegisterClassA (&cls);
160 hWnd = CreateWindowA (className, winName,
161 WS_OVERLAPPEDWINDOW ,
162 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
166 ShowWindow (hWnd, SW_SHOW);
174 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
175 LPCSTR loc, BOOL clear)
179 if (!himl) return NULL;
181 SetWindowText(hwnd, loc);
183 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
190 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
191 ReleaseDC(hwnd, hdc);
198 /* Useful for checking differences */
200 static void dump_bits(const BYTE *p, const BYTE *q, int size)
206 for (i = 0; i < size * 2; i++)
209 for (j = 0; j < size; j++)
210 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
212 for (j = 0; j < size; j++)
213 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
222 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
223 const BYTE *checkbits, LPCSTR loc)
226 BYTE bits[100*100/8];
233 memset(bits, 0, sizeof(bits));
234 hdc = show_image(hwnd, himl, idx, size, loc, FALSE);
236 c = GetPixel(hdc, 0, 0);
238 for (y = 0; y < size; y ++)
240 for (x = 0; x < size; x++)
243 if (GetPixel(hdc, x, y) != c) bits[i] |= (0x80 >> (x & 0x7));
247 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
248 ReleaseDC(hwnd, hdc);
250 ok (memcmp(bits, checkbits, (size * size)/8) == 0,
251 "%s: bits different\n", loc);
252 if (memcmp(bits, checkbits, (size * size)/8))
253 dump_bits(bits, checkbits, size);
257 static void test_hotspot(void)
268 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
269 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
276 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
277 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
278 HWND hwnd = create_a_window();
281 for (i = 0; i < HOTSPOTS_MAX; i++) {
282 for (j = 0; j < HOTSPOTS_MAX; j++) {
283 int dx1 = hotspots[i].dx;
284 int dy1 = hotspots[i].dy;
285 int dx2 = hotspots[j].dx;
286 int dy2 = hotspots[j].dy;
287 int correctx, correcty, newx, newy;
292 ret = ImageList_BeginDrag(himl1, 0, dx1, dy1);
293 ok(ret != 0, "BeginDrag failed for { %d, %d }\n", dx1, dy1);
294 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
295 show_image(hwnd, himl1, 0, max(SIZEX1, SIZEY1), loc, TRUE);
297 /* check merging the dragged image with a second image */
298 ret = ImageList_SetDragCursorImage(himl2, 0, dx2, dy2);
299 ok(ret != 0, "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
301 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
302 show_image(hwnd, himl2, 0, max(SIZEX2, SIZEY2), loc, TRUE);
304 /* check new hotspot, it should be the same like the old one */
305 himlNew = ImageList_GetDragImage(NULL, &ppt);
306 ok(ppt.x == dx1 && ppt.y == dy1,
307 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
308 dx1, dy1, ppt.x, ppt.y);
309 /* check size of new dragged image */
310 ImageList_GetIconSize(himlNew, &newx, &newy);
311 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
312 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
313 ok(newx == correctx && newy == correcty,
314 "Expected drag image size [%d,%d] got [%d,%d]\n",
315 correctx, correcty, newx, newy);
316 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
317 show_image(hwnd, himlNew, 0, max(correctx, correcty), loc, TRUE);
326 ImageList_Destroy(himl2);
327 ImageList_Destroy(himl1);
331 static void test_add_remove(void)
339 /* create an imagelist to play with */
340 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
341 ok(himl!=0,"failed to create imagelist\n");
343 /* load the icons to add to the image list */
344 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
345 ok(hicon1 != 0, "no hicon1\n");
346 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
347 ok(hicon2 != 0, "no hicon2\n");
348 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
349 ok(hicon3 != 0, "no hicon3\n");
351 /* remove when nothing exists */
352 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
353 /* removing everything from an empty imagelist should succeed */
354 ok(ImageList_RemoveAll(himl),"removed nonexistent icon\n");
357 ok(0==ImageList_AddIcon(himl, hicon1),"failed to add icon1\n");
358 ok(1==ImageList_AddIcon(himl, hicon2),"failed to add icon2\n");
359 ok(2==ImageList_AddIcon(himl, hicon3),"failed to add icon3\n");
361 /* remove an index out of range */
362 ok(!ImageList_Remove(himl,4711),"removed nonexistent icon\n");
365 ok(ImageList_Remove(himl,0),"can't remove 0\n");
366 ok(ImageList_Remove(himl,0),"can't remove 0\n");
367 ok(ImageList_Remove(himl,0),"can't remove 0\n");
369 /* remove one extra */
370 ok(!ImageList_Remove(himl,0),"removed nonexistent icon\n");
373 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
375 ok(-1==ImageList_AddIcon((HIMAGELIST)0xdeadbeef, hicon1),"don't crash on bad handle\n");
377 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
378 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
379 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
382 static void test_imagecount(void)
386 ok(0==ImageList_GetImageCount((HIMAGELIST)0xdeadbeef),"don't crash on bad handle\n");
388 if (!pImageList_SetImageCount)
390 win_skip("ImageList_SetImageCount not available\n");
394 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
395 ok(himl!=0,"failed to create imagelist\n");
397 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
398 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
399 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
400 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
401 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
402 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
404 ok(ImageList_Destroy(himl), "destroy imagelist failed\n");
407 static void test_DrawIndirect(void)
415 IMAGELISTDRAWPARAMS imldp;
419 if (!pImageList_DrawIndirect)
421 win_skip("ImageList_DrawIndirect not available, skipping test\n");
425 hwndfortest = create_a_window();
426 hdc = GetDC(hwndfortest);
427 ok(hdc!=NULL, "couldn't get DC\n");
429 /* create an imagelist to play with */
430 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
431 ok(himl!=0,"failed to create imagelist\n");
433 /* load the icons to add to the image list */
434 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
435 ok(hbm1 != 0, "no bitmap 1\n");
436 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
437 ok(hbm2 != 0, "no bitmap 2\n");
438 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
439 ok(hbm3 != 0, "no bitmap 3\n");
442 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
443 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
445 if (pImageList_SetImageCount)
447 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
448 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
449 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
452 memset(&imldp, 0, sizeof (imldp));
453 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
454 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
455 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
457 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
458 imldp.himl = (HIMAGELIST)0xdeadbeef;
459 ok(!pImageList_DrawIndirect(&imldp),"bad himl succeeded!\n");
465 imldp.fStyle = SRCCOPY;
466 imldp.rgbBk = CLR_DEFAULT;
467 imldp.rgbFg = CLR_DEFAULT;
470 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
472 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
474 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
476 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
479 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
480 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
481 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
484 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
486 /* bitmaps should not be deleted by the imagelist */
487 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
488 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
489 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
491 ReleaseDC(hwndfortest, hdc);
492 DestroyWindow(hwndfortest);
495 static int get_color_format(HBITMAP bmp)
498 HDC hdc = CreateCompatibleDC(0);
499 HBITMAP hOldBmp = SelectObject(hdc, bmp);
502 memset(&bmi, 0, sizeof(bmi));
503 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
504 ret = GetDIBits(hdc, bmp, 0, 0, 0, &bmi, DIB_RGB_COLORS);
505 ok(ret, "GetDIBits failed\n");
507 SelectObject(hdc, hOldBmp);
509 return bmi.bmiHeader.biBitCount;
512 static void test_merge_colors(void)
514 HIMAGELIST himl[8], hmerge;
515 int sizes[] = { ILC_COLOR, ILC_COLOR | ILC_MASK, ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24, ILC_COLOR32, ILC_COLORDDB };
520 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
521 ok(hicon1 != NULL, "failed to create hicon1\n");
523 for (i = 0; i < 8; i++)
525 himl[i] = ImageList_Create(32, 32, sizes[i], 0, 3);
526 ok(himl[i] != NULL, "failed to create himl[%d]\n", i);
527 ok(0 == ImageList_AddIcon(himl[i], hicon1), "add icon1 to himl[%d] failed\n", i);
528 if (i == 0 || i == 1 || i == 7)
530 ImageList_GetImageInfo(himl[i], 0, &info);
531 sizes[i] = get_color_format(info.hbmImage);
535 for (i = 0; i < 8; i++)
536 for (j = 0; j < 8; j++)
538 hmerge = ImageList_Merge(himl[i], 0, himl[j], 0, 0, 0);
539 ok(hmerge != NULL, "merge himl[%d], himl[%d] failed\n", i, j);
541 ImageList_GetImageInfo(hmerge, 0, &info);
542 bpp = get_color_format(info.hbmImage);
543 /* ILC_COLOR[X] is defined as [X] */
544 if (i == 4 && j == 7)
545 ok(bpp == 16, /* merging ILC_COLOR16 with ILC_COLORDDB seems to be a special case */
546 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
548 ok(bpp == (i > j ? sizes[i] : sizes[j]),
549 "wrong biBitCount %d when merging lists %d (%d) and %d (%d)\n", bpp, i, sizes[i], j, sizes[j]);
550 ok(info.hbmMask != 0, "Imagelist merged from %d and %d had no mask\n", i, j);
552 if (hmerge) ImageList_Destroy(hmerge);
555 for (i = 0; i < 8; i++)
556 ImageList_Destroy(himl[i]);
559 static void test_merge(void)
561 HIMAGELIST himl1, himl2, hmerge;
563 HWND hwnd = create_a_window();
565 himl1 = ImageList_Create(32,32,0,0,3);
566 ok(himl1 != NULL,"failed to create himl1\n");
568 himl2 = ImageList_Create(32,32,0,0,3);
569 ok(himl2 != NULL,"failed to create himl2\n");
571 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
572 ok(hicon1 != NULL, "failed to create hicon1\n");
574 if (!himl1 || !himl2 || !hicon1)
577 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
578 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
580 /* If himl1 has no images, merge still succeeds */
581 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
582 ok(hmerge != NULL, "merge himl1,-1 failed\n");
583 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
584 if (hmerge) ImageList_Destroy(hmerge);
586 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
587 ok(hmerge != NULL,"merge himl1,0 failed\n");
588 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
589 if (hmerge) ImageList_Destroy(hmerge);
591 /* Same happens if himl2 is empty */
592 ImageList_Destroy(himl2);
593 himl2 = ImageList_Create(32,32,0,0,3);
594 ok(himl2 != NULL,"failed to recreate himl2\n");
598 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
599 ok(hmerge != NULL, "merge himl2,-1 failed\n");
600 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
601 if (hmerge) ImageList_Destroy(hmerge);
603 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
604 ok(hmerge != NULL, "merge himl2,0 failed\n");
605 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
606 if (hmerge) ImageList_Destroy(hmerge);
608 /* Now try merging an image with itself */
609 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
611 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
612 ok(hmerge != NULL, "merge himl2 with itself failed\n");
613 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
614 if (hmerge) ImageList_Destroy(hmerge);
616 /* Try merging 2 different image lists */
617 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
619 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
620 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
621 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
622 if (hmerge) ImageList_Destroy(hmerge);
624 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
625 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
626 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
627 if (hmerge) ImageList_Destroy(hmerge);
629 ImageList_Destroy(himl1);
630 ImageList_Destroy(himl2);
635 /*********************** imagelist storage test ***************************/
641 IStream IStream_iface;
642 char *iml_data; /* written imagelist data */
646 static struct my_IStream *impl_from_IStream(IStream *iface)
648 return CONTAINING_RECORD(iface, struct my_IStream, IStream_iface);
651 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(IStream *iface, REFIID riid,
658 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(IStream *iface)
664 static ULONG STDMETHODCALLTYPE Test_Stream_Release(IStream *iface)
670 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(IStream *iface, void *pv, ULONG cb,
677 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
679 my_is->iml_data_size += add;
681 if (!my_is->iml_data)
682 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
684 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
686 return my_is->iml_data != NULL;
689 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(IStream *iface, const void *pv, ULONG cb,
692 struct my_IStream *my_is = impl_from_IStream(iface);
693 ULONG current_iml_data_size = my_is->iml_data_size;
695 if (!allocate_storage(my_is, cb)) return E_FAIL;
697 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
698 if (pcbWritten) *pcbWritten = cb;
703 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
704 DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
710 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
716 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(IStream *iface, IStream *pstm,
717 ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead,
718 ULARGE_INTEGER *pcbWritten)
724 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(IStream *iface, DWORD grfCommitFlags)
730 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(IStream *iface)
736 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
737 ULARGE_INTEGER cb, DWORD dwLockType)
743 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
744 ULARGE_INTEGER cb, DWORD dwLockType)
750 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(IStream *iface, STATSTG *pstatstg,
757 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(IStream *iface, IStream **ppstm)
763 static const IStreamVtbl Test_Stream_Vtbl =
765 Test_Stream_QueryInterface,
775 Test_Stream_LockRegion,
776 Test_Stream_UnlockRegion,
781 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
783 static INT DIB_GetWidthBytes( int width, int bpp )
785 return ((width * bpp + 31) / 8) & ~3;
788 static ULONG check_bitmap_data(const char *bm_data, ULONG bm_data_size,
789 INT width, INT height, INT bpp,
792 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
793 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
794 ULONG hdr_size, image_size;
796 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
797 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
799 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
800 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
801 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
802 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
803 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
805 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
806 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
807 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
808 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
809 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
811 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
812 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
817 sprintf(fname, "bmp_%s.bmp", comment);
818 f = fopen(fname, "wb");
819 fwrite(bm_data, 1, bm_data_size, f);
823 return hdr_size + image_size;
826 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow, INT flags)
828 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
830 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
831 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
832 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
833 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
834 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
835 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
836 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
837 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
838 ok(ilh->flags == flags || broken(!(ilh->flags & 0xfe) && (flags & 0xfe) == ILC_COLOR4), /* <= w2k */
839 "wrong flags %04x\n", ilh->flags);
840 ok(ilh->ovls[0] == -1, "wrong ovls[0] %04x\n", ilh->ovls[0]);
841 ok(ilh->ovls[1] == -1, "wrong ovls[1] %04x\n", ilh->ovls[1]);
842 ok(ilh->ovls[2] == -1, "wrong ovls[2] %04x\n", ilh->ovls[2]);
843 ok(ilh->ovls[3] == -1, "wrong ovls[3] %04x\n", ilh->ovls[3]);
846 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
850 HBITMAP hbmp, hbmp_old;
852 RECT rc = { 0, 0, cx, cy };
854 hdc = CreateCompatibleDC(0);
856 memset(&bmi, 0, sizeof(bmi));
857 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
858 bmi.bmiHeader.biHeight = cx;
859 bmi.bmiHeader.biWidth = cy;
860 bmi.bmiHeader.biBitCount = 24;
861 bmi.bmiHeader.biPlanes = 1;
862 bmi.bmiHeader.biCompression = BI_RGB;
863 hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, NULL, NULL, 0);
865 hbmp_old = SelectObject(hdc, hbmp);
867 hbrush = CreateSolidBrush(color);
868 FillRect(hdc, &rc, hbrush);
869 DeleteObject(hbrush);
871 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
873 SelectObject(hdc, hbmp_old);
879 #define iml_clear_stream_data() \
880 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
881 Test_Stream.iml_data = NULL; \
882 Test_Stream.iml_data_size = 0;
884 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
885 INT width, INT height, INT flags, const char *comment)
887 INT ret, cxx, cyy, size;
889 trace("%s\n", comment);
891 ret = ImageList_GetImageCount(himl);
892 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
894 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
895 ok(ret, "ImageList_GetIconSize failed\n");
896 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
897 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
899 iml_clear_stream_data();
900 ret = ImageList_Write(himl, &Test_Stream.IStream_iface);
901 ok(ret, "ImageList_Write failed\n");
903 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
904 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
906 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow, flags);
907 size = check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
908 Test_Stream.iml_data_size - sizeof(ILHEAD),
909 width, height, flags & 0xfe, comment);
910 if (size < Test_Stream.iml_data_size - sizeof(ILHEAD)) /* mask is present */
912 ok( flags & ILC_MASK, "extra data %u/%u but mask not expected\n",
913 Test_Stream.iml_data_size, size );
914 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD) + size,
915 Test_Stream.iml_data_size - sizeof(ILHEAD) - size,
916 width, height, 1, comment);
920 static void image_list_init(HIMAGELIST himl)
926 static const struct test_data
929 INT cx, cy, cur, max, grow, width, height, bpp;
933 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
934 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
935 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
936 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
937 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
938 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
939 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
940 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
941 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
942 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
943 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
944 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
945 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
946 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
947 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
948 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
949 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
950 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
951 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
952 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
953 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
954 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
955 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
956 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
959 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "total 0");
961 #define add_bitmap(grey) \
962 sprintf(comment, "%d", n++); \
963 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
964 ImageList_Add(himl, hbm, NULL); \
967 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
969 add_bitmap(td[i].grey);
970 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
971 td[i].width, td[i].height, td[i].bpp, td[i].comment);
976 static void test_imagelist_storage(void)
983 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
984 ok(himl != 0, "ImageList_Create failed\n");
986 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "empty");
988 image_list_init(himl);
989 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "orig");
991 ret = ImageList_Remove(himl, 4);
992 ok(ret, "ImageList_Remove failed\n");
993 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "1");
995 ret = ImageList_Remove(himl, 5);
996 ok(ret, "ImageList_Remove failed\n");
997 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "2");
999 ret = ImageList_Remove(himl, 6);
1000 ok(ret, "ImageList_Remove failed\n");
1001 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "3");
1003 ret = ImageList_Remove(himl, 7);
1004 ok(ret, "ImageList_Remove failed\n");
1005 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "4");
1007 ret = ImageList_Remove(himl, -2);
1008 ok(!ret, "ImageList_Remove(-2) should fail\n");
1009 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "5");
1011 ret = ImageList_Remove(himl, 20);
1012 ok(!ret, "ImageList_Remove(20) should fail\n");
1013 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "6");
1015 ret = ImageList_Remove(himl, -1);
1016 ok(ret, "ImageList_Remove(-1) failed\n");
1017 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "7");
1019 ret = ImageList_Destroy(himl);
1020 ok(ret, "ImageList_Destroy failed\n");
1022 iml_clear_stream_data();
1024 /* test ImageList_Create storage allocation */
1026 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
1027 ok(himl != 0, "ImageList_Create failed\n");
1028 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 0 grow 32");
1029 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1030 ret = ImageList_Add(himl, hbm, NULL);
1031 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1032 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, ILC_COLOR24, "add 1 x 9");
1034 ret = ImageList_Destroy(himl);
1035 ok(ret, "ImageList_Destroy failed\n");
1036 iml_clear_stream_data();
1038 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1039 ok(himl != 0, "ImageList_Create failed\n");
1040 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 4");
1041 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1042 ret = ImageList_Add(himl, hbm, NULL);
1043 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1044 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "add 9 x 1");
1045 ret = ImageList_Add(himl, hbm, NULL);
1046 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1047 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, ILC_COLOR24, "add 9 x 1");
1049 ret = ImageList_Destroy(himl);
1050 ok(ret, "ImageList_Destroy failed\n");
1051 iml_clear_stream_data();
1053 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1054 ok(himl != 0, "ImageList_Create failed\n");
1055 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, ILC_COLOR24, "init 207 grow 209");
1056 ret = ImageList_Destroy(himl);
1057 ok(ret, "ImageList_Destroy failed\n");
1058 iml_clear_stream_data();
1060 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1061 ok(himl != 0, "ImageList_Create failed\n");
1062 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, ILC_COLOR24, "init 209 grow 207");
1063 ret = ImageList_Destroy(himl);
1064 ok(ret, "ImageList_Destroy failed\n");
1065 iml_clear_stream_data();
1067 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1068 ok(himl != 0, "ImageList_Create failed\n");
1069 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, ILC_COLOR24, "init 14 grow 4");
1070 ret = ImageList_Destroy(himl);
1071 ok(ret, "ImageList_Destroy failed\n");
1072 iml_clear_stream_data();
1074 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1075 ok(himl != 0, "ImageList_Create failed\n");
1076 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 5 grow 9");
1077 ret = ImageList_Destroy(himl);
1078 ok(ret, "ImageList_Destroy failed\n");
1079 iml_clear_stream_data();
1081 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1082 ok(himl != 0, "ImageList_Create failed\n");
1083 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, ILC_COLOR24, "init 9 grow 5");
1084 ret = ImageList_Destroy(himl);
1085 ok(ret, "ImageList_Destroy failed\n");
1086 iml_clear_stream_data();
1088 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1089 ok(himl != 0, "ImageList_Create failed\n");
1090 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, ILC_COLOR24, "init 2 grow 4");
1091 ret = ImageList_Destroy(himl);
1092 ok(ret, "ImageList_Destroy failed\n");
1093 iml_clear_stream_data();
1095 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1096 ok(himl != 0, "ImageList_Create failed\n");
1097 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24, "init 4 grow 2");
1098 ret = ImageList_Destroy(himl);
1099 ok(ret, "ImageList_Destroy failed\n");
1100 iml_clear_stream_data();
1102 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR8, 4, 2);
1103 ok(himl != 0, "ImageList_Create failed\n");
1104 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR8, "bpp 8");
1105 ret = ImageList_Destroy(himl);
1106 ok(ret, "ImageList_Destroy failed\n");
1107 iml_clear_stream_data();
1109 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4, 4, 2);
1110 ok(himl != 0, "ImageList_Create failed\n");
1111 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp 4");
1112 ret = ImageList_Destroy(himl);
1113 ok(ret, "ImageList_Destroy failed\n");
1114 iml_clear_stream_data();
1116 himl = ImageList_Create(BMP_CX, BMP_CX, 0, 4, 2);
1117 ok(himl != 0, "ImageList_Create failed\n");
1118 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1119 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1120 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1121 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1122 DestroyIcon( icon );
1123 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4, "bpp default");
1124 ret = ImageList_Destroy(himl);
1125 ok(ret, "ImageList_Destroy failed\n");
1126 iml_clear_stream_data();
1128 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24|ILC_MASK, 4, 2);
1129 ok(himl != 0, "ImageList_Create failed\n");
1130 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1132 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1133 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1134 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1135 DestroyIcon( icon );
1136 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR24|ILC_MASK,
1138 ret = ImageList_Destroy(himl);
1139 ok(ret, "ImageList_Destroy failed\n");
1140 iml_clear_stream_data();
1142 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 4, 2);
1143 ok(himl != 0, "ImageList_Create failed\n");
1144 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1146 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1147 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1148 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1149 DestroyIcon( icon );
1150 check_iml_data(himl, BMP_CX, BMP_CX, 2, 5, 4, BMP_CX * 4, BMP_CX * 2, ILC_COLOR4|ILC_MASK,
1152 ret = ImageList_Destroy(himl);
1153 ok(ret, "ImageList_Destroy failed\n");
1154 iml_clear_stream_data();
1156 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 99);
1157 ok(himl != 0, "ImageList_Create failed\n");
1158 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1160 icon = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1161 ok( ImageList_AddIcon(himl, icon) == 0,"failed to add icon\n");
1162 ok( ImageList_AddIcon(himl, icon) == 1,"failed to add icon\n");
1163 check_iml_data(himl, BMP_CX, BMP_CX, 2, 3, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1164 "init 2 grow 99 2 icons");
1165 ok( ImageList_AddIcon(himl, icon) == 2,"failed to add icon\n");
1166 DestroyIcon( icon );
1167 check_iml_data(himl, BMP_CX, BMP_CX, 3, 104, 100, BMP_CX * 4, BMP_CX * 104/4, ILC_COLOR4|ILC_MASK,
1168 "init 2 grow 99 3 icons");
1169 ok( ImageList_Remove(himl, -1) == TRUE,"failed to remove icon\n");
1170 check_iml_data(himl, BMP_CX, BMP_CX, 0, 100, 100, BMP_CX * 4, BMP_CX * 100/4, ILC_COLOR4|ILC_MASK,
1171 "init 2 grow 99 empty");
1172 ok( ImageList_SetImageCount(himl, 22) == TRUE,"failed to set image count\n");
1173 check_iml_data(himl, BMP_CX, BMP_CX, 22, 23, 100, BMP_CX * 4, BMP_CX * 24/4, ILC_COLOR4|ILC_MASK,
1174 "init 2 grow 99 set count 22");
1175 ok( ImageList_SetImageCount(himl, 0) == TRUE,"failed to set image count\n");
1176 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 100, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1177 "init 2 grow 99 set count 0");
1178 ok( ImageList_SetImageCount(himl, 42) == TRUE,"failed to set image count\n");
1179 check_iml_data(himl, BMP_CX, BMP_CX, 42, 43, 100, BMP_CX * 4, BMP_CX * 44/4, ILC_COLOR4|ILC_MASK,
1180 "init 2 grow 99 set count 42");
1181 ret = ImageList_Destroy(himl);
1182 ok(ret, "ImageList_Destroy failed\n");
1183 iml_clear_stream_data();
1185 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65536+12);
1186 ok(himl != 0, "ImageList_Create failed\n");
1187 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 12, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1188 "init 2 grow 65536+12");
1189 ret = ImageList_Destroy(himl);
1190 ok(ret, "ImageList_Destroy failed\n");
1191 iml_clear_stream_data();
1193 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, 65535);
1194 ok(himl != 0, "ImageList_Create failed\n");
1195 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 0, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1196 "init 2 grow 65535");
1197 ret = ImageList_Destroy(himl);
1198 ok(ret, "ImageList_Destroy failed\n");
1199 iml_clear_stream_data();
1201 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR4|ILC_MASK, 2, -20);
1202 ok(himl != 0, "ImageList_Create failed\n");
1203 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX, ILC_COLOR4|ILC_MASK,
1205 ret = ImageList_Destroy(himl);
1206 ok(ret, "ImageList_Destroy failed\n");
1207 iml_clear_stream_data();
1210 static void test_shell_imagelist(void)
1212 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1213 IImageList *iml = NULL;
1220 /* Try to load function from shell32 */
1221 hShell32 = LoadLibrary("shell32.dll");
1222 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1224 if (!pSHGetImageList)
1226 win_skip("SHGetImageList not available, skipping test\n");
1227 FreeLibrary(hShell32);
1231 /* Get system image list */
1232 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1234 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1237 FreeLibrary(hShell32);
1241 IImageList_GetImageCount(iml, &out);
1242 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1244 /* Fetch the small icon size */
1245 cx = GetSystemMetrics(SM_CXSMICON);
1246 cy = GetSystemMetrics(SM_CYSMICON);
1248 /* Check icon size matches */
1249 IImageList_GetImageRect(iml, 0, &rect);
1250 ok(((rect.right == cx) && (rect.bottom == cy)),
1251 "IImageList_GetImageRect returned r:%d,b:%d\n",
1252 rect.right, rect.bottom);
1254 IImageList_Release(iml);
1255 FreeLibrary(hShell32);
1258 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1261 UINT32 *buffer = NULL;
1262 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1265 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1266 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1268 if(!hBitmap || !buffer)
1270 DeleteObject(hBitmap);
1280 static BOOL colour_match(UINT32 x, UINT32 y)
1282 const INT32 tolerance = 8;
1284 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1285 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1286 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1288 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1291 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1292 UINT32 expected, int line)
1294 bits[0] = 0x00FFFFFF;
1295 pImageList_DrawIndirect(ildp);
1296 ok(colour_match(bits[0], expected),
1297 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1298 bits[0] & 0x00FFFFFF, expected, line);
1302 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1303 UINT fStyle, UINT32 expected, int line)
1305 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1306 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1307 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1310 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1311 DWORD dwRop, UINT32 expected, int line)
1313 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1314 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1315 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1318 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1319 UINT fState, DWORD Frame, UINT32 expected, int line)
1321 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1322 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1323 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1326 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1327 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1328 UINT32 broken_expected, int line)
1330 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1331 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1332 bits[0] = 0x00FFFFFF;
1333 pImageList_DrawIndirect(&ildp);
1334 ok(colour_match(bits[0], expected) ||
1335 broken(colour_match(bits[0], broken_expected)),
1336 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1337 bits[0] & 0x00FFFFFF, expected, line);
1340 static void test_ImageList_DrawIndirect(void)
1342 HIMAGELIST himl = NULL;
1345 HBITMAP hbmOld = NULL, hbmDst = NULL;
1346 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1347 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1348 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1350 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1351 int bpp, broken_value;
1353 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1356 hdcDst = CreateCompatibleDC(0);
1357 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1360 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1362 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1363 ok(hbmMask != 0, "CreateBitmap failed\n");
1364 if(!hbmMask) goto cleanup;
1366 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1367 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1368 if(!hbmInverseMask) goto cleanup;
1370 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1371 ok(himl != 0, "ImageList_Create failed\n");
1372 if(!himl) goto cleanup;
1374 /* Add a no-alpha image */
1375 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1376 if(!hbmImage) goto cleanup;
1378 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1379 ok(iImage != -1, "ImageList_Add failed\n");
1380 if(iImage == -1) goto cleanup;
1382 /* Add an alpha image */
1383 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1384 if(!hbmAlphaImage) goto cleanup;
1386 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1387 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1388 if(iAlphaImage == -1) goto cleanup;
1390 /* Add a transparent alpha image */
1391 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1392 if(!hbmTransparentImage) goto cleanup;
1394 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1395 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1396 if(iTransparentImage == -1) goto cleanup;
1399 bitmapInfo.bmiHeader.biBitCount = 32;
1400 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1401 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1402 if (!hbmDst || !bits)
1404 hbmOld = SelectObject(hdcDst, hbmDst);
1406 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1407 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1408 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1409 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1410 else broken_value = 0x00B4BDC4;
1411 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1412 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1413 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1414 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1416 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1417 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1419 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1420 else broken_value = 0x009DA8B1;
1421 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1422 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1423 else broken_value = 0x008C99A3;
1424 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1425 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1426 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1427 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1429 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1431 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1432 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1434 /* ILD_ROP is ignored when the image has an alpha channel */
1435 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1436 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1438 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1439 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1441 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1442 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1444 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1445 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1446 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1451 SelectObject(hdcDst, hbmOld);
1453 DeleteObject(hbmDst);
1459 DeleteObject(hbmMask);
1461 DeleteObject(hbmInverseMask);
1464 DeleteObject(hbmImage);
1466 DeleteObject(hbmAlphaImage);
1467 if(hbmTransparentImage)
1468 DeleteObject(hbmTransparentImage);
1472 ret = ImageList_Destroy(himl);
1473 ok(ret, "ImageList_Destroy failed\n");
1477 static void test_iimagelist(void)
1479 IImageList *imgl, *imgl2;
1484 if (!pHIMAGELIST_QueryInterface)
1486 win_skip("XP imagelist functions not available\n");
1490 /* test reference counting on destruction */
1491 imgl = (IImageList*)createImageList(32, 32);
1492 ret = IImageList_AddRef(imgl);
1493 ok(ret == 2, "Expected 2, got %d\n", ret);
1494 ret = ImageList_Destroy((HIMAGELIST)imgl);
1495 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1496 ret = ImageList_Destroy((HIMAGELIST)imgl);
1497 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1498 ret = ImageList_Destroy((HIMAGELIST)imgl);
1499 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1501 imgl = (IImageList*)createImageList(32, 32);
1502 ret = IImageList_AddRef(imgl);
1503 ok(ret == 2, "Expected 2, got %d\n", ret);
1504 ret = ImageList_Destroy((HIMAGELIST)imgl);
1505 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1506 ret = IImageList_Release(imgl);
1507 ok(ret == 0, "Expected 0, got %d\n", ret);
1508 ret = ImageList_Destroy((HIMAGELIST)imgl);
1509 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1511 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1512 imgl = (IImageList*)createImageList(32, 32);
1513 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1514 ok(hr == S_OK, "got 0x%08x\n", hr);
1515 ok(imgl2 == imgl, "got different pointer\n");
1516 ret = IImageList_Release(imgl);
1517 ok(ret == 1, "got %u\n", ret);
1518 IImageList_Release(imgl);
1520 if (!pImageList_CoCreateInstance)
1522 win_skip("Vista imagelist functions not available\n");
1526 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1527 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1530 IImageList_Release(imgl);
1532 himl = createImageList(32, 32);
1537 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1538 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1541 IImageList_Release(imgl);
1543 ImageList_Destroy(himl);
1546 static void test_hotspot_v6(void)
1557 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1558 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1565 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1566 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1567 IImageList *imgl1, *imgl2;
1570 /* cast to IImageList */
1571 imgl1 = (IImageList *) himl1;
1572 imgl2 = (IImageList *) himl2;
1574 for (i = 0; i < HOTSPOTS_MAX; i++) {
1575 for (j = 0; j < HOTSPOTS_MAX; j++) {
1576 int dx1 = hotspots[i].dx;
1577 int dy1 = hotspots[i].dy;
1578 int dx2 = hotspots[j].dx;
1579 int dy2 = hotspots[j].dy;
1580 int correctx, correcty, newx, newy;
1582 IImageList *imglNew;
1585 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1586 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1587 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1589 /* check merging the dragged image with a second image */
1590 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1591 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1592 dx1, dy1, dx2, dy2);
1593 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1595 /* check new hotspot, it should be the same like the old one */
1596 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1597 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1598 ok(ppt.x == dx1 && ppt.y == dy1,
1599 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1600 dx1, dy1, ppt.x, ppt.y);
1601 /* check size of new dragged image */
1602 IImageList_GetIconSize(imglNew, &newx, &newy);
1603 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1604 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1605 ok(newx == correctx && newy == correcty,
1606 "Expected drag image size [%d,%d] got [%d,%d]\n",
1607 correctx, correcty, newx, newy);
1608 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1609 IImageList_EndDrag(imgl2);
1617 IImageList_Release(imgl2);
1618 IImageList_Release(imgl1);
1621 static void test_IImageList_Add_Remove(void)
1633 /* create an imagelist to play with */
1634 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1635 ok(himl != 0,"failed to create imagelist\n");
1637 imgl = (IImageList *) himl;
1639 /* load the icons to add to the image list */
1640 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1641 ok(hicon1 != 0, "no hicon1\n");
1642 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1643 ok(hicon2 != 0, "no hicon2\n");
1644 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1645 ok(hicon3 != 0, "no hicon3\n");
1647 /* remove when nothing exists */
1648 hr = IImageList_Remove(imgl, 0);
1649 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1651 /* removing everything from an empty imagelist should succeed */
1652 hr = IImageList_Remove(imgl, -1);
1653 ok(hr == S_OK, "removed nonexistent icon\n");
1657 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1659 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1661 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1663 /* remove an index out of range */
1664 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1667 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1668 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1669 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1671 /* remove one extra */
1672 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1674 IImageList_Release(imgl);
1675 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1676 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1677 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1680 static void test_IImageList_Get_SetImageCount(void)
1687 /* create an imagelist to play with */
1688 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1689 ok(himl != 0,"failed to create imagelist\n");
1691 imgl = (IImageList *) himl;
1693 /* check SetImageCount/GetImageCount */
1694 hr = IImageList_SetImageCount(imgl, 3);
1695 ok(hr == S_OK, "got 0x%08x\n", hr);
1697 hr = IImageList_GetImageCount(imgl, &ret);
1698 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1699 hr = IImageList_SetImageCount(imgl, 1);
1700 ok(hr == S_OK, "got 0x%08x\n", hr);
1702 hr = IImageList_GetImageCount(imgl, &ret);
1703 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1704 hr = IImageList_SetImageCount(imgl, 0);
1705 ok(hr == S_OK, "got 0x%08x\n", hr);
1707 hr = IImageList_GetImageCount(imgl, &ret);
1708 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1710 IImageList_Release(imgl);
1713 static void test_IImageList_Draw(void)
1722 IMAGELISTDRAWPARAMS imldp;
1728 hwndfortest = create_a_window();
1729 hdc = GetDC(hwndfortest);
1730 ok(hdc!=NULL, "couldn't get DC\n");
1732 /* create an imagelist to play with */
1733 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1734 ok(himl!=0,"failed to create imagelist\n");
1736 imgl = (IImageList *) himl;
1738 /* load the icons to add to the image list */
1739 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1740 ok(hbm1 != 0, "no bitmap 1\n");
1741 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1742 ok(hbm2 != 0, "no bitmap 2\n");
1743 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1744 ok(hbm3 != 0, "no bitmap 3\n");
1748 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1750 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1752 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1753 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1757 /* crashes on native */
1758 IImageList_Draw(imgl, NULL);
1761 memset(&imldp, 0, sizeof (imldp));
1762 hr = IImageList_Draw(imgl, &imldp);
1763 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1765 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1769 REDRAW(hwndfortest);
1772 imldp.fStyle = SRCCOPY;
1773 imldp.rgbBk = CLR_DEFAULT;
1774 imldp.rgbFg = CLR_DEFAULT;
1777 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1779 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1781 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1783 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1786 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1787 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1788 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1791 IImageList_Release(imgl);
1793 /* bitmaps should not be deleted by the imagelist */
1794 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1795 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1796 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1798 ReleaseDC(hwndfortest, hdc);
1799 DestroyWindow(hwndfortest);
1802 static void test_IImageList_Merge(void)
1804 HIMAGELIST himl1, himl2;
1805 IImageList *imgl1, *imgl2, *merge;
1807 HWND hwnd = create_a_window();
1811 himl1 = ImageList_Create(32,32,0,0,3);
1812 ok(himl1 != NULL,"failed to create himl1\n");
1814 himl2 = ImageList_Create(32,32,0,0,3);
1815 ok(himl2 != NULL,"failed to create himl2\n");
1817 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1818 ok(hicon1 != NULL, "failed to create hicon1\n");
1820 if (!himl1 || !himl2 || !hicon1)
1823 /* cast to IImageList */
1824 imgl1 = (IImageList *) himl1;
1825 imgl2 = (IImageList *) himl2;
1828 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1832 /* null cases that crash on native */
1833 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1834 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1837 /* If himl1 has no images, merge still succeeds */
1838 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1839 ok(hr == S_OK, "merge himl1,-1 failed\n");
1840 if (hr == S_OK) IImageList_Release(merge);
1842 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1843 ok(hr == S_OK, "merge himl1,0 failed\n");
1844 if (hr == S_OK) IImageList_Release(merge);
1846 /* Same happens if himl2 is empty */
1847 IImageList_Release(imgl2);
1848 himl2 = ImageList_Create(32,32,0,0,3);
1849 ok(himl2 != NULL,"failed to recreate himl2\n");
1851 imgl2 = (IImageList *) himl2;
1853 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1854 ok(hr == S_OK, "merge himl2,-1 failed\n");
1855 if (hr == S_OK) IImageList_Release(merge);
1857 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1858 ok(hr == S_OK, "merge himl2,0 failed\n");
1859 if (hr == S_OK) IImageList_Release(merge);
1861 /* Now try merging an image with itself */
1863 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1865 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1866 ok(hr == S_OK, "merge himl2 with itself failed\n");
1867 if (hr == S_OK) IImageList_Release(merge);
1869 /* Try merging 2 different image lists */
1871 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1873 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1874 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1875 if (hr == S_OK) IImageList_Release(merge);
1877 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1878 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1879 if (hr == S_OK) IImageList_Release(merge);
1881 IImageList_Release(imgl1);
1882 IImageList_Release(imgl2);
1884 DestroyIcon(hicon1);
1885 DestroyWindow(hwnd);
1888 static void test_iconsize(void)
1894 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1895 /* null pointers, not zero imagelist dimensions */
1896 ret = ImageList_GetIconSize(himl, NULL, NULL);
1897 ok(!ret, "got %d\n", ret);
1899 /* doesn't touch return pointers */
1901 ret = ImageList_GetIconSize(himl, &cx, NULL);
1902 ok(!ret, "got %d\n", ret);
1903 ok(cx == 0x1abe11ed, "got %d\n", cx);
1906 ret = ImageList_GetIconSize(himl, NULL, &cy);
1907 ok(!ret, "got %d\n", ret);
1908 ok(cy == 0x1abe11ed, "got %d\n", cy);
1910 ImageList_Destroy(himl);
1912 ret = ImageList_GetIconSize((HIMAGELIST)0xdeadbeef, &cx, &cy);
1913 ok(!ret, "got %d\n", ret);
1916 static void test_create_destroy(void)
1921 /* list with zero or negative image dimensions */
1922 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1923 ok(himl == NULL, "got %p\n", himl);
1925 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1926 ok(himl == NULL, "got %p\n", himl);
1928 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1929 ok(himl == NULL, "got %p\n", himl);
1931 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1932 ok(himl == NULL, "got %p\n", himl);
1934 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1935 ok(himl == NULL, "got %p\n", himl);
1937 rc = ImageList_Destroy((HIMAGELIST)0xdeadbeef);
1938 ok(rc == FALSE, "ImageList_Destroy(0xdeadbeef) should fail and not crash\n");
1941 static void test_IImageList_Clone(void)
1943 IImageList *imgl, *imgl2;
1948 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1949 imgl = (IImageList*)himl;
1953 /* crashes on native */
1954 IImageList_Clone(imgl, &IID_IImageList, NULL);
1957 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1958 ok(hr == S_OK, "got 0x%08x\n", hr);
1959 ref = IImageList_Release(imgl2);
1960 ok(ref == 0, "got %u\n", ref);
1962 IImageList_Release(imgl);
1965 static void test_IImageList_GetBkColor(void)
1972 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1973 imgl = (IImageList*)himl;
1977 /* crashes on native */
1978 IImageList_GetBkColor(imgl, NULL);
1981 hr = IImageList_GetBkColor(imgl, &color);
1982 ok(hr == S_OK, "got 0x%08x\n", hr);
1984 IImageList_Release(imgl);
1987 static void test_IImageList_SetBkColor(void)
1994 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1995 imgl = (IImageList*)himl;
1999 /* crashes on native */
2000 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
2003 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2004 ok(hr == S_OK, "got 0x%08x\n", hr);
2006 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
2007 ok(hr == S_OK, "got 0x%08x\n", hr);
2010 hr = IImageList_GetBkColor(imgl, &color);
2011 ok(hr == S_OK, "got 0x%08x\n", hr);
2012 ok(color == CLR_NONE, "got %x\n", color);
2014 IImageList_Release(imgl);
2017 static void test_IImageList_GetImageCount(void)
2024 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2025 imgl = (IImageList*)himl;
2029 /* crashes on native */
2030 IImageList_GetImageCount(imgl, NULL);
2034 hr = IImageList_GetImageCount(imgl, &count);
2035 ok(hr == S_OK, "got 0x%08x\n", hr);
2036 ok(count == 0, "got %d\n", count);
2038 IImageList_Release(imgl);
2041 static void test_IImageList_GetIconSize(void)
2048 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
2049 imgl = (IImageList*)himl;
2051 hr = IImageList_GetIconSize(imgl, NULL, NULL);
2052 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2054 hr = IImageList_GetIconSize(imgl, &cx, NULL);
2055 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2057 hr = IImageList_GetIconSize(imgl, NULL, &cy);
2058 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2060 IImageList_Release(imgl);
2063 START_TEST(imagelist)
2065 ULONG_PTR ctx_cookie;
2068 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
2069 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
2070 pImageList_Add = NULL;
2071 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
2072 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
2074 hinst = GetModuleHandleA(NULL);
2076 InitCommonControls();
2078 test_create_destroy();
2082 test_DrawIndirect();
2084 test_merge_colors();
2085 test_imagelist_storage();
2088 FreeLibrary(hComCtl32);
2090 /* Now perform v6 tests */
2092 if (!load_v6_module(&ctx_cookie, &hCtx))
2095 /* Reload comctl32 */
2096 hComCtl32 = LoadLibraryA("comctl32.dll");
2097 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
2098 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
2099 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
2100 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
2101 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
2102 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
2104 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2107 test_ImageList_DrawIndirect();
2108 test_shell_imagelist();
2112 test_IImageList_Add_Remove();
2113 test_IImageList_Get_SetImageCount();
2114 test_IImageList_Draw();
2115 test_IImageList_Merge();
2116 test_IImageList_Clone();
2117 test_IImageList_GetBkColor();
2118 test_IImageList_SetBkColor();
2119 test_IImageList_GetImageCount();
2120 test_IImageList_GetIconSize();
2124 unload_v6_module(ctx_cookie, hCtx);