Jacek Caban : server: Allow passing suspend context in select request.
Alexandre Julliard
julliard at winehq.org
Thu Apr 16 16:45:13 CDT 2020
Module: wine
Branch: master
Commit: e70b684dedaa1a7c9b5fc884f7083cbf7228600f
URL: https://source.winehq.org/git/wine.git/?a=commit;h=e70b684dedaa1a7c9b5fc884f7083cbf7228600f
Author: Jacek Caban <jacek at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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 )
More information about the wine-cvs
mailing list