diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 2ad3cfb561c..64a8b8e921a 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -934,7 +934,7 @@ static int do_relocations( char *base, const IMAGE_DATA_DIRECTORY *dir, * Map an executable (PE format) image into memory. */ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_size, SIZE_T mask, - SIZE_T header_size, int shared_fd, BOOL removable, PVOID *addr_ptr ) + SIZE_T header_size, int shared_fd, HANDLE dup_mapping, PVOID *addr_ptr ) { IMAGE_DOS_HEADER *dos; IMAGE_NT_HEADERS *nt; @@ -975,7 +975,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz if (!st.st_size) goto error; header_size = min( header_size, st.st_size ); if (map_file_into_view( view, fd, 0, header_size, 0, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY, - removable ) != STATUS_SUCCESS) goto error; + !dup_mapping ) != STATUS_SUCCESS) goto error; dos = (IMAGE_DOS_HEADER *)ptr; nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew); header_end = ptr + ROUND_SIZE( 0, header_size ); @@ -1019,7 +1019,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz /* in that case Windows simply maps in the whole file */ if (map_file_into_view( view, fd, 0, total_size, 0, VPROT_COMMITTED | VPROT_READ, - removable ) != STATUS_SUCCESS) goto error; + !dup_mapping ) != STATUS_SUCCESS) goto error; /* check that all sections are loaded at the right offset */ if (nt->OptionalHeader.FileAlignment != nt->OptionalHeader.SectionAlignment) goto error; @@ -1121,7 +1121,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz end < file_start || map_file_into_view( view, fd, sec->VirtualAddress, file_size, file_start, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY, - removable ) != STATUS_SUCCESS) + !dup_mapping ) != STATUS_SUCCESS) { ERR_(module)( "Could not map section %.8s, file probably truncated\n", sec->Name ); goto error; @@ -1195,11 +1195,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz } done: - if (!removable) /* don't keep handle open on removable media */ - NtDuplicateObject( NtCurrentProcess(), hmapping, - NtCurrentProcess(), &view->mapping, - 0, 0, DUPLICATE_SAME_ACCESS ); - + view->mapping = dup_mapping; RtlLeaveCriticalSection( &csVirtual ); *addr_ptr = ptr; @@ -1208,6 +1204,7 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz error: if (view) delete_view( view ); RtlLeaveCriticalSection( &csVirtual ); + if (dup_mapping) NtClose( dup_mapping ); return status; } @@ -1837,13 +1834,12 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p NTSTATUS res; SIZE_T size = 0; SIZE_T mask = get_mask( zero_bits ); - int unix_handle = -1, flags, needs_close; + int unix_handle = -1, needs_close; int prot; void *base; struct file_view *view; DWORD size_low, size_high, header_size, shared_size; - HANDLE shared_file; - BOOL removable = FALSE; + HANDLE dup_mapping, shared_file; LARGE_INTEGER offset; offset.QuadPart = offset_ptr ? offset_ptr->QuadPart : 0; @@ -1871,14 +1867,14 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p size_low = reply->size_low; size_high = reply->size_high; header_size = reply->header_size; + dup_mapping = reply->mapping; shared_file = reply->shared_file; shared_size = reply->shared_size; } SERVER_END_REQ; if (res) return res; - if ((res = server_get_unix_fd( handle, 0, &unix_handle, &needs_close, NULL, &flags ))) return res; - removable = (flags & FD_FLAG_REMOVABLE) != 0; + if ((res = server_get_unix_fd( handle, 0, &unix_handle, &needs_close, NULL, NULL ))) goto done; if (prot & VPROT_IMAGE) { @@ -1889,14 +1885,14 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p if ((res = server_get_unix_fd( shared_file, FILE_READ_DATA|FILE_WRITE_DATA, &shared_fd, &shared_needs_close, NULL, NULL ))) goto done; res = map_image( handle, unix_handle, base, size_low, mask, header_size, - shared_fd, removable, addr_ptr ); + shared_fd, dup_mapping, addr_ptr ); if (shared_needs_close) close( shared_fd ); NtClose( shared_file ); } else { res = map_image( handle, unix_handle, base, size_low, mask, header_size, - -1, removable, addr_ptr ); + -1, dup_mapping, addr_ptr ); } if (needs_close) close( unix_handle ); if (!res) *size_ptr = size_low; @@ -1926,7 +1922,6 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p res = STATUS_INVALID_PARAMETER; goto done; } - removable = FALSE; /* fall through */ case PAGE_READONLY: case PAGE_WRITECOPY: @@ -1964,16 +1959,13 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p TRACE("handle=%p size=%lx offset=%x%08x\n", handle, size, offset.u.HighPart, offset.u.LowPart ); - res = map_file_into_view( view, unix_handle, 0, size, offset.QuadPart, prot, removable ); + res = map_file_into_view( view, unix_handle, 0, size, offset.QuadPart, prot, !dup_mapping ); if (res == STATUS_SUCCESS) { - if (!removable) /* don't keep handle open on removable media */ - NtDuplicateObject( NtCurrentProcess(), handle, - NtCurrentProcess(), &view->mapping, - 0, 0, DUPLICATE_SAME_ACCESS ); - *addr_ptr = view->base; *size_ptr = size; + view->mapping = dup_mapping; + dup_mapping = 0; /* don't close it */ } else { @@ -1985,6 +1977,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p RtlLeaveCriticalSection( &csVirtual ); done: + if (dup_mapping) NtClose( dup_mapping ); if (needs_close) close( unix_handle ); return res; } diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index ce55bf03998..03969ffa344 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1535,6 +1535,7 @@ struct get_mapping_info_reply int protect; int header_size; void* base; + obj_handle_t mapping; obj_handle_t shared_file; int shared_size; }; @@ -4436,6 +4437,6 @@ union generic_reply struct query_symlink_reply query_symlink_reply; }; -#define SERVER_PROTOCOL_VERSION 263 +#define SERVER_PROTOCOL_VERSION 264 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/mapping.c b/server/mapping.c index fe99879ebd7..9b123e2cbcb 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -432,6 +432,7 @@ DECL_HANDLER(open_mapping) DECL_HANDLER(get_mapping_info) { struct mapping *mapping; + struct fd *fd; if ((mapping = (struct mapping *)get_handle_obj( current->process, req->handle, 0, &mapping_ops ))) @@ -443,9 +444,20 @@ DECL_HANDLER(get_mapping_info) reply->base = mapping->base; reply->shared_file = 0; reply->shared_size = mapping->shared_size; + if ((fd = get_obj_fd( &mapping->obj ))) + { + if (!is_fd_removable(fd)) + reply->mapping = alloc_handle( current->process, mapping, 0, 0 ); + release_object( fd ); + } if (mapping->shared_file) - reply->shared_file = alloc_handle( current->process, mapping->shared_file, - GENERIC_READ|GENERIC_WRITE, 0 ); + { + if (!(reply->shared_file = alloc_handle( current->process, mapping->shared_file, + GENERIC_READ|GENERIC_WRITE, 0 ))) + { + if (reply->mapping) close_handle( current->process, reply->mapping ); + } + } release_object( mapping ); } } diff --git a/server/protocol.def b/server/protocol.def index a71bceebaa9..3f7fbd5a8a9 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1159,6 +1159,7 @@ enum char_info_mode int protect; /* protection flags */ int header_size; /* header size (for VPROT_IMAGE mapping) */ void* base; /* default base addr (for VPROT_IMAGE mapping) */ + obj_handle_t mapping; /* duplicate mapping handle unless removable */ obj_handle_t shared_file; /* shared mapping file handle */ int shared_size; /* shared mapping size */ @END diff --git a/server/trace.c b/server/trace.c index 1770a6d6d74..5defbda3b72 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1570,6 +1570,7 @@ static void dump_get_mapping_info_reply( const struct get_mapping_info_reply *re fprintf( stderr, " protect=%d,", req->protect ); fprintf( stderr, " header_size=%d,", req->header_size ); fprintf( stderr, " base=%p,", req->base ); + fprintf( stderr, " mapping=%p,", req->mapping ); fprintf( stderr, " shared_file=%p,", req->shared_file ); fprintf( stderr, " shared_size=%d", req->shared_size ); } @@ -3966,6 +3967,7 @@ static const struct { "FILE_LOCK_CONFLICT", STATUS_FILE_LOCK_CONFLICT }, { "HANDLES_CLOSED", STATUS_HANDLES_CLOSED }, { "HANDLE_NOT_CLOSABLE", STATUS_HANDLE_NOT_CLOSABLE }, + { "ILLEGAL_FUNCTION", STATUS_ILLEGAL_FUNCTION }, { "INSTANCE_NOT_AVAILABLE", STATUS_INSTANCE_NOT_AVAILABLE }, { "INVALID_CID", STATUS_INVALID_CID }, { "INVALID_FILE_FOR_SECTION", STATUS_INVALID_FILE_FOR_SECTION },