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