Commit a8b8d9c0 authored by Alexandre Julliard's avatar Alexandre Julliard

Added server-side file mapping object support.

parent 56d236f0
......@@ -162,9 +162,8 @@ struct select_reply
int signaled; /* signaled handle */
};
#define SELECT_ALL 1
#define SELECT_MSG 2
#define SELECT_ALERTABLE 4
#define SELECT_TIMEOUT 8
#define SELECT_ALERTABLE 2
#define SELECT_TIMEOUT 4
/* Create an event */
......@@ -243,7 +242,7 @@ struct open_named_obj_request
int inherit; /* inherit flag */
char name[0]; /* object name */
};
enum open_named_obj { OPEN_EVENT, OPEN_MUTEX, OPEN_SEMAPHORE };
enum open_named_obj { OPEN_EVENT, OPEN_MUTEX, OPEN_SEMAPHORE, OPEN_MAPPING };
struct open_named_obj_reply
{
......@@ -263,14 +262,6 @@ struct create_file_reply
};
/* Get a Unix handle to a file */
struct get_unix_handle_request
{
int handle; /* handle to the file */
unsigned int access; /* desired access */
};
/* Get a Unix fd to read from a file */
struct get_read_fd_request
{
......@@ -364,7 +355,7 @@ struct set_console_fd_request
};
/* Create a console */
/* Create a change notification */
struct create_change_notification_request
{
int subtree; /* watch all the subtree */
......@@ -376,6 +367,42 @@ struct create_change_notification_reply
};
/* Create a file mapping */
struct create_mapping_request
{
int size_high; /* mapping size */
int size_low; /* mapping size */
int protect; /* protection flags (see below) */
int handle; /* file handle */
char name[0]; /* object name */
};
struct create_mapping_reply
{
int handle; /* handle to the mapping */
};
/* protection flags */
#define VPROT_READ 0x01
#define VPROT_WRITE 0x02
#define VPROT_EXEC 0x04
#define VPROT_WRITECOPY 0x08
#define VPROT_GUARD 0x10
#define VPROT_NOCACHE 0x20
#define VPROT_COMMITTED 0x40
/* Get information about a file mapping */
struct get_mapping_info_request
{
int handle; /* handle to the mapping */
};
struct get_mapping_info_reply
{
int size_high; /* mapping size */
int size_low; /* mapping size */
int protect; /* protection flags */
};
/* client-side functions */
#ifndef __WINE_SERVER__
......@@ -383,14 +410,11 @@ struct create_change_notification_reply
#include "server/request.h"
/* client communication functions */
#define CHECK_LEN(len,wanted) \
if ((len) == (wanted)) ; \
else CLIENT_ProtocolError( __FUNCTION__ ": len %d != %d\n", (len), (wanted) );
extern void CLIENT_ProtocolError( const char *err, ... );
extern void CLIENT_SendRequest( enum request req, int pass_fd,
int n, ... /* arg_1, len_1, etc. */ );
extern unsigned int CLIENT_WaitReply( int *len, int *passed_fd,
int n, ... /* arg_1, len_1, etc. */ );
extern unsigned int CLIENT_WaitSimpleReply( void *reply, int len, int *passed_fd );
struct _THDB;
extern int CLIENT_NewThread( struct _THDB *thdb, int *thandle, int *phandle );
......@@ -399,8 +423,6 @@ extern int CLIENT_InitThread(void);
extern int CLIENT_CloseHandle( int handle );
extern int CLIENT_DuplicateHandle( int src_process, int src_handle, int dst_process,
int dst_handle, DWORD access, BOOL32 inherit, DWORD options );
extern int CLIENT_GetThreadInfo( int handle, struct get_thread_info_reply *reply );
extern int CLIENT_GetProcessInfo( int handle, struct get_process_info_reply *reply );
extern int CLIENT_OpenProcess( void *pid, DWORD access, BOOL32 inherit );
extern int CLIENT_Select( int count, int *handles, int flags, int timeout );
#endif /* __WINE_SERVER__ */
......
......@@ -20,6 +20,7 @@
struct object;
struct object_name;
struct thread;
struct file;
struct wait_queue_entry;
struct object_ops
......@@ -27,7 +28,7 @@ struct object_ops
/* dump the object (for debugging) */
void (*dump)(struct object *,int);
/* add a thread to the object wait queue */
void (*add_queue)(struct object *,struct wait_queue_entry *);
int (*add_queue)(struct object *,struct wait_queue_entry *);
/* remove a thread from the object wait queue */
void (*remove_queue)(struct object *,struct wait_queue_entry *);
/* is object signaled? */
......@@ -63,6 +64,7 @@ extern int init_object( struct object *obj, const struct object_ops *ops,
extern struct object *grab_object( void *obj );
extern void release_object( void *obj );
extern struct object *find_object( const char *name );
extern int no_add_queue( struct object *obj, struct wait_queue_entry *entry );
extern int no_satisfied( struct object *obj, struct thread *thread );
extern int no_read_fd( struct object *obj );
extern int no_write_fd( struct object *obj );
......@@ -171,7 +173,9 @@ extern int release_semaphore( int handle, unsigned int count, unsigned int *prev
/* file functions */
extern struct object *create_file( int fd );
extern int file_get_unix_handle( int handle, unsigned int access );
extern struct file *get_file_obj( struct process *process, int handle,
unsigned int access );
extern int file_get_mmap_fd( struct file *file );
extern int set_file_pointer( int handle, int *low, int *high, int whence );
extern int truncate_file( int handle );
extern int get_file_info( int handle, struct get_file_info_reply *reply );
......@@ -194,6 +198,13 @@ extern int set_console_fd( int handle, int fd );
extern struct object *create_change_notification( int subtree, int filter );
/* file mapping functions */
extern struct object *create_mapping( int size_high, int size_low, int protect,
int handle, const char *name );
extern int open_mapping( unsigned int access, int inherit, const char *name );
extern int get_mapping_info( int handle, struct get_mapping_info_reply *reply );
extern int debug_level;
#endif /* __WINE_SERVER_OBJECT_H */
......@@ -24,7 +24,6 @@ enum request
REQ_RELEASE_SEMAPHORE,
REQ_OPEN_NAMED_OBJ,
REQ_CREATE_FILE,
REQ_GET_UNIX_HANDLE,
REQ_GET_READ_FD,
REQ_GET_WRITE_FD,
REQ_SET_FILE_POINTER,
......@@ -35,6 +34,8 @@ enum request
REQ_CREATE_CONSOLE,
REQ_SET_CONSOLE_FD,
REQ_CREATE_CHANGE_NOTIFICATION,
REQ_CREATE_MAPPING,
REQ_GET_MAPPING_INFO,
REQ_NB_REQUESTS
};
......@@ -62,7 +63,6 @@ DECL_HANDLER(create_semaphore);
DECL_HANDLER(release_semaphore);
DECL_HANDLER(open_named_obj);
DECL_HANDLER(create_file);
DECL_HANDLER(get_unix_handle);
DECL_HANDLER(get_read_fd);
DECL_HANDLER(get_write_fd);
DECL_HANDLER(set_file_pointer);
......@@ -73,6 +73,8 @@ DECL_HANDLER(create_pipe);
DECL_HANDLER(create_console);
DECL_HANDLER(set_console_fd);
DECL_HANDLER(create_change_notification);
DECL_HANDLER(create_mapping);
DECL_HANDLER(get_mapping_info);
static const struct handler {
void (*handler)();
......@@ -97,7 +99,6 @@ static const struct handler {
{ (void(*)())req_release_semaphore, sizeof(struct release_semaphore_request) },
{ (void(*)())req_open_named_obj, sizeof(struct open_named_obj_request) },
{ (void(*)())req_create_file, sizeof(struct create_file_request) },
{ (void(*)())req_get_unix_handle, sizeof(struct get_unix_handle_request) },
{ (void(*)())req_get_read_fd, sizeof(struct get_read_fd_request) },
{ (void(*)())req_get_write_fd, sizeof(struct get_write_fd_request) },
{ (void(*)())req_set_file_pointer, sizeof(struct set_file_pointer_request) },
......@@ -108,6 +109,8 @@ static const struct handler {
{ (void(*)())req_create_console, sizeof(struct create_console_request) },
{ (void(*)())req_set_console_fd, sizeof(struct set_console_fd_request) },
{ (void(*)())req_create_change_notification, sizeof(struct create_change_notification_request) },
{ (void(*)())req_create_mapping, sizeof(struct create_mapping_request) },
{ (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) },
};
#endif /* WANT_REQUEST_HANDLERS */
......
......@@ -52,7 +52,7 @@ extern void get_thread_info( struct thread *thread,
struct get_thread_info_reply *reply );
extern int send_reply( struct thread *thread, int pass_fd,
int n, ... /* arg_1, len_1, ..., arg_n, len_n */ );
extern void add_queue( struct object *obj, struct wait_queue_entry *entry );
extern int add_queue( struct object *obj, struct wait_queue_entry *entry );
extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
extern void kill_thread( struct thread *thread, int exit_code );
extern void thread_killed( struct thread *thread, int exit_code );
......
......@@ -10,6 +10,7 @@ C_SRCS = \
console.c \
event.c \
file.c \
mapping.c \
mutex.c \
object.c \
pipe.c \
......
......@@ -30,7 +30,7 @@ struct console
};
static void console_dump( struct object *obj, int verbose );
static void console_add_queue( struct object *obj, struct wait_queue_entry *entry );
static int console_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int console_signaled( struct object *obj, struct thread *thread );
static int console_get_read_fd( struct object *obj );
......@@ -124,15 +124,22 @@ static void console_dump( struct object *obj, int verbose )
console->is_read ? "input" : "output", console->fd );
}
static void console_add_queue( struct object *obj, struct wait_queue_entry *entry )
static int console_add_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct console *console = (struct console *)obj;
assert( obj->ops == &console_ops );
if (!obj->head) /* first on the queue */
add_select_user( console->fd,
console->is_read ? READ_EVENT : WRITE_EVENT,
&select_ops, console );
{
if (!add_select_user( console->fd,
console->is_read ? READ_EVENT : WRITE_EVENT,
&select_ops, console ))
{
SET_ERROR( ERROR_OUTOFMEMORY );
return 0;
}
}
add_queue( obj, entry );
return 1;
}
static void console_remove_queue( struct object *obj, struct wait_queue_entry *entry )
......
......@@ -27,7 +27,7 @@ struct file
};
static void file_dump( struct object *obj, int verbose );
static void file_add_queue( struct object *obj, struct wait_queue_entry *entry );
static int file_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int file_signaled( struct object *obj, struct thread *thread );
static int file_get_read_fd( struct object *obj );
......@@ -90,13 +90,20 @@ static void file_dump( struct object *obj, int verbose )
printf( "File fd=%d\n", file->fd );
}
static void file_add_queue( struct object *obj, struct wait_queue_entry *entry )
static int file_add_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct file *file = (struct file *)obj;
assert( obj->ops == &file_ops );
if (!obj->head) /* first on the queue */
add_select_user( file->fd, READ_EVENT | WRITE_EVENT, &select_ops, file );
{
if (!add_select_user( file->fd, READ_EVENT | WRITE_EVENT, &select_ops, file ))
{
SET_ERROR( ERROR_OUTOFMEMORY );
return 0;
}
}
add_queue( obj, entry );
return 1;
}
static void file_remove_queue( struct object *obj, struct wait_queue_entry *entry )
......@@ -195,17 +202,16 @@ void file_set_error(void)
}
}
int file_get_unix_handle( int handle, unsigned int access )
struct file *get_file_obj( struct process *process, int handle,
unsigned int access )
{
struct file *file;
int unix_handle;
return (struct file *)get_handle_obj( current->process, handle,
access, &file_ops );
}
if (!(file = (struct file *)get_handle_obj( current->process, handle,
access, &file_ops )))
return -1;
unix_handle = dup( file->fd );
release_object( file );
return unix_handle;
int file_get_mmap_fd( struct file *file )
{
return dup( file->fd );
}
int set_file_pointer( int handle, int *low, int *high, int whence )
......@@ -220,8 +226,7 @@ int set_file_pointer( int handle, int *low, int *high, int whence )
return 0;
}
if (!(file = (struct file *)get_handle_obj( current->process, handle,
0, &file_ops )))
if (!(file = get_file_obj( current->process, handle, 0 )))
return 0;
if ((result = lseek( file->fd, *low, whence )) == -1)
{
......@@ -243,8 +248,7 @@ int truncate_file( int handle )
struct file *file;
int result;
if (!(file = (struct file *)get_handle_obj( current->process, handle,
GENERIC_WRITE, &file_ops )))
if (!(file = get_file_obj( current->process, handle, GENERIC_WRITE )))
return 0;
if (((result = lseek( file->fd, 0, SEEK_CUR )) == -1) ||
(ftruncate( file->fd, result ) == -1))
......@@ -263,8 +267,7 @@ int get_file_info( int handle, struct get_file_info_reply *reply )
struct file *file;
struct stat st;
if (!(file = (struct file *)get_handle_obj( current->process, handle,
0, &file_ops )))
if (!(file = get_file_obj( current->process, handle, 0 )))
return 0;
if (fstat( file->fd, &st ) == -1)
{
......
......@@ -25,10 +25,10 @@ int main( int argc, char *argv[] )
debug_level = 1;
if (debug_level) printf( "Server: starting (pid=%d)\n", getpid() );
if (debug_level) fprintf( stderr, "Server: starting (pid=%d)\n", getpid() );
server_init( fd );
select_loop();
if (debug_level) printf( "Server: exiting (pid=%d)\n", getpid() );
if (debug_level) fprintf( stderr, "Server: exiting (pid=%d)\n", getpid() );
exit(0);
error:
......
/*
* Server-side file mapping management
*
* Copyright (C) 1999 Alexandre Julliard
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "winerror.h"
#include "winnt.h"
#include "server/thread.h"
struct mapping
{
struct object obj; /* object header */
int size_high; /* mapping size */
int size_low; /* mapping size */
int protect; /* protection flags */
struct file *file; /* file mapped */
};
static void mapping_dump( struct object *obj, int verbose );
static void mapping_destroy( struct object *obj );
static const struct object_ops mapping_ops =
{
mapping_dump,
no_add_queue,
NULL, /* should never get called */
NULL, /* should never get called */
NULL, /* should never get called */
no_read_fd,
no_write_fd,
no_flush,
mapping_destroy
};
struct object *create_mapping( int size_high, int size_low, int protect,
int handle, const char *name )
{
struct mapping *mapping;
if (!(mapping = (struct mapping *)create_named_object( name, &mapping_ops,
sizeof(*mapping) )))
return NULL;
if (GET_ERROR() == ERROR_ALREADY_EXISTS)
return &mapping->obj; /* Nothing else to do */
mapping->size_high = size_high;
mapping->size_low = size_low;
mapping->protect = protect;
if (handle != -1)
{
int access = 0;
if (protect & VPROT_READ) access |= GENERIC_READ;
if (protect & VPROT_WRITE) access |= GENERIC_WRITE;
if (!(mapping->file = get_file_obj( current->process, handle, access )))
{
release_object( mapping );
return NULL;
}
}
else mapping->file = NULL;
return &mapping->obj;
}
int open_mapping( unsigned int access, int inherit, const char *name )
{
return open_object( name, &mapping_ops, access, inherit );
}
int get_mapping_info( int handle, struct get_mapping_info_reply *reply )
{
struct mapping *mapping;
int fd;
if (!(mapping = (struct mapping *)get_handle_obj( current->process, handle,
0, &mapping_ops )))
return -1;
reply->size_high = mapping->size_high;
reply->size_low = mapping->size_low;
reply->protect = mapping->protect;
if (mapping->file) fd = file_get_mmap_fd( mapping->file );
else fd = -1;
release_object( mapping );
return fd;
}
static void mapping_dump( struct object *obj, int verbose )
{
struct mapping *mapping = (struct mapping *)obj;
assert( obj->ops == &mapping_ops );
fprintf( stderr, "Mapping size=%08x%08x prot=%08x file=%p\n",
mapping->size_high, mapping->size_low, mapping->protect, mapping->file );
}
static void mapping_destroy( struct object *obj )
{
struct mapping *mapping = (struct mapping *)obj;
assert( obj->ops == &mapping_ops );
if (mapping->file) release_object( mapping->file );
free( mapping );
}
......@@ -147,6 +147,12 @@ struct object *find_object( const char *name )
/* functions for unimplemented object operations */
int no_add_queue( struct object *obj, struct wait_queue_entry *entry )
{
SET_ERROR( ERROR_INVALID_HANDLE );
return 0;
}
int no_satisfied( struct object *obj, struct thread *thread )
{
return 0; /* not abandoned */
......
......@@ -30,7 +30,7 @@ struct pipe
};
static void pipe_dump( struct object *obj, int verbose );
static void pipe_add_queue( struct object *obj, struct wait_queue_entry *entry );
static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry );
static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry );
static int pipe_signaled( struct object *obj, struct thread *thread );
static int pipe_get_read_fd( struct object *obj );
......@@ -101,15 +101,22 @@ static void pipe_dump( struct object *obj, int verbose )
(pipe->side == READ_SIDE) ? "read" : "write", pipe->fd );
}
static void pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
static int pipe_add_queue( struct object *obj, struct wait_queue_entry *entry )
{
struct pipe *pipe = (struct pipe *)obj;
assert( obj->ops == &pipe_ops );
if (!obj->head) /* first on the queue */
add_select_user( pipe->fd,
(pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT,
&select_ops, pipe );
{
if (!add_select_user( pipe->fd,
(pipe->side == READ_SIDE) ? READ_EVENT : WRITE_EVENT,
&select_ops, pipe ))
{
SET_ERROR( ERROR_OUTOFMEMORY );
return 0;
}
}
add_queue( obj, entry );
return 1;
}
static void pipe_remove_queue( struct object *obj, struct wait_queue_entry *entry )
......
......@@ -382,6 +382,9 @@ DECL_HANDLER(open_named_obj)
case OPEN_SEMAPHORE:
reply.handle = open_semaphore( req->access, req->inherit, name );
break;
case OPEN_MAPPING:
reply.handle = open_mapping( req->access, req->inherit, name );
break;
default:
fatal_protocol_error( "open_named_obj: invalid type %d\n", req->type );
}
......@@ -409,13 +412,6 @@ DECL_HANDLER(create_file)
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* get a Unix handle to a file */
DECL_HANDLER(get_unix_handle)
{
int handle = file_get_unix_handle( req->handle, req->access );
send_reply( current, handle, 0 );
}
/* get a Unix fd to read from a file */
DECL_HANDLER(get_read_fd)
{
......@@ -552,3 +548,30 @@ DECL_HANDLER(create_change_notification)
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* create a file mapping */
DECL_HANDLER(create_mapping)
{
struct object *obj;
struct create_mapping_reply reply = { -1 };
char *name = (char *)data;
if (!len) name = NULL;
else CHECK_STRING( "create_mapping", name, len );
if ((obj = create_mapping( req->size_high, req->size_low,
req->protect, req->handle, name )))
{
int access = FILE_MAP_ALL_ACCESS;
if (!(req->protect & VPROT_WRITE)) access &= ~FILE_MAP_WRITE;
reply.handle = alloc_handle( current->process, obj, access, 0 );
release_object( obj );
}
send_reply( current, -1, 1, &reply, sizeof(reply) );
}
/* get a mapping information */
DECL_HANDLER(get_mapping_info)
{
struct get_mapping_info_reply reply;
int map_fd = get_mapping_info( req->handle, &reply );
send_reply( current, map_fd, 1, &reply, sizeof(reply) );
}
......@@ -199,7 +199,7 @@ int send_reply( struct thread *thread, int pass_fd, int n,
}
/* add a thread to an object wait queue; return 1 if OK, 0 on error */
void add_queue( struct object *obj, struct wait_queue_entry *entry )
int add_queue( struct object *obj, struct wait_queue_entry *entry )
{
grab_object( obj );
entry->obj = obj;
......@@ -208,6 +208,7 @@ void add_queue( struct object *obj, struct wait_queue_entry *entry )
if (obj->tail) obj->tail->next = entry;
else obj->head = entry;
obj->tail = entry;
return 1;
}
/* remove a thread from an object wait queue */
......@@ -278,7 +279,12 @@ static int wait_on( struct thread *thread, int count,
return 0;
}
entry->thread = thread;
obj->ops->add_queue( obj, entry );
if (!obj->ops->add_queue( obj, entry ))
{
wait->count = i - 1;
end_wait( thread );
return 0;
}
release_object( obj );
}
return 1;
......
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