~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/comctl32/imagelist.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  *  ImageList implementation
  3  *
  4  *  Copyright 1998 Eric Kohl
  5  *  Copyright 2000 Jason Mawdsley
  6  *  Copyright 2001, 2004 Michael Stefaniuc
  7  *  Copyright 2001 Charles Loep for CodeWeavers
  8  *  Copyright 2002 Dimitrie O. Paun
  9  *  Copyright 2009 Owen Rudge for CodeWeavers
 10  *
 11  * This library is free software; you can redistribute it and/or
 12  * modify it under the terms of the GNU Lesser General Public
 13  * License as published by the Free Software Foundation; either
 14  * version 2.1 of the License, or (at your option) any later version.
 15  *
 16  * This library is distributed in the hope that it will be useful,
 17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19  * Lesser General Public License for more details.
 20  *
 21  * You should have received a copy of the GNU Lesser General Public
 22  * License along with this library; if not, write to the Free Software
 23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 24  *
 25  * NOTE
 26  *
 27  * This code was audited for completeness against the documented features
 28  * of Comctl32.dll version 6.0 on Sep. 12, 2002, by Dimitrie O. Paun.
 29  *
 30  * Unless otherwise noted, we believe this code to be complete, as per
 31  * the specification mentioned above.
 32  * If you discover missing features, or bugs, please note them below.
 33  *
 34  *  TODO:
 35  *    - Add support for ILD_PRESERVEALPHA, ILD_SCALE, ILD_DPISCALE
 36  *    - Add support for ILS_GLOW, ILS_SHADOW, ILS_SATURATE, ILS_ALPHA
 37  *    - Thread-safe locking
 38  */
 39 
 40 #include <stdarg.h>
 41 #include <stdlib.h>
 42 #include <string.h>
 43 
 44 #define COBJMACROS
 45 
 46 #include "winerror.h"
 47 #include "windef.h"
 48 #include "winbase.h"
 49 #include "objbase.h"
 50 #include "wingdi.h"
 51 #include "winuser.h"
 52 #include "commctrl.h"
 53 #include "comctl32.h"
 54 #include "commoncontrols.h"
 55 #include "imagelist.h"
 56 #include "wine/debug.h"
 57 
 58 WINE_DEFAULT_DEBUG_CHANNEL(imagelist);
 59 
 60 
 61 #define MAX_OVERLAYIMAGE 15
 62 
 63 /* internal image list data used for Drag & Drop operations */
 64 typedef struct
 65 {
 66     HWND        hwnd;
 67     HIMAGELIST  himl;
 68     /* position of the drag image relative to the window */
 69     INT         x;
 70     INT         y;
 71     /* offset of the hotspot relative to the origin of the image */
 72     INT         dxHotspot;
 73     INT         dyHotspot;
 74     /* is the drag image visible */
 75     BOOL        bShow;
 76     /* saved background */
 77     HBITMAP     hbmBg;
 78 } INTERNALDRAG;
 79 
 80 static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, FALSE, 0 };
 81 
 82 static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count, UINT width);
 83 static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv);
 84 
 85 static inline BOOL is_valid(HIMAGELIST himl)
 86 {
 87     return himl && himl->magic == IMAGELIST_MAGIC;
 88 }
 89 
 90 /*
 91  * An imagelist with N images is tiled like this:
 92  *
 93  *   N/4 ->
 94  *
 95  * 4 048C..
 96  *   159D..
 97  * | 26AE.N
 98  * V 37BF.
 99  */
100 
101 #define TILE_COUNT 4
102 
103 static inline UINT imagelist_height( UINT count )
104 {
105     return ((count + TILE_COUNT - 1)/TILE_COUNT);
106 }
107 
108 static inline void imagelist_point_from_index( HIMAGELIST himl, UINT index, LPPOINT pt )
109 {
110     pt->x = (index%TILE_COUNT) * himl->cx;
111     pt->y = (index/TILE_COUNT) * himl->cy;
112 }
113 
114 static inline void imagelist_get_bitmap_size( HIMAGELIST himl, UINT count, UINT cx, SIZE *sz )
115 {
116     sz->cx = cx * TILE_COUNT;
117     sz->cy = imagelist_height( count ) * himl->cy;
118 }
119 
120 /*
121  * imagelist_copy_images()
122  *
123  * Copies a block of count images from offset src in the list to offset dest.
124  * Images are copied a row at at time. Assumes hdcSrc and hdcDest are different.
125  */
126 static inline void imagelist_copy_images( HIMAGELIST himl, HDC hdcSrc, HDC hdcDest,
127                                           UINT src, UINT count, UINT dest )
128 {
129     POINT ptSrc, ptDest;
130     SIZE sz;
131     UINT i;
132 
133     for ( i=0; i<TILE_COUNT; i++ )
134     {
135         imagelist_point_from_index( himl, src+i, &ptSrc );
136         imagelist_point_from_index( himl, dest+i, &ptDest );
137         sz.cx = himl->cx;
138         sz.cy = himl->cy * imagelist_height( count - i );
139 
140         BitBlt( hdcDest, ptDest.x, ptDest.y, sz.cx, sz.cy,
141                 hdcSrc, ptSrc.x, ptSrc.y, SRCCOPY );
142     }
143 }
144 
145 /*************************************************************************
146  * IMAGELIST_InternalExpandBitmaps [Internal]
147  *
148  * Expands the bitmaps of an image list by the given number of images.
149  *
150  * PARAMS
151  *     himl        [I] handle to image list
152  *     nImageCount [I] number of images to add
153  *
154  * RETURNS
155  *     nothing
156  *
157  * NOTES
158  *     This function CANNOT be used to reduce the number of images.
159  */
160 static void
161 IMAGELIST_InternalExpandBitmaps (HIMAGELIST himl, INT nImageCount, INT cx, INT cy)
162 {
163     HDC     hdcBitmap;
164     HBITMAP hbmNewBitmap, hbmNull;
165     INT     nNewCount;
166     SIZE    sz;
167 
168     if ((himl->cCurImage + nImageCount <= himl->cMaxImage)
169         && (himl->cy >= cy))
170         return;
171 
172     if (cx == 0) cx = himl->cx;
173     nNewCount = himl->cCurImage + nImageCount + himl->cGrow;
174 
175     imagelist_get_bitmap_size(himl, nNewCount, cx, &sz);
176 
177     TRACE("Create expanded bitmaps : himl=%p x=%d y=%d count=%d\n", himl, sz.cx, cy, nNewCount);
178     hdcBitmap = CreateCompatibleDC (0);
179 
180     hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount, cx);
181 
182     if (hbmNewBitmap == 0)
183         ERR("creating new image bitmap (x=%d y=%d)!\n", sz.cx, cy);
184 
185     if (himl->cCurImage)
186     {
187         hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
188         BitBlt (hdcBitmap, 0, 0, sz.cx, sz.cy,
189                 himl->hdcImage, 0, 0, SRCCOPY);
190         SelectObject (hdcBitmap, hbmNull);
191     }
192     SelectObject (himl->hdcImage, hbmNewBitmap);
193     DeleteObject (himl->hbmImage);
194     himl->hbmImage = hbmNewBitmap;
195 
196     if (himl->flags & ILC_MASK)
197     {
198         hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
199 
200         if (hbmNewBitmap == 0)
201             ERR("creating new mask bitmap!\n");
202 
203         if(himl->cCurImage)
204         {
205             hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
206             BitBlt (hdcBitmap, 0, 0, sz.cx, sz.cy,
207                     himl->hdcMask, 0, 0, SRCCOPY);
208             SelectObject (hdcBitmap, hbmNull);
209         }
210         SelectObject (himl->hdcMask, hbmNewBitmap);
211         DeleteObject (himl->hbmMask);
212         himl->hbmMask = hbmNewBitmap;
213     }
214 
215     himl->cMaxImage = nNewCount;
216 
217     DeleteDC (hdcBitmap);
218 }
219 
220 
221 /*************************************************************************
222  * ImageList_Add [COMCTL32.@]
223  *
224  * Add an image or images to an image list.
225  *
226  * PARAMS
227  *     himl     [I] handle to image list
228  *     hbmImage [I] handle to image bitmap
229  *     hbmMask  [I] handle to mask bitmap
230  *
231  * RETURNS
232  *     Success: Index of the first new image.
233  *     Failure: -1
234  */
235 
236 INT WINAPI
237 ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
238 {
239     HDC     hdcBitmap, hdcTemp;
240     INT     nFirstIndex, nImageCount, i;
241     BITMAP  bmp;
242     HBITMAP hOldBitmap, hOldBitmapTemp;
243     POINT   pt;
244 
245     TRACE("himl=%p hbmimage=%p hbmmask=%p\n", himl, hbmImage, hbmMask);
246     if (!is_valid(himl))
247         return -1;
248 
249     if (!GetObjectW(hbmImage, sizeof(BITMAP), &bmp))
250         return -1;
251 
252     nImageCount = bmp.bmWidth / himl->cx;
253 
254     IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
255 
256     hdcBitmap = CreateCompatibleDC(0);
257 
258     hOldBitmap = SelectObject(hdcBitmap, hbmImage);
259 
260     for (i=0; i<nImageCount; i++)
261     {
262         imagelist_point_from_index( himl, himl->cCurImage + i, &pt );
263 
264         /* Copy result to the imagelist
265         */
266         BitBlt( himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
267                 hdcBitmap, i*himl->cx, 0, SRCCOPY );
268 
269         if (!himl->hbmMask)
270              continue;
271 
272         hdcTemp   = CreateCompatibleDC(0);
273         hOldBitmapTemp = SelectObject(hdcTemp, hbmMask);
274 
275         BitBlt( himl->hdcMask, pt.x, pt.y, himl->cx, bmp.bmHeight,
276                 hdcTemp, i*himl->cx, 0, SRCCOPY );
277 
278         SelectObject(hdcTemp, hOldBitmapTemp);
279         DeleteDC(hdcTemp);
280 
281         /* Remove the background from the image
282         */
283         BitBlt( himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
284                 himl->hdcMask, pt.x, pt.y, 0x220326 ); /* NOTSRCAND */
285     }
286 
287     SelectObject(hdcBitmap, hOldBitmap);
288     DeleteDC(hdcBitmap);
289 
290     nFirstIndex = himl->cCurImage;
291     himl->cCurImage += nImageCount;
292 
293     return nFirstIndex;
294 }
295 
296 
297 /*************************************************************************
298  * ImageList_AddIcon [COMCTL32.@]
299  *
300  * Adds an icon to an image list.
301  *
302  * PARAMS
303  *     himl  [I] handle to image list
304  *     hIcon [I] handle to icon
305  *
306  * RETURNS
307  *     Success: index of the new image
308  *     Failure: -1
309  */
310 #undef ImageList_AddIcon
311 INT WINAPI ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
312 {
313     return ImageList_ReplaceIcon (himl, -1, hIcon);
314 }
315 
316 
317 /*************************************************************************
318  * ImageList_AddMasked [COMCTL32.@]
319  *
320  * Adds an image or images to an image list and creates a mask from the
321  * specified bitmap using the mask color.
322  *
323  * PARAMS
324  *     himl    [I] handle to image list.
325  *     hBitmap [I] handle to bitmap
326  *     clrMask [I] mask color.
327  *
328  * RETURNS
329  *     Success: Index of the first new image.
330  *     Failure: -1
331  */
332 
333 INT WINAPI
334 ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
335 {
336     HDC    hdcMask, hdcBitmap;
337     INT    i, nIndex, nImageCount;
338     BITMAP bmp;
339     HBITMAP hOldBitmap;
340     HBITMAP hMaskBitmap=0;
341     COLORREF bkColor;
342     POINT  pt;
343 
344     TRACE("himl=%p hbitmap=%p clrmask=%x\n", himl, hBitmap, clrMask);
345     if (!is_valid(himl))
346         return -1;
347 
348     if (!GetObjectW(hBitmap, sizeof(BITMAP), &bmp))
349         return -1;
350 
351     if (himl->cx > 0)
352         nImageCount = bmp.bmWidth / himl->cx;
353     else
354         nImageCount = 0;
355 
356     IMAGELIST_InternalExpandBitmaps (himl, nImageCount, bmp.bmWidth, bmp.bmHeight);
357 
358     nIndex = himl->cCurImage;
359     himl->cCurImage += nImageCount;
360 
361     hdcBitmap = CreateCompatibleDC(0);
362     hOldBitmap = SelectObject(hdcBitmap, hBitmap);
363 
364     /* Create a temp Mask so we can remove the background of the Image */
365     hdcMask = CreateCompatibleDC(0);
366     hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
367     SelectObject(hdcMask, hMaskBitmap);
368 
369     /* create monochrome image to the mask bitmap */
370     bkColor = (clrMask != CLR_DEFAULT) ? clrMask : GetPixel (hdcBitmap, 0, 0);
371     SetBkColor (hdcBitmap, bkColor);
372     BitBlt (hdcMask, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcBitmap, 0, 0, SRCCOPY);
373 
374     SetBkColor(hdcBitmap, RGB(255,255,255));
375 
376     /*
377      * Remove the background from the image
378      *
379      * WINDOWS BUG ALERT!!!!!!
380      *  The statement below should not be done in common practice
381      *  but this is how ImageList_AddMasked works in Windows.
382      *  It overwrites the original bitmap passed, this was discovered
383      *  by using the same bitmap to iterate the different styles
384      *  on windows where it failed (BUT ImageList_Add is OK)
385      *  This is here in case some apps rely on this bug
386      *
387      *  Blt mode 0x220326 is NOTSRCAND
388      */
389     BitBlt(hdcBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMask, 0, 0, 0x220326);
390 
391     /* Copy result to the imagelist */
392     for (i=0; i<nImageCount; i++)
393     {
394         imagelist_point_from_index( himl, nIndex + i, &pt );
395         BitBlt(himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
396                 hdcBitmap, i*himl->cx, 0, SRCCOPY);
397         BitBlt(himl->hdcMask, pt.x, pt.y, himl->cx, bmp.bmHeight,
398                 hdcMask, i*himl->cx, 0, SRCCOPY);
399     }
400 
401     /* Clean up */
402     SelectObject(hdcBitmap, hOldBitmap);
403     DeleteDC(hdcBitmap);
404     DeleteObject(hMaskBitmap);
405     DeleteDC(hdcMask);
406 
407     return nIndex;
408 }
409 
410 
411 /*************************************************************************
412  * ImageList_BeginDrag [COMCTL32.@]
413  *
414  * Creates a temporary image list that contains one image. It will be used
415  * as a drag image.
416  *
417  * PARAMS
418  *     himlTrack [I] handle to the source image list
419  *     iTrack    [I] index of the drag image in the source image list
420  *     dxHotspot [I] X position of the hot spot of the drag image
421  *     dyHotspot [I] Y position of the hot spot of the drag image
422  *
423  * RETURNS
424  *     Success: TRUE
425  *     Failure: FALSE
426  */
427 
428 BOOL WINAPI
429 ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
430                      INT dxHotspot, INT dyHotspot)
431 {
432     INT cx, cy;
433 
434     TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack,
435           dxHotspot, dyHotspot);
436 
437     if (!is_valid(himlTrack))
438         return FALSE;
439 
440     if (InternalDrag.himl)
441         ImageList_EndDrag ();
442 
443     cx = himlTrack->cx;
444     cy = himlTrack->cy;
445 
446     InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1);
447     if (InternalDrag.himl == NULL) {
448         WARN("Error creating drag image list!\n");
449         return FALSE;
450     }
451 
452     InternalDrag.dxHotspot = dxHotspot;
453     InternalDrag.dyHotspot = dyHotspot;
454 
455     /* copy image */
456     BitBlt (InternalDrag.himl->hdcImage, 0, 0, cx, cy, himlTrack->hdcImage, iTrack * cx, 0, SRCCOPY);
457 
458     /* copy mask */
459     BitBlt (InternalDrag.himl->hdcMask, 0, 0, cx, cy, himlTrack->hdcMask, iTrack * cx, 0, SRCCOPY);
460 
461     InternalDrag.himl->cCurImage = 1;
462 
463     return TRUE;
464 }
465 
466 
467 /*************************************************************************
468  * ImageList_Copy [COMCTL32.@]
469  *
470  *  Copies an image of the source image list to an image of the
471  *  destination image list. Images can be copied or swapped.
472  *
473  * PARAMS
474  *     himlDst [I] handle to the destination image list
475  *     iDst    [I] destination image index.
476  *     himlSrc [I] handle to the source image list
477  *     iSrc    [I] source image index
478  *     uFlags  [I] flags for the copy operation
479  *
480  * RETURNS
481  *     Success: TRUE
482  *     Failure: FALSE
483  *
484  * NOTES
485  *     Copying from one image list to another is possible. The original
486  *     implementation just copies or swaps within one image list.
487  *     Could this feature become a bug??? ;-)
488  */
489 
490 BOOL WINAPI
491 ImageList_Copy (HIMAGELIST himlDst, INT iDst,   HIMAGELIST himlSrc,
492                 INT iSrc, UINT uFlags)
493 {
494     POINT ptSrc, ptDst;
495 
496     TRACE("himlDst=%p iDst=%d himlSrc=%p iSrc=%d\n", himlDst, iDst, himlSrc, iSrc);
497 
498     if (!is_valid(himlSrc) || !is_valid(himlDst))
499         return FALSE;
500     if ((iDst < 0) || (iDst >= himlDst->cCurImage))
501         return FALSE;
502     if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
503         return FALSE;
504 
505     imagelist_point_from_index( himlDst, iDst, &ptDst );
506     imagelist_point_from_index( himlSrc, iSrc, &ptSrc );
507 
508     if (uFlags & ILCF_SWAP) {
509         /* swap */
510         HDC     hdcBmp;
511         HBITMAP hbmTempImage, hbmTempMask;
512 
513         hdcBmp = CreateCompatibleDC (0);
514 
515         /* create temporary bitmaps */
516         hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
517                                        himlSrc->uBitsPixel, NULL);
518         hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
519                                       1, NULL);
520 
521         /* copy (and stretch) destination to temporary bitmaps.(save) */
522         /* image */
523         SelectObject (hdcBmp, hbmTempImage);
524         StretchBlt   (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
525                       himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
526                       SRCCOPY);
527         /* mask */
528         SelectObject (hdcBmp, hbmTempMask);
529         StretchBlt   (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
530                       himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
531                       SRCCOPY);
532 
533         /* copy (and stretch) source to destination */
534         /* image */
535         StretchBlt   (himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
536                       himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
537                       SRCCOPY);
538         /* mask */
539         StretchBlt   (himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
540                       himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
541                       SRCCOPY);
542 
543         /* copy (without stretching) temporary bitmaps to source (restore) */
544         /* mask */
545         BitBlt       (himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
546                       hdcBmp, 0, 0, SRCCOPY);
547 
548         /* image */
549         BitBlt       (himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
550                       hdcBmp, 0, 0, SRCCOPY);
551         /* delete temporary bitmaps */
552         DeleteObject (hbmTempMask);
553         DeleteObject (hbmTempImage);
554         DeleteDC(hdcBmp);
555     }
556     else {
557         /* copy image */
558         StretchBlt   (himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
559                       himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
560                       SRCCOPY);
561 
562         /* copy mask */
563         StretchBlt   (himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
564                       himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
565                       SRCCOPY);
566     }
567 
568     return TRUE;
569 }
570 
571 
572 /*************************************************************************
573  * ImageList_Create [COMCTL32.@]
574  *
575  * Creates a new image list.
576  *
577  * PARAMS
578  *     cx       [I] image height
579  *     cy       [I] image width
580  *     flags    [I] creation flags
581  *     cInitial [I] initial number of images in the image list
582  *     cGrow    [I] number of images by which image list grows
583  *
584  * RETURNS
585  *     Success: Handle to the created image list
586  *     Failure: NULL
587  */
588 HIMAGELIST WINAPI
589 ImageList_Create (INT cx, INT cy, UINT flags,
590                   INT cInitial, INT cGrow)
591 {
592     HIMAGELIST himl;
593     INT      nCount;
594     HBITMAP  hbmTemp;
595     UINT     ilc = (flags & 0xFE);
596     static const WORD aBitBlend25[] =
597         {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
598 
599     static const WORD aBitBlend50[] =
600         {0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
601 
602     TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
603 
604     /* Create the IImageList interface for the image list */
605     if (!SUCCEEDED(ImageListImpl_CreateInstance(NULL, &IID_IImageList, (void **) &himl)))
606         return NULL;
607 
608     cGrow = (cGrow < 4) ? 4 : (cGrow + 3) & ~3;
609 
610     himl->magic     = IMAGELIST_MAGIC;
611     himl->cx        = cx;
612     himl->cy        = cy;
613     himl->flags     = flags;
614     himl->cMaxImage = cInitial + 1;
615     himl->cInitial  = cInitial;
616     himl->cGrow     = cGrow;
617     himl->clrFg     = CLR_DEFAULT;
618     himl->clrBk     = CLR_NONE;
619 
620     /* initialize overlay mask indices */
621     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
622         himl->nOvlIdx[nCount] = -1;
623 
624     /* Create Image & Mask DCs */
625     himl->hdcImage = CreateCompatibleDC (0);
626     if (!himl->hdcImage)
627         goto cleanup;
628     if (himl->flags & ILC_MASK){
629         himl->hdcMask = CreateCompatibleDC(0);
630         if (!himl->hdcMask)
631             goto cleanup;
632     }
633 
634     /* Default to ILC_COLOR4 if none of the ILC_COLOR* flags are specified */
635     if (ilc == ILC_COLOR)
636         ilc = ILC_COLOR4;
637 
638     if (ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32)
639         himl->uBitsPixel = ilc;
640     else
641         himl->uBitsPixel = (UINT)GetDeviceCaps (himl->hdcImage, BITSPIXEL);
642 
643     if (himl->cMaxImage > 0) {
644         himl->hbmImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage, cx);
645         SelectObject(himl->hdcImage, himl->hbmImage);
646     } else
647         himl->hbmImage = 0;
648 
649     if ((himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
650         SIZE sz;
651 
652         imagelist_get_bitmap_size(himl, himl->cMaxImage, himl->cx, &sz);
653         himl->hbmMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
654         if (himl->hbmMask == 0) {
655             ERR("Error creating mask bitmap!\n");
656             goto cleanup;
657         }
658         SelectObject(himl->hdcMask, himl->hbmMask);
659     }
660     else
661         himl->hbmMask = 0;
662 
663     /* create blending brushes */
664     hbmTemp = CreateBitmap (8, 8, 1, 1, aBitBlend25);
665     himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
666     DeleteObject (hbmTemp);
667 
668     hbmTemp = CreateBitmap (8, 8, 1, 1, aBitBlend50);
669     himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
670     DeleteObject (hbmTemp);
671 
672     TRACE("created imagelist %p\n", himl);
673     return himl;
674 
675 cleanup:
676     if (himl) ImageList_Destroy(himl);
677     return NULL;
678 }
679 
680 
681 /*************************************************************************
682  * ImageList_Destroy [COMCTL32.@]
683  *
684  * Destroys an image list.
685  *
686  * PARAMS
687  *     himl [I] handle to image list
688  *
689  * RETURNS
690  *     Success: TRUE
691  *     Failure: FALSE
692  */
693 
694 BOOL WINAPI
695 ImageList_Destroy (HIMAGELIST himl)
696 {
697     if (!is_valid(himl))
698         return FALSE;
699 
700     /* delete image bitmaps */
701     if (himl->hbmImage)
702         DeleteObject (himl->hbmImage);
703     if (himl->hbmMask)
704         DeleteObject (himl->hbmMask);
705 
706     /* delete image & mask DCs */
707     if (himl->hdcImage)
708         DeleteDC(himl->hdcImage);
709     if (himl->hdcMask)
710         DeleteDC(himl->hdcMask);
711 
712     /* delete blending brushes */
713     if (himl->hbrBlend25)
714         DeleteObject (himl->hbrBlend25);
715     if (himl->hbrBlend50)
716         DeleteObject (himl->hbrBlend50);
717 
718     /* Free the IImageList instance */
719     IImageList_Release((IImageList *) himl);
720     return TRUE;
721 }
722 
723 
724 /*************************************************************************
725  * ImageList_DragEnter [COMCTL32.@]
726  *
727  * Locks window update and displays the drag image at the given position.
728  *
729  * PARAMS
730  *     hwndLock [I] handle of the window that owns the drag image.
731  *     x        [I] X position of the drag image.
732  *     y        [I] Y position of the drag image.
733  *
734  * RETURNS
735  *     Success: TRUE
736  *     Failure: FALSE
737  *
738  * NOTES
739  *     The position of the drag image is relative to the window, not
740  *     the client area.
741  */
742 
743 BOOL WINAPI
744 ImageList_DragEnter (HWND hwndLock, INT x, INT y)
745 {
746     TRACE("(hwnd=%p x=%d y=%d)\n", hwndLock, x, y);
747 
748     if (!is_valid(InternalDrag.himl))
749         return FALSE;
750 
751     if (hwndLock)
752         InternalDrag.hwnd = hwndLock;
753     else
754         InternalDrag.hwnd = GetDesktopWindow ();
755 
756     InternalDrag.x = x;
757     InternalDrag.y = y;
758 
759     /* draw the drag image and save the background */
760     if (!ImageList_DragShowNolock(TRUE)) {
761         return FALSE;
762     }
763 
764     return TRUE;
765 }
766 
767 
768 /*************************************************************************
769  * ImageList_DragLeave [COMCTL32.@]
770  *
771  * Unlocks window update and hides the drag image.
772  *
773  * PARAMS
774  *     hwndLock [I] handle of the window that owns the drag image.
775  *
776  * RETURNS
777  *     Success: TRUE
778  *     Failure: FALSE
779  */
780 
781 BOOL WINAPI
782 ImageList_DragLeave (HWND hwndLock)
783 {
784     /* As we don't save drag info in the window this can lead to problems if
785        an app does not supply the same window as DragEnter */
786     /* if (hwndLock)
787         InternalDrag.hwnd = hwndLock;
788     else
789         InternalDrag.hwnd = GetDesktopWindow (); */
790     if(!hwndLock)
791         hwndLock = GetDesktopWindow();
792     if(InternalDrag.hwnd != hwndLock)
793         FIXME("DragLeave hWnd != DragEnter hWnd\n");
794 
795     ImageList_DragShowNolock (FALSE);
796 
797     return TRUE;
798 }
799 
800 
801 /*************************************************************************
802  * ImageList_InternalDragDraw [Internal]
803  *
804  * Draws the drag image.
805  *
806  * PARAMS
807  *     hdc [I] device context to draw into.
808  *     x   [I] X position of the drag image.
809  *     y   [I] Y position of the drag image.
810  *
811  * RETURNS
812  *     Success: TRUE
813  *     Failure: FALSE
814  *
815  * NOTES
816  *     The position of the drag image is relative to the window, not
817  *     the client area.
818  *
819  */
820 
821 static inline void
822 ImageList_InternalDragDraw (HDC hdc, INT x, INT y)
823 {
824     IMAGELISTDRAWPARAMS imldp;
825 
826     ZeroMemory (&imldp, sizeof(imldp));
827     imldp.cbSize  = sizeof(imldp);
828     imldp.himl    = InternalDrag.himl;
829     imldp.i       = 0;
830     imldp.hdcDst  = hdc,
831     imldp.x       = x;
832     imldp.y       = y;
833     imldp.rgbBk   = CLR_DEFAULT;
834     imldp.rgbFg   = CLR_DEFAULT;
835     imldp.fStyle  = ILD_NORMAL;
836     imldp.fState  = ILS_ALPHA;
837     imldp.Frame   = 128;
838 
839     /* FIXME: instead of using the alpha blending, we should
840      * create a 50% mask, and draw it semitransparantly that way */
841     ImageList_DrawIndirect (&imldp);
842 }
843 
844 /*************************************************************************
845  * ImageList_DragMove [COMCTL32.@]
846  *
847  * Moves the drag image.
848  *
849  * PARAMS
850  *     x [I] X position of the drag image.
851  *     y [I] Y position of the drag image.
852  *
853  * RETURNS
854  *     Success: TRUE
855  *     Failure: FALSE
856  *
857  * NOTES
858  *     The position of the drag image is relative to the window, not
859  *     the client area.
860  *
861  * BUGS
862  *     The drag image should be drawn semitransparent.
863  */
864 
865 BOOL WINAPI
866 ImageList_DragMove (INT x, INT y)
867 {
868     TRACE("(x=%d y=%d)\n", x, y);
869 
870     if (!is_valid(InternalDrag.himl))
871         return FALSE;
872 
873     /* draw/update the drag image */
874     if (InternalDrag.bShow) {
875         HDC hdcDrag;
876         HDC hdcOffScreen;
877         HDC hdcBg;
878         HBITMAP hbmOffScreen;
879         INT origNewX, origNewY;
880         INT origOldX, origOldY;
881         INT origRegX, origRegY;
882         INT sizeRegX, sizeRegY;
883 
884 
885         /* calculate the update region */
886         origNewX = x - InternalDrag.dxHotspot;
887         origNewY = y - InternalDrag.dyHotspot;
888         origOldX = InternalDrag.x - InternalDrag.dxHotspot;
889         origOldY = InternalDrag.y - InternalDrag.dyHotspot;
890         origRegX = min(origNewX, origOldX);
891         origRegY = min(origNewY, origOldY);
892         sizeRegX = InternalDrag.himl->cx + abs(x - InternalDrag.x);
893         sizeRegY = InternalDrag.himl->cy + abs(y - InternalDrag.y);
894 
895         hdcDrag = GetDCEx(InternalDrag.hwnd, 0,
896                           DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
897         hdcOffScreen = CreateCompatibleDC(hdcDrag);
898         hdcBg = CreateCompatibleDC(hdcDrag);
899 
900         hbmOffScreen = CreateCompatibleBitmap(hdcDrag, sizeRegX, sizeRegY);
901         SelectObject(hdcOffScreen, hbmOffScreen);
902         SelectObject(hdcBg, InternalDrag.hbmBg);
903 
904         /* get the actual background of the update region */
905         BitBlt(hdcOffScreen, 0, 0, sizeRegX, sizeRegY, hdcDrag,
906                origRegX, origRegY, SRCCOPY);
907         /* erase the old image */
908         BitBlt(hdcOffScreen, origOldX - origRegX, origOldY - origRegY,
909                InternalDrag.himl->cx, InternalDrag.himl->cy, hdcBg, 0, 0,
910                SRCCOPY);
911         /* save the background */
912         BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
913                hdcOffScreen, origNewX - origRegX, origNewY - origRegY, SRCCOPY);
914         /* draw the image */
915         ImageList_InternalDragDraw(hdcOffScreen, origNewX - origRegX, 
916                                    origNewY - origRegY);
917         /* draw the update region to the screen */
918         BitBlt(hdcDrag, origRegX, origRegY, sizeRegX, sizeRegY,
919                hdcOffScreen, 0, 0, SRCCOPY);
920 
921         DeleteDC(hdcBg);
922         DeleteDC(hdcOffScreen);
923         DeleteObject(hbmOffScreen);
924         ReleaseDC(InternalDrag.hwnd, hdcDrag);
925     }
926 
927     /* update the image position */
928     InternalDrag.x = x;
929     InternalDrag.y = y;
930 
931     return TRUE;
932 }
933 
934 
935 /*************************************************************************
936  * ImageList_DragShowNolock [COMCTL32.@]
937  *
938  * Shows or hides the drag image.
939  *
940  * PARAMS
941  *     bShow [I] TRUE shows the drag image, FALSE hides it.
942  *
943  * RETURNS
944  *     Success: TRUE
945  *     Failure: FALSE
946  *
947  * BUGS
948  *     The drag image should be drawn semitransparent.
949  */
950 
951 BOOL WINAPI
952 ImageList_DragShowNolock (BOOL bShow)
953 {
954     HDC hdcDrag;
955     HDC hdcBg;
956     INT x, y;
957 
958     if (!is_valid(InternalDrag.himl))
959         return FALSE;
960     
961     TRACE("bShow=0x%X!\n", bShow);
962 
963     /* DragImage is already visible/hidden */
964     if ((InternalDrag.bShow && bShow) || (!InternalDrag.bShow && !bShow)) {
965         return FALSE;
966     }
967 
968     /* position of the origin of the DragImage */
969     x = InternalDrag.x - InternalDrag.dxHotspot;
970     y = InternalDrag.y - InternalDrag.dyHotspot;
971 
972     hdcDrag = GetDCEx (InternalDrag.hwnd, 0,
973                          DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
974     if (!hdcDrag) {
975         return FALSE;
976     }
977 
978     hdcBg = CreateCompatibleDC(hdcDrag);
979     if (!InternalDrag.hbmBg) {
980         InternalDrag.hbmBg = CreateCompatibleBitmap(hdcDrag,
981                     InternalDrag.himl->cx, InternalDrag.himl->cy);
982     }
983     SelectObject(hdcBg, InternalDrag.hbmBg);
984 
985     if (bShow) {
986         /* save the background */
987         BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
988                hdcDrag, x, y, SRCCOPY);
989         /* show the image */
990         ImageList_InternalDragDraw(hdcDrag, x, y);
991     } else {
992         /* hide the image */
993         BitBlt(hdcDrag, x, y, InternalDrag.himl->cx, InternalDrag.himl->cy,
994                hdcBg, 0, 0, SRCCOPY);
995     }
996 
997     InternalDrag.bShow = !InternalDrag.bShow;
998 
999     DeleteDC(hdcBg);
1000     ReleaseDC (InternalDrag.hwnd, hdcDrag);
1001     return TRUE;
1002 }
1003 
1004 
1005 /*************************************************************************
1006  * ImageList_Draw [COMCTL32.@]
1007  *
1008  * Draws an image.
1009  *
1010  * PARAMS
1011  *     himl   [I] handle to image list
1012  *     i      [I] image index
1013  *     hdc    [I] handle to device context
1014  *     x      [I] x position
1015  *     y      [I] y position
1016  *     fStyle [I] drawing flags
1017  *
1018  * RETURNS
1019  *     Success: TRUE
1020  *     Failure: FALSE
1021  *
1022  * SEE
1023  *     ImageList_DrawEx.
1024  */
1025 
1026 BOOL WINAPI
1027 ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, UINT fStyle)
1028 {
1029     return ImageList_DrawEx (himl, i, hdc, x, y, 0, 0, 
1030                              CLR_DEFAULT, CLR_DEFAULT, fStyle);
1031 }
1032 
1033 
1034 /*************************************************************************
1035  * ImageList_DrawEx [COMCTL32.@]
1036  *
1037  * Draws an image and allows to use extended drawing features.
1038  *
1039  * PARAMS
1040  *     himl   [I] handle to image list
1041  *     i      [I] image index
1042  *     hdc    [I] handle to device context
1043  *     x      [I] X position
1044  *     y      [I] Y position
1045  *     dx     [I] X offset
1046  *     dy     [I] Y offset
1047  *     rgbBk  [I] background color
1048  *     rgbFg  [I] foreground color
1049  *     fStyle [I] drawing flags
1050  *
1051  * RETURNS
1052  *     Success: TRUE
1053  *     Failure: FALSE
1054  *
1055  * NOTES
1056  *     Calls ImageList_DrawIndirect.
1057  *
1058  * SEE
1059  *     ImageList_DrawIndirect.
1060  */
1061 
1062 BOOL WINAPI
1063 ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1064                   INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1065                   UINT fStyle)
1066 {
1067     IMAGELISTDRAWPARAMS imldp;
1068 
1069     ZeroMemory (&imldp, sizeof(imldp));
1070     imldp.cbSize  = sizeof(imldp);
1071     imldp.himl    = himl;
1072     imldp.i       = i;
1073     imldp.hdcDst  = hdc,
1074     imldp.x       = x;
1075     imldp.y       = y;
1076     imldp.cx      = dx;
1077     imldp.cy      = dy;
1078     imldp.rgbBk   = rgbBk;
1079     imldp.rgbFg   = rgbFg;
1080     imldp.fStyle  = fStyle;
1081 
1082     return ImageList_DrawIndirect (&imldp);
1083 }
1084 
1085 
1086 /*************************************************************************
1087  * ImageList_DrawIndirect [COMCTL32.@]
1088  *
1089  * Draws an image using various parameters specified in pimldp.
1090  *
1091  * PARAMS
1092  *     pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1093  *
1094  * RETURNS
1095  *     Success: TRUE
1096  *     Failure: FALSE
1097  */
1098 
1099 BOOL WINAPI
1100 ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1101 {
1102     INT cx, cy, nOvlIdx;
1103     DWORD fState, dwRop;
1104     UINT fStyle;
1105     COLORREF oldImageBk, oldImageFg;
1106     HDC hImageDC, hImageListDC, hMaskListDC;
1107     HBITMAP hImageBmp, hOldImageBmp, hBlendMaskBmp;
1108     BOOL bIsTransparent, bBlend, bResult = FALSE, bMask;
1109     HIMAGELIST himl;
1110     POINT pt;
1111 
1112     if (!pimldp || !(himl = pimldp->himl)) return FALSE;
1113     if (!is_valid(himl)) return FALSE;
1114     if ((pimldp->i < 0) || (pimldp->i >= himl->cCurImage)) return FALSE;
1115 
1116     imagelist_point_from_index( himl, pimldp->i, &pt );
1117     pt.x += pimldp->xBitmap;
1118     pt.y += pimldp->yBitmap;
1119 
1120     fState = pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS) ? ILS_NORMAL : pimldp->fState;
1121     fStyle = pimldp->fStyle & ~ILD_OVERLAYMASK;
1122     cx = (pimldp->cx == 0) ? himl->cx : pimldp->cx;
1123     cy = (pimldp->cy == 0) ? himl->cy : pimldp->cy;
1124 
1125     bIsTransparent = (fStyle & ILD_TRANSPARENT);
1126     if( pimldp->rgbBk == CLR_NONE )
1127         bIsTransparent = TRUE;
1128     if( ( pimldp->rgbBk == CLR_DEFAULT ) && ( himl->clrBk == CLR_NONE ) )
1129         bIsTransparent = TRUE;
1130     bMask = (himl->flags & ILC_MASK) && (fStyle & ILD_MASK) ;
1131     bBlend = (fStyle & (ILD_BLEND25 | ILD_BLEND50) ) && !bMask;
1132 
1133     TRACE("himl(%p) hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n",
1134           himl, himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy);
1135 
1136     /* we will use these DCs to access the images and masks in the ImageList */
1137     hImageListDC = himl->hdcImage;
1138     hMaskListDC  = himl->hdcMask;
1139 
1140     /* these will accumulate the image and mask for the image we're drawing */
1141     hImageDC = CreateCompatibleDC( pimldp->hdcDst );
1142     hImageBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy );
1143     hBlendMaskBmp = bBlend ? CreateBitmap(cx, cy, 1, 1, NULL) : 0;
1144 
1145     /* Create a compatible DC. */
1146     if (!hImageListDC || !hImageDC || !hImageBmp ||
1147         (bBlend && !hBlendMaskBmp) || (himl->hbmMask && !hMaskListDC))
1148         goto cleanup;
1149     
1150     hOldImageBmp = SelectObject(hImageDC, hImageBmp);
1151   
1152     /*
1153      * To obtain a transparent look, background color should be set
1154      * to white and foreground color to black when blting the
1155      * monochrome mask.
1156      */
1157     oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) );
1158     oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) );
1159 
1160     /*
1161      * Draw the initial image
1162      */
1163     if( bMask ) {
1164         if (himl->hbmMask) {
1165             HBRUSH hOldBrush;
1166             hOldBrush = SelectObject (hImageDC, CreateSolidBrush (GetTextColor(pimldp->hdcDst)));
1167             PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1168             BitBlt(hImageDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, SRCPAINT);
1169             DeleteObject (SelectObject (hImageDC, hOldBrush));
1170             if( bIsTransparent )
1171             {
1172                 BitBlt ( pimldp->hdcDst, pimldp->x,  pimldp->y, cx, cy, hImageDC, 0, 0, SRCAND);
1173                 bResult = TRUE;
1174                 goto end;
1175             }
1176         } else {
1177             HBRUSH hOldBrush = SelectObject (hImageDC, GetStockObject(BLACK_BRUSH));
1178             PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY);
1179             SelectObject(hImageDC, hOldBrush);
1180         }
1181     } else {
1182         /* blend the image with the needed solid background */
1183         COLORREF colour = RGB(0,0,0);
1184         HBRUSH hOldBrush;
1185 
1186         if( !bIsTransparent )
1187         {
1188             colour = pimldp->rgbBk;
1189             if( colour == CLR_DEFAULT )
1190                 colour = himl->clrBk;
1191             if( colour == CLR_NONE )
1192                 colour = GetBkColor(pimldp->hdcDst);
1193         }
1194 
1195         hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
1196         PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1197         if (himl->hbmMask)
1198         {
1199             BitBlt( hImageDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, SRCAND );
1200             BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, pt.x, pt.y, SRCPAINT );
1201         }
1202         else
1203             BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, pt.x, pt.y, SRCCOPY);
1204         DeleteObject (SelectObject (hImageDC, hOldBrush));
1205     }
1206 
1207     /* Time for blending, if required */
1208     if (bBlend) {
1209         HBRUSH hBlendBrush, hOldBrush;
1210         COLORREF clrBlend = pimldp->rgbFg;
1211         HDC hBlendMaskDC = hImageListDC;
1212         HBITMAP hOldBitmap;
1213 
1214         /* Create the blend Mask */
1215         hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBmp);
1216         hBlendBrush = fStyle & ILD_BLEND50 ? himl->hbrBlend50 : himl->hbrBlend25;
1217         hOldBrush = SelectObject(hBlendMaskDC, hBlendBrush);
1218         PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
1219         SelectObject(hBlendMaskDC, hOldBrush);
1220 
1221         /* Modify the blend mask if an Image Mask exist */
1222         if(himl->hbmMask) {
1223             BitBlt(hBlendMaskDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, 0x220326); /* NOTSRCAND */
1224             BitBlt(hBlendMaskDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, NOTSRCCOPY);
1225         }
1226 
1227         /* now apply blend to the current image given the BlendMask */
1228         if (clrBlend == CLR_DEFAULT) clrBlend = GetSysColor (COLOR_HIGHLIGHT);
1229         else if (clrBlend == CLR_NONE) clrBlend = GetTextColor (pimldp->hdcDst);
1230         hOldBrush = SelectObject (hImageDC, CreateSolidBrush(clrBlend));
1231         BitBlt (hImageDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, 0xB8074A); /* PSDPxax */
1232         DeleteObject(SelectObject(hImageDC, hOldBrush));
1233         SelectObject(hBlendMaskDC, hOldBitmap);
1234     }
1235 
1236     /* Now do the overlay image, if any */
1237     nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
1238     if ( (nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) {
1239         nOvlIdx = himl->nOvlIdx[nOvlIdx - 1];
1240         if ((nOvlIdx >= 0) && (nOvlIdx < himl->cCurImage)) {
1241             POINT ptOvl;
1242             imagelist_point_from_index( himl, nOvlIdx, &ptOvl );
1243             ptOvl.x += pimldp->xBitmap;
1244             if (himl->hbmMask && !(fStyle & ILD_IMAGE))
1245                 BitBlt (hImageDC, 0, 0, cx, cy, hMaskListDC, ptOvl.x, ptOvl.y, SRCAND);
1246             BitBlt (hImageDC, 0, 0, cx, cy, hImageListDC, ptOvl.x, ptOvl.y, SRCPAINT);
1247         }
1248     }
1249 
1250     if (fState & ILS_SATURATE) FIXME("ILS_SATURATE: unimplemented!\n");
1251     if (fState & ILS_GLOW) FIXME("ILS_GLOW: unimplemented!\n");
1252     if (fState & ILS_SHADOW) FIXME("ILS_SHADOW: unimplemented!\n");
1253     if (fState & ILS_ALPHA) FIXME("ILS_ALPHA: unimplemented!\n");
1254 
1255     if (fStyle & ILD_PRESERVEALPHA) FIXME("ILD_PRESERVEALPHA: unimplemented!\n");
1256     if (fStyle & ILD_SCALE) FIXME("ILD_SCALE: unimplemented!\n");
1257     if (fStyle & ILD_DPISCALE) FIXME("ILD_DPISCALE: unimplemented!\n");
1258 
1259     /* now copy the image to the screen */
1260     dwRop = SRCCOPY;
1261     if (himl->hbmMask && bIsTransparent ) {
1262         COLORREF oldDstFg = SetTextColor(pimldp->hdcDst, RGB( 0, 0, 0 ) );
1263         COLORREF oldDstBk = SetBkColor(pimldp->hdcDst, RGB( 0xff, 0xff, 0xff ));
1264         BitBlt (pimldp->hdcDst, pimldp->x,  pimldp->y, cx, cy, hMaskListDC, pt.x, pt.y, SRCAND);
1265         SetBkColor(pimldp->hdcDst, oldDstBk);
1266         SetTextColor(pimldp->hdcDst, oldDstFg);
1267         dwRop = SRCPAINT;
1268     }
1269     if (fStyle & ILD_ROP) dwRop = pimldp->dwRop;
1270     BitBlt (pimldp->hdcDst, pimldp->x,  pimldp->y, cx, cy, hImageDC, 0, 0, dwRop);
1271 
1272     bResult = TRUE;
1273 end:
1274     /* cleanup the mess */
1275     SetBkColor(hImageDC, oldImageBk);
1276     SetTextColor(hImageDC, oldImageFg);
1277     SelectObject(hImageDC, hOldImageBmp);
1278 cleanup:
1279     DeleteObject(hBlendMaskBmp);
1280     DeleteObject(hImageBmp);
1281     DeleteDC(hImageDC);
1282 
1283     return bResult;
1284 }
1285 
1286 
1287 /*************************************************************************
1288  * ImageList_Duplicate [COMCTL32.@]
1289  *
1290  * Duplicates an image list.
1291  *
1292  * PARAMS
1293  *     himlSrc [I] source image list handle
1294  *
1295  * RETURNS
1296  *     Success: Handle of duplicated image list.
1297  *     Failure: NULL
1298  */
1299 
1300 HIMAGELIST WINAPI
1301 ImageList_Duplicate (HIMAGELIST himlSrc)
1302 {
1303     HIMAGELIST himlDst;
1304 
1305     if (!is_valid(himlSrc)) {
1306         ERR("Invalid image list handle!\n");
1307         return NULL;
1308     }
1309 
1310     himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1311                                 himlSrc->cInitial, himlSrc->cGrow);
1312 
1313     if (himlDst)
1314     {
1315         SIZE sz;
1316 
1317         imagelist_get_bitmap_size(himlSrc, himlSrc->cCurImage, himlSrc->cx, &sz);
1318         BitBlt (himlDst->hdcImage, 0, 0, sz.cx, sz.cy,
1319                 himlSrc->hdcImage, 0, 0, SRCCOPY);
1320 
1321         if (himlDst->hbmMask)
1322             BitBlt (himlDst->hdcMask, 0, 0, sz.cx, sz.cy,
1323                     himlSrc->hdcMask, 0, 0, SRCCOPY);
1324 
1325         himlDst->cCurImage = himlSrc->cCurImage;
1326         himlDst->cMaxImage = himlSrc->cMaxImage;
1327     }
1328     return himlDst;
1329 }
1330 
1331 
1332 /*************************************************************************
1333  * ImageList_EndDrag [COMCTL32.@]
1334  *
1335  * Finishes a drag operation.
1336  *
1337  * PARAMS
1338  *     no Parameters
1339  *
1340  * RETURNS
1341  *     Success: TRUE
1342  *     Failure: FALSE
1343  */
1344 
1345 VOID WINAPI
1346 ImageList_EndDrag (void)
1347 {
1348     /* cleanup the InternalDrag struct */
1349     InternalDrag.hwnd = 0;
1350     ImageList_Destroy (InternalDrag.himl);
1351     InternalDrag.himl = 0;
1352     InternalDrag.x= 0;
1353     InternalDrag.y= 0;
1354     InternalDrag.dxHotspot = 0;
1355     InternalDrag.dyHotspot = 0;
1356     InternalDrag.bShow = FALSE;
1357     DeleteObject(InternalDrag.hbmBg);
1358     InternalDrag.hbmBg = 0;
1359 }
1360 
1361 
1362 /*************************************************************************
1363  * ImageList_GetBkColor [COMCTL32.@]
1364  *
1365  * Returns the background color of an image list.
1366  *
1367  * PARAMS
1368  *     himl [I] Image list handle.
1369  *
1370  * RETURNS
1371  *     Success: background color
1372  *     Failure: CLR_NONE
1373  */
1374 
1375 COLORREF WINAPI
1376 ImageList_GetBkColor (HIMAGELIST himl)
1377 {
1378     return himl ? himl->clrBk : CLR_NONE;
1379 }
1380 
1381 
1382 /*************************************************************************
1383  * ImageList_GetDragImage [COMCTL32.@]
1384  *
1385  * Returns the handle to the internal drag image list.
1386  *
1387  * PARAMS
1388  *     ppt        [O] Pointer to the drag position. Can be NULL.
1389  *     pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1390  *
1391  * RETURNS
1392  *     Success: Handle of the drag image list.
1393  *     Failure: NULL.
1394  */
1395 
1396 HIMAGELIST WINAPI
1397 ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1398 {
1399     if (is_valid(InternalDrag.himl)) {
1400         if (ppt) {
1401             ppt->x = InternalDrag.x;
1402             ppt->y = InternalDrag.y;
1403         }
1404         if (pptHotspot) {
1405             pptHotspot->x = InternalDrag.dxHotspot;
1406             pptHotspot->y = InternalDrag.dyHotspot;
1407         }
1408         return (InternalDrag.himl);
1409     }
1410 
1411     return NULL;
1412 }
1413 
1414 
1415 /*************************************************************************
1416  * ImageList_GetFlags [COMCTL32.@]
1417  *
1418  * Gets the flags of the specified image list.
1419  *
1420  * PARAMS
1421  *     himl [I] Handle to image list
1422  *
1423  * RETURNS
1424  *     Image list flags.
1425  *
1426  * BUGS
1427  *    Stub.
1428  */
1429 
1430 DWORD WINAPI
1431 ImageList_GetFlags(HIMAGELIST himl)
1432 {
1433     TRACE("%p\n", himl);
1434 
1435     return is_valid(himl) ? himl->flags : 0;
1436 }
1437 
1438 
1439 /*************************************************************************
1440  * ImageList_GetIcon [COMCTL32.@]
1441  *
1442  * Creates an icon from a masked image of an image list.
1443  *
1444  * PARAMS
1445  *     himl  [I] handle to image list
1446  *     i     [I] image index
1447  *     flags [I] drawing style flags
1448  *
1449  * RETURNS
1450  *     Success: icon handle
1451  *     Failure: NULL
1452  */
1453 
1454 HICON WINAPI
1455 ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1456 {
1457     ICONINFO ii;
1458     HICON hIcon;
1459     HBITMAP hOldDstBitmap;
1460     HDC hdcDst;
1461     POINT pt;
1462 
1463     TRACE("%p %d %d\n", himl, i, fStyle);
1464     if (!is_valid(himl) || (i < 0) || (i >= himl->cCurImage)) return NULL;
1465 
1466     ii.fIcon = TRUE;
1467     ii.xHotspot = 0;
1468     ii.yHotspot = 0;
1469 
1470     /* create colour bitmap */
1471     hdcDst = GetDC(0);
1472     ii.hbmColor = CreateCompatibleBitmap(hdcDst, himl->cx, himl->cy);
1473     ReleaseDC(0, hdcDst);
1474 
1475     hdcDst = CreateCompatibleDC(0);
1476 
1477     imagelist_point_from_index( himl, i, &pt );
1478 
1479     /* draw mask*/
1480     ii.hbmMask  = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
1481     hOldDstBitmap = SelectObject (hdcDst, ii.hbmMask);
1482     if (himl->hbmMask) {
1483         BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1484                 himl->hdcMask, pt.x, pt.y, SRCCOPY);
1485     }
1486     else
1487         PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1488 
1489     /* draw image*/
1490     SelectObject (hdcDst, ii.hbmColor);
1491     BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1492             himl->hdcImage, pt.x, pt.y, SRCCOPY);
1493 
1494     /*
1495      * CreateIconIndirect requires us to deselect the bitmaps from
1496      * the DCs before calling
1497      */
1498     SelectObject(hdcDst, hOldDstBitmap);
1499 
1500     hIcon = CreateIconIndirect (&ii);
1501 
1502     DeleteObject (ii.hbmMask);
1503     DeleteObject (ii.hbmColor);
1504     DeleteDC (hdcDst);
1505 
1506     return hIcon;
1507 }
1508 
1509 
1510 /*************************************************************************
1511  * ImageList_GetIconSize [COMCTL32.@]
1512  *
1513  * Retrieves the size of an image in an image list.
1514  *
1515  * PARAMS
1516  *     himl [I] handle to image list
1517  *     cx   [O] pointer to the image width.
1518  *     cy   [O] pointer to the image height.
1519  *
1520  * RETURNS
1521  *     Success: TRUE
1522  *     Failure: FALSE
1523  *
1524  * NOTES
1525  *     All images in an image list have the same size.
1526  */
1527 
1528 BOOL WINAPI
1529 ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1530 {
1531     if (!is_valid(himl))
1532         return FALSE;
1533     if ((himl->cx <= 0) || (himl->cy <= 0))
1534         return FALSE;
1535 
1536     if (cx)
1537         *cx = himl->cx;
1538     if (cy)
1539         *cy = himl->cy;
1540 
1541     return TRUE;
1542 }
1543 
1544 
1545 /*************************************************************************
1546  * ImageList_GetImageCount [COMCTL32.@]
1547  *
1548  * Returns the number of images in an image list.
1549  *
1550  * PARAMS
1551  *     himl [I] handle to image list
1552  *
1553  * RETURNS
1554  *     Success: Number of images.
1555  *     Failure: 0
1556  */
1557 
1558 INT WINAPI
1559 ImageList_GetImageCount (HIMAGELIST himl)
1560 {
1561     if (!is_valid(himl))
1562         return 0;
1563 
1564     return himl->cCurImage;
1565 }
1566 
1567 
1568 /*************************************************************************
1569  * ImageList_GetImageInfo [COMCTL32.@]
1570  *
1571  * Returns information about an image in an image list.
1572  *
1573  * PARAMS
1574  *     himl       [I] handle to image list
1575  *     i          [I] image index
1576  *     pImageInfo [O] pointer to the image information
1577  *
1578  * RETURNS
1579  *     Success: TRUE
1580  *     Failure: FALSE
1581  */
1582 
1583 BOOL WINAPI
1584 ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1585 {
1586     POINT pt;
1587 
1588     if (!is_valid(himl) || (pImageInfo == NULL))
1589         return FALSE;
1590     if ((i < 0) || (i >= himl->cCurImage))
1591         return FALSE;
1592 
1593     pImageInfo->hbmImage = himl->hbmImage;
1594     pImageInfo->hbmMask  = himl->hbmMask;
1595 
1596     imagelist_point_from_index( himl, i, &pt );
1597     pImageInfo->rcImage.top    = pt.y;
1598     pImageInfo->rcImage.bottom = pt.y + himl->cy;
1599     pImageInfo->rcImage.left   = pt.x;
1600     pImageInfo->rcImage.right  = pt.x + himl->cx;
1601 
1602     return TRUE;
1603 }
1604 
1605 
1606 /*************************************************************************
1607  * ImageList_GetImageRect [COMCTL32.@]
1608  *
1609  * Retrieves the rectangle of the specified image in an image list.
1610  *
1611  * PARAMS
1612  *     himl   [I] handle to image list
1613  *     i      [I] image index
1614  *     lpRect [O] pointer to the image rectangle
1615  *
1616  * RETURNS
1617  *    Success: TRUE
1618  *    Failure: FALSE
1619  *
1620  * NOTES
1621  *    This is an UNDOCUMENTED function!!!
1622  */
1623 
1624 BOOL WINAPI
1625 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1626 {
1627     POINT pt;
1628 
1629     if (!is_valid(himl) || (lpRect == NULL))
1630         return FALSE;
1631     if ((i < 0) || (i >= himl->cCurImage))
1632         return FALSE;
1633 
1634     imagelist_point_from_index( himl, i, &pt );
1635     lpRect->left   = pt.x;
1636     lpRect->top    = pt.y;
1637     lpRect->right  = pt.x + himl->cx;
1638     lpRect->bottom = pt.y + himl->cy;
1639 
1640     return TRUE;
1641 }
1642 
1643 
1644 /*************************************************************************
1645  * ImageList_LoadImage  [COMCTL32.@]
1646  * ImageList_LoadImageA [COMCTL32.@]
1647  *
1648  * Creates an image list from a bitmap, icon or cursor.
1649  *
1650  * See ImageList_LoadImageW.
1651  */
1652 
1653 HIMAGELIST WINAPI
1654 ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1655                         COLORREF clrMask, UINT uType, UINT uFlags)
1656 {
1657     HIMAGELIST himl;
1658     LPWSTR lpbmpW;
1659     DWORD len;
1660 
1661     if (!HIWORD(lpbmp))
1662         return ImageList_LoadImageW(hi, (LPCWSTR)lpbmp, cx, cGrow, clrMask,
1663                                     uType, uFlags);
1664 
1665     len = MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, NULL, 0);
1666     lpbmpW = Alloc(len * sizeof(WCHAR));
1667     MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, lpbmpW, len);
1668 
1669     himl = ImageList_LoadImageW(hi, lpbmpW, cx, cGrow, clrMask, uType, uFlags);
1670     Free (lpbmpW);
1671     return himl;
1672 }
1673 
1674 
1675 /*************************************************************************
1676  * ImageList_LoadImageW [COMCTL32.@]
1677  *
1678  * Creates an image list from a bitmap, icon or cursor.
1679  *
1680  * PARAMS
1681  *     hi      [I] instance handle
1682  *     lpbmp   [I] name or id of the image
1683  *     cx      [I] width of each image
1684  *     cGrow   [I] number of images to expand
1685  *     clrMask [I] mask color
1686  *     uType   [I] type of image to load
1687  *     uFlags  [I] loading flags
1688  *
1689  * RETURNS
1690  *     Success: handle to the loaded image list
1691  *     Failure: NULL
1692  *
1693  * SEE
1694  *     LoadImage ()
1695  */
1696 
1697 HIMAGELIST WINAPI
1698 ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1699                       COLORREF clrMask, UINT uType, UINT uFlags)
1700 {
1701     HIMAGELIST himl = NULL;
1702     HANDLE   handle;
1703     INT      nImageCount;
1704 
1705     handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1706     if (!handle) {
1707         WARN("Couldn't load image\n");
1708         return NULL;
1709     }
1710 
1711     if (uType == IMAGE_BITMAP) {
1712         BITMAP bmp;
1713         GetObjectW (handle, sizeof(BITMAP), &bmp);
1714 
1715         /* To match windows behavior, if cx is set to zero and
1716          the flag DI_DEFAULTSIZE is specified, cx becomes the
1717          system metric value for icons. If the flag is not specified
1718          the function sets the size to the height of the bitmap */
1719         if (cx == 0)
1720         {
1721             if (uFlags & DI_DEFAULTSIZE)
1722                 cx = GetSystemMetrics (SM_CXICON);
1723             else
1724                 cx = bmp.bmHeight;
1725         }
1726 
1727         nImageCount = bmp.bmWidth / cx;
1728 
1729         himl = ImageList_Create (cx, bmp.bmHeight, ILC_MASK | ILC_COLOR,
1730                                  nImageCount, cGrow);
1731         if (!himl) {
1732             DeleteObject (handle);
1733             return NULL;
1734         }
1735         ImageList_AddMasked (himl, handle, clrMask);
1736     }
1737     else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1738         ICONINFO ii;
1739         BITMAP bmp;
1740 
1741         GetIconInfo (handle, &ii);
1742         GetObjectW (ii.hbmColor, sizeof(BITMAP), &bmp);
1743         himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1744                                  ILC_MASK | ILC_COLOR, 1, cGrow);
1745         if (!himl) {
1746             DeleteObject (ii.hbmColor);
1747             DeleteObject (ii.hbmMask);
1748             DeleteObject (handle);
1749             return NULL;
1750         }
1751         ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1752         DeleteObject (ii.hbmColor);
1753         DeleteObject (ii.hbmMask);
1754     }
1755 
1756     DeleteObject (handle);
1757 
1758     return himl;
1759 }
1760 
1761 
1762 /*************************************************************************
1763  * ImageList_Merge [COMCTL32.@]
1764  *
1765  * Create an image list containing a merged image from two image lists.
1766  *
1767  * PARAMS
1768  *     himl1 [I] handle to first image list
1769  *     i1    [I] first image index
1770  *     himl2 [I] handle to second image list
1771  *     i2    [I] second image index
1772  *     dx    [I] X offset of the second image relative to the first.
1773  *     dy    [I] Y offset of the second image relative to the first.
1774  *
1775  * RETURNS
1776  *     Success: The newly created image list. It contains a single image
1777  *              consisting of the second image merged with the first.
1778  *     Failure: NULL, if either himl1 or himl2 are invalid.
1779  *
1780  * NOTES
1781  *   - The returned image list should be deleted by the caller using
1782  *     ImageList_Destroy() when it is no longer required.
1783  *   - If either i1 or i2 are not valid image indices they will be treated
1784  *     as a blank image.
1785  */
1786 HIMAGELIST WINAPI
1787 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
1788                  INT dx, INT dy)
1789 {
1790     HIMAGELIST himlDst = NULL;
1791     INT      cxDst, cyDst;
1792     INT      xOff1, yOff1, xOff2, yOff2;
1793     POINT    pt1, pt2;
1794 
1795     TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2,
1796            i2, dx, dy);
1797 
1798     if (!is_valid(himl1) || !is_valid(himl2))
1799         return NULL;
1800 
1801     if (dx > 0) {
1802         cxDst = max (himl1->cx, dx + himl2->cx);
1803         xOff1 = 0;
1804         xOff2 = dx;
1805     }
1806     else if (dx < 0) {
1807         cxDst = max (himl2->cx, himl1->cx - dx);
1808         xOff1 = -dx;
1809         xOff2 = 0;
1810     }
1811     else {
1812         cxDst = max (himl1->cx, himl2->cx);
1813         xOff1 = 0;
1814         xOff2 = 0;
1815     }
1816 
1817     if (dy > 0) {
1818         cyDst = max (himl1->cy, dy + himl2->cy);
1819         yOff1 = 0;
1820         yOff2 = dy;
1821     }
1822     else if (dy < 0) {
1823         cyDst = max (himl2->cy, himl1->cy - dy);
1824         yOff1 = -dy;
1825         yOff2 = 0;
1826     }
1827     else {
1828         cyDst = max (himl1->cy, himl2->cy);
1829         yOff1 = 0;
1830         yOff2 = 0;
1831     }
1832 
1833     himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
1834 
1835     if (himlDst)
1836     {
1837         imagelist_point_from_index( himl1, i1, &pt1 );
1838         imagelist_point_from_index( himl1, i2, &pt2 );
1839 
1840         /* copy image */
1841         BitBlt (himlDst->hdcImage, 0, 0, cxDst, cyDst, himl1->hdcImage, 0, 0, BLACKNESS);
1842         if (i1 >= 0 && i1 < himl1->cCurImage)
1843             BitBlt (himlDst->hdcImage, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcImage, pt1.x, pt1.y, SRCCOPY);
1844         if (i2 >= 0 && i2 < himl2->cCurImage)
1845         {
1846             BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , pt2.x, pt2.y, SRCAND);
1847             BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCPAINT);
1848         }
1849 
1850         /* copy mask */
1851         BitBlt (himlDst->hdcMask, 0, 0, cxDst, cyDst, himl1->hdcMask, 0, 0, WHITENESS);
1852         if (i1 >= 0 && i1 < himl1->cCurImage)
1853             BitBlt (himlDst->hdcMask,  xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcMask,  pt1.x, pt1.y, SRCCOPY);
1854         if (i2 >= 0 && i2 < himl2->cCurImage)
1855             BitBlt (himlDst->hdcMask,  xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask,  pt2.x, pt2.y, SRCAND);
1856 
1857         himlDst->cCurImage = 1;
1858     }
1859 
1860     return himlDst;
1861 }
1862 
1863 
1864 /***********************************************************************
1865  *           DIB_GetDIBWidthBytes
1866  *
1867  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
1868  */
1869 static int DIB_GetDIBWidthBytes( int width, int depth )
1870 {
1871     int words;
1872 
1873     switch(depth)
1874     {
1875     case 1:  words = (width + 31) / 32; break;
1876     case 4:  words = (width + 7) / 8; break;
1877     case 8:  words = (width + 3) / 4; break;
1878     case 15:
1879     case 16: words = (width + 1) / 2; break;
1880     case 24: words = (width * 3 + 3)/4; break;
1881 
1882     default:
1883         WARN("(%d): Unsupported depth\n", depth );
1884         /* fall through */
1885     case 32:
1886         words = width;
1887         break;
1888     }
1889     return 4 * words;
1890 }
1891 
1892 /***********************************************************************
1893  *           DIB_GetDIBImageBytes
1894  *
1895  * Return the number of bytes used to hold the image in a DIB bitmap.
1896  */
1897 static int DIB_GetDIBImageBytes( int width, int height, int depth )
1898 {
1899     return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
1900 }
1901 
1902 
1903 /* helper for ImageList_Read, see comments below */
1904 static BOOL _read_bitmap(HDC hdcIml, LPSTREAM pstm)
1905 {
1906     BITMAPFILEHEADER    bmfh;
1907     int bitsperpixel, palspace;
1908     char bmi_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
1909     LPBITMAPINFO bmi = (LPBITMAPINFO)bmi_buf;
1910     int                result = FALSE;
1911     LPBYTE             bits = NULL;
1912 
1913     if (FAILED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)))
1914         return FALSE;
1915 
1916     if (bmfh.bfType != (('M'<<8)|'B'))
1917         return FALSE;
1918 
1919     if (FAILED(IStream_Read ( pstm, &bmi->bmiHeader, sizeof(bmi->bmiHeader), NULL)))
1920         return FALSE;
1921 
1922     if ((bmi->bmiHeader.biSize != sizeof(bmi->bmiHeader)))
1923         return FALSE;
1924 
1925     TRACE("width %u, height %u, planes %u, bpp %u\n",
1926           bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1927           bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount);
1928 
1929     bitsperpixel = bmi->bmiHeader.biPlanes * bmi->bmiHeader.biBitCount;
1930     if (bitsperpixel<=8)
1931         palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
1932     else
1933         palspace = 0;
1934 
1935     bmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, bitsperpixel);
1936 
1937     /* read the palette right after the end of the bitmapinfoheader */
1938     if (palspace && FAILED(IStream_Read(pstm, bmi->bmiColors, palspace, NULL)))
1939         goto error;
1940 
1941     bits = Alloc(bmi->bmiHeader.biSizeImage);
1942     if (!bits)
1943         goto error;
1944     if (FAILED(IStream_Read(pstm, bits, bmi->bmiHeader.biSizeImage, NULL)))
1945         goto error;
1946 
1947     if (!StretchDIBits(hdcIml, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1948                   0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
1949                   bits, bmi, DIB_RGB_COLORS, SRCCOPY))
1950         goto error;
1951     result = TRUE;
1952 
1953 error:
1954     Free(bits);
1955     return result;
1956 }
1957 
1958 /*************************************************************************
1959  * ImageList_Read [COMCTL32.@]
1960  *
1961  * Reads an image list from a stream.
1962  *
1963  * PARAMS
1964  *     pstm [I] pointer to a stream
1965  *
1966  * RETURNS
1967  *     Success: handle to image list
1968  *     Failure: NULL
1969  *
1970  * The format is like this:
1971  *      ILHEAD                  ilheadstruct;
1972  *
1973  * for the color image part:
1974  *      BITMAPFILEHEADER        bmfh;
1975  *      BITMAPINFOHEADER        bmih;
1976  * only if it has a palette:
1977  *      RGBQUAD         rgbs[nr_of_paletted_colors];
1978  *
1979  *      BYTE                    colorbits[imagesize];
1980  *
1981  * the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
1982  *      BITMAPFILEHEADER        bmfh_mask;
1983  *      BITMAPINFOHEADER        bmih_mask;
1984  * only if it has a palette (it usually does not):
1985  *      RGBQUAD         rgbs[nr_of_paletted_colors];
1986  *
1987  *      BYTE                    maskbits[imagesize];
1988  */
1989 HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
1990 {
1991     ILHEAD      ilHead;
1992     HIMAGELIST  himl;
1993     int         i;
1994 
1995     TRACE("%p\n", pstm);
1996 
1997     if (FAILED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
1998         return NULL;
1999     if (ilHead.usMagic != (('L' << 8) | 'I'))
2000         return NULL;
2001     if (ilHead.usVersion != 0x101) /* probably version? */
2002         return NULL;
2003 
2004     TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n",
2005           ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
2006 
2007     himl = ImageList_Create(ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
2008     if (!himl)
2009         return NULL;
2010 
2011     if (!_read_bitmap(himl->hdcImage, pstm))
2012     {
2013         WARN("failed to read bitmap from stream\n");
2014         return NULL;
2015     }
2016     if (ilHead.flags & ILC_MASK)
2017     {
2018         if (!_read_bitmap(himl->hdcMask, pstm))
2019         {
2020             WARN("failed to read mask bitmap from stream\n");
2021             return NULL;
2022         }
2023     }
2024 
2025     himl->cCurImage = ilHead.cCurImage;
2026     himl->cMaxImage = ilHead.cMaxImage;
2027 
2028     ImageList_SetBkColor(himl,ilHead.bkcolor);
2029     for (i=0;i<4;i++)
2030         ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2031     return himl;
2032 }
2033 
2034 
2035 /*************************************************************************
2036  * ImageList_Remove [COMCTL32.@]
2037  *
2038  * Removes an image from an image list
2039  *
2040  * PARAMS
2041  *     himl [I] image list handle
2042  *     i    [I] image index
2043  *
2044  * RETURNS
2045  *     Success: TRUE
2046  *     Failure: FALSE
2047  *
2048  * FIXME: as the image list storage test shows, native comctl32 simply shifts
2049  * images without creating a new bitmap.
2050  */
2051 BOOL WINAPI
2052 ImageList_Remove (HIMAGELIST himl, INT i)
2053 {
2054     HBITMAP hbmNewImage, hbmNewMask;
2055     HDC     hdcBmp;
2056     SIZE    sz;
2057 
2058     TRACE("(himl=%p i=%d)\n", himl, i);
2059 
2060     if (!is_valid(himl)) {
2061         ERR("Invalid image list handle!\n");
2062         return FALSE;
2063     }
2064 
2065     if ((i < -1) || (i >= himl->cCurImage)) {
2066         TRACE("index out of range! %d\n", i);
2067         return FALSE;
2068     }
2069 
2070     if (i == -1) {
2071         INT nCount;
2072 
2073         /* remove all */
2074         if (himl->cCurImage == 0) {
2075             /* remove all on empty ImageList is allowed */
2076             TRACE("remove all on empty ImageList!\n");
2077             return TRUE;
2078         }
2079 
2080         himl->cMaxImage = himl->cInitial + himl->cGrow - 1;
2081         himl->cCurImage = 0;
2082         for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2083              himl->nOvlIdx[nCount] = -1;
2084 
2085         hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage, himl->cx);
2086         SelectObject (himl->hdcImage, hbmNewImage);
2087         DeleteObject (himl->hbmImage);
2088         himl->hbmImage = hbmNewImage;
2089 
2090         if (himl->hbmMask) {
2091 
2092             imagelist_get_bitmap_size(himl, himl->cMaxImage, himl->cx, &sz);
2093             hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2094             SelectObject (himl->hdcMask, hbmNewMask);
2095             DeleteObject (himl->hbmMask);
2096             himl->hbmMask = hbmNewMask;
2097         }
2098     }
2099     else {
2100         /* delete one image */
2101         TRACE("Remove single image! %d\n", i);
2102 
2103         /* create new bitmap(s) */
2104         TRACE(" - Number of images: %d / %d (Old/New)\n",
2105                  himl->cCurImage, himl->cCurImage - 1);
2106 
2107         hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage, himl->cx);
2108 
2109         imagelist_get_bitmap_size(himl, himl->cMaxImage, himl->cx, &sz );
2110         if (himl->hbmMask)
2111             hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2112         else
2113             hbmNewMask = 0;  /* Just to keep compiler happy! */
2114 
2115         hdcBmp = CreateCompatibleDC (0);
2116 
2117         /* copy all images and masks prior to the "removed" image */
2118         if (i > 0) {
2119             TRACE("Pre image copy: Copy %d images\n", i);
2120 
2121             SelectObject (hdcBmp, hbmNewImage);
2122             imagelist_copy_images( himl, himl->hdcImage, hdcBmp, 0, i, 0 );
2123 
2124             if (himl->hbmMask) {
2125                 SelectObject (hdcBmp, hbmNewMask);
2126                 imagelist_copy_images( himl, himl->hdcMask, hdcBmp, 0, i, 0 );
2127             }
2128         }
2129 
2130         /* copy all images and masks behind the removed image */
2131         if (i < himl->cCurImage - 1) {
2132             TRACE("Post image copy!\n");
2133 
2134             SelectObject (hdcBmp, hbmNewImage);
2135             imagelist_copy_images( himl, himl->hdcImage, hdcBmp, i + 1,
2136                                    (himl->cCurImage - i), i );
2137 
2138             if (himl->hbmMask) {
2139                 SelectObject (hdcBmp, hbmNewMask);
2140                 imagelist_copy_images( himl, himl->hdcMask, hdcBmp, i + 1,
2141                                        (himl->cCurImage - i), i );
2142             }
2143         }
2144 
2145         DeleteDC (hdcBmp);
2146 
2147         /* delete old images and insert new ones */
2148         SelectObject (himl->hdcImage, hbmNewImage);
2149         DeleteObject (himl->hbmImage);
2150         himl->hbmImage = hbmNewImage;
2151         if (himl->hbmMask) {
2152             SelectObject (himl->hdcMask, hbmNewMask);
2153             DeleteObject (himl->hbmMask);
2154             himl->hbmMask = hbmNewMask;
2155         }
2156 
2157         himl->cCurImage--;
2158     }
2159 
2160     return TRUE;
2161 }
2162 
2163 
2164 /*************************************************************************
2165  * ImageList_Replace [COMCTL32.@]
2166  *
2167  * Replaces an image in an image list with a new image.
2168  *
2169  * PARAMS
2170  *     himl     [I] handle to image list
2171  *     i        [I] image index
2172  *     hbmImage [I] handle to image bitmap
2173  *     hbmMask  [I] handle to mask bitmap. Can be NULL.
2174  *
2175  * RETURNS
2176  *     Success: TRUE
2177  *     Failure: FALSE
2178  */
2179 
2180 BOOL WINAPI
2181 ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2182                    HBITMAP hbmMask)
2183 {
2184     HDC hdcImage;
2185     BITMAP bmp;
2186     HBITMAP hOldBitmap;
2187     POINT pt;
2188 
2189     TRACE("%p %d %p %p\n", himl, i, hbmImage, hbmMask);
2190 
2191     if (!is_valid(himl)) {
2192         ERR("Invalid image list handle!\n");
2193         return FALSE;
2194     }
2195 
2196     if ((i >= himl->cMaxImage) || (i < 0)) {
2197         ERR("Invalid image index!\n");
2198         return FALSE;
2199     }
2200 
2201     if (!GetObjectW(hbmImage, sizeof(BITMAP), &bmp))
2202         return FALSE;
2203 
2204     hdcImage = CreateCompatibleDC (0);
2205 
2206     /* Replace Image */
2207     hOldBitmap = SelectObject (hdcImage, hbmImage);
2208 
2209     imagelist_point_from_index(himl, i, &pt);
2210     StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
2211                   hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2212 
2213     if (himl->hbmMask)
2214     {
2215         HDC hdcTemp;
2216         HBITMAP hOldBitmapTemp;
2217 
2218         hdcTemp   = CreateCompatibleDC(0);
2219         hOldBitmapTemp = SelectObject(hdcTemp, hbmMask);
2220 
2221         StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
2222                       hdcTemp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2223         SelectObject(hdcTemp, hOldBitmapTemp);
2224         DeleteDC(hdcTemp);
2225 
2226         /* Remove the background from the image
2227         */
2228         BitBlt (himl->hdcImage, pt.x, pt.y, bmp.bmWidth, bmp.bmHeight,
2229                 himl->hdcMask, pt.x, pt.y, 0x220326); /* NOTSRCAND */
2230     }
2231 
2232     SelectObject (hdcImage, hOldBitmap);
2233     DeleteDC (hdcImage);
2234 
2235     return TRUE;
2236 }
2237 
2238 
2239 /*************************************************************************
2240  * ImageList_ReplaceIcon [COMCTL32.@]
2241  *
2242  * Replaces an image in an image list using an icon.
2243  *
2244  * PARAMS
2245  *     himl  [I] handle to image list
2246  *     i     [I] image index
2247  *     hIcon [I] handle to icon
2248  *
2249  * RETURNS
2250  *     Success: index of the replaced image
2251  *     Failure: -1
2252  */
2253 
2254 INT WINAPI
2255 ImageList_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon)
2256 {
2257     HDC     hdcImage;
2258     HICON   hBestFitIcon;
2259     HBITMAP hbmOldSrc;
2260     ICONINFO  ii;
2261     BITMAP  bmp;
2262     BOOL    ret;
2263     POINT   pt;
2264 
2265     TRACE("(%p %d %p)\n", himl, nIndex, hIcon);
2266 
2267     if (!is_valid(himl)) {
2268         ERR("invalid image list\n");
2269         return -1;
2270     }
2271     if ((nIndex >= himl->cMaxImage) || (nIndex < -1)) {
2272         ERR("invalid image index %d / %d\n", nIndex, himl->cMaxImage);
2273         return -1;
2274     }
2275 
2276     hBestFitIcon = CopyImage(
2277         hIcon, IMAGE_ICON,
2278         himl->cx, himl->cy,
2279         LR_COPYFROMRESOURCE);
2280     /* the above will fail if the icon wasn't loaded from a resource, so try
2281      * again without LR_COPYFROMRESOURCE flag */
2282     if (!hBestFitIcon)
2283         hBestFitIcon = CopyImage(
2284             hIcon, IMAGE_ICON,
2285             himl->cx, himl->cy,
2286             0);
2287     if (!hBestFitIcon)
2288         return -1;
2289 
2290     ret = GetIconInfo (hBestFitIcon, &ii);
2291     if (!ret) {
2292         DestroyIcon(hBestFitIcon);
2293         return -1;
2294     }
2295 
2296     ret = GetObjectW (ii.hbmMask, sizeof(BITMAP), &bmp);
2297     if (!ret) {
2298         ERR("couldn't get mask bitmap info\n");
2299         if (ii.hbmColor)
2300             DeleteObject (ii.hbmColor);
2301         if (ii.hbmMask)
2302             DeleteObject (ii.hbmMask);
2303         DestroyIcon(hBestFitIcon);
2304         return -1;
2305     }
2306 
2307     if (nIndex == -1) {
2308         if (himl->cCurImage + 1 > himl->cMaxImage)
2309             IMAGELIST_InternalExpandBitmaps (himl, 1, 0, 0);
2310 
2311         nIndex = himl->cCurImage;
2312         himl->cCurImage++;
2313     }
2314 
2315     hdcImage = CreateCompatibleDC (0);
2316     TRACE("hdcImage=%p\n", hdcImage);
2317     if (hdcImage == 0)
2318         ERR("invalid hdcImage!\n");
2319 
2320     imagelist_point_from_index(himl, nIndex, &pt);
2321 
2322     SetTextColor(himl->hdcImage, RGB(0,0,0));
2323     SetBkColor  (himl->hdcImage, RGB(255,255,255));
2324 
2325     if (ii.hbmColor)
2326     {
2327         hbmOldSrc = SelectObject (hdcImage, ii.hbmColor);
2328         StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
2329                     hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2330         if (himl->hbmMask)
2331         {
2332             SelectObject (hdcImage, ii.hbmMask);
2333             StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
2334                         hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2335         }
2336     }
2337     else
2338     {
2339         UINT height = bmp.bmHeight / 2;
2340         hbmOldSrc = SelectObject (hdcImage, ii.hbmMask);
2341         StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
2342                     hdcImage, 0, height, bmp.bmWidth, height, SRCCOPY);
2343         if (himl->hbmMask)
2344             StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
2345                         hdcImage, 0, 0, bmp.bmWidth, height, SRCCOPY);
2346     }
2347 
2348     SelectObject (hdcImage, hbmOldSrc);
2349 
2350     DestroyIcon(hBestFitIcon);
2351     if (hdcImage)
2352         DeleteDC (hdcImage);
2353     if (ii.hbmColor)
2354         DeleteObject (ii.hbmColor);
2355     if (ii.hbmMask)
2356         DeleteObject (ii.hbmMask);
2357 
2358     TRACE("Insert index = %d, himl->cCurImage = %d\n", nIndex, himl->cCurImage);
2359     return nIndex;
2360 }
2361 
2362 
2363 /*************************************************************************
2364  * ImageList_SetBkColor [COMCTL32.@]
2365  *
2366  * Sets the background color of an image list.
2367  *
2368  * PARAMS
2369  *     himl  [I] handle to image list
2370  *     clrBk [I] background color
2371  *
2372  * RETURNS
2373  *     Success: previous background color
2374  *     Failure: CLR_NONE
2375  */
2376 
2377 COLORREF WINAPI
2378 ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2379 {
2380     COLORREF clrOldBk;
2381 
2382     if (!is_valid(himl))
2383         return CLR_NONE;
2384 
2385     clrOldBk = himl->clrBk;
2386     himl->clrBk = clrBk;
2387     return clrOldBk;
2388 }
2389 
2390 
2391 /*************************************************************************
2392  * ImageList_SetDragCursorImage [COMCTL32.@]
2393  *
2394  * Combines the specified image with the current drag image
2395  *
2396  * PARAMS
2397  *     himlDrag  [I] handle to drag image list
2398  *     iDrag     [I] drag image index
2399  *     dxHotspot [I] X position of the hot spot
2400  *     dyHotspot [I] Y position of the hot spot
2401  *
2402  * RETURNS
2403  *     Success: TRUE
2404  *     Failure: FALSE
2405  *
2406  * NOTES
2407  *   - The names dxHotspot, dyHotspot are misleading because they have nothing
2408  *     to do with a hotspot but are only the offset of the origin of the new
2409  *     image relative to the origin of the old image.
2410  *
2411  *   - When this function is called and the drag image is visible, a
2412  *     short flickering occurs but this matches the Win9x behavior. It is
2413  *     possible to fix the flickering using code like in ImageList_DragMove.
2414  */
2415 
2416 BOOL WINAPI
2417 ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2418                               INT dxHotspot, INT dyHotspot)
2419 {
2420     HIMAGELIST himlTemp;
2421     BOOL visible;
2422 
2423     if (!is_valid(InternalDrag.himl) || !is_valid(himlDrag))
2424         return FALSE;
2425 
2426     TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2427            dxHotspot, dyHotspot, InternalDrag.dxHotspot, InternalDrag.dyHotspot);
2428 
2429     visible = InternalDrag.bShow;
2430 
2431     himlTemp = ImageList_Merge (InternalDrag.himl, 0, himlDrag, iDrag,
2432                                 dxHotspot, dyHotspot);
2433 
2434     if (visible) {
2435         /* hide the drag image */
2436         ImageList_DragShowNolock(FALSE);
2437     }
2438     if ((InternalDrag.himl->cx != himlTemp->cx) ||
2439            (InternalDrag.himl->cy != himlTemp->cy)) {
2440         /* the size of the drag image changed, invalidate the buffer */
2441         DeleteObject(InternalDrag.hbmBg);
2442         InternalDrag.hbmBg = 0;
2443     }
2444 
2445     ImageList_Destroy (InternalDrag.himl);
2446     InternalDrag.himl = himlTemp;
2447 
2448     if (visible) {
2449         /* show the drag image */
2450         ImageList_DragShowNolock(TRUE);
2451     }
2452 
2453     return TRUE;
2454 }
2455 
2456 
2457 /*************************************************************************
2458  * ImageList_SetFilter [COMCTL32.@]
2459  *
2460  * Sets a filter (or does something completely different)!!???
2461  * It removes 12 Bytes from the stack (3 Parameters).
2462  *
2463  * PARAMS
2464  *     himl     [I] SHOULD be a handle to image list
2465  *     i        [I] COULD be an index?
2466  *     dwFilter [I] ???
2467  *
2468  * RETURNS
2469  *     Success: TRUE ???
2470  *     Failure: FALSE ???
2471  *
2472  * BUGS
2473  *     This is an UNDOCUMENTED function!!!!
2474  *     empty stub.
2475  */
2476 
2477 BOOL WINAPI
2478 ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2479 {
2480     FIXME("(%p 0x%x 0x%x):empty stub!\n", himl, i, dwFilter);
2481 
2482     return FALSE;
2483 }
2484 
2485 
2486 /*************************************************************************
2487  * ImageList_SetFlags [COMCTL32.@]
2488  *
2489  * Sets the image list flags.
2490  *
2491  * PARAMS
2492  *     himl  [I] Handle to image list
2493  *     flags [I] Flags to set
2494  *
2495  * RETURNS
2496  *     Old flags?
2497  *
2498  * BUGS
2499  *    Stub.
2500  */
2501 
2502 DWORD WINAPI
2503 ImageList_SetFlags(HIMAGELIST himl, DWORD flags)
2504 {
2505     FIXME("(%p %08x):empty stub\n", himl, flags);
2506     return 0;
2507 }
2508 
2509 
2510 /*************************************************************************
2511  * ImageList_SetIconSize [COMCTL32.@]
2512  *
2513  * Sets the image size of the bitmap and deletes all images.
2514  *
2515  * PARAMS
2516  *     himl [I] handle to image list
2517  *     cx   [I] image width
2518  *     cy   [I] image height
2519  *
2520  * RETURNS
2521  *     Success: TRUE
2522  *     Failure: FALSE
2523  */
2524 
2525 BOOL WINAPI
2526 ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2527 {
2528     INT nCount;
2529     HBITMAP hbmNew;
2530 
2531     if (!is_valid(himl))
2532         return FALSE;
2533 
2534     /* remove all images */
2535     himl->cMaxImage = himl->cInitial + 1;
2536     himl->cCurImage = 0;
2537     himl->cx        = cx;
2538     himl->cy        = cy;
2539 
2540     /* initialize overlay mask indices */
2541     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2542         himl->nOvlIdx[nCount] = -1;
2543 
2544     hbmNew = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage, himl->cx);
2545     SelectObject (himl->hdcImage, hbmNew);
2546     DeleteObject (himl->hbmImage);
2547     himl->hbmImage = hbmNew;
2548 
2549     if (himl->hbmMask) {
2550         SIZE sz;
2551         imagelist_get_bitmap_size(himl, himl->cMaxImage, himl->cx, &sz);
2552         hbmNew = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2553         SelectObject (himl->hdcMask, hbmNew);
2554         DeleteObject (himl->hbmMask);
2555         himl->hbmMask = hbmNew;
2556     }
2557 
2558     return TRUE;
2559 }
2560 
2561 
2562 /*************************************************************************
2563  * ImageList_SetImageCount [COMCTL32.@]
2564  *
2565  * Resizes an image list to the specified number of images.
2566  *
2567  * PARAMS
2568  *     himl        [I] handle to image list
2569  *     iImageCount [I] number of images in the image list
2570  *
2571  * RETURNS
2572  *     Success: TRUE
2573  *     Failure: FALSE
2574  */
2575 
2576 BOOL WINAPI
2577 ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount)
2578 {
2579     HDC     hdcBitmap;
2580     HBITMAP hbmNewBitmap, hbmOld;
2581     INT     nNewCount, nCopyCount;
2582 
2583     TRACE("%p %d\n",himl,iImageCount);
2584 
2585     if (!is_valid(himl))
2586         return FALSE;
2587     if (himl->cMaxImage > iImageCount)
2588     {
2589         himl->cCurImage = iImageCount;
2590         /* TODO: shrink the bitmap when cMaxImage-cCurImage>cGrow ? */
2591         return TRUE;
2592     }
2593 
2594     nNewCount = iImageCount + himl->cGrow;
2595     nCopyCount = min(himl->cCurImage, iImageCount);
2596 
2597     hdcBitmap = CreateCompatibleDC (0);
2598 
2599     hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount, himl->cx);
2600 
2601     if (hbmNewBitmap != 0)
2602     {
2603         hbmOld = SelectObject (hdcBitmap, hbmNewBitmap);
2604         imagelist_copy_images( himl, himl->hdcImage, hdcBitmap, 0, nCopyCount, 0 );
2605         SelectObject (hdcBitmap, hbmOld);
2606 
2607         /* FIXME: delete 'empty' image space? */
2608 
2609         SelectObject (himl->hdcImage, hbmNewBitmap);
2610         DeleteObject (himl->hbmImage);
2611         himl->hbmImage = hbmNewBitmap;
2612     }
2613     else
2614         ERR("Could not create new image bitmap !\n");
2615 
2616     if (himl->hbmMask)
2617     {
2618         SIZE sz;
2619         imagelist_get_bitmap_size( himl, nNewCount, himl->cx, &sz );
2620         hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2621         if (hbmNewBitmap != 0)
2622         {
2623             hbmOld = SelectObject (hdcBitmap, hbmNewBitmap);
2624             imagelist_copy_images( himl, himl->hdcMask, hdcBitmap, 0, nCopyCount, 0 );
2625             SelectObject (hdcBitmap, hbmOld);
2626 
2627             /* FIXME: delete 'empty' image space? */
2628 
2629             SelectObject (himl->hdcMask, hbmNewBitmap);
2630             DeleteObject (himl->hbmMask);
2631             himl->hbmMask = hbmNewBitmap;
2632         }
2633         else
2634             ERR("Could not create new mask bitmap!\n");
2635     }
2636 
2637     DeleteDC (hdcBitmap);
2638 
2639     /* Update max image count and current image count */
2640     himl->cMaxImage = nNewCount;
2641     himl->cCurImage = iImageCount;
2642 
2643     return TRUE;
2644 }
2645 
2646 
2647 /*************************************************************************
2648  * ImageList_SetOverlayImage [COMCTL32.@]
2649  *
2650  * Assigns an overlay mask index to an existing image in an image list.
2651  *
2652  * PARAMS
2653  *     himl     [I] handle to image list
2654  *     iImage   [I] image index
2655  *     iOverlay [I] overlay mask index
2656  *
2657  * RETURNS
2658  *     Success: TRUE
2659  *     Failure: FALSE
2660  */
2661 
2662 BOOL WINAPI
2663 ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2664 {
2665     if (!is_valid(himl))
2666         return FALSE;
2667     if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2668         return FALSE;
2669     if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2670         return FALSE;
2671     himl->nOvlIdx[iOverlay - 1] = iImage;
2672     return TRUE;
2673 }
2674 
2675 
2676 
2677 /* helper for ImageList_Write - write bitmap to pstm
2678  * currently everything is written as 24 bit RGB, except masks
2679  */
2680 static BOOL
2681 _write_bitmap(HBITMAP hBitmap, LPSTREAM pstm)
2682 {
2683     LPBITMAPFILEHEADER bmfh;
2684     LPBITMAPINFOHEADER bmih;
2685     LPBYTE data = NULL, lpBits;
2686     BITMAP bm;
2687     INT bitCount, sizeImage, offBits, totalSize;
2688     HDC xdc;
2689     BOOL result = FALSE;
2690 
2691     if (!GetObjectW(hBitmap, sizeof(BITMAP), &bm))
2692         return FALSE;
2693 
2694     bitCount = bm.bmBitsPixel == 1 ? 1 : 24;
2695     sizeImage = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, bitCount);
2696 
2697     totalSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
2698     if(bitCount != 24)
2699         totalSize += (1 << bitCount) * sizeof(RGBQUAD);
2700     offBits = totalSize;
2701     totalSize += sizeImage;
2702 
2703     data = Alloc(totalSize);
2704     bmfh = (LPBITMAPFILEHEADER)data;
2705     bmih = (LPBITMAPINFOHEADER)(data + sizeof(BITMAPFILEHEADER));
2706     lpBits = data + offBits;
2707 
2708     /* setup BITMAPFILEHEADER */
2709     bmfh->bfType      = (('M' << 8) | 'B');
2710     bmfh->bfSize      = offBits;
2711     bmfh->bfReserved1 = 0;
2712     bmfh->bfReserved2 = 0;
2713     bmfh->bfOffBits   = offBits;
2714 
2715     /* setup BITMAPINFOHEADER */
2716     bmih->biSize          = sizeof(BITMAPINFOHEADER);
2717     bmih->biWidth         = bm.bmWidth;
2718     bmih->biHeight        = bm.bmHeight;
2719     bmih->biPlanes        = 1;
2720     bmih->biBitCount      = bitCount;
2721     bmih->biCompression   = BI_RGB;
2722     bmih->biSizeImage     = sizeImage;
2723     bmih->biXPelsPerMeter = 0;
2724     bmih->biYPelsPerMeter = 0;
2725     bmih->biClrUsed       = 0;
2726     bmih->biClrImportant  = 0;
2727 
2728     xdc = GetDC(0);
2729     result = GetDIBits(xdc, hBitmap, 0, bm.bmHeight, lpBits, (BITMAPINFO *)bmih, DIB_RGB_COLORS) == bm.bmHeight;
2730     ReleaseDC(0, xdc);
2731     if (!result)
2732         goto failed;
2733 
2734     TRACE("width %u, height %u, planes %u, bpp %u\n",
2735           bmih->biWidth, bmih->biHeight,
2736           bmih->biPlanes, bmih->biBitCount);
2737 
2738     if(bitCount == 1) {
2739         /* Hack. */
2740         LPBITMAPINFO inf = (LPBITMAPINFO)bmih;
2741         inf->bmiColors[0].rgbRed = inf->bmiColors[0].rgbGreen = inf->bmiColors[0].rgbBlue = 0;
2742         inf->bmiColors[1].rgbRed = inf->bmiColors[1].rgbGreen = inf->bmiColors[1].rgbBlue = 0xff;
2743     }
2744 
2745     if(FAILED(IStream_Write(pstm, data, totalSize, NULL)))
2746         goto failed;
2747 
2748     result = TRUE;
2749 
2750 failed:
2751     Free(data);
2752 
2753     return result;
2754 }
2755 
2756 
2757 /*************************************************************************
2758  * ImageList_Write [COMCTL32.@]
2759  *
2760  * Writes an image list to a stream.
2761  *
2762  * PARAMS
2763  *     himl [I] handle to image list
2764  *     pstm [O] Pointer to a stream.
2765  *
2766  * RETURNS
2767  *     Success: TRUE
2768  *     Failure: FALSE
2769  *
2770  * BUGS
2771  *     probably.
2772  */
2773 
2774 BOOL WINAPI
2775 ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
2776 {
2777     ILHEAD ilHead;
2778     int i;
2779 
2780     TRACE("%p %p\n", himl, pstm);
2781 
2782     if (!is_valid(himl))
2783         return FALSE;
2784 
2785     ilHead.usMagic   = (('L' << 8) | 'I');
2786     ilHead.usVersion = 0x101;
2787     ilHead.cCurImage = himl->cCurImage;
2788     ilHead.cMaxImage = himl->cMaxImage;
2789     ilHead.cGrow     = himl->cGrow;
2790     ilHead.cx        = himl->cx;
2791     ilHead.cy        = himl->cy;
2792     ilHead.bkcolor   = himl->clrBk;
2793     ilHead.flags     = himl->flags;
2794     for(i = 0; i < 4; i++) {
2795         ilHead.ovls[i] = himl->nOvlIdx[i];
2796     }
2797 
2798     TRACE("cx %u, cy %u, flags 0x04%x, cCurImage %u, cMaxImage %u\n",
2799           ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
2800 
2801     if(FAILED(IStream_Write(pstm, &ilHead, sizeof(ILHEAD), NULL)))
2802         return FALSE;
2803 
2804     /* write the bitmap */
2805     if(!_write_bitmap(himl->hbmImage, pstm))
2806         return FALSE;
2807 
2808     /* write the mask if we have one */
2809     if(himl->flags & ILC_MASK) {
2810         if(!_write_bitmap(himl->hbmMask, pstm))
2811             return FALSE;
2812     }
2813 
2814     return TRUE;
2815 }
2816 
2817 
2818 static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count, UINT width)
2819 {
2820     HBITMAP hbmNewBitmap;
2821     UINT ilc = (himl->flags & 0xFE);
2822     SIZE sz;
2823 
2824     imagelist_get_bitmap_size( himl, count, width, &sz );
2825 
2826     if ((ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) || ilc == ILC_COLOR)
2827     {
2828         VOID* bits;
2829         BITMAPINFO *bmi;
2830 
2831         TRACE("Creating DIBSection %d x %d, %d Bits per Pixel\n",
2832               sz.cx, sz.cy, himl->uBitsPixel);
2833 
2834         if (himl->uBitsPixel <= ILC_COLOR8)
2835         {
2836             LPPALETTEENTRY pal;
2837             ULONG i, colors;
2838             BYTE temp;
2839 
2840             colors = 1 << himl->uBitsPixel;
2841             bmi = Alloc(sizeof(BITMAPINFOHEADER) +
2842                             sizeof(PALETTEENTRY) * colors);
2843 
2844             pal = (LPPALETTEENTRY)bmi->bmiColors;
2845             GetPaletteEntries(GetStockObject(DEFAULT_PALETTE), 0, colors, pal);
2846 
2847             /* Swap colors returned by GetPaletteEntries so we can use them for
2848              * CreateDIBSection call. */
2849             for (i = 0; i < colors; i++)
2850             {
2851                 temp = pal[i].peBlue;
2852                 bmi->bmiColors[i].rgbRed = pal[i].peRed;
2853                 bmi->bmiColors[i].rgbBlue = temp;
2854             }
2855         }
2856         else
2857         {
2858             bmi = Alloc(sizeof(BITMAPINFOHEADER));
2859         }
2860 
2861         bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2862         bmi->bmiHeader.biWidth = sz.cx;
2863         bmi->bmiHeader.biHeight = sz.cy;
2864         bmi->bmiHeader.biPlanes = 1;
2865         bmi->bmiHeader.biBitCount = himl->uBitsPixel;
2866         bmi->bmiHeader.biCompression = BI_RGB;
2867         bmi->bmiHeader.biSizeImage = 0;
2868         bmi->bmiHeader.biXPelsPerMeter = 0;
2869         bmi->bmiHeader.biYPelsPerMeter = 0;
2870         bmi->bmiHeader.biClrUsed = 0;
2871         bmi->bmiHeader.biClrImportant = 0;
2872 
2873         hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, &bits, 0, 0);
2874 
2875         Free (bmi);
2876     }
2877     else /*if (ilc == ILC_COLORDDB)*/
2878     {
2879         TRACE("Creating Bitmap: %d Bits per Pixel\n", himl->uBitsPixel);
2880 
2881         hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, himl->uBitsPixel, NULL);
2882     }
2883     TRACE("returning %p\n", hbmNewBitmap);
2884     return hbmNewBitmap;
2885 }
2886 
2887 /*************************************************************************
2888  * ImageList_SetColorTable [COMCTL32.@]
2889  *
2890  * Sets the color table of an image list.
2891  *
2892  * PARAMS
2893  *     himl        [I] Handle to the image list.
2894  *     uStartIndex [I] The first index to set.
2895  *     cEntries    [I] Number of entries to set.
2896  *     prgb        [I] New color information for color table for the image list.
2897  *
2898  * RETURNS
2899  *     Success: Number of entries in the table that were set.
2900  *     Failure: Zero.
2901  *
2902  * SEE
2903  *     ImageList_Create(), SetDIBColorTable()
2904  */
2905 
2906 UINT WINAPI
2907 ImageList_SetColorTable (HIMAGELIST himl, UINT uStartIndex, UINT cEntries, CONST RGBQUAD * prgb)
2908 {
2909     return SetDIBColorTable(himl->hdcImage, uStartIndex, cEntries, prgb);
2910 }
2911 
2912 /*************************************************************************
2913  * ImageList_CoCreateInstance [COMCTL32.@]
2914  *
2915  * Creates a new imagelist instance and returns an interface pointer to it.
2916  *
2917  * PARAMS
2918  *     rclsid      [I] A reference to the CLSID (CLSID_ImageList).
2919  *     punkOuter   [I] Pointer to IUnknown interface for aggregation, if desired
2920  *     riid        [I] Identifier of the requested interface.
2921  *     ppv         [O] Returns the address of the pointer requested, or NULL.
2922  *
2923  * RETURNS
2924  *     Success: S_OK.
2925  *     Failure: Error value.
2926  */
2927 HRESULT WINAPI
2928 ImageList_CoCreateInstance (REFCLSID rclsid, const IUnknown *punkOuter, REFIID riid, void **ppv)
2929 {
2930     TRACE("(%s,%p,%s,%p)\n", debugstr_guid(rclsid), punkOuter, debugstr_guid(riid), ppv);
2931 
2932     if (!IsEqualCLSID(&CLSID_ImageList, rclsid))
2933         return E_NOINTERFACE;
2934 
2935     return ImageListImpl_CreateInstance(punkOuter, riid, ppv);
2936 }
2937 
2938 
2939 /*************************************************************************
2940  * IImageList implementation
2941  */
2942 
2943 static HRESULT WINAPI ImageListImpl_QueryInterface(IImageList *iface,
2944     REFIID iid, void **ppv)
2945 {
2946     HIMAGELIST This = (HIMAGELIST) iface;
2947     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
2948 
2949     if (!ppv) return E_INVALIDARG;
2950 
2951     if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IImageList, iid))
2952         *ppv = This;
2953     else
2954     {
2955         *ppv = NULL;
2956         return E_NOINTERFACE;
2957     }
2958 
2959     IUnknown_AddRef((IUnknown*)*ppv);
2960     return S_OK;
2961 }
2962 
2963 static ULONG WINAPI ImageListImpl_AddRef(IImageList *iface)
2964 {
2965     HIMAGELIST This = (HIMAGELIST) iface;
2966     ULONG ref = InterlockedIncrement(&This->ref);
2967 
2968     TRACE("(%p) refcount=%u\n", iface, ref);
2969     return ref;
2970 }
2971 
2972 static ULONG WINAPI ImageListImpl_Release(IImageList *iface)
2973 {
2974     HIMAGELIST This = (HIMAGELIST) iface;
2975     ULONG ref = InterlockedDecrement(&This->ref);
2976 
2977     TRACE("(%p) refcount=%u\n", iface, ref);
2978 
2979     if (ref == 0)
2980         HeapFree(GetProcessHeap(), 0, This);
2981 
2982     return ref;
2983 }
2984 
2985 static HRESULT WINAPI ImageListImpl_Add(IImageList *iface, HBITMAP hbmImage,
2986     HBITMAP hbmMask, int *pi)
2987 {
2988     FIXME("STUB: %p %p %p %p\n", iface, hbmImage, hbmMask, pi);
2989     return E_NOTIMPL;
2990 }
2991 
2992 static HRESULT WINAPI ImageListImpl_ReplaceIcon(IImageList *iface, int i,
2993     HICON hicon, int *pi)
2994 {
2995     FIXME("STUB: %p %d %p %p\n", iface, i, hicon, pi);
2996     return E_NOTIMPL;
2997 }
2998 
2999 static HRESULT WINAPI ImageListImpl_SetOverlayImage(IImageList *iface,
3000     int iImage, int iOverlay)
3001 {
3002     FIXME("STUB: %p %d %d\n", iface, iImage, iOverlay);
3003     return E_NOTIMPL;
3004 }
3005 
3006 static HRESULT WINAPI ImageListImpl_Replace(IImageList *iface, int i,
3007     HBITMAP hbmImage, HBITMAP hbmMask)
3008 {
3009     FIXME("STUB: %p %d %p %p\n", iface, i, hbmImage, hbmMask);
3010     return E_NOTIMPL;
3011 }
3012 
3013 static HRESULT WINAPI ImageListImpl_AddMasked(IImageList *iface, HBITMAP hbmImage,
3014     COLORREF crMask, int *pi)
3015 {
3016     FIXME("STUB: %p %p %x %p\n", iface, hbmImage, crMask, pi);
3017     return E_NOTIMPL;
3018 }
3019 
3020 static HRESULT WINAPI ImageListImpl_Draw(IImageList *iface,
3021     IMAGELISTDRAWPARAMS *pimldp)
3022 {
3023     FIXME("STUB: %p %p\n", iface, pimldp);
3024     return E_NOTIMPL;
3025 }
3026 
3027 static HRESULT WINAPI ImageListImpl_Remove(IImageList *iface, int i)
3028 {
3029     FIXME("STUB: %p %d\n", iface, i);
3030     return E_NOTIMPL;
3031 }
3032 
3033 static HRESULT WINAPI ImageListImpl_GetIcon(IImageList *iface, int i, UINT flags,
3034     HICON *picon)
3035 {
3036     FIXME("STUB: %p %d %x %p\n", iface, i, flags, picon);
3037     return E_NOTIMPL;
3038 }
3039 
3040 static HRESULT WINAPI ImageListImpl_GetImageInfo(IImageList *iface, int i,
3041     IMAGEINFO *pImageInfo)
3042 {
3043     FIXME("STUB: %p %d %p\n", iface, i, pImageInfo);
3044     return E_NOTIMPL;
3045 }
3046 
3047 static HRESULT WINAPI ImageListImpl_Copy(IImageList *iface, int iDst,
3048     IUnknown *punkSrc, int iSrc, UINT uFlags)
3049 {
3050     FIXME("STUB: %p %d %p %d %x\n", iface, iDst, punkSrc, iSrc, uFlags);
3051     return E_NOTIMPL;
3052 }
3053 
3054 static HRESULT WINAPI ImageListImpl_Merge(IImageList *iface, int i1,
3055     IUnknown *punk2, int i2, int dx, int dy, REFIID riid, PVOID *ppv)
3056 {
3057     FIXME("STUB: %p %d %p %d %d %d %s %p\n", iface, i1, punk2, i2, dx, dy,
3058         debugstr_guid(riid), ppv);
3059     return E_NOTIMPL;
3060 }
3061 
3062 static HRESULT WINAPI ImageListImpl_Clone(IImageList *iface, REFIID riid,
3063     PVOID *ppv)
3064 {
3065     FIXME("STUB: %p %s %p\n", iface, debugstr_guid(riid), ppv);
3066     return E_NOTIMPL;
3067 }
3068 
3069 static HRESULT WINAPI ImageListImpl_GetImageRect(IImageList *iface, int i,
3070     RECT *prc)
3071 {
3072     FIXME("STUB: %p %d %p\n", iface, i, prc);
3073     return E_NOTIMPL;
3074 }
3075 
3076 static HRESULT WINAPI ImageListImpl_GetIconSize(IImageList *iface, int *cx,
3077     int *cy)
3078 {
3079     FIXME("STUB: %p %p %p\n", iface, cx, cy);
3080     return E_NOTIMPL;
3081 }
3082 
3083 static HRESULT WINAPI ImageListImpl_SetIconSize(IImageList *iface, int cx,
3084     int cy)
3085 {
3086     FIXME("STUB: %p %d %d\n", iface, cx, cy);
3087     return E_NOTIMPL;
3088 }
3089 
3090 static HRESULT WINAPI ImageListImpl_GetImageCount(IImageList *iface, int *pi)
3091 {
3092     FIXME("STUB: %p %p\n", iface, pi);
3093     return E_NOTIMPL;
3094 }
3095 
3096 static HRESULT WINAPI ImageListImpl_SetImageCount(IImageList *iface,
3097     UINT uNewCount)
3098 {
3099     FIXME("STUB: %p %d\n", iface, uNewCount);
3100     return E_NOTIMPL;
3101 }
3102 
3103 static HRESULT WINAPI ImageListImpl_SetBkColor(IImageList *iface, COLORREF clrBk,
3104     COLORREF *pclr)
3105 {
3106     FIXME("STUB: %p %x %p\n", iface, clrBk, pclr);
3107     return E_NOTIMPL;
3108 }
3109 
3110 static HRESULT WINAPI ImageListImpl_GetBkColor(IImageList *iface, COLORREF *pclr)
3111 {
3112     FIXME("STUB: %p %p\n", iface, pclr);
3113     return E_NOTIMPL;
3114 }
3115 
3116 static HRESULT WINAPI ImageListImpl_BeginDrag(IImageList *iface, int iTrack,
3117     int dxHotspot, int dyHotspot)
3118 {
3119     FIXME("STUB: %p %d %d %d\n", iface, iTrack, dxHotspot, dyHotspot);
3120     return E_NOTIMPL;
3121 }
3122 
3123 static HRESULT WINAPI ImageListImpl_EndDrag(IImageList *iface)
3124 {
3125     FIXME("STUB: %p\n", iface);
3126     return E_NOTIMPL;
3127 }
3128 
3129 static HRESULT WINAPI ImageListImpl_DragEnter(IImageList *iface, HWND hwndLock,
3130     int x, int y)
3131 {
3132     FIXME("STUB: %p %p %d %d\n", iface, hwndLock, x, y);
3133     return E_NOTIMPL;
3134 }
3135 
3136 static HRESULT WINAPI ImageListImpl_DragLeave(IImageList *iface, HWND hwndLock)
3137 {
3138     FIXME("STUB: %p %p\n", iface, hwndLock);
3139     return E_NOTIMPL;
3140 }
3141 
3142 static HRESULT WINAPI ImageListImpl_DragMove(IImageList *iface, int x, int y)
3143 {
3144     FIXME("STUB: %p %d %d\n", iface, x, y);
3145     return E_NOTIMPL;
3146 }
3147 
3148 static HRESULT WINAPI ImageListImpl_SetDragCursorImage(IImageList *iface,
3149     IUnknown *punk, int iDrag, int dxHotspot, int dyHotspot)
3150 {
3151     FIXME("STUB: %p %p %d %d %d\n", iface, punk, iDrag, dxHotspot, dyHotspot);
3152     return E_NOTIMPL;
3153 }
3154 
3155 static HRESULT WINAPI ImageListImpl_DragShowNolock(IImageList *iface, BOOL fShow)
3156 {
3157     FIXME("STUB: %p %d\n", iface, fShow);
3158     return E_NOTIMPL;
3159 }
3160 
3161 static HRESULT WINAPI ImageListImpl_GetDragImage(IImageList *iface, POINT *ppt,
3162     POINT *pptHotspot, REFIID riid, PVOID *ppv)
3163 {
3164     FIXME("STUB: %p %p %p %s %p\n", iface, ppt, pptHotspot, debugstr_guid(riid),
3165         ppv);
3166     return E_NOTIMPL;
3167 }
3168 
3169 static HRESULT WINAPI ImageListImpl_GetItemFlags(IImageList *iface, int i,
3170     DWORD *dwFlags)
3171 {
3172     FIXME("STUB: %p %d %p\n", iface, i, dwFlags);
3173     return E_NOTIMPL;
3174 }
3175 
3176 static HRESULT WINAPI ImageListImpl_GetOverlayImage(IImageList *iface, int iOverlay,
3177     int *piIndex)
3178 {
3179     FIXME("STUB: %p %d %p\n", iface, iOverlay, piIndex);
3180     return E_NOTIMPL;
3181 }
3182 
3183 
3184 static const IImageListVtbl ImageListImpl_Vtbl = {
3185     ImageListImpl_QueryInterface,
3186     ImageListImpl_AddRef,
3187     ImageListImpl_Release,
3188     ImageListImpl_Add,
3189     ImageListImpl_ReplaceIcon,
3190     ImageListImpl_SetOverlayImage,
3191     ImageListImpl_Replace,
3192     ImageListImpl_AddMasked,
3193     ImageListImpl_Draw,
3194     ImageListImpl_Remove,
3195     ImageListImpl_GetIcon,
3196     ImageListImpl_GetImageInfo,
3197     ImageListImpl_Copy,
3198     ImageListImpl_Merge,
3199     ImageListImpl_Clone,
3200     ImageListImpl_GetImageRect,
3201     ImageListImpl_GetIconSize,
3202     ImageListImpl_SetIconSize,
3203     ImageListImpl_GetImageCount,
3204     ImageListImpl_SetImageCount,
3205     ImageListImpl_SetBkColor,
3206     ImageListImpl_GetBkColor,
3207     ImageListImpl_BeginDrag,
3208     ImageListImpl_EndDrag,
3209     ImageListImpl_DragEnter,
3210     ImageListImpl_DragLeave,
3211     ImageListImpl_DragMove,
3212     ImageListImpl_SetDragCursorImage,
3213     ImageListImpl_DragShowNolock,
3214     ImageListImpl_GetDragImage,
3215     ImageListImpl_GetItemFlags,
3216     ImageListImpl_GetOverlayImage
3217 };
3218 
3219 /*************************************************************************
3220  * HIMAGELIST_QueryInterface [COMCTL32.@]
3221  *
3222  * Returns a pointer to an IImageList or IImageList2 object for the given
3223  * HIMAGELIST.
3224  *
3225  * PARAMS
3226  *     himl        [I] Image list handle.
3227  *     riid        [I] Identifier of the requested interface.
3228  *     ppv         [O] Returns the address of the pointer requested, or NULL.
3229  *
3230  * RETURNS
3231  *     Success: S_OK.
3232  *     Failure: Error value.
3233  */
3234 HRESULT WINAPI
3235 HIMAGELIST_QueryInterface (HIMAGELIST himl, REFIID riid, void **ppv)
3236 {
3237     TRACE("(%p,%s,%p)\n", himl, debugstr_guid(riid), ppv);
3238     return IImageList_QueryInterface((IImageList *) himl, riid, ppv);
3239 }
3240 
3241 static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv)
3242 {
3243     HIMAGELIST This;
3244     HRESULT ret;
3245 
3246     TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
3247 
3248     *ppv = NULL;
3249 
3250     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
3251 
3252     This = HeapAlloc(GetProcessHeap(), 0, sizeof(struct _IMAGELIST));
3253     if (!This) return E_OUTOFMEMORY;
3254 
3255     ZeroMemory(This, sizeof(struct _IMAGELIST));
3256 
3257     This->lpVtbl = &ImageListImpl_Vtbl;
3258     This->ref = 1;
3259 
3260     ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
3261     IUnknown_Release((IUnknown*)This);
3262 
3263     return ret;
3264 }
3265 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.