[COMCTL32] imagelist: Make the exported functions use the internal IImageList2
[reactos.git] / dll / win32 / comctl32 / imagelist.c
index 66cd03d..11ad508 100644 (file)
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
- * NOTE
- *
- * This code was audited for completeness against the documented features
- * of Comctl32.dll version 6.0 on Sep. 12, 2002, by Dimitrie O. Paun.
- *
- * Unless otherwise noted, we believe this code to be complete, as per
- * the specification mentioned above.
- * If you discover missing features, or bugs, please note them below.
- *
  *  TODO:
  *    - Add support for ILD_PRESERVEALPHA, ILD_SCALE, ILD_DPISCALE
- *    - Add support for ILS_GLOW, ILS_SHADOW, ILS_SATURATE
+ *    - Add support for ILS_GLOW, ILS_SHADOW
  *    - Thread-safe locking
  */
 
 #include "commctrl.h"
 #include "comctl32.h"
 #include "commoncontrols.h"
-#include "imagelist.h"
 #include "wine/debug.h"
+#include "wine/exception.h"
+#include "wine/heap.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(imagelist);
 
-
 #define MAX_OVERLAYIMAGE 15
 
+#ifdef __REACTOS__
+//The big bad reactos image list hack!
+BOOL is_valid2(HIMAGELIST himl);
+INT WINAPI Internal_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon);
+BOOL WINAPI Internal_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp);
+COLORREF WINAPI Internal_SetBkColor (HIMAGELIST himl, COLORREF clrBk);
+BOOL WINAPI Internal_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay);
+
+#define ImageList_Add Internal_Add
+#define ImageList_ReplaceIcon Internal_ReplaceIcon
+#define ImageList_SetOverlayImage Internal_SetOverlayImage
+#define ImageList_Replace Internal_Replace
+#define ImageList_AddMasked Internal_AddMasked
+#define ImageList_Remove Internal_Remove
+#define ImageList_GetIcon Internal_GetIcon
+#define ImageList_GetImageInfo Internal_GetImageInfo
+#define ImageList_Copy Internal_Copy
+#define ImageList_Merge Internal_Merge
+#define ImageList_Duplicate Internal_Duplicate
+#define ImageList_GetIconSize Internal_GetIconSize
+#define ImageList_SetIconSize Internal_SetIconSize
+#define ImageList_GetImageCount Internal_GetImageCount
+#define ImageList_SetImageCount Internal_SetImageCount
+#define ImageList_SetBkColor Internal_SetBkColor
+#define ImageList_GetBkColor Internal_GetBkColor
+#define ImageList_BeginDrag Internal_BeginDrag
+#define ImageList_DrawIndirect Internal_DrawIndirect
+#endif
+
+struct _IMAGELIST
+{
+    IImageList2 IImageList2_iface;         /* 00: IImageList vtable */
+    INT         cCurImage;                 /* 04: ImageCount */
+    INT         cMaxImage;                 /* 08: maximages */
+    INT         cGrow;                     /* 0C: cGrow */
+    INT         cx;                        /* 10: cx */
+    INT         cy;                        /* 14: cy */
+    DWORD       x4;
+    UINT        flags;                     /* 1C: flags */
+    COLORREF    clrFg;                     /* 20: foreground color */
+    COLORREF    clrBk;                     /* 24: background color */
+
+
+    HBITMAP     hbmImage;                  /* 28: images Bitmap */
+    HBITMAP     hbmMask;                   /* 2C: masks  Bitmap */
+    HDC         hdcImage;                  /* 30: images MemDC  */
+    HDC         hdcMask;                   /* 34: masks  MemDC  */
+    INT         nOvlIdx[MAX_OVERLAYIMAGE]; /* 38: overlay images index */
+
+    /* not yet found out */
+    #ifdef __REACTOS__
+    ULONG   usMagic;
+    #endif
+    HBRUSH  hbrBlend25;
+    HBRUSH  hbrBlend50;
+    INT     cInitial;
+    UINT    uBitsPixel;
+    char   *has_alpha;
+    BOOL    color_table_set;
+
+    LONG        ref;                       /* reference count */
+};
+
+#define IMAGELIST_MAGIC 0x53414D58
+
+/* Header used by ImageList_Read() and ImageList_Write() */
+#include "pshpack2.h"
+typedef struct _ILHEAD
+{
+    USHORT     usMagic;
+    USHORT     usVersion;
+    WORD       cCurImage;
+    WORD       cMaxImage;
+    WORD       cGrow;
+    WORD       cx;
+    WORD       cy;
+    COLORREF   bkcolor;
+    WORD       flags;
+    SHORT      ovls[4];
+} ILHEAD;
+#include "poppack.h"
+
 /* internal image list data used for Drag & Drop operations */
 typedef struct
 {
     HWND       hwnd;
     HIMAGELIST himl;
+    HIMAGELIST himlNoCursor;
     /* position of the drag image relative to the window */
     INT                x;
     INT                y;
@@ -77,11 +151,16 @@ typedef struct
     HBITMAP    hbmBg;
 } INTERNALDRAG;
 
-static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, FALSE, 0 };
+static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, 0, FALSE, 0 };
+
+static inline HIMAGELIST impl_from_IImageList2(IImageList2 *iface)
+{
+    return CONTAINING_RECORD(iface, struct _IMAGELIST, IImageList2_iface);
+}
 
 static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count);
 static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv);
-static inline BOOL is_valid(HIMAGELIST himl);
+static BOOL is_valid(HIMAGELIST himl);
 
 /*
  * An imagelist with N images is tiled like this:
@@ -113,6 +192,17 @@ static inline void imagelist_get_bitmap_size( HIMAGELIST himl, UINT count, SIZE
     sz->cy = imagelist_height( count ) * himl->cy;
 }
 
+static inline int get_dib_stride( int width, int bpp )
+{
+    return ((width * bpp + 31) >> 3) & ~3;
+}
+
+static inline int get_dib_image_size( const BITMAPINFO *info )
+{
+    return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount )
+        * abs( info->bmiHeader.biHeight );
+}
+
 /*
  * imagelist_copy_images()
  *
@@ -138,6 +228,56 @@ static inline void imagelist_copy_images( HIMAGELIST himl, HDC hdcSrc, HDC hdcDe
     }
 }
 
+static void add_dib_bits( HIMAGELIST himl, int pos, int count, int width, int height,
+                          BITMAPINFO *info, BITMAPINFO *mask_info, DWORD *bits, BYTE *mask_bits )
+{
+    int i, j, n;
+    POINT pt;
+    int stride = info->bmiHeader.biWidth;
+    int mask_stride = (info->bmiHeader.biWidth + 31) / 32 * 4;
+
+    for (n = 0; n < count; n++)
+    {
+        BOOL has_alpha = FALSE;
+
+        imagelist_point_from_index( himl, pos + n, &pt );
+
+        /* check if bitmap has an alpha channel */
+        for (i = 0; i < height && !has_alpha; i++)
+            for (j = n * width; j < (n + 1) * width; j++)
+                if ((has_alpha = ((bits[i * stride + j] & 0xff000000) != 0))) break;
+
+        if (!has_alpha)  /* generate alpha channel from the mask */
+        {
+            for (i = 0; i < height; i++)
+                for (j = n * width; j < (n + 1) * width; j++)
+                    if (!mask_info || !((mask_bits[i * mask_stride + j / 8] << (j % 8)) & 0x80))
+                        bits[i * stride + j] |= 0xff000000;
+                    else
+                        bits[i * stride + j] = 0;
+        }
+        else
+        {
+            himl->has_alpha[pos + n] = 1;
+
+            if (mask_info && himl->hbmMask)  /* generate the mask from the alpha channel */
+            {
+                for (i = 0; i < height; i++)
+                    for (j = n * width; j < (n + 1) * width; j++)
+                        if ((bits[i * stride + j] >> 24) > 25) /* more than 10% alpha */
+                            mask_bits[i * mask_stride + j / 8] &= ~(0x80 >> (j % 8));
+                        else
+                            mask_bits[i * mask_stride + j / 8] |= 0x80 >> (j % 8);
+            }
+        }
+        StretchDIBits( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
+                       n * width, 0, width, height, bits, info, DIB_RGB_COLORS, SRCCOPY );
+        if (mask_info)
+            StretchDIBits( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
+                           n * width, 0, width, height, mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY );
+    }
+}
+
 /* add images with an alpha channel when the image list is 32 bpp */
 static BOOL add_with_alpha( HIMAGELIST himl, HDC hdc, int pos, int count,
                             int width, int height, HBITMAP hbmImage, HBITMAP hbmMask )
@@ -147,8 +287,6 @@ static BOOL add_with_alpha( HIMAGELIST himl, HDC hdc, int pos, int count,
     BITMAPINFO *info, *mask_info = NULL;
     DWORD *bits = NULL;
     BYTE *mask_bits = NULL;
-    int i, j, n;
-    POINT pt;
     DWORD mask_width;
 
     if (!GetObjectW( hbmImage, sizeof(bm), &bm )) return FALSE;
@@ -160,7 +298,7 @@ static BOOL add_with_alpha( HIMAGELIST himl, HDC hdc, int pos, int count,
     SelectObject( hdc, hbmImage );
     mask_width = (bm.bmWidth + 31) / 32 * 4;
 
-    if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
+    if (!(info = heap_alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
     info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     info->bmiHeader.biWidth = bm.bmWidth;
     info->bmiHeader.biHeight = -height;
@@ -172,71 +310,35 @@ static BOOL add_with_alpha( HIMAGELIST himl, HDC hdc, int pos, int count,
     info->bmiHeader.biYPelsPerMeter = 0;
     info->bmiHeader.biClrUsed = 0;
     info->bmiHeader.biClrImportant = 0;
-    if (!(bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ))) goto done;
+    if (!(bits = heap_alloc( info->bmiHeader.biSizeImage ))) goto done;
     if (!GetDIBits( hdc, hbmImage, 0, height, bits, info, DIB_RGB_COLORS )) goto done;
 
     if (hbmMask)
     {
-        if (!(mask_info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[2] ))))
+        if (!(mask_info = heap_alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[2] ))))
             goto done;
         mask_info->bmiHeader = info->bmiHeader;
         mask_info->bmiHeader.biBitCount = 1;
         mask_info->bmiHeader.biSizeImage = mask_width * height;
-        if (!(mask_bits = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage )))
+        if (!(mask_bits = heap_alloc_zero( mask_info->bmiHeader.biSizeImage )))
             goto done;
         if (!GetDIBits( hdc, hbmMask, 0, height, mask_bits, mask_info, DIB_RGB_COLORS )) goto done;
     }
 
-    for (n = 0; n < count; n++)
-    {
-        int has_alpha = 0;
-
-        imagelist_point_from_index( himl, pos + n, &pt );
-
-        /* check if bitmap has an alpha channel */
-        for (i = 0; i < height && !has_alpha; i++)
-            for (j = n * width; j < (n + 1) * width; j++)
-                if ((has_alpha = ((bits[i * bm.bmWidth + j] & 0xff000000) != 0))) break;
-
-        if (!has_alpha)  /* generate alpha channel from the mask */
-        {
-            for (i = 0; i < height; i++)
-                for (j = n * width; j < (n + 1) * width; j++)
-                    if (!mask_bits || !((mask_bits[i * mask_width + j / 8] << (j % 8)) & 0x80))
-                        bits[i * bm.bmWidth + j] |= 0xff000000;
-                    else
-                        bits[i * bm.bmWidth + j] = 0;
-        }
-        else
-        {
-            himl->has_alpha[pos + n] = 1;
-
-            if (mask_info && himl->hbmMask)  /* generate the mask from the alpha channel */
-            {
-                for (i = 0; i < height; i++)
-                    for (j = n * width; j < (n + 1) * width; j++)
-                        if ((bits[i * bm.bmWidth + j] >> 24) > 25) /* more than 10% alpha */
-                            mask_bits[i * mask_width + j / 8] &= ~(0x80 >> (j % 8));
-                        else
-                            mask_bits[i * mask_width + j / 8] |= 0x80 >> (j % 8);
-            }
-        }
-        StretchDIBits( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
-                       n * width, 0, width, height, bits, info, DIB_RGB_COLORS, SRCCOPY );
-        if (mask_info)
-            StretchDIBits( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
-                           n * width, 0, width, height, mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY );
-    }
+    add_dib_bits( himl, pos, count, width, height, info, mask_info, bits, mask_bits );
     ret = TRUE;
 
 done:
-    HeapFree( GetProcessHeap(), 0, info );
-    HeapFree( GetProcessHeap(), 0, mask_info );
-    HeapFree( GetProcessHeap(), 0, bits );
-    HeapFree( GetProcessHeap(), 0, mask_bits );
+    heap_free( info );
+    heap_free( mask_info );
+    heap_free( bits );
+    heap_free( mask_bits );
     return ret;
 }
 
+UINT WINAPI
+ImageList_SetColorTable(HIMAGELIST himl, UINT uStartIndex, UINT cEntries, const RGBQUAD *prgb);
+
 /*************************************************************************
  * IMAGELIST_InternalExpandBitmaps [Internal]
  *
@@ -313,7 +415,7 @@ IMAGELIST_InternalExpandBitmaps(HIMAGELIST himl, INT nImageCount)
         if (new_alpha) himl->has_alpha = new_alpha;
         else
         {
-            HeapFree( GetProcessHeap(), 0, himl->has_alpha );
+            heap_free( himl->has_alpha );
             himl->has_alpha = NULL;
         }
     }
@@ -359,7 +461,8 @@ ImageList_Add (HIMAGELIST himl,     HBITMAP hbmImage, HBITMAP hbmMask)
 
     nImageCount = bmp.bmWidth / himl->cx;
 
-    TRACE("%p has %d images (%d x %d)\n", hbmImage, nImageCount, bmp.bmWidth, bmp.bmHeight);
+    TRACE("%p has %d images (%d x %d) bpp %d\n", hbmImage, nImageCount, bmp.bmWidth, bmp.bmHeight,
+          bmp.bmBitsPixel);
 
     IMAGELIST_InternalExpandBitmaps(himl, nImageCount);
 
@@ -377,6 +480,14 @@ ImageList_Add (HIMAGELIST himl,    HBITMAP hbmImage, HBITMAP hbmMask)
         SelectObject(hdcTemp, hbmMask);
     }
 
+    if (himl->uBitsPixel <= 8 && bmp.bmBitsPixel <= 8 &&
+        !himl->color_table_set && himl->cCurImage == 0)
+    {
+        RGBQUAD colors[256];
+        UINT num = GetDIBColorTable( hdcBitmap, 0, 1 << bmp.bmBitsPixel, colors );
+        if (num) ImageList_SetColorTable( himl, 0, num, colors );
+    }
+
     for (i=0; i<nImageCount; i++)
     {
         imagelist_point_from_index( himl, himl->cCurImage + i, &pt );
@@ -474,8 +585,6 @@ ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
     SetBkColor (hdcBitmap, bkColor);
     BitBlt (hdcMask, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcBitmap, 0, 0, SRCCOPY);
 
-    SetBkColor(hdcBitmap, RGB(255,255,255));
-
     /*
      * Remove the background from the image
      *
@@ -489,7 +598,11 @@ ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
      *
      *  Blt mode 0x220326 is NOTSRCAND
      */
-    BitBlt(hdcBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMask, 0, 0, 0x220326);
+    if (bmp.bmBitsPixel > 8)  /* NOTSRCAND can't work with palettes */
+    {
+        SetBkColor(hdcBitmap, RGB(255,255,255));
+        BitBlt(hdcBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMask, 0, 0, 0x220326);
+    }
 
     DeleteDC(hdcBitmap);
     DeleteDC(hdcMask);
@@ -523,6 +636,7 @@ ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
                     INT dxHotspot, INT dyHotspot)
 {
     INT cx, cy;
+    POINT src, dst;
 
     TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack,
          dxHotspot, dyHotspot);
@@ -530,13 +644,16 @@ ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
     if (!is_valid(himlTrack))
        return FALSE;
 
+    if (iTrack >= himlTrack->cCurImage)
+        return FALSE;
+
     if (InternalDrag.himl)
-        ImageList_EndDrag ();
+        return FALSE;
 
     cx = himlTrack->cx;
     cy = himlTrack->cy;
 
-    InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1);
+    InternalDrag.himlNoCursor = InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1);
     if (InternalDrag.himl == NULL) {
         WARN("Error creating drag image list!\n");
         return FALSE;
@@ -546,10 +663,12 @@ ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
     InternalDrag.dyHotspot = dyHotspot;
 
     /* copy image */
-    BitBlt (InternalDrag.himl->hdcImage, 0, 0, cx, cy, himlTrack->hdcImage, iTrack * cx, 0, SRCCOPY);
-
-    /* copy mask */
-    BitBlt (InternalDrag.himl->hdcMask, 0, 0, cx, cy, himlTrack->hdcMask, iTrack * cx, 0, SRCCOPY);
+    imagelist_point_from_index(InternalDrag.himl, 0, &dst);
+    imagelist_point_from_index(himlTrack, iTrack, &src);
+    BitBlt(InternalDrag.himl->hdcImage, dst.x, dst.y, cx, cy, himlTrack->hdcImage, src.x, src.y,
+            SRCCOPY);
+    BitBlt(InternalDrag.himl->hdcMask, dst.x, dst.y, cx, cy, himlTrack->hdcMask, src.x, src.y,
+            SRCCOPY);
 
     InternalDrag.himl->cCurImage = 1;
 
@@ -694,13 +813,21 @@ ImageList_Create (INT cx, INT cy, UINT flags,
 
     TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
 
-    if (cx <= 0 || cy <= 0) return NULL;
+    if (cx < 0 || cy < 0) return NULL;
+    if (!((flags&ILC_COLORDDB) == ILC_COLORDDB) && (cx == 0 || cy == 0)) return NULL;
 
     /* Create the IImageList interface for the image list */
     if (FAILED(ImageListImpl_CreateInstance(NULL, &IID_IImageList, (void **)&himl)))
         return NULL;
 
-    cGrow = (cGrow < 4) ? 4 : (cGrow + 3) & ~3;
+    cGrow = (WORD)((max( cGrow, 1 ) + 3) & ~3);
+
+    if (cGrow > 256)
+    {
+        /* Windows doesn't limit the size here, but X11 doesn't let us allocate such huge bitmaps */
+        WARN( "grow %d too large, limiting to 256\n", cGrow );
+        cGrow = 256;
+    }
 
     himl->cx        = cx;
     himl->cy        = cy;
@@ -710,6 +837,7 @@ ImageList_Create (INT cx, INT cy, UINT flags,
     himl->cGrow     = cGrow;
     himl->clrFg     = CLR_DEFAULT;
     himl->clrBk     = CLR_NONE;
+    himl->color_table_set = FALSE;
 
     /* initialize overlay mask indices */
     for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
@@ -727,7 +855,10 @@ ImageList_Create (INT cx, INT cy, UINT flags,
 
     /* Default to ILC_COLOR4 if none of the ILC_COLOR* flags are specified */
     if (ilc == ILC_COLOR)
+    {
         ilc = ILC_COLOR4;
+        himl->flags |= ILC_COLOR4;
+    }
 
     if (ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32)
         himl->uBitsPixel = ilc;
@@ -755,7 +886,7 @@ ImageList_Create (INT cx, INT cy, UINT flags,
         himl->hbmMask = 0;
 
     if (ilc == ILC_COLOR32)
-        himl->has_alpha = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, himl->cMaxImage );
+        himl->has_alpha = heap_alloc_zero( himl->cMaxImage );
     else
         himl->has_alpha = NULL;
 
@@ -837,11 +968,7 @@ ImageList_DragEnter (HWND hwndLock, INT x, INT y)
     InternalDrag.y = y;
 
     /* draw the drag image and save the background */
-    if (!ImageList_DragShowNolock(TRUE)) {
-       return FALSE;
-    }
-
-    return TRUE;
+    return ImageList_DragShowNolock(TRUE);
 }
 
 
@@ -1105,7 +1232,7 @@ ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, UINT fStyle)
 /*************************************************************************
  * ImageList_DrawEx [COMCTL32.@]
  *
- * Draws an image and allows to use extended drawing features.
+ * Draws an image and allows using extended drawing features.
  *
  * PARAMS
  *     himl   [I] handle to image list
@@ -1153,8 +1280,11 @@ ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
     return ImageList_DrawIndirect (&imldp);
 }
 
-
+#ifdef __REACTOS__
+static BOOL alpha_blend_image( HIMAGELIST himl, HDC srce_dc, HDC dest_dc, int dest_x, int dest_y,
+#else
 static BOOL alpha_blend_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int dest_y,
+#endif
                                int src_x, int src_y, int cx, int cy, BLENDFUNCTION func,
                                UINT style, COLORREF blend_col )
 {
@@ -1167,7 +1297,7 @@ static BOOL alpha_blend_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int des
     int i, j;
 
     if (!(hdc = CreateCompatibleDC( 0 ))) return FALSE;
-    if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
+    if (!(info = heap_alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
     info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     info->bmiHeader.biWidth = cx;
     info->bmiHeader.biHeight = cy;
@@ -1179,9 +1309,17 @@ static BOOL alpha_blend_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int des
     info->bmiHeader.biYPelsPerMeter = 0;
     info->bmiHeader.biClrUsed = 0;
     info->bmiHeader.biClrImportant = 0;
+#ifdef __REACTOS__
+    if (!(bmp = CreateDIBSection( srce_dc, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done;
+#else
     if (!(bmp = CreateDIBSection( himl->hdcImage, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done;
+#endif
     SelectObject( hdc, bmp );
+#ifdef __REACTOS__
+    BitBlt( hdc, 0, 0, cx, cy, srce_dc, src_x, src_y, SRCCOPY );
+#else
     BitBlt( hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY );
+#endif
 
     if (blend_col != CLR_NONE)
     {
@@ -1225,6 +1363,14 @@ static BOOL alpha_blend_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int des
         /* generate alpha channel from the mask */
         info->bmiHeader.biBitCount = 1;
         info->bmiHeader.biSizeImage = width_bytes * cy;
+        info->bmiColors[0].rgbRed      = 0;
+        info->bmiColors[0].rgbGreen    = 0;
+        info->bmiColors[0].rgbBlue     = 0;
+        info->bmiColors[0].rgbReserved = 0;
+        info->bmiColors[1].rgbRed      = 0xff;
+        info->bmiColors[1].rgbGreen    = 0xff;
+        info->bmiColors[1].rgbBlue     = 0xff;
+        info->bmiColors[1].rgbReserved = 0;
         if (!(mask = CreateDIBSection( himl->hdcMask, info, DIB_RGB_COLORS, &mask_bits, 0, 0 )))
             goto done;
         SelectObject( hdc, mask );
@@ -1242,10 +1388,72 @@ done:
     DeleteDC( hdc );
     if (bmp) DeleteObject( bmp );
     if (mask) DeleteObject( mask );
-    HeapFree( GetProcessHeap(), 0, info );
+    heap_free( info );
     return ret;
 }
 
+#ifdef __REACTOS__
+HDC saturate_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int dest_y,
+                    int src_x, int src_y, int cx, int cy, COLORREF rgbFg)
+{
+    HDC hdc = NULL;
+    HBITMAP bmp = 0;
+    BITMAPINFO *info;
+
+    unsigned int *ptr;
+    void *bits;
+    int i;
+
+    /* create a dc and its device independent bitmap for doing the work,
+       shamelessly copied from the alpha-blending function above */
+    if (!(hdc = CreateCompatibleDC( 0 ))) return FALSE;
+    if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
+    info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    info->bmiHeader.biWidth = cx;
+    info->bmiHeader.biHeight = cy;
+    info->bmiHeader.biPlanes = 1;
+    info->bmiHeader.biBitCount = 32;
+    info->bmiHeader.biCompression = BI_RGB;
+    info->bmiHeader.biSizeImage = cx * cy * 4;
+    info->bmiHeader.biXPelsPerMeter = 0;
+    info->bmiHeader.biYPelsPerMeter = 0;
+    info->bmiHeader.biClrUsed = 0;
+    info->bmiHeader.biClrImportant = 0;
+    if (!(bmp = CreateDIBSection(himl->hdcImage, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done;
+
+    /* bind both surfaces */
+    SelectObject(hdc, bmp);
+
+    /* copy into our dc the section that covers just the icon we we're asked for */
+    BitBlt(hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY);
+
+    /* loop every pixel of the bitmap */
+    for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
+    {
+        COLORREF orig_color = *ptr;
+
+        /* calculate the effective luminance using the constants from here, adapted to the human eye:
+           <http://bobpowell.net/grayscale.aspx> */
+        float mixed_color = (GetRValue(orig_color) * .30 +
+                             GetGValue(orig_color) * .59 +
+                             GetBValue(orig_color) * .11);
+
+        *ptr = RGBA(mixed_color, mixed_color, mixed_color, GetAValue(orig_color));
+    }
+
+done:
+
+    if (bmp)
+        DeleteObject(bmp);
+
+    if (info)
+        HeapFree(GetProcessHeap(), 0, info);
+
+    /* return the handle to our desaturated dc, that will substitute its original counterpart in the next calls */
+    return hdc;
+}
+#endif /* __REACTOS__ */
+
 /*************************************************************************
  * ImageList_DrawIndirect [COMCTL32.@]
  *
@@ -1273,6 +1481,9 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
     HBRUSH hOldBrush;
     POINT pt;
     BOOL has_alpha;
+#ifdef __REACTOS__
+    HDC hdcSaturated = NULL;
+#endif
 
     if (!pimldp || !(himl = pimldp->himl)) return FALSE;
     if (!is_valid(himl)) return FALSE;
@@ -1322,6 +1533,24 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
     oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) );
     oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) );
 
+#ifdef __REACTOS__
+    /*
+     * If the ILS_SATURATE bit is enabled we should multiply the
+     * RGB colors of the original image by the contents of rgbFg.
+     */
+    if (fState & ILS_SATURATE)
+    {
+        hdcSaturated = saturate_image(himl, pimldp->hdcDst, pimldp->x, pimldp->y,
+                                      pt.x, pt.y, cx, cy, pimldp->rgbFg);
+
+        hImageListDC = hdcSaturated;
+        /* shitty way of getting subroutines to blit at the right place (top left corner),
+           as our modified imagelist only contains a single image for performance reasons */
+        pt.x = 0;
+        pt.y = 0;
+    }
+#endif
+
     has_alpha = (himl->has_alpha && himl->has_alpha[pimldp->i]);
     if (!bMask && (has_alpha || (fState & ILS_ALPHA)))
     {
@@ -1342,7 +1571,11 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
 
         if (bIsTransparent)
         {
+#ifdef __REACTOS__
+            bResult = alpha_blend_image( himl, hImageListDC, pimldp->hdcDst, pimldp->x, pimldp->y,
+#else
             bResult = alpha_blend_image( himl, pimldp->hdcDst, pimldp->x, pimldp->y,
+#endif
                                          pt.x, pt.y, cx, cy, func, fStyle, blend_col );
             goto end;
         }
@@ -1352,7 +1585,11 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
 
         hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
         PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
+#ifdef __REACTOS__
+        alpha_blend_image( himl, hImageListDC, hImageDC, 0, 0, pt.x, pt.y, cx, cy, func, fStyle, blend_col );
+#else
         alpha_blend_image( himl, hImageDC, 0, 0, pt.x, pt.y, cx, cy, func, fStyle, blend_col );
+#endif
         DeleteObject (SelectObject (hImageDC, hOldBrush));
         bResult = BitBlt( pimldp->hdcDst, pimldp->x,  pimldp->y, cx, cy, hImageDC, 0, 0, SRCCOPY );
         goto end;
@@ -1446,7 +1683,9 @@ ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
        }
     }
 
+#ifndef __REACTOS__
     if (fState & ILS_SATURATE) FIXME("ILS_SATURATE: unimplemented!\n");
+#endif
     if (fState & ILS_GLOW) FIXME("ILS_GLOW: unimplemented!\n");
     if (fState & ILS_SHADOW) FIXME("ILS_SHADOW: unimplemented!\n");
 
@@ -1474,6 +1713,10 @@ end:
     SetTextColor(hImageDC, oldImageFg);
     SelectObject(hImageDC, hOldImageBmp);
 cleanup:
+#ifdef __REACTOS__
+    if (hdcSaturated)
+        DeleteDC(hdcSaturated);
+#endif
     DeleteObject(hBlendMaskBmp);
     DeleteObject(hImageBmp);
     DeleteDC(hImageDC);
@@ -1546,8 +1789,10 @@ ImageList_EndDrag (void)
 {
     /* cleanup the InternalDrag struct */
     InternalDrag.hwnd = 0;
+    if (InternalDrag.himl != InternalDrag.himlNoCursor)
+        ImageList_Destroy (InternalDrag.himlNoCursor);
     ImageList_Destroy (InternalDrag.himl);
-    InternalDrag.himl = 0;
+    InternalDrag.himlNoCursor = InternalDrag.himl = 0;
     InternalDrag.x= 0;
     InternalDrag.y= 0;
     InternalDrag.dxHotspot = 0;
@@ -1630,8 +1875,13 @@ DWORD WINAPI
 ImageList_GetFlags(HIMAGELIST himl)
 {
     TRACE("%p\n", himl);
-
+#ifdef __REACTOS__
+    if(!is_valid2(himl))
+        return 0;
+    return himl->flags;
+#else
     return is_valid(himl) ? himl->flags : 0;
+#endif
 }
 
 
@@ -1729,8 +1979,6 @@ ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
 {
     if (!is_valid(himl) || !cx || !cy)
        return FALSE;
-    if ((himl->cx <= 0) || (himl->cy <= 0))
-       return FALSE;
 
     *cx = himl->cx;
     *cy = himl->cy;
@@ -1821,6 +2069,12 @@ ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
 BOOL WINAPI
 ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
 {
+#ifdef __REACTOS__
+    IMAGEINFO ImageInfo;
+    if (!ImageList_GetImageInfo(himl, i, &ImageInfo))
+        return FALSE;
+    *lpRect = ImageInfo.rcImage;
+#else
     POINT pt;
 
     if (!is_valid(himl) || (lpRect == NULL))
@@ -1833,7 +2087,7 @@ ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
     lpRect->top    = pt.y;
     lpRect->right  = pt.x + himl->cx;
     lpRect->bottom = pt.y + himl->cy;
-
+#endif
     return TRUE;
 }
 
@@ -1860,11 +2114,11 @@ ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
                                     uType, uFlags);
 
     len = MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, NULL, 0);
-    lpbmpW = Alloc(len * sizeof(WCHAR));
+    lpbmpW = heap_alloc(len * sizeof(WCHAR));
     MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, lpbmpW, len);
 
     himl = ImageList_LoadImageW(hi, lpbmpW, cx, cGrow, clrMask, uType, uFlags);
-    Free (lpbmpW);
+    heap_free (lpbmpW);
     return himl;
 }
 
@@ -1926,7 +2180,8 @@ ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
 
         nImageCount = dib.dsBm.bmWidth / cx;
 
-        himl = ImageList_Create (cx, dib.dsBm.bmHeight, ILC_MASK | color, nImageCount, cGrow);
+        if (clrMask != CLR_NONE) color |= ILC_MASK;
+        himl = ImageList_Create (cx, dib.dsBm.bmHeight, color, nImageCount, cGrow);
         if (!himl) {
             DeleteObject (handle);
             return NULL;
@@ -1974,13 +2229,13 @@ ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
  * RETURNS
  *     Success: The newly created image list. It contains a single image
  *              consisting of the second image merged with the first.
- *     Failure: NULL, if either himl1 or himl2 are invalid.
+ *     Failure: NULL, if either himl1 or himl2 is invalid.
  *
  * NOTES
  *   - The returned image list should be deleted by the caller using
  *     ImageList_Destroy() when it is no longer required.
- *   - If either i1 or i2 are not valid image indices they will be treated
- *     as a blank image.
+ *   - If either i1 or i2 is not a valid image index, they will be treated
+ *     as blank images.
  */
 HIMAGELIST WINAPI
 ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
@@ -1990,6 +2245,7 @@ ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
     INT      cxDst, cyDst;
     INT      xOff1, yOff1, xOff2, yOff2;
     POINT    pt1, pt2;
+    INT      newFlags;
 
     TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2,
           i2, dx, dy);
@@ -2029,7 +2285,10 @@ ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
         yOff2 = 0;
     }
 
-    himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | ILC_COLOR, 1, 1);
+    newFlags = (himl1->flags > himl2->flags ? himl1->flags : himl2->flags) & ILC_COLORDDB;
+    if (newFlags == ILC_COLORDDB && (himl1->flags & ILC_COLORDDB) == ILC_COLOR16)
+        newFlags = ILC_COLOR16; /* this is what native (at least v5) does, don't know why */
+    himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | newFlags, 1, 1);
 
     if (himlDst)
     {
@@ -2042,8 +2301,13 @@ ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
             BitBlt (himlDst->hdcImage, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcImage, pt1.x, pt1.y, SRCCOPY);
         if (i2 >= 0 && i2 < himl2->cCurImage)
         {
-            BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , pt2.x, pt2.y, SRCAND);
-            BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCPAINT);
+            if (himl2->flags & ILC_MASK)
+            {
+                BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , pt2.x, pt2.y, SRCAND);
+                BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCPAINT);
+            }
+            else
+                BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCCOPY);
         }
 
         /* copy mask */
@@ -2060,66 +2324,24 @@ ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
 }
 
 
-/***********************************************************************
- *           DIB_GetDIBWidthBytes
- *
- * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
- */
-static int DIB_GetDIBWidthBytes( int width, int depth )
-{
-    int words;
-
-    switch(depth)
-    {
-    case 1:  words = (width + 31) / 32; break;
-    case 4:  words = (width + 7) / 8; break;
-    case 8:  words = (width + 3) / 4; break;
-    case 15:
-    case 16: words = (width + 1) / 2; break;
-    case 24: words = (width * 3 + 3)/4; break;
-
-    default:
-        WARN("(%d): Unsupported depth\n", depth );
-        /* fall through */
-    case 32:
-        words = width;
-        break;
-    }
-    return 4 * words;
-}
-
-/***********************************************************************
- *           DIB_GetDIBImageBytes
- *
- * Return the number of bytes used to hold the image in a DIB bitmap.
- */
-static int DIB_GetDIBImageBytes( int width, int height, int depth )
-{
-    return DIB_GetDIBWidthBytes( width, depth ) * abs( height );
-}
-
-
 /* helper for ImageList_Read, see comments below */
-static BOOL _read_bitmap(HDC hdcIml, LPSTREAM pstm)
+static void *read_bitmap(IStream *pstm, BITMAPINFO *bmi)
 {
     BITMAPFILEHEADER   bmfh;
     int bitsperpixel, palspace;
-    char bmi_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
-    LPBITMAPINFO bmi = (LPBITMAPINFO)bmi_buf;
-    int                result = FALSE;
-    LPBYTE             bits = NULL;
+    void *bits;
 
     if (FAILED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)))
-        return FALSE;
+        return NULL;
 
     if (bmfh.bfType != (('M'<<8)|'B'))
-        return FALSE;
+        return NULL;
 
     if (FAILED(IStream_Read ( pstm, &bmi->bmiHeader, sizeof(bmi->bmiHeader), NULL)))
-        return FALSE;
+        return NULL;
 
     if ((bmi->bmiHeader.biSize != sizeof(bmi->bmiHeader)))
-        return FALSE;
+        return NULL;
 
     TRACE("width %u, height %u, planes %u, bpp %u\n",
           bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
@@ -2131,27 +2353,21 @@ static BOOL _read_bitmap(HDC hdcIml, LPSTREAM pstm)
     else
         palspace = 0;
 
-    bmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, bitsperpixel);
+    bmi->bmiHeader.biSizeImage = get_dib_image_size( bmi );
 
     /* read the palette right after the end of the bitmapinfoheader */
     if (palspace && FAILED(IStream_Read(pstm, bmi->bmiColors, palspace, NULL)))
-       goto error;
-
-    bits = Alloc(bmi->bmiHeader.biSizeImage);
-    if (!bits)
-        goto error;
-    if (FAILED(IStream_Read(pstm, bits, bmi->bmiHeader.biSizeImage, NULL)))
-        goto error;
+        return NULL;
 
-    if (!StretchDIBits(hdcIml, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
-                  0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
-                  bits, bmi, DIB_RGB_COLORS, SRCCOPY))
-        goto error;
-    result = TRUE;
+    bits = heap_alloc_zero(bmi->bmiHeader.biSizeImage);
+    if (!bits) return NULL;
 
-error:
-    Free(bits);
-    return result;
+    if (FAILED(IStream_Read(pstm, bits, bmi->bmiHeader.biSizeImage, NULL)))
+    {
+        heap_free(bits);
+        return NULL;
+    }
+    return bits;
 }
 
 /*************************************************************************
@@ -2185,11 +2401,16 @@ error:
  *
  *     BYTE                    maskbits[imagesize];
  */
-HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
+HIMAGELIST WINAPI ImageList_Read(IStream *pstm)
 {
+    char image_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
+    char mask_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
+    BITMAPINFO *image_info = (BITMAPINFO *)image_buf;
+    BITMAPINFO *mask_info = (BITMAPINFO *)mask_buf;
+    void *image_bits, *mask_bits = NULL;
     ILHEAD     ilHead;
     HIMAGELIST himl;
-    int                i;
+    unsigned int i;
 
     TRACE("%p\n", pstm);
 
@@ -2207,19 +2428,56 @@ HIMAGELIST WINAPI ImageList_Read (LPSTREAM pstm)
     if (!himl)
        return NULL;
 
-    if (!_read_bitmap(himl->hdcImage, pstm))
+    if (!(image_bits = read_bitmap(pstm, image_info)))
     {
        WARN("failed to read bitmap from stream\n");
        return NULL;
     }
     if (ilHead.flags & ILC_MASK)
     {
-        if (!_read_bitmap(himl->hdcMask, pstm))
+        if (!(mask_bits = read_bitmap(pstm, mask_info)))
         {
             WARN("failed to read mask bitmap from stream\n");
            return NULL;
        }
     }
+    else mask_info = NULL;
+
+    if (himl->has_alpha && image_info->bmiHeader.biBitCount == 32)
+    {
+        DWORD *ptr = image_bits;
+        BYTE *mask_ptr = mask_bits;
+        int stride = himl->cy * image_info->bmiHeader.biWidth;
+
+        if (image_info->bmiHeader.biHeight > 0)  /* bottom-up */
+        {
+            ptr += image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride;
+            mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / 8;
+            stride = -stride;
+            image_info->bmiHeader.biHeight = himl->cy;
+        }
+        else image_info->bmiHeader.biHeight = -himl->cy;
+
+        for (i = 0; i < ilHead.cCurImage; i += TILE_COUNT)
+        {
+            add_dib_bits( himl, i, min( ilHead.cCurImage - i, TILE_COUNT ),
+                          himl->cx, himl->cy, image_info, mask_info, ptr, mask_ptr );
+            ptr += stride;
+            mask_ptr += stride / 8;
+        }
+    }
+    else
+    {
+        StretchDIBits( himl->hdcImage, 0, 0, image_info->bmiHeader.biWidth, image_info->bmiHeader.biHeight,
+                       0, 0, image_info->bmiHeader.biWidth, image_info->bmiHeader.biHeight,
+                       image_bits, image_info, DIB_RGB_COLORS, SRCCOPY);
+        if (mask_info)
+            StretchDIBits( himl->hdcMask, 0, 0, mask_info->bmiHeader.biWidth, mask_info->bmiHeader.biHeight,
+                           0, 0, mask_info->bmiHeader.biWidth, mask_info->bmiHeader.biHeight,
+                           mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY);
+    }
+    heap_free( image_bits );
+    heap_free( mask_bits );
 
     himl->cCurImage = ilHead.cCurImage;
     himl->cMaxImage = ilHead.cMaxImage;
@@ -2276,11 +2534,17 @@ ImageList_Remove (HIMAGELIST himl, INT i)
            return TRUE;
        }
 
-        himl->cMaxImage = himl->cInitial + himl->cGrow - 1;
+        himl->cMaxImage = himl->cGrow;
         himl->cCurImage = 0;
         for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
              himl->nOvlIdx[nCount] = -1;
 
+        if (himl->has_alpha)
+        {
+            heap_free( himl->has_alpha );
+            himl->has_alpha = heap_alloc_zero( himl->cMaxImage );
+        }
+
         hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
         SelectObject (himl->hdcImage, hbmNewImage);
         DeleteObject (himl->hbmImage);
@@ -2455,7 +2719,6 @@ done:
 INT WINAPI
 ImageList_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon)
 {
-    HDC     hdcImage;
     HICON   hBestFitIcon;
     ICONINFO  ii;
     BITMAP  bmp;
@@ -2487,38 +2750,19 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon)
     if (!hBestFitIcon)
         return -1;
 
-    ret = GetIconInfo (hBestFitIcon, &ii);
-    if (!ret) {
-        DestroyIcon(hBestFitIcon);
-        return -1;
-    }
-
-    ret = GetObjectW (ii.hbmMask, sizeof(BITMAP), &bmp);
-    if (!ret) {
-        ERR("couldn't get mask bitmap info\n");
-        if (ii.hbmColor)
-            DeleteObject (ii.hbmColor);
-        if (ii.hbmMask)
-            DeleteObject (ii.hbmMask);
-        DestroyIcon(hBestFitIcon);
-        return -1;
-    }
-
     if (nIndex == -1) {
-        if (himl->cCurImage + 1 > himl->cMaxImage)
+        if (himl->cCurImage + 1 >= himl->cMaxImage)
             IMAGELIST_InternalExpandBitmaps(himl, 1);
 
         nIndex = himl->cCurImage;
         himl->cCurImage++;
     }
 
-    hdcImage = CreateCompatibleDC (0);
-    TRACE("hdcImage=%p\n", hdcImage);
-    if (hdcImage == 0)
-       ERR("invalid hdcImage!\n");
-
-    if (himl->has_alpha)
+    if (himl->has_alpha && GetIconInfo (hBestFitIcon, &ii))
     {
+        HDC hdcImage = CreateCompatibleDC( 0 );
+        GetObjectW (ii.hbmMask, sizeof(BITMAP), &bmp);
+
         if (!ii.hbmColor)
         {
             UINT height = bmp.bmHeight / 2;
@@ -2530,48 +2774,38 @@ ImageList_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon)
             ret = add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, height, color, ii.hbmMask );
             DeleteDC( hdcMask );
             DeleteObject( color );
-            if (ret) goto done;
         }
-        else if (add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, bmp.bmHeight,
-                                 ii.hbmColor, ii.hbmMask )) goto done;
+        else ret = add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, bmp.bmHeight,
+                                   ii.hbmColor, ii.hbmMask );
+
+        DeleteDC( hdcImage );
+        DeleteObject (ii.hbmMask);
+        if (ii.hbmColor) DeleteObject (ii.hbmColor);
+        if (ret) goto done;
     }
 
     imagelist_point_from_index(himl, nIndex, &pt);
 
-    SetTextColor(himl->hdcImage, RGB(0,0,0));
-    SetBkColor  (himl->hdcImage, RGB(255,255,255));
-
-    if (ii.hbmColor)
+    if (himl->hbmMask)
     {
-        SelectObject (hdcImage, ii.hbmColor);
-        StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
-                    hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
-        if (himl->hbmMask)
-        {
-            SelectObject (hdcImage, ii.hbmMask);
-            StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
-                        hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
-        }
+        DrawIconEx( himl->hdcImage, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_IMAGE );
+        PatBlt( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy, WHITENESS );
+        DrawIconEx( himl->hdcMask, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_MASK );
     }
     else
     {
-        UINT height = bmp.bmHeight / 2;
-        SelectObject (hdcImage, ii.hbmMask);
-        StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
-                    hdcImage, 0, height, bmp.bmWidth, height, SRCCOPY);
-        if (himl->hbmMask)
-            StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
-                        hdcImage, 0, 0, bmp.bmWidth, height, SRCCOPY);
+        COLORREF color = himl->clrBk != CLR_NONE ? himl->clrBk : comctl32_color.clrWindow;
+        HBRUSH brush = CreateSolidBrush( GetNearestColor( himl->hdcImage, color ));
+
+        SelectObject( himl->hdcImage, brush );
+        PatBlt( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy, PATCOPY );
+        SelectObject( himl->hdcImage, GetStockObject(BLACK_BRUSH) );
+        DeleteObject( brush );
+        DrawIconEx( himl->hdcImage, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_NORMAL );
     }
 
 done:
     DestroyIcon(hBestFitIcon);
-    if (hdcImage)
-       DeleteDC (hdcImage);
-    if (ii.hbmColor)
-       DeleteObject (ii.hbmColor);
-    if (ii.hbmMask)
-       DeleteObject (ii.hbmMask);
 
     TRACE("Insert index = %d, himl->cCurImage = %d\n", nIndex, himl->cCurImage);
     return nIndex;
@@ -2646,7 +2880,7 @@ ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
 
     visible = InternalDrag.bShow;
 
-    himlTemp = ImageList_Merge (InternalDrag.himl, 0, himlDrag, iDrag,
+    himlTemp = ImageList_Merge (InternalDrag.himlNoCursor, 0, himlDrag, iDrag,
                                 dxHotspot, dyHotspot);
 
     if (visible) {
@@ -2660,7 +2894,8 @@ ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
        InternalDrag.hbmBg = 0;
     }
 
-    ImageList_Destroy (InternalDrag.himl);
+    if (InternalDrag.himl != InternalDrag.himlNoCursor)
+        ImageList_Destroy (InternalDrag.himl);
     InternalDrag.himl = himlTemp;
 
     if (visible) {
@@ -2802,14 +3037,8 @@ ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount)
 
     if (!is_valid(himl))
        return FALSE;
-    if (himl->cMaxImage > iImageCount)
-    {
-        himl->cCurImage = iImageCount;
-        /* TODO: shrink the bitmap when cMaxImage-cCurImage>cGrow ? */
-       return TRUE;
-    }
 
-    nNewCount = iImageCount + himl->cGrow;
+    nNewCount = iImageCount + 1;
     nCopyCount = min(himl->cCurImage, iImageCount);
 
     hdcBitmap = CreateCompatibleDC (0);
@@ -2829,7 +3058,7 @@ ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount)
        himl->hbmImage = hbmNewBitmap;
     }
     else
-       ERR("Could not create new image bitmap !\n");
+       ERR("Could not create new image bitmap!\n");
 
     if (himl->hbmMask)
     {
@@ -2860,7 +3089,7 @@ ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount)
         if (new_alpha) himl->has_alpha = new_alpha;
         else
         {
-            HeapFree( GetProcessHeap(), 0, himl->has_alpha );
+            heap_free( himl->has_alpha );
             himl->has_alpha = NULL;
         }
     }
@@ -2906,8 +3135,7 @@ ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
 /* helper for ImageList_Write - write bitmap to pstm
  * currently everything is written as 24 bit RGB, except masks
  */
-static BOOL
-_write_bitmap(HBITMAP hBitmap, LPSTREAM pstm)
+static BOOL _write_bitmap(HBITMAP hBitmap, IStream *pstm)
 {
     LPBITMAPFILEHEADER bmfh;
     LPBITMAPINFOHEADER bmih;
@@ -2920,16 +3148,16 @@ _write_bitmap(HBITMAP hBitmap, LPSTREAM pstm)
     if (!GetObjectW(hBitmap, sizeof(BITMAP), &bm))
         return FALSE;
 
-    bitCount = bm.bmBitsPixel == 1 ? 1 : 24;
-    sizeImage = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, bitCount);
+    bitCount = bm.bmBitsPixel;
+    sizeImage = get_dib_stride(bm.bmWidth, bitCount) * bm.bmHeight;
 
     totalSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
-    if(bitCount != 24)
+    if(bitCount <= 8)
        totalSize += (1 << bitCount) * sizeof(RGBQUAD);
     offBits = totalSize;
     totalSize += sizeImage;
 
-    data = Alloc(totalSize);
+    data = heap_alloc_zero(totalSize);
     bmfh = (LPBITMAPFILEHEADER)data;
     bmih = (LPBITMAPINFOHEADER)(data + sizeof(BITMAPFILEHEADER));
     lpBits = data + offBits;
@@ -2964,20 +3192,13 @@ _write_bitmap(HBITMAP hBitmap, LPSTREAM pstm)
           bmih->biWidth, bmih->biHeight,
           bmih->biPlanes, bmih->biBitCount);
 
-    if(bitCount == 1) {
-        /* Hack. */
-       LPBITMAPINFO inf = (LPBITMAPINFO)bmih;
-       inf->bmiColors[0].rgbRed = inf->bmiColors[0].rgbGreen = inf->bmiColors[0].rgbBlue = 0;
-       inf->bmiColors[1].rgbRed = inf->bmiColors[1].rgbGreen = inf->bmiColors[1].rgbBlue = 0xff;
-    }
-
     if(FAILED(IStream_Write(pstm, data, totalSize, NULL)))
        goto failed;
 
     result = TRUE;
 
 failed:
-    Free(data);
+    heap_free(data);
 
     return result;
 }
@@ -3000,8 +3221,7 @@ failed:
  *     probably.
  */
 
-BOOL WINAPI
-ImageList_Write (HIMAGELIST himl, LPSTREAM pstm)
+BOOL WINAPI ImageList_Write(HIMAGELIST himl, IStream *pstm)
 {
     ILHEAD ilHead;
     int i;
@@ -3054,54 +3274,42 @@ static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count)
 
     if ((ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) || ilc == ILC_COLOR)
     {
-        VOID* bits;
-        BITMAPINFO *bmi;
+        char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
+        BITMAPINFO *bmi = (BITMAPINFO *)buffer;
 
         TRACE("Creating DIBSection %d x %d, %d Bits per Pixel\n",
               sz.cx, sz.cy, himl->uBitsPixel);
 
-       if (himl->uBitsPixel <= ILC_COLOR8)
-       {
-           LPPALETTEENTRY pal;
-           ULONG i, colors;
-           BYTE temp;
-
-           colors = 1 << himl->uBitsPixel;
-           bmi = Alloc(sizeof(BITMAPINFOHEADER) +
-                           sizeof(PALETTEENTRY) * colors);
-
-           pal = (LPPALETTEENTRY)bmi->bmiColors;
-           GetPaletteEntries(GetStockObject(DEFAULT_PALETTE), 0, colors, pal);
-
-           /* Swap colors returned by GetPaletteEntries so we can use them for
-            * CreateDIBSection call. */
-           for (i = 0; i < colors; i++)
-           {
-               temp = pal[i].peBlue;
-               bmi->bmiColors[i].rgbRed = pal[i].peRed;
-               bmi->bmiColors[i].rgbBlue = temp;
-           }
-       }
-       else
-       {
-           bmi = Alloc(sizeof(BITMAPINFOHEADER));
-       }
-
+        memset( buffer, 0, sizeof(buffer) );
        bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bmi->bmiHeader.biWidth = sz.cx;
        bmi->bmiHeader.biHeight = sz.cy;
        bmi->bmiHeader.biPlanes = 1;
        bmi->bmiHeader.biBitCount = himl->uBitsPixel;
        bmi->bmiHeader.biCompression = BI_RGB;
-       bmi->bmiHeader.biSizeImage = 0;
-       bmi->bmiHeader.biXPelsPerMeter = 0;
-       bmi->bmiHeader.biYPelsPerMeter = 0;
-       bmi->bmiHeader.biClrUsed = 0;
-       bmi->bmiHeader.biClrImportant = 0;
 
-       hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, &bits, 0, 0);
-
-       Free (bmi);
+       if (himl->uBitsPixel <= ILC_COLOR8)
+       {
+            if (!himl->color_table_set)
+            {
+                /* retrieve the default color map */
+                HBITMAP tmp = CreateBitmap( 1, 1, 1, 1, NULL );
+                GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
+                DeleteObject( tmp );
+                if (ilc == ILC_COLOR4)
+                {
+                    RGBQUAD tmp;
+                    tmp = bmi->bmiColors[7];
+                    bmi->bmiColors[7] = bmi->bmiColors[8];
+                    bmi->bmiColors[8] = tmp;
+                }
+            }
+            else
+            {
+                GetDIBColorTable(himl->hdcImage, 0, 1 << himl->uBitsPixel, bmi->bmiColors);
+            }
+        }
+       hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, 0, 0);
     }
     else /*if (ilc == ILC_COLORDDB)*/
     {
@@ -3133,8 +3341,14 @@ static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count)
  */
 
 UINT WINAPI
-ImageList_SetColorTable (HIMAGELIST himl, UINT uStartIndex, UINT cEntries, CONST RGBQUAD * prgb)
+ImageList_SetColorTable(HIMAGELIST himl, UINT uStartIndex, UINT cEntries, const RGBQUAD *prgb)
 {
+#ifdef __REACTOS__
+    if(!is_valid2(himl))
+        return 0;
+#endif
+    TRACE("(%p, %d, %d, %p)\n", himl, uStartIndex, cEntries, prgb);
+    himl->color_table_set = TRUE;
     return SetDIBColorTable(himl->hdcImage, uStartIndex, cEntries, prgb);
 }
 
@@ -3169,38 +3383,43 @@ ImageList_CoCreateInstance (REFCLSID rclsid, const IUnknown *punkOuter, REFIID r
  * IImageList implementation
  */
 
-static HRESULT WINAPI ImageListImpl_QueryInterface(IImageList *iface,
+static HRESULT WINAPI ImageListImpl_QueryInterface(IImageList2 *iface,
     REFIID iid, void **ppv)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+
     TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
 
     if (!ppv) return E_INVALIDARG;
 
-    if (IsEqualIID(&IID_IUnknown, iid) || IsEqualIID(&IID_IImageList, iid))
-        *ppv = This;
+    if (IsEqualIID(&IID_IUnknown, iid) ||
+        IsEqualIID(&IID_IImageList, iid) ||
+        IsEqualIID(&IID_IImageList2, iid))
+    {
+        *ppv = &imgl->IImageList2_iface;
+    }
     else
     {
         *ppv = NULL;
         return E_NOINTERFACE;
     }
 
-    IUnknown_AddRef((IUnknown*)*ppv);
+    IImageList2_AddRef(iface);
     return S_OK;
 }
 
-static ULONG WINAPI ImageListImpl_AddRef(IImageList *iface)
+static ULONG WINAPI ImageListImpl_AddRef(IImageList2 *iface)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
-    ULONG ref = InterlockedIncrement(&This->ref);
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    ULONG ref = InterlockedIncrement(&imgl->ref);
 
     TRACE("(%p) refcount=%u\n", iface, ref);
     return ref;
 }
 
-static ULONG WINAPI ImageListImpl_Release(IImageList *iface)
+static ULONG WINAPI ImageListImpl_Release(IImageList2 *iface)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST This = impl_from_IImageList2(iface);
     ULONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) refcount=%u\n", iface, ref);
@@ -3219,24 +3438,24 @@ static ULONG WINAPI ImageListImpl_Release(IImageList *iface)
         if (This->hbrBlend25) DeleteObject (This->hbrBlend25);
         if (This->hbrBlend50) DeleteObject (This->hbrBlend50);
 
-        This->lpVtbl = NULL;
-        HeapFree(GetProcessHeap(), 0, This->has_alpha);
-        HeapFree(GetProcessHeap(), 0, This);
+        This->IImageList2_iface.lpVtbl = NULL;
+        heap_free(This->has_alpha);
+        heap_free(This);
     }
 
     return ref;
 }
 
-static HRESULT WINAPI ImageListImpl_Add(IImageList *iface, HBITMAP hbmImage,
+static HRESULT WINAPI ImageListImpl_Add(IImageList2 *iface, HBITMAP hbmImage,
     HBITMAP hbmMask, int *pi)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     int ret;
 
     if (!pi)
         return E_FAIL;
 
-    ret = ImageList_Add(This, hbmImage, hbmMask);
+    ret = ImageList_Add(imgl, hbmImage, hbmMask);
 
     if (ret == -1)
         return E_FAIL;
@@ -3245,16 +3464,16 @@ static HRESULT WINAPI ImageListImpl_Add(IImageList *iface, HBITMAP hbmImage,
     return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_ReplaceIcon(IImageList *iface, int i,
+static HRESULT WINAPI ImageListImpl_ReplaceIcon(IImageList2 *iface, int i,
     HICON hicon, int *pi)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     int ret;
 
     if (!pi)
         return E_FAIL;
 
-    ret = ImageList_ReplaceIcon(This, i, hicon);
+    ret = ImageList_ReplaceIcon(imgl, i, hicon);
 
     if (ret == -1)
         return E_FAIL;
@@ -3263,30 +3482,30 @@ static HRESULT WINAPI ImageListImpl_ReplaceIcon(IImageList *iface, int i,
     return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_SetOverlayImage(IImageList *iface,
+static HRESULT WINAPI ImageListImpl_SetOverlayImage(IImageList2 *iface,
     int iImage, int iOverlay)
 {
-    return ImageList_SetOverlayImage((HIMAGELIST) iface, iImage, iOverlay)
-        ? S_OK : E_FAIL;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    return ImageList_SetOverlayImage(imgl, iImage, iOverlay) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_Replace(IImageList *iface, int i,
+static HRESULT WINAPI ImageListImpl_Replace(IImageList2 *iface, int i,
     HBITMAP hbmImage, HBITMAP hbmMask)
 {
-    return ImageList_Replace((HIMAGELIST) iface, i, hbmImage, hbmMask) ? S_OK :
-        E_FAIL;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    return ImageList_Replace(imgl, i, hbmImage, hbmMask) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_AddMasked(IImageList *iface, HBITMAP hbmImage,
+static HRESULT WINAPI ImageListImpl_AddMasked(IImageList2 *iface, HBITMAP hbmImage,
     COLORREF crMask, int *pi)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     int ret;
 
     if (!pi)
         return E_FAIL;
 
-    ret = ImageList_AddMasked(This, hbmImage, crMask);
+    ret = ImageList_AddMasked(imgl, hbmImage, crMask);
 
     if (ret == -1)
         return E_FAIL;
@@ -3295,17 +3514,17 @@ static HRESULT WINAPI ImageListImpl_AddMasked(IImageList *iface, HBITMAP hbmImag
     return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_Draw(IImageList *iface,
+static HRESULT WINAPI ImageListImpl_Draw(IImageList2 *iface,
     IMAGELISTDRAWPARAMS *pimldp)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     HIMAGELIST old_himl;
     int ret;
 
     /* As far as I can tell, Windows simply ignores the contents of pimldp->himl
        so we shall simulate the same */
     old_himl = pimldp->himl;
-    pimldp->himl = This;
+    pimldp->himl = imgl;
 
     ret = ImageList_DrawIndirect(pimldp);
 
@@ -3313,20 +3532,22 @@ static HRESULT WINAPI ImageListImpl_Draw(IImageList *iface,
     return ret ? S_OK : E_INVALIDARG;
 }
 
-static HRESULT WINAPI ImageListImpl_Remove(IImageList *iface, int i)
+static HRESULT WINAPI ImageListImpl_Remove(IImageList2 *iface, int i)
 {
-    return (ImageList_Remove((HIMAGELIST) iface, i) == 0) ? E_INVALIDARG : S_OK;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    return (ImageList_Remove(imgl, i) == 0) ? E_INVALIDARG : S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_GetIcon(IImageList *iface, int i, UINT flags,
+static HRESULT WINAPI ImageListImpl_GetIcon(IImageList2 *iface, int i, UINT flags,
     HICON *picon)
 {
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     HICON hIcon;
 
     if (!picon)
         return E_FAIL;
 
-    hIcon = ImageList_GetIcon((HIMAGELIST) iface, i, flags);
+    hIcon = ImageList_GetIcon(imgl, i, flags);
 
     if (hIcon == NULL)
         return E_FAIL;
@@ -3335,28 +3556,35 @@ static HRESULT WINAPI ImageListImpl_GetIcon(IImageList *iface, int i, UINT flags
     return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_GetImageInfo(IImageList *iface, int i,
+static HRESULT WINAPI ImageListImpl_GetImageInfo(IImageList2 *iface, int i,
     IMAGEINFO *pImageInfo)
 {
-    return ImageList_GetImageInfo((HIMAGELIST) iface, i, pImageInfo) ? S_OK : E_FAIL;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    return ImageList_GetImageInfo(imgl, i, pImageInfo) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_Copy(IImageList *iface, int iDst,
-    IUnknown *punkSrc, int iSrc, UINT uFlags)
+static HRESULT WINAPI ImageListImpl_Copy(IImageList2 *iface, int dst_index,
+    IUnknown *unk_src, int src_index, UINT flags)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     IImageList *src = NULL;
     HRESULT ret;
 
-    if (!punkSrc)
+    if (!unk_src)
+        return E_FAIL;
+
+#ifdef __REACTOS__
+    /* Make sure that the second image list uses the same implementation with the first */
+    if (!is_valid2((HIMAGELIST)unk_src))
         return E_FAIL;
+#endif
 
     /* TODO: Add test for IID_ImageList2 too */
-    if (FAILED(IImageList_QueryInterface(punkSrc, &IID_IImageList,
+    if (FAILED(IUnknown_QueryInterface(unk_src, &IID_IImageList,
             (void **) &src)))
         return E_FAIL;
 
-    if (ImageList_Copy(This, iDst, (HIMAGELIST) src, iSrc, uFlags))
+    if (ImageList_Copy(imgl, dst_index, (HIMAGELIST) src, src_index, flags))
         ret = S_OK;
     else
         ret = E_FAIL;
@@ -3365,151 +3593,159 @@ static HRESULT WINAPI ImageListImpl_Copy(IImageList *iface, int iDst,
     return ret;
 }
 
-static HRESULT WINAPI ImageListImpl_Merge(IImageList *iface, int i1,
+static HRESULT WINAPI ImageListImpl_Merge(IImageList2 *iface, int i1,
     IUnknown *punk2, int i2, int dx, int dy, REFIID riid, void **ppv)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     IImageList *iml2 = NULL;
-    HIMAGELIST hNew;
+    HIMAGELIST merged;
     HRESULT ret = E_FAIL;
 
     TRACE("(%p)->(%d %p %d %d %d %s %p)\n", iface, i1, punk2, i2, dx, dy, debugstr_guid(riid), ppv);
 
+#ifdef __REACTOS__
+    /* Make sure that the second image list uses the same implementation with the first */
+    if (!is_valid2((HIMAGELIST)punk2))
+        return E_FAIL;
+#endif
+
     /* TODO: Add test for IID_ImageList2 too */
-    if (FAILED(IImageList_QueryInterface(punk2, &IID_IImageList,
+    if (FAILED(IUnknown_QueryInterface(punk2, &IID_IImageList,
             (void **) &iml2)))
         return E_FAIL;
 
-    hNew = ImageList_Merge(This, i1, (HIMAGELIST) iml2, i2, dx, dy);
+    merged = ImageList_Merge(imgl, i1, (HIMAGELIST) iml2, i2, dx, dy);
 
     /* Get the interface for the new image list */
-    if (hNew)
+    if (merged)
     {
-        IImageList *imerge = (IImageList*)hNew;
-
-        ret = HIMAGELIST_QueryInterface(hNew, riid, ppv);
-        IImageList_Release(imerge);
+        ret = HIMAGELIST_QueryInterface(merged, riid, ppv);
+        ImageList_Destroy(merged);
     }
 
     IImageList_Release(iml2);
     return ret;
 }
 
-static HRESULT WINAPI ImageListImpl_Clone(IImageList *iface, REFIID riid, void **ppv)
+static HRESULT WINAPI ImageListImpl_Clone(IImageList2 *iface, REFIID riid, void **ppv)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     HIMAGELIST clone;
     HRESULT ret = E_FAIL;
 
     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
 
-    clone = ImageList_Duplicate(This);
+    clone = ImageList_Duplicate(imgl);
 
     /* Get the interface for the new image list */
     if (clone)
     {
-        IImageList *iclone = (IImageList*)clone;
-
         ret = HIMAGELIST_QueryInterface(clone, riid, ppv);
-        IImageList_Release(iclone);
+        ImageList_Destroy(clone);
     }
 
     return ret;
 }
 
-static HRESULT WINAPI ImageListImpl_GetImageRect(IImageList *iface, int i,
+static HRESULT WINAPI ImageListImpl_GetImageRect(IImageList2 *iface, int i,
     RECT *prc)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
     IMAGEINFO info;
 
     if (!prc)
         return E_FAIL;
 
-    if (!ImageList_GetImageInfo(This, i, &info))
+    if (!ImageList_GetImageInfo(imgl, i, &info))
         return E_FAIL;
 
-    return CopyRect(prc, &info.rcImage) ? S_OK : E_FAIL;
+    *prc = info.rcImage;
+
+    return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_GetIconSize(IImageList *iface, int *cx,
+static HRESULT WINAPI ImageListImpl_GetIconSize(IImageList2 *iface, int *cx,
     int *cy)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
-
-    return ImageList_GetIconSize(This, cx, cy) ? S_OK : E_INVALIDARG;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    return ImageList_GetIconSize(imgl, cx, cy) ? S_OK : E_INVALIDARG;
 }
 
-static HRESULT WINAPI ImageListImpl_SetIconSize(IImageList *iface, int cx,
+static HRESULT WINAPI ImageListImpl_SetIconSize(IImageList2 *iface, int cx,
     int cy)
 {
-    return ImageList_SetIconSize((HIMAGELIST) iface, cx, cy) ? S_OK : E_FAIL;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    return ImageList_SetIconSize(imgl, cx, cy) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_GetImageCount(IImageList *iface, int *pi)
+static HRESULT WINAPI ImageListImpl_GetImageCount(IImageList2 *iface, int *pi)
 {
-    *pi = ImageList_GetImageCount((HIMAGELIST) iface);
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    *pi = ImageList_GetImageCount(imgl);
     return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_SetImageCount(IImageList *iface,
-    UINT uNewCount)
+static HRESULT WINAPI ImageListImpl_SetImageCount(IImageList2 *iface, UINT count)
 {
-    return ImageList_SetImageCount((HIMAGELIST) iface, uNewCount) ? S_OK : E_FAIL;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    return ImageList_SetImageCount(imgl, count) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_SetBkColor(IImageList *iface, COLORREF clrBk,
+static HRESULT WINAPI ImageListImpl_SetBkColor(IImageList2 *iface, COLORREF clrBk,
     COLORREF *pclr)
 {
-    *pclr = ImageList_SetBkColor((HIMAGELIST) iface, clrBk);
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    *pclr = ImageList_SetBkColor(imgl, clrBk);
     return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_GetBkColor(IImageList *iface, COLORREF *pclr)
+static HRESULT WINAPI ImageListImpl_GetBkColor(IImageList2 *iface, COLORREF *pclr)
 {
-    *pclr = ImageList_GetBkColor((HIMAGELIST) iface);
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    *pclr = ImageList_GetBkColor(imgl);
     return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_BeginDrag(IImageList *iface, int iTrack,
+static HRESULT WINAPI ImageListImpl_BeginDrag(IImageList2 *iface, int iTrack,
     int dxHotspot, int dyHotspot)
 {
-    return ImageList_BeginDrag((HIMAGELIST) iface, iTrack, dxHotspot, dyHotspot) ? S_OK : E_FAIL;
+    HIMAGELIST imgl = impl_from_IImageList2(iface);
+    return ImageList_BeginDrag(imgl, iTrack, dxHotspot, dyHotspot) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_EndDrag(IImageList *iface)
+static HRESULT WINAPI ImageListImpl_EndDrag(IImageList2 *iface)
 {
     ImageList_EndDrag();
     return S_OK;
 }
 
-static HRESULT WINAPI ImageListImpl_DragEnter(IImageList *iface, HWND hwndLock,
+static HRESULT WINAPI ImageListImpl_DragEnter(IImageList2 *iface, HWND hwndLock,
     int x, int y)
 {
     return ImageList_DragEnter(hwndLock, x, y) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_DragLeave(IImageList *iface, HWND hwndLock)
+static HRESULT WINAPI ImageListImpl_DragLeave(IImageList2 *iface, HWND hwndLock)
 {
     return ImageList_DragLeave(hwndLock) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_DragMove(IImageList *iface, int x, int y)
+static HRESULT WINAPI ImageListImpl_DragMove(IImageList2 *iface, int x, int y)
 {
     return ImageList_DragMove(x, y) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_SetDragCursorImage(IImageList *iface,
+static HRESULT WINAPI ImageListImpl_SetDragCursorImage(IImageList2 *iface,
     IUnknown *punk, int iDrag, int dxHotspot, int dyHotspot)
 {
     IImageList *iml2 = NULL;
-    HRESULT ret;
+    BOOL ret;
 
     if (!punk)
         return E_FAIL;
 
     /* TODO: Add test for IID_ImageList2 too */
-    if (FAILED(IImageList_QueryInterface(punk, &IID_IImageList,
+    if (FAILED(IUnknown_QueryInterface(punk, &IID_IImageList,
             (void **) &iml2)))
         return E_FAIL;
 
@@ -3521,12 +3757,12 @@ static HRESULT WINAPI ImageListImpl_SetDragCursorImage(IImageList *iface,
     return ret ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_DragShowNolock(IImageList *iface, BOOL fShow)
+static HRESULT WINAPI ImageListImpl_DragShowNolock(IImageList2 *iface, BOOL fShow)
 {
     return ImageList_DragShowNolock(fShow) ? S_OK : E_FAIL;
 }
 
-static HRESULT WINAPI ImageListImpl_GetDragImage(IImageList *iface, POINT *ppt,
+static HRESULT WINAPI ImageListImpl_GetDragImage(IImageList2 *iface, POINT *ppt,
     POINT *pptHotspot, REFIID riid, PVOID *ppv)
 {
     HRESULT ret = E_FAIL;
@@ -3549,17 +3785,17 @@ static HRESULT WINAPI ImageListImpl_GetDragImage(IImageList *iface, POINT *ppt,
     return ret;
 }
 
-static HRESULT WINAPI ImageListImpl_GetItemFlags(IImageList *iface, int i,
+static HRESULT WINAPI ImageListImpl_GetItemFlags(IImageList2 *iface, int i,
     DWORD *dwFlags)
 {
     FIXME("STUB: %p %d %p\n", iface, i, dwFlags);
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI ImageListImpl_GetOverlayImage(IImageList *iface, int iOverlay,
+static HRESULT WINAPI ImageListImpl_GetOverlayImage(IImageList2 *iface, int iOverlay,
     int *piIndex)
 {
-    HIMAGELIST This = (HIMAGELIST) iface;
+    HIMAGELIST This = impl_from_IImageList2(iface);
     int i;
 
     if ((iOverlay < 0) || (iOverlay > This->cCurImage))
@@ -3577,8 +3813,80 @@ static HRESULT WINAPI ImageListImpl_GetOverlayImage(IImageList *iface, int iOver
     return E_FAIL;
 }
 
+static HRESULT WINAPI ImageListImpl_Resize(IImageList2 *iface, INT cx, INT cy)
+{
+    FIXME("(%p)->(%d %d): stub\n", iface, cx, cy);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_GetOriginalSize(IImageList2 *iface, INT image, DWORD flags, INT *cx, INT *cy)
+{
+    FIXME("(%p)->(%d %x %p %p): stub\n", iface, image, flags, cx, cy);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_SetOriginalSize(IImageList2 *iface, INT image, INT cx, INT cy)
+{
+    FIXME("(%p)->(%d %d %d): stub\n", iface, image, cx, cy);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_SetCallback(IImageList2 *iface, IUnknown *callback)
+{
+    FIXME("(%p)->(%p): stub\n", iface, callback);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_GetCallback(IImageList2 *iface, REFIID riid, void **ppv)
+{
+    FIXME("(%p)->(%s %p): stub\n", iface, debugstr_guid(riid), ppv);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_ForceImagePresent(IImageList2 *iface, INT image, DWORD flags)
+{
+    FIXME("(%p)->(%d %x): stub\n", iface, image, flags);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_DiscardImages(IImageList2 *iface, INT first_image, INT last_image, DWORD flags)
+{
+    FIXME("(%p)->(%d %d %x): stub\n", iface, first_image, last_image, flags);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_PreloadImages(IImageList2 *iface, IMAGELISTDRAWPARAMS *params)
+{
+    FIXME("(%p)->(%p): stub\n", iface, params);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_GetStatistics(IImageList2 *iface, IMAGELISTSTATS *stats)
+{
+    FIXME("(%p)->(%p): stub\n", iface, stats);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_Initialize(IImageList2 *iface, INT cx, INT cy, UINT flags, INT initial, INT grow)
+{
+    FIXME("(%p)->(%d %d %d %d %d): stub\n", iface, cx, cy, flags, initial, grow);
+    return E_NOTIMPL;
+}
 
-static const IImageListVtbl ImageListImpl_Vtbl = {
+static HRESULT WINAPI ImageListImpl_Replace2(IImageList2 *iface, INT i, HBITMAP image, HBITMAP mask, IUnknown *unk, DWORD flags)
+{
+    FIXME("(%p)->(%d %p %p %p %x): stub\n", iface, i, image, mask, unk, flags);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ImageListImpl_ReplaceFromImageList(IImageList2 *iface, INT i, IImageList *imagelist, INT src,
+    IUnknown *unk, DWORD flags)
+{
+    FIXME("(%p)->(%d %p %d %p %x): stub\n", iface, i, imagelist, src, unk, flags);
+    return E_NOTIMPL;
+}
+
+static const IImageList2Vtbl ImageListImpl_Vtbl = {
     ImageListImpl_QueryInterface,
     ImageListImpl_AddRef,
     ImageListImpl_Release,
@@ -3610,12 +3918,39 @@ static const IImageListVtbl ImageListImpl_Vtbl = {
     ImageListImpl_DragShowNolock,
     ImageListImpl_GetDragImage,
     ImageListImpl_GetItemFlags,
-    ImageListImpl_GetOverlayImage
+    ImageListImpl_GetOverlayImage,
+    ImageListImpl_Resize,
+    ImageListImpl_GetOriginalSize,
+    ImageListImpl_SetOriginalSize,
+    ImageListImpl_SetCallback,
+    ImageListImpl_GetCallback,
+    ImageListImpl_ForceImagePresent,
+    ImageListImpl_DiscardImages,
+    ImageListImpl_PreloadImages,
+    ImageListImpl_GetStatistics,
+    ImageListImpl_Initialize,
+    ImageListImpl_Replace2,
+    ImageListImpl_ReplaceFromImageList
 };
 
-static inline BOOL is_valid(HIMAGELIST himl)
+static BOOL is_valid(HIMAGELIST himl)
 {
-    return himl && himl->lpVtbl == &ImageListImpl_Vtbl;
+    BOOL valid;
+    __TRY
+    {
+    #ifdef __REACTOS__
+        valid = himl && himl->usMagic == IMAGELIST_MAGIC;
+    #else
+        valid = himl && himl->IImageList2_iface.lpVtbl == &ImageListImpl_Vtbl;
+    #endif
+
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        valid = FALSE;
+    }
+    __ENDTRY
+    return valid;
 }
 
 /*************************************************************************
@@ -3637,7 +3972,7 @@ HRESULT WINAPI
 HIMAGELIST_QueryInterface (HIMAGELIST himl, REFIID riid, void **ppv)
 {
     TRACE("(%p,%s,%p)\n", himl, debugstr_guid(riid), ppv);
-    return IImageList_QueryInterface((IImageList *) himl, riid, ppv);
+    return IImageList2_QueryInterface((IImageList2 *) himl, riid, ppv);
 }
 
 static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv)
@@ -3651,14 +3986,325 @@ static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID ii
 
     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
 
-    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct _IMAGELIST));
+    This = heap_alloc_zero(sizeof(struct _IMAGELIST));
     if (!This) return E_OUTOFMEMORY;
 
-    This->lpVtbl = &ImageListImpl_Vtbl;
+    This->IImageList2_iface.lpVtbl = &ImageListImpl_Vtbl;
+#ifdef __REACTOS__
+    This->usMagic = IMAGELIST_MAGIC;
+#endif
     This->ref = 1;
 
-    ret = IUnknown_QueryInterface((IUnknown*)This, iid, ppv);
-    IUnknown_Release((IUnknown*)This);
+    ret = IImageList2_QueryInterface(&This->IImageList2_iface, iid, ppv);
+    IImageList2_Release(&This->IImageList2_iface);
 
     return ret;
 }
+
+
+
+#ifdef __REACTOS__
+//The big bad reactos image list hack!
+#undef ImageList_Add
+#undef ImageList_ReplaceIcon
+#undef ImageList_SetOverlayImage
+#undef ImageList_Replace
+#undef ImageList_AddMasked
+#undef ImageList_Remove
+#undef ImageList_GetIcon
+#undef ImageList_GetImageInfo
+#undef ImageList_Copy
+#undef ImageList_Merge
+#undef ImageList_Duplicate
+#undef ImageList_GetIconSize
+#undef ImageList_SetIconSize
+#undef ImageList_GetImageCount
+#undef ImageList_SetImageCount
+#undef ImageList_SetBkColor
+#undef ImageList_GetBkColor
+#undef ImageList_BeginDrag
+#undef ImageList_DrawIndirect
+
+static inline IImageList2* IImageList2_from_impl(HIMAGELIST himl)
+{
+    if (is_valid(himl))
+    {
+        return &himl->IImageList2_iface;
+    }
+    return NULL;
+}
+
+BOOL is_valid2(HIMAGELIST himl)
+{
+    BOOL valid;
+    __TRY
+    {
+        valid = himl && 
+                himl->IImageList2_iface.lpVtbl == &ImageListImpl_Vtbl && 
+                himl->usMagic == IMAGELIST_MAGIC;
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        valid = FALSE;
+    }
+    __ENDTRY
+    return valid;
+}
+
+INT WINAPI
+ImageList_Add (HIMAGELIST himl,        HBITMAP hbmImage, HBITMAP hbmMask)
+{
+    int res;
+    HRESULT hr;
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return -1;
+
+    hr = piml->lpVtbl->Add(piml, hbmImage, hbmMask, &res);
+    if (FAILED(hr))
+        return -1;
+
+    return res;
+}
+
+INT WINAPI
+ImageList_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon)
+{
+    int res;
+    HRESULT hr;
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return -1;
+
+    hr = piml->lpVtbl->ReplaceIcon(piml, nIndex, hIcon, &res);
+    if (FAILED(hr))
+        return -1;
+
+    return res;
+}
+
+BOOL WINAPI
+ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
+{
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return FALSE;
+
+    return (piml->lpVtbl->SetOverlayImage(piml, iImage, iOverlay) == S_OK) ? TRUE : FALSE;
+}
+
+BOOL WINAPI
+ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
+                  HBITMAP hbmMask)
+{
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return FALSE;
+
+    return (piml->lpVtbl->Replace(piml, i, hbmImage, hbmMask) == S_OK) ? TRUE : FALSE;
+}
+
+INT WINAPI
+ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
+{
+    int res;
+    IImageList2* piml = IImageList2_from_impl(himl);
+    HRESULT hr;
+    if (!piml)
+        return -1;
+
+    hr = piml->lpVtbl->AddMasked(piml, hBitmap, clrMask, &res);
+    if (FAILED(hr))
+        return -1;
+
+    return res;
+}
+
+BOOL WINAPI
+ImageList_Remove (HIMAGELIST himl, INT i)
+{
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return -1;
+
+    return (piml->lpVtbl->Remove(piml, i) == S_OK) ? TRUE : FALSE;
+}
+
+HICON WINAPI
+ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
+{
+    HICON res;
+    IImageList2* piml = IImageList2_from_impl(himl);
+    HRESULT hr;
+    if (!piml)
+        return NULL;
+
+    hr = piml->lpVtbl->GetIcon(piml, i, fStyle, &res);
+    if (FAILED(hr))
+        return NULL;
+
+    return res;
+}
+
+BOOL WINAPI
+ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
+{
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return FALSE;
+
+    return (piml->lpVtbl->GetImageInfo(piml, i, pImageInfo) == S_OK) ? TRUE : FALSE;
+}
+
+BOOL WINAPI
+ImageList_Copy (HIMAGELIST himlDst, INT iDst,  HIMAGELIST himlSrc,
+               INT iSrc, UINT uFlags)
+{
+    IImageList2 *pimlDst, *pimlSrc;
+    pimlDst = IImageList2_from_impl(himlDst);
+    pimlSrc = IImageList2_from_impl(himlSrc);
+    if (!pimlDst || !pimlSrc)
+        return FALSE;
+
+    return (pimlDst->lpVtbl->Copy(pimlDst, iDst, (IUnknown*)pimlSrc, iSrc, uFlags) == S_OK) ? TRUE : FALSE;
+}
+
+HIMAGELIST WINAPI
+ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
+                INT dx, INT dy)
+{
+    HRESULT hr;
+    IImageList2 *piml1, *piml2, *pimlMerged;
+    piml1 = IImageList2_from_impl(himl1);
+    piml2 = IImageList2_from_impl(himl2);
+    if (!piml1 || !piml2)
+        return NULL;
+
+    hr = piml1->lpVtbl->Merge(piml1, i1, (IUnknown*)piml2, i2, dx, dy, &IID_IImageList2, (void**)&pimlMerged);
+    if (FAILED(hr))
+        return NULL;
+
+    return (HIMAGELIST)pimlMerged;
+}
+
+HIMAGELIST WINAPI
+ImageList_Duplicate (HIMAGELIST himlSrc)
+{
+    HRESULT hr;
+    IImageList2 *piml, *pimlCloned;
+    piml = IImageList2_from_impl(himlSrc);
+    if (!piml)
+        return FALSE;
+
+    hr = piml->lpVtbl->Clone(piml, &IID_IImageList2, (void**)&pimlCloned);
+    if (FAILED(hr))
+        return NULL;
+
+    return (HIMAGELIST)pimlCloned;
+}
+
+BOOL WINAPI
+ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
+{
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return FALSE;
+
+    return (piml->lpVtbl->GetIconSize(piml, cx, cy) == S_OK) ? TRUE : FALSE;
+}
+
+BOOL WINAPI
+ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
+{
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return FALSE;
+
+    return (piml->lpVtbl->SetIconSize(piml, cx, cy) == S_OK) ? TRUE : FALSE;
+}
+
+INT WINAPI
+ImageList_GetImageCount (HIMAGELIST himl)
+{
+    int res;
+    HRESULT hr;
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return 0;
+
+    hr = piml->lpVtbl->GetImageCount(piml, &res);
+    if (FAILED(hr))
+        return 0;
+
+    return res;
+}
+
+BOOL WINAPI
+ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount)
+{
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return FALSE;
+
+    return (piml->lpVtbl->SetImageCount(piml, iImageCount) == S_OK) ? TRUE : FALSE;
+}
+
+COLORREF WINAPI
+ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
+{
+    COLORREF res;
+    HRESULT hr;
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return CLR_NONE;
+
+    hr = piml->lpVtbl->SetBkColor(piml, clrBk, &res);
+    if (FAILED(hr))
+        return CLR_NONE;
+
+    return res;
+}
+
+COLORREF WINAPI
+ImageList_GetBkColor (HIMAGELIST himl)
+{
+    COLORREF res;
+    HRESULT hr;
+    IImageList2* piml = IImageList2_from_impl(himl);
+    if (!piml)
+        return CLR_NONE;
+
+    hr = piml->lpVtbl->GetBkColor(piml, &res);
+    if (FAILED(hr))
+        return CLR_NONE;
+
+    return res;
+}
+
+BOOL WINAPI
+ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
+                    INT dxHotspot, INT dyHotspot)
+{
+    IImageList2* piml = IImageList2_from_impl(himlTrack);
+    if (!piml)
+        return FALSE;
+
+    return (piml->lpVtbl->BeginDrag(piml, iTrack, dxHotspot, dyHotspot) == S_OK) ? TRUE : FALSE;
+}
+
+BOOL WINAPI
+ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
+{
+    IImageList2* piml;
+
+    if (!pimldp)
+        return FALSE;
+
+    piml = IImageList2_from_impl(pimldp->himl);
+    if (!piml)
+        return FALSE;
+
+    return (piml->lpVtbl->Draw(piml, pimldp) == S_OK) ? TRUE : FALSE;
+}
+
+#endif