[PATCH 5/6] ole32: Cache the address for the library's DllGetClassObject and DllCanUnloadNow in the OpenDll list entry.

Robert Shearman rob at codeweavers.com
Wed Apr 4 12:56:51 CDT 2007


---
  dlls/ole32/compobj.c |   44 ++++++++++++++++++++++++--------------------
  1 files changed, 24 insertions(+), 20 deletions(-)
-------------- next part --------------
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index bd5c496..9380bb7 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -151,11 +151,16 @@ static CRITICAL_SECTION csRegisteredClas
  * next unload-call but not before 600 sec.
  */
 
+typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
+typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void);
+
 typedef struct tagOpenDll
 {
   LONG refs;
   LPWSTR library_name;
   HANDLE library;
+  DllGetClassObjectFunc DllGetClassObject;
+  DllCanUnloadNowFunc DllCanUnloadNow;
   struct list entry;
 } OpenDll;
 
@@ -564,27 +569,14 @@ void apartment_joinmta(void)
 static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
                                         REFCLSID rclsid, REFIID riid, void **ppv)
 {
-    typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
-    DllGetClassObjectFunc DllGetClassObject;
     OpenDll *open_dll_entry;
     HRESULT hr;
 
     hr = COMPOBJ_DllList_Add( dllpath, &open_dll_entry );
     if (FAILED(hr))
-    {
-        ERR("couldn't load in-process dll %s\n", debugstr_w(dllpath));
         return hr;
-    }
     
-    if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(open_dll_entry->library, "DllGetClassObject")))
-    {
-        /* failure: the dll did not export DllGetClassObject */
-        ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(dllpath));
-        return CO_E_DLLNOTFOUND;
-    }
-    
-    /* OK: get the ClassObject */
-    hr = DllGetClassObject(rclsid, riid, ppv);
+    hr = open_dll_entry->DllGetClassObject(rclsid, riid, ppv);
     
     if (hr != S_OK)
         ERR("DllGetClassObject returned error 0x%08x\n", hr);
@@ -603,6 +595,8 @@ static HRESULT COMPOBJ_DllList_Add(LPCWS
     int len;
     HRESULT hr = S_OK;
     HANDLE hLibrary;
+    DllCanUnloadNowFunc DllCanUnloadNow;
+    DllGetClassObjectFunc DllGetClassObject;
 
     TRACE("\n");
 
@@ -614,10 +608,22 @@ static HRESULT COMPOBJ_DllList_Add(LPCWS
     hLibrary = LoadLibraryExW(library_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
     if (!hLibrary)
     {
+        ERR("couldn't load in-process dll %s\n", debugstr_w(library_name));
         /* failure: DLL could not be loaded */
         return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */
     }
-    
+
+    DllCanUnloadNow = GetProcAddress(hLibrary, "DllCanUnloadNow");
+    /* Note: failing to find DllCanUnloadNow is not a failure */
+    DllGetClassObject = GetProcAddress(hLibrary, "DllGetClassObject");
+    if (!DllGetClassObject)
+    {
+        /* failure: the dll did not export DllGetClassObject */
+        ERR("couldn't find function DllGetClassObject in %s\n", debugstr_w(library_name));
+        FreeLibrary(hLibrary);
+        return CO_E_DLLNOTFOUND;
+    }
+
     EnterCriticalSection( &csOpenDllList );
 
     *ret = COMPOBJ_DllList_Get(library_name);
@@ -638,6 +644,8 @@ static HRESULT COMPOBJ_DllList_Add(LPCWS
             memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR));
             entry->library = hLibrary;
             entry->refs = 1;
+            entry->DllCanUnloadNow = DllCanUnloadNow;
+            entry->DllGetClassObject = DllGetClassObject;
             list_add_tail(&openDllList, &entry->entry);
         }
         else
@@ -689,8 +697,6 @@ static void COMPOBJ_DllList_ReleaseRef(O
 static void COMPOBJ_DllList_FreeUnused(int Timeout)
 {
     OpenDll *curr, *next;
-    typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void);
-    DllCanUnloadNowFunc DllCanUnloadNow;
 
     TRACE("\n");
 
@@ -698,9 +704,7 @@ static void COMPOBJ_DllList_FreeUnused(i
 
     LIST_FOR_EACH_ENTRY_SAFE(curr, next, &openDllList, OpenDll, entry)
     {
-	DllCanUnloadNow = (DllCanUnloadNowFunc) GetProcAddress(curr->library, "DllCanUnloadNow");
-
-	if ( (DllCanUnloadNow != NULL) && (DllCanUnloadNow() == S_OK) )
+	if ( (curr->DllCanUnloadNow != NULL) && (curr->DllCanUnloadNow() == S_OK) )
             COMPOBJ_DllList_ReleaseRef(curr);
     }
 


More information about the wine-patches mailing list