Module: wine Branch: master Commit: d1a8155882e83378add14a5d0785477ad8fccb56 URL: http://source.winehq.org/git/wine.git/?a=commit;h=d1a8155882e83378add14a5d07...
Author: Andrey Turkin andrey.turkin@gmail.com Date: Fri Sep 28 00:03:39 2007 +0400
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 bf35a47..bbb071b 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 e37f25c..314a3a6 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 1282bb4..13f5939 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 31e1c9f..d671a1c 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 c84f0b8..d56aad0 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 8eec8a7..2e83c12 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 7411565..0a013ab 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 b431413..d1575e1 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