Fixed several bugs with DLL initialization.
diff --git a/loader/module.c b/loader/module.c
index 83716d2..8787e83 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -70,20 +70,14 @@
* from itself, but also via LoadLibrary from one of the called initialization
* routines.)
*/
-void MODULE_InitializeDLLs( PDB32 *process, HMODULE32 root,
- DWORD type, LPVOID lpReserved )
+static void MODULE_DoInitializeDLLs( PDB32 *process, WINE_MODREF *wm,
+ DWORD type, LPVOID lpReserved )
{
- WINE_MODREF *wm = MODULE32_LookupHMODULE( process, root );
int i;
- if (!wm) return;
-
- /* If called for main EXE, check for invalid recursion */
- if ( !root && wm->initDone )
- {
- FIXME(module, "Invalid recursion!\n");
- return;
- }
+ assert( wm && !wm->initDone );
+ TRACE( module, "(%p,%08x,%ld,%p) - START\n",
+ process, wm->module, type, lpReserved );
/* Tag current MODREF to prevent recursive loop */
wm->initDone = TRUE;
@@ -91,8 +85,8 @@
/* Recursively initialize all child DLLs */
for ( i = 0; i < wm->nDeps; i++ )
if ( wm->deps[i] && !wm->deps[i]->initDone )
- MODULE_InitializeDLLs( process,
- wm->deps[i]->module, type, lpReserved );
+ MODULE_DoInitializeDLLs( process,
+ wm->deps[i], type, lpReserved );
/* Now we can call the initialization routine */
switch ( wm->type )
@@ -106,15 +100,72 @@
break;
}
- /* If called for main EXE, reset recursion flags */
- if ( !root )
- for ( wm = process->modref_list; wm; wm = wm->next )
- {
- if (!wm->initDone)
- FIXME(module, "Orphaned module in modref_list?\n");
+ TRACE( module, "(%p,%08x,%ld,%p) - END\n",
+ process, wm->module, type, lpReserved );
+}
- wm->initDone = FALSE;
+void MODULE_InitializeDLLs( PDB32 *process, HMODULE32 root,
+ DWORD type, LPVOID lpReserved )
+{
+ BOOL32 inProgress = FALSE;
+ WINE_MODREF *wm;
+
+ /* Grab the process critical section to protect the recursion flags */
+ /* FIXME: This is probably overkill! */
+ EnterCriticalSection( &process->crit_section );
+
+ TRACE( module, "(%p,%08x,%ld,%p) - START\n", process, root, type, lpReserved );
+
+ /* First, check whether initialization is currently in progress */
+ for ( wm = process->modref_list; wm; wm = wm->next )
+ if ( wm->initDone )
+ {
+ inProgress = TRUE;
+ break;
}
+
+ if ( inProgress )
+ {
+ /*
+ * If this a LoadLibrary call from within an initialization routine,
+ * treat it analogously to an implicitly referenced DLL.
+ * Anything else may not happen at this point!
+ */
+ if ( root )
+ {
+ wm = MODULE32_LookupHMODULE( process, root );
+ if ( wm && !wm->initDone )
+ MODULE_DoInitializeDLLs( process, wm, type, lpReserved );
+ }
+ else
+ FIXME(module, "Invalid recursion!\n");
+ }
+ else
+ {
+ /* If we arrive here, this is the start of an initialization run */
+ if ( !root )
+ {
+ /* If called for main EXE, initialize all DLLs */
+ for ( wm = process->modref_list; wm; wm = wm->next )
+ if ( !wm->initDone )
+ MODULE_DoInitializeDLLs( process, wm, type, lpReserved );
+ }
+ else
+ {
+ /* If called for a specific DLL, initialize only it and its children */
+ wm = MODULE32_LookupHMODULE( process, root );
+ if (wm) MODULE_DoInitializeDLLs( process, wm, type, lpReserved );
+ }
+
+ /* We're finished, so we reset all recursion flags */
+ for ( wm = process->modref_list; wm; wm = wm->next )
+ wm->initDone = FALSE;
+ }
+
+ TRACE( module, "(%p,%08x,%ld,%p) - END\n", process, root, type, lpReserved );
+
+ /* Release critical section */
+ LeaveCriticalSection( &process->crit_section );
}
@@ -745,7 +796,15 @@
*/
HMODULE32 WINAPI LoadLibraryEx32A(LPCSTR libname,HFILE32 hfile,DWORD flags)
{
- return MODULE_LoadLibraryEx32A(libname,PROCESS_Current(),hfile,flags);
+ HMODULE32 hmod;
+ hmod = MODULE_LoadLibraryEx32A(libname,PROCESS_Current(),hfile,flags);
+
+ /* initialize DLL just loaded */
+ if ( hmod >= 32 )
+ MODULE_InitializeDLLs( PROCESS_Current(), hmod,
+ DLL_PROCESS_ATTACH, (LPVOID)-1 );
+
+ return hmod;
}
HMODULE32 MODULE_LoadLibraryEx32A(LPCSTR libname,PDB32*process,HFILE32 hfile,DWORD flags)
@@ -764,9 +823,6 @@
strcat( buffer, ".dll" );
hmod = PE_LoadLibraryEx32A(buffer,process,hfile,flags);
}
- /* initialize DLL just loaded */
- if (hmod >= 32)
- MODULE_InitializeDLLs( PROCESS_Current(), hmod, DLL_PROCESS_ATTACH, NULL);
return hmod;
}