Module: wine Branch: master Commit: 5ffe867dc7194b7741fa9fd1aed3eb859d3a8257 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5ffe867dc7194b7741fa9fd1ae...
Author: Rob Shearman rob@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,