diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index a7e6d712df1..21d752b18ca 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2323,7 +2323,7 @@ static NTSTATUS load_so_dll( LPCWSTR load_path, const UNICODE_STRING *nt_name, image_info.u.s.WineBuiltin = 1; if ((status = build_module( load_path, &win_name, &module, &image_info, NULL, flags, &wm ))) { - if (module) unix_funcs->unload_builtin_dll( module ); + if (module) NtUnmapViewOfSection( NtCurrentProcess(), module ); return status; } TRACE_(loaddll)( "Loaded %s at %p: builtin\n", debugstr_us(nt_name), module ); @@ -2360,7 +2360,7 @@ static NTSTATUS load_builtin_dll( LPCWSTR load_path, UNICODE_STRING *nt_name, TRACE( "loading %s\n", debugstr_us(nt_name) ); status = build_module( load_path, nt_name, &module, &image_info, NULL, flags, pwm ); if (!status) (*pwm)->unix_entry = unix_entry; - else if (module) unix_funcs->unload_builtin_dll( module ); + else if (module) NtUnmapViewOfSection( NtCurrentProcess(), module ); return status; } @@ -3245,7 +3245,6 @@ static void free_modref( WINE_MODREF *wm ) free_tls_slot( &wm->ldr ); RtlReleaseActivationContext( wm->ldr.ActivationContext ); - unix_funcs->unload_builtin_dll( wm->ldr.DllBase ); NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.DllBase ); if (cached_modref == wm) cached_modref = NULL; RtlFreeUnicodeString( &wm->ldr.FullDllName ); diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 1c26d1322f8..bfa34e5ee8d 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -132,40 +132,6 @@ const char *user_name = NULL; static HMODULE ntdll_module; static const IMAGE_EXPORT_DIRECTORY *ntdll_exports; -struct file_id -{ - dev_t dev; - ino_t ino; -}; - -struct builtin_module -{ - struct list entry; - struct file_id id; - void *handle; - void *module; - void *unix_handle; -}; - -static struct list builtin_modules = LIST_INIT( builtin_modules ); - -static NTSTATUS add_builtin_module( void *module, void *handle, const struct stat *st ) -{ - struct builtin_module *builtin; - if (!(builtin = malloc( sizeof(*builtin) ))) return STATUS_NO_MEMORY; - builtin->handle = handle; - builtin->module = module; - builtin->unix_handle = NULL; - if (st) - { - builtin->id.dev = st->st_dev; - builtin->id.ino = st->st_ino; - } - else memset( &builtin->id, 0, sizeof(builtin->id) ); - list_add_tail( &builtin_modules, &builtin->entry ); - return STATUS_SUCCESS; -} - /* adjust an array of pointers to make them into RVAs */ static inline void fixup_rva_ptrs( void *array, BYTE *base, unsigned int count ) { @@ -1081,7 +1047,6 @@ static void fill_builtin_image_info( void *module, pe_image_info_t *info ) static NTSTATUS dlopen_dll( const char *so_name, UNICODE_STRING *nt_name, void **ret_module, pe_image_info_t *image_info, BOOL prefer_native ) { - struct builtin_module *builtin; void *module, *handle; const IMAGE_NT_HEADERS *nt; @@ -1097,14 +1062,12 @@ static NTSTATUS dlopen_dll( const char *so_name, UNICODE_STRING *nt_name, void * if (!callback_module) return STATUS_NO_MEMORY; WARN( "got old-style builtin library %s, constructors won't work\n", debugstr_a(so_name) ); module = callback_module; - LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) - if (builtin->module == module) goto already_loaded; + if (get_builtin_so_handle( module )) goto already_loaded; } else if ((nt = dlsym( handle, "__wine_spec_nt_header" ))) { module = (HMODULE)((nt->OptionalHeader.ImageBase + 0xffff) & ~0xffff); - LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) - if (builtin->module == module) goto already_loaded; + if (get_builtin_so_handle( module )) goto already_loaded; if (map_so_dll( nt, module )) { dlclose( handle ); @@ -1114,8 +1077,6 @@ static NTSTATUS dlopen_dll( const char *so_name, UNICODE_STRING *nt_name, void * else /* already loaded .so */ { WARN( "%s already loaded?\n", debugstr_a(so_name)); - LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) - if (builtin->handle == handle) goto already_loaded; return STATUS_INVALID_IMAGE_FORMAT; } @@ -1127,18 +1088,17 @@ static NTSTATUS dlopen_dll( const char *so_name, UNICODE_STRING *nt_name, void * return STATUS_IMAGE_ALREADY_LOADED; } - if (add_builtin_module( module, handle, NULL )) + if (virtual_create_builtin_view( module, nt_name, image_info, handle )) { dlclose( handle ); return STATUS_NO_MEMORY; } - virtual_create_builtin_view( module, nt_name, image_info ); *ret_module = module; return STATUS_SUCCESS; already_loaded: - fill_builtin_image_info( builtin->module, image_info ); - *ret_module = builtin->module; + fill_builtin_image_info( module, image_info ); + *ret_module = module; dlclose( handle ); return STATUS_SUCCESS; } @@ -1149,7 +1109,6 @@ already_loaded: */ static NTSTATUS dlopen_unix_dll( void *module, const char *name, void **unix_entry ) { - struct builtin_module *builtin; void *unix_module, *handle, *entry; const IMAGE_NT_HEADERS *nt; NTSTATUS status = STATUS_INVALID_IMAGE_FORMAT; @@ -1160,34 +1119,26 @@ static NTSTATUS dlopen_unix_dll( void *module, const char *name, void **unix_ent if (!(entry = dlsym( handle, "__wine_init_unix_lib" ))) goto done; unix_module = (HMODULE)((nt->OptionalHeader.ImageBase + 0xffff) & ~0xffff); - LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) + switch (set_builtin_unix_handle( module, handle )) { - if (builtin->module == module) - { - if (builtin->unix_handle == handle) /* already loaded */ - { - *unix_entry = entry; - status = STATUS_SUCCESS; - goto done; - } - if (builtin->unix_handle) - { - ERR( "module %p already has a Unix module that's not %s\n", module, debugstr_a(name) ); - goto done; - } - if ((status = map_so_dll( nt, unix_module ))) goto done; - if ((status = fixup_ntdll_imports( name, unix_module ))) goto done; - builtin->unix_handle = handle; - *unix_entry = entry; - return STATUS_SUCCESS; - } - else if (builtin->unix_handle == handle) - { - ERR( "%s already loaded for module %p\n", debugstr_a(name), module ); - goto done; - } + case STATUS_IMAGE_ALREADY_LOADED: + *unix_entry = entry; + return STATUS_SUCCESS; + case STATUS_SUCCESS: + map_so_dll( nt, unix_module ); + fixup_ntdll_imports( name, unix_module ); + *unix_entry = entry; + return STATUS_SUCCESS; + case STATUS_OBJECT_NAME_COLLISION: + ERR( "module %p already has a Unix module that's not %s\n", module, debugstr_a(name) ); + break; + case STATUS_DUPLICATE_NAME: + ERR( "%s already loaded for module %p\n", debugstr_a(name), module ); + break; + case STATUS_DLL_NOT_FOUND: + ERR( "builtin module not found for %s\n", debugstr_a(name) ); + break; } - ERR( "builtin module not found for %s\n", debugstr_a(name) ); done: dlclose( handle ); return status; @@ -1281,13 +1232,12 @@ static inline char *prepend( char *buffer, const char *str, size_t len ) * * Open a file for a new dll. Helper for open_builtin_file. */ -static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, HANDLE *mapping, void **module, - SECTION_IMAGE_INFORMATION *image_info, struct stat *st, BOOL prefer_native ) +static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, void **module, + SECTION_IMAGE_INFORMATION *image_info, BOOL prefer_native ) { - struct builtin_module *builtin; LARGE_INTEGER size; NTSTATUS status; - HANDLE handle; + HANDLE handle, mapping; if ((status = open_unix_file( &handle, name, GENERIC_READ | SYNCHRONIZE, attr, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, @@ -1296,56 +1246,42 @@ static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, HANDLE 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 (!stat( name, st )) return status; + struct stat st; + if (!stat( name, &st )) return status; } /* otherwise continue searching */ return STATUS_DLL_NOT_FOUND; } - if (!stat( name, st )) - { - LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) - { - 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), - builtin->module ); - NtClose( handle ); - *module = builtin->module; - return STATUS_SUCCESS; - } - } - } - else memset( st, 0, sizeof(*st) ); - - *module = NULL; 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, NULL, &size, PAGE_EXECUTE_READ, SEC_IMAGE, handle ); NtClose( handle ); 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 */ if (!(image_info->u.s.WineBuiltin)) { WARN( "%s found in WINEDLLPATH but not a builtin, ignoring\n", debugstr_a(name) ); - NtClose( *mapping ); + NtClose( mapping ); return STATUS_DLL_NOT_FOUND; } if (!is_valid_binary( image_info )) { TRACE( "%s is for arch %x, continuing search\n", debugstr_a(name), image_info->Machine ); - NtClose( *mapping ); + NtClose( mapping ); return STATUS_IMAGE_MACHINE_TYPE_MISMATCH; } if (prefer_native && (image_info->DllCharacteristics & IMAGE_DLLCHARACTERISTICS_PREFER_NATIVE)) { TRACE( "%s has prefer-native flag, ignoring builtin\n", debugstr_a(name) ); - NtClose( *mapping ); + NtClose( mapping ); return STATUS_IMAGE_ALREADY_LOADED; } + status = virtual_map_builtin_module( mapping, module ); + NtClose( mapping ); return status; } @@ -1353,14 +1289,14 @@ static NTSTATUS open_dll_file( const char *name, OBJECT_ATTRIBUTES *attr, HANDLE /*********************************************************************** * open_builtin_file */ -static NTSTATUS open_builtin_file( char *name, OBJECT_ATTRIBUTES *attr, HANDLE *mapping, void **module, - SECTION_IMAGE_INFORMATION *image_info, struct stat *st, - BOOL prefer_native ) +static NTSTATUS open_builtin_file( char *name, OBJECT_ATTRIBUTES *attr, void **module, + SECTION_IMAGE_INFORMATION *image_info, BOOL prefer_native ) { NTSTATUS status; int fd; - status = open_dll_file( name, attr, mapping, module, image_info, st, prefer_native ); + *module = NULL; + status = open_dll_file( name, attr, module, image_info, prefer_native ); if (status != STATUS_DLL_NOT_FOUND) return status; /* try .so file */ @@ -1387,28 +1323,6 @@ static NTSTATUS open_builtin_file( char *name, OBJECT_ATTRIBUTES *attr, HANDLE * } -/*********************************************************************** - * 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 */ @@ -1421,8 +1335,6 @@ static NTSTATUS CDECL load_builtin_dll( UNICODE_STRING *nt_name, void **module, OBJECT_ATTRIBUTES attr; NTSTATUS status = STATUS_DLL_NOT_FOUND; BOOL found_image = FALSE; - HANDLE mapping; - struct stat st; for (i = namepos = 0; i < len; i++) if (nt_name->Buffer[i] == '/' || nt_name->Buffer[i] == '\\') namepos = i + 1; @@ -1456,7 +1368,7 @@ static NTSTATUS CDECL load_builtin_dll( UNICODE_STRING *nt_name, void **module, ptr = prepend( ptr, ptr, namelen ); ptr = prepend( ptr, "/dlls", sizeof("/dlls") - 1 ); ptr = prepend( ptr, build_dir, strlen(build_dir) ); - status = open_builtin_file( ptr, &attr, &mapping, module, image_info, &st, prefer_native ); + status = open_builtin_file( ptr, &attr, module, image_info, prefer_native ); if (status != STATUS_DLL_NOT_FOUND) goto done; /* now as a program */ @@ -1467,7 +1379,7 @@ static NTSTATUS CDECL load_builtin_dll( UNICODE_STRING *nt_name, void **module, ptr = prepend( ptr, ptr, namelen ); ptr = prepend( ptr, "/programs", sizeof("/programs") - 1 ); ptr = prepend( ptr, build_dir, strlen(build_dir) ); - status = open_builtin_file( ptr, &attr, &mapping, module, image_info, &st, prefer_native ); + status = open_builtin_file( ptr, &attr, module, image_info, prefer_native ); if (status != STATUS_DLL_NOT_FOUND) goto done; } @@ -1475,7 +1387,7 @@ static NTSTATUS CDECL load_builtin_dll( UNICODE_STRING *nt_name, void **module, { file[pos + len + 1] = 0; ptr = prepend( file + pos, dll_paths[i], strlen(dll_paths[i]) ); - status = open_builtin_file( ptr, &attr, &mapping, module, image_info, &st, prefer_native ); + status = open_builtin_file( ptr, &attr, module, image_info, prefer_native ); if (status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) found_image = TRUE; else if (status != STATUS_DLL_NOT_FOUND) goto done; } @@ -1484,11 +1396,7 @@ static NTSTATUS CDECL load_builtin_dll( UNICODE_STRING *nt_name, void **module, WARN( "cannot find builtin library for %s\n", debugstr_us(nt_name) ); done: - if (!status && !*module) - { - status = map_builtin_module( mapping, module, &st ); - NtClose( mapping ); - } + if (status == STATUS_IMAGE_NOT_AT_BASE) status = STATUS_SUCCESS; if (!status && ext) { strcpy( ext, ".so" ); @@ -1499,26 +1407,6 @@ done: } -/*********************************************************************** - * unload_builtin_dll - */ -static NTSTATUS CDECL unload_builtin_dll( void *module ) -{ - struct builtin_module *builtin; - - LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) - { - if (builtin->module != module) continue; - list_remove( &builtin->entry ); - if (builtin->handle) dlclose( builtin->handle ); - if (builtin->unix_handle) dlclose( builtin->unix_handle ); - free( builtin ); - return STATUS_SUCCESS; - } - return STATUS_INVALID_PARAMETER; -} - - #ifdef __FreeBSD__ /* The PT_LOAD segments are sorted in increasing order, and the first * starts at the beginning of the ELF file. By parsing the file, we can @@ -1555,7 +1443,7 @@ static BOOL get_relocbase(caddr_t mapbase, caddr_t *relocbase) static void CDECL init_builtin_dll( void *module ) { #ifdef HAVE_DLINFO - struct builtin_module *builtin; + void *handle = NULL; struct link_map *map; void (*init_func)(int, char **, char **) = NULL; void (**init_array)(int, char **, char **) = NULL; @@ -1566,16 +1454,9 @@ static void CDECL init_builtin_dll( void *module ) const Elf32_Dyn *dyn; #endif - LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) - { - if (builtin->module != module) continue; - if (!builtin->handle) break; - if (!dlinfo( builtin->handle, RTLD_DI_LINKMAP, &map )) goto found; - break; - } - return; + if (!(handle = get_builtin_so_handle( module ))) return; + if (dlinfo( handle, RTLD_DI_LINKMAP, &map )) return; -found: for (dyn = map->l_ld; dyn->d_tag; dyn++) { caddr_t relocbase = (caddr_t)map->l_addr; @@ -1615,24 +1496,15 @@ static void load_ntdll(void) SECTION_IMAGE_INFORMATION info; OBJECT_ATTRIBUTES attr; UNICODE_STRING str; - HANDLE mapping; - struct stat st; void *module; char *name = build_path( dll_dir, "ntdll.dll.so" ); init_unicode_string( &str, path ); InitializeObjectAttributes( &attr, &str, 0, 0, NULL ); name[strlen(name) - 3] = 0; /* remove .so */ - status = open_builtin_file( name, &attr, &mapping, &module, &info, &st, FALSE ); - if (!status && !module) - { - SIZE_T len = 0; - status = NtMapViewOfSection( mapping, NtCurrentProcess(), &module, 0, 0, NULL, &len, - ViewShare, 0, PAGE_EXECUTE_READ ); - if (status == STATUS_IMAGE_NOT_AT_BASE) relocate_ntdll( module ); - status = add_builtin_module( module, NULL, &st ); - } - if (status) fatal_error( "failed to load %s error %x\n", name, status ); + status = open_builtin_file( name, &attr, &module, &info, FALSE ); + if (status == STATUS_IMAGE_NOT_AT_BASE) relocate_ntdll( module ); + else if (status) fatal_error( "failed to load %s error %x\n", name, status ); free( name ); load_ntdll_functions( module ); ntdll_module = module; @@ -1718,7 +1590,6 @@ static struct unix_funcs unix_funcs = virtual_release_address_space, load_so_dll, load_builtin_dll, - unload_builtin_dll, init_builtin_dll, unwind_builtin_dll, __wine_dbg_get_channel_flags, diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index b8b6619c0a9..a8917f11c08 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -173,8 +173,9 @@ extern void *anon_mmap_alloc( size_t size, int prot ) DECLSPEC_HIDDEN; extern void virtual_init(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 NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_create_builtin_view( void *module, const UNICODE_STRING *nt_name, - pe_image_info_t *info ) DECLSPEC_HIDDEN; + pe_image_info_t *info, void *so_handle ) DECLSPEC_HIDDEN; extern TEB *virtual_alloc_first_teb(void) DECLSPEC_HIDDEN; extern NTSTATUS virtual_alloc_teb( TEB **ret_teb ) DECLSPEC_HIDDEN; extern void virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN; @@ -196,6 +197,8 @@ extern void virtual_set_force_exec( BOOL enable ) DECLSPEC_HIDDEN; extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN; extern void virtual_fill_image_information( const pe_image_info_t *pe_info, SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN; +extern void *get_builtin_so_handle( void *module ) DECLSPEC_HIDDEN; +extern NTSTATUS set_builtin_unix_handle( void *module, void *unix_handle ) DECLSPEC_HIDDEN; extern NTSTATUS get_thread_ldt_entry( HANDLE handle, void *data, ULONG len, ULONG *ret_len ) DECLSPEC_HIDDEN; extern BOOL get_thread_times( int unix_pid, int unix_tid, LARGE_INTEGER *kernel_time, diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index ab5f8ad52df..ebe14321289 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -83,6 +83,18 @@ struct reserved_area static struct list reserved_areas = LIST_INIT(reserved_areas); +struct builtin_module +{ + struct list entry; + dev_t dev; + ino_t ino; + void *handle; + void *module; + void *unix_handle; +}; + +static struct list builtin_modules = LIST_INIT( builtin_modules ); + struct file_view { struct wine_rb_entry entry; /* entry in global view tree */ @@ -547,6 +559,116 @@ static void mmap_init( const struct preload_info *preload_info ) #endif } +/*********************************************************************** + * add_builtin_module + */ +static void add_builtin_module( void *module, void *handle, const struct stat *st ) +{ + struct builtin_module *builtin; + + if (!(builtin = malloc( sizeof(*builtin) ))) return; + builtin->handle = handle; + builtin->module = module; + builtin->unix_handle = NULL; + if (st) + { + builtin->dev = st->st_dev; + builtin->ino = st->st_ino; + } + else + { + builtin->dev = 0; + builtin->ino = 0; + } + list_add_tail( &builtin_modules, &builtin->entry ); +} + + +/*********************************************************************** + * remove_builtin_module + */ +static NTSTATUS remove_builtin_module( void *module ) +{ + struct builtin_module *builtin; + + LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) + { + if (builtin->module != module) continue; + list_remove( &builtin->entry ); + if (builtin->handle) dlclose( builtin->handle ); + if (builtin->unix_handle) dlclose( builtin->unix_handle ); + free( builtin ); + return STATUS_SUCCESS; + } + return STATUS_INVALID_PARAMETER; +} + + +/*********************************************************************** + * find_builtin_module + */ +static void *find_builtin_module( const struct stat *st ) +{ + struct builtin_module *builtin; + + LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) + if (builtin->dev == st->st_dev && builtin->ino == st->st_ino) return builtin->module; + return NULL; +} + + +/*********************************************************************** + * get_builtin_so_handle + */ +void *get_builtin_so_handle( void *module ) +{ + sigset_t sigset; + void *ret = NULL; + struct builtin_module *builtin; + + server_enter_uninterrupted_section( &virtual_mutex, &sigset ); + LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) + { + if (builtin->module != module) continue; + ret = builtin->handle; + break; + } + server_leave_uninterrupted_section( &virtual_mutex, &sigset ); + return ret; +} + + +/*********************************************************************** + * set_builtin_unix_handle + */ +NTSTATUS set_builtin_unix_handle( void *module, void *handle ) +{ + sigset_t sigset; + NTSTATUS status = STATUS_DLL_NOT_FOUND; + struct builtin_module *builtin; + + server_enter_uninterrupted_section( &virtual_mutex, &sigset ); + LIST_FOR_EACH_ENTRY( builtin, &builtin_modules, struct builtin_module, entry ) + { + if (builtin->module == module) + { + if (builtin->unix_handle == handle) status = STATUS_IMAGE_ALREADY_LOADED; + else if (builtin->unix_handle) status = STATUS_OBJECT_NAME_COLLISION; + else status = STATUS_SUCCESS; + break; + } + if (builtin->unix_handle == handle) + { + status = STATUS_DUPLICATE_NAME; + break; + } + } + if (!status) builtin->unix_handle = handle; + server_leave_uninterrupted_section( &virtual_mutex, &sigset ); + return status; +} + + /*********************************************************************** * free_ranges_lower_bound * @@ -2248,12 +2370,13 @@ static NTSTATUS get_mapping_info( HANDLE handle, ACCESS_MASK access, unsigned in */ static NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned short zero_bits_64, SIZE_T commit_size, const LARGE_INTEGER *offset_ptr, SIZE_T *size_ptr, - ULONG alloc_type, ULONG protect ) + ULONG alloc_type, ULONG protect, BOOL is_builtin ) { NTSTATUS res; mem_size_t full_size; ACCESS_MASK access; SIZE_T size; + struct stat st; pe_image_info_t *image_info = NULL; WCHAR *filename; void *base; @@ -2312,6 +2435,18 @@ static NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned sh res = STATUS_INVALID_PARAMETER; server_enter_uninterrupted_section( &virtual_mutex, &sigset ); + if (is_builtin) /* check for already loaded builtin */ + { + fstat( unix_handle, &st ); + if ((base = find_builtin_module( &st ))) + { + *addr_ptr = base; + *size_ptr = image_info->map_size; + res = STATUS_SUCCESS; + goto done; + } + } + if (sec_flags & SEC_IMAGE) { base = wine_server_get_ptr( image_info->base ); @@ -2381,6 +2516,7 @@ static NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, unsigned sh if (res >= 0) { + if (is_builtin) add_builtin_module( view->base, NULL, &st ); *addr_ptr = view->base; *size_ptr = size; VIRTUAL_DEBUG_DUMP_VIEW( view ); @@ -2525,10 +2661,23 @@ void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) } +/*********************************************************************** + * virtual_map_builtin_module + */ +NTSTATUS virtual_map_builtin_module( HANDLE mapping, void **module ) +{ + SIZE_T size = 0; + + *module = NULL; + return virtual_map_section( mapping, module, 0, 0, NULL, &size, 0, PAGE_EXECUTE_READ, TRUE ); +} + + /*********************************************************************** * virtual_create_builtin_view */ -NTSTATUS virtual_create_builtin_view( void *module, const UNICODE_STRING *nt_name, pe_image_info_t *info ) +NTSTATUS virtual_create_builtin_view( void *module, const UNICODE_STRING *nt_name, + pe_image_info_t *info, void *so_handle ) { NTSTATUS status; sigset_t sigset; @@ -2573,6 +2722,7 @@ NTSTATUS virtual_create_builtin_view( void *module, const UNICODE_STRING *nt_nam if (status >= 0) { + add_builtin_module( view->base, so_handle, NULL ); VIRTUAL_DEBUG_DUMP_VIEW( view ); if (is_beyond_limit( base, size, working_set_limit )) working_set_limit = address_space_limit; } @@ -4115,7 +4265,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p } return virtual_map_section( handle, addr_ptr, zero_bits_64, commit_size, - offset_ptr, size_ptr, alloc_type, protect ); + offset_ptr, size_ptr, alloc_type, protect, FALSE ); } @@ -4152,7 +4302,11 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr ) status = wine_server_call( req ); } SERVER_END_REQ; - if (!status) delete_view( view ); + if (!status) + { + if (view->protect & SEC_IMAGE) remove_builtin_module( view->base ); + delete_view( view ); + } else FIXME( "failed to unmap %p %x\n", view->base, status ); } server_leave_uninterrupted_section( &virtual_mutex, &sigset ); diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h index 290379a9310..390f148b007 100644 --- a/dlls/ntdll/unixlib.h +++ b/dlls/ntdll/unixlib.h @@ -26,7 +26,7 @@ struct _DISPATCHER_CONTEXT; /* increment this when you change the function table */ -#define NTDLL_UNIXLIB_VERSION 115 +#define NTDLL_UNIXLIB_VERSION 116 struct unix_funcs { @@ -76,7 +76,6 @@ struct unix_funcs NTSTATUS (CDECL *load_so_dll)( UNICODE_STRING *nt_name, void **module ); NTSTATUS (CDECL *load_builtin_dll)( UNICODE_STRING *name, void **module, void **unix_entry, SECTION_IMAGE_INFORMATION *image_info, BOOL prefer_native ); - NTSTATUS (CDECL *unload_builtin_dll)( void *module ); void (CDECL *init_builtin_dll)( void *module ); NTSTATUS (CDECL *unwind_builtin_dll)( ULONG type, struct _DISPATCHER_CONTEXT *dispatch, CONTEXT *context );