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