From 24a5a101426e16aa3f9ab9981af67c2edc72adcf Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 22 Mar 2021 09:56:57 +0100 Subject: [PATCH] ntdll: Replace image mapping by the builtin module directly in NtMapViewOfSection(). Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/loader.c | 68 ++++++++++++++++++++++++++++++++++ dlls/ntdll/unix/unix_private.h | 2 + dlls/ntdll/unix/virtual.c | 7 +++- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 25be205c696..fd30c5ac939 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1421,6 +1421,74 @@ static NTSTATUS CDECL load_builtin_dll( UNICODE_STRING *nt_name, void **module, } +/*********************************************************************** + * load_builtin + * + * Load the builtin dll if specified by load order configuration. + * Return STATUS_IMAGE_ALREADY_LOADED if we should keep the native one that we have found. + */ +NTSTATUS load_builtin( const pe_image_info_t *image_info, const WCHAR *filename, + void **module, SIZE_T *size ) +{ + NTSTATUS status; + UNICODE_STRING nt_name; + SECTION_IMAGE_INFORMATION info; + enum loadorder loadorder; + const WCHAR *app_name = NULL; + + if (NtCurrentTeb()->Peb->ImageBaseAddress) + app_name = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer; + + init_unicode_string( &nt_name, filename ); + loadorder = get_load_order( app_name, &nt_name ); + + if (image_info->image_flags & IMAGE_FLAGS_WineBuiltin) + { + switch (loadorder) + { + case LO_NATIVE_BUILTIN: + case LO_BUILTIN: + case LO_BUILTIN_NATIVE: + case LO_DEFAULT: + status = find_builtin_dll( &nt_name, module, size, &info, FALSE ); + if (status == STATUS_DLL_NOT_FOUND) return STATUS_IMAGE_ALREADY_LOADED; + return status; + default: + return STATUS_DLL_NOT_FOUND; + } + } + if (image_info->image_flags & IMAGE_FLAGS_WineFakeDll) + { + TRACE( "%s is a fake Wine dll\n", debugstr_us(&nt_name) ); + switch (loadorder) + { + case LO_NATIVE_BUILTIN: + case LO_BUILTIN: + case LO_BUILTIN_NATIVE: + case LO_DEFAULT: + return find_builtin_dll( &nt_name, module, size, &info, FALSE ); + default: + return STATUS_DLL_NOT_FOUND; + } + } + switch (loadorder) + { + case LO_NATIVE: + case LO_NATIVE_BUILTIN: + return STATUS_IMAGE_ALREADY_LOADED; + case LO_BUILTIN: + return find_builtin_dll( &nt_name, module, size, &info, FALSE ); + case LO_BUILTIN_NATIVE: + case LO_DEFAULT: + status = find_builtin_dll( &nt_name, module, size, &info, (loadorder == LO_DEFAULT) ); + if (status == STATUS_DLL_NOT_FOUND) return STATUS_IMAGE_ALREADY_LOADED; + return status; + default: + return STATUS_DLL_NOT_FOUND; + } +} + + #ifdef __FreeBSD__ /* The PT_LOAD segments are sorted in increasing order, and the first * starts at the beginning of the ELF file. By parsing the file, we can diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index e527f5f799b..5e9eacb3bf8 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -141,6 +141,8 @@ extern DWORD ntdll_umbstowcs( const char *src, DWORD srclen, WCHAR *dst, DWORD d extern int ntdll_wcstoumbs( const WCHAR *src, DWORD srclen, char *dst, DWORD dstlen, BOOL strict ) DECLSPEC_HIDDEN; extern char **build_envp( const WCHAR *envW ) DECLSPEC_HIDDEN; extern NTSTATUS exec_wineloader( char **argv, int socketfd, const pe_image_info_t *pe_info ) DECLSPEC_HIDDEN; +extern NTSTATUS load_builtin( const pe_image_info_t *image_info, const WCHAR *filename, + void **addr_ptr, SIZE_T *size_ptr ) DECLSPEC_HIDDEN; extern void start_server( BOOL debug ) DECLSPEC_HIDDEN; extern ULONG_PTR get_image_address(void) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index a38b8478371..69592892840 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2531,8 +2531,11 @@ static NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned sh if (image_info) { filename = (WCHAR *)(image_info + 1); - res = virtual_map_image( handle, access, addr_ptr, size_ptr, zero_bits_64, shared_file, - alloc_type, image_info, filename, FALSE ); + /* check if we can replace that mapping with the builtin */ + res = load_builtin( image_info, filename, addr_ptr, size_ptr ); + if (res == STATUS_IMAGE_ALREADY_LOADED) + res = virtual_map_image( handle, access, addr_ptr, size_ptr, zero_bits_64, shared_file, + alloc_type, image_info, filename, FALSE ); if (shared_file) NtClose( shared_file ); free( image_info ); return res;