ntdll/kernel32: #7 (2nd try)
Eric Pouech
pouech-eric at wanadoo.fr
Sat Mar 15 14:11:38 CST 2003
ChangeLog
- 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
-------------- next part --------------
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;
More information about the wine-patches
mailing list