ole32: Cache the address for the library's DllGetClassObject and DllCanUnloadNow in the OpenDll list entry.
This commit is contained in:
parent
1d8879bccc
commit
30721a88e3
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue