Rob Shearman : ole32: Convert the OpenDll list to a standard Wine
list.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed Apr 4 15:40:08 CDT 2007
Module: wine
Branch: master
Commit: 247255568cb5f77db5f255ecf79599901380b2ca
URL: http://source.winehq.org/git/wine.git/?a=commit;h=247255568cb5f77db5f255ecf79599901380b2ca
Author: Rob Shearman <rob at codeweavers.com>
Date: Wed Apr 4 18:53:36 2007 +0100
ole32: Convert the OpenDll list to a standard Wine list.
Store the library name and make it reference counted.
---
dlls/ole32/compobj.c | 125 ++++++++++++++++++++++++++++++--------------------
1 files changed, 75 insertions(+), 50 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index 28bd184..177e17f 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -151,12 +151,15 @@ static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0,
* next unload-call but not before 600 sec.
*/
-typedef struct tagOpenDll {
- HINSTANCE hLibrary;
- struct tagOpenDll *next;
+typedef struct tagOpenDll
+{
+ LONG refs;
+ LPWSTR library_name;
+ HANDLE library;
+ struct list entry;
} OpenDll;
-static OpenDll *openDllList = NULL; /* linked list of open dlls */
+static struct list openDllList = LIST_INIT(openDllList);
static CRITICAL_SECTION csOpenDllList;
static CRITICAL_SECTION_DEBUG dll_cs_debug =
@@ -171,7 +174,9 @@ static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','
'0','x','#','#','#','#','#','#','#','#',' ',0};
static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
-static void COMPOBJ_DLLList_Add(HANDLE hLibrary);
+static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, HANDLE hLibrary, OpenDll **ret);
+static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name);
+static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry);
static void COMPOBJ_DllList_FreeUnused(int Timeout);
static void COMPOBJ_InitProcess( void )
@@ -547,44 +552,77 @@ void apartment_joinmta(void)
* This section contains OpenDllList implementation
*/
-static void COMPOBJ_DLLList_Add(HANDLE hLibrary)
+/* caller must ensure that library_name is not already in the open dll list */
+static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, HANDLE hLibrary, OpenDll **ret)
{
- OpenDll *ptr;
- OpenDll *tmp;
+ OpenDll *entry;
+ int len;
+ HRESULT hr = S_OK;
TRACE("\n");
EnterCriticalSection( &csOpenDllList );
- if (openDllList == NULL) {
- /* empty list -- add first node */
- openDllList = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
- openDllList->hLibrary=hLibrary;
- openDllList->next = NULL;
- } else {
- /* search for this dll */
- int found = FALSE;
- for (ptr = openDllList; ptr->next != NULL; ptr=ptr->next) {
- if (ptr->hLibrary == hLibrary) {
- found = TRUE;
- break;
- }
+ *ret = COMPOBJ_DllList_Get(library_name);
+ if (!*ret)
+ {
+ len = strlenW(library_name);
+ entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
+ if (entry)
+ entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
+ if (entry && entry->library_name)
+ {
+ memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR));
+ entry->library = hLibrary;
+ entry->refs = 1;
+ list_add_tail(&openDllList, &entry->entry);
}
- if (!found) {
- /* dll not found, add it */
- tmp = openDllList;
- openDllList = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
- openDllList->hLibrary = hLibrary;
- openDllList->next = tmp;
- }
+ else
+ hr = E_OUTOFMEMORY;
+ *ret = entry;
}
LeaveCriticalSection( &csOpenDllList );
+
+ return hr;
+}
+
+static OpenDll *COMPOBJ_DllList_Get(LPCWSTR library_name)
+{
+ OpenDll *ptr;
+ OpenDll *ret = NULL;
+ EnterCriticalSection(&csOpenDllList);
+ LIST_FOR_EACH_ENTRY(ptr, &openDllList, OpenDll, entry)
+ {
+ if (!strcmpiW(library_name, ptr->library_name))
+ {
+ ret = ptr;
+ break;
+ }
+ }
+ LeaveCriticalSection(&csOpenDllList);
+ return ret;
+}
+
+static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry)
+{
+ if (!InterlockedDecrement(&entry->refs))
+ {
+ EnterCriticalSection(&csOpenDllList);
+ list_remove(&entry->entry);
+ LeaveCriticalSection(&csOpenDllList);
+
+ TRACE("freeing %p\n", entry->library);
+ FreeLibrary(entry->library);
+
+ HeapFree(GetProcessHeap(), 0, entry->library_name);
+ HeapFree(GetProcessHeap(), 0, entry);
+ }
}
static void COMPOBJ_DllList_FreeUnused(int Timeout)
{
- OpenDll *curr, *next, *prev = NULL;
+ OpenDll *curr, *next;
typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void);
DllCanUnloadNowFunc DllCanUnloadNow;
@@ -592,27 +630,12 @@ static void COMPOBJ_DllList_FreeUnused(int Timeout)
EnterCriticalSection( &csOpenDllList );
- for (curr = openDllList; curr != NULL; ) {
- DllCanUnloadNow = (DllCanUnloadNowFunc) GetProcAddress(curr->hLibrary, "DllCanUnloadNow");
-
- if ( (DllCanUnloadNow != NULL) && (DllCanUnloadNow() == S_OK) ) {
- next = curr->next;
-
- TRACE("freeing %p\n", curr->hLibrary);
- FreeLibrary(curr->hLibrary);
-
- HeapFree(GetProcessHeap(), 0, curr);
- if (curr == openDllList) {
- openDllList = next;
- } else {
- prev->next = next;
- }
+ LIST_FOR_EACH_ENTRY_SAFE(curr, next, &openDllList, OpenDll, entry)
+ {
+ DllCanUnloadNow = (DllCanUnloadNowFunc) GetProcAddress(curr->library, "DllCanUnloadNow");
- curr = next;
- } else {
- prev = curr;
- curr = curr->next;
- }
+ if ( (DllCanUnloadNow != NULL) && (DllCanUnloadNow() == S_OK) )
+ COMPOBJ_DllList_ReleaseRef(curr);
}
LeaveCriticalSection( &csOpenDllList );
@@ -1730,6 +1753,7 @@ static HRESULT get_inproc_class_object(HKEY hkeydll, REFCLSID rclsid, REFIID rii
WCHAR dllpath[MAX_PATH+1];
WCHAR threading_model[10 /* strlenW(L"apartment")+1 */];
HRESULT hr;
+ OpenDll *open_dll_entry;
get_threading_model(hkeydll, threading_model, ARRAYSIZE(threading_model));
/* "Apartment" */
@@ -1821,6 +1845,8 @@ static HRESULT get_inproc_class_object(HKEY hkeydll, REFCLSID rclsid, REFIID rii
return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
}
+ COMPOBJ_DllList_Add( dllpath, hLibrary, &open_dll_entry );
+
if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject")))
{
/* failure: the dll did not export DllGetClassObject */
@@ -1830,7 +1856,6 @@ static HRESULT get_inproc_class_object(HKEY hkeydll, REFCLSID rclsid, REFIID rii
}
/* OK: get the ClassObject */
- COMPOBJ_DLLList_Add( hLibrary );
hr = DllGetClassObject(rclsid, riid, ppv);
if (hr != S_OK)
More information about the wine-cvs
mailing list