From 019322fc283311218f07df1ecbca58abe5b661a1 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Fri, 30 Nov 2007 13:40:39 -0800 Subject: [PATCH] ntdll: unload modules based on inter-module dependencies --- dlls/ntdll/loader.c | 33 +++++++++++++++++++++++++++++++++ 1 files changed, 33 insertions(+), 0 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index ca1ebdd..dc51422 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -77,6 +77,7 @@ typedef struct _wine_modref { LDR_MODULE ldr; int nDeps; + int nValidDeps; struct _wine_modref **deps; } WINE_MODREF; @@ -644,6 +645,7 @@ static NTSTATUS fixup_imports( WINE_MODR /* Allocate module dependency list */ wm->nDeps = nb_imports; wm->deps = RtlAllocateHeap( GetProcessHeap(), 0, nb_imports*sizeof(WINE_MODREF *) ); + wm->nValidDeps = 0; /* load the imported modules. They are automatically * added to the modref list of the process. @@ -655,6 +657,8 @@ static NTSTATUS fixup_imports( WINE_MODR { if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i], load_path ))) status = STATUS_DLL_NOT_FOUND; + else + wm->nValidDeps++; } current_modref = prev; if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie ); @@ -679,6 +683,7 @@ static WINE_MODREF *alloc_module( HMODUL wm->nDeps = 0; wm->deps = NULL; + wm->nValidDeps = 0; wm->ldr.BaseAddress = hModule; wm->ldr.EntryPoint = NULL; @@ -1029,6 +1034,8 @@ static void process_detach( BOOL bForceD { PLIST_ENTRY mark, entry; PLDR_MODULE mod; + WINE_MODREF *wm; + int i; RtlEnterCriticalSection( &loader_section ); if (bForceDetach) process_detaching = 1; @@ -1037,6 +1044,7 @@ static void process_detach( BOOL bForceD { for (entry = mark->Blink; entry != mark; entry = entry->Blink) { + PLIST_ENTRY entry2; mod = CONTAINING_RECORD(entry, LDR_MODULE, InInitializationOrderModuleList); /* Check whether to detach this DLL */ @@ -1044,12 +1052,37 @@ static void process_detach( BOOL bForceD continue; if ( mod->LoadCount && !bForceDetach ) continue; + wm = get_modref(mod->BaseAddress); + if (wm && wm->nValidDeps) + continue; /* Call detach notification */ mod->Flags &= ~LDR_PROCESS_ATTACHED; MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), DLL_PROCESS_DETACH, lpReserved ); + /* update dependendies */ + for (entry2 = mark->Blink; entry2 != mark; entry2 = entry2->Blink) + { + PLDR_MODULE mod2; + mod2 = CONTAINING_RECORD(entry2, LDR_MODULE, + InInitializationOrderModuleList); + wm = get_modref(mod2->BaseAddress); + if (wm && wm->nValidDeps) + { + for ( i = 0; i < wm->nDeps; i++ ) + { + /* remove dependencies to detached module */ + if (wm->deps[i] && + wm->deps[i]->ldr.BaseAddress == mod->BaseAddress) + { + wm->deps[i] = 0; + wm->nValidDeps--; + } + } + } + } + /* Restart at head of WINE_MODREF list, as entries might have been added and/or removed while performing the call ... */ break; -- 1.4.1