[PATCH 4/4] qedit: Support COM aggregation for SampleGrabber.

Michael Stefaniuc mstefani at redhat.de
Tue Jun 26 16:54:49 CDT 2012


---
 dlls/qedit/main.c           |    3 +
 dlls/qedit/samplegrabber.c  |  137 ++++++++++++++++++++++++------------------
 dlls/qedit/tests/mediadet.c |    3 +-
 3 files changed, 82 insertions(+), 61 deletions(-)

diff --git a/dlls/qedit/main.c b/dlls/qedit/main.c
index 734f326..6b0375e 100644
--- a/dlls/qedit/main.c
+++ b/dlls/qedit/main.c
@@ -105,6 +105,9 @@ static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter
     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
 
     *ppobj = NULL;
+    if (pOuter && !IsEqualGUID(&IID_IUnknown, riid))
+        return E_INVALIDARG;
+
     hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
     if (SUCCEEDED(hres)) {
         hres = IUnknown_QueryInterface(punk, riid, ppobj);
diff --git a/dlls/qedit/samplegrabber.c b/dlls/qedit/samplegrabber.c
index 6080b6e..c748c98 100644
--- a/dlls/qedit/samplegrabber.c
+++ b/dlls/qedit/samplegrabber.c
@@ -365,11 +365,13 @@ static inline SG_Pin *impl_from_IPin(IPin *iface)
 
 /* Sample Grabber filter implementation */
 typedef struct _SG_Impl {
+    IUnknown IUnknown_inner;
     IBaseFilter IBaseFilter_iface;
     ISampleGrabber ISampleGrabber_iface;
     IMemInputPin IMemInputPin_iface;
     /* TODO: IMediaPosition, IMediaSeeking, IQualityControl */
-    LONG refCount;
+    IUnknown *outer_unk;
+    LONG ref;
     CRITICAL_SECTION critSect;
     FILTER_INFO info;
     FILTER_STATE state;
@@ -392,7 +394,11 @@ enum {
     OneShot_Past,
 };
 
-/* Get the SampleGrabber implementation This pointer from various interface pointers */
+static inline SG_Impl *impl_from_IUnknown(IUnknown *iface)
+{
+    return CONTAINING_RECORD(iface, SG_Impl, IUnknown_inner);
+}
+
 static inline SG_Impl *impl_from_IBaseFilter(IBaseFilter *iface)
 {
     return CONTAINING_RECORD(iface, SG_Impl, IBaseFilter_iface);
@@ -431,61 +437,71 @@ static void SampleGrabber_cleanup(SG_Impl *This)
     DeleteCriticalSection(&This->critSect);
 }
 
-/* Common helper AddRef called from all interfaces */
-static ULONG SampleGrabber_addref(SG_Impl *This)
+/* SampleGrabber inner IUnknown */
+static HRESULT WINAPI SampleGrabber_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
 {
-    ULONG refCount = InterlockedIncrement(&This->refCount);
-    TRACE("(%p) new ref = %u\n", This, refCount);
-    return refCount;
+    SG_Impl *This = impl_from_IUnknown(iface);
+
+    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+
+    *ppv = NULL;
+    if (IsEqualIID(riid, &IID_IUnknown))
+        *ppv = &This->IUnknown_inner;
+    else if (IsEqualIID(riid, &IID_IPersist) || IsEqualIID(riid, &IID_IMediaFilter) ||
+        IsEqualIID(riid, &IID_IBaseFilter))
+        *ppv = &This->IBaseFilter_iface;
+    else if (IsEqualIID(riid, &IID_ISampleGrabber))
+        *ppv = &This->ISampleGrabber_iface;
+    else if (IsEqualIID(riid, &IID_IMemInputPin))
+        *ppv = &This->IMemInputPin_iface;
+    else if (IsEqualIID(riid, &IID_IMediaPosition))
+        FIXME("IMediaPosition not implemented\n");
+    else if (IsEqualIID(riid, &IID_IMediaSeeking))
+        FIXME("IMediaSeeking not implemented\n");
+    else if (IsEqualIID(riid, &IID_IQualityControl))
+        FIXME("IQualityControl not implemented\n");
+    else
+        WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppv);
+
+    if (!*ppv)
+        return E_NOINTERFACE;
+
+    IUnknown_AddRef((IUnknown*)*ppv);
+    return S_OK;
 }
 
-/* Common helper Release called from all interfaces */
-static ULONG SampleGrabber_release(SG_Impl *This)
+static ULONG WINAPI SampleGrabber_AddRef(IUnknown *iface)
 {
-    ULONG refCount = InterlockedDecrement(&This->refCount);
-    TRACE("(%p) new ref = %u\n", This, refCount);
-    if (refCount == 0)
+    SG_Impl *This = impl_from_IUnknown(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+
+    TRACE("(%p) new ref = %u\n", This, ref);
+
+    return ref;
+}
+
+static ULONG WINAPI SampleGrabber_Release(IUnknown *iface)
+{
+    SG_Impl *This = impl_from_IUnknown(iface);
+    ULONG ref = InterlockedDecrement(&This->ref);
+
+    TRACE("(%p) new ref = %u\n", This, ref);
+
+    if (ref == 0)
     {
         SampleGrabber_cleanup(This);
         CoTaskMemFree(This);
         return 0;
     }
-    return refCount;
+    return ref;
 }
 
-/* Common helper QueryInterface called from all interfaces */
-static HRESULT SampleGrabber_query(SG_Impl *This, REFIID riid, void **ppvObject)
+static const IUnknownVtbl samplegrabber_vtbl =
 {
-    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
-
-    if (IsEqualIID(riid, &IID_IUnknown) ||
-        IsEqualIID(riid, &IID_IPersist) ||
-        IsEqualIID(riid, &IID_IMediaFilter) ||
-        IsEqualIID(riid, &IID_IBaseFilter)) {
-        SampleGrabber_addref(This);
-        *ppvObject = &This->IBaseFilter_iface;
-        return S_OK;
-    }
-    else if (IsEqualIID(riid, &IID_ISampleGrabber)) {
-        SampleGrabber_addref(This);
-        *ppvObject = &This->ISampleGrabber_iface;
-        return S_OK;
-    }
-    else if (IsEqualIID(riid, &IID_IMemInputPin)) {
-        SampleGrabber_addref(This);
-        *ppvObject = &This->IMemInputPin_iface;
-        return S_OK;
-    }
-    else if (IsEqualIID(riid, &IID_IMediaPosition))
-        FIXME("IMediaPosition not implemented\n");
-    else if (IsEqualIID(riid, &IID_IMediaSeeking))
-        FIXME("IMediaSeeking not implemented\n");
-    else if (IsEqualIID(riid, &IID_IQualityControl))
-        FIXME("IQualityControl not implemented\n");
-    *ppvObject = NULL;
-    WARN("(%p, %s,%p): not found\n", This, debugstr_guid(riid), ppvObject);
-    return E_NOINTERFACE;
-}
+    SampleGrabber_QueryInterface,
+    SampleGrabber_AddRef,
+    SampleGrabber_Release,
+};
 
 /* Helper that buffers data and/or calls installed sample callbacks */
 static void SampleGrabber_callback(SG_Impl *This, IMediaSample *sample)
@@ -554,7 +570,7 @@ static HRESULT WINAPI
 SampleGrabber_IBaseFilter_QueryInterface(IBaseFilter *iface, REFIID riid, void **ppv)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
-    return SampleGrabber_query(This, riid, ppv);
+    return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
 }
 
 /* IUnknown */
@@ -562,7 +578,7 @@ static ULONG WINAPI
 SampleGrabber_IBaseFilter_AddRef(IBaseFilter *iface)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
-    return SampleGrabber_addref(This);
+    return IUnknown_AddRef(This->outer_unk);
 }
 
 /* IUnknown */
@@ -570,7 +586,7 @@ static ULONG WINAPI
 SampleGrabber_IBaseFilter_Release(IBaseFilter *iface)
 {
     SG_Impl *This = impl_from_IBaseFilter(iface);
-    return SampleGrabber_release(This);
+    return IUnknown_Release(This->outer_unk);
 }
 
 /* IPersist */
@@ -743,7 +759,7 @@ static HRESULT WINAPI
 SampleGrabber_ISampleGrabber_QueryInterface(ISampleGrabber *iface, REFIID riid, void **ppv)
 {
     SG_Impl *This = impl_from_ISampleGrabber(iface);
-    return SampleGrabber_query(This, riid, ppv);
+    return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
 }
 
 /* IUnknown */
@@ -751,7 +767,7 @@ static ULONG WINAPI
 SampleGrabber_ISampleGrabber_AddRef(ISampleGrabber *iface)
 {
     SG_Impl *This = impl_from_ISampleGrabber(iface);
-    return SampleGrabber_addref(This);
+    return IUnknown_AddRef(This->outer_unk);
 }
 
 /* IUnknown */
@@ -759,7 +775,7 @@ static ULONG WINAPI
 SampleGrabber_ISampleGrabber_Release(ISampleGrabber *iface)
 {
     SG_Impl *This = impl_from_ISampleGrabber(iface);
-    return SampleGrabber_release(This);
+    return IUnknown_Release(This->outer_unk);
 }
 
 /* ISampleGrabber */
@@ -893,7 +909,7 @@ static HRESULT WINAPI
 SampleGrabber_IMemInputPin_QueryInterface(IMemInputPin *iface, REFIID riid, void **ppv)
 {
     SG_Impl *This = impl_from_IMemInputPin(iface);
-    return SampleGrabber_query(This, riid, ppv);
+    return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
 }
 
 /* IUnknown */
@@ -901,7 +917,7 @@ static ULONG WINAPI
 SampleGrabber_IMemInputPin_AddRef(IMemInputPin *iface)
 {
     SG_Impl *This = impl_from_IMemInputPin(iface);
-    return SampleGrabber_addref(This);
+    return IUnknown_AddRef(This->outer_unk);
 }
 
 /* IUnknown */
@@ -909,7 +925,7 @@ static ULONG WINAPI
 SampleGrabber_IMemInputPin_Release(IMemInputPin *iface)
 {
     SG_Impl *This = impl_from_IMemInputPin(iface);
-    return SampleGrabber_release(This);
+    return IUnknown_Release(This->outer_unk);
 }
 
 /* IMemInputPin */
@@ -1454,9 +1470,6 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
 
     TRACE("(%p,%p)\n", ppv, pUnkOuter);
 
-    if (pUnkOuter)
-        return CLASS_E_NOAGGREGATION;
-
     obj = CoTaskMemAlloc(sizeof(SG_Impl));
     if (NULL == obj) {
         *ppv = NULL;
@@ -1464,7 +1477,8 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
     }
     ZeroMemory(obj, sizeof(SG_Impl));
 
-    obj->refCount = 1;
+    obj->ref = 1;
+    obj->IUnknown_inner.lpVtbl = &samplegrabber_vtbl;
     obj->IBaseFilter_iface.lpVtbl = &IBaseFilter_VTable;
     obj->ISampleGrabber_iface.lpVtbl = &ISampleGrabber_VTable;
     obj->IMemInputPin_iface.lpVtbl = &IMemInputPin_VTable;
@@ -1494,7 +1508,12 @@ HRESULT SampleGrabber_create(IUnknown *pUnkOuter, LPVOID *ppv)
     obj->oneShot = OneShot_None;
     obj->bufferLen = -1;
     obj->bufferData = NULL;
-    *ppv = obj;
 
+    if (pUnkOuter)
+        obj->outer_unk = pUnkOuter;
+    else
+        obj->outer_unk = &obj->IUnknown_inner;
+
+    *ppv = &obj->IUnknown_inner;
     return S_OK;
 }
diff --git a/dlls/qedit/tests/mediadet.c b/dlls/qedit/tests/mediadet.c
index 1d75680..1229db6 100644
--- a/dlls/qedit/tests/mediadet.c
+++ b/dlls/qedit/tests/mediadet.c
@@ -353,8 +353,7 @@ static void test_samplegrabber(void)
     /* COM aggregation */
     hr = CoCreateInstance(&CLSID_SampleGrabber, &unk_obj.IUnknown_iface, CLSCTX_INPROC_SERVER,
             &IID_IUnknown, (void**)&unk_obj.inner_unk);
-    todo_wine ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
-    if (hr != S_OK) return;
+    ok(hr == S_OK, "CoCreateInstance failed: %08x\n", hr);
 
     hr = IUnknown_QueryInterface(unk_obj.inner_unk, &IID_ISampleGrabber, (void**)&sg);
     ok(hr == S_OK, "QueryInterface for IID_ISampleGrabber failed: %08x\n", hr);
-- 
1.7.6.5



More information about the wine-patches mailing list