From d1a8155882e83378add14a5d0785477ad8fccb56 Mon Sep 17 00:00:00 2001 From: Andrey Turkin <andrey.turkin@gmail.com> Date: Fri, 28 Sep 2007 00:03:39 +0400 Subject: [PATCH] server: Allow completion object to be attached to an fd object. --- dlls/ntdll/file.c | 17 +++++++++++++++++ include/wine/server_protocol.h | 19 ++++++++++++++++++- server/completion.c | 3 ++- server/fd.c | 22 ++++++++++++++++++++++ server/file.h | 5 +++++ server/protocol.def | 8 ++++++++ server/request.h | 2 ++ server/trace.c | 10 ++++++++++ 8 files changed, 84 insertions(+), 2 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index bf35a47d738..bbb071b786a 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -1658,6 +1658,23 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io, } break; + case FileCompletionInformation: + if (len >= sizeof(FILE_COMPLETION_INFORMATION)) + { + FILE_COMPLETION_INFORMATION *info = (FILE_COMPLETION_INFORMATION *)ptr; + + SERVER_START_REQ( set_completion_info ) + { + req->handle = handle; + req->chandle = info->CompletionPort; + req->ckey = info->CompletionKey; + io->u.Status = wine_server_call( req ); + } + SERVER_END_REQ; + } else + io->u.Status = STATUS_INVALID_PARAMETER_3; + break; + default: FIXME("Unsupported class (%d)\n", class); io->u.Status = STATUS_NOT_IMPLEMENTED; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index e37f25c8e61..314a3a624ec 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4156,6 +4156,20 @@ struct query_completion_reply }; + +struct set_completion_info_request +{ + struct request_header __header; + obj_handle_t handle; + obj_handle_t chandle; + unsigned long ckey; +}; +struct set_completion_info_reply +{ + struct reply_header __header; +}; + + enum request { REQ_new_process, @@ -4383,6 +4397,7 @@ enum request REQ_add_completion, REQ_remove_completion, REQ_query_completion, + REQ_set_completion_info, REQ_NB_REQUESTS }; @@ -4615,6 +4630,7 @@ union generic_request struct add_completion_request add_completion_request; struct remove_completion_request remove_completion_request; struct query_completion_request query_completion_request; + struct set_completion_info_request set_completion_info_request; }; union generic_reply { @@ -4845,8 +4861,9 @@ union generic_reply struct add_completion_reply add_completion_reply; struct remove_completion_reply remove_completion_reply; struct query_completion_reply query_completion_reply; + struct set_completion_info_reply set_completion_info_reply; }; -#define SERVER_PROTOCOL_VERSION 314 +#define SERVER_PROTOCOL_VERSION 315 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/completion.c b/server/completion.c index 1282bb47d93..13f59395cb8 100644 --- a/server/completion.c +++ b/server/completion.c @@ -39,6 +39,7 @@ #include "wine/unicode.h" #include "object.h" +#include "file.h" #include "handle.h" #include "request.h" @@ -124,7 +125,7 @@ static struct completion *create_completion( struct directory *root, const struc return completion; } -static struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access ) +struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access ) { return (struct completion *) get_handle_obj( process, handle, access, &completion_ops ); } diff --git a/server/fd.c b/server/fd.c index 31e1c9fd6a7..d671a1cddc6 100644 --- a/server/fd.c +++ b/server/fd.c @@ -180,6 +180,8 @@ struct fd struct async_queue *read_q; /* async readers of this fd */ struct async_queue *write_q; /* async writers of this fd */ struct async_queue *wait_q; /* other async waiters of this fd */ + struct completion *completion; /* completion object attached to this fd */ + unsigned long comp_key; /* completion key to set in completion events */ }; static void fd_dump( struct object *obj, int verbose ); @@ -1329,6 +1331,7 @@ static void fd_destroy( struct object *obj ) free_async_queue( fd->write_q ); free_async_queue( fd->wait_q ); + if (fd->completion) release_object( fd->completion ); remove_fd_locks( fd ); list_remove( &fd->inode_entry ); if (fd->poll_index != -1) remove_poll_user( fd, fd->poll_index ); @@ -1406,6 +1409,7 @@ static struct fd *alloc_fd_object(void) fd->read_q = NULL; fd->write_q = NULL; fd->wait_q = NULL; + fd->completion = NULL; list_init( &fd->inode_entry ); list_init( &fd->locks ); @@ -1438,6 +1442,7 @@ struct fd *alloc_pseudo_fd( const struct fd_ops *fd_user_ops, struct object *use fd->read_q = NULL; fd->write_q = NULL; fd->wait_q = NULL; + fd->completion = NULL; fd->no_fd_status = STATUS_BAD_DEVICE_TYPE; list_init( &fd->inode_entry ); list_init( &fd->locks ); @@ -2009,3 +2014,20 @@ DECL_HANDLER(cancel_async) release_object( fd ); } } + +/* attach completion object to a fd */ +DECL_HANDLER(set_completion_info) +{ + struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); + + if (fd) + { + if (!fd->completion) + { + fd->completion = get_completion_obj( current->process, req->chandle, IO_COMPLETION_MODIFY_STATE ); + fd->comp_key = req->ckey; + } + else set_error( STATUS_INVALID_PARAMETER ); + release_object( fd ); + } +} diff --git a/server/file.h b/server/file.h index c84f0b8179b..d56aad037fe 100644 --- a/server/file.h +++ b/server/file.h @@ -25,6 +25,7 @@ struct fd; struct async_queue; +struct completion; typedef unsigned __int64 file_pos_t; @@ -120,6 +121,10 @@ extern void do_change_notify( int unix_fd ); extern void sigio_callback(void); extern struct object *create_dir_obj( struct fd *fd ); +/* completion */ + +struct completion *get_completion_obj( struct process *process, obj_handle_t handle, unsigned int access ); + /* serial port functions */ extern int is_serial_fd( struct fd *fd ); diff --git a/server/protocol.def b/server/protocol.def index 8eec8a7596c..2e83c12ebd5 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2983,3 +2983,11 @@ enum message_type @REPLY unsigned int depth; /* completion queue depth */ @END + + +/* associate object with completion port */ +@REQ(set_completion_info) + obj_handle_t handle; /* object handle */ + obj_handle_t chandle; /* port handle */ + unsigned long ckey; /* completion key */ +@END diff --git a/server/request.h b/server/request.h index 741156596ea..0a013abb315 100644 --- a/server/request.h +++ b/server/request.h @@ -335,6 +335,7 @@ DECL_HANDLER(open_completion); DECL_HANDLER(add_completion); DECL_HANDLER(remove_completion); DECL_HANDLER(query_completion); +DECL_HANDLER(set_completion_info); #ifdef WANT_REQUEST_HANDLERS @@ -566,6 +567,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_add_completion, (req_handler)req_remove_completion, (req_handler)req_query_completion, + (req_handler)req_set_completion_info, }; #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/trace.c b/server/trace.c index b4314135137..d1575e1b9ed 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3628,6 +3628,13 @@ static void dump_query_completion_reply( const struct query_completion_reply *re fprintf( stderr, " depth=%08x", req->depth ); } +static void dump_set_completion_info_request( const struct set_completion_info_request *req ) +{ + fprintf( stderr, " handle=%p,", req->handle ); + fprintf( stderr, " chandle=%p,", req->chandle ); + fprintf( stderr, " ckey=%lx", req->ckey ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_get_new_process_info_request, @@ -3854,6 +3861,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_add_completion_request, (dump_func)dump_remove_completion_request, (dump_func)dump_query_completion_request, + (dump_func)dump_set_completion_info_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -4082,6 +4090,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)0, (dump_func)dump_remove_completion_reply, (dump_func)dump_query_completion_reply, + (dump_func)0, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -4310,6 +4319,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "add_completion", "remove_completion", "query_completion", + "set_completion_info", }; static const struct -- GitLab