diff --git a/include/server.h b/include/server.h index 228c4bb0623..f0601ade8b8 100644 --- a/include/server.h +++ b/include/server.h @@ -30,6 +30,9 @@ struct cmsg_fd int fd; /* fd to pass */ }; +/* request handler definition */ +#define DECL_HANDLER(name) \ + void req_##name( struct name##_request *req, void *data, int len, int fd ) /* Request structures */ @@ -314,6 +317,19 @@ struct event_op_request enum event_op { PULSE_EVENT, SET_EVENT, RESET_EVENT }; +/* Open an event */ +struct open_event_request +{ + unsigned int access; /* wanted access rights */ + int inherit; /* inherit flag */ + char name[0]; /* object name */ +}; +struct open_event_reply +{ + int handle; /* handle to the event */ +}; + + /* Create a mutex */ struct create_mutex_request { @@ -334,6 +350,19 @@ struct release_mutex_request }; +/* Open a mutex */ +struct open_mutex_request +{ + unsigned int access; /* wanted access rights */ + int inherit; /* inherit flag */ + char name[0]; /* object name */ +}; +struct open_mutex_reply +{ + int handle; /* handle to the mutex */ +}; + + /* Create a semaphore */ struct create_semaphore_request { @@ -360,19 +389,16 @@ struct release_semaphore_reply }; -/* Open a named object (event, mutex, semaphore) */ -struct open_named_obj_request +/* Open a semaphore */ +struct open_semaphore_request { - int type; /* object type (see below) */ unsigned int access; /* wanted access rights */ int inherit; /* inherit flag */ char name[0]; /* object name */ }; -enum open_named_obj { OPEN_EVENT, OPEN_MUTEX, OPEN_SEMAPHORE, OPEN_MAPPING }; - -struct open_named_obj_reply +struct open_semaphore_reply { - int handle; /* handle to the object */ + int handle; /* handle to the semaphore */ }; @@ -640,6 +666,19 @@ struct create_mapping_reply #define VPROT_COMMITTED 0x40 +/* Open a mapping */ +struct open_mapping_request +{ + unsigned int access; /* wanted access rights */ + int inherit; /* inherit flag */ + char name[0]; /* object name */ +}; +struct open_mapping_reply +{ + int handle; /* handle to the mapping */ +}; + + /* Get information about a file mapping */ struct get_mapping_info_request { @@ -692,12 +731,13 @@ struct next_process_reply }; +/* requests definitions */ +#include "server/request.h" + /* client-side functions */ #ifndef __WINE_SERVER__ -#include "server/request.h" - /* client communication functions */ extern void CLIENT_SendRequest( enum request req, int pass_fd, int n, ... /* arg_1, len_1, etc. */ ); diff --git a/include/server/process.h b/include/server/process.h deleted file mode 100644 index cfd0d881e43..00000000000 --- a/include/server/process.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Wine server processes - * - * Copyright (C) 1999 Alexandre Julliard - */ - -#ifndef __WINE_SERVER_PROCESS_H -#define __WINE_SERVER_PROCESS_H - -#ifndef __WINE_SERVER__ -#error This file can only be used in the Wine server -#endif - -#include "server/object.h" - -/* process structures */ - -struct process; - -struct process_snapshot -{ - struct process *process; /* process ptr */ - struct process *parent; /* process parent */ - int threads; /* number of threads */ - int priority; /* priority class */ -}; - -/* process functions */ - -extern struct process *create_initial_process(void); -extern struct process *create_process( struct new_process_request *req ); -extern struct process *get_process_from_id( void *id ); -extern struct process *get_process_from_handle( int handle, unsigned int access ); -extern int get_process_init_info( struct process *process, struct init_process_reply *reply ); -extern void add_process_thread( struct process *process, - struct thread *thread ); -extern void remove_process_thread( struct process *process, - struct thread *thread ); -extern void kill_process( struct process *process, int exit_code ); -extern void get_process_info( struct process *process, - struct get_process_info_reply *reply ); -extern void set_process_info( struct process *process, - struct set_process_info_request *req ); -extern int alloc_console( struct process *process ); -extern int free_console( struct process *process ); -extern struct object *get_console( struct process *process, int output ); -extern struct process_snapshot *process_snap( int *count ); - -/* handle functions */ - -/* alloc_handle takes a void *obj for convenience, but you better make sure */ -/* that the thing pointed to starts with a struct object... */ -extern int alloc_handle( struct process *process, void *obj, - unsigned int access, int inherit ); -extern int close_handle( struct process *process, int handle ); -extern int set_handle_info( struct process *process, int handle, - int mask, int flags ); -extern struct object *get_handle_obj( struct process *process, int handle, - unsigned int access, const struct object_ops *ops ); -extern int duplicate_handle( struct process *src, int src_handle, struct process *dst, - unsigned int access, int inherit, int options ); -extern int open_object( const char *name, const struct object_ops *ops, - unsigned int access, int inherit ); - -#endif /* __WINE_SERVER_PROCESS_H */ diff --git a/include/server/request.h b/include/server/request.h index 6167edd31d4..ae44fa289d9 100644 --- a/include/server/request.h +++ b/include/server/request.h @@ -28,11 +28,13 @@ enum request REQ_SELECT, REQ_CREATE_EVENT, REQ_EVENT_OP, + REQ_OPEN_EVENT, REQ_CREATE_MUTEX, REQ_RELEASE_MUTEX, + REQ_OPEN_MUTEX, REQ_CREATE_SEMAPHORE, REQ_RELEASE_SEMAPHORE, - REQ_OPEN_NAMED_OBJ, + REQ_OPEN_SEMAPHORE, REQ_CREATE_FILE, REQ_GET_READ_FD, REQ_GET_WRITE_FD, @@ -56,6 +58,7 @@ enum request REQ_READ_CONSOLE_INPUT, REQ_CREATE_CHANGE_NOTIFICATION, REQ_CREATE_MAPPING, + REQ_OPEN_MAPPING, REQ_GET_MAPPING_INFO, REQ_CREATE_DEVICE, REQ_CREATE_SNAPSHOT, @@ -65,9 +68,6 @@ enum request #ifdef WANT_REQUEST_HANDLERS -#define DECL_HANDLER(name) \ - static void req_##name( struct name##_request *req, void *data, int len, int fd ) - DECL_HANDLER(new_process); DECL_HANDLER(new_thread); DECL_HANDLER(set_debug); @@ -91,11 +91,13 @@ DECL_HANDLER(open_process); DECL_HANDLER(select); DECL_HANDLER(create_event); DECL_HANDLER(event_op); +DECL_HANDLER(open_event); DECL_HANDLER(create_mutex); DECL_HANDLER(release_mutex); +DECL_HANDLER(open_mutex); DECL_HANDLER(create_semaphore); DECL_HANDLER(release_semaphore); -DECL_HANDLER(open_named_obj); +DECL_HANDLER(open_semaphore); DECL_HANDLER(create_file); DECL_HANDLER(get_read_fd); DECL_HANDLER(get_write_fd); @@ -119,6 +121,7 @@ DECL_HANDLER(write_console_input); DECL_HANDLER(read_console_input); DECL_HANDLER(create_change_notification); DECL_HANDLER(create_mapping); +DECL_HANDLER(open_mapping); DECL_HANDLER(get_mapping_info); DECL_HANDLER(create_device); DECL_HANDLER(create_snapshot); @@ -151,11 +154,13 @@ static const struct handler { { (void(*)())req_select, sizeof(struct select_request) }, { (void(*)())req_create_event, sizeof(struct create_event_request) }, { (void(*)())req_event_op, sizeof(struct event_op_request) }, + { (void(*)())req_open_event, sizeof(struct open_event_request) }, { (void(*)())req_create_mutex, sizeof(struct create_mutex_request) }, { (void(*)())req_release_mutex, sizeof(struct release_mutex_request) }, + { (void(*)())req_open_mutex, sizeof(struct open_mutex_request) }, { (void(*)())req_create_semaphore, sizeof(struct create_semaphore_request) }, { (void(*)())req_release_semaphore, sizeof(struct release_semaphore_request) }, - { (void(*)())req_open_named_obj, sizeof(struct open_named_obj_request) }, + { (void(*)())req_open_semaphore, sizeof(struct open_semaphore_request) }, { (void(*)())req_create_file, sizeof(struct create_file_request) }, { (void(*)())req_get_read_fd, sizeof(struct get_read_fd_request) }, { (void(*)())req_get_write_fd, sizeof(struct get_write_fd_request) }, @@ -179,6 +184,7 @@ static const struct handler { { (void(*)())req_read_console_input, sizeof(struct read_console_input_request) }, { (void(*)())req_create_change_notification, sizeof(struct create_change_notification_request) }, { (void(*)())req_create_mapping, sizeof(struct create_mapping_request) }, + { (void(*)())req_open_mapping, sizeof(struct open_mapping_request) }, { (void(*)())req_get_mapping_info, sizeof(struct get_mapping_info_request) }, { (void(*)())req_create_device, sizeof(struct create_device_request) }, { (void(*)())req_create_snapshot, sizeof(struct create_snapshot_request) }, diff --git a/memory/virtual.c b/memory/virtual.c index ef5d69d9cc4..5e810e0aa54 100644 --- a/memory/virtual.c +++ b/memory/virtual.c @@ -1118,14 +1118,13 @@ HANDLE WINAPI OpenFileMappingA( BOOL inherit, /* [in] Inherit flag */ LPCSTR name ) /* [in] Name of file-mapping object */ { - struct open_named_obj_request req; - struct open_named_obj_reply reply; + struct open_mapping_request req; + struct open_mapping_reply reply; int len = name ? strlen(name) + 1 : 0; - req.type = OPEN_MAPPING; req.access = access; req.inherit = inherit; - CLIENT_SendRequest( REQ_OPEN_NAMED_OBJ, -1, 2, &req, sizeof(req), name, len ); + CLIENT_SendRequest( REQ_OPEN_MAPPING, -1, 2, &req, sizeof(req), name, len ); CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); if (reply.handle == -1) return 0; /* must return 0 on failure, not -1 */ return reply.handle; diff --git a/scheduler/event.c b/scheduler/event.c index 04f5778e621..8ab01077fe6 100644 --- a/scheduler/event.c +++ b/scheduler/event.c @@ -60,14 +60,13 @@ HANDLE WINAPI WIN16_CreateEvent( BOOL manual_reset, BOOL initial_state ) */ HANDLE WINAPI OpenEventA( DWORD access, BOOL inherit, LPCSTR name ) { - struct open_named_obj_request req; - struct open_named_obj_reply reply; + struct open_event_request req; + struct open_event_reply reply; int len = name ? strlen(name) + 1 : 0; - req.type = OPEN_EVENT; req.access = access; req.inherit = inherit; - CLIENT_SendRequest( REQ_OPEN_NAMED_OBJ, -1, 2, &req, sizeof(req), name, len ); + CLIENT_SendRequest( REQ_OPEN_EVENT, -1, 2, &req, sizeof(req), name, len ); CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); if (reply.handle == -1) return 0; /* must return 0 on failure, not -1 */ return (HANDLE)reply.handle; diff --git a/scheduler/mutex.c b/scheduler/mutex.c index 7bbe6a8f82e..185dea8aac5 100644 --- a/scheduler/mutex.c +++ b/scheduler/mutex.c @@ -49,14 +49,13 @@ HANDLE WINAPI CreateMutexW( SECURITY_ATTRIBUTES *sa, BOOL owner, */ HANDLE WINAPI OpenMutexA( DWORD access, BOOL inherit, LPCSTR name ) { - struct open_named_obj_request req; - struct open_named_obj_reply reply; + struct open_mutex_request req; + struct open_mutex_reply reply; int len = name ? strlen(name) + 1 : 0; - req.type = OPEN_MUTEX; req.access = access; req.inherit = inherit; - CLIENT_SendRequest( REQ_OPEN_NAMED_OBJ, -1, 2, &req, sizeof(req), name, len ); + CLIENT_SendRequest( REQ_OPEN_MUTEX, -1, 2, &req, sizeof(req), name, len ); CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); if (reply.handle == -1) return 0; /* must return 0 on failure, not -1 */ return reply.handle; diff --git a/scheduler/semaphore.c b/scheduler/semaphore.c index 298df02e787..dbe2eecddca 100644 --- a/scheduler/semaphore.c +++ b/scheduler/semaphore.c @@ -60,14 +60,13 @@ HANDLE WINAPI CreateSemaphoreW( SECURITY_ATTRIBUTES *sa, LONG initial, */ HANDLE WINAPI OpenSemaphoreA( DWORD access, BOOL inherit, LPCSTR name ) { - struct open_named_obj_request req; - struct open_named_obj_reply reply; + struct open_semaphore_request req; + struct open_semaphore_reply reply; int len = name ? strlen(name) + 1 : 0; - req.type = OPEN_SEMAPHORE; req.access = access; req.inherit = inherit; - CLIENT_SendRequest( REQ_OPEN_NAMED_OBJ, -1, 2, &req, sizeof(req), name, len ); + CLIENT_SendRequest( REQ_OPEN_SEMAPHORE, -1, 2, &req, sizeof(req), name, len ); CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL ); if (reply.handle == -1) return 0; /* must return 0 on failure, not -1 */ return reply.handle; diff --git a/server/Makefile.in b/server/Makefile.in index f062a95cee4..3aaa6da47b8 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -11,6 +11,7 @@ C_SRCS = \ device.c \ event.c \ file.c \ + handle.c \ mapping.c \ mutex.c \ object.c \ diff --git a/server/change.c b/server/change.c index bae2f235505..679df12c803 100644 --- a/server/change.c +++ b/server/change.c @@ -10,7 +10,9 @@ #include "winerror.h" #include "winnt.h" -#include "server/thread.h" + +#include "handle.h" +#include "thread.h" struct change { @@ -38,7 +40,7 @@ static const struct object_ops change_ops = }; -struct object *create_change_notification( int subtree, int filter ) +static struct object *create_change_notification( int subtree, int filter ) { struct change *change; if (!(change = mem_alloc( sizeof(*change) ))) return NULL; @@ -69,3 +71,18 @@ static void change_destroy( struct object *obj ) assert( obj->ops == &change_ops ); free( change ); } + +/* create a change notification */ +DECL_HANDLER(create_change_notification) +{ + struct object *obj; + struct create_change_notification_reply reply = { -1 }; + + if ((obj = create_change_notification( req->subtree, req->filter ))) + { + reply.handle = alloc_handle( current->process, obj, + STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} diff --git a/server/console.c b/server/console.c index 0d095b41c84..d067c211fc7 100644 --- a/server/console.c +++ b/server/console.c @@ -23,8 +23,10 @@ #include "winerror.h" #include "winnt.h" #include "wincon.h" -#include "server/process.h" -#include "server/thread.h" + +#include "handle.h" +#include "process.h" +#include "thread.h" struct screen_buffer; @@ -153,7 +155,7 @@ int create_console( int fd, struct object *obj[2] ) return 1; } -int set_console_fd( int handle, int fd, int pid ) +static int set_console_fd( int handle, int fd, int pid ) { struct console_input *input; struct screen_buffer *output; @@ -206,7 +208,7 @@ int set_console_fd( int handle, int fd, int pid ) return 1; } -int get_console_mode( int handle, int *mode ) +static int get_console_mode( int handle, int *mode ) { struct object *obj; int ret = 0; @@ -228,7 +230,7 @@ int get_console_mode( int handle, int *mode ) return ret; } -int set_console_mode( int handle, int mode ) +static int set_console_mode( int handle, int mode ) { struct object *obj; int ret = 0; @@ -251,7 +253,7 @@ int set_console_mode( int handle, int mode ) } /* set misc console information (output handle only) */ -int set_console_info( int handle, struct set_console_info_request *req, const char *title ) +static int set_console_info( int handle, struct set_console_info_request *req, const char *title ) { struct screen_buffer *console; if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle, @@ -272,7 +274,7 @@ int set_console_info( int handle, struct set_console_info_request *req, const ch } /* get misc console information (output handle only) */ -int get_console_info( int handle, struct get_console_info_reply *reply, const char **title ) +static int get_console_info( int handle, struct get_console_info_reply *reply, const char **title ) { struct screen_buffer *console; if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle, @@ -287,7 +289,7 @@ int get_console_info( int handle, struct get_console_info_reply *reply, const ch } /* add input events to a console input queue */ -int write_console_input( int handle, int count, INPUT_RECORD *records ) +static int write_console_input( int handle, int count, INPUT_RECORD *records ) { INPUT_RECORD *new_rec; struct console_input *console; @@ -310,7 +312,7 @@ int write_console_input( int handle, int count, INPUT_RECORD *records ) } /* retrieve a pointer to the console input records */ -int read_console_input( int handle, int count, int flush ) +static int read_console_input( int handle, int count, int flush ) { struct console_input *console; @@ -472,3 +474,91 @@ static void screen_buffer_destroy( struct object *obj ) if (console->title) free( console->title ); free( console ); } + +/* allocate a console for the current process */ +DECL_HANDLER(alloc_console) +{ + alloc_console( current->process ); + send_reply( current, -1, 0 ); +} + +/* free the console of the current process */ +DECL_HANDLER(free_console) +{ + free_console( current->process ); + send_reply( current, -1, 0 ); +} + +/* open a handle to the process console */ +DECL_HANDLER(open_console) +{ + struct object *obj; + struct open_console_reply reply = { -1 }; + if ((obj = get_console( current->process, req->output ))) + { + reply.handle = alloc_handle( current->process, obj, req->access, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* set info about a console (output only) */ +DECL_HANDLER(set_console_info) +{ + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "set_console_info", name, len ); + set_console_info( req->handle, req, name ); + send_reply( current, -1, 0 ); +} + +/* get info about a console (output only) */ +DECL_HANDLER(get_console_info) +{ + struct get_console_info_reply reply; + const char *title; + get_console_info( req->handle, &reply, &title ); + send_reply( current, -1, 2, &reply, sizeof(reply), + title, title ? strlen(title)+1 : 0 ); +} + +/* set a console fd */ +DECL_HANDLER(set_console_fd) +{ + set_console_fd( req->handle, fd, req->pid ); + send_reply( current, -1, 0 ); +} + +/* get a console mode (input or output) */ +DECL_HANDLER(get_console_mode) +{ + struct get_console_mode_reply reply; + get_console_mode( req->handle, &reply.mode ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* set a console mode (input or output) */ +DECL_HANDLER(set_console_mode) +{ + set_console_mode( req->handle, req->mode ); + send_reply( current, -1, 0 ); +} + +/* add input records to a console input queue */ +DECL_HANDLER(write_console_input) +{ + struct write_console_input_reply reply; + INPUT_RECORD *records = (INPUT_RECORD *)data; + + if (len != req->count * sizeof(INPUT_RECORD)) + fatal_protocol_error( "write_console_input: bad length %d for %d records\n", + len, req->count ); + reply.written = write_console_input( req->handle, req->count, records ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* fetch input records from a console input queue */ +DECL_HANDLER(read_console_input) +{ + read_console_input( req->handle, req->count, req->flush ); +} diff --git a/server/device.c b/server/device.c index 83446f45101..5822293cb5d 100644 --- a/server/device.c +++ b/server/device.c @@ -18,7 +18,9 @@ #include "winerror.h" #include "winbase.h" -#include "server/thread.h" + +#include "handle.h" +#include "thread.h" struct device { @@ -44,7 +46,7 @@ static const struct object_ops device_ops = device_destroy }; -struct object *create_device( int id ) +static struct object *create_device( int id ) { struct device *dev; @@ -77,3 +79,18 @@ static void device_destroy( struct object *obj ) assert( obj->ops == &device_ops ); free( dev ); } + +/* create a device */ +DECL_HANDLER(create_device) +{ + struct object *obj; + struct create_device_reply reply = { -1 }; + + if ((obj = create_device( req->id ))) + { + reply.handle = alloc_handle( current->process, obj, + req->access, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} diff --git a/server/event.c b/server/event.c index 04f51603918..5546d6e476c 100644 --- a/server/event.c +++ b/server/event.c @@ -10,8 +10,9 @@ #include "winerror.h" #include "winnt.h" -#include "server/process.h" -#include "server/thread.h" + +#include "handle.h" +#include "thread.h" struct event { @@ -40,7 +41,7 @@ static const struct object_ops event_ops = }; -struct object *create_event( const char *name, int manual_reset, int initial_state ) +static struct object *create_event( const char *name, int manual_reset, int initial_state ) { struct event *event; @@ -55,12 +56,7 @@ struct object *create_event( const char *name, int manual_reset, int initial_sta return &event->obj; } -int open_event( unsigned int access, int inherit, const char *name ) -{ - return open_object( name, &event_ops, access, inherit ); -} - -int pulse_event( int handle ) +static int pulse_event( int handle ) { struct event *event; @@ -75,7 +71,7 @@ int pulse_event( int handle ) return 1; } -int set_event( int handle ) +static int set_event( int handle ) { struct event *event; @@ -89,7 +85,7 @@ int set_event( int handle ) return 1; } -int reset_event( int handle ) +static int reset_event( int handle ) { struct event *event; @@ -132,3 +128,53 @@ static void event_destroy( struct object *obj ) assert( obj->ops == &event_ops ); free( event ); } + +/* create an event */ +DECL_HANDLER(create_event) +{ + struct create_event_reply reply = { -1 }; + struct object *obj; + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "create_event", name, len ); + + obj = create_event( name, req->manual_reset, req->initial_state ); + if (obj) + { + reply.handle = alloc_handle( current->process, obj, EVENT_ALL_ACCESS, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* open a handle to an event */ +DECL_HANDLER(open_event) +{ + struct open_event_reply reply; + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "open_event", name, len ); + + reply.handle = open_object( name, &event_ops, req->access, req->inherit ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* do an event operation */ +DECL_HANDLER(event_op) +{ + switch(req->op) + { + case PULSE_EVENT: + pulse_event( req->handle ); + break; + case SET_EVENT: + set_event( req->handle ); + break; + case RESET_EVENT: + reset_event( req->handle ); + break; + default: + fatal_protocol_error( "event_op: invalid operation %d\n", req->op ); + } + send_reply( current, -1, 0 ); +} diff --git a/server/file.c b/server/file.c index 6d992bdc287..00f1c60897b 100644 --- a/server/file.c +++ b/server/file.c @@ -20,8 +20,9 @@ #include "winerror.h" #include "winbase.h" -#include "server/process.h" -#include "server/thread.h" + +#include "handle.h" +#include "thread.h" struct file { @@ -98,8 +99,8 @@ static int check_sharing( const char *name, int hash, unsigned int access, return 1; } -struct object *create_file( int fd, const char *name, unsigned int access, - unsigned int sharing, int create, unsigned int attrs ) +static struct object *create_file( int fd, const char *name, unsigned int access, + unsigned int sharing, int create, unsigned int attrs ) { struct file *file; int hash = 0; @@ -399,7 +400,7 @@ int file_get_mmap_fd( struct file *file ) return dup( file->fd ); } -int set_file_pointer( int handle, int *low, int *high, int whence ) +static int set_file_pointer( int handle, int *low, int *high, int whence ) { struct file *file; int result; @@ -428,7 +429,7 @@ int set_file_pointer( int handle, int *low, int *high, int whence ) return 1; } -int truncate_file( int handle ) +static int truncate_file( int handle ) { struct file *file; int result; @@ -468,7 +469,7 @@ int grow_file( struct file *file, int size_high, int size_low ) return 0; } -int set_file_time( int handle, time_t access_time, time_t write_time ) +static int set_file_time( int handle, time_t access_time, time_t write_time ) { struct file *file; struct utimbuf utimbuf; @@ -493,16 +494,142 @@ int set_file_time( int handle, time_t access_time, time_t write_time ) return 0; } -int file_lock( struct file *file, int offset_high, int offset_low, - int count_high, int count_low ) +static int file_lock( struct file *file, int offset_high, int offset_low, + int count_high, int count_low ) { /* FIXME: implement this */ return 1; } -int file_unlock( struct file *file, int offset_high, int offset_low, - int count_high, int count_low ) +static int file_unlock( struct file *file, int offset_high, int offset_low, + int count_high, int count_low ) { /* FIXME: implement this */ return 1; } +/* create a file */ +DECL_HANDLER(create_file) +{ + struct create_file_reply reply = { -1 }; + struct object *obj; + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "create_file", name, len ); + + if ((obj = create_file( fd, name, req->access, + req->sharing, req->create, req->attrs )) != NULL) + { + reply.handle = alloc_handle( current->process, obj, req->access, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* get a Unix fd to read from a file */ +DECL_HANDLER(get_read_fd) +{ + struct object *obj; + int read_fd; + + if ((obj = get_handle_obj( current->process, req->handle, GENERIC_READ, NULL ))) + { + read_fd = obj->ops->get_read_fd( obj ); + release_object( obj ); + } + else read_fd = -1; + send_reply( current, read_fd, 0 ); +} + +/* get a Unix fd to write to a file */ +DECL_HANDLER(get_write_fd) +{ + struct object *obj; + int write_fd; + + if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL ))) + { + write_fd = obj->ops->get_write_fd( obj ); + release_object( obj ); + } + else write_fd = -1; + send_reply( current, write_fd, 0 ); +} + +/* set a file current position */ +DECL_HANDLER(set_file_pointer) +{ + struct set_file_pointer_reply reply; + reply.low = req->low; + reply.high = req->high; + set_file_pointer( req->handle, &reply.low, &reply.high, req->whence ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* truncate (or extend) a file */ +DECL_HANDLER(truncate_file) +{ + truncate_file( req->handle ); + send_reply( current, -1, 0 ); +} + +/* flush a file buffers */ +DECL_HANDLER(flush_file) +{ + struct object *obj; + + if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL ))) + { + obj->ops->flush( obj ); + release_object( obj ); + } + send_reply( current, -1, 0 ); +} + +/* set a file access and modification times */ +DECL_HANDLER(set_file_time) +{ + set_file_time( req->handle, req->access_time, req->write_time ); + send_reply( current, -1, 0 ); +} + +/* get a file information */ +DECL_HANDLER(get_file_info) +{ + struct object *obj; + struct get_file_info_reply reply; + + if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) + { + obj->ops->get_file_info( obj, &reply ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* lock a region of a file */ +DECL_HANDLER(lock_file) +{ + struct file *file; + + if ((file = get_file_obj( current->process, req->handle, 0 ))) + { + file_lock( file, req->offset_high, req->offset_low, + req->count_high, req->count_low ); + release_object( file ); + } + send_reply( current, -1, 0 ); +} + +/* unlock a region of a file */ +DECL_HANDLER(unlock_file) +{ + struct file *file; + + if ((file = get_file_obj( current->process, req->handle, 0 ))) + { + file_unlock( file, req->offset_high, req->offset_low, + req->count_high, req->count_low ); + release_object( file ); + } + send_reply( current, -1, 0 ); +} diff --git a/server/handle.c b/server/handle.c new file mode 100644 index 00000000000..a99583bb4d0 --- /dev/null +++ b/server/handle.c @@ -0,0 +1,372 @@ +/* + * Server-side handle management + * + * Copyright (C) 1998 Alexandre Julliard + */ + +#include +#include +#include +#include +#include + +#include "winerror.h" +#include "winbase.h" + +#include "handle.h" +#include "process.h" +#include "thread.h" + +struct handle_entry +{ + struct object *ptr; + unsigned int access; +}; + +static struct process *initial_process; + +/* reserved handle access rights */ +#define RESERVED_SHIFT 25 +#define RESERVED_INHERIT (HANDLE_FLAG_INHERIT << RESERVED_SHIFT) +#define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE << RESERVED_SHIFT) +#define RESERVED_ALL (RESERVED_INHERIT | RESERVED_CLOSE_PROTECT) + +/* global handle macros */ +#define HANDLE_OBFUSCATOR 0x544a4def +#define HANDLE_IS_GLOBAL(h) (((h) ^ HANDLE_OBFUSCATOR) < 0x10000) +#define HANDLE_LOCAL_TO_GLOBAL(h) ((h) ^ HANDLE_OBFUSCATOR) +#define HANDLE_GLOBAL_TO_LOCAL(h) ((h) ^ HANDLE_OBFUSCATOR) + +#define MIN_HANDLE_ENTRIES 32 + +/* grow a handle table */ +/* return 1 if OK, 0 on error */ +static int grow_handle_table( struct handle_table *table ) +{ + struct handle_entry *new_entries; + int count = table->count; + + if (count >= INT_MAX / 2) return 0; + count *= 2; + if (!(new_entries = realloc( table->entries, count * sizeof(struct handle_entry) ))) + { + SET_ERROR( ERROR_OUTOFMEMORY ); + return 0; + } + table->count = count; + table->entries = new_entries; + return 1; +} + +/* allocate a handle for an object, incrementing its refcount */ +/* return the handle, or -1 on error */ +int alloc_handle( struct process *process, void *obj, unsigned int access, + int inherit ) +{ + struct handle_table *table = get_process_handles( process ); + struct handle_entry *entry; + int handle; + + assert( !(access & RESERVED_ALL) ); + if (inherit) access |= RESERVED_INHERIT; + + /* find the first free entry */ + + if (!(entry = table->entries)) return -1; + for (handle = 0; handle <= table->last; handle++, entry++) + if (!entry->ptr) goto found; + + if (handle >= table->count) + { + if (!grow_handle_table( table )) return -1; + entry = table->entries + handle; /* the table may have moved */ + } + table->last = handle; + + found: + entry->ptr = grab_object( obj ); + entry->access = access; + return handle + 1; /* avoid handle 0 */ +} + +/* return an handle entry, or NULL if the handle is invalid */ +static struct handle_entry *get_handle( struct process *process, int handle ) +{ + struct handle_table *table; + struct handle_entry *entry; + + if (HANDLE_IS_GLOBAL(handle)) + { + handle = HANDLE_GLOBAL_TO_LOCAL(handle); + process = initial_process; + } + table = get_process_handles( process ); + handle--; /* handles start at 1 */ + if ((handle < 0) || (handle > table->last)) goto error; + entry = table->entries + handle; + if (!entry->ptr) goto error; + return entry; + + error: + SET_ERROR( ERROR_INVALID_HANDLE ); + return NULL; +} + +/* attempt to shrink a table */ +/* return 1 if OK, 0 on error */ +static int shrink_handle_table( struct handle_table *table ) +{ + struct handle_entry *new_entries; + struct handle_entry *entry = table->entries + table->last; + int count = table->count; + + while (table->last >= 0) + { + if (entry->ptr) break; + table->last--; + entry--; + } + if (table->last >= count / 4) return 1; /* no need to shrink */ + if (count < MIN_HANDLE_ENTRIES * 2) return 1; /* too small to shrink */ + count /= 2; + if (!(new_entries = realloc( table->entries, + count * sizeof(struct handle_entry) ))) + return 0; + table->count = count; + table->entries = new_entries; + return 1; +} + +/* copy the handle table of the parent process */ +/* return 1 if OK, 0 on error */ +int copy_handle_table( struct process *process, struct process *parent ) +{ + struct handle_table *parent_table; + struct handle_table *table = get_process_handles( process ); + struct handle_entry *ptr; + int i, count, last; + + if (!parent) /* first process */ + { + if (!initial_process) initial_process = process; + parent_table = NULL; + count = MIN_HANDLE_ENTRIES; + last = -1; + } + else + { + parent_table = get_process_handles( parent ); + assert( parent_table->entries ); + count = parent_table->count; + last = parent_table->last; + } + + if (!(ptr = mem_alloc( count * sizeof(struct handle_entry)))) return 0; + table->entries = ptr; + table->count = count; + table->last = last; + + if (last >= 0) + { + memcpy( ptr, parent_table->entries, (last + 1) * sizeof(struct handle_entry) ); + for (i = 0; i <= last; i++, ptr++) + { + if (!ptr->ptr) continue; + if (ptr->access & RESERVED_INHERIT) grab_object( ptr->ptr ); + else ptr->ptr = NULL; /* don't inherit this entry */ + } + } + /* attempt to shrink the table */ + shrink_handle_table( table ); + return 1; +} + +/* close a handle and decrement the refcount of the associated object */ +/* return 1 if OK, 0 on error */ +int close_handle( struct process *process, int handle ) +{ + struct handle_table *table; + struct handle_entry *entry; + struct object *obj; + + if (HANDLE_IS_GLOBAL(handle)) + { + handle = HANDLE_GLOBAL_TO_LOCAL(handle); + process = initial_process; + } + table = get_process_handles( process ); + if (!(entry = get_handle( process, handle ))) return 0; + if (entry->access & RESERVED_CLOSE_PROTECT) return 0; /* FIXME: error code */ + obj = entry->ptr; + entry->ptr = NULL; + if (handle-1 == table->last) shrink_handle_table( table ); + release_object( obj ); + return 1; +} + +/* retrieve the object corresponding to a handle, incrementing its refcount */ +struct object *get_handle_obj( struct process *process, int handle, + unsigned int access, const struct object_ops *ops ) +{ + struct handle_entry *entry; + struct object *obj; + + switch( handle ) + { + case 0xfffffffe: /* current thread pseudo-handle */ + obj = ¤t->obj; + break; + case 0x7fffffff: /* current process pseudo-handle */ + obj = (struct object *)current->process; + break; + default: + if (!(entry = get_handle( process, handle ))) return NULL; + if ((entry->access & access) != access) + { + SET_ERROR( ERROR_ACCESS_DENIED ); + return NULL; + } + obj = entry->ptr; + break; + } + if (ops && (obj->ops != ops)) + { + SET_ERROR( ERROR_INVALID_HANDLE ); /* not the right type */ + return NULL; + } + return grab_object( obj ); +} + +/* get/set the handle reserved flags */ +/* return the new flags (or -1 on error) */ +static int set_handle_info( struct process *process, int handle, int mask, int flags ) +{ + struct handle_entry *entry; + + if (!(entry = get_handle( process, handle ))) return -1; + mask = (mask << RESERVED_SHIFT) & RESERVED_ALL; + flags = (flags << RESERVED_SHIFT) & mask; + entry->access = (entry->access & ~mask) | flags; + return (entry->access & RESERVED_ALL) >> RESERVED_SHIFT; +} + +/* duplicate a handle */ +int duplicate_handle( struct process *src, int src_handle, struct process *dst, + unsigned int access, int inherit, int options ) +{ + int res; + struct handle_entry *entry = get_handle( src, src_handle ); + if (!entry) return -1; + + if (options & DUP_HANDLE_SAME_ACCESS) access = entry->access; + if (options & DUP_HANDLE_MAKE_GLOBAL) dst = initial_process; + access &= ~RESERVED_ALL; + res = alloc_handle( dst, entry->ptr, access, inherit ); + if (options & DUP_HANDLE_MAKE_GLOBAL) res = HANDLE_LOCAL_TO_GLOBAL(res); + return res; +} + +/* free the process handle entries */ +void free_handles( struct process *process ) +{ + struct handle_table *table = get_process_handles( process ); + struct handle_entry *entry; + int handle; + + if (!(entry = table->entries)) return; + for (handle = 0; handle <= table->last; handle++, entry++) + { + struct object *obj = entry->ptr; + entry->ptr = NULL; + if (obj) release_object( obj ); + } + free( table->entries ); + table->count = 0; + table->last = -1; + table->entries = NULL; +} + +/* open a new handle to an existing object */ +int open_object( const char *name, const struct object_ops *ops, + unsigned int access, int inherit ) +{ + struct object *obj = find_object( name ); + if (!obj) + { + SET_ERROR( ERROR_FILE_NOT_FOUND ); + return -1; + } + if (ops && obj->ops != ops) + { + release_object( obj ); + SET_ERROR( ERROR_INVALID_HANDLE ); /* FIXME: not the right type */ + return -1; + } + return alloc_handle( current->process, obj, access, inherit ); +} + +/* dump a handle table on stdout */ +void dump_handles( struct process *process ) +{ + struct handle_table *table = get_process_handles( process ); + struct handle_entry *entry; + int i; + + if (!table->entries) return; + entry = table->entries; + for (i = 0; i <= table->last; i++, entry++) + { + if (!entry->ptr) continue; + printf( "%5d: %p %08x ", i + 1, entry->ptr, entry->access ); + entry->ptr->ops->dump( entry->ptr, 0 ); + } +} + +/* close a handle */ +DECL_HANDLER(close_handle) +{ + close_handle( current->process, req->handle ); + send_reply( current, -1, 0 ); +} + +/* get information about a handle */ +DECL_HANDLER(get_handle_info) +{ + struct get_handle_info_reply reply; + reply.flags = set_handle_info( current->process, req->handle, 0, 0 ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* set a handle information */ +DECL_HANDLER(set_handle_info) +{ + set_handle_info( current->process, req->handle, req->mask, req->flags ); + send_reply( current, -1, 0 ); +} + +/* duplicate a handle */ +DECL_HANDLER(dup_handle) +{ + struct dup_handle_reply reply = { -1 }; + struct process *src, *dst; + + if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE ))) + { + if (req->options & DUP_HANDLE_MAKE_GLOBAL) + { + reply.handle = duplicate_handle( src, req->src_handle, NULL, + req->access, req->inherit, req->options ); + } + else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE ))) + { + reply.handle = duplicate_handle( src, req->src_handle, dst, + req->access, req->inherit, req->options ); + release_object( dst ); + } + /* close the handle no matter what happened */ + if (req->options & DUP_HANDLE_CLOSE_SOURCE) + close_handle( src, req->src_handle ); + release_object( src ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} diff --git a/server/handle.h b/server/handle.h new file mode 100644 index 00000000000..cb991e81139 --- /dev/null +++ b/server/handle.h @@ -0,0 +1,43 @@ +/* + * Server-side handle definitions + * + * Copyright (C) 1999 Alexandre Julliard + */ + +#ifndef __WINE_SERVER_HANDLE_H +#define __WINE_SERVER_HANDLE_H + +#ifndef __WINE_SERVER__ +#error This file can only be used in the Wine server +#endif + +struct process; +struct object_ops; +struct handle_entry; + +/* handle structures */ + +struct handle_table +{ + int count; + int last; + struct handle_entry *entries; +}; + +/* handle functions */ + +/* alloc_handle takes a void *obj for convenience, but you better make sure */ +/* that the thing pointed to starts with a struct object... */ +extern int alloc_handle( struct process *process, void *obj, + unsigned int access, int inherit ); +extern int close_handle( struct process *process, int handle ); +extern struct object *get_handle_obj( struct process *process, int handle, + unsigned int access, const struct object_ops *ops ); +extern int duplicate_handle( struct process *src, int src_handle, struct process *dst, + unsigned int access, int inherit, int options ); +extern int open_object( const char *name, const struct object_ops *ops, + unsigned int access, int inherit ); +extern int copy_handle_table( struct process *process, struct process *parent ); +extern void free_handles( struct process *process ); + +#endif /* __WINE_SERVER_HANDLE_H */ diff --git a/server/main.c b/server/main.c index e7190c96525..31cb48867b6 100644 --- a/server/main.c +++ b/server/main.c @@ -11,8 +11,8 @@ #include #include "server.h" -#include "server/object.h" -#include "server/thread.h" +#include "object.h" +#include "thread.h" int main( int argc, char *argv[] ) { diff --git a/server/mapping.c b/server/mapping.c index acacbb6431b..06091189a08 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -12,8 +12,10 @@ #include "config.h" #include "winerror.h" #include "winnt.h" -#include "server/process.h" -#include "server/thread.h" +#include "winbase.h" + +#include "handle.h" +#include "thread.h" struct mapping { @@ -79,8 +81,8 @@ static void init_page_size(void) (((int)(size) + ((int)(addr) & page_mask) + page_mask) & ~page_mask) -struct object *create_mapping( int size_high, int size_low, int protect, - int handle, const char *name ) +static struct object *create_mapping( int size_high, int size_low, int protect, + int handle, const char *name ) { struct mapping *mapping; int access = 0; @@ -131,12 +133,7 @@ struct object *create_mapping( int size_high, int size_low, int protect, return NULL; } -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 ) +static int get_mapping_info( int handle, struct get_mapping_info_reply *reply ) { struct mapping *mapping; int fd; @@ -169,3 +166,43 @@ static void mapping_destroy( struct object *obj ) if (mapping->file) release_object( mapping->file ); free( mapping ); } + +/* 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, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* open a handle to a mapping */ +DECL_HANDLER(open_mapping) +{ + struct open_mapping_reply reply; + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "open_mapping", name, len ); + + reply.handle = open_object( name, &mapping_ops, req->access, req->inherit ); + 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) ); +} diff --git a/server/mutex.c b/server/mutex.c index 1127de2f6b8..2adaacb2500 100644 --- a/server/mutex.c +++ b/server/mutex.c @@ -10,8 +10,9 @@ #include "winerror.h" #include "winnt.h" -#include "server/process.h" -#include "server/thread.h" + +#include "handle.h" +#include "thread.h" struct mutex { @@ -43,7 +44,7 @@ static const struct object_ops mutex_ops = }; -struct object *create_mutex( const char *name, int owned ) +static struct object *create_mutex( const char *name, int owned ) { struct mutex *mutex; @@ -61,11 +62,6 @@ struct object *create_mutex( const char *name, int owned ) return &mutex->obj; } -int open_mutex( unsigned int access, int inherit, const char *name ) -{ - return open_object( name, &mutex_ops, access, inherit ); -} - /* release a mutex once the recursion count is 0 */ static void do_release( struct mutex *mutex, struct thread *thread ) { @@ -79,7 +75,7 @@ static void do_release( struct mutex *mutex, struct thread *thread ) wake_up( &mutex->obj, 0 ); } -int release_mutex( int handle ) +static int release_mutex( int handle ) { struct mutex *mutex; @@ -148,3 +144,40 @@ static void mutex_destroy( struct object *obj ) assert( obj->ops == &mutex_ops ); free( mutex ); } + +/* create a mutex */ +DECL_HANDLER(create_mutex) +{ + struct create_mutex_reply reply = { -1 }; + struct object *obj; + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "create_mutex", name, len ); + + obj = create_mutex( name, req->owned ); + if (obj) + { + reply.handle = alloc_handle( current->process, obj, MUTEX_ALL_ACCESS, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* open a handle to a mutex */ +DECL_HANDLER(open_mutex) +{ + struct open_mutex_reply reply; + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "open_mutex", name, len ); + + reply.handle = open_object( name, &mutex_ops, req->access, req->inherit ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* release a mutex */ +DECL_HANDLER(release_mutex) +{ + if (release_mutex( req->handle )) CLEAR_ERROR(); + send_reply( current, -1, 0 ); +} diff --git a/server/object.c b/server/object.c index 4a40ac5936f..b907af3e2bb 100644 --- a/server/object.c +++ b/server/object.c @@ -11,8 +11,7 @@ #include #include "winerror.h" -#include "server.h" -#include "server/thread.h" +#include "thread.h" int debug_level = 0; diff --git a/include/server/object.h b/server/object.h similarity index 63% rename from include/server/object.h rename to server/object.h index 933afe7bb54..48c27991d02 100644 --- a/include/server/object.h +++ b/server/object.h @@ -81,6 +81,7 @@ extern void default_select_event( int fd, int event, void *private ); struct iovec; struct thread; +extern void fatal_protocol_error( const char *err, ... ); extern void call_req_handler( struct thread *thread, enum request req, void *data, int len, int fd ); extern void call_timeout_handler( struct thread *thread ); @@ -91,6 +92,11 @@ extern void trace_timeout(void); extern void trace_kill( int exit_code ); extern void trace_reply( struct thread *thread, int type, int pass_fd, struct iovec *vec, int veclen ); +/* check that the string is NULL-terminated and that the len is correct */ +#define CHECK_STRING(func,str,len) \ + do { if (((str)[(len)-1] || strlen(str) != (len)-1)) \ + fatal_protocol_error( "%s: invalid string '%.*s'\n", (func), (len), (str) ); \ + } while(0) /* select functions */ @@ -118,88 +124,22 @@ extern void set_timeout( int client_fd, struct timeval *when ); extern int send_reply_v( int client_fd, int type, int pass_fd, struct iovec *vec, int veclen ); -/* event functions */ - -extern struct object *create_event( const char *name, int manual_reset, int initial_state ); -extern int open_event( unsigned int access, int inherit, const char *name ); -extern int pulse_event( int handle ); -extern int set_event( int handle ); -extern int reset_event( int handle ); - - /* mutex functions */ -extern struct object *create_mutex( const char *name, int owned ); -extern int open_mutex( unsigned int access, int inherit, const char *name ); -extern int release_mutex( int handle ); extern void abandon_mutexes( struct thread *thread ); - -/* semaphore functions */ - -extern struct object *create_semaphore( const char *name, unsigned int initial, unsigned int max ); -extern int open_semaphore( unsigned int access, int inherit, const char *name ); -extern int release_semaphore( int handle, unsigned int count, unsigned int *prev_count ); - - /* file functions */ -extern struct object *create_file( int fd, const char *name, unsigned int access, - unsigned int sharing, int create, unsigned int attrs ); 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 grow_file( struct file *file, int size_high, int size_low ); extern struct file *create_temp_file( int access ); -extern int set_file_time( int handle, time_t access_time, time_t write_time ); -extern int file_lock( struct file *file, int offset_high, int offset_low, - int count_high, int count_low ); -extern int file_unlock( struct file *file, int offset_high, int offset_low, - int count_high, int count_low ); extern void file_set_error(void); - -/* pipe functions */ - -extern int create_pipe( struct object *obj[2] ); - - /* console functions */ -struct tagINPUT_RECORD; extern int create_console( int fd, struct object *obj[2] ); -extern int set_console_fd( int handle, int fd, int pid ); -extern int get_console_mode( int handle, int *mode ); -extern int set_console_mode( int handle, int mode ); -extern int set_console_info( int handle, struct set_console_info_request *req, - const char *title ); -extern int get_console_info( int handle, struct get_console_info_reply *reply, - const char **title ); -extern int write_console_input( int handle, int count, struct tagINPUT_RECORD *records ); -extern int read_console_input( int handle, int count, int flush ); - - -/* change notification functions */ - -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 ); - - -/* device functions */ -extern struct object *create_device( int id ); - - -/* snapshot functions */ -extern struct object *create_snapshot( int flags ); -extern int snapshot_next_process( int handle, int reset, struct next_process_reply *reply ); extern int debug_level; diff --git a/server/pipe.c b/server/pipe.c index 06260f911b3..575f6f25413 100644 --- a/server/pipe.c +++ b/server/pipe.c @@ -18,7 +18,9 @@ #include "winerror.h" #include "winbase.h" -#include "server/thread.h" + +#include "handle.h" +#include "thread.h" enum side { READ_SIDE, WRITE_SIDE }; @@ -59,7 +61,7 @@ static const struct select_ops select_ops = NULL /* we never set a timeout on a pipe */ }; -int create_pipe( struct object *obj[2] ) +static int create_pipe( struct object *obj[2] ) { struct pipe *newpipe[2]; int fd[2]; @@ -200,3 +202,27 @@ static void pipe_destroy( struct object *obj ) close( pipe->fd ); free( pipe ); } + +/* create an anonymous pipe */ +DECL_HANDLER(create_pipe) +{ + struct create_pipe_reply reply = { -1, -1 }; + struct object *obj[2]; + if (create_pipe( obj )) + { + reply.handle_read = alloc_handle( current->process, obj[0], + STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ, + req->inherit ); + if (reply.handle_read != -1) + { + reply.handle_write = alloc_handle( current->process, obj[1], + STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE, + req->inherit ); + if (reply.handle_write == -1) + close_handle( current->process, reply.handle_read ); + } + release_object( obj[0] ); + release_object( obj[1] ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} diff --git a/server/process.c b/server/process.c index 61273f0e319..6d435aaa733 100644 --- a/server/process.c +++ b/server/process.c @@ -17,37 +17,19 @@ #include "winnt.h" #include "server.h" -#include "server/process.h" -#include "server/thread.h" - -/* reserved handle access rights */ -#define RESERVED_SHIFT 25 -#define RESERVED_INHERIT (HANDLE_FLAG_INHERIT << RESERVED_SHIFT) -#define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE << RESERVED_SHIFT) -#define RESERVED_ALL (RESERVED_INHERIT | RESERVED_CLOSE_PROTECT) - -/* global handle macros */ -#define HANDLE_OBFUSCATOR 0x544a4def -#define HANDLE_IS_GLOBAL(h) (((h) ^ HANDLE_OBFUSCATOR) < 0x10000) -#define HANDLE_LOCAL_TO_GLOBAL(h) ((h) ^ HANDLE_OBFUSCATOR) -#define HANDLE_GLOBAL_TO_LOCAL(h) ((h) ^ HANDLE_OBFUSCATOR) - -struct handle_entry -{ - struct object *ptr; - unsigned int access; -}; +#include "handle.h" +#include "process.h" +#include "thread.h" /* process structure */ + struct process { struct object obj; /* object header */ struct process *next; /* system-wide process list */ struct process *prev; struct thread *thread_list; /* head of the thread list */ - struct handle_entry *entries; /* handle entry table */ - int handle_count; /* nb of allocated handle entries */ - int handle_last; /* last used handle entry */ + struct handle_table handles; /* handle table */ int exit_code; /* process exit code */ int running_threads; /* number of threads running in this process */ struct timeval start_time; /* absolute time at process start */ @@ -59,20 +41,15 @@ struct process struct new_process_request *info; /* startup info (freed after startup) */ }; - static struct process initial_process; static struct process *first_process = &initial_process; static int running_processes; -#define MIN_HANDLE_ENTRIES 32 - /* process operations */ static void process_dump( struct object *obj, int verbose ); static int process_signaled( struct object *obj, struct thread *thread ); static void process_destroy( struct object *obj ); -static void free_handles( struct process *process ); -static int copy_handle_table( struct process *process, struct process *parent ); static const struct object_ops process_ops = { @@ -133,7 +110,7 @@ struct process *create_initial_process(void) } /* create a new process */ -struct process *create_process( struct new_process_request *req ) +static struct process *create_process( struct new_process_request *req ) { struct process *process = NULL; struct process *parent = current->process; @@ -223,8 +200,14 @@ struct process *get_process_from_handle( int handle, unsigned int access ) access, &process_ops ); } +/* get a pointer to the process handle table */ +struct handle_table *get_process_handles( struct process *process ) +{ + return &process->handles; +} + /* retrieve the initialization info for a new process */ -int get_process_init_info( struct process *process, struct init_process_reply *reply ) +static int get_process_init_info( struct process *process, struct init_process_reply *reply ) { struct new_process_request *info; if (!(info = process->info)) return 0; @@ -248,25 +231,6 @@ static void process_killed( struct process *process, int exit_code ) free_handles( process ); } -/* free the process handle entries */ -static void free_handles( struct process *process ) -{ - struct handle_entry *entry; - int handle; - - if (!(entry = process->entries)) return; - for (handle = 0; handle <= process->handle_last; handle++, entry++) - { - struct object *obj = entry->ptr; - entry->ptr = NULL; - if (obj) release_object( obj ); - } - free( process->entries ); - process->handle_count = 0; - process->handle_last = -1; - process->entries = NULL; -} - /* add a thread to a process running threads list */ void add_process_thread( struct process *process, struct thread *thread ) { @@ -297,268 +261,16 @@ void remove_process_thread( struct process *process, struct thread *thread ) release_object( thread ); } -/* grow a handle table */ -/* return 1 if OK, 0 on error */ -static int grow_handle_table( struct process *process ) -{ - struct handle_entry *new_entries; - int count = process->handle_count; - - if (count >= INT_MAX / 2) return 0; - count *= 2; - if (!(new_entries = realloc( process->entries, count * sizeof(struct handle_entry) ))) - { - SET_ERROR( ERROR_OUTOFMEMORY ); - return 0; - } - process->handle_count = count; - process->entries = new_entries; - return 1; -} - -/* allocate a handle for an object, incrementing its refcount */ -/* return the handle, or -1 on error */ -int alloc_handle( struct process *process, void *obj, unsigned int access, - int inherit ) -{ - struct handle_entry *entry; - int handle; - - assert( !(access & RESERVED_ALL) ); - if (inherit) access |= RESERVED_INHERIT; - - /* find the first free entry */ - - if (!(entry = process->entries)) return -1; - for (handle = 0; handle <= process->handle_last; handle++, entry++) - if (!entry->ptr) goto found; - - if (handle >= process->handle_count) - { - if (!grow_handle_table( process )) return -1; - entry = process->entries + handle; /* the table may have moved */ - } - process->handle_last = handle; - - found: - entry->ptr = grab_object( obj ); - entry->access = access; - return handle + 1; /* avoid handle 0 */ -} - -/* return an handle entry, or NULL if the handle is invalid */ -static struct handle_entry *get_handle( struct process *process, int handle ) -{ - struct handle_entry *entry; - - if (HANDLE_IS_GLOBAL(handle)) - { - handle = HANDLE_GLOBAL_TO_LOCAL(handle); - process = &initial_process; - } - handle--; /* handles start at 1 */ - if ((handle < 0) || (handle > process->handle_last)) goto error; - entry = process->entries + handle; - if (!entry->ptr) goto error; - return entry; - - error: - SET_ERROR( ERROR_INVALID_HANDLE ); - return NULL; -} - -/* attempt to shrink a table */ -/* return 1 if OK, 0 on error */ -static int shrink_handle_table( struct process *process ) -{ - struct handle_entry *new_entries; - struct handle_entry *entry = process->entries + process->handle_last; - int count = process->handle_count; - - while (process->handle_last >= 0) - { - if (entry->ptr) break; - process->handle_last--; - entry--; - } - if (process->handle_last >= count / 4) return 1; /* no need to shrink */ - if (count < MIN_HANDLE_ENTRIES * 2) return 1; /* too small to shrink */ - count /= 2; - if (!(new_entries = realloc( process->entries, - count * sizeof(struct handle_entry) ))) - return 0; - process->handle_count = count; - process->entries = new_entries; - return 1; -} - -/* copy the handle table of the parent process */ -/* return 1 if OK, 0 on error */ -static int copy_handle_table( struct process *process, struct process *parent ) -{ - struct handle_entry *ptr; - int i, count, last; - - if (!parent) /* first process */ - { - count = MIN_HANDLE_ENTRIES; - last = -1; - } - else - { - assert( parent->entries ); - count = parent->handle_count; - last = parent->handle_last; - } - - if (!(ptr = mem_alloc( count * sizeof(struct handle_entry)))) return 0; - process->entries = ptr; - process->handle_count = count; - process->handle_last = last; - - if (last >= 0) - { - memcpy( ptr, parent->entries, (last + 1) * sizeof(struct handle_entry) ); - for (i = 0; i <= last; i++, ptr++) - { - if (!ptr->ptr) continue; - if (ptr->access & RESERVED_INHERIT) grab_object( ptr->ptr ); - else ptr->ptr = NULL; /* don't inherit this entry */ - } - } - /* attempt to shrink the table */ - shrink_handle_table( process ); - return 1; -} - -/* close a handle and decrement the refcount of the associated object */ -/* return 1 if OK, 0 on error */ -int close_handle( struct process *process, int handle ) -{ - struct handle_entry *entry; - struct object *obj; - - if (HANDLE_IS_GLOBAL(handle)) - { - handle = HANDLE_GLOBAL_TO_LOCAL(handle); - process = &initial_process; - } - if (!(entry = get_handle( process, handle ))) return 0; - if (entry->access & RESERVED_CLOSE_PROTECT) return 0; /* FIXME: error code */ - obj = entry->ptr; - entry->ptr = NULL; - if (handle-1 == process->handle_last) shrink_handle_table( process ); - release_object( obj ); - return 1; -} - -/* retrieve the object corresponding to a handle, incrementing its refcount */ -struct object *get_handle_obj( struct process *process, int handle, - unsigned int access, const struct object_ops *ops ) -{ - struct handle_entry *entry; - struct object *obj; - - switch( handle ) - { - case 0xfffffffe: /* current thread pseudo-handle */ - obj = ¤t->obj; - break; - case 0x7fffffff: /* current process pseudo-handle */ - obj = (struct object *)current->process; - break; - default: - if (!(entry = get_handle( process, handle ))) return NULL; - if ((entry->access & access) != access) - { - SET_ERROR( ERROR_ACCESS_DENIED ); - return NULL; - } - obj = entry->ptr; - break; - } - if (ops && (obj->ops != ops)) - { - SET_ERROR( ERROR_INVALID_HANDLE ); /* not the right type */ - return NULL; - } - return grab_object( obj ); -} - -/* get/set the handle reserved flags */ -/* return the new flags (or -1 on error) */ -int set_handle_info( struct process *process, int handle, int mask, int flags ) -{ - struct handle_entry *entry; - - if (!(entry = get_handle( process, handle ))) return -1; - mask = (mask << RESERVED_SHIFT) & RESERVED_ALL; - flags = (flags << RESERVED_SHIFT) & mask; - entry->access = (entry->access & ~mask) | flags; - return (entry->access & RESERVED_ALL) >> RESERVED_SHIFT; -} - -/* duplicate a handle */ -int duplicate_handle( struct process *src, int src_handle, struct process *dst, - unsigned int access, int inherit, int options ) -{ - int res; - struct handle_entry *entry = get_handle( src, src_handle ); - if (!entry) return -1; - - if (options & DUP_HANDLE_SAME_ACCESS) access = entry->access; - if (options & DUP_HANDLE_MAKE_GLOBAL) dst = &initial_process; - access &= ~RESERVED_ALL; - res = alloc_handle( dst, entry->ptr, access, inherit ); - if (options & DUP_HANDLE_MAKE_GLOBAL) res = HANDLE_LOCAL_TO_GLOBAL(res); - return res; -} - -/* open a new handle to an existing object */ -int open_object( const char *name, const struct object_ops *ops, - unsigned int access, int inherit ) -{ - struct object *obj = find_object( name ); - if (!obj) - { - SET_ERROR( ERROR_FILE_NOT_FOUND ); - return -1; - } - if (ops && obj->ops != ops) - { - release_object( obj ); - SET_ERROR( ERROR_INVALID_HANDLE ); /* FIXME: not the right type */ - return -1; - } - return alloc_handle( current->process, obj, access, inherit ); -} - -/* dump a handle table on stdout */ -void dump_handles( struct process *process ) -{ - struct handle_entry *entry; - int i; - - if (!process->entries) return; - entry = process->entries; - for (i = 0; i <= process->handle_last; i++, entry++) - { - if (!entry->ptr) continue; - printf( "%5d: %p %08x ", i + 1, entry->ptr, entry->access ); - entry->ptr->ops->dump( entry->ptr, 0 ); - } -} - /* kill a process on the spot */ -void kill_process( struct process *process, int exit_code ) +static void kill_process( struct process *process, int exit_code ) { while (process->thread_list) kill_thread( process->thread_list, exit_code ); } /* get all information about a process */ -void get_process_info( struct process *process, - struct get_process_info_reply *reply ) +static void get_process_info( struct process *process, + struct get_process_info_reply *reply ) { reply->pid = process; reply->exit_code = process->exit_code; @@ -568,8 +280,8 @@ void get_process_info( struct process *process, } /* set all information about a process */ -void set_process_info( struct process *process, - struct set_process_info_request *req ) +static void set_process_info( struct process *process, + struct set_process_info_request *req ) { if (req->mask & SET_PROCESS_INFO_PRIORITY) process->priority = req->priority; @@ -634,3 +346,95 @@ struct process_snapshot *process_snap( int *count ) *count = running_processes; return snapshot; } + +/* create a new process */ +DECL_HANDLER(new_process) +{ + struct new_process_reply reply; + struct process *process; + + if ((process = create_process( req ))) + { + reply.pid = process; + reply.handle = alloc_handle( current->process, process, + PROCESS_ALL_ACCESS, req->inherit ); + release_object( process ); + } + else + { + reply.handle = -1; + reply.pid = NULL; + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* initialize a new process */ +DECL_HANDLER(init_process) +{ + struct init_process_reply reply; + if (current->state != RUNNING) + { + fatal_protocol_error( "init_process: init_thread not called yet\n" ); + return; + } + if (!get_process_init_info( current->process, &reply )) + { + fatal_protocol_error( "init_process: called twice\n" ); + return; + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* open a handle to a process */ +DECL_HANDLER(open_process) +{ + struct open_process_reply reply = { -1 }; + struct process *process = get_process_from_id( req->pid ); + if (process) + { + reply.handle = alloc_handle( current->process, process, + req->access, req->inherit ); + release_object( process ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* terminate a process */ +DECL_HANDLER(terminate_process) +{ + struct process *process; + + if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE ))) + { + kill_process( process, req->exit_code ); + release_object( process ); + } + if (current) send_reply( current, -1, 0 ); +} + +/* fetch information about a process */ +DECL_HANDLER(get_process_info) +{ + struct process *process; + struct get_process_info_reply reply = { 0, 0, 0 }; + + if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION ))) + { + get_process_info( process, &reply ); + release_object( process ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* set information about a process */ +DECL_HANDLER(set_process_info) +{ + struct process *process; + + if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION ))) + { + set_process_info( process, req ); + release_object( process ); + } + send_reply( current, -1, 0 ); +} diff --git a/server/process.h b/server/process.h new file mode 100644 index 00000000000..341444315b3 --- /dev/null +++ b/server/process.h @@ -0,0 +1,44 @@ +/* + * Wine server processes + * + * Copyright (C) 1999 Alexandre Julliard + */ + +#ifndef __WINE_SERVER_PROCESS_H +#define __WINE_SERVER_PROCESS_H + +#ifndef __WINE_SERVER__ +#error This file can only be used in the Wine server +#endif + +#include "object.h" + +/* process structures */ + +struct process; +struct handle_table; + +struct process_snapshot +{ + struct process *process; /* process ptr */ + struct process *parent; /* process parent */ + int threads; /* number of threads */ + int priority; /* priority class */ +}; + +/* process functions */ + +extern struct process *create_initial_process(void); +extern struct process *get_process_from_id( void *id ); +extern struct process *get_process_from_handle( int handle, unsigned int access ); +extern struct handle_table *get_process_handles( struct process *process ); +extern void add_process_thread( struct process *process, + struct thread *thread ); +extern void remove_process_thread( struct process *process, + struct thread *thread ); +extern int alloc_console( struct process *process ); +extern int free_console( struct process *process ); +extern struct object *get_console( struct process *process, int output ); +extern struct process_snapshot *process_snap( int *count ); + +#endif /* __WINE_SERVER_PROCESS_H */ diff --git a/server/request.c b/server/request.c index 49b9f5a972b..cb99777a292 100644 --- a/server/request.c +++ b/server/request.c @@ -20,20 +20,12 @@ #include "wincon.h" #define WANT_REQUEST_HANDLERS #include "server.h" -#include "server/request.h" -#include "server/process.h" -#include "server/thread.h" - -/* check that the string is NULL-terminated and that the len is correct */ -#define CHECK_STRING(func,str,len) \ - do { if (((str)[(len)-1] || strlen(str) != (len)-1)) \ - fatal_protocol_error( "%s: invalid string '%.*s'\n", (func), (len), (str) ); \ - } while(0) +#include "thread.h" struct thread *current = NULL; /* thread handling the current request */ /* complain about a protocol error and terminate the client connection */ -static void fatal_protocol_error( const char *err, ... ) +void fatal_protocol_error( const char *err, ... ) { va_list args; @@ -60,7 +52,7 @@ void call_req_handler( struct thread *thread, enum request req, if (len < handler->min_size) { - fatal_protocol_error( "req %d bad length %d < %d)\n", req, len, handler->min_size ); + fatal_protocol_error( "req %d bad length %d < %d\n", req, len, handler->min_size ); return; } @@ -100,82 +92,6 @@ void call_kill_handler( struct thread *thread, int exit_code ) current = (old_current != thread) ? old_current : NULL; } - -/* create a new process */ -DECL_HANDLER(new_process) -{ - struct new_process_reply reply; - struct process *process; - - if ((process = create_process( req ))) - { - reply.pid = process; - reply.handle = alloc_handle( current->process, process, - PROCESS_ALL_ACCESS, req->inherit ); - release_object( process ); - } - else - { - reply.handle = -1; - reply.pid = NULL; - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* create a new thread */ -DECL_HANDLER(new_thread) -{ - struct new_thread_reply reply; - int new_fd; - - if ((new_fd = dup(fd)) != -1) - { - reply.tid = create_thread( new_fd, req->pid, req->suspend, - req->inherit, &reply.handle ); - if (!reply.tid) close( new_fd ); - } - else - SET_ERROR( ERROR_TOO_MANY_OPEN_FILES ); - - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* initialize a new process */ -DECL_HANDLER(init_process) -{ - struct init_process_reply reply; - if (current->state != RUNNING) - { - fatal_protocol_error( "init_process: init_thread not called yet\n" ); - return; - } - if (!get_process_init_info( current->process, &reply )) - { - fatal_protocol_error( "init_process: called twice\n" ); - return; - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* initialize a new thread */ -DECL_HANDLER(init_thread) -{ - struct init_thread_reply reply; - - if (current->state != STARTING) - { - fatal_protocol_error( "init_thread: already running\n" ); - return; - } - current->state = RUNNING; - current->unix_pid = req->unix_pid; - if (current->suspend > 0) - kill( current->unix_pid, SIGSTOP ); - reply.pid = current->process; - reply.tid = current; - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - /* set the debug level */ DECL_HANDLER(set_debug) { @@ -186,135 +102,6 @@ DECL_HANDLER(set_debug) send_reply( current, -1, 0 ); } -/* terminate a process */ -DECL_HANDLER(terminate_process) -{ - struct process *process; - - if ((process = get_process_from_handle( req->handle, PROCESS_TERMINATE ))) - { - kill_process( process, req->exit_code ); - release_object( process ); - } - if (current) send_reply( current, -1, 0 ); -} - -/* terminate a thread */ -DECL_HANDLER(terminate_thread) -{ - struct thread *thread; - - if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE ))) - { - kill_thread( thread, req->exit_code ); - release_object( thread ); - } - if (current) send_reply( current, -1, 0 ); -} - -/* close a handle */ -DECL_HANDLER(close_handle) -{ - close_handle( current->process, req->handle ); - send_reply( current, -1, 0 ); -} - -/* get information about a handle */ -DECL_HANDLER(get_handle_info) -{ - struct get_handle_info_reply reply; - reply.flags = set_handle_info( current->process, req->handle, 0, 0 ); - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* set a handle information */ -DECL_HANDLER(set_handle_info) -{ - set_handle_info( current->process, req->handle, req->mask, req->flags ); - send_reply( current, -1, 0 ); -} - -/* duplicate a handle */ -DECL_HANDLER(dup_handle) -{ - struct dup_handle_reply reply = { -1 }; - struct process *src, *dst; - - if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE ))) - { - if (req->options & DUP_HANDLE_MAKE_GLOBAL) - { - reply.handle = duplicate_handle( src, req->src_handle, NULL, - req->access, req->inherit, req->options ); - } - else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE ))) - { - reply.handle = duplicate_handle( src, req->src_handle, dst, - req->access, req->inherit, req->options ); - release_object( dst ); - } - /* close the handle no matter what happened */ - if (req->options & DUP_HANDLE_CLOSE_SOURCE) - close_handle( src, req->src_handle ); - release_object( src ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* fetch information about a process */ -DECL_HANDLER(get_process_info) -{ - struct process *process; - struct get_process_info_reply reply = { 0, 0, 0 }; - - if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION ))) - { - get_process_info( process, &reply ); - release_object( process ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* set information about a process */ -DECL_HANDLER(set_process_info) -{ - struct process *process; - - if ((process = get_process_from_handle( req->handle, PROCESS_SET_INFORMATION ))) - { - set_process_info( process, req ); - release_object( process ); - } - send_reply( current, -1, 0 ); -} - -/* fetch information about a thread */ -DECL_HANDLER(get_thread_info) -{ - struct thread *thread; - struct get_thread_info_reply reply = { 0, 0 }; - - if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION ))) - { - get_thread_info( thread, &reply ); - release_object( thread ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* set information about a thread */ -DECL_HANDLER(set_thread_info) -{ - struct thread *thread; - - if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION ))) - { - set_thread_info( thread, req ); - release_object( thread ); - } - send_reply( current, -1, 0 ); -} - /* debugger support operations */ DECL_HANDLER(debugger) { @@ -331,505 +118,3 @@ DECL_HANDLER(debugger) send_reply( current, -1, 0 ); } - -/* suspend a thread */ -DECL_HANDLER(suspend_thread) -{ - struct thread *thread; - struct suspend_thread_reply reply = { -1 }; - if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME ))) - { - reply.count = suspend_thread( thread ); - release_object( thread ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); - -} - -/* resume a thread */ -DECL_HANDLER(resume_thread) -{ - struct thread *thread; - struct resume_thread_reply reply = { -1 }; - if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME ))) - { - reply.count = resume_thread( thread ); - release_object( thread ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); - -} - -/* queue an APC for a thread */ -DECL_HANDLER(queue_apc) -{ - struct thread *thread; - if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) - { - thread_queue_apc( thread, req->func, req->param ); - release_object( thread ); - } - send_reply( current, -1, 0 ); -} - -/* open a handle to a process */ -DECL_HANDLER(open_process) -{ - struct open_process_reply reply = { -1 }; - struct process *process = get_process_from_id( req->pid ); - if (process) - { - reply.handle = alloc_handle( current->process, process, - req->access, req->inherit ); - release_object( process ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* select on a handle list */ -DECL_HANDLER(select) -{ - if (len != req->count * sizeof(int)) - fatal_protocol_error( "select: bad length %d for %d handles\n", - len, req->count ); - sleep_on( current, req->count, (int *)data, req->flags, req->timeout ); -} - -/* create an event */ -DECL_HANDLER(create_event) -{ - struct create_event_reply reply = { -1 }; - struct object *obj; - char *name = (char *)data; - if (!len) name = NULL; - else CHECK_STRING( "create_event", name, len ); - - obj = create_event( name, req->manual_reset, req->initial_state ); - if (obj) - { - reply.handle = alloc_handle( current->process, obj, EVENT_ALL_ACCESS, req->inherit ); - release_object( obj ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* do an event operation */ -DECL_HANDLER(event_op) -{ - switch(req->op) - { - case PULSE_EVENT: - pulse_event( req->handle ); - break; - case SET_EVENT: - set_event( req->handle ); - break; - case RESET_EVENT: - reset_event( req->handle ); - break; - default: - fatal_protocol_error( "event_op: invalid operation %d\n", req->op ); - } - send_reply( current, -1, 0 ); -} - -/* create a mutex */ -DECL_HANDLER(create_mutex) -{ - struct create_mutex_reply reply = { -1 }; - struct object *obj; - char *name = (char *)data; - if (!len) name = NULL; - else CHECK_STRING( "create_mutex", name, len ); - - obj = create_mutex( name, req->owned ); - if (obj) - { - reply.handle = alloc_handle( current->process, obj, MUTEX_ALL_ACCESS, req->inherit ); - release_object( obj ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* release a mutex */ -DECL_HANDLER(release_mutex) -{ - if (release_mutex( req->handle )) CLEAR_ERROR(); - send_reply( current, -1, 0 ); -} - -/* create a semaphore */ -DECL_HANDLER(create_semaphore) -{ - struct create_semaphore_reply reply = { -1 }; - struct object *obj; - char *name = (char *)data; - if (!len) name = NULL; - else CHECK_STRING( "create_semaphore", name, len ); - - obj = create_semaphore( name, req->initial, req->max ); - if (obj) - { - reply.handle = alloc_handle( current->process, obj, SEMAPHORE_ALL_ACCESS, req->inherit ); - release_object( obj ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* release a semaphore */ -DECL_HANDLER(release_semaphore) -{ - struct release_semaphore_reply reply; - if (release_semaphore( req->handle, req->count, &reply.prev_count )) CLEAR_ERROR(); - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* open a handle to a named object (event, mutex, semaphore) */ -DECL_HANDLER(open_named_obj) -{ - struct open_named_obj_reply reply; - char *name = (char *)data; - if (!len) name = NULL; - else CHECK_STRING( "open_named_obj", name, len ); - - switch(req->type) - { - case OPEN_EVENT: - reply.handle = open_event( req->access, req->inherit, name ); - break; - case OPEN_MUTEX: - reply.handle = open_mutex( req->access, req->inherit, name ); - break; - 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 ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* create a file */ -DECL_HANDLER(create_file) -{ - struct create_file_reply reply = { -1 }; - struct object *obj; - char *name = (char *)data; - if (!len) name = NULL; - else CHECK_STRING( "create_file", name, len ); - - if ((obj = create_file( fd, name, req->access, - req->sharing, req->create, req->attrs )) != NULL) - { - reply.handle = alloc_handle( current->process, obj, req->access, req->inherit ); - release_object( obj ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* get a Unix fd to read from a file */ -DECL_HANDLER(get_read_fd) -{ - struct object *obj; - int read_fd; - - if ((obj = get_handle_obj( current->process, req->handle, GENERIC_READ, NULL ))) - { - read_fd = obj->ops->get_read_fd( obj ); - release_object( obj ); - } - else read_fd = -1; - send_reply( current, read_fd, 0 ); -} - -/* get a Unix fd to write to a file */ -DECL_HANDLER(get_write_fd) -{ - struct object *obj; - int write_fd; - - if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL ))) - { - write_fd = obj->ops->get_write_fd( obj ); - release_object( obj ); - } - else write_fd = -1; - send_reply( current, write_fd, 0 ); -} - -/* set a file current position */ -DECL_HANDLER(set_file_pointer) -{ - struct set_file_pointer_reply reply; - reply.low = req->low; - reply.high = req->high; - set_file_pointer( req->handle, &reply.low, &reply.high, req->whence ); - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* truncate (or extend) a file */ -DECL_HANDLER(truncate_file) -{ - truncate_file( req->handle ); - send_reply( current, -1, 0 ); -} - -/* flush a file buffers */ -DECL_HANDLER(flush_file) -{ - struct object *obj; - - if ((obj = get_handle_obj( current->process, req->handle, GENERIC_WRITE, NULL ))) - { - obj->ops->flush( obj ); - release_object( obj ); - } - send_reply( current, -1, 0 ); -} - -/* set a file access and modification times */ -DECL_HANDLER(set_file_time) -{ - set_file_time( req->handle, req->access_time, req->write_time ); - send_reply( current, -1, 0 ); -} - -/* get a file information */ -DECL_HANDLER(get_file_info) -{ - struct object *obj; - struct get_file_info_reply reply; - - if ((obj = get_handle_obj( current->process, req->handle, 0, NULL ))) - { - obj->ops->get_file_info( obj, &reply ); - release_object( obj ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* lock a region of a file */ -DECL_HANDLER(lock_file) -{ - struct file *file; - - if ((file = get_file_obj( current->process, req->handle, 0 ))) - { - file_lock( file, req->offset_high, req->offset_low, - req->count_high, req->count_low ); - release_object( file ); - } - send_reply( current, -1, 0 ); -} - - -/* unlock a region of a file */ -DECL_HANDLER(unlock_file) -{ - struct file *file; - - if ((file = get_file_obj( current->process, req->handle, 0 ))) - { - file_unlock( file, req->offset_high, req->offset_low, - req->count_high, req->count_low ); - release_object( file ); - } - send_reply( current, -1, 0 ); -} - - -/* create an anonymous pipe */ -DECL_HANDLER(create_pipe) -{ - struct create_pipe_reply reply = { -1, -1 }; - struct object *obj[2]; - if (create_pipe( obj )) - { - reply.handle_read = alloc_handle( current->process, obj[0], - STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ, - req->inherit ); - if (reply.handle_read != -1) - { - reply.handle_write = alloc_handle( current->process, obj[1], - STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE, - req->inherit ); - if (reply.handle_write == -1) - close_handle( current->process, reply.handle_read ); - } - release_object( obj[0] ); - release_object( obj[1] ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* allocate a console for the current process */ -DECL_HANDLER(alloc_console) -{ - alloc_console( current->process ); - send_reply( current, -1, 0 ); -} - -/* free the console of the current process */ -DECL_HANDLER(free_console) -{ - free_console( current->process ); - send_reply( current, -1, 0 ); -} - -/* open a handle to the process console */ -DECL_HANDLER(open_console) -{ - struct object *obj; - struct open_console_reply reply = { -1 }; - if ((obj = get_console( current->process, req->output ))) - { - reply.handle = alloc_handle( current->process, obj, req->access, req->inherit ); - release_object( obj ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* set info about a console (output only) */ -DECL_HANDLER(set_console_info) -{ - char *name = (char *)data; - if (!len) name = NULL; - else CHECK_STRING( "set_console_info", name, len ); - set_console_info( req->handle, req, name ); - send_reply( current, -1, 0 ); -} - -/* get info about a console (output only) */ -DECL_HANDLER(get_console_info) -{ - struct get_console_info_reply reply; - const char *title; - get_console_info( req->handle, &reply, &title ); - send_reply( current, -1, 2, &reply, sizeof(reply), - title, title ? strlen(title)+1 : 0 ); -} - -/* set a console fd */ -DECL_HANDLER(set_console_fd) -{ - set_console_fd( req->handle, fd, req->pid ); - send_reply( current, -1, 0 ); -} - -/* get a console mode (input or output) */ -DECL_HANDLER(get_console_mode) -{ - struct get_console_mode_reply reply; - get_console_mode( req->handle, &reply.mode ); - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* set a console mode (input or output) */ -DECL_HANDLER(set_console_mode) -{ - set_console_mode( req->handle, req->mode ); - send_reply( current, -1, 0 ); -} - -/* add input records to a console input queue */ -DECL_HANDLER(write_console_input) -{ - struct write_console_input_reply reply; - INPUT_RECORD *records = (INPUT_RECORD *)data; - - if (len != req->count * sizeof(INPUT_RECORD)) - fatal_protocol_error( "write_console_input: bad length %d for %d records\n", - len, req->count ); - reply.written = write_console_input( req->handle, req->count, records ); - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* fetch input records from a console input queue */ -DECL_HANDLER(read_console_input) -{ - read_console_input( req->handle, req->count, req->flush ); -} - -/* create a change notification */ -DECL_HANDLER(create_change_notification) -{ - struct object *obj; - struct create_change_notification_reply reply = { -1 }; - - if ((obj = create_change_notification( req->subtree, req->filter ))) - { - reply.handle = alloc_handle( current->process, obj, - STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE, 0 ); - release_object( obj ); - } - 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, req->inherit ); - 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) ); -} - -/* create a device */ -DECL_HANDLER(create_device) -{ - struct object *obj; - struct create_device_reply reply = { -1 }; - - if ((obj = create_device( req->id ))) - { - reply.handle = alloc_handle( current->process, obj, - req->access, req->inherit ); - release_object( obj ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* create a snapshot */ -DECL_HANDLER(create_snapshot) -{ - struct object *obj; - struct create_snapshot_reply reply = { -1 }; - - if ((obj = create_snapshot( req->flags ))) - { - reply.handle = alloc_handle( current->process, obj, 0, req->inherit ); - release_object( obj ); - } - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - -/* get the next process from a snapshot */ -DECL_HANDLER(next_process) -{ - struct next_process_reply reply; - snapshot_next_process( req->handle, req->reset, &reply ); - send_reply( current, -1, 1, &reply, sizeof(reply) ); -} - diff --git a/server/select.c b/server/select.c index 4121eac9bd9..013ba715c49 100644 --- a/server/select.c +++ b/server/select.c @@ -15,7 +15,7 @@ #include #include -#include "server/object.h" +#include "object.h" /* select user fd */ struct user diff --git a/server/semaphore.c b/server/semaphore.c index ad92a6953da..5d297e40ec0 100644 --- a/server/semaphore.c +++ b/server/semaphore.c @@ -10,8 +10,9 @@ #include "winerror.h" #include "winnt.h" -#include "server/process.h" -#include "server/thread.h" + +#include "handle.h" +#include "thread.h" struct semaphore { @@ -40,7 +41,7 @@ static const struct object_ops semaphore_ops = }; -struct object *create_semaphore( const char *name, unsigned int initial, unsigned int max ) +static struct object *create_semaphore( const char *name, unsigned int initial, unsigned int max ) { struct semaphore *sem; @@ -60,12 +61,7 @@ struct object *create_semaphore( const char *name, unsigned int initial, unsigne return &sem->obj; } -int open_semaphore( unsigned int access, int inherit, const char *name ) -{ - return open_object( name, &semaphore_ops, access, inherit ); -} - -int release_semaphore( int handle, unsigned int count, unsigned int *prev_count ) +static int release_semaphore( int handle, unsigned int count, unsigned int *prev_count ) { struct semaphore *sem; @@ -124,3 +120,41 @@ static void semaphore_destroy( struct object *obj ) assert( obj->ops == &semaphore_ops ); free( sem ); } + +/* create a semaphore */ +DECL_HANDLER(create_semaphore) +{ + struct create_semaphore_reply reply = { -1 }; + struct object *obj; + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "create_semaphore", name, len ); + + obj = create_semaphore( name, req->initial, req->max ); + if (obj) + { + reply.handle = alloc_handle( current->process, obj, SEMAPHORE_ALL_ACCESS, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* open a handle to a semaphore */ +DECL_HANDLER(open_semaphore) +{ + struct open_semaphore_reply reply; + char *name = (char *)data; + if (!len) name = NULL; + else CHECK_STRING( "open_semaphore", name, len ); + + reply.handle = open_object( name, &semaphore_ops, req->access, req->inherit ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* release a semaphore */ +DECL_HANDLER(release_semaphore) +{ + struct release_semaphore_reply reply; + if (release_semaphore( req->handle, req->count, &reply.prev_count )) CLEAR_ERROR(); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} diff --git a/server/snapshot.c b/server/snapshot.c index ee189937658..c9e678a819c 100644 --- a/server/snapshot.c +++ b/server/snapshot.c @@ -13,8 +13,10 @@ #include "winerror.h" #include "winnt.h" #include "tlhelp32.h" -#include "server/process.h" -#include "server/thread.h" + +#include "handle.h" +#include "process.h" +#include "thread.h" struct snapshot @@ -44,7 +46,7 @@ static const struct object_ops snapshot_ops = /* create a new snapshot */ -struct object *create_snapshot( int flags ) +static struct object *create_snapshot( int flags ) { struct snapshot *snapshot; if (!(snapshot = mem_alloc( sizeof(*snapshot) ))) return NULL; @@ -59,7 +61,7 @@ struct object *create_snapshot( int flags ) } /* get the next process in the snapshot */ -int snapshot_next_process( int handle, int reset, struct next_process_reply *reply ) +static int snapshot_next_process( int handle, int reset, struct next_process_reply *reply ) { struct snapshot *snapshot; struct process_snapshot *ptr; @@ -108,3 +110,25 @@ static void snapshot_destroy( struct object *obj ) } free( snapshot ); } + +/* create a snapshot */ +DECL_HANDLER(create_snapshot) +{ + struct object *obj; + struct create_snapshot_reply reply = { -1 }; + + if ((obj = create_snapshot( req->flags ))) + { + reply.handle = alloc_handle( current->process, obj, 0, req->inherit ); + release_object( obj ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* get the next process from a snapshot */ +DECL_HANDLER(next_process) +{ + struct next_process_reply reply; + snapshot_next_process( req->handle, req->reset, &reply ); + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} diff --git a/server/socket.c b/server/socket.c index 371b10b06fb..7b2033d4bcf 100644 --- a/server/socket.c +++ b/server/socket.c @@ -18,8 +18,7 @@ #include "config.h" #include "server.h" - -#include "server/object.h" +#include "object.h" /* Some versions of glibc don't define this */ #ifndef SCM_RIGHTS diff --git a/server/thread.c b/server/thread.c index d184f04eea9..eff2b08cae1 100644 --- a/server/thread.c +++ b/server/thread.c @@ -18,9 +18,11 @@ #include "winbase.h" #include "winerror.h" + +#include "handle.h" #include "server.h" -#include "server/thread.h" -#include "server/process.h" +#include "process.h" +#include "thread.h" /* thread queues */ @@ -81,6 +83,7 @@ static void init_thread( struct thread *thread, int fd ) thread->client_fd = fd; thread->unix_pid = 0; /* not known yet */ thread->mutex = NULL; + thread->debugger = NULL; thread->wait = NULL; thread->apc = NULL; thread->apc_count = 0; @@ -107,7 +110,7 @@ void create_initial_thread( int fd ) } /* create a new thread */ -struct thread *create_thread( int fd, void *pid, int suspend, int inherit, int *handle ) +static struct thread *create_thread( int fd, void *pid, int suspend, int inherit, int *handle ) { struct thread *thread; struct process *process; @@ -192,19 +195,9 @@ struct thread *get_thread_from_handle( int handle, unsigned int access ) access, &thread_ops ); } -/* get all information about a thread */ -void get_thread_info( struct thread *thread, - struct get_thread_info_reply *reply ) -{ - reply->tid = thread; - reply->exit_code = thread->exit_code; - reply->priority = thread->priority; -} - - /* set all information about a thread */ -void set_thread_info( struct thread *thread, - struct set_thread_info_request *req ) +static void set_thread_info( struct thread *thread, + struct set_thread_info_request *req ) { if (req->mask & SET_THREAD_INFO_PRIORITY) thread->priority = req->priority; @@ -216,7 +209,7 @@ void set_thread_info( struct thread *thread, } /* suspend a thread */ -int suspend_thread( struct thread *thread ) +static int suspend_thread( struct thread *thread ) { int old_count = thread->suspend; if (thread->suspend < MAXIMUM_SUSPEND_COUNT) @@ -230,7 +223,7 @@ int suspend_thread( struct thread *thread ) } /* resume a thread */ -int resume_thread( struct thread *thread ) +static int resume_thread( struct thread *thread ) { int old_count = thread->suspend; if (thread->suspend > 0) @@ -456,7 +449,7 @@ static int wake_thread( struct thread *thread ) } /* sleep on a list of objects */ -void sleep_on( struct thread *thread, int count, int *handles, int flags, int timeout ) +static void sleep_on( struct thread *thread, int count, int *handles, int flags, int timeout ) { assert( !thread->wait ); if (!wait_on( thread, count, handles, flags, timeout )) @@ -498,7 +491,7 @@ void wake_up( struct object *obj, int max ) } /* queue an async procedure call */ -int thread_queue_apc( struct thread *thread, void *func, void *param ) +static int thread_queue_apc( struct thread *thread, void *func, void *param ) { struct thread_apc *apc; if (!thread->apc) @@ -534,3 +527,130 @@ void thread_killed( struct thread *thread, int exit_code ) wake_up( &thread->obj, 0 ); release_object( thread ); } + +/* create a new thread */ +DECL_HANDLER(new_thread) +{ + struct new_thread_reply reply; + int new_fd; + + if ((new_fd = dup(fd)) != -1) + { + reply.tid = create_thread( new_fd, req->pid, req->suspend, + req->inherit, &reply.handle ); + if (!reply.tid) close( new_fd ); + } + else + SET_ERROR( ERROR_TOO_MANY_OPEN_FILES ); + + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* initialize a new thread */ +DECL_HANDLER(init_thread) +{ + struct init_thread_reply reply; + + if (current->state != STARTING) + { + fatal_protocol_error( "init_thread: already running\n" ); + return; + } + current->state = RUNNING; + current->unix_pid = req->unix_pid; + if (current->suspend > 0) kill( current->unix_pid, SIGSTOP ); + reply.pid = current->process; + reply.tid = current; + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* terminate a thread */ +DECL_HANDLER(terminate_thread) +{ + struct thread *thread; + + if ((thread = get_thread_from_handle( req->handle, THREAD_TERMINATE ))) + { + kill_thread( thread, req->exit_code ); + release_object( thread ); + } + if (current) send_reply( current, -1, 0 ); +} + +/* fetch information about a thread */ +DECL_HANDLER(get_thread_info) +{ + struct thread *thread; + struct get_thread_info_reply reply = { 0, 0, 0 }; + + if ((thread = get_thread_from_handle( req->handle, THREAD_QUERY_INFORMATION ))) + { + reply.tid = thread; + reply.exit_code = thread->exit_code; + reply.priority = thread->priority; + release_object( thread ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); +} + +/* set information about a thread */ +DECL_HANDLER(set_thread_info) +{ + struct thread *thread; + + if ((thread = get_thread_from_handle( req->handle, THREAD_SET_INFORMATION ))) + { + set_thread_info( thread, req ); + release_object( thread ); + } + send_reply( current, -1, 0 ); +} + +/* suspend a thread */ +DECL_HANDLER(suspend_thread) +{ + struct thread *thread; + struct suspend_thread_reply reply = { -1 }; + if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME ))) + { + reply.count = suspend_thread( thread ); + release_object( thread ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); + +} + +/* resume a thread */ +DECL_HANDLER(resume_thread) +{ + struct thread *thread; + struct resume_thread_reply reply = { -1 }; + if ((thread = get_thread_from_handle( req->handle, THREAD_SUSPEND_RESUME ))) + { + reply.count = resume_thread( thread ); + release_object( thread ); + } + send_reply( current, -1, 1, &reply, sizeof(reply) ); + +} + +/* select on a handle list */ +DECL_HANDLER(select) +{ + if (len != req->count * sizeof(int)) + fatal_protocol_error( "select: bad length %d for %d handles\n", + len, req->count ); + sleep_on( current, req->count, (int *)data, req->flags, req->timeout ); +} + +/* queue an APC for a thread */ +DECL_HANDLER(queue_apc) +{ + struct thread *thread; + if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) + { + thread_queue_apc( thread, req->func, req->param ); + release_object( thread ); + } + send_reply( current, -1, 0 ); +} diff --git a/include/server/thread.h b/server/thread.h similarity index 79% rename from include/server/thread.h rename to server/thread.h index bc77a37dc4e..fed1d185663 100644 --- a/include/server/thread.h +++ b/server/thread.h @@ -11,7 +11,7 @@ #error This file can only be used in the Wine server #endif -#include "server/object.h" +#include "object.h" /* thread structure */ @@ -19,6 +19,7 @@ struct process; struct thread_wait; struct thread_apc; struct mutex; +struct debugger; enum run_state { STARTING, RUNNING, TERMINATED }; @@ -31,6 +32,7 @@ struct thread struct thread *proc_prev; struct process *process; struct mutex *mutex; /* list of currently owned mutexes */ + struct debugger *debugger; /* debugger info if this thread is a debugger */ struct thread_wait *wait; /* current wait condition if sleeping */ struct thread_apc *apc; /* list of async procedure calls */ int apc_count; /* number of outstanding APCs */ @@ -50,27 +52,17 @@ extern struct thread *current; /* thread functions */ extern void create_initial_thread( int fd ); -extern struct thread *create_thread( int fd, void *pid, int suspend, int inherit, int *handle ); extern struct thread *get_thread_from_id( void *id ); extern struct thread *get_thread_from_handle( int handle, unsigned int access ); -extern void get_thread_info( struct thread *thread, - struct get_thread_info_reply *reply ); -extern void set_thread_info( struct thread *thread, - struct set_thread_info_request *req ); -extern int suspend_thread( struct thread *thread ); -extern int resume_thread( struct thread *thread ); extern void suspend_all_threads( void ); extern void resume_all_threads( void ); extern int send_reply( struct thread *thread, int pass_fd, int n, ... /* arg_1, len_1, ..., arg_n, len_n */ ); 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 int thread_queue_apc( struct thread *thread, void *func, void *param ); extern void kill_thread( struct thread *thread, int exit_code ); extern void thread_killed( struct thread *thread, int exit_code ); extern void thread_timeout(void); -extern void sleep_on( struct thread *thread, int count, int *handles, - int flags, int timeout ); extern void wake_up( struct object *obj, int max ); #define GET_ERROR() (current->error) diff --git a/server/trace.c b/server/trace.c index a0a5e498615..dcd5aa20229 100644 --- a/server/trace.c +++ b/server/trace.c @@ -4,7 +4,7 @@ #include #include #include "server.h" -#include "server/thread.h" +#include "thread.h" static int dump_new_process_request( struct new_process_request *req, int len ) { @@ -269,6 +269,20 @@ static int dump_event_op_request( struct event_op_request *req, int len ) return (int)sizeof(*req); } +static int dump_open_event_request( struct open_event_request *req, int len ) +{ + fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " inherit=%d,", req->inherit ); + fprintf( stderr, " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) ); + return len; +} + +static int dump_open_event_reply( struct open_event_reply *req, int len ) +{ + fprintf( stderr, " handle=%d", req->handle ); + return (int)sizeof(*req); +} + static int dump_create_mutex_request( struct create_mutex_request *req, int len ) { fprintf( stderr, " owned=%d,", req->owned ); @@ -289,6 +303,20 @@ static int dump_release_mutex_request( struct release_mutex_request *req, int le return (int)sizeof(*req); } +static int dump_open_mutex_request( struct open_mutex_request *req, int len ) +{ + fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " inherit=%d,", req->inherit ); + fprintf( stderr, " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) ); + return len; +} + +static int dump_open_mutex_reply( struct open_mutex_reply *req, int len ) +{ + fprintf( stderr, " handle=%d", req->handle ); + return (int)sizeof(*req); +} + static int dump_create_semaphore_request( struct create_semaphore_request *req, int len ) { fprintf( stderr, " initial=%08x,", req->initial ); @@ -317,16 +345,15 @@ static int dump_release_semaphore_reply( struct release_semaphore_reply *req, in return (int)sizeof(*req); } -static int dump_open_named_obj_request( struct open_named_obj_request *req, int len ) +static int dump_open_semaphore_request( struct open_semaphore_request *req, int len ) { - fprintf( stderr, " type=%d,", req->type ); fprintf( stderr, " access=%08x,", req->access ); fprintf( stderr, " inherit=%d,", req->inherit ); fprintf( stderr, " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) ); return len; } -static int dump_open_named_obj_reply( struct open_named_obj_reply *req, int len ) +static int dump_open_semaphore_reply( struct open_semaphore_reply *req, int len ) { fprintf( stderr, " handle=%d", req->handle ); return (int)sizeof(*req); @@ -584,6 +611,20 @@ static int dump_create_mapping_reply( struct create_mapping_reply *req, int len return (int)sizeof(*req); } +static int dump_open_mapping_request( struct open_mapping_request *req, int len ) +{ + fprintf( stderr, " access=%08x,", req->access ); + fprintf( stderr, " inherit=%d,", req->inherit ); + fprintf( stderr, " name=\"%.*s\"", len - (int)sizeof(*req), (char *)(req+1) ); + return len; +} + +static int dump_open_mapping_reply( struct open_mapping_reply *req, int len ) +{ + fprintf( stderr, " handle=%d", req->handle ); + return (int)sizeof(*req); +} + static int dump_get_mapping_info_request( struct get_mapping_info_request *req, int len ) { fprintf( stderr, " handle=%d", req->handle ); @@ -694,16 +735,20 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] = (void(*)())dump_create_event_reply }, { (int(*)(void *,int))dump_event_op_request, (void(*)())0 }, + { (int(*)(void *,int))dump_open_event_request, + (void(*)())dump_open_event_reply }, { (int(*)(void *,int))dump_create_mutex_request, (void(*)())dump_create_mutex_reply }, { (int(*)(void *,int))dump_release_mutex_request, (void(*)())0 }, + { (int(*)(void *,int))dump_open_mutex_request, + (void(*)())dump_open_mutex_reply }, { (int(*)(void *,int))dump_create_semaphore_request, (void(*)())dump_create_semaphore_reply }, { (int(*)(void *,int))dump_release_semaphore_request, (void(*)())dump_release_semaphore_reply }, - { (int(*)(void *,int))dump_open_named_obj_request, - (void(*)())dump_open_named_obj_reply }, + { (int(*)(void *,int))dump_open_semaphore_request, + (void(*)())dump_open_semaphore_reply }, { (int(*)(void *,int))dump_create_file_request, (void(*)())dump_create_file_reply }, { (int(*)(void *,int))dump_get_read_fd_request, @@ -750,6 +795,8 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] = (void(*)())dump_create_change_notification_reply }, { (int(*)(void *,int))dump_create_mapping_request, (void(*)())dump_create_mapping_reply }, + { (int(*)(void *,int))dump_open_mapping_request, + (void(*)())dump_open_mapping_reply }, { (int(*)(void *,int))dump_get_mapping_info_request, (void(*)())dump_get_mapping_info_reply }, { (int(*)(void *,int))dump_create_device_request, @@ -785,11 +832,13 @@ static const char * const req_names[REQ_NB_REQUESTS] = "select", "create_event", "event_op", + "open_event", "create_mutex", "release_mutex", + "open_mutex", "create_semaphore", "release_semaphore", - "open_named_obj", + "open_semaphore", "create_file", "get_read_fd", "get_write_fd", @@ -813,6 +862,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = "read_console_input", "create_change_notification", "create_mapping", + "open_mapping", "get_mapping_info", "create_device", "create_snapshot", diff --git a/tools/make_requests b/tools/make_requests index b587a912bb9..0b0f69f77f6 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -33,7 +33,7 @@ print TRACE < #include #include "server.h" -#include "server/thread.h" +#include "thread.h" EOF ### Parse server.h to find request/reply structure definitions @@ -159,9 +159,6 @@ print REQUESTS <