[COMCTL32] imagelist: Make the exported functions use the internal IImageList2

- 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.
This commit is contained in:
Giannis Adamopoulos 2018-12-31 02:28:18 +02:00
parent 419fb423ce
commit cc25a266f2

View 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