Commit 5ffe867d authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

ole32: Implement CoFreeUnusedLibrariesEx.

Fix CoFreeUnusedLibraries to use a delay of 10 minutes when used with multi-threaded apartments.
parent cd64bf8e
...@@ -181,6 +181,7 @@ struct apartment_loaded_dll ...@@ -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',' ...@@ -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) ...@@ -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, ...@@ -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,7 +807,7 @@ static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, ...@@ -805,7 +807,7 @@ 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);
...@@ -813,10 +815,17 @@ static void apartment_freeunusedlibraries(struct apartment *apt) ...@@ -813,10 +815,17 @@ static void apartment_freeunusedlibraries(struct apartment *apt)
{ {
if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK)) if (entry->dll->DllCanUnloadNow && (entry->dll->DllCanUnloadNow() == S_OK))
{ {
list_remove(&entry->entry); if (!delay || (entry->unload_time && (entry->unload_time < GetTickCount())))
COMPOBJ_DllList_ReleaseRef(entry->dll, TRUE); {
HeapFree(GetProcessHeap(), 0, entry); 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); LeaveCriticalSection(&apt->cs);
} }
...@@ -2482,13 +2491,16 @@ void WINAPI CoFreeAllLibraries(void) ...@@ -2482,13 +2491,16 @@ void WINAPI CoFreeAllLibraries(void)
/* NOP */ /* NOP */
} }
/*********************************************************************** /***********************************************************************
* CoFreeUnusedLibraries [OLE32.@] * CoFreeUnusedLibrariesEx [OLE32.@]
* CoFreeUnusedLibraries [COMPOBJ.17]
* *
* Frees any unused libraries. Unused are identified as those that return * Frees any previously unused libraries whose delay has expired and marks
* S_OK from their DllCanUnloadNow function. * 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 * RETURNS
* Nothing. * Nothing.
...@@ -2496,7 +2508,7 @@ void WINAPI CoFreeAllLibraries(void) ...@@ -2496,7 +2508,7 @@ void WINAPI CoFreeAllLibraries(void)
* SEE ALSO * SEE ALSO
* CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary * CoLoadLibrary, CoFreeAllLibraries, CoFreeLibrary
*/ */
void WINAPI CoFreeUnusedLibraries(void) void WINAPI CoFreeUnusedLibrariesEx(DWORD dwUnloadDelay, DWORD dwReserved)
{ {
struct apartment *apt = COM_CurrentApt(); struct apartment *apt = COM_CurrentApt();
if (!apt) if (!apt)
...@@ -2505,7 +2517,33 @@ void WINAPI CoFreeUnusedLibraries(void) ...@@ -2505,7 +2517,33 @@ void WINAPI CoFreeUnusedLibraries(void)
return; 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);
} }
/*********************************************************************** /***********************************************************************
......
...@@ -20,6 +20,7 @@ ...@@ -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)
......
...@@ -329,6 +329,7 @@ HINSTANCE WINAPI CoLoadLibrary(LPOLESTR lpszLibName, BOOL bAutoFree); ...@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment