ole32: Implement CoFreeUnusedLibrariesEx.

Fix CoFreeUnusedLibraries to use a delay of 10 minutes when used with 
multi-threaded apartments.
This commit is contained in:
Rob Shearman 2007-09-12 10:02:08 +01:00 committed by Alexandre Julliard
parent cd64bf8e4d
commit 5ffe867dc7
3 changed files with 54 additions and 14 deletions

View file

@ -181,6 +181,7 @@ struct apartment_loaded_dll
{ {
struct list entry; struct list entry;
OpenDll *dll; 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',' ', 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 LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
REFCLSID rclsid, REFIID riid, void **ppv); 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 HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret);
static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name); 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); if (apt->filter) IUnknown_Release(apt->filter);
/* free as many unused libraries as possible... */ /* 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 /* ... and free the memory for the apartment loaded dll entry and
* release the dll list reference without freeing the library for the * 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; hr = E_OUTOFMEMORY;
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {
apartment_loaded_dll->unload_time = 0;
hr = COMPOBJ_DllList_Add( dllpath, &apartment_loaded_dll->dll ); hr = COMPOBJ_DllList_Add( dllpath, &apartment_loaded_dll->dll );
if (FAILED(hr)) if (FAILED(hr))
HeapFree(GetProcessHeap(), 0, apartment_loaded_dll); HeapFree(GetProcessHeap(), 0, apartment_loaded_dll);
@ -805,18 +807,25 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
return hr; return hr;
} }
static void apartment_freeunusedlibraries(struct apartment *apt) static void apartment_freeunusedlibraries(struct apartment *apt, DWORD delay)
{ {
struct apartment_loaded_dll *entry, *next; struct apartment_loaded_dll *entry, *next;
EnterCriticalSection(&apt->cs); EnterCriticalSection(&apt->cs);
LIST_FOR_EACH_ENTRY_SAFE(entry, next, &apt->loaded_dlls, struct apartment_loaded_dll, entry) LIST_FOR_EACH_ENTRY_SAFE(entry, next, &apt->loaded_dlls, struct apartment_loaded_dll, entry)
{ {
if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK)) if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK))
{
if (!delay || (entry->unload_time && (entry->unload_time < GetTickCount())))
{ {
list_remove(&entry->entry); list_remove(&entry->entry);
COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE); COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE);
HeapFree(GetProcessHeap(), 0, entry); HeapFree(GetProcessHeap(), 0, entry);
} }
else
entry->unload_time = GetTickCount() + delay;
}
else if (entry->unload_time)
entry->unload_time = 0;
} }
LeaveCriticalSection(&apt->cs); LeaveCriticalSection(&apt->cs);
} }
@ -2482,6 +2491,42 @@ void WINAPI CoFreeAllLibraries(void)
/* NOP */ /* NOP */
} }
/***********************************************************************
* CoFreeUnusedLibrariesEx [OLE32.@]
*
* 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.
*
* SEE ALSO
* CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary
*/
void WINAPI CoFreeUnusedLibrariesEx(DWORD dwUnloadDelay, DWORD dwReserved)
{
struct apartment *apt = COM_CurrentApt();
if (!apt)
{
ERR("apartment not initialised\n");
return;
}
if (dwUnloadDelay == INFINITE)
{
if (apt->multi_threaded)
dwUnloadDelay = 10 * 60 * 1000; /* 10 minutes */
else
dwUnloadDelay = 0;
}
apartment_freeunusedlibraries(apt, dwUnloadDelay);
}
/*********************************************************************** /***********************************************************************
* CoFreeUnusedLibraries [OLE32.@] * CoFreeUnusedLibraries [OLE32.@]
@ -2498,14 +2543,7 @@ void WINAPI CoFreeAllLibraries(void)
*/ */
void WINAPI CoFreeUnusedLibraries(void) void WINAPI CoFreeUnusedLibraries(void)
{ {
struct apartment *apt = COM_CurrentApt(); CoFreeUnusedLibrariesEx(INFINITE, 0);
if (!apt)
{
ERR("apartment not initialised\n");
return;
}
apartment_freeunusedlibraries(apt);
} }
/*********************************************************************** /***********************************************************************

View file

@ -20,6 +20,7 @@
@ stdcall CoFreeAllLibraries() @ stdcall CoFreeAllLibraries()
@ stdcall CoFreeLibrary(long) @ stdcall CoFreeLibrary(long)
@ stdcall CoFreeUnusedLibraries() @ stdcall CoFreeUnusedLibraries()
@ stdcall CoFreeUnusedLibrariesEx(long long)
@ stdcall CoGetCallContext(ptr ptr) @ stdcall CoGetCallContext(ptr ptr)
@ stub CoGetCallerTID @ stub CoGetCallerTID
@ stdcall CoGetClassObject(ptr long ptr ptr ptr) @ stdcall CoGetClassObject(ptr long ptr ptr ptr)

View file

@ -329,6 +329,7 @@ HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree);
void WINAPI CoFreeAllLibraries(void); void WINAPI CoFreeAllLibraries(void);
void WINAPI CoFreeLibrary(HINSTANCE hLibrary); void WINAPI CoFreeLibrary(HINSTANCE hLibrary);
void WINAPI CoFreeUnusedLibraries(void); 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 CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv);
HRESULT WINAPI CoCreateInstanceEx(REFCLSID rclsid, HRESULT WINAPI CoCreateInstanceEx(REFCLSID rclsid,