- moved the module loading/unloading code to dlls/ntdll
- moved the remaining needed static variables from loader to dlls/ntdll (and storing LoaderLock in PDB)
(Alexandre, the LoaderLock is at a wrong offset - it's in 0xA0 in PEB, but 0xA0 is used for priority in PDB :-(
So I put it at offset 0xAC of PDB, which is unused, but that's really starting to be even uglier than what we've done with the TEB)
A+ -- Eric Pouech
diff -u -x '*~' -x '.#*' dlls/ntdll6/loader.c dlls/ntdll/loader.c --- dlls/ntdll6/loader.c 2003-03-15 09:57:50.000000000 +0100 +++ dlls/ntdll/loader.c 2003-03-15 18:10:03.000000000 +0100 @@ -35,6 +35,10 @@ WINE_DECLARE_DEBUG_CHANNEL(module); WINE_DECLARE_DEBUG_CHANNEL(loaddll); +WINE_MODREF *MODULE_modref_list = NULL; + +static WINE_MODREF *exe_modref; +static int process_detaching = 0; /* set on process detach to avoid deadlocks with thread detach */ static int free_lib_count; /* recursion depth of LdrUnloadDll calls */ /* filter for page-fault exceptions */ @@ -131,6 +135,194 @@ return wm; } +/************************************************************************* + * MODULE_InitDLL + */ +BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) +{ + BOOL retv = TRUE; + + static LPCSTR typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH", + "THREAD_ATTACH", "THREAD_DETACH" }; + assert( wm ); + + /* Skip calls for modules loaded with special load flags */ + + if (wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) return TRUE; + + TRACE("(%s,%s,%p) - CALL\n", wm->modname, typeName[type], lpReserved ); + + /* Call the initialization routine */ + retv = PE_InitDLL( wm->module, type, lpReserved ); + + /* The state of the module list may have changed due to the call + to PE_InitDLL. We cannot assume that this module has not been + deleted. */ + TRACE("(%p,%s,%p) - RETURN %d\n", wm, typeName[type], lpReserved, retv ); + + return retv; +} + + +/************************************************************************* + * MODULE_DllProcessAttach + * + * Send the process attach notification to all DLLs the given module + * depends on (recursively). This is somewhat complicated due to the fact that + * + * - we have to respect the module dependencies, i.e. modules implicitly + * referenced by another module have to be initialized before the module + * itself can be initialized + * + * - the initialization routine of a DLL can itself call LoadLibrary, + * thereby introducing a whole new set of dependencies (even involving + * the 'old' modules) at any time during the whole process + * + * (Note that this routine can be recursively entered not only directly + * from itself, but also via LoadLibrary from one of the called initialization + * routines.) + * + * Furthermore, we need to rearrange the main WINE_MODREF list to allow + * the process *detach* notifications to be sent in the correct order. + * This must not only take into account module dependencies, but also + * 'hidden' dependencies created by modules calling LoadLibrary in their + * attach notification routine. + * + * The strategy is rather simple: we move a WINE_MODREF to the head of the + * list after the attach notification has returned. This implies that the + * detach notifications are called in the reverse of the sequence the attach + * notifications *returned*. + */ +BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ) +{ + BOOL retv = TRUE; + int i; + + RtlEnterCriticalSection( &loader_section ); + + if (!wm) + { + wm = exe_modref; + PE_InitTls(); + } + assert( wm ); + + /* prevent infinite recursion in case of cyclical dependencies */ + if ( ( wm->flags & WINE_MODREF_MARKER ) + || ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) ) + goto done; + + TRACE("(%s,%p) - START\n", wm->modname, lpReserved ); + + /* Tag current MODREF to prevent recursive loop */ + wm->flags |= WINE_MODREF_MARKER; + + /* Recursively attach all DLLs this one depends on */ + for ( i = 0; retv && i < wm->nDeps; i++ ) + if ( wm->deps[i] ) + retv = MODULE_DllProcessAttach( wm->deps[i], lpReserved ); + + /* Call DLL entry point */ + if ( retv ) + { + retv = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ); + if ( retv ) + wm->flags |= WINE_MODREF_PROCESS_ATTACHED; + } + + /* Re-insert MODREF at head of list */ + if ( retv && wm->prev ) + { + wm->prev->next = wm->next; + if ( wm->next ) wm->next->prev = wm->prev; + + wm->prev = NULL; + wm->next = MODULE_modref_list; + MODULE_modref_list = wm->next->prev = wm; + } + + /* Remove recursion flag */ + wm->flags &= ~WINE_MODREF_MARKER; + + TRACE("(%s,%p) - END\n", wm->modname, lpReserved ); + + done: + RtlLeaveCriticalSection( &loader_section ); + return retv; +} + +/************************************************************************* + * MODULE_DllProcessDetach + * + * Send DLL process detach notifications. See the comment about calling + * sequence at MODULE_DllProcessAttach. Unless the bForceDetach flag + * is set, only DLLs with zero refcount are notified. + */ +void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved ) +{ + WINE_MODREF *wm; + + RtlEnterCriticalSection( &loader_section ); + if (bForceDetach) process_detaching = 1; + do + { + for ( wm = MODULE_modref_list; wm; wm = wm->next ) + { + /* Check whether to detach this DLL */ + if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) + continue; + if ( wm->refCount > 0 && !bForceDetach ) + continue; + + /* Call detach notification */ + wm->flags &= ~WINE_MODREF_PROCESS_ATTACHED; + MODULE_InitDLL( wm, DLL_PROCESS_DETACH, lpReserved ); + + /* Restart at head of WINE_MODREF list, as entries might have + been added and/or removed while performing the call ... */ + break; + } + } while ( wm ); + + RtlLeaveCriticalSection( &loader_section ); +} + +/************************************************************************* + * MODULE_DllThreadAttach + * + * Send DLL thread attach notifications. These are sent in the + * reverse sequence of process detach notification. + * + */ +void MODULE_DllThreadAttach( LPVOID lpReserved ) +{ + WINE_MODREF *wm; + + /* don't do any attach calls if process is exiting */ + if (process_detaching) return; + /* FIXME: there is still a race here */ + + RtlEnterCriticalSection( &loader_section ); + + PE_InitTls(); + + for ( wm = MODULE_modref_list; wm; wm = wm->next ) + if ( !wm->next ) + break; + + for ( ; wm; wm = wm->prev ) + { + if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) + continue; + if ( wm->flags & WINE_MODREF_NO_DLL_CALLS ) + continue; + + MODULE_InitDLL( wm, DLL_THREAD_ATTACH, lpReserved ); + } + + RtlLeaveCriticalSection( &loader_section ); +} + /****************************************************************** * LdrDisableThreadCalloutsForDll (NTDLL.@) * diff -u -x '*~' -x '.#*' dlls/ntdll6/ntdll_misc.h dlls/ntdll/ntdll_misc.h --- dlls/ntdll6/ntdll_misc.h 2003-03-15 08:49:00.000000000 +0100 +++ dlls/ntdll/ntdll_misc.h 2003-03-15 18:09:30.000000000 +0100 @@ -38,4 +38,5 @@ HANDLE *pdb = (HANDLE *)NtCurrentTeb()->process; return pdb[0x18 / sizeof(HANDLE)]; /* get dword at offset 0x18 in pdb */ } +extern CRITICAL_SECTION loader_section; #endif diff -u -x '*~' -x '.#*' include6/module.h include/module.h --- include6/module.h 2003-03-15 13:08:19.000000000 +0100 +++ include/module.h 2003-03-15 17:54:03.000000000 +0100 @@ -203,13 +203,6 @@ extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name ); extern SEGPTR WINAPI HasGPHandler16( SEGPTR address ); extern void MODULE_WalkModref( DWORD id ); -/* the following parts of module.c are temporary exported during move of code - * from loader/module.c to dlls/ntdll/loader.c - */ -extern WINE_MODREF *exe_modref; -extern CRITICAL_SECTION loader_section; -extern int process_detaching; -extern BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ); /* loader/ne/module.c */ extern NE_MODULE *NE_GetPtr( HMODULE16 hModule ); Common subdirectories: include6/msvcrt and include/msvcrt Common subdirectories: include6/wine and include/wine Common subdirectories: loader6/CVS and loader/CVS diff -u -x '*~' -x '.#*' loader6/module.c loader/module.c --- loader6/module.c 2003-03-15 15:06:59.000000000 +0100 +++ loader/module.c 2003-03-15 18:11:35.000000000 +0100 @@ -45,11 +45,6 @@ WINE_DECLARE_DEBUG_CHANNEL(win32); WINE_DECLARE_DEBUG_CHANNEL(loaddll); -WINE_MODREF *MODULE_modref_list = NULL; - -WINE_MODREF *exe_modref; -int process_detaching = 0; /* set on process detach to avoid deadlocks with thread detach */ - /*********************************************************************** * wait_input_idle * @@ -68,193 +63,10 @@ return 0; } - -/************************************************************************* - * MODULE_InitDLL - */ -BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) -{ - BOOL retv = TRUE; - - static LPCSTR typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH", - "THREAD_ATTACH", "THREAD_DETACH" }; - assert( wm ); - - /* Skip calls for modules loaded with special load flags */ - - if (wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) return TRUE; - - TRACE("(%s,%s,%p) - CALL\n", wm->modname, typeName[type], lpReserved ); - - /* Call the initialization routine */ - retv = PE_InitDLL( wm->module, type, lpReserved ); - - /* The state of the module list may have changed due to the call - to PE_InitDLL. We cannot assume that this module has not been - deleted. */ - TRACE("(%p,%s,%p) - RETURN %d\n", wm, typeName[type], lpReserved, retv ); - - return retv; -} - - -/************************************************************************* - * MODULE_DllProcessAttach - * - * Send the process attach notification to all DLLs the given module - * depends on (recursively). This is somewhat complicated due to the fact that - * - * - we have to respect the module dependencies, i.e. modules implicitly - * referenced by another module have to be initialized before the module - * itself can be initialized - * - * - the initialization routine of a DLL can itself call LoadLibrary, - * thereby introducing a whole new set of dependencies (even involving - * the 'old' modules) at any time during the whole process - * - * (Note that this routine can be recursively entered not only directly - * from itself, but also via LoadLibrary from one of the called initialization - * routines.) - * - * Furthermore, we need to rearrange the main WINE_MODREF list to allow - * the process *detach* notifications to be sent in the correct order. - * This must not only take into account module dependencies, but also - * 'hidden' dependencies created by modules calling LoadLibrary in their - * attach notification routine. - * - * The strategy is rather simple: we move a WINE_MODREF to the head of the - * list after the attach notification has returned. This implies that the - * detach notifications are called in the reverse of the sequence the attach - * notifications *returned*. - */ -BOOL MODULE_DllProcessAttach( WINE_MODREF *wm, LPVOID lpReserved ) -{ - BOOL retv = TRUE; - int i; - - RtlEnterCriticalSection( &loader_section ); - - if (!wm) - { - wm = exe_modref; - PE_InitTls(); - } - assert( wm ); - - /* prevent infinite recursion in case of cyclical dependencies */ - if ( ( wm->flags & WINE_MODREF_MARKER ) - || ( wm->flags & WINE_MODREF_PROCESS_ATTACHED ) ) - goto done; - - TRACE("(%s,%p) - START\n", wm->modname, lpReserved ); - - /* Tag current MODREF to prevent recursive loop */ - wm->flags |= WINE_MODREF_MARKER; - - /* Recursively attach all DLLs this one depends on */ - for ( i = 0; retv && i < wm->nDeps; i++ ) - if ( wm->deps[i] ) - retv = MODULE_DllProcessAttach( wm->deps[i], lpReserved ); - - /* Call DLL entry point */ - if ( retv ) - { - retv = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ); - if ( retv ) - wm->flags |= WINE_MODREF_PROCESS_ATTACHED; - } - - /* Re-insert MODREF at head of list */ - if ( retv && wm->prev ) - { - wm->prev->next = wm->next; - if ( wm->next ) wm->next->prev = wm->prev; - - wm->prev = NULL; - wm->next = MODULE_modref_list; - MODULE_modref_list = wm->next->prev = wm; - } - - /* Remove recursion flag */ - wm->flags &= ~WINE_MODREF_MARKER; - - TRACE("(%s,%p) - END\n", wm->modname, lpReserved ); - - done: - RtlLeaveCriticalSection( &loader_section ); - return retv; -} - -/************************************************************************* - * MODULE_DllProcessDetach - * - * Send DLL process detach notifications. See the comment about calling - * sequence at MODULE_DllProcessAttach. Unless the bForceDetach flag - * is set, only DLLs with zero refcount are notified. - */ -void MODULE_DllProcessDetach( BOOL bForceDetach, LPVOID lpReserved ) -{ - WINE_MODREF *wm; - - RtlEnterCriticalSection( &loader_section ); - if (bForceDetach) process_detaching = 1; - do - { - for ( wm = MODULE_modref_list; wm; wm = wm->next ) - { - /* Check whether to detach this DLL */ - if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) - continue; - if ( wm->refCount > 0 && !bForceDetach ) - continue; - - /* Call detach notification */ - wm->flags &= ~WINE_MODREF_PROCESS_ATTACHED; - MODULE_InitDLL( wm, DLL_PROCESS_DETACH, lpReserved ); - - /* Restart at head of WINE_MODREF list, as entries might have - been added and/or removed while performing the call ... */ - break; - } - } while ( wm ); - - RtlLeaveCriticalSection( &loader_section ); -} - -/************************************************************************* - * MODULE_DllThreadAttach - * - * Send DLL thread attach notifications. These are sent in the - * reverse sequence of process detach notification. - * - */ -void MODULE_DllThreadAttach( LPVOID lpReserved ) +static inline CRITICAL_SECTION* get_loader_crst(void) { - WINE_MODREF *wm; - - /* don't do any attach calls if process is exiting */ - if (process_detaching) return; - /* FIXME: there is still a race here */ - - RtlEnterCriticalSection( &loader_section ); - - PE_InitTls(); - - for ( wm = MODULE_modref_list; wm; wm = wm->next ) - if ( !wm->next ) - break; - - for ( ; wm; wm = wm->prev ) - { - if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) ) - continue; - if ( wm->flags & WINE_MODREF_NO_DLL_CALLS ) - continue; - - MODULE_InitDLL( wm, DLL_THREAD_ATTACH, lpReserved ); - } - - RtlLeaveCriticalSection( &loader_section ); + void** pdb = (HANDLE *)NtCurrentTeb()->process; + return pdb[0xAC / sizeof(void*)]; } /**************************************************************************** @@ -926,7 +738,7 @@ lpFileName[0] = 0; - RtlEnterCriticalSection( &loader_section ); + RtlEnterCriticalSection( get_loader_crst() ); if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32)) { /* 16-bit task - get current NE module name */ @@ -948,7 +760,7 @@ } else SetLastError( RtlNtStatusToDosError( nts ) ); } - RtlLeaveCriticalSection( &loader_section ); + RtlLeaveCriticalSection( get_loader_crst() ); TRACE( "%s\n", debugstr_an(lpFileName, len) ); return len; @@ -964,7 +776,7 @@ lpFileName[0] = 0; - RtlEnterCriticalSection( &loader_section ); + RtlEnterCriticalSection( get_loader_crst() ); if (!hModule && !(NtCurrentTeb()->tibflags & TEBF_WIN32)) { /* 16-bit task - get current NE module name */ @@ -993,7 +805,7 @@ else SetLastError( RtlNtStatusToDosError( nts ) ); } - RtlLeaveCriticalSection( &loader_section ); + RtlLeaveCriticalSection( get_loader_crst() ); TRACE( "%s\n", debugstr_wn(lpFileName, len) ); return len;