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;
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,6 +2491,42 @@ void WINAPI CoFreeAllLibraries(void)
/* 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.@]
@ -2498,14 +2543,7 @@ void WINAPI CoFreeAllLibraries(void)
*/
void WINAPI CoFreeUnusedLibraries(void)
{
struct apartment *apt = COM_CurrentApt();
if (!apt)
{
ERR("apartment not initialised\n");
return;
}
apartment_freeunusedlibraries(apt);
CoFreeUnusedLibrariesEx(INFINITE, 0);
}
/***********************************************************************

View File

@ -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)

View File

@ -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,