Rob Shearman : ole32: Fix CoUninitialize to only free libraries that return S_OK from DllCanUnloadNow .

Alexandre Julliard julliard at wine.codeweavers.com
Mon May 14 10:52:33 CDT 2007


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

Author: Rob Shearman <rob at codeweavers.com>
Date:   Sun May 13 22:17:23 2007 +0100

ole32: Fix CoUninitialize to only free libraries that return S_OK from DllCanUnloadNow.

---

 dlls/ole32/compobj.c |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 7eef76e..614b426 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -187,10 +187,11 @@ static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','
 static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
 static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
                                         REFCLSID rclsid, REFIID riid, void **ppv);
+static void apartment_freeunusedlibraries(struct apartment *apt);
 
 static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret);
 static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name);
-static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry);
+static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry);
 
 static DWORD COM_RegReadPath(HKEY hkeyroot, const WCHAR *keyname, const WCHAR *valuename, WCHAR * dst, DWORD dstlen);
 
@@ -399,10 +400,16 @@ DWORD apartment_release(struct apartment *apt)
 
         if (apt->filter) IUnknown_Release(apt->filter);
 
+        /* free as many unused libraries as possible... */
+        apartment_freeunusedlibraries(apt);
+
+        /* ... and free the memory for the apartment loaded dll entry and
+         * release the dll list reference without freeing the library for the
+         * rest */
         while ((cursor = list_head(&apt->loaded_dlls)))
         {
             struct apartment_loaded_dll *apartment_loaded_dll = LIST_ENTRY(cursor, struct apartment_loaded_dll, entry);
-            COMPOBJ_DllList_ReleaseRef(apartment_loaded_dll->dll);
+            COMPOBJ_DllList_ReleaseRef(apartment_loaded_dll->dll, FALSE);
             list_remove(cursor);
             HeapFree(GetProcessHeap(), 0, apartment_loaded_dll);
         }
@@ -643,7 +650,7 @@ static void apartment_freeunusedlibraries(struct apartment *apt)
 	if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK))
         {
             list_remove(&entry->entry);
-            COMPOBJ_DllList_ReleaseRef(entry->dll);
+            COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE);
             HeapFree(GetProcessHeap(), 0, entry);
         }
     }
@@ -745,9 +752,11 @@ static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name)
     return ret;
 }
 
-static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry)
+/* pass FALSE for free_entry to release a reference without destroying the
+ * entry if it reaches zero or TRUE otherwise */
+static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry, BOOL free_entry)
 {
-    if (!InterlockedDecrement(&entry->refs))
+    if (!InterlockedDecrement(&entry->refs) && free_entry)
     {
         EnterCriticalSection(&csOpenDllList);
         list_remove(&entry->entry);




More information about the wine-cvs mailing list