Zebediah Figura : mp3dmod: Support COM aggregation.

Alexandre Julliard julliard at winehq.org
Mon Jun 25 15:41:50 CDT 2018


Module: wine
Branch: master
Commit: 10e4eb8aca7d0278acb988df1a2871de9ce318b8
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=10e4eb8aca7d0278acb988df1a2871de9ce318b8

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Fri Jun 22 13:36:04 2018 -0500

mp3dmod: Support COM aggregation.

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/mp3dmod/mp3dmod.c       | 80 ++++++++++++++++++++++++++++++++------------
 dlls/mp3dmod/tests/mp3dmod.c | 57 +++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 21 deletions(-)

diff --git a/dlls/mp3dmod/mp3dmod.c b/dlls/mp3dmod/mp3dmod.c
index 4949780..90bcf66 100644
--- a/dlls/mp3dmod/mp3dmod.c
+++ b/dlls/mp3dmod/mp3dmod.c
@@ -43,7 +43,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(mp3dmod);
 static HINSTANCE mp3dmod_instance;
 
 struct mp3_decoder {
+    IUnknown IUnknown_inner;
     IMediaObject IMediaObject_iface;
+    IUnknown *outer;
     LONG ref;
     mpg123_handle *mh;
     DMO_MEDIA_TYPE outtype;
@@ -51,33 +53,35 @@ struct mp3_decoder {
     REFERENCE_TIME timestamp;
 };
 
-static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
+static inline struct mp3_decoder *impl_from_IUnknown(IUnknown *iface)
 {
-    return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
+    return CONTAINING_RECORD(iface, struct mp3_decoder, IUnknown_inner);
 }
 
-static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **ppv)
+static HRESULT WINAPI Unknown_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
 {
-    struct mp3_decoder *This = impl_from_IMediaObject(iface);
+    struct mp3_decoder *This = impl_from_IUnknown(iface);
 
-    TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), ppv);
+    TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(iid), obj);
 
-    if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IMediaObject))
-        *ppv = &This->IMediaObject_iface;
+    if (IsEqualGUID(iid, &IID_IUnknown))
+        *obj = &This->IUnknown_inner;
+    else if (IsEqualGUID(iid, &IID_IMediaObject))
+        *obj = &This->IMediaObject_iface;
     else
     {
         FIXME("no interface for %s\n", debugstr_guid(iid));
-        *ppv = NULL;
+        *obj = NULL;
         return E_NOINTERFACE;
     }
 
-    IMediaObject_AddRef(iface);
+    IUnknown_AddRef((IUnknown *)*obj);
     return S_OK;
 }
 
-static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
+static ULONG WINAPI Unknown_AddRef(IUnknown *iface)
 {
-    struct mp3_decoder *This = impl_from_IMediaObject(iface);
+    struct mp3_decoder *This = impl_from_IUnknown(iface);
     ULONG refcount = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) AddRef from %d\n", This, refcount - 1);
@@ -85,9 +89,9 @@ static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
     return refcount;
 }
 
-static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
+static ULONG WINAPI Unknown_Release(IUnknown *iface)
 {
-    struct mp3_decoder *This = impl_from_IMediaObject(iface);
+    struct mp3_decoder *This = impl_from_IUnknown(iface);
     ULONG refcount = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) Release from %d\n", This, refcount + 1);
@@ -100,6 +104,35 @@ static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
     return refcount;
 }
 
+static const IUnknownVtbl Unknown_vtbl = {
+    Unknown_QueryInterface,
+    Unknown_AddRef,
+    Unknown_Release,
+};
+
+static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
+{
+    return CONTAINING_RECORD(iface, struct mp3_decoder, IMediaObject_iface);
+}
+
+static HRESULT WINAPI MediaObject_QueryInterface(IMediaObject *iface, REFIID iid, void **obj)
+{
+    struct mp3_decoder *This = impl_from_IMediaObject(iface);
+    return IUnknown_QueryInterface(This->outer, iid, obj);
+}
+
+static ULONG WINAPI MediaObject_AddRef(IMediaObject *iface)
+{
+    struct mp3_decoder *This = impl_from_IMediaObject(iface);
+    return IUnknown_AddRef(This->outer);
+}
+
+static ULONG WINAPI MediaObject_Release(IMediaObject *iface)
+{
+    struct mp3_decoder *This = impl_from_IMediaObject(iface);
+    return IUnknown_Release(This->outer);
+}
+
 static HRESULT WINAPI MediaObject_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output)
 {
     FIXME("(%p)->(%p, %p) stub!\n", iface, input, output);
@@ -389,7 +422,7 @@ static HRESULT WINAPI MediaObject_Lock(IMediaObject *iface, LONG lock)
     return E_NOTIMPL;
 }
 
-static const IMediaObjectVtbl IMediaObject_vtbl = {
+static const IMediaObjectVtbl MediaObject_vtbl = {
     MediaObject_QueryInterface,
     MediaObject_AddRef,
     MediaObject_Release,
@@ -416,23 +449,28 @@ static const IMediaObjectVtbl IMediaObject_vtbl = {
     MediaObject_Lock,
 };
 
-static HRESULT create_mp3_decoder(REFIID iid, void **obj)
+static HRESULT create_mp3_decoder(IUnknown *outer, REFIID iid, void **obj)
 {
     struct mp3_decoder *This;
+    HRESULT hr;
     int err;
 
     if (!(This = heap_alloc_zero(sizeof(*This))))
         return E_OUTOFMEMORY;
 
-    This->IMediaObject_iface.lpVtbl = &IMediaObject_vtbl;
-    This->ref = 0;
+    This->IUnknown_inner.lpVtbl = &Unknown_vtbl;
+    This->IMediaObject_iface.lpVtbl = &MediaObject_vtbl;
+    This->ref = 1;
+    This->outer = outer ? outer : &This->IUnknown_inner;
 
     mpg123_init();
     This->mh = mpg123_new(NULL, &err);
     mpg123_open_feed(This->mh);
     mpg123_format_none(This->mh);
 
-    return IMediaObject_QueryInterface(&This->IMediaObject_iface, iid, obj);
+    hr = IUnknown_QueryInterface(&This->IUnknown_inner, iid, obj);
+    IUnknown_Release(&This->IUnknown_inner);
+    return hr;
 }
 
 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID iid, void **obj)
@@ -466,13 +504,13 @@ static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown
 {
     TRACE("(%p, %s, %p)\n", outer, debugstr_guid(iid), obj);
 
-    if (outer)
+    if (outer && !IsEqualGUID(iid, &IID_IUnknown))
     {
         *obj = NULL;
-        return CLASS_E_NOAGGREGATION;
+        return E_NOINTERFACE;
     }
 
-    return create_mp3_decoder(iid, obj);
+    return create_mp3_decoder(outer, iid, obj);
 }
 
 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL lock)
diff --git a/dlls/mp3dmod/tests/mp3dmod.c b/dlls/mp3dmod/tests/mp3dmod.c
index 68c6b4d..75fd0e2 100644
--- a/dlls/mp3dmod/tests/mp3dmod.c
+++ b/dlls/mp3dmod/tests/mp3dmod.c
@@ -230,6 +230,62 @@ static void test_convert(void)
     IMediaObject_Release(dmo);
 }
 
+static const GUID IID_test_outer = {0xdeadbeef,0,0,{0,0,0,0,0,0,0,0x66}};
+
+static HRESULT WINAPI Outer_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
+{
+    if (IsEqualGUID(iid, &IID_test_outer))
+    {
+        *obj = (IUnknown *)0xdeadbeef;
+        return S_OK;
+    }
+    ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI Outer_AddRef(IUnknown *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI Outer_Release(IUnknown *iface)
+{
+    return 1;
+}
+
+static IUnknownVtbl Outer_vtbl = {
+    Outer_QueryInterface,
+    Outer_AddRef,
+    Outer_Release,
+};
+
+static IUnknown Outer = { &Outer_vtbl };
+
+static void test_aggregation(void)
+{
+    IUnknown *unk, *unk2;
+    IMediaObject *dmo;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
+        &IID_IUnknown, (void **)&unk);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    hr = IUnknown_QueryInterface(unk, &IID_IMediaObject, (void **)&dmo);
+    ok(hr == S_OK, "got %#x\n", hr);
+
+    hr = IMediaObject_QueryInterface(dmo, &IID_test_outer, (void **)&unk2);
+    ok(hr == S_OK, "got %#x\n", hr);
+    ok(unk2 == (IUnknown *)0xdeadbeef, "got unk %p\n", unk2);
+
+    IUnknown_Release(dmo);
+    IUnknown_Release(unk);
+
+    hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
+        &IID_IMediaObject, (void **)&unk);
+    ok(hr == E_NOINTERFACE, "got %#x\n", hr);
+}
+
 START_TEST(mp3dmod)
 {
     IMediaObject *dmo;
@@ -247,6 +303,7 @@ START_TEST(mp3dmod)
     IMediaObject_Release(dmo);
 
     test_convert();
+    test_aggregation();
 
     CoUninitialize();
 }




More information about the wine-cvs mailing list