Fixed sequence of DLL_PROCESS_DETACH notification calls.
Moved PE_MODREF flags to WINE_MODREF level.
Better handling of LoadLibraryEx flags.
PE_InitTls() changed to work only on the current thread.
diff --git a/loader/module.c b/loader/module.c
index 86cc727..9d1008e 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -73,37 +73,84 @@
static void MODULE_DoInitializeDLLs( WINE_MODREF *wm,
DWORD type, LPVOID lpReserved )
{
- int i;
+ WINE_MODREF *xwm;
+ int i, skip = FALSE;
- assert( wm && !wm->initDone );
- TRACE( module, "(%08x,%ld,%p) - START\n",
- wm->module, type, lpReserved );
+ assert( wm && !(wm->flags & WINE_MODREF_MARKER) );
+ TRACE( module, "(%s,%08x,%ld,%p) - START\n",
+ wm->modname, wm->module, type, lpReserved );
/* Tag current MODREF to prevent recursive loop */
- wm->initDone = TRUE;
+ wm->flags |= WINE_MODREF_MARKER;
- /* Recursively initialize all child DLLs */
- for ( i = 0; i < wm->nDeps; i++ )
- if ( wm->deps[i] && !wm->deps[i]->initDone )
- MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
-
- /* Now we can call the initialization routine */
- switch ( wm->type )
+ switch ( type )
{
- case MODULE32_PE:
- PE_InitDLL( wm, type, lpReserved );
+ default:
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ /* Recursively attach all DLLs this one depends on */
+ for ( i = 0; i < wm->nDeps; i++ )
+ if ( wm->deps[i] && !(wm->deps[i]->flags & WINE_MODREF_MARKER) )
+ MODULE_DoInitializeDLLs( wm->deps[i], type, lpReserved );
break;
- case MODULE32_ELF:
- /* no need to do that, dlopen() already does */
- break;
- default:
- ERR(module, "wine_modref type %d not handled.\n", wm->type);
+ case DLL_PROCESS_DETACH:
+ case DLL_THREAD_DETACH:
+ /* Recursively detach all DLLs that depend on this one */
+ for ( xwm = PROCESS_Current()->modref_list; xwm; xwm = xwm->next )
+ if ( !(xwm->flags & WINE_MODREF_MARKER) )
+ for ( i = 0; i < xwm->nDeps; i++ )
+ if ( xwm->deps[i] == wm )
+ {
+ MODULE_DoInitializeDLLs( xwm, type, lpReserved );
+ break;
+ }
break;
}
- TRACE( module, "(%08x,%ld,%p) - END\n",
- wm->module, type, lpReserved );
+ /* 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 ) )
+ skip = TRUE;
+
+ if ( type == DLL_PROCESS_ATTACH )
+ if ( wm->flags & WINE_MODREF_PROCESS_ATTACHED )
+ skip = TRUE;
+ else
+ wm->flags |= WINE_MODREF_PROCESS_ATTACHED;
+
+ if ( type == DLL_PROCESS_DETACH )
+ if ( wm->flags & WINE_MODREF_PROCESS_DETACHED )
+ skip = TRUE;
+ else
+ wm->flags |= WINE_MODREF_PROCESS_DETACHED;
+
+ if ( !skip )
+ {
+ /* Now we can call the initialization routine */
+ TRACE( module, "(%s,%08x,%ld,%p) - CALL\n",
+ wm->modname, wm->module, type, lpReserved );
+
+ switch ( wm->type )
+ {
+ case MODULE32_PE:
+ PE_InitDLL( wm, type, lpReserved );
+ break;
+
+ case MODULE32_ELF:
+ /* no need to do that, dlopen() already does */
+ break;
+
+ default:
+ ERR(module, "wine_modref type %d not handled.\n", wm->type);
+ break;
+ }
+ }
+
+ TRACE( module, "(%s,%08x,%ld,%p) - END\n",
+ wm->modname, wm->module, type, lpReserved );
}
void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
@@ -119,7 +166,7 @@
/* First, check whether initialization is currently in progress */
for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
- if ( wm->initDone )
+ if ( wm->flags & WINE_MODREF_MARKER )
{
inProgress = TRUE;
break;
@@ -135,7 +182,7 @@
if ( root )
{
wm = MODULE32_LookupHMODULE( root );
- if ( wm && !wm->initDone )
+ if ( wm && !(wm->flags & WINE_MODREF_MARKER) )
MODULE_DoInitializeDLLs( wm, type, lpReserved );
}
else
@@ -147,9 +194,26 @@
if ( !root )
{
/* If called for main EXE, initialize all DLLs */
- for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
- if ( !wm->initDone )
- MODULE_DoInitializeDLLs( wm, type, lpReserved );
+ switch ( type )
+ {
+ default: /* Hmmm. */
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
+ if ( !wm->next )
+ break;
+ for ( ; wm; wm = wm->prev )
+ if ( !(wm->flags & WINE_MODREF_MARKER) )
+ MODULE_DoInitializeDLLs( wm, type, lpReserved );
+ break;
+
+ case DLL_PROCESS_DETACH:
+ case DLL_THREAD_DETACH:
+ for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
+ if ( !(wm->flags & WINE_MODREF_MARKER) )
+ MODULE_DoInitializeDLLs( wm, type, lpReserved );
+ break;
+ }
}
else
{
@@ -160,7 +224,7 @@
/* We're finished, so we reset all recursion flags */
for ( wm = PROCESS_Current()->modref_list; wm; wm = wm->next )
- wm->initDone = FALSE;
+ wm->flags &= ~WINE_MODREF_MARKER;
}
TRACE( module, "(%08x,%ld,%p) - END\n", root, type, lpReserved );
@@ -169,6 +233,49 @@
LeaveCriticalSection( &PROCESS_Current()->crit_section );
}
+/****************************************************************************
+ * DisableThreadLibraryCalls (KERNEL32.74)
+ *
+ * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
+ */
+BOOL WINAPI DisableThreadLibraryCalls( HMODULE hModule )
+{
+ WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
+ if ( !wm ) return FALSE;
+
+ wm->flags |= WINE_MODREF_NO_DLL_CALLS;
+ return TRUE;
+}
+
+/****************************************************************************
+ * MODULE_IncRefCount
+ */
+static void MODULE_IncRefCount( HMODULE hModule )
+{
+ WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
+ if ( !wm ) return;
+
+ EnterCriticalSection( &PROCESS_Current()->crit_section );
+ wm->refCount++;
+ LeaveCriticalSection( &PROCESS_Current()->crit_section );
+}
+
+/****************************************************************************
+ * MODULE_DecRefCount
+ */
+static int MODULE_DecRefCount( HMODULE hModule )
+{
+ int retv;
+ WINE_MODREF *wm = MODULE32_LookupHMODULE( hModule );
+ if ( !wm ) return 0;
+
+ EnterCriticalSection( &PROCESS_Current()->crit_section );
+ if ( ( retv = wm->refCount ) > 0 ) wm->refCount--;
+ LeaveCriticalSection( &PROCESS_Current()->crit_section );
+
+ return retv;
+}
+
/***********************************************************************
* MODULE_CreateDummyModule
@@ -1103,15 +1210,14 @@
HMODULE hmod;
hmod = MODULE_LoadLibraryExA( libname, hfile, flags );
- /* at least call not the dllmain...*/
- if ( DONT_RESOLVE_DLL_REFERENCES==flags || LOAD_LIBRARY_AS_DATAFILE==flags )
- { FIXME(module,"flag not properly supported %lx\n", flags);
- return hmod;
- }
+ if ( hmod >= 32 )
+ {
+ /* Increment RefCount */
+ MODULE_IncRefCount( hmod );
- /* initialize DLL just loaded */
- if ( hmod >= 32 )
- MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, (LPVOID)-1 );
+ /* Initialize DLL just loaded */
+ MODULE_InitializeDLLs( hmod, DLL_PROCESS_ATTACH, NULL );
+ }
return hmod;
}
@@ -1159,8 +1265,10 @@
*/
BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
{
- FIXME(module,"(0x%08x): stub\n", hLibModule);
- return TRUE; /* FIXME */
+ if ( MODULE_DecRefCount( hLibModule ) != 1 ) return TRUE;
+
+ FIXME(module,"(0x%08x): should unload now\n", hLibModule);
+ return TRUE; /* FIXME */
}
/***********************************************************************
diff --git a/loader/pe_image.c b/loader/pe_image.c
index b6e0466..4982dc4 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -740,11 +740,18 @@
HEAP_ZERO_MEMORY, sizeof(*wm) );
wm->module = hModule;
+ if ( builtin )
+ wm->flags |= WINE_MODREF_INTERNAL;
+ if ( flags & DONT_RESOLVE_DLL_REFERENCES )
+ wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS;
+ if ( flags & LOAD_LIBRARY_AS_DATAFILE )
+ wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE;
+
wm->type = MODULE32_PE;
- wm->binfmt.pe.flags = builtin? PE_MODREF_INTERNAL : 0;
wm->binfmt.pe.pe_export = pe_export;
wm->binfmt.pe.pe_import = pe_import;
wm->binfmt.pe.pe_resource = pe_resource;
+ wm->binfmt.pe.tlsindex = -1;
if ( pe_export )
modname = (char *)RVA( pe_export->Name );
@@ -753,8 +760,7 @@
/* try to find out the name from the OFSTRUCT */
char *s;
modname = ofs->szPathName;
- while ((s=strchr(modname,'\\')))
- modname = s+1;
+ if ((s=strrchr(modname,'\\'))) modname = s+1;
}
wm->modname = HEAP_strdupA( GetProcessHeap(), 0, modname );
@@ -766,8 +772,11 @@
/* Link MODREF into process list */
+ EnterCriticalSection( &PROCESS_Current()->crit_section );
+
wm->next = PROCESS_Current()->modref_list;
PROCESS_Current()->modref_list = wm;
+ if ( wm->next ) wm->next->prev = wm;
if ( !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL) )
{
@@ -776,6 +785,9 @@
PROCESS_Current()->exe_modref = wm;
}
+ LeaveCriticalSection( &PROCESS_Current()->crit_section );
+
+
/* Dump Exports */
if ( pe_export )
@@ -783,16 +795,23 @@
/* Fixup Imports */
- if ( pe_import && fixup_imports( wm ) )
+ if ( pe_import && fixup_imports( wm )
+ && !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE )
+ && !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) )
{
/* remove entry from modref chain */
- WINE_MODREF **xwm;
- for ( xwm = &PROCESS_Current()->modref_list; *xwm; xwm = &(*xwm)->next )
- if ( *xwm == wm )
- {
- *xwm = wm->next;
- break;
- }
+ EnterCriticalSection( &PROCESS_Current()->crit_section );
+
+ if ( !wm->prev )
+ PROCESS_Current()->modref_list = wm->next;
+ else
+ wm->prev->next = wm->next;
+
+ if ( wm->next ) wm->next->prev = wm->prev;
+ wm->next = wm->prev = NULL;
+
+ LeaveCriticalSection( &PROCESS_Current()->crit_section );
+
/* FIXME: there are several more dangling references
* left. Including dlls loaded by this dll before the
* failed one. Unrolling is rather difficult with the
@@ -943,15 +962,6 @@
{
if (wm->type!=MODULE32_PE)
return;
- if (wm->binfmt.pe.flags & PE_MODREF_NO_DLL_CALLS)
- return;
- if (type==DLL_PROCESS_ATTACH)
- {
- if (wm->binfmt.pe.flags & PE_MODREF_PROCESS_ATTACHED)
- return;
-
- wm->binfmt.pe.flags |= PE_MODREF_PROCESS_ATTACHED;
- }
/* DLL_ATTACH_PROCESS:
* lpreserved is NULL for dynamic loads, not-NULL for static loads
@@ -979,7 +989,7 @@
* Pointers in those structs are not RVAs but real pointers which have been
* relocated by do_relocations() already.
*/
-void PE_InitTls(THDB *thdb)
+void PE_InitTls( void )
{
WINE_MODREF *wm;
PE_MODREF *pem;
@@ -987,10 +997,9 @@
DWORD size,datasize;
LPVOID mem;
PIMAGE_TLS_DIRECTORY pdir;
- PDB *pdb = thdb->process;
int delta;
- for (wm = pdb->modref_list;wm;wm=wm->next) {
+ for (wm = PROCESS_Current()->modref_list;wm;wm=wm->next) {
if (wm->type!=MODULE32_PE)
continue;
pem = &(wm->binfmt.pe);
@@ -1002,11 +1011,10 @@
DataDirectory[IMAGE_FILE_THREAD_LOCAL_STORAGE].VirtualAddress);
- if (!(pem->flags & PE_MODREF_TLS_ALLOCED)) {
- pem->tlsindex = THREAD_TlsAlloc(thdb);
+ if ( pem->tlsindex == -1 ) {
+ pem->tlsindex = TlsAlloc();
*pdir->AddressOfIndex=pem->tlsindex;
}
- pem->flags |= PE_MODREF_TLS_ALLOCED;
datasize= pdir->EndAddressOfRawData-pdir->StartAddressOfRawData;
size = datasize + pdir->SizeOfZeroFill;
mem=VirtualAlloc(0,size,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
@@ -1018,21 +1026,8 @@
if (*cbs)
FIXME(win32, "TLS Callbacks aren't going to be called\n");
}
- /* Don't use TlsSetValue, we are in the wrong thread */
- thdb->tls_array[pem->tlsindex] = mem;
+
+ TlsSetValue( pem->tlsindex, mem );
}
}
-/****************************************************************************
- * DisableThreadLibraryCalls (KERNEL32.74)
- * Don't call DllEntryPoint for DLL_THREAD_{ATTACH,DETACH} if set.
- */
-BOOL WINAPI DisableThreadLibraryCalls(HMODULE hModule)
-{
- WINE_MODREF *wm;
-
- for (wm=PROCESS_Current()->modref_list;wm;wm=wm->next)
- if ((wm->module == hModule) && (wm->type==MODULE32_PE))
- wm->binfmt.pe.flags|=PE_MODREF_NO_DLL_CALLS;
- return TRUE;
-}