From 2393324ce158c6e47d7fc3dcaf1266302e96285b Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Tue, 22 Mar 2016 23:46:30 +0800
Subject: windowscodecs: Improve compatibility of IMILBitmapSource interface.
 (v3)

Based on Focht's investigation. This makes the test application attached
to the bug 34764 work.
---
 dlls/windowscodecs/bitmap.c            | 184 ++++++++++++++++++++++++++-------
 dlls/windowscodecs/wincodecs_private.h |  58 +++++++++--
 2 files changed, 197 insertions(+), 45 deletions(-)

diff --git a/dlls/windowscodecs/bitmap.c b/dlls/windowscodecs/bitmap.c
index 6adaab0..09a5e62 100644
--- a/dlls/windowscodecs/bitmap.c
+++ b/dlls/windowscodecs/bitmap.c
@@ -135,6 +135,7 @@ static HRESULT WINAPI BitmapLockImpl_QueryInterface(IWICBitmapLock *iface, REFII
     }
     else
     {
+        FIXME("unknown interface %s\n", debugstr_guid(iid));
         *ppv = NULL;
         return E_NOINTERFACE;
     }
@@ -248,12 +249,14 @@ static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid,
     {
         *ppv = &This->IWICBitmap_iface;
     }
-    else if (IsEqualIID(&IID_IMILBitmapSource, iid))
+    else if (IsEqualIID(&IID_IMILBitmap, iid) ||
+             IsEqualIID(&IID_IMILBitmapSource, iid))
     {
         *ppv = &This->IMILBitmapSource_iface;
     }
     else
     {
+        FIXME("unknown interface %s\n", debugstr_guid(iid));
         *ppv = NULL;
         return E_NOINTERFACE;
     }
@@ -479,13 +482,22 @@ static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmapSource *iface, REF
     if (!ppv) return E_INVALIDARG;
 
     if (IsEqualIID(&IID_IUnknown, iid) ||
+        IsEqualIID(&IID_IMILBitmap, iid) ||
         IsEqualIID(&IID_IMILBitmapSource, iid))
     {
         IUnknown_AddRef(&This->IMILBitmapSource_iface);
         *ppv = &This->IMILBitmapSource_iface;
         return S_OK;
     }
+    else if (IsEqualIID(&IID_IWICBitmap, iid) ||
+             IsEqualIID(&IID_IWICBitmapSource, iid))
+    {
+        IUnknown_AddRef(&This->IWICBitmap_iface);
+        *ppv = &This->IWICBitmap_iface;
+        return S_OK;
+    }
 
+    FIXME("unknown interface %s\n", debugstr_guid(iid));
     *ppv = NULL;
     return E_NOINTERFACE;
 }
@@ -506,6 +518,7 @@ static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmapSource *iface,
     UINT *width, UINT *height)
 {
     BitmapImpl *This = impl_from_IMILBitmapSource(iface);
+    TRACE("(%p,%p,%p)\n", iface, width, height);
     return IWICBitmap_GetSize(&This->IWICBitmap_iface, width, height);
 }
 
@@ -559,6 +572,7 @@ static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmapSource *iface,
         }
     }
 
+    TRACE("=> %u\n", *format);
     return S_OK;
 }
 
@@ -566,6 +580,7 @@ static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmapSource *iface,
     double *dpix, double *dpiy)
 {
     BitmapImpl *This = impl_from_IMILBitmapSource(iface);
+    TRACE("(%p,%p,%p)\n", iface, dpix, dpiy);
     return IWICBitmap_GetResolution(&This->IWICBitmap_iface, dpix, dpiy);
 }
 
@@ -573,6 +588,7 @@ static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmapSource *iface,
     IWICPalette *palette)
 {
     BitmapImpl *This = impl_from_IMILBitmapSource(iface);
+    TRACE("(%p,%p)\n", iface, palette);
     return IWICBitmap_CopyPalette(&This->IWICBitmap_iface, palette);
 }
 
@@ -580,10 +596,11 @@ static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmapSource *iface,
     const WICRect *rc, UINT stride, UINT size, BYTE *buffer)
 {
     BitmapImpl *This = impl_from_IMILBitmapSource(iface);
+    TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer);
     return IWICBitmap_CopyPixels(&This->IWICBitmap_iface, rc, stride, size, buffer);
 }
 
-static HRESULT WINAPI IMILBitmapImpl_UnknownMethod1(IMILBitmapSource *iface, void **ppv)
+static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmapSource *iface, void **ppv)
 {
     BitmapImpl *This = impl_from_IMILBitmapSource(iface);
 
@@ -591,12 +608,46 @@ static HRESULT WINAPI IMILBitmapImpl_UnknownMethod1(IMILBitmapSource *iface, voi
 
     if (!ppv) return E_INVALIDARG;
 
-    IUnknown_AddRef(&This->IMILUnknown1_iface);
+    /* reference count is not incremented here */
     *ppv = &This->IMILUnknown1_iface;
 
     return S_OK;
 }
 
+static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmapSource *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock)
+{
+    BitmapImpl *This = impl_from_IMILBitmapSource(iface);
+    TRACE("(%p,%p,%08x,%p)\n", iface, rc, flags, lock);
+    return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock);
+}
+
+static HRESULT WINAPI IMILBitmapImpl_Unlock(IMILBitmapSource *iface, IWICBitmapLock *lock)
+{
+    TRACE("(%p,%p)\n", iface, lock);
+    IWICBitmapLock_Release(lock);
+    return S_OK;
+}
+
+static HRESULT WINAPI IMILBitmapImpl_SetPalette(IMILBitmapSource *iface, IWICPalette *palette)
+{
+    BitmapImpl *This = impl_from_IMILBitmapSource(iface);
+    TRACE("(%p,%p)\n", iface, palette);
+    return IWICBitmap_SetPalette(&This->IWICBitmap_iface, palette);
+}
+
+static HRESULT WINAPI IMILBitmapImpl_SetResolution(IMILBitmapSource *iface, double dpix, double dpiy)
+{
+    BitmapImpl *This = impl_from_IMILBitmapSource(iface);
+    TRACE("(%p,%f,%f)\n", iface, dpix, dpiy);
+    return IWICBitmap_SetResolution(&This->IWICBitmap_iface, dpix, dpiy);
+}
+
+static HRESULT WINAPI IMILBitmapImpl_AddDirtyRect(IMILBitmapSource *iface, const WICRect *rc)
+{
+    FIXME("(%p,%p): stub\n", iface, rc);
+    return E_NOTIMPL;
+}
+
 static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl =
 {
     IMILBitmapImpl_QueryInterface,
@@ -607,26 +658,20 @@ static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl =
     IMILBitmapImpl_GetResolution,
     IMILBitmapImpl_CopyPalette,
     IMILBitmapImpl_CopyPixels,
-    IMILBitmapImpl_UnknownMethod1,
+    IMILBitmapImpl_unknown1,
+    IMILBitmapImpl_Lock,
+    IMILBitmapImpl_Unlock,
+    IMILBitmapImpl_SetPalette,
+    IMILBitmapImpl_SetResolution,
+    IMILBitmapImpl_AddDirtyRect
 };
 
 static HRESULT WINAPI IMILUnknown1Impl_QueryInterface(IMILUnknown1 *iface, REFIID iid,
     void **ppv)
 {
-    BitmapImpl *This = impl_from_IMILUnknown1(iface);
-
-    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
-
-    if (!ppv) return E_INVALIDARG;
-
-    if (IsEqualIID(&IID_IUnknown, iid))
-    {
-        IUnknown_AddRef(&This->IMILUnknown1_iface);
-        *ppv = iface;
-        return S_OK;
-    }
-
-    return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv);
+    FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv);
+    *ppv = NULL;
+    return E_NOINTERFACE;
 }
 
 static ULONG WINAPI IMILUnknown1Impl_AddRef(IMILUnknown1 *iface)
@@ -641,47 +686,108 @@ static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface)
     return IWICBitmap_Release(&This->IWICBitmap_iface);
 }
 
+DECLSPEC_HIDDEN void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg)
+{
+    FIXME("(%p,%p): stub\n", iface, arg);
+}
+
+static HRESULT WINAPI IMILUnknown1Impl_unknown2(IMILUnknown1 *iface, void *arg1, void *arg2)
+{
+    FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
+    return E_NOTIMPL;
+}
+
+DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg)
+{
+    FIXME("(%p,%p): stub\n", iface, arg);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IMILUnknown1Impl_unknown4(IMILUnknown1 *iface, void *arg)
+{
+    FIXME("(%p,%p): stub\n", iface, arg);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IMILUnknown1Impl_unknown5(IMILUnknown1 *iface, void *arg)
+{
+    FIXME("(%p,%p): stub\n", iface, arg);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IMILUnknown1Impl_unknown6(IMILUnknown1 *iface, DWORD64 arg)
+{
+    FIXME("(%p,%s): stub\n", iface, wine_dbgstr_longlong(arg));
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IMILUnknown1Impl_unknown7(IMILUnknown1 *iface, void *arg)
+{
+    FIXME("(%p,%p): stub\n", iface, arg);
+    return E_NOTIMPL;
+}
+
+DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface)
+{
+    FIXME("(%p): stub\n", iface);
+    return E_NOTIMPL;
+}
+
+DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown1, 8)
+DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown3, 8)
+DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown8, 4)
+
 static const IMILUnknown1Vtbl IMILUnknown1Impl_Vtbl =
 {
     IMILUnknown1Impl_QueryInterface,
     IMILUnknown1Impl_AddRef,
     IMILUnknown1Impl_Release,
+    THISCALL(IMILUnknown1Impl_unknown1),
+    IMILUnknown1Impl_unknown2,
+    THISCALL(IMILUnknown1Impl_unknown3),
+    IMILUnknown1Impl_unknown4,
+    IMILUnknown1Impl_unknown5,
+    IMILUnknown1Impl_unknown6,
+    IMILUnknown1Impl_unknown7,
+    THISCALL(IMILUnknown1Impl_unknown8)
 };
 
 static HRESULT WINAPI IMILUnknown2Impl_QueryInterface(IMILUnknown2 *iface, REFIID iid,
     void **ppv)
 {
-    BitmapImpl *This = impl_from_IMILUnknown2(iface);
-
-    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
-
-    if (!ppv) return E_INVALIDARG;
-
-    if (IsEqualIID(&IID_IUnknown, iid))
-    {
-        IUnknown_AddRef(&This->IMILUnknown2_iface);
-        *ppv = iface;
-        return S_OK;
-    }
-
-    return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv);
+    FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv);
+    *ppv = NULL;
+    return E_NOINTERFACE;
 }
 
 static ULONG WINAPI IMILUnknown2Impl_AddRef(IMILUnknown2 *iface)
 {
-    BitmapImpl *This = impl_from_IMILUnknown2(iface);
-    return IWICBitmap_AddRef(&This->IWICBitmap_iface);
+    FIXME("(%p): stub\n", iface);
+    return 0;
 }
 
 static ULONG WINAPI IMILUnknown2Impl_Release(IMILUnknown2 *iface)
 {
-    BitmapImpl *This = impl_from_IMILUnknown2(iface);
-    return IWICBitmap_Release(&This->IWICBitmap_iface);
+    FIXME("(%p): stub\n", iface);
+    return 0;
 }
 
-static HRESULT WINAPI IMILUnknown2Impl_UnknownMethod1(IMILUnknown2 *iface, void *arg1, void *arg2)
+static HRESULT WINAPI IMILUnknown2Impl_unknown1(IMILUnknown2 *iface, void *arg1, void **arg2)
 {
     FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
+    if (arg2) *arg2 = NULL;
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IMILUnknown2Impl_unknown2(IMILUnknown2 *iface, void *arg1, void *arg2)
+{
+    FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI IMILUnknown2Impl_unknown3(IMILUnknown2 *iface, void *arg1)
+{
+    FIXME("(%p,%p): stub\n", iface, arg1);
     return E_NOTIMPL;
 }
 
@@ -690,7 +796,9 @@ static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl =
     IMILUnknown2Impl_QueryInterface,
     IMILUnknown2Impl_AddRef,
     IMILUnknown2Impl_Release,
-    IMILUnknown2Impl_UnknownMethod1,
+    IMILUnknown2Impl_unknown1,
+    IMILUnknown2Impl_unknown2,
+    IMILUnknown2Impl_unknown3
 };
 
 HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight,
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index f54403c..218228a 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -30,7 +30,13 @@ DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47
 
 DEFINE_GUID(GUID_VendorWine, 0xddf46da1,0x7dc1,0x404e,0x98,0xf2,0xef,0xa4,0x8d,0xfc,0x95,0x0a);
 
+DEFINE_GUID(IID_IMILBitmap,0xb1784d3f,0x8115,0x4763,0x13,0xaa,0x32,0xed,0xdb,0x68,0x29,0x4a);
 DEFINE_GUID(IID_IMILBitmapSource,0x7543696a,0xbc8d,0x46b0,0x5f,0x81,0x8d,0x95,0x72,0x89,0x72,0xbe);
+DEFINE_GUID(IID_IMILBitmapLock,0xa67b2b53,0x8fa1,0x4155,0x8f,0x64,0x0c,0x24,0x7a,0x8f,0x84,0xcd);
+DEFINE_GUID(IID_IMILBitmapScaler,0xa767b0f0,0x1c8c,0x4aef,0x56,0x8f,0xad,0xf9,0x6d,0xcf,0xd5,0xcb);
+DEFINE_GUID(IID_IMILFormatConverter,0x7e2a746f,0x25c5,0x4851,0xb3,0xaf,0x44,0x3b,0x79,0x63,0x9e,0xc0);
+DEFINE_GUID(IID_IMILPalette,0xca8e206f,0xf22c,0x4af7,0x6f,0xba,0x7b,0xed,0x5e,0xb1,0xc9,0x2f);
+
 #define INTERFACE IMILBitmapSource
 DECLARE_INTERFACE_(IMILBitmapSource,IUnknown)
 {
@@ -38,16 +44,39 @@ DECLARE_INTERFACE_(IMILBitmapSource,IUnknown)
     STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE;
     STDMETHOD_(ULONG,AddRef)(THIS) PURE;
     STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** IWICBitmapSource methods ***/
+    STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE;
+    STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE;
+    STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE;
+    STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE;
+    STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE;
     /*** IMILBitmapSource methods ***/
-    STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *);
-    STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *);
-    STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *);
-    STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *);
-    STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *);
-    STDMETHOD_(HRESULT,UnknownMethod1)(THIS_ void **);
+    STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE;
+    STDMETHOD_(HRESULT,Lock)(THIS_ const WICRect *,DWORD,IWICBitmapLock **) PURE;
+    STDMETHOD_(HRESULT,Unlock)(THIS_ IWICBitmapLock *) PURE;
+    STDMETHOD_(HRESULT,SetPalette)(THIS_ IWICPalette *) PURE;
+    STDMETHOD_(HRESULT,SetResolution)(THIS_ double,double) PURE;
+    STDMETHOD_(HRESULT,AddDirtyRect)(THIS_ const WICRect *) PURE;
 };
 #undef INTERFACE
 
+#ifdef __i386__  /* thiscall functions are i386-specific */
+
+#define THISCALL(func) __thiscall_ ## func
+#define DEFINE_THISCALL_WRAPPER(func,args) \
+    extern typeof(func) THISCALL(func); \
+    __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \
+                    "popl %eax\n\t" \
+                    "pushl %ecx\n\t" \
+                    "pushl %eax\n\t" \
+                    "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) )
+#else /* __i386__ */
+
+#define THISCALL(func) func
+#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */
+
+#endif /* __i386__ */
+
 #define INTERFACE IMILUnknown1
 DECLARE_INTERFACE_(IMILUnknown1,IUnknown)
 {
@@ -55,6 +84,19 @@ DECLARE_INTERFACE_(IMILUnknown1,IUnknown)
     STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE;
     STDMETHOD_(ULONG,AddRef)(THIS) PURE;
     STDMETHOD_(ULONG,Release)(THIS) PURE;
+    /*** thiscall method ***/
+    STDMETHOD_(void,unknown1)(THIS_ void*) PURE;
+    /*** stdcall ***/
+    STDMETHOD_(HRESULT,unknown2)(THIS_ void*, void*) PURE;
+    /*** thiscall method ***/
+    STDMETHOD_(HRESULT,unknown3)(THIS_ void*) PURE;
+     /*** stdcall ***/
+    STDMETHOD_(HRESULT,unknown4)(THIS_ void*) PURE;
+    STDMETHOD_(HRESULT,unknown5)(THIS_ void*) PURE;
+    STDMETHOD_(HRESULT,unknown6)(THIS_ DWORD64) PURE;
+    STDMETHOD_(HRESULT,unknown7)(THIS_ void*) PURE;
+    /*** thiscall method ***/
+    STDMETHOD_(HRESULT,unknown8)(THIS) PURE;
 };
 #undef INTERFACE
 
@@ -66,7 +108,9 @@ DECLARE_INTERFACE_(IMILUnknown2,IUnknown)
     STDMETHOD_(ULONG,AddRef)(THIS) PURE;
     STDMETHOD_(ULONG,Release)(THIS) PURE;
     /*** unknown methods ***/
-    STDMETHOD_(HRESULT,UnknownMethod1)(THIS_ void *, void *) PURE;
+    STDMETHOD_(HRESULT,unknown1)(THIS_ void *,void **) PURE;
+    STDMETHOD_(HRESULT,unknown2)(THIS_ void *,void *) PURE;
+    STDMETHOD_(HRESULT,unknown3)(THIS_ void *) PURE;
 };
 #undef INTERFACE
 
-- 
2.7.1

