Rob Shearman : ole32: Fix circular reference count in default handler objects.

Alexandre Julliard julliard at winehq.org
Tue Nov 24 12:40:24 CST 2009


Module: wine
Branch: master
Commit: 6592c25bc749373cad0e7584ef13e010b4a2431d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6592c25bc749373cad0e7584ef13e010b4a2431d

Author: Rob Shearman <robertshearman at gmail.com>
Date:   Tue Nov 24 14:06:57 2009 +0000

ole32: Fix circular reference count in default handler objects.

This is caused by caching a pointer and reference to the data cache's
IPersistStorage interface without managing reference counts
appropriately.

---

 dlls/ole32/defaulthandler.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/dlls/ole32/defaulthandler.c b/dlls/ole32/defaulthandler.c
index a3da0dd..5130513 100644
--- a/dlls/ole32/defaulthandler.c
+++ b/dlls/ole32/defaulthandler.c
@@ -1960,9 +1960,21 @@ static DefaultHandler* DefaultHandler_Construct(
                        &IID_IUnknown,
                        (void**)&This->dataCache);
   if(SUCCEEDED(hr))
+  {
     hr = IUnknown_QueryInterface(This->dataCache, &IID_IPersistStorage, (void**)&This->dataCache_PersistStg);
+    /* keeping a reference to This->dataCache_PersistStg causes us to keep a
+     * reference on the outer object */
+    if (SUCCEEDED(hr))
+        IUnknown_Release(This->outerUnknown);
+    else
+        IUnknown_Release(This->dataCache);
+  }
   if(FAILED(hr))
+  {
     ERR("Unexpected error creating data cache\n");
+    HeapFree(GetProcessHeap(), 0, This);
+    return NULL;
+  }
 
   This->clsid = *clsid;
   This->clientSite = NULL;
@@ -2009,6 +2021,13 @@ static DefaultHandler* DefaultHandler_Construct(
 static void DefaultHandler_Destroy(
   DefaultHandler* This)
 {
+  TRACE("(%p)\n", This);
+
+  /* AddRef/Release may be called on this object during destruction.
+   * Prevent the object being destroyed recursively by artificially raising
+   * the reference count. */
+  This->ref = 10000;
+
   /* release delegates */
   DefaultHandler_Stop(This);
   release_delegates(This);
@@ -2020,6 +2039,9 @@ static void DefaultHandler_Destroy(
 
   if (This->dataCache)
   {
+    /* to balance out the release of dataCache_PersistStg which will result
+     * in a reference being released from the outer unknown */
+    IUnknown_AddRef(This->outerUnknown);
     IPersistStorage_Release(This->dataCache_PersistStg);
     IUnknown_Release(This->dataCache);
     This->dataCache_PersistStg = NULL;




More information about the wine-cvs mailing list