ole32: Implement CoFreeUnusedLibrariesEx.
Fix CoFreeUnusedLibraries to use a delay of 10 minutes when used with multi-threaded apartments.
This commit is contained in:
parent
cd64bf8e4d
commit
5ffe867dc7
|
@ -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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue