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