ole32: Cache the address for the library's DllGetClassObject and DllCanUnloadNow in the OpenDll list entry.

This commit is contained in:
Rob Shearman 2007-04-04 18:56:51 +01:00 committed by Alexandre Julliard
parent 1d8879bccc
commit 30721a88e3
1 changed files with 23 additions and 19 deletions

View File

@ -151,11 +151,16 @@ static CRITICAL_SECTION csRegisteredClassList = { &class_cs_debug, -1, 0, 0, 0,
* next unload-call but not before 600 sec. * 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 typedef struct tagOpenDll
{ {
LONG refs; LONG refs;
LPWSTR library_name; LPWSTR library_name;
HANDLE library; HANDLE library;
DllGetClassObjectFunc DllGetClassObject;
DllCanUnloadNowFunc DllCanUnloadNow;
struct list entry; struct list entry;
} OpenDll; } OpenDll;
@ -564,27 +569,14 @@ void apartment_joinmta(void)
static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath, static HRESULT apartment_getclassobject(struct apartment *apt, LPCWSTR dllpath,
REFCLSID rclsid, REFIID riid, void **ppv) REFCLSID rclsid, REFIID riid, void **ppv)
{ {
typedef HRESULT (CALLBACK *DllGetClassObjectFunc)(REFCLSID clsid, REFIID iid, LPVOID *ppv);
DllGetClassObjectFunc DllGetClassObject;
OpenDll *open_dll_entry; OpenDll *open_dll_entry;
HRESULT hr; HRESULT hr;
hr = COMPOBJ_DllList_Add( dllpath, &open_dll_entry ); hr = COMPOBJ_DllList_Add( dllpath, &open_dll_entry );
if (FAILED(hr)) if (FAILED(hr))
{
ERR("couldn't load in-process dll %s\n", debugstr_w(dllpath));
return hr; return hr;
}
if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(open_dll_entry->library, "DllGetClassObject"))) hr = open_dll_entry->DllGetClassObject(rclsid, riid, ppv);
{
/* 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);
if (hr != S_OK) if (hr != S_OK)
ERR("DllGetClassObject returned error 0x%08x\n", hr); ERR("DllGetClassObject returned error 0x%08x\n", hr);
@ -603,6 +595,8 @@ static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret)
int len; int len;
HRESULT hr = S_OK; HRESULT hr = S_OK;
HANDLE hLibrary; HANDLE hLibrary;
DllCanUnloadNowFunc DllCanUnloadNow;
DllGetClassObjectFunc DllGetClassObject;
TRACE("\n"); TRACE("\n");
@ -614,10 +608,22 @@ static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret)
hLibrary = LoadLibraryExW(library_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH); hLibrary = LoadLibraryExW(library_name, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!hLibrary) if (!hLibrary)
{ {
ERR("couldn't load in-process dll %s\n", debugstr_w(library_name));
/* failure: DLL could not be loaded */ /* failure: DLL could not be loaded */
return E_ACCESSDENIED; /* FIXME: or should this be CO_E_DLLNOTFOUND? */ 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 ); EnterCriticalSection( &csOpenDllList );
*ret = COMPOBJ_DllList_Get(library_name); *ret = COMPOBJ_DllList_Get(library_name);
@ -638,6 +644,8 @@ static HRESULT COMPOBJ_DllList_Add(LPCWSTR library_name, OpenDll **ret)
memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR)); memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR));
entry->library = hLibrary; entry->library = hLibrary;
entry->refs = 1; entry->refs = 1;
entry->DllCanUnloadNow = DllCanUnloadNow;
entry->DllGetClassObject = DllGetClassObject;
list_add_tail(&openDllList, &entry->entry); list_add_tail(&openDllList, &entry->entry);
} }
else else
@ -689,8 +697,6 @@ static void COMPOBJ_DllList_ReleaseRef(OpenDll *entry)
static void COMPOBJ_DllList_FreeUnused(int Timeout) static void COMPOBJ_DllList_FreeUnused(int Timeout)
{ {
OpenDll *curr, *next; OpenDll *curr, *next;
typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void);
DllCanUnloadNowFunc DllCanUnloadNow;
TRACE("\n"); TRACE("\n");
@ -698,9 +704,7 @@ static void COMPOBJ_DllList_FreeUnused(int Timeout)
LIST_FOR_EACH_ENTRY_SAFE(curr, next, &openDllList, OpenDll, entry) LIST_FOR_EACH_ENTRY_SAFE(curr, next, &openDllList, OpenDll, entry)
{ {
DllCanUnloadNow = (DllCanUnloadNowFunc) GetProcAddress(curr->library, "DllCanUnloadNow"); if ( (curr->DllCanUnloadNow != NULL) && (curr->DllCanUnloadNow() == S_OK) )
if ( (DllCanUnloadNow != NULL) && (DllCanUnloadNow() == S_OK) )
COMPOBJ_DllList_ReleaseRef(curr); COMPOBJ_DllList_ReleaseRef(curr);
} }