From 9b79d698b2c069cb403f26dcda24614216a9ceaa Mon Sep 17 00:00:00 2001 From: Eric Pouech Date: Thu, 20 Mar 2003 04:55:59 +0000 Subject: [PATCH] Moved the module loading/unloading code and the remaining needed static variables to ntdll. --- dlls/ntdll/loader.c | 195 +++++++++++++++++++++++++++++++++++++++++++- include/module.h | 7 -- loader/module.c | 193 ------------------------------------------- 3 files changed, 194 insertions(+), 201 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 64a2a4bab6d..e4a51ba51f3 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1,4 +1,7 @@ /* + * Loader functions + * + * Copyright 1995 Alexandre Julliard * Copyright 2002 Dmitry Timoshkov for Codeweavers * * This library is free software; you can redistribute it and/or @@ -35,6 +38,10 @@ WINE_DECLARE_DEBUG_CHANNEL(module); 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 */ @@ -45,7 +52,7 @@ static WINE_EXCEPTION_FILTER(page_fault) return EXCEPTION_CONTINUE_SEARCH; } -CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" ); +static CRITICAL_SECTION loader_section = CRITICAL_SECTION_INIT( "loader_section" ); /************************************************************************* * MODULE32_LookupHMODULE @@ -131,6 +138,192 @@ WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename ) return wm; } +/************************************************************************* + * MODULE_InitDLL + */ +static BOOL MODULE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved ) +{ + static const char * const typeName[] = { "PROCESS_DETACH", "PROCESS_ATTACH", + "THREAD_ATTACH", "THREAD_DETACH" }; + BOOL retv = TRUE; + + /* 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 --git a/include/module.h b/include/module.h index a83673cd0e9..99024aa6241 100644 --- a/include/module.h +++ b/include/module.h @@ -203,13 +203,6 @@ extern enum binary_type MODULE_GetBinaryType( HANDLE hfile ); 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 ); diff --git a/loader/module.c b/loader/module.c index e0ded57390c..6b9b3756e2e 100644 --- a/loader/module.c +++ b/loader/module.c @@ -45,11 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(module); 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 */ - inline static HMODULE get_exe_module(void) { HMODULE mod; @@ -77,194 +72,6 @@ static DWORD wait_input_idle( HANDLE process, DWORD timeout ) } -/************************************************************************* - * 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 ); -} - /**************************************************************************** * DisableThreadLibraryCalls (KERNEL32.@) *