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