Module: wine Branch: master Commit: e70b684dedaa1a7c9b5fc884f7083cbf7228600f URL: https://source.winehq.org/git/wine.git/?a=commit;h=e70b684dedaa1a7c9b5fc884f...
Author: Jacek Caban jacek@codeweavers.com Date: Wed Apr 15 14:55:03 2020 +0200
server: Allow passing suspend context in select request.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/server.c | 1 + include/wine/server_protocol.h | 8 +++++--- server/protocol.def | 5 ++++- server/request.h | 3 ++- server/thread.c | 22 ++++++++++++++++++++-- server/trace.c | 5 ++++- 6 files changed, 36 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c index 9053ad2042..7e178aa745 100644 --- a/dlls/ntdll/server.c +++ b/dlls/ntdll/server.c @@ -624,6 +624,7 @@ unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT req->cookie = wine_server_client_ptr( &cookie ); req->prev_apc = apc_handle; req->timeout = abs_timeout; + req->size = size; wine_server_add_data( req, &result, sizeof(result) ); wine_server_add_data( req, select_op, size ); ret = server_call_unlocked( req ); diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 298e2dbfa4..77f62afb72 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1257,16 +1257,18 @@ struct select_request int flags; client_ptr_t cookie; abstime_t timeout; + data_size_t size; obj_handle_t prev_apc; /* VARARG(result,apc_result); */ - /* VARARG(data,select_op); */ - char __pad_36[4]; + /* VARARG(data,select_op,size); */ + /* VARARG(context,context); */ }; struct select_reply { struct reply_header __header; apc_call_t call; obj_handle_t apc_handle; + /* VARARG(context,context); */ char __pad_52[4]; }; #define SELECT_ALERTABLE 1 @@ -6716,7 +6718,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 598 +#define SERVER_PROTOCOL_VERSION 599
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index bfe817b654..318c3b0b83 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1106,12 +1106,15 @@ struct rawinput_device int flags; /* wait flags (see below) */ client_ptr_t cookie; /* magic cookie to return to client */ abstime_t timeout; /* timeout */ + data_size_t size; /* size of select_op */ obj_handle_t prev_apc; /* handle to previous APC */ VARARG(result,apc_result); /* result of previous APC */ - VARARG(data,select_op); /* operation-specific data */ + VARARG(data,select_op,size); /* operation-specific data */ + VARARG(context,context); /* suspend context */ @REPLY apc_call_t call; /* APC call arguments */ obj_handle_t apc_handle; /* handle to next APC */ + VARARG(context,context); /* suspend context */ @END #define SELECT_ALERTABLE 1 #define SELECT_INTERRUPTIBLE 2 diff --git a/server/request.h b/server/request.h index d8967211e7..c1f4fc6b39 100644 --- a/server/request.h +++ b/server/request.h @@ -938,7 +938,8 @@ C_ASSERT( sizeof(struct open_thread_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct select_request, flags) == 12 ); C_ASSERT( FIELD_OFFSET(struct select_request, cookie) == 16 ); C_ASSERT( FIELD_OFFSET(struct select_request, timeout) == 24 ); -C_ASSERT( FIELD_OFFSET(struct select_request, prev_apc) == 32 ); +C_ASSERT( FIELD_OFFSET(struct select_request, size) == 32 ); +C_ASSERT( FIELD_OFFSET(struct select_request, prev_apc) == 36 ); C_ASSERT( sizeof(struct select_request) == 40 ); C_ASSERT( FIELD_OFFSET(struct select_reply, call) == 8 ); C_ASSERT( FIELD_OFFSET(struct select_reply, apc_handle) == 48 ); diff --git a/server/thread.c b/server/thread.c index ba481223b7..d75dc238d5 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1536,18 +1536,36 @@ DECL_HANDLER(select) struct thread_apc *apc; const apc_result_t *result = get_req_data();
- if (get_req_data_size() < sizeof(*result)) + if (get_req_data_size() < sizeof(*result) || + get_req_data_size() - sizeof(*result) < req->size || + req->size & 3) { set_error( STATUS_INVALID_PARAMETER ); return; } + + if (get_req_data_size() - sizeof(*result) - req->size == sizeof(context_t)) + { + const context_t *context = (const context_t *)((const char *)(result + 1) + req->size); + if (current->context || context->cpu != current->process->cpu) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + + if (!(current->suspend_context = mem_alloc( sizeof(*context) ))) return; + memcpy( current->suspend_context, context, sizeof(*context) ); + current->suspend_context->flags = 0; /* to keep track of what is modified */ + current->context = current->suspend_context; + } + if (!req->cookie) { set_error( STATUS_INVALID_PARAMETER ); return; }
- op_size = min( get_req_data_size() - sizeof(*result), sizeof(select_op) ); + op_size = min( req->size, sizeof(select_op) ); memset( &select_op, 0, sizeof(select_op) ); memcpy( &select_op, result + 1, op_size );
diff --git a/server/trace.c b/server/trace.c index 095a45f0dd..9dd7ab73a1 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1588,15 +1588,18 @@ static void dump_select_request( const struct select_request *req ) fprintf( stderr, " flags=%d", req->flags ); dump_uint64( ", cookie=", &req->cookie ); dump_abstime( ", timeout=", &req->timeout ); + fprintf( stderr, ", size=%u", req->size ); fprintf( stderr, ", prev_apc=%04x", req->prev_apc ); dump_varargs_apc_result( ", result=", cur_size ); - dump_varargs_select_op( ", data=", cur_size ); + dump_varargs_select_op( ", data=", min(cur_size,req->size) ); + dump_varargs_context( ", context=", cur_size ); }
static void dump_select_reply( const struct select_reply *req ) { dump_apc_call( " call=", &req->call ); fprintf( stderr, ", apc_handle=%04x", req->apc_handle ); + dump_varargs_context( ", context=", cur_size ); }
static void dump_create_event_request( const struct create_event_request *req )