ole32: Convert the OpenDll list to a standard Wine list.

Store the library name and make it reference counted.
This commit is contained in:
Rob Shearman 2007-04-04 18:53:36 +01:00 committed by Alexandre Julliard
parent 7df5deab23
commit 247255568c
1 changed files with 75 additions and 50 deletions

View File

@ -151,12 +151,15 @@ 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 struct tagOpenDll { typedef struct tagOpenDll
HINSTANCE hLibrary; {
struct tagOpenDll *next; LONG refs;
LPWSTR library_name;
HANDLE library;
struct list entry;
} OpenDll; } OpenDll;
static OpenDll *openDllList = NULL; /* linked list of open dlls */ static struct list openDllList = LIST_INIT(openDllList);
static CRITICAL_SECTION csOpenDllList; static CRITICAL_SECTION csOpenDllList;
static CRITICAL_SECTION_DEBUG dll_cs_debug = 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}; '0','x','#','#','#','#','#','#','#','#',' ',0};
static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 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_DllList_FreeUnused(int Timeout);
static void COMPOBJ_InitProcess( void ) static void COMPOBJ_InitProcess( void )
@ -547,44 +552,77 @@ void apartment_joinmta(void)
* This section contains OpenDllList implementation * 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 *entry;
OpenDll *tmp; int len;
HRESULT hr = S_OK;
TRACE("\n"); TRACE("\n");
EnterCriticalSection( &csOpenDllList ); EnterCriticalSection( &csOpenDllList );
if (openDllList == NULL) { *ret = COMPOBJ_DllList_Get(library_name);
/* empty list -- add first node */ if (!*ret)
openDllList = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll)); {
openDllList->hLibrary=hLibrary; len = strlenW(library_name);
openDllList->next = NULL; entry = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));
} else { if (entry)
/* search for this dll */ entry->library_name = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
int found = FALSE; if (entry && entry->library_name)
for (ptr = openDllList; ptr->next != NULL; ptr=ptr->next) { {
if (ptr->hLibrary == hLibrary) { memcpy(entry->library_name, library_name, (len + 1)*sizeof(WCHAR));
found = TRUE; entry->library = hLibrary;
break; 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 ); 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) static void COMPOBJ_DllList_FreeUnused(int Timeout)
{ {
OpenDll *curr, *next, *prev = NULL; OpenDll *curr, *next;
typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void); typedef HRESULT (WINAPI *DllCanUnloadNowFunc)(void);
DllCanUnloadNowFunc DllCanUnloadNow; DllCanUnloadNowFunc DllCanUnloadNow;
@ -592,27 +630,12 @@ static void COMPOBJ_DllList_FreeUnused(int Timeout)
EnterCriticalSection( &csOpenDllList ); EnterCriticalSection( &csOpenDllList );
for (curr = openDllList; curr != NULL; ) { LIST_FOR_EACH_ENTRY_SAFE(curr, next, &openDllList, OpenDll, entry)
DllCanUnloadNow = (DllCanUnloadNowFunc) GetProcAddress(curr->hLibrary, "DllCanUnloadNow"); {
DllCanUnloadNow = (DllCanUnloadNowFunc) GetProcAddress(curr->library, "DllCanUnloadNow");
if ( (DllCanUnloadNow != NULL) && (DllCanUnloadNow() == S_OK) ) { if ( (DllCanUnloadNow != NULL) && (DllCanUnloadNow() == S_OK) )
next = curr->next; COMPOBJ_DllList_ReleaseRef(curr);
TRACE("freeing %p\n", curr->hLibrary);
FreeLibrary(curr->hLibrary);
HeapFree(GetProcessHeap(), 0, curr);
if (curr == openDllList) {
openDllList = next;
} else {
prev->next = next;
}
curr = next;
} else {
prev = curr;
curr = curr->next;
}
} }
LeaveCriticalSection( &csOpenDllList ); LeaveCriticalSection( &csOpenDllList );
@ -1730,6 +1753,7 @@ static HRESULT get_inproc_class_object(HKEY hkeydll, REFCLSID rclsid, REFIID rii
WCHAR dllpath[MAX_PATH+1]; WCHAR dllpath[MAX_PATH+1];
WCHAR threading_model[10 /* strlenW(L"apartment")+1 */]; WCHAR threading_model[10 /* strlenW(L"apartment")+1 */];
HRESULT hr; HRESULT hr;
OpenDll *open_dll_entry;
get_threading_model(hkeydll, threading_model, ARRAYSIZE(threading_model)); get_threading_model(hkeydll, threading_model, ARRAYSIZE(threading_model));
/* "Apartment" */ /* "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? */ 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"))) if (!(DllGetClassObject = (DllGetClassObjectFunc)GetProcAddress(hLibrary, "DllGetClassObject")))
{ {
/* failure: the dll did not export 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 */ /* OK: get the ClassObject */
COMPOBJ_DLLList_Add( hLibrary );
hr = DllGetClassObject(rclsid, riid, ppv); hr = DllGetClassObject(rclsid, riid, ppv);
if (hr != S_OK) if (hr != S_OK)