server: Allow passing suspend context in select request.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2020-04-15 14:55:03 +02:00 committed by Alexandre Julliard
parent 85f9f51df8
commit e70b684ded
6 changed files with 36 additions and 8 deletions

View File

@ -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 );

View File

@ -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 ### */

View File

@ -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

View File

@ -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 );

View File

@ -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 );

View File

@ -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 )