[PATCH] quartz: Fix FilterGraph2_Connect to be thread-safe and not recurse infinitely any more

Maarten Lankhorst maarten at codeweavers.com
Fri Nov 14 09:42:41 CST 2008


---
 dlls/quartz/filtergraph.c |   40 ++++++++++++++++++++++++++++------------
 1 files changed, 28 insertions(+), 12 deletions(-)

diff --git a/dlls/quartz/filtergraph.c b/dlls/quartz/filtergraph.c
index eec0e44..5b23ab2 100644
--- a/dlls/quartz/filtergraph.c
+++ b/dlls/quartz/filtergraph.c
@@ -204,6 +204,7 @@ typedef struct _IFilterGraphImpl {
     LONGLONG start_time;
     LONGLONG position;
     LONGLONG stop_position;
+    LONG recursioncount;
 } IFilterGraphImpl;
 
 static HRESULT WINAPI Filtergraph_QueryInterface(IFilterGraphImpl *This,
@@ -895,9 +896,18 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
         IBaseFilter_Release(PinInfo.pFilter);
     }
 
+    EnterCriticalSection(&This->cs);
+    ++This->recursioncount;
+    if (This->recursioncount >= 5)
+    {
+        WARN("Recursion count has reached %d\n", This->recursioncount);
+        hr = VFW_E_CANNOT_CONNECT;
+        goto out;
+    }
+
     hr = IPin_QueryDirection(ppinOut, &dir);
     if (FAILED(hr))
-        return hr;
+        goto out;
 
     if (dir == PINDIR_INPUT)
     {
@@ -910,42 +920,44 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
 
     hr = CheckCircularConnection(This, ppinOut, ppinIn);
     if (FAILED(hr))
-        return hr;
+        goto out;
 
     /* Try direct connection first */
     hr = IPin_Connect(ppinOut, ppinIn, NULL);
-    if (SUCCEEDED(hr)) {
-        return S_OK;
-    }
+    if (SUCCEEDED(hr))
+        goto out;
+
     TRACE("Direct connection failed, trying to render using extra filters\n");
 
     hr = IPin_QueryPinInfo(ppinIn, &PinInfo);
     if (FAILED(hr))
-       return hr;
+        goto out;
 
     hr = IBaseFilter_GetClassID(PinInfo.pFilter, &FilterCLSID);
     IBaseFilter_Release(PinInfo.pFilter);
     if (FAILED(hr))
-       return hr;
+        goto out;
 
     /* Find the appropriate transform filter than can transform the minor media type of output pin of the upstream 
      * filter to the minor mediatype of input pin of the renderer */
     hr = IPin_EnumMediaTypes(ppinOut, &penummt);
-    if (FAILED(hr)) {
+    if (FAILED(hr))
+    {
         WARN("EnumMediaTypes (%x)\n", hr);
-        return hr;
+        goto out;
     }
 
     hr = IEnumMediaTypes_Next(penummt, 1, &mt, &nbmt);
     if (FAILED(hr)) {
         WARN("IEnumMediaTypes_Next (%x)\n", hr);
-        return hr;
+        goto out;
     }
 
     if (!nbmt)
     {
         WARN("No media type found!\n");
-        return S_OK;
+        hr = VFW_E_INVALIDMEDIATYPE;
+        goto out;
     }
     TRACE("MajorType %s\n", debugstr_guid(&mt->majortype));
     TRACE("SubType %s\n", debugstr_guid(&mt->subtype));
@@ -956,7 +968,7 @@ static HRESULT WINAPI FilterGraph2_Connect(IFilterGraph2 *iface, IPin *ppinOut,
     hr = IFilterMapper2_EnumMatchingFilters(This->pFilterMapper2, &pEnumMoniker, 0, FALSE, MERIT_UNLIKELY, TRUE, 1, tab, NULL, NULL, FALSE, FALSE, 0, NULL, NULL, NULL);
     if (FAILED(hr)) {
         WARN("Unable to enum filters (%x)\n", hr);
-        return hr;
+        goto out;
     }
 
     hr = VFW_E_CANNOT_RENDER;
@@ -1083,6 +1095,9 @@ error:
     IEnumMediaTypes_Release(penummt);
     DeleteMediaType(mt);
 
+out:
+    --This->recursioncount;
+    LeaveCriticalSection(&This->cs);
     TRACE("--> %08x\n", hr);
     return SUCCEEDED(hr) ? S_OK : hr;
 }
@@ -5429,6 +5444,7 @@ HRESULT FilterGraph_create(IUnknown *pUnkOuter, LPVOID *ppObj)
     fimpl->start_time = fimpl->position = 0;
     fimpl->stop_position = -1;
     fimpl->punkFilterMapper2 = NULL;
+    fimpl->recursioncount = 0;
 
     /* create Filtermapper aggregated. */
     hr = CoCreateInstance(&CLSID_FilterMapper2, pUnkOuter ? pUnkOuter : (IUnknown*)&fimpl->IInner_vtbl, CLSCTX_INPROC_SERVER,
-- 
1.5.6.5


--------------060200030508050908050507--



More information about the wine-patches mailing list