mirror of
https://github.com/reactos/wine.git
synced 2025-02-21 21:32:01 +00:00
Moved the module loading/unloading code and the remaining needed
static variables to ntdll.
This commit is contained in:
parent
500a2f95f7
commit
9b79d698b2
@ -1,4 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
|
* Loader functions
|
||||||
|
*
|
||||||
|
* Copyright 1995 Alexandre Julliard
|
||||||
* Copyright 2002 Dmitry Timoshkov for Codeweavers
|
* Copyright 2002 Dmitry Timoshkov for Codeweavers
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* 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(module);
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(loaddll);
|
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 */
|
static int free_lib_count; /* recursion depth of LdrUnloadDll calls */
|
||||||
|
|
||||||
/* filter for page-fault exceptions */
|
/* filter for page-fault exceptions */
|
||||||
@ -45,7 +52,7 @@ static WINE_EXCEPTION_FILTER(page_fault)
|
|||||||
return EXCEPTION_CONTINUE_SEARCH;
|
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
|
* MODULE32_LookupHMODULE
|
||||||
@ -131,6 +138,192 @@ WINE_MODREF *MODULE_AllocModRef( HMODULE hModule, LPCSTR filename )
|
|||||||
return wm;
|
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.@)
|
* LdrDisableThreadCalloutsForDll (NTDLL.@)
|
||||||
*
|
*
|
||||||
|
@ -203,13 +203,6 @@ extern enum binary_type MODULE_GetBinaryType( HANDLE hfile );
|
|||||||
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
|
extern FARPROC16 WINAPI WIN32_GetProcAddress16( HMODULE hmodule, LPCSTR name );
|
||||||
extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
|
extern SEGPTR WINAPI HasGPHandler16( SEGPTR address );
|
||||||
extern void MODULE_WalkModref( DWORD id );
|
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 */
|
/* loader/ne/module.c */
|
||||||
extern NE_MODULE *NE_GetPtr( HMODULE16 hModule );
|
extern NE_MODULE *NE_GetPtr( HMODULE16 hModule );
|
||||||
|
193
loader/module.c
193
loader/module.c
@ -45,11 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(module);
|
|||||||
WINE_DECLARE_DEBUG_CHANNEL(win32);
|
WINE_DECLARE_DEBUG_CHANNEL(win32);
|
||||||
WINE_DECLARE_DEBUG_CHANNEL(loaddll);
|
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)
|
inline static HMODULE get_exe_module(void)
|
||||||
{
|
{
|
||||||
HMODULE mod;
|
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.@)
|
* DisableThreadLibraryCalls (KERNEL32.@)
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user