[COMCTL32] imagelist: Make the exported functions use the internal IImageList2 1211/head
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Mon, 31 Dec 2018 00:28:18 +0000 (02:28 +0200)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Wed, 12 Jun 2019 16:20:44 +0000 (19:20 +0300)
- Add a hack to rename the exported functions and use the Internal_ prefix for them so that the IImageList can use them with minimal code changes.
- Add the correct implementation of the affected exported functions making them now use the IImageList of the passed HIMAGELIST.

This indirection is possible because an HIMAGELIST is also a IImageList*.
This indirection is also needed because we can end up using image lists created by either comctl32 v5 or comctl32 v6.
This is how windows manage to use an HIMAGELIST created by comctl32 v5 when it is passed to comctl32 v6.
What really happens in this scenario is that the exported functions of both versions end up using the interface
stored in the object without checking if this interface is the version provided in the same dll or in the other.

dll/win32/comctl32/imagelist.c

index 1f119f3..11ad508 100644 (file)
@@ -51,6 +51,35 @@ 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 */
@@ -72,6 +101,9 @@ struct _IMAGELIST
     INT         nOvlIdx[MAX_OVERLAYIMAGE]; /* 38: overlay images index */
 
     /* not yet found out */
+    #ifdef __REACTOS__
+    ULONG   usMagic;
+    #endif
     HBRUSH  hbrBlend25;
     HBRUSH  hbrBlend50;
     INT     cInitial;
@@ -1843,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
 }
 
 
@@ -2032,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))
@@ -2044,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;
 }
 
@@ -3300,6 +3343,10 @@ static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count)
 UINT WINAPI
 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);
@@ -3526,6 +3573,12 @@ static HRESULT WINAPI ImageListImpl_Copy(IImageList2 *iface, int dst_index,
     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(IUnknown_QueryInterface(unk_src, &IID_IImageList,
             (void **) &src)))
@@ -3550,6 +3603,12 @@ static HRESULT WINAPI ImageListImpl_Merge(IImageList2 *iface, int i1,
 
     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(IUnknown_QueryInterface(punk2, &IID_IImageList,
             (void **) &iml2)))
@@ -3879,7 +3938,12 @@ static BOOL is_valid(HIMAGELIST himl)
     BOOL valid;
     __TRY
     {
+    #ifdef __REACTOS__
+        valid = himl && himl->usMagic == IMAGELIST_MAGIC;
+    #else
         valid = himl && himl->IImageList2_iface.lpVtbl == &ImageListImpl_Vtbl;
+    #endif
+
     }
     __EXCEPT_PAGE_FAULT
     {
@@ -3926,6 +3990,9 @@ static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID ii
     if (!This) return E_OUTOFMEMORY;
 
     This->IImageList2_iface.lpVtbl = &ImageListImpl_Vtbl;
+#ifdef __REACTOS__
+    This->usMagic = IMAGELIST_MAGIC;
+#endif
     This->ref = 1;
 
     ret = IImageList2_QueryInterface(&This->IImageList2_iface, iid, ppv);
@@ -3933,3 +4000,311 @@ static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID ii
 
     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