Module: wine Branch: master Commit: c2ab7a625e5728977668688a66c4e0b7eaa14c3e URL: http://source.winehq.org/git/wine.git/?a=commit;h=c2ab7a625e5728977668688a66...
Author: Alexandre Julliard julliard@winehq.org Date: Thu Aug 22 10:34:11 2013 +0200
server: Add a structure to pass the parameters of a select request.
---
dlls/ntdll/sync.c | 7 +++-- include/wine/server_protocol.h | 20 +++++++++++++++- server/protocol.def | 18 ++++++++++++++- server/thread.c | 34 ++++++++++++++++++++++------- server/trace.c | 46 +++++++++++++++++++++++++++++++++------- 5 files changed, 103 insertions(+), 22 deletions(-)
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c index 2e6ffdf..89f6ee6 100644 --- a/dlls/ntdll/sync.c +++ b/dlls/ntdll/sync.c @@ -1109,18 +1109,19 @@ NTSTATUS NTDLL_queue_process_apc( HANDLE process, const apc_call_t *call, apc_re NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags, const LARGE_INTEGER *timeout, HANDLE signal_object ) { + select_op_t select_op; NTSTATUS ret; UINT i; int cookie; BOOL user_apc = FALSE; - obj_handle_t obj_handles[MAXIMUM_WAIT_OBJECTS]; obj_handle_t apc_handle = 0; apc_call_t call; apc_result_t result; timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
memset( &result, 0, sizeof(result) ); - for (i = 0; i < count; i++) obj_handles[i] = wine_server_obj_handle( handles[i] ); + select_op.wait.op = SELECT_WAIT; + for (i = 0; i < count; i++) select_op.wait.handles[i] = wine_server_obj_handle( handles[i] );
for (;;) { @@ -1132,7 +1133,7 @@ NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UIN req->prev_apc = apc_handle; req->timeout = abs_timeout; wine_server_add_data( req, &result, sizeof(result) ); - wine_server_add_data( req, obj_handles, count * sizeof(*obj_handles) ); + wine_server_add_data( req, &select_op, offsetof( select_op_t, wait.handles[count] )); ret = wine_server_call( req ); abs_timeout = reply->timeout; apc_handle = reply->apc_handle; diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 98835b2..590bd81 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -404,6 +404,22 @@ struct token_groups
};
+enum select_op +{ + SELECT_NONE, + SELECT_WAIT +}; + +typedef union +{ + enum select_op op; + struct + { + enum select_op op; + obj_handle_t handles[MAXIMUM_WAIT_OBJECTS]; + } wait; +} select_op_t; + enum apc_type { APC_NONE, @@ -1056,7 +1072,7 @@ struct select_request obj_handle_t prev_apc; timeout_t timeout; /* VARARG(result,apc_result); */ - /* VARARG(handles,handles); */ + /* VARARG(data,select_op); */ }; struct select_reply { @@ -5771,6 +5787,6 @@ union generic_reply struct set_suspend_context_reply set_suspend_context_reply; };
-#define SERVER_PROTOCOL_VERSION 443 +#define SERVER_PROTOCOL_VERSION 444
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 6748e5d..4601942 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -420,6 +420,22 @@ struct token_groups /* VARARG(sids,SID); */ };
+enum select_op +{ + SELECT_NONE, + SELECT_WAIT +}; + +typedef union +{ + enum select_op op; + struct + { + enum select_op op; /* SELECT_WAIT */ + obj_handle_t handles[MAXIMUM_WAIT_OBJECTS]; + } wait; +} select_op_t; + enum apc_type { APC_NONE, @@ -924,7 +940,7 @@ struct rawinput_device obj_handle_t prev_apc; /* handle to previous APC */ timeout_t timeout; /* timeout */ VARARG(result,apc_result); /* result of previous APC */ - VARARG(handles,handles); /* handles to select on */ + VARARG(data,select_op); /* operation-specific data */ @REPLY timeout_t timeout; /* timeout converted to absolute */ apc_call_t call; /* APC call arguments */ diff --git a/server/thread.c b/server/thread.c index 5f9738d..c6eeaf9 100644 --- a/server/thread.c +++ b/server/thread.c @@ -710,23 +710,39 @@ static int signal_object( obj_handle_t handle ) }
/* select on a list of handles */ -static timeout_t select_on( unsigned int count, client_ptr_t cookie, const obj_handle_t *handles, +static timeout_t select_on( const select_op_t *select_op, data_size_t op_size, client_ptr_t cookie, int flags, timeout_t timeout, obj_handle_t signal_obj ) { int ret; - unsigned int i; + unsigned int i, count; struct object *objects[MAXIMUM_WAIT_OBJECTS];
if (timeout <= 0) timeout = current_time - timeout;
- if (count > MAXIMUM_WAIT_OBJECTS) + switch (select_op->op) { + case SELECT_NONE: + count = 0; + break; + + case SELECT_WAIT: + count = (op_size - offsetof( select_op_t, wait.handles )) / sizeof(select_op->wait.handles[0]); + if (op_size < offsetof( select_op_t, wait.handles ) || count > MAXIMUM_WAIT_OBJECTS) + { + set_error( STATUS_INVALID_PARAMETER ); + return 0; + } + break; + + default: set_error( STATUS_INVALID_PARAMETER ); return 0; } + for (i = 0; i < count; i++) { - if (!(objects[i] = get_handle_obj( current->process, handles[i], SYNCHRONIZE, NULL ))) + if (!(objects[i] = get_handle_obj( current->process, select_op->wait.handles[i], + SYNCHRONIZE, NULL ))) break; }
@@ -1310,17 +1326,19 @@ DECL_HANDLER(resume_thread) /* select on a handle list */ DECL_HANDLER(select) { + select_op_t select_op; + data_size_t op_size; struct thread_apc *apc; - unsigned int count; const apc_result_t *result = get_req_data(); - const obj_handle_t *handles = (const obj_handle_t *)(result + 1);
if (get_req_data_size() < sizeof(*result)) { set_error( STATUS_INVALID_PARAMETER ); return; } - count = (get_req_data_size() - sizeof(*result)) / sizeof(obj_handle_t); + op_size = min( get_req_data_size() - sizeof(*result), sizeof(select_op) ); + memset( &select_op, 0, sizeof(select_op) ); + memcpy( &select_op, result + 1, op_size );
/* first store results of previous apc */ if (req->prev_apc) @@ -1348,7 +1366,7 @@ DECL_HANDLER(select) release_object( apc ); }
- reply->timeout = select_on( count, req->cookie, handles, req->flags, req->timeout, req->signal ); + reply->timeout = select_on( &select_op, op_size, req->cookie, req->flags, req->timeout, req->signal );
if (get_error() == STATUS_USER_APC) { diff --git a/server/trace.c b/server/trace.c index 7740545..c9af74f 100644 --- a/server/trace.c +++ b/server/trace.c @@ -66,6 +66,19 @@ static void dump_uints( const int *ptr, int len ) fputc( '}', stderr ); }
+static void dump_handles( const char *prefix, const obj_handle_t *data, data_size_t size ) +{ + data_size_t len = size / sizeof(*data); + + fprintf( stderr,"%s{", prefix ); + while (len > 0) + { + fprintf( stderr, "%04x", *data++ ); + if (--len) fputc( ',', stderr ); + } + fputc( '}', stderr ); +} + static void dump_timeout( const char *prefix, const timeout_t *time ) { fprintf( stderr, "%s%s", prefix, get_timeout_str(*time) ); @@ -367,16 +380,33 @@ static void dump_varargs_apc_result( const char *prefix, data_size_t size ) remove_data( size ); }
-static void dump_varargs_handles( const char *prefix, data_size_t size ) +static void dump_varargs_select_op( const char *prefix, data_size_t size ) { - const obj_handle_t *data = cur_data; - data_size_t len = size / sizeof(*data); + select_op_t data;
- fprintf( stderr,"%s{", prefix ); - while (len > 0) + if (!size) { - fprintf( stderr, "%04x", *data++ ); - if (--len) fputc( ',', stderr ); + fprintf( stderr, "%s{}", prefix ); + return; + } + memset( &data, 0, sizeof(data) ); + memcpy( &data, cur_data, min( size, sizeof(data) )); + + fprintf( stderr, "%s{", prefix ); + switch (data.op) + { + case SELECT_NONE: + fprintf( stderr, "NONE" ); + break; + case SELECT_WAIT: + fprintf( stderr, "WAIT" ); + if (size > offsetof( select_op_t, wait.handles )) + dump_handles( ",handles=", data.wait.handles, + min( size, sizeof(data.wait) ) - offsetof( select_op_t, wait.handles )); + break; + default: + fprintf( stderr, "op=%u", data.op ); + break; } fputc( '}', stderr ); remove_data( size ); @@ -1361,7 +1391,7 @@ static void dump_select_request( const struct select_request *req ) fprintf( stderr, ", prev_apc=%04x", req->prev_apc ); dump_timeout( ", timeout=", &req->timeout ); dump_varargs_apc_result( ", result=", cur_size ); - dump_varargs_handles( ", handles=", cur_size ); + dump_varargs_select_op( ", data=", cur_size ); }
static void dump_select_reply( const struct select_reply *req )