FreeLibrary partial implementation.
diff --git a/loader/module.c b/loader/module.c
index 59a15f3..d91b0a6 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -252,11 +252,15 @@
*/
static void MODULE_IncRefCount( HMODULE hModule )
{
- WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
- if ( !wm ) return;
+ WINE_MODREF *wm;
EnterCriticalSection( &PROCESS_Current()->crit_section );
- wm->refCount++;
+ wm = MODULE32_LookupHMODULE( hModule );
+ if( wm )
+ {
+ wm->refCount++;
+ TRACE(module, "(%08x) count now %d\n", hModule, wm->refCount);
+ }
LeaveCriticalSection( &PROCESS_Current()->crit_section );
}
@@ -265,12 +269,16 @@
*/
static int MODULE_DecRefCount( HMODULE hModule )
{
- int retv;
- WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
- if ( !wm ) return 0;
+ int retv = 0;
+ WINE_MODREF *wm;
EnterCriticalSection( &PROCESS_Current()->crit_section );
- if ( ( retv = wm->refCount ) > 0 ) wm->refCount--;
+ wm = MODULE32_LookupHMODULE( hModule );
+ if( wm && ( retv = wm->refCount ) > 0 )
+ {
+ wm->refCount--;
+ TRACE(module, "(%08x) count now %d\n", hModule, wm->refCount);
+ }
LeaveCriticalSection( &PROCESS_Current()->crit_section );
return retv;
@@ -1188,9 +1196,6 @@
if ( hmod >= 32 )
{
- /* Increment RefCount */
- MODULE_IncRefCount( hmod );
-
/* Initialize DLL just loaded */
MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, NULL );
/* FIXME: check for failure, SLE(ERROR_DLL_INIT_FAILED) */
@@ -1204,9 +1209,15 @@
HMODULE hmod;
hmod = ELF_LoadLibraryExA( libname, hfile, flags );
- if (hmod) return hmod;
+ if(hmod < (HMODULE)32)
+ hmod = PE_LoadLibraryExA( libname, hfile, flags );
- hmod = PE_LoadLibraryExA( libname, hfile, flags );
+ if(hmod >= (HMODULE)32)
+ {
+ /* Increment RefCount */
+ MODULE_IncRefCount( hmod );
+ }
+
return hmod;
}
@@ -1237,17 +1248,100 @@
return ret;
}
+
+/***********************************************************************
+ * MODULE_FreeLibrary (internal)
+ *
+ * Decrease the loadcount of the dll.
+ * If the count reaches 0, then notify the dll and free all dlls
+ * that depend on this one.
+ *
+ */
+static void MODULE_FreeLibrary(WINE_MODREF *wm, BOOL first)
+{
+ int i;
+
+ assert(wm != NULL);
+
+ /* Don't do anything if there still are references */
+ if( MODULE_DecRefCount(wm->module) > 1 )
+ return;
+
+ TRACE( module, "(%s, %08x, %d) - START\n", wm->modname, wm->module, first);
+
+ /* Evaluate module flags */
+ if(!( ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
+ || ( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
+ || ( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE ) ))
+ {
+ /* Now we can call the initialization routine */
+ TRACE( module, "(%s, %08x, %d) - CALL\n", wm->modname, wm->module, first);
+
+ switch ( wm->type )
+ {
+ case MODULE32_PE:
+ PE_InitDLL(wm, DLL_PROCESS_DETACH, (LPVOID)(first ? 0 : 1));
+ break;
+
+ case MODULE32_ELF:
+ FIXME(module, "FreeLibrary requested on ELF module '%s'\n", wm->modname);
+ break;
+
+ default:
+ ERR(module, "wine_modref type %d not handled.\n", wm->type);
+ break;
+ }
+ }
+
+ /* Recursively free all DLLs that depend on this one */
+ for( i = 0; i < wm->nDeps; i++ )
+ {
+ if(wm->deps[i])
+ {
+ MODULE_FreeLibrary(wm->deps[i], FALSE);
+ break;
+ }
+ }
+
+ /* Be sure that the freed library and the list head are unlinked properly */
+ if(PROCESS_Current()->modref_list == wm)
+ PROCESS_Current()->modref_list = wm->next;
+ if(wm->next)
+ wm->next->prev = wm->prev;
+ if(wm->prev)
+ wm->prev->next = wm->next;
+
+ FIXME(module,"should free memory of module %08x '%s'\n", wm->module, wm->modname);
+
+ TRACE( module, "(%s, %08x, %d) - END\n", wm->modname, wm->module, first);
+}
+
+
/***********************************************************************
* FreeLibrary
*/
BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
{
- if ( MODULE_DecRefCount( hLibModule ) != 1 ) return TRUE;
+ WINE_MODREF *wm;
+ BOOL retval = TRUE;
- FIXME(module,"(0x%08x): should unload now\n", hLibModule);
- return TRUE; /* FIXME */
+ EnterCriticalSection(&PROCESS_Current()->crit_section);
+
+ wm = MODULE32_LookupHMODULE(hLibModule);
+ if(!wm)
+ {
+ ERR(module, "(%08x) module not found in process' modref_list. Freed too many times?\n", hLibModule);
+ retval = FALSE;
+ }
+ else
+ MODULE_FreeLibrary(wm, TRUE); /* This always succeeds */
+
+ LeaveCriticalSection(&PROCESS_Current()->crit_section);
+
+ return retval;
}
+
/***********************************************************************
* FreeLibraryAndExitThread
*/