wininet: Support the Cache-Control max-age directive for setting url cache entry...
[wine/testsucceed.git] / dlls / comctl32 / tests / imagelist.c
blobcc98a17651f2da8957ebc25cbed9031f5e56cb2c
1 /*
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
24 #define COBJMACROS
25 #define CONST_VTABLE
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <assert.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "objbase.h"
36 #include "commctrl.h" /* must be included after objbase.h to get ImageList_Write */
37 #include "initguid.h"
38 #include "commoncontrols.h"
39 #include "shellapi.h"
41 #include "wine/test.h"
42 #include "v6util.h"
44 #undef VISIBLE
46 #ifdef VISIBLE
47 #define WAIT Sleep (1000)
48 #define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW)
49 #else
50 #define WAIT
51 #define REDRAW(hwnd)
52 #endif
54 #define IMAGELIST_MAGIC (('L' << 8) | 'I')
56 #include "pshpack2.h"
57 /* Header used by ImageList_Read() and ImageList_Write() */
58 typedef struct _ILHEAD
60 USHORT usMagic;
61 USHORT usVersion;
62 WORD cCurImage;
63 WORD cMaxImage;
64 WORD cGrow;
65 WORD cx;
66 WORD cy;
67 COLORREF bkcolor;
68 WORD flags;
69 SHORT ovls[4];
70 } ILHEAD;
71 #include "poppack.h"
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 *,
78 REFIID,void **);
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);
129 DeleteObject(hbm);
130 return himl;
133 static HWND create_a_window(void)
135 char className[] = "bmwnd";
136 char winName[] = "Test Bitmap";
137 HWND hWnd;
138 static int registered = 0;
140 if (!registered)
142 WNDCLASSA cls;
144 cls.style = CS_HREDRAW | CS_VREDRAW | CS_GLOBALCLASS;
145 cls.lpfnWndProc = DefWindowProcA;
146 cls.cbClsExtra = 0;
147 cls.cbWndExtra = 0;
148 cls.hInstance = 0;
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);
156 registered = 1;
159 /* Setup window */
160 hWnd = CreateWindowA (className, winName,
161 WS_OVERLAPPEDWINDOW ,
162 CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, 0,
163 0, hinst, 0);
165 #ifdef VISIBLE
166 ShowWindow (hWnd, SW_SHOW);
167 #endif
168 REDRAW(hWnd);
169 WAIT;
171 return hWnd;
174 static HDC show_image(HWND hwnd, HIMAGELIST himl, int idx, int size,
175 LPCSTR loc, BOOL clear)
177 HDC hdc = NULL;
178 #ifdef VISIBLE
179 if (!himl) return NULL;
181 SetWindowText(hwnd, loc);
182 hdc = GetDC(hwnd);
183 ImageList_Draw(himl, idx, hdc, 0, 0, ILD_TRANSPARENT);
185 REDRAW(hwnd);
186 WAIT;
188 if (clear)
190 BitBlt(hdc, 0, 0, size, size, hdc, size+1, size+1, SRCCOPY);
191 ReleaseDC(hwnd, hdc);
192 hdc = NULL;
194 #endif /* VISIBLE */
195 return hdc;
198 /* Useful for checking differences */
199 #if 0
200 static void dump_bits(const BYTE *p, const BYTE *q, int size)
202 int i, j;
204 size /= 8;
206 for (i = 0; i < size * 2; i++)
208 printf("|");
209 for (j = 0; j < size; j++)
210 printf("%c%c", p[j] & 0xf0 ? 'X' : ' ', p[j] & 0xf ? 'X' : ' ');
211 printf(" -- ");
212 for (j = 0; j < size; j++)
213 printf("%c%c", q[j] & 0xf0 ? 'X' : ' ', q[j] & 0xf ? 'X' : ' ');
214 printf("|\n");
215 p += size * 4;
216 q += size * 4;
218 printf("\n");
220 #endif
222 static void check_bits(HWND hwnd, HIMAGELIST himl, int idx, int size,
223 const BYTE *checkbits, LPCSTR loc)
225 #ifdef VISIBLE
226 BYTE bits[100*100/8];
227 COLORREF c;
228 HDC hdc;
229 int x, y, i = -1;
231 if (!himl) return;
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++)
242 if (!(x & 0x7)) i++;
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);
254 #endif /* VISIBLE */
257 static void test_hotspot(void)
259 struct hotspot {
260 int dx;
261 int dy;
264 #define SIZEX1 47
265 #define SIZEY1 31
266 #define SIZEX2 11
267 #define SIZEY2 17
268 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
269 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
270 { 10, 7 },
271 { SIZEX1, SIZEY1 },
272 { -9, -8 },
273 { -7, 35 }
275 int i, j, ret;
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;
288 char loc[256];
289 HIMAGELIST himlNew;
290 POINT ppt;
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",
300 dx1, dy1, dx2, dy2);
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);
318 ImageList_EndDrag();
321 #undef SIZEX1
322 #undef SIZEY1
323 #undef SIZEX2
324 #undef SIZEY2
325 #undef HOTSPOTS_MAX
326 ImageList_Destroy(himl2);
327 ImageList_Destroy(himl1);
328 DestroyWindow(hwnd);
331 static void test_add_remove(void)
333 HIMAGELIST himl ;
335 HICON hicon1 ;
336 HICON hicon2 ;
337 HICON hicon3 ;
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");
356 /* add three */
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");
364 /* remove three */
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");
372 /* destroy it */
373 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
375 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
376 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
377 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
380 static void test_imagecount(void)
382 HIMAGELIST himl;
384 if (!pImageList_SetImageCount)
386 win_skip("ImageList_SetImageCount not available\n");
387 return;
390 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
391 ok(himl!=0,"failed to create imagelist\n");
393 ok(pImageList_SetImageCount(himl, 3), "couldn't increase image count\n");
394 ok(ImageList_GetImageCount(himl) == 3, "invalid image count after increase\n");
395 ok(pImageList_SetImageCount(himl, 1), "couldn't decrease image count\n");
396 ok(ImageList_GetImageCount(himl) == 1, "invalid image count after decrease to 1\n");
397 ok(pImageList_SetImageCount(himl, 0), "couldn't decrease image count\n");
398 ok(ImageList_GetImageCount(himl) == 0, "invalid image count after decrease to 0\n");
400 ok(ImageList_Destroy(himl), "destroy imagelist failed\n");
403 static void test_DrawIndirect(void)
405 HIMAGELIST himl;
407 HBITMAP hbm1;
408 HBITMAP hbm2;
409 HBITMAP hbm3;
411 IMAGELISTDRAWPARAMS imldp;
412 HDC hdc;
413 HWND hwndfortest;
415 if (!pImageList_DrawIndirect)
417 win_skip("ImageList_DrawIndirect not available, skipping test\n");
418 return;
421 hwndfortest = create_a_window();
422 hdc = GetDC(hwndfortest);
423 ok(hdc!=NULL, "couldn't get DC\n");
425 /* create an imagelist to play with */
426 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
427 ok(himl!=0,"failed to create imagelist\n");
429 /* load the icons to add to the image list */
430 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
431 ok(hbm1 != 0, "no bitmap 1\n");
432 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
433 ok(hbm2 != 0, "no bitmap 2\n");
434 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
435 ok(hbm3 != 0, "no bitmap 3\n");
437 /* add three */
438 ok(0==ImageList_Add(himl, hbm1, 0),"failed to add bitmap 1\n");
439 ok(1==ImageList_Add(himl, hbm2, 0),"failed to add bitmap 2\n");
441 if (pImageList_SetImageCount)
443 ok(pImageList_SetImageCount(himl,3),"Setimage count failed\n");
444 /*ok(2==ImageList_Add(himl, hbm3, NULL),"failed to add bitmap 3\n"); */
445 ok(ImageList_Replace(himl, 2, hbm3, 0),"failed to replace bitmap 3\n");
448 memset(&imldp, 0, sizeof (imldp));
449 ok(!pImageList_DrawIndirect(&imldp), "zero data succeeded!\n");
450 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
451 ok(!pImageList_DrawIndirect(&imldp), "zero hdc succeeded!\n");
452 imldp.hdcDst = hdc;
453 ok(!pImageList_DrawIndirect(&imldp),"zero himl succeeded!\n");
454 imldp.himl = himl;
456 REDRAW(hwndfortest);
457 WAIT;
459 imldp.fStyle = SRCCOPY;
460 imldp.rgbBk = CLR_DEFAULT;
461 imldp.rgbFg = CLR_DEFAULT;
462 imldp.y = 100;
463 imldp.x = 100;
464 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
465 imldp.i ++;
466 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
467 imldp.i ++;
468 ok(pImageList_DrawIndirect(&imldp),"should succeed\n");
469 imldp.i ++;
470 ok(!pImageList_DrawIndirect(&imldp),"should fail\n");
472 /* remove three */
473 ok(ImageList_Remove(himl, 0), "removing 1st bitmap\n");
474 ok(ImageList_Remove(himl, 0), "removing 2nd bitmap\n");
475 ok(ImageList_Remove(himl, 0), "removing 3rd bitmap\n");
477 /* destroy it */
478 ok(ImageList_Destroy(himl),"destroy imagelist failed\n");
480 /* bitmaps should not be deleted by the imagelist */
481 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
482 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
483 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
485 ReleaseDC(hwndfortest, hdc);
486 DestroyWindow(hwndfortest);
489 static void test_merge(void)
491 HIMAGELIST himl1, himl2, hmerge;
492 HICON hicon1;
493 HWND hwnd = create_a_window();
495 himl1 = ImageList_Create(32,32,0,0,3);
496 ok(himl1 != NULL,"failed to create himl1\n");
498 himl2 = ImageList_Create(32,32,0,0,3);
499 ok(himl2 != NULL,"failed to create himl2\n");
501 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
502 ok(hicon1 != NULL, "failed to create hicon1\n");
504 if (!himl1 || !himl2 || !hicon1)
505 return;
507 ok(0==ImageList_AddIcon(himl2, hicon1),"add icon1 to himl2 failed\n");
508 check_bits(hwnd, himl2, 0, 32, icon_bits, "add icon1 to himl2");
510 /* If himl1 has no images, merge still succeeds */
511 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
512 ok(hmerge != NULL, "merge himl1,-1 failed\n");
513 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,-1");
514 if (hmerge) ImageList_Destroy(hmerge);
516 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
517 ok(hmerge != NULL,"merge himl1,0 failed\n");
518 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1,0");
519 if (hmerge) ImageList_Destroy(hmerge);
521 /* Same happens if himl2 is empty */
522 ImageList_Destroy(himl2);
523 himl2 = ImageList_Create(32,32,0,0,3);
524 ok(himl2 != NULL,"failed to recreate himl2\n");
525 if (!himl2)
526 return;
528 hmerge = ImageList_Merge(himl1, -1, himl2, -1, 0, 0);
529 ok(hmerge != NULL, "merge himl2,-1 failed\n");
530 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,-1");
531 if (hmerge) ImageList_Destroy(hmerge);
533 hmerge = ImageList_Merge(himl1, -1, himl2, 0, 0, 0);
534 ok(hmerge != NULL, "merge himl2,0 failed\n");
535 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2,0");
536 if (hmerge) ImageList_Destroy(hmerge);
538 /* Now try merging an image with itself */
539 ok(0==ImageList_AddIcon(himl2, hicon1),"re-add icon1 to himl2 failed\n");
541 hmerge = ImageList_Merge(himl2, 0, himl2, 0, 0, 0);
542 ok(hmerge != NULL, "merge himl2 with itself failed\n");
543 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl2 with itself");
544 if (hmerge) ImageList_Destroy(hmerge);
546 /* Try merging 2 different image lists */
547 ok(0==ImageList_AddIcon(himl1, hicon1),"add icon1 to himl1 failed\n");
549 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 0, 0);
550 ok(hmerge != NULL, "merge himl1 with himl2 failed\n");
551 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2");
552 if (hmerge) ImageList_Destroy(hmerge);
554 hmerge = ImageList_Merge(himl1, 0, himl2, 0, 8, 16);
555 ok(hmerge != NULL, "merge himl1 with himl2 8,16 failed\n");
556 check_bits(hwnd, hmerge, 0, 32, empty_bits, "merge himl1 with himl2, 8,16");
557 if (hmerge) ImageList_Destroy(hmerge);
559 ImageList_Destroy(himl1);
560 ImageList_Destroy(himl2);
561 DestroyIcon(hicon1);
562 DestroyWindow(hwnd);
565 /*********************** imagelist storage test ***************************/
567 #define BMP_CX 48
569 struct my_IStream
571 IStream is;
572 char *iml_data; /* written imagelist data */
573 ULONG iml_data_size;
576 static HRESULT STDMETHODCALLTYPE Test_Stream_QueryInterface(
577 IStream* This,
578 REFIID riid,
579 void** ppvObject)
581 assert(0);
582 return E_NOTIMPL;
585 static ULONG STDMETHODCALLTYPE Test_Stream_AddRef(
586 IStream* This)
588 assert(0);
589 return 2;
592 static ULONG STDMETHODCALLTYPE Test_Stream_Release(
593 IStream* This)
595 assert(0);
596 return 1;
599 static HRESULT STDMETHODCALLTYPE Test_Stream_Read(
600 IStream* This,
601 void* pv,
602 ULONG cb,
603 ULONG* pcbRead)
605 assert(0);
606 return E_NOTIMPL;
609 static BOOL allocate_storage(struct my_IStream *my_is, ULONG add)
611 my_is->iml_data_size += add;
613 if (!my_is->iml_data)
614 my_is->iml_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data_size);
615 else
616 my_is->iml_data = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, my_is->iml_data, my_is->iml_data_size);
618 return my_is->iml_data ? TRUE : FALSE;
621 static HRESULT STDMETHODCALLTYPE Test_Stream_Write(
622 IStream* This,
623 const void* pv,
624 ULONG cb,
625 ULONG* pcbWritten)
627 struct my_IStream *my_is = (struct my_IStream *)This;
628 ULONG current_iml_data_size = my_is->iml_data_size;
630 if (!allocate_storage(my_is, cb)) return E_FAIL;
632 memcpy(my_is->iml_data + current_iml_data_size, pv, cb);
633 if (pcbWritten) *pcbWritten = cb;
635 return S_OK;
638 static HRESULT STDMETHODCALLTYPE Test_Stream_Seek(
639 IStream* This,
640 LARGE_INTEGER dlibMove,
641 DWORD dwOrigin,
642 ULARGE_INTEGER* plibNewPosition)
644 assert(0);
645 return E_NOTIMPL;
648 static HRESULT STDMETHODCALLTYPE Test_Stream_SetSize(
649 IStream* This,
650 ULARGE_INTEGER libNewSize)
652 assert(0);
653 return E_NOTIMPL;
656 static HRESULT STDMETHODCALLTYPE Test_Stream_CopyTo(
657 IStream* This,
658 IStream* pstm,
659 ULARGE_INTEGER cb,
660 ULARGE_INTEGER* pcbRead,
661 ULARGE_INTEGER* pcbWritten)
663 assert(0);
664 return E_NOTIMPL;
667 static HRESULT STDMETHODCALLTYPE Test_Stream_Commit(
668 IStream* This,
669 DWORD grfCommitFlags)
671 assert(0);
672 return E_NOTIMPL;
675 static HRESULT STDMETHODCALLTYPE Test_Stream_Revert(
676 IStream* This)
678 assert(0);
679 return E_NOTIMPL;
682 static HRESULT STDMETHODCALLTYPE Test_Stream_LockRegion(
683 IStream* This,
684 ULARGE_INTEGER libOffset,
685 ULARGE_INTEGER cb,
686 DWORD dwLockType)
688 assert(0);
689 return E_NOTIMPL;
692 static HRESULT STDMETHODCALLTYPE Test_Stream_UnlockRegion(
693 IStream* This,
694 ULARGE_INTEGER libOffset,
695 ULARGE_INTEGER cb,
696 DWORD dwLockType)
698 assert(0);
699 return E_NOTIMPL;
702 static HRESULT STDMETHODCALLTYPE Test_Stream_Stat(
703 IStream* This,
704 STATSTG* pstatstg,
705 DWORD grfStatFlag)
707 assert(0);
708 return E_NOTIMPL;
711 static HRESULT STDMETHODCALLTYPE Test_Stream_Clone(
712 IStream* This,
713 IStream** ppstm)
715 assert(0);
716 return E_NOTIMPL;
719 static const IStreamVtbl Test_Stream_Vtbl =
721 Test_Stream_QueryInterface,
722 Test_Stream_AddRef,
723 Test_Stream_Release,
724 Test_Stream_Read,
725 Test_Stream_Write,
726 Test_Stream_Seek,
727 Test_Stream_SetSize,
728 Test_Stream_CopyTo,
729 Test_Stream_Commit,
730 Test_Stream_Revert,
731 Test_Stream_LockRegion,
732 Test_Stream_UnlockRegion,
733 Test_Stream_Stat,
734 Test_Stream_Clone
737 static struct my_IStream Test_Stream = { { &Test_Stream_Vtbl }, 0, 0 };
739 static INT DIB_GetWidthBytes( int width, int bpp )
741 int words;
743 switch (bpp)
745 case 1: words = (width + 31) / 32; break;
746 case 4: words = (width + 7) / 8; break;
747 case 8: words = (width + 3) / 4; break;
748 case 15:
749 case 16: words = (width + 1) / 2; break;
750 case 24: words = (width * 3 + 3)/4; break;
751 case 32: words = width; break;
753 default:
754 trace("Unknown depth %d, please report.\n", bpp );
755 assert(0);
756 return -1;
758 return 4 * words;
761 static void check_bitmap_data(const char *bm_data, ULONG bm_data_size,
762 INT width, INT height, INT bpp,
763 const char *comment)
765 const BITMAPFILEHEADER *bmfh = (const BITMAPFILEHEADER *)bm_data;
766 const BITMAPINFOHEADER *bmih = (const BITMAPINFOHEADER *)(bm_data + sizeof(*bmfh));
767 ULONG hdr_size, image_size;
769 hdr_size = sizeof(*bmfh) + sizeof(*bmih);
770 if (bmih->biBitCount <= 8) hdr_size += (1 << bpp) * sizeof(RGBQUAD);
772 ok(bmfh->bfType == (('M' << 8) | 'B'), "wrong bfType 0x%02x\n", bmfh->bfType);
773 ok(bmfh->bfSize == hdr_size, "wrong bfSize 0x%02x\n", bmfh->bfSize);
774 ok(bmfh->bfReserved1 == 0, "wrong bfReserved1 0x%02x\n", bmfh->bfReserved1);
775 ok(bmfh->bfReserved2 == 0, "wrong bfReserved2 0x%02x\n", bmfh->bfReserved2);
776 ok(bmfh->bfOffBits == hdr_size, "wrong bfOffBits 0x%02x\n", bmfh->bfOffBits);
778 ok(bmih->biSize == sizeof(*bmih), "wrong biSize %d\n", bmih->biSize);
779 ok(bmih->biWidth == width, "wrong biWidth %d (expected %d)\n", bmih->biWidth, width);
780 ok(bmih->biHeight == height, "wrong biHeight %d (expected %d)\n", bmih->biHeight, height);
781 ok(bmih->biPlanes == 1, "wrong biPlanes %d\n", bmih->biPlanes);
782 ok(bmih->biBitCount == bpp, "wrong biBitCount %d\n", bmih->biBitCount);
784 image_size = DIB_GetWidthBytes(bmih->biWidth, bmih->biBitCount) * bmih->biHeight;
785 ok(bmih->biSizeImage == image_size, "wrong biSizeImage %u\n", bmih->biSizeImage);
786 #if 0
788 char fname[256];
789 FILE *f;
790 sprintf(fname, "bmp_%s.bmp", comment);
791 f = fopen(fname, "wb");
792 fwrite(bm_data, 1, bm_data_size, f);
793 fclose(f);
795 #endif
798 static void check_ilhead_data(const char *ilh_data, INT cx, INT cy, INT cur, INT max, INT grow)
800 const ILHEAD *ilh = (const ILHEAD *)ilh_data;
802 ok(ilh->usMagic == IMAGELIST_MAGIC, "wrong usMagic %4x (expected %02x)\n", ilh->usMagic, IMAGELIST_MAGIC);
803 ok(ilh->usVersion == 0x101, "wrong usVersion %x (expected 0x101)\n", ilh->usVersion);
804 ok(ilh->cCurImage == cur, "wrong cCurImage %d (expected %d)\n", ilh->cCurImage, cur);
805 ok(ilh->cMaxImage == max, "wrong cMaxImage %d (expected %d)\n", ilh->cMaxImage, max);
806 ok(ilh->cGrow == grow, "wrong cGrow %d (expected %d)\n", ilh->cGrow, grow);
807 ok(ilh->cx == cx, "wrong cx %d (expected %d)\n", ilh->cx, cx);
808 ok(ilh->cy == cy, "wrong cy %d (expected %d)\n", ilh->cy, cy);
809 ok(ilh->bkcolor == CLR_NONE, "wrong bkcolor %x\n", ilh->bkcolor);
810 ok(ilh->flags == ILC_COLOR24, "wrong flags %04x\n", ilh->flags);
811 ok(ilh->ovls[0] == -1 ||
812 ilh->ovls[0] == 0, /* win95 */
813 "wrong ovls[0] %04x\n", ilh->ovls[0]);
814 ok(ilh->ovls[1] == -1 ||
815 ilh->ovls[1] == 0, /* win95 */
816 "wrong ovls[1] %04x\n", ilh->ovls[1]);
817 ok(ilh->ovls[2] == -1 ||
818 ilh->ovls[2] == 0, /* win95 */
819 "wrong ovls[2] %04x\n", ilh->ovls[2]);
820 ok(ilh->ovls[3] == -1 ||
821 ilh->ovls[3] == 0, /* win95 */
822 "wrong ovls[3] %04x\n", ilh->ovls[3]);
825 static HBITMAP create_bitmap(INT cx, INT cy, COLORREF color, const char *comment)
827 HDC hdc;
828 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
829 BITMAPINFO *bmi = (BITMAPINFO *)bmibuf;
830 HBITMAP hbmp, hbmp_old;
831 HBRUSH hbrush;
832 RECT rc = { 0, 0, cx, cy };
834 hdc = CreateCompatibleDC(0);
836 memset(bmi, 0, sizeof(*bmi));
837 bmi->bmiHeader.biSize = sizeof(bmi->bmiHeader);
838 bmi->bmiHeader.biHeight = cx;
839 bmi->bmiHeader.biWidth = cy;
840 bmi->bmiHeader.biBitCount = 24;
841 bmi->bmiHeader.biPlanes = 1;
842 bmi->bmiHeader.biCompression = BI_RGB;
843 hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, NULL, 0);
845 hbmp_old = SelectObject(hdc, hbmp);
847 hbrush = CreateSolidBrush(color);
848 FillRect(hdc, &rc, hbrush);
849 DeleteObject(hbrush);
851 DrawText(hdc, comment, -1, &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
853 SelectObject(hdc, hbmp_old);
854 DeleteDC(hdc);
856 return hbmp;
859 #define iml_clear_stream_data() \
860 HeapFree(GetProcessHeap(), 0, Test_Stream.iml_data); \
861 Test_Stream.iml_data = NULL; \
862 Test_Stream.iml_data_size = 0;
864 static void check_iml_data(HIMAGELIST himl, INT cx, INT cy, INT cur, INT max, INT grow,
865 INT width, INT height, INT bpp, const char *comment)
867 INT ret, cxx, cyy;
869 trace("%s\n", comment);
871 ret = ImageList_GetImageCount(himl);
872 ok(ret == cur, "expected image count %d got %d\n", cur, ret);
874 ret = ImageList_GetIconSize(himl, &cxx, &cyy);
875 ok(ret, "ImageList_GetIconSize failed\n");
876 ok(cxx == cx, "wrong cx %d (expected %d)\n", cxx, cx);
877 ok(cyy == cy, "wrong cy %d (expected %d)\n", cyy, cy);
879 iml_clear_stream_data();
880 ret = ImageList_Write(himl, &Test_Stream.is);
881 ok(ret, "ImageList_Write failed\n");
883 ok(Test_Stream.iml_data != 0, "ImageList_Write didn't write any data\n");
884 ok(Test_Stream.iml_data_size > sizeof(ILHEAD), "ImageList_Write wrote not enough data\n");
886 check_ilhead_data(Test_Stream.iml_data, cx, cy, cur, max, grow);
887 check_bitmap_data(Test_Stream.iml_data + sizeof(ILHEAD),
888 Test_Stream.iml_data_size - sizeof(ILHEAD),
889 width, height, bpp, comment);
892 static void image_list_init(HIMAGELIST himl)
894 HBITMAP hbm;
895 char comment[16];
896 INT n = 1, i;
897 static const struct test_data
899 BYTE grey;
900 INT cx, cy, cur, max, grow, width, height, bpp;
901 const char *comment;
902 } td[] =
904 { 255, BMP_CX, BMP_CX, 1, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 1" },
905 { 170, BMP_CX, BMP_CX, 2, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 2" },
906 { 85, BMP_CX, BMP_CX, 3, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 3" },
907 { 0, BMP_CX, BMP_CX, 4, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 4" },
908 { 0, BMP_CX, BMP_CX, 5, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 5" },
909 { 85, BMP_CX, BMP_CX, 6, 7, 4, BMP_CX * 4, BMP_CX * 2, 24, "total 6" },
910 { 170, BMP_CX, BMP_CX, 7, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 7" },
911 { 255, BMP_CX, BMP_CX, 8, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 8" },
912 { 255, BMP_CX, BMP_CX, 9, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 9" },
913 { 170, BMP_CX, BMP_CX, 10, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 10" },
914 { 85, BMP_CX, BMP_CX, 11, 12, 4, BMP_CX * 4, BMP_CX * 3, 24, "total 11" },
915 { 0, BMP_CX, BMP_CX, 12, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 12" },
916 { 0, BMP_CX, BMP_CX, 13, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 13" },
917 { 85, BMP_CX, BMP_CX, 14, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 14" },
918 { 170, BMP_CX, BMP_CX, 15, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 15" },
919 { 255, BMP_CX, BMP_CX, 16, 17, 4, BMP_CX * 4, BMP_CX * 5, 24, "total 16" },
920 { 255, BMP_CX, BMP_CX, 17, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 17" },
921 { 170, BMP_CX, BMP_CX, 18, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 18" },
922 { 85, BMP_CX, BMP_CX, 19, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 19" },
923 { 0, BMP_CX, BMP_CX, 20, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 20" },
924 { 0, BMP_CX, BMP_CX, 21, 22, 4, BMP_CX * 4, BMP_CX * 6, 24, "total 21" },
925 { 85, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 22" },
926 { 170, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 23" },
927 { 255, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "total 24" }
930 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "total 0");
932 #define add_bitmap(grey) \
933 sprintf(comment, "%d", n++); \
934 hbm = create_bitmap(BMP_CX, BMP_CX, RGB((grey),(grey),(grey)), comment); \
935 ImageList_Add(himl, hbm, NULL); \
936 DeleteObject(hbm);
938 for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
940 add_bitmap(td[i].grey);
941 check_iml_data(himl, td[i].cx, td[i].cy, td[i].cur, td[i].max, td[i].grow,
942 td[i].width, td[i].height, td[i].bpp, td[i].comment);
944 #undef add_bitmap
947 static void test_imagelist_storage(void)
949 HIMAGELIST himl;
950 HBITMAP hbm;
951 INT ret;
953 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 1, 1);
954 ok(himl != 0, "ImageList_Create failed\n");
956 check_iml_data(himl, BMP_CX, BMP_CX, 0, 2, 4, BMP_CX * 4, BMP_CX * 1, 24, "empty");
958 image_list_init(himl);
959 check_iml_data(himl, BMP_CX, BMP_CX, 24, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "orig");
961 ret = ImageList_Remove(himl, 4);
962 ok(ret, "ImageList_Remove failed\n");
963 check_iml_data(himl, BMP_CX, BMP_CX, 23, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "1");
965 ret = ImageList_Remove(himl, 5);
966 ok(ret, "ImageList_Remove failed\n");
967 check_iml_data(himl, BMP_CX, BMP_CX, 22, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "2");
969 ret = ImageList_Remove(himl, 6);
970 ok(ret, "ImageList_Remove failed\n");
971 check_iml_data(himl, BMP_CX, BMP_CX, 21, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "3");
973 ret = ImageList_Remove(himl, 7);
974 ok(ret, "ImageList_Remove failed\n");
975 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "4");
977 ret = ImageList_Remove(himl, -2);
978 ok(!ret, "ImageList_Remove(-2) should fail\n");
979 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "5");
981 ret = ImageList_Remove(himl, 20);
982 ok(!ret, "ImageList_Remove(20) should fail\n");
983 check_iml_data(himl, BMP_CX, BMP_CX, 20, 27, 4, BMP_CX * 4, BMP_CX * 7, 24, "6");
985 ret = ImageList_Remove(himl, -1);
986 ok(ret, "ImageList_Remove(-1) failed\n");
987 check_iml_data(himl, BMP_CX, BMP_CX, 0, 4, 4, BMP_CX * 4, BMP_CX * 1, 24, "7");
989 ret = ImageList_Destroy(himl);
990 ok(ret, "ImageList_Destroy failed\n");
992 iml_clear_stream_data();
994 /* test ImageList_Create storage allocation */
996 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 0, 32);
997 ok(himl != 0, "ImageList_Create failed\n");
998 check_iml_data(himl, BMP_CX, BMP_CX, 0, 1, 32, BMP_CX * 4, BMP_CX * 1, 24, "init 0 grow 32");
999 hbm = create_bitmap(BMP_CX * 9, BMP_CX, 0, "9");
1000 ret = ImageList_Add(himl, hbm, NULL);
1001 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1002 check_iml_data(himl, BMP_CX, BMP_CX, 1, 34, 32, BMP_CX * 4, BMP_CX * 9, 24, "add 1 x 9");
1003 DeleteObject(hbm);
1004 ret = ImageList_Destroy(himl);
1005 ok(ret, "ImageList_Destroy failed\n");
1006 iml_clear_stream_data();
1008 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 4);
1009 ok(himl != 0, "ImageList_Create failed\n");
1010 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 4");
1011 hbm = create_bitmap(BMP_CX, BMP_CX * 9, 0, "9");
1012 ret = ImageList_Add(himl, hbm, NULL);
1013 ok(ret == 0, "ImageList_Add returned %d, expected 0\n", ret);
1014 check_iml_data(himl, BMP_CX, BMP_CX, 9, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "add 9 x 1");
1015 ret = ImageList_Add(himl, hbm, NULL);
1016 ok(ret == 9, "ImageList_Add returned %d, expected 9\n", ret);
1017 check_iml_data(himl, BMP_CX, BMP_CX, 18, 25, 4, BMP_CX * 4, BMP_CX * 7, 24, "add 9 x 1");
1018 DeleteObject(hbm);
1019 ret = ImageList_Destroy(himl);
1020 ok(ret, "ImageList_Destroy failed\n");
1021 iml_clear_stream_data();
1023 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 207, 209);
1024 ok(himl != 0, "ImageList_Create failed\n");
1025 check_iml_data(himl, BMP_CX, BMP_CX, 0, 208, 212, BMP_CX * 4, BMP_CX * 52, 24, "init 207 grow 209");
1026 ret = ImageList_Destroy(himl);
1027 ok(ret, "ImageList_Destroy failed\n");
1028 iml_clear_stream_data();
1030 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 209, 207);
1031 ok(himl != 0, "ImageList_Create failed\n");
1032 check_iml_data(himl, BMP_CX, BMP_CX, 0, 210, 208, BMP_CX * 4, BMP_CX * 53, 24, "init 209 grow 207");
1033 ret = ImageList_Destroy(himl);
1034 ok(ret, "ImageList_Destroy failed\n");
1035 iml_clear_stream_data();
1037 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 14, 4);
1038 ok(himl != 0, "ImageList_Create failed\n");
1039 check_iml_data(himl, BMP_CX, BMP_CX, 0, 15, 4, BMP_CX * 4, BMP_CX * 4, 24, "init 14 grow 4");
1040 ret = ImageList_Destroy(himl);
1041 ok(ret, "ImageList_Destroy failed\n");
1042 iml_clear_stream_data();
1044 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 5, 9);
1045 ok(himl != 0, "ImageList_Create failed\n");
1046 check_iml_data(himl, BMP_CX, BMP_CX, 0, 6, 12, BMP_CX * 4, BMP_CX * 2, 24, "init 5 grow 9");
1047 ret = ImageList_Destroy(himl);
1048 ok(ret, "ImageList_Destroy failed\n");
1049 iml_clear_stream_data();
1051 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 9, 5);
1052 ok(himl != 0, "ImageList_Create failed\n");
1053 check_iml_data(himl, BMP_CX, BMP_CX, 0, 10, 8, BMP_CX * 4, BMP_CX * 3, 24, "init 9 grow 5");
1054 ret = ImageList_Destroy(himl);
1055 ok(ret, "ImageList_Destroy failed\n");
1056 iml_clear_stream_data();
1058 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 2, 4);
1059 ok(himl != 0, "ImageList_Create failed\n");
1060 check_iml_data(himl, BMP_CX, BMP_CX, 0, 3, 4, BMP_CX * 4, BMP_CX * 1, 24, "init 2 grow 4");
1061 ret = ImageList_Destroy(himl);
1062 ok(ret, "ImageList_Destroy failed\n");
1063 iml_clear_stream_data();
1065 himl = ImageList_Create(BMP_CX, BMP_CX, ILC_COLOR24, 4, 2);
1066 ok(himl != 0, "ImageList_Create failed\n");
1067 check_iml_data(himl, BMP_CX, BMP_CX, 0, 5, 4, BMP_CX * 4, BMP_CX * 2, 24, "init 4 grow 2");
1068 ret = ImageList_Destroy(himl);
1069 ok(ret, "ImageList_Destroy failed\n");
1070 iml_clear_stream_data();
1073 static void test_shell_imagelist(void)
1075 BOOL (WINAPI *pSHGetImageList)(INT, REFIID, void**);
1076 IImageList *iml = NULL;
1077 HMODULE hShell32;
1078 HRESULT hr;
1079 int out = 0;
1080 RECT rect;
1081 int cx, cy;
1083 /* Try to load function from shell32 */
1084 hShell32 = LoadLibrary("shell32.dll");
1085 pSHGetImageList = (void*)GetProcAddress(hShell32, (LPCSTR) 727);
1087 if (!pSHGetImageList)
1089 win_skip("SHGetImageList not available, skipping test\n");
1090 return;
1093 /* Get system image list */
1094 hr = (pSHGetImageList)(SHIL_SYSSMALL, &IID_IImageList, (void**)&iml);
1096 ok(SUCCEEDED(hr), "SHGetImageList failed, hr=%x\n", hr);
1098 if (hr != S_OK)
1099 return;
1101 IImageList_GetImageCount(iml, &out);
1102 ok(out > 0, "IImageList_GetImageCount returned out <= 0\n");
1104 /* Fetch the small icon size */
1105 cx = GetSystemMetrics(SM_CXSMICON);
1106 cy = GetSystemMetrics(SM_CYSMICON);
1108 /* Check icon size matches */
1109 IImageList_GetImageRect(iml, 0, &rect);
1110 ok(((rect.right == cx) && (rect.bottom == cy)),
1111 "IImageList_GetImageRect returned r:%d,b:%d\n",
1112 rect.right, rect.bottom);
1114 IImageList_Release(iml);
1115 FreeLibrary(hShell32);
1118 static HBITMAP create_test_bitmap(HDC hdc, int bpp, UINT32 pixel1, UINT32 pixel2)
1120 HBITMAP hBitmap;
1121 UINT32 *buffer = NULL;
1122 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, bpp, BI_RGB,
1123 0, 0, 0, 0, 0}};
1125 hBitmap = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, (void**)&buffer, NULL, 0);
1126 ok(hBitmap != NULL && buffer != NULL, "CreateDIBSection failed.\n");
1128 if(!hBitmap || !buffer)
1130 DeleteObject(hBitmap);
1131 return NULL;
1134 buffer[0] = pixel1;
1135 buffer[1] = pixel2;
1137 return hBitmap;
1140 static BOOL colour_match(UINT32 x, UINT32 y)
1142 const INT32 tolerance = 8;
1144 const INT32 dr = abs((INT32)(x & 0x000000FF) - (INT32)(y & 0x000000FF));
1145 const INT32 dg = abs((INT32)((x & 0x0000FF00) >> 8) - (INT32)((y & 0x0000FF00) >> 8));
1146 const INT32 db = abs((INT32)((x & 0x00FF0000) >> 16) - (INT32)((y & 0x00FF0000) >> 16));
1148 return (dr <= tolerance && dg <= tolerance && db <= tolerance);
1151 static void check_ImageList_DrawIndirect(IMAGELISTDRAWPARAMS *ildp, UINT32 *bits,
1152 UINT32 expected, int line)
1154 bits[0] = 0x00FFFFFF;
1155 pImageList_DrawIndirect(ildp);
1156 ok(colour_match(bits[0], expected),
1157 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1158 bits[0] & 0x00FFFFFF, expected, line);
1162 static void check_ImageList_DrawIndirect_fStyle(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1163 UINT fStyle, UINT32 expected, int line)
1165 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1166 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, ILS_NORMAL, 0, 0x00000000};
1167 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1170 static void check_ImageList_DrawIndirect_ILD_ROP(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1171 DWORD dwRop, UINT32 expected, int line)
1173 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1174 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, ILD_IMAGE | ILD_ROP, dwRop, ILS_NORMAL, 0, 0x00000000};
1175 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1178 static void check_ImageList_DrawIndirect_fState(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i, UINT fStyle,
1179 UINT fState, DWORD Frame, UINT32 expected, int line)
1181 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1182 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1183 check_ImageList_DrawIndirect(&ildp, bits, expected, line);
1186 static void check_ImageList_DrawIndirect_broken(HDC hdc, HIMAGELIST himl, UINT32 *bits, int i,
1187 UINT fStyle, UINT fState, DWORD Frame, UINT32 expected,
1188 UINT32 broken_expected, int line)
1190 IMAGELISTDRAWPARAMS ildp = {sizeof(IMAGELISTDRAWPARAMS), himl, i, hdc,
1191 0, 0, 0, 0, 0, 0, CLR_NONE, CLR_NONE, fStyle, 0, fState, Frame, 0x00000000};
1192 bits[0] = 0x00FFFFFF;
1193 pImageList_DrawIndirect(&ildp);
1194 ok(colour_match(bits[0], expected) ||
1195 broken(colour_match(bits[0], broken_expected)),
1196 "ImageList_DrawIndirect: Pixel %08X, Expected a close match to %08X from line %d\n",
1197 bits[0] & 0x00FFFFFF, expected, line);
1200 static void test_ImageList_DrawIndirect(void)
1202 HIMAGELIST himl = NULL;
1203 int ret;
1204 HDC hdcDst = NULL;
1205 HBITMAP hbmOld = NULL, hbmDst = NULL;
1206 HBITMAP hbmMask = NULL, hbmInverseMask = NULL;
1207 HBITMAP hbmImage = NULL, hbmAlphaImage = NULL, hbmTransparentImage = NULL;
1208 int iImage = -1, iAlphaImage = -1, iTransparentImage = -1;
1209 UINT32 *bits = 0;
1210 UINT32 maskBits = 0x00000000, inverseMaskBits = 0xFFFFFFFF;
1211 int bpp, broken_value;
1213 BITMAPINFO bitmapInfo = {{sizeof(BITMAPINFOHEADER), 2, 1, 1, 32, BI_RGB,
1214 0, 0, 0, 0, 0}};
1216 hdcDst = CreateCompatibleDC(0);
1217 ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1218 if (!hdcDst)
1219 return;
1220 bpp = GetDeviceCaps(hdcDst, BITSPIXEL);
1222 hbmMask = CreateBitmap(2, 1, 1, 1, &maskBits);
1223 ok(hbmMask != 0, "CreateBitmap failed\n");
1224 if(!hbmMask) goto cleanup;
1226 hbmInverseMask = CreateBitmap(2, 1, 1, 1, &inverseMaskBits);
1227 ok(hbmInverseMask != 0, "CreateBitmap failed\n");
1228 if(!hbmInverseMask) goto cleanup;
1230 himl = pImageList_Create(2, 1, ILC_COLOR32, 0, 1);
1231 ok(himl != 0, "ImageList_Create failed\n");
1232 if(!himl) goto cleanup;
1234 /* Add a no-alpha image */
1235 hbmImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x00ABCDEF);
1236 if(!hbmImage) goto cleanup;
1238 iImage = pImageList_Add(himl, hbmImage, hbmMask);
1239 ok(iImage != -1, "ImageList_Add failed\n");
1240 if(iImage == -1) goto cleanup;
1242 /* Add an alpha image */
1243 hbmAlphaImage = create_test_bitmap(hdcDst, 32, 0x89ABCDEF, 0x89ABCDEF);
1244 if(!hbmAlphaImage) goto cleanup;
1246 iAlphaImage = pImageList_Add(himl, hbmAlphaImage, hbmMask);
1247 ok(iAlphaImage != -1, "ImageList_Add failed\n");
1248 if(iAlphaImage == -1) goto cleanup;
1250 /* Add a transparent alpha image */
1251 hbmTransparentImage = create_test_bitmap(hdcDst, 32, 0x00ABCDEF, 0x89ABCDEF);
1252 if(!hbmTransparentImage) goto cleanup;
1254 iTransparentImage = pImageList_Add(himl, hbmTransparentImage, hbmMask);
1255 ok(iTransparentImage != -1, "ImageList_Add failed\n");
1256 if(iTransparentImage == -1) goto cleanup;
1258 /* 32-bit Tests */
1259 bitmapInfo.bmiHeader.biBitCount = 32;
1260 hbmDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
1261 ok (hbmDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1262 if (!hbmDst || !bits)
1263 goto cleanup;
1264 hbmOld = SelectObject(hdcDst, hbmDst);
1266 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_NORMAL, 0x00ABCDEF, __LINE__);
1267 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_TRANSPARENT, 0x00ABCDEF, __LINE__);
1268 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, 0x00D4D9DD, __LINE__);
1269 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1270 else broken_value = 0x00B4BDC4;
1271 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1272 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_MASK, 0x00ABCDEF, __LINE__);
1273 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_IMAGE, 0x00ABCDEF, __LINE__);
1274 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iImage, ILD_PRESERVEALPHA, 0x00ABCDEF, __LINE__);
1276 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, 0x00D3E5F7, __LINE__);
1277 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_TRANSPARENT, 0x00D3E5F7, __LINE__);
1279 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1280 else broken_value = 0x009DA8B1;
1281 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND25, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1282 if (bpp == 16 || bpp == 24) broken_value = 0x00D4D9DD;
1283 else broken_value = 0x008C99A3;
1284 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_BLEND50, ILS_NORMAL, 0, 0x00E8F1FA, broken_value, __LINE__);
1285 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_MASK, 0x00D3E5F7, __LINE__);
1286 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_IMAGE, 0x00D3E5F7, __LINE__);
1287 todo_wine check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iAlphaImage, ILD_PRESERVEALPHA, 0x005D6F81, __LINE__);
1289 check_ImageList_DrawIndirect_fStyle(hdcDst, himl, bits, iTransparentImage, ILD_NORMAL, 0x00FFFFFF, __LINE__);
1291 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCCOPY, 0x00ABCDEF, __LINE__);
1292 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iImage, SRCINVERT, 0x00543210, __LINE__);
1294 /* ILD_ROP is ignored when the image has an alpha channel */
1295 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCCOPY, 0x00D3E5F7, __LINE__);
1296 check_ImageList_DrawIndirect_ILD_ROP(hdcDst, himl, bits, iAlphaImage, SRCINVERT, 0x00D3E5F7, __LINE__);
1298 todo_wine check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00CCCCCC, __LINE__);
1299 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_SATURATE, 0, 0x00AFAFAF, 0x00F0F0F0, __LINE__);
1301 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_GLOW, 0, 0x00ABCDEF, __LINE__);
1302 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_SHADOW, 0, 0x00ABCDEF, __LINE__);
1304 check_ImageList_DrawIndirect_fState(hdcDst, himl, bits, iImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00D5E6F7, __LINE__);
1305 check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_ALPHA, 127, 0x00E9F2FB, 0x00AEB7C0, __LINE__);
1306 todo_wine check_ImageList_DrawIndirect_broken(hdcDst, himl, bits, iAlphaImage, ILD_NORMAL, ILS_NORMAL, 127, 0x00E9F2FB, 0x00D3E5F7, __LINE__);
1308 cleanup:
1310 if(hbmOld)
1311 SelectObject(hdcDst, hbmOld);
1312 if(hbmDst)
1313 DeleteObject(hbmDst);
1315 if(hdcDst)
1316 DeleteDC(hdcDst);
1318 if(hbmMask)
1319 DeleteObject(hbmMask);
1320 if(hbmInverseMask)
1321 DeleteObject(hbmInverseMask);
1323 if(hbmImage)
1324 DeleteObject(hbmImage);
1325 if(hbmAlphaImage)
1326 DeleteObject(hbmAlphaImage);
1327 if(hbmTransparentImage)
1328 DeleteObject(hbmTransparentImage);
1330 if(himl)
1332 ret = ImageList_Destroy(himl);
1333 ok(ret, "ImageList_Destroy failed\n");
1337 static void test_iimagelist(void)
1339 IImageList *imgl, *imgl2;
1340 HIMAGELIST himl;
1341 HRESULT hr;
1342 ULONG ret;
1344 if (!pHIMAGELIST_QueryInterface)
1346 win_skip("XP imagelist functions not available\n");
1347 return;
1350 /* test reference counting on destruction */
1351 imgl = (IImageList*)createImageList(32, 32);
1352 ret = IUnknown_AddRef(imgl);
1353 ok(ret == 2, "Expected 2, got %d\n", ret);
1354 ret = ImageList_Destroy((HIMAGELIST)imgl);
1355 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1356 ret = ImageList_Destroy((HIMAGELIST)imgl);
1357 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1358 ret = ImageList_Destroy((HIMAGELIST)imgl);
1359 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1361 imgl = (IImageList*)createImageList(32, 32);
1362 ret = IUnknown_AddRef(imgl);
1363 ok(ret == 2, "Expected 2, got %d\n", ret);
1364 ret = ImageList_Destroy((HIMAGELIST)imgl);
1365 ok(ret == TRUE, "Expected TRUE, got %d\n", ret);
1366 ret = IImageList_Release(imgl);
1367 ok(ret == 0, "Expected 0, got %d\n", ret);
1368 ret = ImageList_Destroy((HIMAGELIST)imgl);
1369 ok(ret == FALSE, "Expected FALSE, got %d\n", ret);
1371 /* ref counting, HIMAGELIST_QueryInterface adds a reference */
1372 imgl = (IImageList*)createImageList(32, 32);
1373 hr = pHIMAGELIST_QueryInterface((HIMAGELIST)imgl, &IID_IImageList, (void**)&imgl2);
1374 ok(hr == S_OK, "got 0x%08x\n", hr);
1375 ok(imgl2 == imgl, "got different pointer\n");
1376 ret = IImageList_Release(imgl);
1377 ok(ret == 1, "got %u\n", ret);
1378 IImageList_Release(imgl);
1380 if (!pImageList_CoCreateInstance)
1382 win_skip("Vista imagelist functions not available\n");
1383 return;
1386 hr = pImageList_CoCreateInstance(&CLSID_ImageList, NULL, &IID_IImageList, (void **) &imgl);
1387 ok(SUCCEEDED(hr), "ImageList_CoCreateInstance failed, hr=%x\n", hr);
1389 if (hr == S_OK)
1390 IImageList_Release(imgl);
1392 himl = createImageList(32, 32);
1394 if (!himl)
1395 return;
1397 hr = (pHIMAGELIST_QueryInterface)(himl, &IID_IImageList, (void **) &imgl);
1398 ok(SUCCEEDED(hr), "HIMAGELIST_QueryInterface failed, hr=%x\n", hr);
1400 if (hr == S_OK)
1401 IImageList_Release(imgl);
1403 ImageList_Destroy(himl);
1406 static void test_hotspot_v6(void)
1408 struct hotspot {
1409 int dx;
1410 int dy;
1413 #define SIZEX1 47
1414 #define SIZEY1 31
1415 #define SIZEX2 11
1416 #define SIZEY2 17
1417 #define HOTSPOTS_MAX 4 /* Number of entries in hotspots */
1418 static const struct hotspot hotspots[HOTSPOTS_MAX] = {
1419 { 10, 7 },
1420 { SIZEX1, SIZEY1 },
1421 { -9, -8 },
1422 { -7, 35 }
1424 int i, j;
1425 HIMAGELIST himl1 = createImageList(SIZEX1, SIZEY1);
1426 HIMAGELIST himl2 = createImageList(SIZEX2, SIZEY2);
1427 IImageList *imgl1, *imgl2;
1428 HRESULT hr;
1430 /* cast to IImageList */
1431 imgl1 = (IImageList *) himl1;
1432 imgl2 = (IImageList *) himl2;
1434 for (i = 0; i < HOTSPOTS_MAX; i++) {
1435 for (j = 0; j < HOTSPOTS_MAX; j++) {
1436 int dx1 = hotspots[i].dx;
1437 int dy1 = hotspots[i].dy;
1438 int dx2 = hotspots[j].dx;
1439 int dy2 = hotspots[j].dy;
1440 int correctx, correcty, newx, newy;
1441 char loc[256];
1442 IImageList *imglNew;
1443 POINT ppt;
1445 hr = IImageList_BeginDrag(imgl1, 0, dx1, dy1);
1446 ok(SUCCEEDED(hr), "BeginDrag failed for { %d, %d }\n", dx1, dy1);
1447 sprintf(loc, "BeginDrag (%d,%d)\n", i, j);
1449 /* check merging the dragged image with a second image */
1450 hr = IImageList_SetDragCursorImage(imgl2, (IUnknown *) imgl2, 0, dx2, dy2);
1451 ok(SUCCEEDED(hr), "SetDragCursorImage failed for {%d, %d}{%d, %d}\n",
1452 dx1, dy1, dx2, dy2);
1453 sprintf(loc, "SetDragCursorImage (%d,%d)\n", i, j);
1455 /* check new hotspot, it should be the same like the old one */
1456 hr = IImageList_GetDragImage(imgl2, NULL, &ppt, &IID_IImageList, (PVOID *) &imglNew);
1457 ok(SUCCEEDED(hr), "GetDragImage failed\n");
1458 ok(ppt.x == dx1 && ppt.y == dy1,
1459 "Expected drag hotspot [%d,%d] got [%d,%d]\n",
1460 dx1, dy1, ppt.x, ppt.y);
1461 /* check size of new dragged image */
1462 IImageList_GetIconSize(imglNew, &newx, &newy);
1463 correctx = max(SIZEX1, max(SIZEX2 + dx2, SIZEX1 - dx2));
1464 correcty = max(SIZEY1, max(SIZEY2 + dy2, SIZEY1 - dy2));
1465 ok(newx == correctx && newy == correcty,
1466 "Expected drag image size [%d,%d] got [%d,%d]\n",
1467 correctx, correcty, newx, newy);
1468 sprintf(loc, "GetDragImage (%d,%d)\n", i, j);
1469 IImageList_EndDrag(imgl2);
1472 #undef SIZEX1
1473 #undef SIZEY1
1474 #undef SIZEX2
1475 #undef SIZEY2
1476 #undef HOTSPOTS_MAX
1477 IImageList_Release(imgl2);
1478 IImageList_Release(imgl1);
1481 static void test_IImageList_Add_Remove(void)
1483 IImageList *imgl;
1484 HIMAGELIST himl;
1485 HRESULT hr;
1487 HICON hicon1;
1488 HICON hicon2;
1489 HICON hicon3;
1491 int ret;
1493 /* create an imagelist to play with */
1494 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1495 ok(himl != 0,"failed to create imagelist\n");
1497 imgl = (IImageList *) himl;
1499 /* load the icons to add to the image list */
1500 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1501 ok(hicon1 != 0, "no hicon1\n");
1502 hicon2 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1503 ok(hicon2 != 0, "no hicon2\n");
1504 hicon3 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1505 ok(hicon3 != 0, "no hicon3\n");
1507 /* remove when nothing exists */
1508 hr = IImageList_Remove(imgl, 0);
1509 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1511 /* removing everything from an empty imagelist should succeed */
1512 hr = IImageList_Remove(imgl, -1);
1513 ok(hr == S_OK, "removed nonexistent icon\n");
1515 /* add three */
1516 ret = -1;
1517 ok( IImageList_ReplaceIcon(imgl, -1, hicon1, &ret) == S_OK && (ret == 0),"failed to add icon1\n");
1518 ret = -1;
1519 ok( IImageList_ReplaceIcon(imgl, -1, hicon2, &ret) == S_OK && (ret == 1),"failed to add icon2\n");
1520 ret = -1;
1521 ok( IImageList_ReplaceIcon(imgl, -1, hicon3, &ret) == S_OK && (ret == 2),"failed to add icon3\n");
1523 /* remove an index out of range */
1524 ok( IImageList_Remove(imgl, 4711) == E_INVALIDARG, "got 0x%08x\n", hr);
1526 /* remove three */
1527 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1528 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1529 ok( IImageList_Remove(imgl,0) == S_OK, "can't remove 0\n");
1531 /* remove one extra */
1532 ok( IImageList_Remove(imgl, 0) == E_INVALIDARG, "got 0x%08x\n", hr);
1534 IImageList_Release(imgl);
1535 ok(DestroyIcon(hicon1),"icon 1 wasn't deleted\n");
1536 ok(DestroyIcon(hicon2),"icon 2 wasn't deleted\n");
1537 ok(DestroyIcon(hicon3),"icon 3 wasn't deleted\n");
1540 static void test_IImageList_Get_SetImageCount(void)
1542 IImageList *imgl;
1543 HIMAGELIST himl;
1544 HRESULT hr;
1545 INT ret;
1547 /* create an imagelist to play with */
1548 himl = ImageList_Create(84, 84, ILC_COLOR16, 0, 3);
1549 ok(himl != 0,"failed to create imagelist\n");
1551 imgl = (IImageList *) himl;
1553 /* check SetImageCount/GetImageCount */
1554 hr = IImageList_SetImageCount(imgl, 3);
1555 ok(hr == S_OK, "got 0x%08x\n", hr);
1556 ret = 0;
1557 hr = IImageList_GetImageCount(imgl, &ret);
1558 ok(hr == S_OK && ret == 3, "invalid image count after increase\n");
1559 hr = IImageList_SetImageCount(imgl, 1);
1560 ok(hr == S_OK, "got 0x%08x\n", hr);
1561 ret = 0;
1562 hr = IImageList_GetImageCount(imgl, &ret);
1563 ok(hr == S_OK && ret == 1, "invalid image count after decrease to 1\n");
1564 hr = IImageList_SetImageCount(imgl, 0);
1565 ok(hr == S_OK, "got 0x%08x\n", hr);
1566 ret = -1;
1567 hr = IImageList_GetImageCount(imgl, &ret);
1568 ok(hr == S_OK && ret == 0, "invalid image count after decrease to 0\n");
1570 IImageList_Release(imgl);
1573 static void test_IImageList_Draw(void)
1575 IImageList *imgl;
1576 HIMAGELIST himl;
1578 HBITMAP hbm1;
1579 HBITMAP hbm2;
1580 HBITMAP hbm3;
1582 IMAGELISTDRAWPARAMS imldp;
1583 HWND hwndfortest;
1584 HRESULT hr;
1585 HDC hdc;
1586 int ret;
1588 hwndfortest = create_a_window();
1589 hdc = GetDC(hwndfortest);
1590 ok(hdc!=NULL, "couldn't get DC\n");
1592 /* create an imagelist to play with */
1593 himl = ImageList_Create(48, 48, ILC_COLOR16, 0, 3);
1594 ok(himl!=0,"failed to create imagelist\n");
1596 imgl = (IImageList *) himl;
1598 /* load the icons to add to the image list */
1599 hbm1 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1600 ok(hbm1 != 0, "no bitmap 1\n");
1601 hbm2 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1602 ok(hbm2 != 0, "no bitmap 2\n");
1603 hbm3 = CreateBitmap(48, 48, 1, 1, bitmap_bits);
1604 ok(hbm3 != 0, "no bitmap 3\n");
1606 /* add three */
1607 ret = -1;
1608 ok( IImageList_Add(imgl, hbm1, 0, &ret) == S_OK && (ret == 0), "failed to add bitmap 1\n");
1609 ret = -1;
1610 ok( IImageList_Add(imgl, hbm2, 0, &ret) == S_OK && (ret == 1), "failed to add bitmap 2\n");
1612 ok( IImageList_SetImageCount(imgl, 3) == S_OK, "Setimage count failed\n");
1613 ok( IImageList_Replace(imgl, 2, hbm3, 0) == S_OK, "failed to replace bitmap 3\n");
1615 if (0)
1617 /* crashes on native */
1618 IImageList_Draw(imgl, NULL);
1621 memset(&imldp, 0, sizeof (imldp));
1622 hr = IImageList_Draw(imgl, &imldp);
1623 ok( hr == E_INVALIDARG, "got 0x%08x\n", hr);
1625 imldp.cbSize = IMAGELISTDRAWPARAMS_V3_SIZE;
1626 imldp.hdcDst = hdc;
1627 imldp.himl = himl;
1629 REDRAW(hwndfortest);
1630 WAIT;
1632 imldp.fStyle = SRCCOPY;
1633 imldp.rgbBk = CLR_DEFAULT;
1634 imldp.rgbFg = CLR_DEFAULT;
1635 imldp.y = 100;
1636 imldp.x = 100;
1637 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1638 imldp.i ++;
1639 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1640 imldp.i ++;
1641 ok( IImageList_Draw(imgl, &imldp) == S_OK, "should succeed\n");
1642 imldp.i ++;
1643 ok( IImageList_Draw(imgl, &imldp) == E_INVALIDARG, "should fail\n");
1645 /* remove three */
1646 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 1st bitmap\n");
1647 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 2nd bitmap\n");
1648 ok( IImageList_Remove(imgl, 0) == S_OK, "removing 3rd bitmap\n");
1650 /* destroy it */
1651 IImageList_Release(imgl);
1653 /* bitmaps should not be deleted by the imagelist */
1654 ok(DeleteObject(hbm1),"bitmap 1 can't be deleted\n");
1655 ok(DeleteObject(hbm2),"bitmap 2 can't be deleted\n");
1656 ok(DeleteObject(hbm3),"bitmap 3 can't be deleted\n");
1658 ReleaseDC(hwndfortest, hdc);
1659 DestroyWindow(hwndfortest);
1662 static void test_IImageList_Merge(void)
1664 HIMAGELIST himl1, himl2;
1665 IImageList *imgl1, *imgl2, *merge;
1666 HICON hicon1;
1667 HWND hwnd = create_a_window();
1668 HRESULT hr;
1669 int ret;
1671 himl1 = ImageList_Create(32,32,0,0,3);
1672 ok(himl1 != NULL,"failed to create himl1\n");
1674 himl2 = ImageList_Create(32,32,0,0,3);
1675 ok(himl2 != NULL,"failed to create himl2\n");
1677 hicon1 = CreateIcon(hinst, 32, 32, 1, 1, icon_bits, icon_bits);
1678 ok(hicon1 != NULL, "failed to create hicon1\n");
1680 if (!himl1 || !himl2 || !hicon1)
1681 return;
1683 /* cast to IImageList */
1684 imgl1 = (IImageList *) himl1;
1685 imgl2 = (IImageList *) himl2;
1687 ret = -1;
1688 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl2 failed\n");
1690 if (0)
1692 /* null cases that crash on native */
1693 IImageList_Merge(imgl1, -1, NULL, 0, 0, 0, &IID_IImageList, (void**)&merge);
1694 IImageList_Merge(imgl1, -1, (IUnknown*) imgl2, 0, 0, 0, &IID_IImageList, NULL);
1697 /* If himl1 has no images, merge still succeeds */
1698 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1699 ok(hr == S_OK, "merge himl1,-1 failed\n");
1700 if (hr == S_OK) IImageList_Release(merge);
1702 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1703 ok(hr == S_OK, "merge himl1,0 failed\n");
1704 if (hr == S_OK) IImageList_Release(merge);
1706 /* Same happens if himl2 is empty */
1707 IImageList_Release(imgl2);
1708 himl2 = ImageList_Create(32,32,0,0,3);
1709 ok(himl2 != NULL,"failed to recreate himl2\n");
1711 imgl2 = (IImageList *) himl2;
1713 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, -1, 0, 0, &IID_IImageList, (void **) &merge);
1714 ok(hr == S_OK, "merge himl2,-1 failed\n");
1715 if (hr == S_OK) IImageList_Release(merge);
1717 hr = IImageList_Merge(imgl1, -1, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1718 ok(hr == S_OK, "merge himl2,0 failed\n");
1719 if (hr == S_OK) IImageList_Release(merge);
1721 /* Now try merging an image with itself */
1722 ret = -1;
1723 ok( IImageList_ReplaceIcon(imgl2, -1, hicon1, &ret) == S_OK && (ret == 0),"re-add icon1 to himl2 failed\n");
1725 hr = IImageList_Merge(imgl2, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1726 ok(hr == S_OK, "merge himl2 with itself failed\n");
1727 if (hr == S_OK) IImageList_Release(merge);
1729 /* Try merging 2 different image lists */
1730 ret = -1;
1731 ok( IImageList_ReplaceIcon(imgl1, -1, hicon1, &ret) == S_OK && (ret == 0),"add icon1 to himl1 failed\n");
1733 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 0, 0, &IID_IImageList, (void **) &merge);
1734 ok(hr == S_OK, "merge himl1 with himl2 failed\n");
1735 if (hr == S_OK) IImageList_Release(merge);
1737 hr = IImageList_Merge(imgl1, 0, (IUnknown *) imgl2, 0, 8, 16, &IID_IImageList, (void **) &merge);
1738 ok(hr == S_OK, "merge himl1 with himl2 8,16 failed\n");
1739 if (hr == S_OK) IImageList_Release(merge);
1741 IImageList_Release(imgl1);
1742 IImageList_Release(imgl2);
1744 DestroyIcon(hicon1);
1745 DestroyWindow(hwnd);
1748 static void test_iconsize(void)
1750 HIMAGELIST himl;
1751 INT cx, cy;
1752 BOOL ret;
1754 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1755 /* null pointers, not zero imagelist dimensions */
1756 ret = ImageList_GetIconSize(himl, NULL, NULL);
1757 ok(!ret, "got %d\n", ret);
1759 /* doesn't touch return pointers */
1760 cx = 0xdeadbeef;
1761 ret = ImageList_GetIconSize(himl, &cx, NULL);
1762 ok(!ret, "got %d\n", ret);
1763 ok(cx == 0xdeadbeef, "got %d\n", cx);
1765 cy = 0xdeadbeef;
1766 ret = ImageList_GetIconSize(himl, NULL, &cy);
1767 ok(!ret, "got %d\n", ret);
1768 ok(cy == 0xdeadbeef, "got %d\n", cy);
1770 ImageList_Destroy(himl);
1773 static void test_create(void)
1775 HIMAGELIST himl;
1777 /* list with zero or negative image dimensions */
1778 himl = ImageList_Create(0, 0, ILC_COLOR16, 0, 3);
1779 ok(himl == NULL, "got %p\n", himl);
1781 himl = ImageList_Create(0, 16, ILC_COLOR16, 0, 3);
1782 ok(himl == NULL, "got %p\n", himl);
1784 himl = ImageList_Create(16, 0, ILC_COLOR16, 0, 3);
1785 ok(himl == NULL, "got %p\n", himl);
1787 himl = ImageList_Create(16, -1, ILC_COLOR16, 0, 3);
1788 ok(himl == NULL, "got %p\n", himl);
1790 himl = ImageList_Create(-1, 16, ILC_COLOR16, 0, 3);
1791 ok(himl == NULL, "got %p\n", himl);
1794 static void test_IImageList_Clone(void)
1796 IImageList *imgl, *imgl2;
1797 HIMAGELIST himl;
1798 HRESULT hr;
1799 ULONG ref;
1801 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1802 imgl = (IImageList*)himl;
1804 if (0)
1806 /* crashes on native */
1807 IImageList_Clone(imgl, &IID_IImageList, NULL);
1810 hr = IImageList_Clone(imgl, &IID_IImageList, (void**)&imgl2);
1811 ok(hr == S_OK, "got 0x%08x\n", hr);
1812 ref = IImageList_Release(imgl2);
1813 ok(ref == 0, "got %u\n", ref);
1815 IImageList_Release(imgl);
1818 static void test_IImageList_GetBkColor(void)
1820 IImageList *imgl;
1821 HIMAGELIST himl;
1822 COLORREF color;
1823 HRESULT hr;
1825 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1826 imgl = (IImageList*)himl;
1828 if (0)
1830 /* crashes on native */
1831 IImageList_GetBkColor(imgl, NULL);
1834 hr = IImageList_GetBkColor(imgl, &color);
1835 ok(hr == S_OK, "got 0x%08x\n", hr);
1837 IImageList_Release(imgl);
1840 static void test_IImageList_SetBkColor(void)
1842 IImageList *imgl;
1843 HIMAGELIST himl;
1844 COLORREF color;
1845 HRESULT hr;
1847 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1848 imgl = (IImageList*)himl;
1850 if (0)
1852 /* crashes on native */
1853 IImageList_SetBkColor(imgl, RGB(0, 0, 0), NULL);
1856 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1857 ok(hr == S_OK, "got 0x%08x\n", hr);
1859 hr = IImageList_SetBkColor(imgl, CLR_NONE, &color);
1860 ok(hr == S_OK, "got 0x%08x\n", hr);
1862 color = 0xdeadbeef;
1863 hr = IImageList_GetBkColor(imgl, &color);
1864 ok(hr == S_OK, "got 0x%08x\n", hr);
1865 ok(color == CLR_NONE, "got %x\n", color);
1867 IImageList_Release(imgl);
1870 static void test_IImageList_GetImageCount(void)
1872 IImageList *imgl;
1873 HIMAGELIST himl;
1874 int count;
1875 HRESULT hr;
1877 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1878 imgl = (IImageList*)himl;
1880 if (0)
1882 /* crashes on native */
1883 IImageList_GetImageCount(imgl, NULL);
1886 count = -1;
1887 hr = IImageList_GetImageCount(imgl, &count);
1888 ok(hr == S_OK, "got 0x%08x\n", hr);
1889 ok(count == 0, "got %d\n", count);
1891 IImageList_Release(imgl);
1894 static void test_IImageList_GetIconSize(void)
1896 IImageList *imgl;
1897 HIMAGELIST himl;
1898 int cx, cy;
1899 HRESULT hr;
1901 himl = ImageList_Create(16, 16, ILC_COLOR16, 0, 3);
1902 imgl = (IImageList*)himl;
1904 hr = IImageList_GetIconSize(imgl, NULL, NULL);
1905 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1907 hr = IImageList_GetIconSize(imgl, &cx, NULL);
1908 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1910 hr = IImageList_GetIconSize(imgl, NULL, &cy);
1911 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
1913 IImageList_Release(imgl);
1916 START_TEST(imagelist)
1918 ULONG_PTR ctx_cookie;
1919 HANDLE hCtx;
1921 HMODULE hComCtl32 = GetModuleHandle("comctl32.dll");
1922 pImageList_Create = NULL; /* These are not needed for non-v6.0 tests*/
1923 pImageList_Add = NULL;
1924 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1925 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1927 hinst = GetModuleHandleA(NULL);
1929 InitCommonControls();
1931 test_create();
1932 test_hotspot();
1933 test_add_remove();
1934 test_imagecount();
1935 test_DrawIndirect();
1936 test_merge();
1937 test_imagelist_storage();
1938 test_iconsize();
1940 FreeLibrary(hComCtl32);
1942 /* Now perform v6 tests */
1944 if (!load_v6_module(&ctx_cookie, &hCtx))
1945 return;
1947 /* Reload comctl32 */
1948 hComCtl32 = LoadLibraryA("comctl32.dll");
1949 pImageList_Create = (void*)GetProcAddress(hComCtl32, "ImageList_Create");
1950 pImageList_Add = (void*)GetProcAddress(hComCtl32, "ImageList_Add");
1951 pImageList_DrawIndirect = (void*)GetProcAddress(hComCtl32, "ImageList_DrawIndirect");
1952 pImageList_SetImageCount = (void*)GetProcAddress(hComCtl32, "ImageList_SetImageCount");
1953 pImageList_CoCreateInstance = (void*)GetProcAddress(hComCtl32, "ImageList_CoCreateInstance");
1954 pHIMAGELIST_QueryInterface = (void*)GetProcAddress(hComCtl32, "HIMAGELIST_QueryInterface");
1956 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1958 /* Do v6.0 tests */
1959 test_ImageList_DrawIndirect();
1960 test_shell_imagelist();
1961 test_iimagelist();
1963 test_hotspot_v6();
1964 test_IImageList_Add_Remove();
1965 test_IImageList_Get_SetImageCount();
1966 test_IImageList_Draw();
1967 test_IImageList_Merge();
1968 test_IImageList_Clone();
1969 test_IImageList_GetBkColor();
1970 test_IImageList_SetBkColor();
1971 test_IImageList_GetImageCount();
1972 test_IImageList_GetIconSize();
1974 CoUninitialize();
1976 unload_v6_module(ctx_cookie, hCtx);