Alexandre Julliard : ntdll: Support loading a PE-format ntdll.
Alexandre Julliard
julliard at winehq.org
Tue Jun 30 14:55:06 CDT 2020
Module: wine
Branch: master
Commit: f89f7a54c25eb202e70225713ed39687be048e26
URL: https://source.winehq.org/git/wine.git/?a=commit;h=f89f7a54c25eb202e70225713ed39687be048e26
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue Jun 30 12:00:57 2020 +0200
ntdll: Support loading a PE-format ntdll.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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 efacc0c081..4657745a28 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 f6004c6081..b47efcd0e5 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 6971e6fe91..71d6ee7d4f 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 2fe46c400a..d998966b5f 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;
More information about the wine-cvs
mailing list