ntdll: Support loading a PE-format ntdll.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-06-30 12:00:57 +02:00
parent 4fcf20d1d1
commit f89f7a54c2
4 changed files with 78 additions and 12 deletions

View File

@ -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, static NTSTATUS build_builtin_module( const WCHAR *load_path, const UNICODE_STRING *nt_name,
void *module, DWORD flags, WINE_MODREF **pwm ) void *module, DWORD flags, WINE_MODREF **pwm )
{ {
NTSTATUS status; NTSTATUS status;
pe_image_info_t image_info = { 0 }; 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 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 ); TRACE_(loaddll)( "Loaded %s at %p: builtin\n", debugstr_us(nt_name), module );
} }
*pwm = wm; *pwm = wm;
@ -3919,7 +3919,6 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
*/ */
void __wine_process_init(void) 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','\\', static const WCHAR ntdllW[] = {'\\','?','?','\\','C',':','\\','w','i','n','d','o','w','s','\\',
's','y','s','t','e','m','3','2','\\', 's','y','s','t','e','m','3','2','\\',
'n','t','d','l','l','.','d','l','l',0}; 'n','t','d','l','l','.','d','l','l',0};
@ -3932,7 +3931,7 @@ void __wine_process_init(void)
NTSTATUS status; NTSTATUS status;
ANSI_STRING func_name; ANSI_STRING func_name;
UNICODE_STRING nt_name; UNICODE_STRING nt_name;
HMODULE ntdll_module = (HMODULE)((__wine_spec_nt_header.OptionalHeader.ImageBase + 0xffff) & ~0xffff); MEMORY_BASIC_INFORMATION meminfo;
INITIAL_TEB stack; INITIAL_TEB stack;
ULONG_PTR val; ULONG_PTR val;
TEB *teb = NtCurrentTeb(); TEB *teb = NtCurrentTeb();
@ -3976,7 +3975,9 @@ void __wine_process_init(void)
/* setup the load callback and create ntdll modref */ /* setup the load callback and create ntdll modref */
RtlInitUnicodeString( &nt_name, ntdllW ); 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 ); assert( !status );
RtlInitUnicodeString( &nt_name, kernel32W ); RtlInitUnicodeString( &nt_name, kernel32W );

View File

@ -124,7 +124,7 @@ const char *build_dir = NULL;
const char *config_dir = NULL; const char *config_dir = NULL;
const char **dll_paths = NULL; const char **dll_paths = NULL;
const char *user_name = NULL; const char *user_name = NULL;
HMODULE ntdll_module = NULL; static HMODULE ntdll_module;
struct file_id struct file_id
{ {
@ -1295,10 +1295,22 @@ found:
*/ */
static HMODULE load_ntdll(void) static HMODULE load_ntdll(void)
{ {
NTSTATUS status;
void *module; void *module;
char *name = build_path( dll_dir, "ntdll.dll.so" ); int fd;
NTSTATUS status = dlopen_dll( name, &module ); 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 ); if (status) fatal_error( "failed to load %s error %x\n", name, status );
free( name ); free( name );
return module; return module;

View File

@ -134,7 +134,6 @@ extern const char *build_dir DECLSPEC_HIDDEN;
extern const char *config_dir DECLSPEC_HIDDEN; extern const char *config_dir DECLSPEC_HIDDEN;
extern const char *user_name DECLSPEC_HIDDEN; extern const char *user_name DECLSPEC_HIDDEN;
extern const char **dll_paths DECLSPEC_HIDDEN; extern const char **dll_paths DECLSPEC_HIDDEN;
extern HMODULE ntdll_module DECLSPEC_HIDDEN;
extern USHORT *uctable DECLSPEC_HIDDEN; extern USHORT *uctable DECLSPEC_HIDDEN;
extern USHORT *lctable DECLSPEC_HIDDEN; extern USHORT *lctable DECLSPEC_HIDDEN;
extern SIZE_T startup_info_size 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; data_size_t *ret_len ) DECLSPEC_HIDDEN;
extern void virtual_init(void) 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 ULONG_PTR get_system_affinity_mask(void) DECLSPEC_HIDDEN;
extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN; extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_create_builtin_view( void *module ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_create_builtin_view( void *module ) DECLSPEC_HIDDEN;

View File

@ -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_PTR get_system_affinity_mask(void)
{ {
ULONG num_cpus = NtCurrentTeb()->Peb->NumberOfProcessors; ULONG num_cpus = NtCurrentTeb()->Peb->NumberOfProcessors;