ntdll: Support loading a PE-format ntdll.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4fcf20d1d1
commit
f89f7a54c2
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue