Commit 5fef775d authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Delay mapping a module until we have found the final one to load.

parent 63b62953
...@@ -1140,15 +1140,14 @@ static inline char *prepend( char *buffer, const char *str, size_t len ) ...@@ -1140,15 +1140,14 @@ static inline char *prepend( char *buffer, const char *str, size_t len )
* *
* Open a file for a new dll. Helper for open_builtin_file. * Open a file for a new dll. Helper for open_builtin_file.
*/ */
static NTSTATUS open_dll_file( const char *name, void **module, SECTION_IMAGE_INFORMATION *image_info ) static NTSTATUS open_dll_file( const char *name, HANDLE *mapping, void **module,
SECTION_IMAGE_INFORMATION *image_info, struct stat *st )
{ {
struct builtin_module *builtin; struct builtin_module *builtin;
OBJECT_ATTRIBUTES attr = { sizeof(attr) }; OBJECT_ATTRIBUTES attr = { sizeof(attr) };
LARGE_INTEGER size; LARGE_INTEGER size;
struct stat st;
SIZE_T len = 0;
NTSTATUS status; NTSTATUS status;
HANDLE handle, mapping; HANDLE handle;
if ((status = open_unix_file( &handle, name, GENERIC_READ | SYNCHRONIZE, &attr, 0, if ((status = open_unix_file( &handle, name, GENERIC_READ | SYNCHRONIZE, &attr, 0,
FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN,
...@@ -1157,70 +1156,50 @@ static NTSTATUS open_dll_file( const char *name, void **module, SECTION_IMAGE_IN ...@@ -1157,70 +1156,50 @@ static NTSTATUS open_dll_file( const char *name, void **module, SECTION_IMAGE_IN
if (status != STATUS_OBJECT_PATH_NOT_FOUND && status != STATUS_OBJECT_NAME_NOT_FOUND) if (status != STATUS_OBJECT_PATH_NOT_FOUND && status != STATUS_OBJECT_NAME_NOT_FOUND)
{ {
/* if the file exists but failed to open, report the error */ /* if the file exists but failed to open, report the error */
if (!stat( name, &st )) return status; if (!stat( name, st )) return status;
} }
/* otherwise continue searching */ /* otherwise continue searching */
return STATUS_DLL_NOT_FOUND; return STATUS_DLL_NOT_FOUND;
} }
if (!stat( name, &st )) if (!stat( name, st ))
{ {
LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry )
{ {
if (builtin->id.dev == st.st_dev && builtin->id.ino == st.st_ino) if (builtin->id.dev == st->st_dev && builtin->id.ino == st->st_ino)
{ {
TRACE( "%s is the same file as existing module %p\n", debugstr_a(name), TRACE( "%s is the same file as existing module %p\n", debugstr_a(name),
builtin->module ); builtin->module );
NtClose( handle ); NtClose( handle );
NtUnmapViewOfSection( NtCurrentProcess(), *module );
*module = builtin->module; *module = builtin->module;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
} }
} }
else memset( &st, 0, sizeof(st) ); else memset( st, 0, sizeof(*st) );
*module = NULL;
size.QuadPart = 0; size.QuadPart = 0;
status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | status = NtCreateSection( mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY |
SECTION_MAP_READ | SECTION_MAP_EXECUTE, SECTION_MAP_READ | SECTION_MAP_EXECUTE,
NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle ); NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle );
NtClose( handle ); NtClose( handle );
if (status) return status; if (status) return status;
NtQuerySection( mapping, SectionImageInformation, image_info, sizeof(*image_info), NULL ); NtQuerySection( *mapping, SectionImageInformation, image_info, sizeof(*image_info), NULL );
/* ignore non-builtins */ /* ignore non-builtins */
if (!(image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin)) if (!(image_info->u.ImageFlags & IMAGE_FLAGS_WineBuiltin))
{ {
WARN( "%s found in WINEDLLPATH but not a builtin, ignoring\n", debugstr_a(name) ); WARN( "%s found in WINEDLLPATH but not a builtin, ignoring\n", debugstr_a(name) );
status = STATUS_DLL_NOT_FOUND; status = STATUS_DLL_NOT_FOUND;
NtClose( *mapping );
} }
else if (!is_valid_binary( image_info )) else if (!is_valid_binary( image_info ))
{ {
TRACE( "%s is for arch %x, continuing search\n", debugstr_a(name), image_info->Machine ); TRACE( "%s is for arch %x, continuing search\n", debugstr_a(name), image_info->Machine );
status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
NtClose( *mapping );
} }
else
{
if (*module)
{
NtUnmapViewOfSection( NtCurrentProcess(), *module );
*module = NULL;
}
status = NtMapViewOfSection( mapping, NtCurrentProcess(), module, 0, 0, NULL, &len,
ViewShare, 0, PAGE_EXECUTE_READ );
if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS;
if (!status)
{
status = add_builtin_module( *module, NULL, &st );
if (status)
{
NtUnmapViewOfSection( NtCurrentProcess(), *module );
*module = NULL;
}
}
}
NtClose( mapping );
return status; return status;
} }
...@@ -1228,12 +1207,13 @@ static NTSTATUS open_dll_file( const char *name, void **module, SECTION_IMAGE_IN ...@@ -1228,12 +1207,13 @@ static NTSTATUS open_dll_file( const char *name, void **module, SECTION_IMAGE_IN
/*********************************************************************** /***********************************************************************
* open_builtin_file * open_builtin_file
*/ */
static NTSTATUS open_builtin_file( char *name, void **module, SECTION_IMAGE_INFORMATION *image_info ) static NTSTATUS open_builtin_file( char *name, HANDLE *mapping, void **module,
SECTION_IMAGE_INFORMATION *image_info, struct stat *st )
{ {
NTSTATUS status; NTSTATUS status;
int fd; int fd;
status = open_dll_file( name, module, image_info ); status = open_dll_file( name, mapping, module, image_info, st );
if (status != STATUS_DLL_NOT_FOUND) return status; if (status != STATUS_DLL_NOT_FOUND) return status;
/* try .so file */ /* try .so file */
...@@ -1243,8 +1223,6 @@ static NTSTATUS open_builtin_file( char *name, void **module, SECTION_IMAGE_INFO ...@@ -1243,8 +1223,6 @@ static NTSTATUS open_builtin_file( char *name, void **module, SECTION_IMAGE_INFO
{ {
if (check_library_arch( fd )) if (check_library_arch( fd ))
{ {
NtUnmapViewOfSection( NtCurrentProcess(), *module );
*module = NULL;
if (!dlopen_dll( name, module )) if (!dlopen_dll( name, module ))
{ {
memset( image_info, 0, sizeof(*image_info) ); memset( image_info, 0, sizeof(*image_info) );
...@@ -1265,6 +1243,28 @@ static NTSTATUS open_builtin_file( char *name, void **module, SECTION_IMAGE_INFO ...@@ -1265,6 +1243,28 @@ static NTSTATUS open_builtin_file( char *name, void **module, SECTION_IMAGE_INFO
/*********************************************************************** /***********************************************************************
* map_builtin_module
*/
static NTSTATUS map_builtin_module( HANDLE mapping, void **module, struct stat *st )
{
NTSTATUS status;
SIZE_T len = 0;
*module = NULL;
status = NtMapViewOfSection( mapping, NtCurrentProcess(), module, 0, 0, NULL, &len,
ViewShare, 0, PAGE_EXECUTE_READ );
if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS;
if (!status)
{
status = add_builtin_module( *module, NULL, st );
if (status) NtUnmapViewOfSection( NtCurrentProcess(), *module );
}
return status;
}
/***********************************************************************
* load_builtin_dll * load_builtin_dll
*/ */
static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void **unix_entry, static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void **unix_entry,
...@@ -1274,6 +1274,8 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void * ...@@ -1274,6 +1274,8 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void *
char *ptr = NULL, *file, *ext = NULL; char *ptr = NULL, *file, *ext = NULL;
NTSTATUS status = STATUS_DLL_NOT_FOUND; NTSTATUS status = STATUS_DLL_NOT_FOUND;
BOOL found_image = FALSE; BOOL found_image = FALSE;
HANDLE mapping;
struct stat st;
len = wcslen( name ); len = wcslen( name );
if (build_dir) maxlen = strlen(build_dir) + sizeof("/programs/") + len; if (build_dir) maxlen = strlen(build_dir) + sizeof("/programs/") + len;
...@@ -1302,7 +1304,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void * ...@@ -1302,7 +1304,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void *
ptr = prepend( ptr, ptr, namelen ); ptr = prepend( ptr, ptr, namelen );
ptr = prepend( ptr, "/dlls", sizeof("/dlls") - 1 ); ptr = prepend( ptr, "/dlls", sizeof("/dlls") - 1 );
ptr = prepend( ptr, build_dir, strlen(build_dir) ); ptr = prepend( ptr, build_dir, strlen(build_dir) );
status = open_builtin_file( ptr, module, image_info ); status = open_builtin_file( ptr, &mapping, module, image_info, &st );
if (status != STATUS_DLL_NOT_FOUND) goto done; if (status != STATUS_DLL_NOT_FOUND) goto done;
/* now as a program */ /* now as a program */
...@@ -1313,7 +1315,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void * ...@@ -1313,7 +1315,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void *
ptr = prepend( ptr, ptr, namelen ); ptr = prepend( ptr, ptr, namelen );
ptr = prepend( ptr, "/programs", sizeof("/programs") - 1 ); ptr = prepend( ptr, "/programs", sizeof("/programs") - 1 );
ptr = prepend( ptr, build_dir, strlen(build_dir) ); ptr = prepend( ptr, build_dir, strlen(build_dir) );
status = open_builtin_file( ptr, module, image_info ); status = open_builtin_file( ptr, &mapping, module, image_info, &st );
if (status != STATUS_DLL_NOT_FOUND) goto done; if (status != STATUS_DLL_NOT_FOUND) goto done;
} }
...@@ -1321,7 +1323,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void * ...@@ -1321,7 +1323,7 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void *
{ {
file[pos + len + 1] = 0; file[pos + len + 1] = 0;
ptr = prepend( file + pos, dll_paths[i], strlen(dll_paths[i]) ); ptr = prepend( file + pos, dll_paths[i], strlen(dll_paths[i]) );
status = open_builtin_file( ptr, module, image_info ); status = open_builtin_file( ptr, &mapping, module, image_info, &st );
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE; if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE;
else if (status != STATUS_DLL_NOT_FOUND) goto done; else if (status != STATUS_DLL_NOT_FOUND) goto done;
} }
...@@ -1330,6 +1332,11 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void * ...@@ -1330,6 +1332,11 @@ static NTSTATUS CDECL load_builtin_dll( const WCHAR *name, void **module, void *
WARN( "cannot find builtin library for %s\n", debugstr_w(name) ); WARN( "cannot find builtin library for %s\n", debugstr_w(name) );
done: done:
if (!status && !*module)
{
status = map_builtin_module( mapping, module, &st );
NtClose( mapping );
}
if (!status && ext) if (!status && ext)
{ {
strcpy( ext, ".so" ); strcpy( ext, ".so" );
...@@ -1452,11 +1459,18 @@ static void load_ntdll(void) ...@@ -1452,11 +1459,18 @@ static void load_ntdll(void)
{ {
NTSTATUS status; NTSTATUS status;
SECTION_IMAGE_INFORMATION info; SECTION_IMAGE_INFORMATION info;
void *module = NULL; HANDLE mapping;
struct stat st;
void *module;
char *name = build_path( dll_dir, "ntdll.dll.so" ); char *name = build_path( dll_dir, "ntdll.dll.so" );
name[strlen(name) - 3] = 0; /* remove .so */ name[strlen(name) - 3] = 0; /* remove .so */
status = open_builtin_file( name, &module, &info ); status = open_builtin_file( name, &mapping, &module, &info, &st );
if (!status && !module)
{
status = map_builtin_module( mapping, &module, &st );
NtClose( mapping );
}
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 );
load_ntdll_functions( module ); load_ntdll_functions( module );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment