From f89f7a54c25eb202e70225713ed39687be048e26 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 30 Jun 2020 12:00:57 +0200 Subject: [PATCH] ntdll: Support loading a PE-format ntdll. Signed-off-by: Alexandre Julliard --- dlls/ntdll/loader.c | 17 ++++++----- dlls/ntdll/unix/loader.c | 18 ++++++++++-- dlls/ntdll/unix/unix_private.h | 2 +- dlls/ntdll/unix/virtual.c | 53 ++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 12 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index efacc0c081e..4657745a28f 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1956,12 +1956,12 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, /************************************************************************* - * build_so_dll_module + * build_builtin_module * - * Build the module for a .so builtin library. + * Build the module for a builtin library. */ -static NTSTATUS build_so_dll_module( const WCHAR *load_path, const UNICODE_STRING *nt_name, - void *module, DWORD flags, WINE_MODREF **pwm ) +static NTSTATUS build_builtin_module( const WCHAR *load_path, const UNICODE_STRING *nt_name, + void *module, DWORD flags, WINE_MODREF **pwm ) { NTSTATUS status; pe_image_info_t image_info = { 0 }; @@ -2337,7 +2337,7 @@ static NTSTATUS load_so_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, } else { - if ((status = build_so_dll_module( load_path, &win_name, module, flags, &wm ))) return status; + if ((status = build_builtin_module( load_path, &win_name, module, flags, &wm ))) return status; TRACE_(loaddll)( "Loaded %s at %p: builtin\n", debugstr_us(nt_name), module ); } *pwm = wm; @@ -3919,7 +3919,6 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) */ void __wine_process_init(void) { - extern IMAGE_NT_HEADERS __wine_spec_nt_header; static const WCHAR ntdllW[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\', 's','y','s','t','e','m','3','2','\\', 'n','t','d','l','l','.','d','l','l',0}; @@ -3932,7 +3931,7 @@ void __wine_process_init(void) NTSTATUS status; ANSI_STRING func_name; UNICODE_STRING nt_name; - HMODULE ntdll_module = (HMODULE)((__wine_spec_nt_header.OptionalHeader.ImageBase + 0xffff) & ~0xffff); + MEMORY_BASIC_INFORMATION meminfo; INITIAL_TEB stack; ULONG_PTR val; TEB *teb = NtCurrentTeb(); @@ -3976,7 +3975,9 @@ void __wine_process_init(void) /* setup the load callback and create ntdll modref */ RtlInitUnicodeString( &nt_name, ntdllW ); - status = build_so_dll_module( params->DllPath.Buffer, &nt_name, ntdll_module, 0, &wm ); + NtQueryVirtualMemory( GetCurrentProcess(), __wine_process_init, MemoryBasicInformation, + &meminfo, sizeof(meminfo), NULL ); + status = build_builtin_module( params->DllPath.Buffer, &nt_name, meminfo.AllocationBase, 0, &wm ); assert( !status ); RtlInitUnicodeString( &nt_name, kernel32W ); diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index f6004c60818..b47efcd0e51 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -124,7 +124,7 @@ const char *build_dir = NULL; const char *config_dir = NULL; const char **dll_paths = NULL; const char *user_name = NULL; -HMODULE ntdll_module = NULL; +static HMODULE ntdll_module; struct file_id { @@ -1295,10 +1295,22 @@ found: */ static HMODULE load_ntdll(void) { + NTSTATUS status; void *module; - char *name = build_path( dll_dir, "ntdll.dll.so" ); - NTSTATUS status = dlopen_dll( name, &module ); + int fd; + char *name = build_path( dll_dir, "ntdll.dll" ); + if ((fd = open( name, O_RDONLY )) != -1) + { + status = virtual_map_ntdll( fd, &module ); + close( fd ); + } + else + { + free( name ); + name = build_path( dll_dir, "ntdll.dll.so" ); + status = dlopen_dll( name, &module ); + } if (status) fatal_error( "failed to load %s error %x\n", name, status ); free( name ); return module; diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 6971e6fe917..71d6ee7d4f2 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -134,7 +134,6 @@ extern const char *build_dir DECLSPEC_HIDDEN; extern const char *config_dir DECLSPEC_HIDDEN; extern const char *user_name DECLSPEC_HIDDEN; extern const char **dll_paths DECLSPEC_HIDDEN; -extern HMODULE ntdll_module DECLSPEC_HIDDEN; extern USHORT *uctable DECLSPEC_HIDDEN; extern USHORT *lctable DECLSPEC_HIDDEN; extern SIZE_T startup_info_size DECLSPEC_HIDDEN; @@ -190,6 +189,7 @@ extern NTSTATUS alloc_object_attributes( const OBJECT_ATTRIBUTES *attr, struct o data_size_t *ret_len ) DECLSPEC_HIDDEN; extern void virtual_init(void) DECLSPEC_HIDDEN; +extern NTSTATUS virtual_map_ntdll( int fd, void **module ) DECLSPEC_HIDDEN; extern ULONG_PTR get_system_affinity_mask(void) DECLSPEC_HIDDEN; extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_create_builtin_view( void *module ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 2fe46c400a0..d998966b5fa 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2413,6 +2413,59 @@ void virtual_init(void) } +/*********************************************************************** + * virtual_map_ntdll + * + * Map ntdll, used instead of virtual_map_section() because some things are not initialized yet. + */ +NTSTATUS virtual_map_ntdll( int fd, void **module ) +{ + IMAGE_DOS_HEADER dos; + IMAGE_NT_HEADERS nt; + NTSTATUS status; + SIZE_T size; + void *base; + unsigned int vprot; + struct file_view *view; + + /* load the headers */ + + size = pread( fd, &dos, sizeof(dos), 0 ); + if (size < sizeof(dos)) return STATUS_INVALID_IMAGE_FORMAT; + if (dos.e_magic != IMAGE_DOS_SIGNATURE) return STATUS_INVALID_IMAGE_FORMAT; + + size = pread( fd, &nt, sizeof(nt), dos.e_lfanew ); + if (size < sizeof(nt)) return STATUS_INVALID_IMAGE_PROTECT; + if (nt.Signature != IMAGE_NT_SIGNATURE) return STATUS_INVALID_IMAGE_FORMAT; + if (nt.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; +#ifdef __i386__ + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_I386) return STATUS_INVALID_IMAGE_FORMAT; +#elif defined(__x86_64__) + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) return STATUS_INVALID_IMAGE_FORMAT; +#elif defined(__arm__) + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARM && + nt.FileHeader.Machine != IMAGE_FILE_MACHINE_THUMB && + nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARMNT) return STATUS_INVALID_IMAGE_FORMAT; +#elif defined(__aarch64__) + if (nt.FileHeader.Machine != IMAGE_FILE_MACHINE_ARM64) return STATUS_INVALID_IMAGE_FORMAT; +#endif + + base = (void *)nt.OptionalHeader.ImageBase; + size = ROUND_SIZE( 0, nt.OptionalHeader.SizeOfImage ); + vprot = SEC_IMAGE | SEC_FILE | VPROT_COMMITTED | VPROT_READ | VPROT_EXEC | VPROT_WRITECOPY; + + status = map_view( &view, base, size, FALSE, vprot, 0 ); + if (status == STATUS_CONFLICTING_ADDRESSES) + ERR( "couldn't load ntdll at preferred address %p\n", base ); + if (status) return status; + *module = view->base; + return map_image_into_view( view, fd, base, nt.OptionalHeader.SizeOfHeaders, 0, -1, FALSE ); +} + + +/*********************************************************************** + * get_system_affinity_mask + */ ULONG_PTR get_system_affinity_mask(void) { ULONG num_cpus = NtCurrentTeb()->Peb->NumberOfProcessors;