server: Keep track of mapped memory views.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
d82321006d
commit
a557934c76
|
@ -1329,8 +1329,8 @@ static NTSTATUS stat_mapping_file( struct file_view *view, struct stat *st )
|
|||
*
|
||||
* 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, HANDLE dup_mapping, PVOID *addr_ptr )
|
||||
static NTSTATUS map_image( HANDLE hmapping, ACCESS_MASK access, int fd, char *base, SIZE_T total_size,
|
||||
SIZE_T mask, SIZE_T header_size, int shared_fd, HANDLE dup_mapping, PVOID *addr_ptr )
|
||||
{
|
||||
IMAGE_DOS_HEADER *dos;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
|
@ -1537,6 +1537,19 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
|
|||
|
||||
done:
|
||||
view->mapping = dup_mapping;
|
||||
|
||||
SERVER_START_REQ( map_view )
|
||||
{
|
||||
req->mapping = wine_server_obj_handle( hmapping );
|
||||
req->access = access;
|
||||
req->base = wine_server_client_ptr( view->base );
|
||||
req->size = view->size;
|
||||
req->start = 0;
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (status) goto error;
|
||||
|
||||
VIRTUAL_DEBUG_DUMP_VIEW( view );
|
||||
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||
|
||||
|
@ -2930,14 +2943,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, mask, image_info.header_size,
|
||||
res = map_image( handle, access, unix_handle, base, size, mask, image_info.header_size,
|
||||
shared_fd, dup_mapping, addr_ptr );
|
||||
if (shared_needs_close) close( shared_fd );
|
||||
close_handle( shared_file );
|
||||
}
|
||||
else
|
||||
{
|
||||
res = map_image( handle, unix_handle, base, size, mask, image_info.header_size,
|
||||
res = map_image( handle, access, unix_handle, base, size, mask, image_info.header_size,
|
||||
-1, dup_mapping, addr_ptr );
|
||||
}
|
||||
if (needs_close) close( unix_handle );
|
||||
|
@ -2988,6 +3001,20 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
|
|||
handle, size, offset.u.HighPart, offset.u.LowPart );
|
||||
|
||||
res = map_file_into_view( view, unix_handle, 0, size, offset.QuadPart, vprot, !dup_mapping );
|
||||
if (res == STATUS_SUCCESS)
|
||||
{
|
||||
SERVER_START_REQ( map_view )
|
||||
{
|
||||
req->mapping = wine_server_obj_handle( handle );
|
||||
req->access = access;
|
||||
req->base = wine_server_client_ptr( view->base );
|
||||
req->size = size;
|
||||
req->start = offset.QuadPart;
|
||||
res = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
}
|
||||
|
||||
if (res == STATUS_SUCCESS)
|
||||
{
|
||||
*addr_ptr = view->base;
|
||||
|
@ -3039,8 +3066,13 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HANDLE process, PVOID addr )
|
|||
server_enter_uninterrupted_section( &csVirtual, &sigset );
|
||||
if ((view = VIRTUAL_FindView( addr, 0 )) && !is_view_valloc( view ))
|
||||
{
|
||||
delete_view( view );
|
||||
status = STATUS_SUCCESS;
|
||||
SERVER_START_REQ( unmap_view )
|
||||
{
|
||||
req->base = wine_server_client_ptr( view->base );
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!status) delete_view( view );
|
||||
}
|
||||
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||
return status;
|
||||
|
|
|
@ -2228,6 +2228,36 @@ struct get_mapping_info_reply
|
|||
|
||||
|
||||
|
||||
struct map_view_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t mapping;
|
||||
unsigned int access;
|
||||
char __pad_20[4];
|
||||
client_ptr_t base;
|
||||
mem_size_t size;
|
||||
file_pos_t start;
|
||||
};
|
||||
struct map_view_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct unmap_view_request
|
||||
{
|
||||
struct request_header __header;
|
||||
char __pad_12[4];
|
||||
client_ptr_t base;
|
||||
};
|
||||
struct unmap_view_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct get_mapping_committed_range_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -5626,6 +5656,8 @@ enum request
|
|||
REQ_create_mapping,
|
||||
REQ_open_mapping,
|
||||
REQ_get_mapping_info,
|
||||
REQ_map_view,
|
||||
REQ_unmap_view,
|
||||
REQ_get_mapping_committed_range,
|
||||
REQ_add_mapping_committed_range,
|
||||
REQ_create_snapshot,
|
||||
|
@ -5917,6 +5949,8 @@ union generic_request
|
|||
struct create_mapping_request create_mapping_request;
|
||||
struct open_mapping_request open_mapping_request;
|
||||
struct get_mapping_info_request get_mapping_info_request;
|
||||
struct map_view_request map_view_request;
|
||||
struct unmap_view_request unmap_view_request;
|
||||
struct get_mapping_committed_range_request get_mapping_committed_range_request;
|
||||
struct add_mapping_committed_range_request add_mapping_committed_range_request;
|
||||
struct create_snapshot_request create_snapshot_request;
|
||||
|
@ -6206,6 +6240,8 @@ union generic_reply
|
|||
struct create_mapping_reply create_mapping_reply;
|
||||
struct open_mapping_reply open_mapping_reply;
|
||||
struct get_mapping_info_reply get_mapping_info_reply;
|
||||
struct map_view_reply map_view_reply;
|
||||
struct unmap_view_reply unmap_view_reply;
|
||||
struct get_mapping_committed_range_reply get_mapping_committed_range_reply;
|
||||
struct add_mapping_committed_range_reply add_mapping_committed_range_reply;
|
||||
struct create_snapshot_reply create_snapshot_reply;
|
||||
|
@ -6408,6 +6444,6 @@ union generic_reply
|
|||
struct terminate_job_reply terminate_job_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 537
|
||||
#define SERVER_PROTOCOL_VERSION 538
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -150,6 +150,7 @@ extern struct mapping *get_mapping_obj( struct process *process, obj_handle_t ha
|
|||
extern obj_handle_t open_mapping_file( struct process *process, struct mapping *mapping,
|
||||
unsigned int access, unsigned int sharing );
|
||||
extern struct mapping *grab_mapping_unless_removable( struct mapping *mapping );
|
||||
extern void free_mapped_views( struct process *process );
|
||||
extern int get_page_size(void);
|
||||
|
||||
/* device functions */
|
||||
|
|
|
@ -55,6 +55,16 @@ struct ranges
|
|||
} ranges[1];
|
||||
};
|
||||
|
||||
/* memory view mapped in client address space */
|
||||
struct memory_view
|
||||
{
|
||||
struct list entry; /* entry in per-process view list */
|
||||
unsigned int flags; /* SEC_* flags */
|
||||
client_ptr_t base; /* view base address (in process addr space) */
|
||||
mem_size_t size; /* view size */
|
||||
file_pos_t start; /* start offset in mapping */
|
||||
};
|
||||
|
||||
struct mapping
|
||||
{
|
||||
struct object obj; /* object header */
|
||||
|
@ -196,6 +206,33 @@ static int create_temp_file( file_pos_t size )
|
|||
return fd;
|
||||
}
|
||||
|
||||
/* find a memory view from its base address */
|
||||
static struct memory_view *find_mapped_view( struct process *process, client_ptr_t base )
|
||||
{
|
||||
struct memory_view *view;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( view, &process->views, struct memory_view, entry )
|
||||
if (view->base == base) return view;
|
||||
|
||||
set_error( STATUS_NOT_MAPPED_VIEW );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void free_memory_view( struct memory_view *view )
|
||||
{
|
||||
list_remove( &view->entry );
|
||||
free( view );
|
||||
}
|
||||
|
||||
/* free all mapped views at process exit */
|
||||
void free_mapped_views( struct process *process )
|
||||
{
|
||||
struct list *ptr;
|
||||
|
||||
while ((ptr = list_head( &process->views )))
|
||||
free_memory_view( LIST_ENTRY( ptr, struct memory_view, entry ));
|
||||
}
|
||||
|
||||
/* find the shared PE mapping for a given mapping */
|
||||
static struct file *get_shared_file( struct mapping *mapping )
|
||||
{
|
||||
|
@ -776,6 +813,66 @@ DECL_HANDLER(get_mapping_info)
|
|||
release_object( mapping );
|
||||
}
|
||||
|
||||
/* add a memory view in the current process */
|
||||
DECL_HANDLER(map_view)
|
||||
{
|
||||
struct mapping *mapping = NULL;
|
||||
struct memory_view *view;
|
||||
|
||||
if (!req->size || (req->base & page_mask) || req->base + req->size < req->base) /* overflow */
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
|
||||
/* make sure we don't already have an overlapping view */
|
||||
LIST_FOR_EACH_ENTRY( view, ¤t->process->views, struct memory_view, entry )
|
||||
{
|
||||
if (view->base + view->size <= req->base) continue;
|
||||
if (view->base >= req->base + req->size) continue;
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(mapping = get_mapping_obj( current->process, req->mapping, req->access ))) return;
|
||||
|
||||
if (mapping->flags & SEC_IMAGE)
|
||||
{
|
||||
if (req->start || req->size > mapping->image.map_size)
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else if (req->start >= mapping->size ||
|
||||
req->start + req->size < req->start ||
|
||||
req->start + req->size > ((mapping->size + page_mask) & ~(mem_size_t)page_mask))
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((view = mem_alloc( sizeof(*view) )))
|
||||
{
|
||||
view->base = req->base;
|
||||
view->size = req->size;
|
||||
view->start = req->start;
|
||||
view->flags = mapping->flags;
|
||||
list_add_tail( ¤t->process->views, &view->entry );
|
||||
}
|
||||
|
||||
done:
|
||||
release_object( mapping );
|
||||
}
|
||||
|
||||
/* unmap a memory view from the current process */
|
||||
DECL_HANDLER(unmap_view)
|
||||
{
|
||||
struct memory_view *view = find_mapped_view( current->process, req->base );
|
||||
|
||||
if (view) free_memory_view( view );
|
||||
}
|
||||
|
||||
/* get a range of committed pages in a file mapping */
|
||||
DECL_HANDLER(get_mapping_committed_range)
|
||||
{
|
||||
|
|
|
@ -537,6 +537,7 @@ struct thread *create_process( int fd, struct thread *parent_thread, int inherit
|
|||
list_init( &process->locks );
|
||||
list_init( &process->asyncs );
|
||||
list_init( &process->classes );
|
||||
list_init( &process->views );
|
||||
list_init( &process->dlls );
|
||||
list_init( &process->rawinput_devices );
|
||||
|
||||
|
@ -871,6 +872,7 @@ static void process_killed( struct process *process )
|
|||
free( dll );
|
||||
}
|
||||
destroy_process_classes( process );
|
||||
free_mapped_views( process );
|
||||
free_process_user_handles( process );
|
||||
remove_process_locks( process );
|
||||
set_process_startup_state( process, STARTUP_ABORTED );
|
||||
|
|
|
@ -88,6 +88,7 @@ struct process
|
|||
obj_handle_t winstation; /* main handle to process window station */
|
||||
obj_handle_t desktop; /* handle to desktop to use for new threads */
|
||||
struct token *token; /* security token associated with this process */
|
||||
struct list views; /* list of memory views */
|
||||
struct list dlls; /* list of loaded dlls */
|
||||
client_ptr_t peb; /* PEB address in client address space */
|
||||
client_ptr_t ldt_copy; /* pointer to LDT copy in client addr space */
|
||||
|
|
|
@ -1726,6 +1726,22 @@ enum char_info_mode
|
|||
@END
|
||||
|
||||
|
||||
/* Add a memory view in the current process */
|
||||
@REQ(map_view)
|
||||
obj_handle_t mapping; /* file mapping handle */
|
||||
unsigned int access; /* wanted access rights */
|
||||
client_ptr_t base; /* view base address (page-aligned) */
|
||||
mem_size_t size; /* view size */
|
||||
file_pos_t start; /* start offset in mapping */
|
||||
@END
|
||||
|
||||
|
||||
/* Unmap a memory view from the current process */
|
||||
@REQ(unmap_view)
|
||||
client_ptr_t base; /* view base address */
|
||||
@END
|
||||
|
||||
|
||||
/* Get a range of committed pages in a file mapping */
|
||||
@REQ(get_mapping_committed_range)
|
||||
obj_handle_t handle; /* handle to the mapping */
|
||||
|
|
|
@ -196,6 +196,8 @@ DECL_HANDLER(read_change);
|
|||
DECL_HANDLER(create_mapping);
|
||||
DECL_HANDLER(open_mapping);
|
||||
DECL_HANDLER(get_mapping_info);
|
||||
DECL_HANDLER(map_view);
|
||||
DECL_HANDLER(unmap_view);
|
||||
DECL_HANDLER(get_mapping_committed_range);
|
||||
DECL_HANDLER(add_mapping_committed_range);
|
||||
DECL_HANDLER(create_snapshot);
|
||||
|
@ -486,6 +488,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_create_mapping,
|
||||
(req_handler)req_open_mapping,
|
||||
(req_handler)req_get_mapping_info,
|
||||
(req_handler)req_map_view,
|
||||
(req_handler)req_unmap_view,
|
||||
(req_handler)req_get_mapping_committed_range,
|
||||
(req_handler)req_add_mapping_committed_range,
|
||||
(req_handler)req_create_snapshot,
|
||||
|
@ -1266,6 +1270,14 @@ C_ASSERT( FIELD_OFFSET(struct get_mapping_info_reply, flags) == 16 );
|
|||
C_ASSERT( FIELD_OFFSET(struct get_mapping_info_reply, mapping) == 20 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_mapping_info_reply, shared_file) == 24 );
|
||||
C_ASSERT( sizeof(struct get_mapping_info_reply) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct map_view_request, mapping) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct map_view_request, access) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct map_view_request, base) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct map_view_request, size) == 32 );
|
||||
C_ASSERT( FIELD_OFFSET(struct map_view_request, start) == 40 );
|
||||
C_ASSERT( sizeof(struct map_view_request) == 48 );
|
||||
C_ASSERT( FIELD_OFFSET(struct unmap_view_request, base) == 16 );
|
||||
C_ASSERT( sizeof(struct unmap_view_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_mapping_committed_range_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_mapping_committed_range_request, offset) == 16 );
|
||||
C_ASSERT( sizeof(struct get_mapping_committed_range_request) == 24 );
|
||||
|
|
|
@ -2243,6 +2243,20 @@ static void dump_get_mapping_info_reply( const struct get_mapping_info_reply *re
|
|||
dump_varargs_pe_image_info( ", image=", cur_size );
|
||||
}
|
||||
|
||||
static void dump_map_view_request( const struct map_view_request *req )
|
||||
{
|
||||
fprintf( stderr, " mapping=%04x", req->mapping );
|
||||
fprintf( stderr, ", access=%08x", req->access );
|
||||
dump_uint64( ", base=", &req->base );
|
||||
dump_uint64( ", size=", &req->size );
|
||||
dump_uint64( ", start=", &req->start );
|
||||
}
|
||||
|
||||
static void dump_unmap_view_request( const struct unmap_view_request *req )
|
||||
{
|
||||
dump_uint64( " base=", &req->base );
|
||||
}
|
||||
|
||||
static void dump_get_mapping_committed_range_request( const struct get_mapping_committed_range_request *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
|
@ -4553,6 +4567,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_create_mapping_request,
|
||||
(dump_func)dump_open_mapping_request,
|
||||
(dump_func)dump_get_mapping_info_request,
|
||||
(dump_func)dump_map_view_request,
|
||||
(dump_func)dump_unmap_view_request,
|
||||
(dump_func)dump_get_mapping_committed_range_request,
|
||||
(dump_func)dump_add_mapping_committed_range_request,
|
||||
(dump_func)dump_create_snapshot_request,
|
||||
|
@ -4840,6 +4856,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_create_mapping_reply,
|
||||
(dump_func)dump_open_mapping_reply,
|
||||
(dump_func)dump_get_mapping_info_reply,
|
||||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_get_mapping_committed_range_reply,
|
||||
NULL,
|
||||
(dump_func)dump_create_snapshot_reply,
|
||||
|
@ -5127,6 +5145,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"create_mapping",
|
||||
"open_mapping",
|
||||
"get_mapping_info",
|
||||
"map_view",
|
||||
"unmap_view",
|
||||
"get_mapping_committed_range",
|
||||
"add_mapping_committed_range",
|
||||
"create_snapshot",
|
||||
|
@ -5407,6 +5427,7 @@ static const struct
|
|||
{ "NOT_A_DIRECTORY", STATUS_NOT_A_DIRECTORY },
|
||||
{ "NOT_FOUND", STATUS_NOT_FOUND },
|
||||
{ "NOT_IMPLEMENTED", STATUS_NOT_IMPLEMENTED },
|
||||
{ "NOT_MAPPED_VIEW", STATUS_NOT_MAPPED_VIEW },
|
||||
{ "NOT_REGISTRY_FILE", STATUS_NOT_REGISTRY_FILE },
|
||||
{ "NOT_SUPPORTED", STATUS_NOT_SUPPORTED },
|
||||
{ "NO_DATA_DETECTED", STATUS_NO_DATA_DETECTED },
|
||||
|
|
Loading…
Reference in New Issue