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
...@@ -1915,7 +1915,7 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name, ...@@ -1915,7 +1915,7 @@ static NTSTATUS build_module( LPCWSTR load_path, const UNICODE_STRING *nt_name,
} }
} }
TRACE( "loaded %s %p %p\n", debugstr_us(nt_name), wm, module ); TRACE( "loaded %s %p %p\n", debugstr_us(nt_name), wm, *module );
/* send DLL load event */ /* send DLL load event */
...@@ -2247,7 +2247,7 @@ static NTSTATUS get_dll_load_path_search_flags( LPCWSTR module, DWORD flags, WCH ...@@ -2247,7 +2247,7 @@ static NTSTATUS get_dll_load_path_search_flags( LPCWSTR module, DWORD flags, WCH
* *
* Open a file for a new dll. Helper for find_dll_file. * Open a file for a new dll. Helper for find_dll_file.
*/ */
static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module, static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, HANDLE *mapping,
SECTION_IMAGE_INFORMATION *image_info, struct file_id *id ) SECTION_IMAGE_INFORMATION *image_info, struct file_id *id )
{ {
FILE_BASIC_INFORMATION info; FILE_BASIC_INFORMATION info;
...@@ -2255,16 +2255,10 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void ...@@ -2255,16 +2255,10 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
IO_STATUS_BLOCK io; IO_STATUS_BLOCK io;
LARGE_INTEGER size; LARGE_INTEGER size;
FILE_OBJECTID_BUFFER fid; FILE_OBJECTID_BUFFER fid;
SIZE_T len = 0;
NTSTATUS status; NTSTATUS status;
HANDLE handle, mapping; HANDLE handle;
if ((*pwm = find_fullname_module( nt_name ))) if ((*pwm = find_fullname_module( nt_name ))) return STATUS_SUCCESS;
{
NtUnmapViewOfSection( NtCurrentProcess(), *module );
*module = NULL;
return STATUS_SUCCESS;
}
attr.Length = sizeof(attr); attr.Length = sizeof(attr);
attr.RootDirectory = 0; attr.RootDirectory = 0;
...@@ -2295,42 +2289,25 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void ...@@ -2295,42 +2289,25 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
TRACE( "%s is the same file as existing module %p %s\n", debugstr_w( nt_name->Buffer ), TRACE( "%s is the same file as existing module %p %s\n", debugstr_w( nt_name->Buffer ),
(*pwm)->ldr.DllBase, debugstr_w( (*pwm)->ldr.FullDllName.Buffer )); (*pwm)->ldr.DllBase, debugstr_w( (*pwm)->ldr.FullDllName.Buffer ));
NtClose( handle ); NtClose( handle );
NtUnmapViewOfSection( NtCurrentProcess(), *module );
*module = NULL;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
} }
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 );
if (!status) if (!status)
{ {
NtQuerySection( mapping, SectionImageInformation, image_info, sizeof(*image_info), NULL ); NtQuerySection( *mapping, SectionImageInformation, image_info, sizeof(*image_info), NULL );
if (!is_valid_binary( handle, image_info )) if (!is_valid_binary( handle, image_info ))
{ {
TRACE( "%s is for arch %x, continuing search\n", debugstr_us(nt_name), image_info->Machine ); TRACE( "%s is for arch %x, continuing search\n", debugstr_us(nt_name), image_info->Machine );
status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH; status = STATUS_IMAGE_MACHINE_TYPE_MISMATCH;
NtClose( mapping ); NtClose( *mapping );
} }
} }
NtClose( handle ); NtClose( handle );
if (!status)
{
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;
#ifdef _WIN64
if (!status && !convert_to_pe64( *module, image_info )) status = STATUS_INVALID_IMAGE_FORMAT;
#endif
NtClose( mapping );
}
return status; return status;
} }
...@@ -2338,11 +2315,22 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void ...@@ -2338,11 +2315,22 @@ static NTSTATUS open_dll_file( UNICODE_STRING *nt_name, WINE_MODREF **pwm, void
/****************************************************************************** /******************************************************************************
* load_native_dll (internal) * load_native_dll (internal)
*/ */
static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module, static NTSTATUS load_native_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, HANDLE mapping,
const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id, const SECTION_IMAGE_INFORMATION *image_info, const struct file_id *id,
DWORD flags, WINE_MODREF** pwm ) DWORD flags, WINE_MODREF** pwm )
{ {
return build_module( load_path, nt_name, module, image_info, id, flags, pwm ); void *module = NULL;
SIZE_T len = 0;
NTSTATUS status = NtMapViewOfSection( mapping, NtCurrentProcess(), &module, 0, 0, NULL, &len,
ViewShare, 0, PAGE_EXECUTE_READ );
if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS;
#ifdef _WIN64
if (!status && !convert_to_pe64( module, image_info )) status = STATUS_INVALID_IMAGE_FORMAT;
#endif
if (!status) status = build_module( load_path, nt_name, &module, image_info, id, flags, pwm );
if (status && module) NtUnmapViewOfSection( NtCurrentProcess(), module );
return status;
} }
...@@ -2383,12 +2371,12 @@ static NTSTATUS load_so_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, ...@@ -2383,12 +2371,12 @@ static NTSTATUS load_so_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name,
/*********************************************************************** /***********************************************************************
* load_builtin_dll * load_builtin_dll
*/ */
static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, void **module_ptr, static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name,
DWORD flags, WINE_MODREF** pwm ) DWORD flags, WINE_MODREF** pwm )
{ {
const WCHAR *name, *p; const WCHAR *name, *p;
NTSTATUS status; NTSTATUS status;
void *module = NULL, *unix_entry = NULL; void *module, *unix_entry = NULL;
SECTION_IMAGE_INFORMATION image_info; SECTION_IMAGE_INFORMATION image_info;
/* Fix the name in case we have a full path and extension */ /* Fix the name in case we have a full path and extension */
...@@ -2398,25 +2386,22 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na ...@@ -2398,25 +2386,22 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, const UNICODE_STRING *nt_na
TRACE("Trying built-in %s\n", debugstr_w(name)); TRACE("Trying built-in %s\n", debugstr_w(name));
if (!module_ptr) module_ptr = &module; status = unix_funcs->load_builtin_dll( name, &module, &unix_entry, &image_info );
status = unix_funcs->load_builtin_dll( name, module_ptr, &unix_entry, &image_info );
if (status) return status; if (status) return status;
if ((*pwm = get_modref( *module_ptr ))) /* already loaded */ if ((*pwm = get_modref( module ))) /* already loaded */
{ {
if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++; if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
TRACE( "Found %s for %s at %p, count=%d\n", TRACE( "Found %s for %s at %p, count=%d\n",
debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(name), debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(name),
(*pwm)->ldr.DllBase, (*pwm)->ldr.LoadCount); (*pwm)->ldr.DllBase, (*pwm)->ldr.LoadCount);
*module_ptr = NULL;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
TRACE( "loading %s from %s\n", debugstr_w(name), debugstr_us(nt_name) ); TRACE( "loading %s from %s\n", debugstr_w(name), debugstr_us(nt_name) );
status = build_module( load_path, nt_name, module_ptr, &image_info, NULL, flags, pwm ); status = build_module( load_path, nt_name, &module, &image_info, NULL, flags, pwm );
if (!status) (*pwm)->unix_entry = unix_entry; if (!status) (*pwm)->unix_entry = unix_entry;
else if (*module_ptr) unix_funcs->unload_builtin_dll( *module_ptr ); else if (module) unix_funcs->unload_builtin_dll( module );
return status; return status;
} }
...@@ -2527,7 +2512,7 @@ done: ...@@ -2527,7 +2512,7 @@ done:
* Search for dll in the specified paths. * Search for dll in the specified paths.
*/ */
static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *nt_name, static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *nt_name,
WINE_MODREF **pwm, void **module, SECTION_IMAGE_INFORMATION *image_info, WINE_MODREF **pwm, HANDLE *mapping, SECTION_IMAGE_INFORMATION *image_info,
struct file_id *id ) struct file_id *id )
{ {
WCHAR *name; WCHAR *name;
...@@ -2555,7 +2540,7 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING * ...@@ -2555,7 +2540,7 @@ static NTSTATUS search_dll_file( LPCWSTR paths, LPCWSTR search, UNICODE_STRING *
nt_name->Buffer = NULL; nt_name->Buffer = NULL;
if ((status = RtlDosPathNameToNtPathName_U_WithStatus( name, nt_name, NULL, NULL ))) goto done; if ((status = RtlDosPathNameToNtPathName_U_WithStatus( name, nt_name, NULL, NULL ))) goto done;
status = open_dll_file( nt_name, pwm, module, image_info, id ); status = open_dll_file( nt_name, pwm, mapping, image_info, id );
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;
RtlFreeUnicodeString( nt_name ); RtlFreeUnicodeString( nt_name );
...@@ -2583,7 +2568,7 @@ done: ...@@ -2583,7 +2568,7 @@ done:
* Find the file (or already loaded module) for a given dll name. * Find the file (or already loaded module) for a given dll name.
*/ */
static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext, static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, const WCHAR *default_ext,
UNICODE_STRING *nt_name, WINE_MODREF **pwm, void **module, UNICODE_STRING *nt_name, WINE_MODREF **pwm, HANDLE *mapping,
SECTION_IMAGE_INFORMATION *image_info, struct file_id *id ) SECTION_IMAGE_INFORMATION *image_info, struct file_id *id )
{ {
WCHAR *ext, *dllname; WCHAR *ext, *dllname;
...@@ -2591,7 +2576,6 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con ...@@ -2591,7 +2576,6 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con
ULONG wow64_old_value = 0; ULONG wow64_old_value = 0;
*pwm = NULL; *pwm = NULL;
*module = NULL;
dllname = NULL; dllname = NULL;
if (default_ext) /* first append default extension */ if (default_ext) /* first append default extension */
...@@ -2635,9 +2619,9 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con ...@@ -2635,9 +2619,9 @@ static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname, con
} }
if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH) if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
status = search_dll_file( load_path, libname, nt_name, pwm, module, image_info, id ); status = search_dll_file( load_path, libname, nt_name, pwm, mapping, image_info, id );
else if (!(status = RtlDosPathNameToNtPathName_U_WithStatus( libname, nt_name, NULL, NULL ))) else if (!(status = RtlDosPathNameToNtPathName_U_WithStatus( libname, nt_name, NULL, NULL )))
status = open_dll_file( nt_name, pwm, module, image_info, id ); status = open_dll_file( nt_name, pwm, mapping, image_info, id );
if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) status = STATUS_INVALID_IMAGE_FORMAT; if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) status = STATUS_INVALID_IMAGE_FORMAT;
...@@ -2661,13 +2645,13 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC ...@@ -2661,13 +2645,13 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
WINE_MODREF *main_exe; WINE_MODREF *main_exe;
UNICODE_STRING nt_name; UNICODE_STRING nt_name;
struct file_id id; struct file_id id;
void *module; HANDLE mapping = 0;
SECTION_IMAGE_INFORMATION image_info; SECTION_IMAGE_INFORMATION image_info;
NTSTATUS nts; NTSTATUS nts;
TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) ); TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &module, &image_info, &id ); nts = find_dll_file( load_path, libname, default_ext, &nt_name, pwm, &mapping, &image_info, &id );
if (*pwm) /* found already loaded module */ if (*pwm) /* found already loaded module */
{ {
...@@ -2712,15 +2696,14 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC ...@@ -2712,15 +2696,14 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
case LO_BUILTIN: case LO_BUILTIN:
case LO_BUILTIN_NATIVE: case LO_BUILTIN_NATIVE:
case LO_DEFAULT: case LO_DEFAULT:
nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm ); nts = load_builtin_dll( load_path, &nt_name, flags, pwm );
if (nts == STATUS_DLL_NOT_FOUND) if (nts == STATUS_DLL_NOT_FOUND)
nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm ); nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, pwm );
break; break;
default: default:
nts = STATUS_DLL_NOT_FOUND; nts = STATUS_DLL_NOT_FOUND;
break; break;
} }
if (module) NtUnmapViewOfSection( NtCurrentProcess(), module );
break; break;
} }
if (!(image_info.u.ImageFlags & IMAGE_FLAGS_WineFakeDll)) if (!(image_info.u.ImageFlags & IMAGE_FLAGS_WineFakeDll))
...@@ -2729,14 +2712,14 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC ...@@ -2729,14 +2712,14 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
{ {
case LO_NATIVE: case LO_NATIVE:
case LO_NATIVE_BUILTIN: case LO_NATIVE_BUILTIN:
nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm ); nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, pwm );
break; break;
case LO_BUILTIN: case LO_BUILTIN:
nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm ); nts = load_builtin_dll( load_path, &nt_name, flags, pwm );
break; break;
case LO_BUILTIN_NATIVE: case LO_BUILTIN_NATIVE:
case LO_DEFAULT: case LO_DEFAULT:
nts = load_builtin_dll( load_path, &nt_name, &module, flags, pwm ); nts = load_builtin_dll( load_path, &nt_name, flags, pwm );
if (nts == STATUS_SUCCESS && loadorder == LO_DEFAULT && if (nts == STATUS_SUCCESS && loadorder == LO_DEFAULT &&
(MODULE_InitDLL( *pwm, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS)) (MODULE_InitDLL( *pwm, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS))
{ {
...@@ -2744,21 +2727,17 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC ...@@ -2744,21 +2727,17 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
TRACE( "%s pre-attach returned FALSE, preferring native\n", debugstr_us(&nt_name) ); TRACE( "%s pre-attach returned FALSE, preferring native\n", debugstr_us(&nt_name) );
LdrUnloadDll( (*pwm)->ldr.DllBase ); LdrUnloadDll( (*pwm)->ldr.DllBase );
nts = STATUS_DLL_NOT_FOUND; nts = STATUS_DLL_NOT_FOUND;
/* map the dll again if it was unmapped */
if (!module && open_dll_file( &nt_name, pwm, &module, &image_info, &id )) break;
} }
if (nts == STATUS_DLL_NOT_FOUND) if (nts == STATUS_DLL_NOT_FOUND)
nts = load_native_dll( load_path, &nt_name, &module, &image_info, &id, flags, pwm ); nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, pwm );
break; break;
default: default:
nts = STATUS_DLL_NOT_FOUND; nts = STATUS_DLL_NOT_FOUND;
break; break;
} }
if (module) NtUnmapViewOfSection( NtCurrentProcess(), module );
break; break;
} }
TRACE( "%s is a fake Wine dll\n", debugstr_us(&nt_name) ); TRACE( "%s is a fake Wine dll\n", debugstr_us(&nt_name) );
NtUnmapViewOfSection( NtCurrentProcess(), module );
/* fall through */ /* fall through */
case STATUS_DLL_NOT_FOUND: /* no file found, try builtin */ case STATUS_DLL_NOT_FOUND: /* no file found, try builtin */
...@@ -2768,7 +2747,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC ...@@ -2768,7 +2747,7 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, const WC
case LO_BUILTIN: case LO_BUILTIN:
case LO_BUILTIN_NATIVE: case LO_BUILTIN_NATIVE:
case LO_DEFAULT: case LO_DEFAULT:
nts = load_builtin_dll( load_path, &nt_name, NULL, flags, pwm ); nts = load_builtin_dll( load_path, &nt_name, flags, pwm );
break; break;
default: default:
nts = STATUS_DLL_NOT_FOUND; nts = STATUS_DLL_NOT_FOUND;
...@@ -2783,6 +2762,7 @@ done: ...@@ -2783,6 +2762,7 @@ done:
else else
WARN("Failed to load module %s; status=%x\n", debugstr_w(libname), nts); WARN("Failed to load module %s; status=%x\n", debugstr_w(libname), nts);
if (mapping) NtClose( mapping );
RtlFreeUnicodeString( &nt_name ); RtlFreeUnicodeString( &nt_name );
return nts; return nts;
} }
...@@ -2848,7 +2828,7 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S ...@@ -2848,7 +2828,7 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
NTSTATUS status; NTSTATUS status;
UNICODE_STRING nt_name; UNICODE_STRING nt_name;
WINE_MODREF *wm; WINE_MODREF *wm;
void *module; HANDLE mapping;
SECTION_IMAGE_INFORMATION image_info; SECTION_IMAGE_INFORMATION image_info;
struct file_id id; struct file_id id;
...@@ -2856,12 +2836,12 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S ...@@ -2856,12 +2836,12 @@ NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_S
if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer; if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
status = find_dll_file( load_path, name->Buffer, L".dll", &nt_name, &wm, &module, &image_info, &id ); status = find_dll_file( load_path, name->Buffer, L".dll", &nt_name, &wm, &mapping, &image_info, &id );
if (wm) *base = wm->ldr.DllBase; if (wm) *base = wm->ldr.DllBase;
else else
{ {
if (status == STATUS_SUCCESS) NtUnmapViewOfSection( NtCurrentProcess(), module ); if (status == STATUS_SUCCESS) NtClose( mapping );
status = STATUS_DLL_NOT_FOUND; status = STATUS_DLL_NOT_FOUND;
} }
RtlFreeUnicodeString( &nt_name ); RtlFreeUnicodeString( &nt_name );
......
...@@ -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