[PATCH 1/6] ole32: Convert the OpenDll list to a standard Wine list.

Robert Shearman rob at codeweavers.com
Wed Apr 4 12:53:36 CDT 2007


Store the library name and make it reference counted.
---
  dlls/ole32/compobj.c |  125 
++++++++++++++++++++++++++++++--------------------
  1 files changed, 75 insertions(+), 50 deletions(-)
-------------- next part --------------
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 csRegisteredClas
  * 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[] = {'
                                        '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(i
 
     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(H
     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(H
         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(H
     }
 
     /* OK: get the ClassObject */
-    COMPOBJ_DLLList_Add( hLibrary );
     hr = DllGetClassObject(rclsid, riid, ppv);
 
     if (hr != S_OK)


More information about the wine-patches mailing list