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.
This commit is contained in:
Ulrich Weigand 1999-03-27 16:45:57 +00:00 committed by Alexandre Julliard
parent 1c40024b15
commit e469a583ca
7 changed files with 208 additions and 109 deletions

View file

@ -111,6 +111,7 @@ typedef enum { MODULE32_PE=1, MODULE32_ELF /* ,... */ } MODULE32_TYPE;
typedef struct _wine_modref
{
struct _wine_modref *next;
struct _wine_modref *prev;
MODULE32_TYPE type;
union {
PE_MODREF pe;
@ -121,13 +122,24 @@ typedef struct _wine_modref
int nDeps;
struct _wine_modref **deps;
int initDone;
int flags;
int refCount;
char *modname;
char *shortname;
char *longname;
} WINE_MODREF;
#define WINE_MODREF_INTERNAL 0x00000001
#define WINE_MODREF_NO_DLL_CALLS 0x00000002
#define WINE_MODREF_PROCESS_ATTACHED 0x00000004
#define WINE_MODREF_PROCESS_DETACHED 0x00000008
#define WINE_MODREF_LOAD_AS_DATAFILE 0x00000010
#define WINE_MODREF_DONT_RESOLVE_REFS 0x00000020
#define WINE_MODREF_MARKER 0x80000000
/* Resource types */
typedef struct resource_typeinfo_s NE_TYPEINFO;

View file

@ -11,12 +11,6 @@ typedef struct {
PIMAGE_IMPORT_DESCRIPTOR pe_import;
PIMAGE_EXPORT_DIRECTORY pe_export;
PIMAGE_RESOURCE_DIRECTORY pe_resource;
int flags;
#define PE_MODREF_PROCESS_ATTACHED 0x00000001
#define PE_MODREF_NO_DLL_CALLS 0x00000002
#define PE_MODREF_RELOCS_DONE 0x00000004
#define PE_MODREF_TLS_ALLOCED 0x00000008
#define PE_MODREF_INTERNAL 0x00000010
int tlsindex;
} PE_MODREF;
@ -41,8 +35,7 @@ extern BOOL PE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line, LPCST
BOOL inherit, LPSTARTUPINFOA startup,
LPPROCESS_INFORMATION info );
struct _THDB; /* forward definition */
extern void PE_InitTls(struct _THDB*);
extern void PE_InitTls(void);
extern void PE_InitDLL(struct _wine_modref *wm, DWORD type, LPVOID lpReserved);
extern PIMAGE_RESOURCE_DIRECTORY GetResDirEntryA(PIMAGE_RESOURCE_DIRECTORY,LPCSTR,DWORD,BOOL);

View file

@ -123,7 +123,6 @@ extern THDB *THREAD_Create( struct _PDB *pdb, DWORD flags,
extern THDB *THREAD_Current(void);
extern BOOL THREAD_IsWin16( THDB *thdb );
extern THDB *THREAD_IdToTHDB( DWORD id );
extern DWORD THREAD_TlsAlloc( THDB *thread );
/* scheduler/sysdeps.c */
extern int SYSDEPS_SpawnThread( THDB *thread );

View file

@ -73,37 +73,84 @@ WINE_MODREF *MODULE32_LookupHMODULE( HMODULE hmod )
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 @@ void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
/* 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 @@ void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
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 @@ void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
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 @@ void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
/* 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 @@ void MODULE_InitializeDLLs( HMODULE root, DWORD type, LPVOID lpReserved )
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 WINAPI LoadLibraryExA(LPCSTR libname,HFILE hfile,DWORD flags)
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 @@ HMODULE WINAPI LoadLibraryExW(LPCWSTR libnameW,HFILE hfile,DWORD flags)
*/
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 */
}
/***********************************************************************

View file

@ -740,11 +740,18 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule,
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 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule,
/* 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 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule,
/* 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 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule,
PROCESS_Current()->exe_modref = wm;
}
LeaveCriticalSection( &PROCESS_Current()->crit_section );
/* Dump Exports */
if ( pe_export )
@ -783,16 +795,23 @@ WINE_MODREF *PE_CreateModule( HMODULE hModule,
/* 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 @@ void PE_InitDLL(WINE_MODREF *wm, DWORD type, LPVOID lpReserved)
{
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 @@ void PE_InitDLL(WINE_MODREF *wm, DWORD type, LPVOID lpReserved)
* 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 @@ void PE_InitTls(THDB *thdb)
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 @@ void PE_InitTls(THDB *thdb)
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 @@ void PE_InitTls(THDB *thdb)
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;
}

View file

@ -363,14 +363,14 @@ void PROCESS_Start(void)
/* Initialize thread-local storage */
PE_InitTls( thdb );
PE_InitTls();
if (PE_HEADER(pModule->module32)->OptionalHeader.Subsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI)
AllocConsole();
/* Now call the entry point */
MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)-1 );
MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)1 );
entry = (LPTHREAD_START_ROUTINE)RVA_PTR(pModule->module32,
OptionalHeader.AddressOfEntryPoint);
TRACE(relay, "(entryproc=%p)\n", entry );
@ -509,7 +509,7 @@ error:
*/
void WINAPI ExitProcess( DWORD status )
{
MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, NULL );
MODULE_InitializeDLLs( 0, DLL_PROCESS_DETACH, (LPVOID)1 );
if ( THREAD_IsWin16( THREAD_Current() ) )
TASK_KillCurrentTask( status );

View file

@ -261,7 +261,6 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16
if (!THREAD_InitTHDB( thdb, stack_size, alloc_stack16, sa )) goto error;
thdb->next = THREAD_First;
THREAD_First = thdb;
PE_InitTls( thdb );
return thdb;
error:
@ -282,6 +281,7 @@ static void THREAD_Start(void)
{
THDB *thdb = THREAD_Current();
LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point;
PE_InitTls();
MODULE_InitializeDLLs( 0, DLL_THREAD_ATTACH, NULL );
ExitThread( func( thdb->entry_arg ) );
}
@ -412,10 +412,17 @@ void WINAPI SetLastErrorEx(
/**********************************************************************
* THREAD_TlsAlloc
* TlsAlloc [KERNEL32.530] Allocates a TLS index.
*
* Allocates a thread local storage index
*
* RETURNS
* Success: TLS Index
* Failure: 0xFFFFFFFF
*/
DWORD THREAD_TlsAlloc(THDB *thread)
DWORD WINAPI TlsAlloc( void )
{
THDB *thread = THREAD_Current();
DWORD i, mask, ret = 0;
DWORD *bits = thread->process->tls_bits;
EnterCriticalSection( &thread->process->crit_section );
@ -437,21 +444,6 @@ DWORD THREAD_TlsAlloc(THDB *thread)
}
/**********************************************************************
* TlsAlloc [KERNEL32.530] Allocates a TLS index.
*
* Allocates a thread local storage index
*
* RETURNS
* Success: TLS Index
* Failure: 0xFFFFFFFF
*/
DWORD WINAPI TlsAlloc(void)
{
return THREAD_TlsAlloc(THREAD_Current());
}
/**********************************************************************
* TlsFree [KERNEL32.531] Releases a TLS index.
*