Rob Shearman : ole32: Implement CoFreeUnusedLibrariesEx.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Sep 12 07:51:04 CDT 2007


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

Author: Rob Shearman <rob at codeweavers.com>
Date:   Wed Sep 12 10:02:08 2007 +0100

ole32: Implement CoFreeUnusedLibrariesEx.

Fix CoFreeUnusedLibraries to use a delay of 10 minutes when used with 
multi-threaded apartments.

---

 dlls/ole32/compobj.c  |   64 +++++++++++++++++++++++++++++++++++++++----------
 dlls/ole32/ole32.spec |    1 +
 include/objbase.h     |    1 +
 3 files changed, 53 insertions(+), 13 deletions(-)

diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 662b42a..e0bcea8 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -181,6 +181,7 @@ struct apartment_loaded_dll
 {
     struct list entry;
     OpenDll *dll;
+    DWORD unload_time;
 };
 
 static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','e','a','d','W','n','d','C','l','a','s','s',' ',
@@ -188,7 +189,7 @@ 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 void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay);
 
 static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret);
 static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name);
@@ -403,7 +404,7 @@ DWORD apartment_release(struct apartment *apt)
         if (apt->filter) IUnknown_Release(apt->filter);
 
         /* free as many unused libraries as possible... */
-        apartment_freeunusedlibraries(apt);
+        apartment_freeunusedlibraries(apt, 0);
 
         /* ... and free the memory for the apartment loaded dll entry and
          * release the dll list reference without freeing the library for the
@@ -779,6 +780,7 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
             hr = E_OUTOFMEMORY;
         if (SUCCEEDED(hr))
         {
+            apartment_loaded_dll->unload_time = 0;
             hr = COMPOBJ_DllList_Add( dllpath, &apartment_loaded_dll->dll );
             if (FAILED(hr))
                 HeapFree(GetProcessHeap(), 0, apartment_loaded_dll);
@@ -805,7 +807,7 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
     return hr;
 }
 
-static void apartment_freeunusedlibraries(struct apartment *apt)
+static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
 {
     struct apartment_loaded_dll *entry, *next;
     EnterCriticalSection(&apt->cs);
@@ -813,10 +815,17 @@ 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, TRUE);
-            HeapFree(GetProcessHeap(), 0, entry);
+            if (!delay || (entry->unload_time && (entry->unload_time < GetTickCount())))
+            {
+                list_remove(&entry->entry);
+                COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE);
+                HeapFree(GetProcessHeap(), 0, entry);
+            }
+            else
+                entry->unload_time = GetTickCount() + delay;
         }
+        else if (entry->unload_time)
+            entry->unload_time = 0;
     }
     LeaveCriticalSection(&apt->cs);
 }
@@ -2482,13 +2491,16 @@ void WINAPI CoFreeAllLibraries(void)
     /* NOP */
 }
 
-
 /***********************************************************************
- *           CoFreeUnusedLibraries [OLE32.@]
- *           CoFreeUnusedLibraries [COMPOBJ.17]
+ *           CoFreeUnusedLibrariesEx [OLE32.@]
  *
- * Frees any unused libraries. Unused are identified as those that return
- * S_OK from their DllCanUnloadNow function.
+ * Frees any previously unused libraries whose delay has expired and marks
+ * currently unused libraries for unloading. Unused are identified as those that
+ * return S_OK from their DllCanUnloadNow function.
+ *
+ * PARAMS
+ *  dwUnloadDelay [I] Unload delay in milliseconds.
+ *  dwReserved    [I] Reserved. Set to 0.
  *
  * RETURNS
  *  Nothing.
@@ -2496,7 +2508,7 @@ void WINAPI CoFreeAllLibraries(void)
  * SEE ALSO
  *  CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary
  */
-void WINAPI CoFreeUnusedLibraries(void)
+void WINAPI CoFreeUnusedLibrariesEx(DWORD dwUnloadDelay, DWORD dwReserved)
 {
     struct apartment *apt = COM_CurrentApt();
     if (!apt)
@@ -2505,7 +2517,33 @@ void WINAPI CoFreeUnusedLibraries(void)
         return;
     }
 
-    apartment_freeunusedlibraries(apt);
+    if (dwUnloadDelay == INFINITE)
+    {
+        if (apt->multi_threaded)
+            dwUnloadDelay = 10 * 60 * 1000; /* 10 minutes */
+        else
+            dwUnloadDelay = 0;
+    }
+
+    apartment_freeunusedlibraries(apt, dwUnloadDelay);
+}
+
+/***********************************************************************
+ *           CoFreeUnusedLibraries [OLE32.@]
+ *           CoFreeUnusedLibraries [COMPOBJ.17]
+ *
+ * Frees any unused libraries. Unused are identified as those that return
+ * S_OK from their DllCanUnloadNow function.
+ *
+ * RETURNS
+ *  Nothing.
+ *
+ * SEE ALSO
+ *  CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary
+ */
+void WINAPI CoFreeUnusedLibraries(void)
+{
+    CoFreeUnusedLibrariesEx(INFINITE, 0);
 }
 
 /***********************************************************************
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec
index e018b0f..0b62995 100644
--- a/dlls/ole32/ole32.spec
+++ b/dlls/ole32/ole32.spec
@@ -20,6 +20,7 @@
 @ stdcall CoFreeAllLibraries()
 @ stdcall CoFreeLibrary(long)
 @ stdcall CoFreeUnusedLibraries()
+@ stdcall CoFreeUnusedLibrariesEx(long long)
 @ stdcall CoGetCallContext(ptr ptr)
 @ stub CoGetCallerTID
 @ stdcall CoGetClassObject(ptr long ptr ptr ptr)
diff --git a/include/objbase.h b/include/objbase.h
index 4d94c05..33fe4c9 100644
--- a/include/objbase.h
+++ b/include/objbase.h
@@ -329,6 +329,7 @@ HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
 void WINAPI CoFreeAllLibraries(void);
 void WINAPI CoFreeLibrary(HINSTANCE hLibrary);
 void WINAPI CoFreeUnusedLibraries(void);
+void WINAPI CoFreeUnusedLibrariesEx(DWORD dwUnloadDelay, DWORD dwReserved);
 
 HRESULT WINAPI CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv);
 HRESULT WINAPI CoCreateInstanceEx(REFCLSID      rclsid,




More information about the wine-cvs mailing list