ntdll: Use NtAreMappedFilesTheSame() to find duplicated module mappings.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-03-22 20:38:25 +01:00
parent 20c4ae45ce
commit 0ea5772113
1 changed files with 31 additions and 1 deletions

View File

@ -1167,6 +1167,8 @@ static WINE_MODREF *alloc_module( HMODULE hModule, const UNICODE_STRING *nt_name
wm->ldr.Flags = LDR_DONT_RESOLVE_REFS | (builtin ? LDR_WINE_INTERNAL : 0);
wm->ldr.TlsIndex = -1;
wm->ldr.LoadCount = 1;
wm->ldr.CheckSum = nt->OptionalHeader.CheckSum;
wm->ldr.TimeDateStamp = nt->FileHeader.TimeDateStamp;
if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, nt_name->Length - 3 * sizeof(WCHAR) )))
{
@ -2274,6 +2276,33 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, HANDL
}
/******************************************************************************
* find_existing_module
*
* Find an existing module that is the same mapping as the new module.
*/
static WINE_MODREF *find_existing_module( HMODULE module )
{
WINE_MODREF *wm;
LIST_ENTRY *mark, *entry;
LDR_DATA_TABLE_ENTRY *mod;
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( module );
if ((wm = get_modref( module ))) return wm;
mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
for (entry = mark->Flink; entry != mark; entry = entry->Flink)
{
mod = CONTAINING_RECORD( entry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks );
if (mod->TimeDateStamp != nt->FileHeader.TimeDateStamp) continue;
if (mod->CheckSum != nt->OptionalHeader.CheckSum) continue;
if (NtAreMappedFilesTheSame( mod->DllBase, module ) != STATUS_SUCCESS) continue;
return CONTAINING_RECORD( mod, WINE_MODREF, ldr );
}
return NULL;
}
/******************************************************************************
* load_native_dll (internal)
*/
@ -2351,12 +2380,13 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, UNICODE_STRING *nt_name,
status = unix_funcs->load_builtin_dll( nt_name, &module, &image_info, prefer_native );
if (status) return status;
if ((*pwm = get_modref( module ))) /* already loaded */
if ((*pwm = find_existing_module( module ))) /* already loaded */
{
if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
TRACE( "Found %s for %s at %p, count=%d\n",
debugstr_us(&(*pwm)->ldr.FullDllName), debugstr_us(nt_name),
(*pwm)->ldr.DllBase, (*pwm)->ldr.LoadCount);
if (module != (*pwm)->ldr.DllBase) NtUnmapViewOfSection( NtCurrentProcess(), module );
return STATUS_SUCCESS;
}