server: Add separate requests for getting/setting the thread context during suspend.
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c
index 33868c7..41ffec9 100644
--- a/dlls/ntdll/exception.c
+++ b/dlls/ntdll/exception.c
@@ -72,10 +72,8 @@
context_to_server( &server_context, context );
/* store the context we got at suspend time */
- SERVER_START_REQ( set_thread_context )
+ SERVER_START_REQ( set_suspend_context )
{
- req->handle = wine_server_obj_handle( GetCurrentThread() );
- req->suspend = 1;
wine_server_add_data( req, &server_context, sizeof(server_context) );
wine_server_call( req );
}
@@ -86,10 +84,8 @@
NTDLL_wait_for_multiple_objects( 0, NULL, SELECT_INTERRUPTIBLE, &timeout, 0 );
/* retrieve the new context */
- SERVER_START_REQ( get_thread_context )
+ SERVER_START_REQ( get_suspend_context )
{
- req->handle = wine_server_obj_handle( GetCurrentThread() );
- req->suspend = 1;
wine_server_set_reply( req, &server_context, sizeof(server_context) );
wine_server_call( req );
}
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 6fdae05..6e96f97 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -4815,6 +4815,32 @@
#define SET_CURSOR_CLIP 0x08
+
+struct get_suspend_context_request
+{
+ struct request_header __header;
+ char __pad_12[4];
+};
+struct get_suspend_context_reply
+{
+ struct reply_header __header;
+ /* VARARG(context,context); */
+};
+
+
+
+struct set_suspend_context_request
+{
+ struct request_header __header;
+ /* VARARG(context,context); */
+ char __pad_12[4];
+};
+struct set_suspend_context_reply
+{
+ struct reply_header __header;
+};
+
+
enum request
{
REQ_new_process,
@@ -5060,6 +5086,8 @@
REQ_alloc_user_handle,
REQ_free_user_handle,
REQ_set_cursor,
+ REQ_get_suspend_context,
+ REQ_set_suspend_context,
REQ_NB_REQUESTS
};
@@ -5310,6 +5338,8 @@
struct alloc_user_handle_request alloc_user_handle_request;
struct free_user_handle_request free_user_handle_request;
struct set_cursor_request set_cursor_request;
+ struct get_suspend_context_request get_suspend_context_request;
+ struct set_suspend_context_request set_suspend_context_request;
};
union generic_reply
{
@@ -5558,8 +5588,10 @@
struct alloc_user_handle_reply alloc_user_handle_reply;
struct free_user_handle_reply free_user_handle_reply;
struct set_cursor_reply set_cursor_reply;
+ struct get_suspend_context_reply get_suspend_context_reply;
+ struct set_suspend_context_reply set_suspend_context_reply;
};
-#define SERVER_PROTOCOL_VERSION 422
+#define SERVER_PROTOCOL_VERSION 423
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 6984bc5..f5ebbe7 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1863,7 +1863,7 @@
@REQ(get_thread_context)
obj_handle_t handle; /* thread handle */
unsigned int flags; /* context flags */
- int suspend; /* if getting context during suspend */
+ int suspend; /* suspend the thread if needed */
@REPLY
int self; /* was it a handle to the current thread? */
VARARG(context,context); /* thread context */
@@ -1873,7 +1873,7 @@
/* Set the current context of a thread */
@REQ(set_thread_context)
obj_handle_t handle; /* thread handle */
- int suspend; /* if setting context during suspend */
+ int suspend; /* suspend the thread if needed */
VARARG(context,context); /* thread context */
@REPLY
int self; /* was it a handle to the current thread? */
@@ -3328,3 +3328,16 @@
#define SET_CURSOR_COUNT 0x02
#define SET_CURSOR_POS 0x04
#define SET_CURSOR_CLIP 0x08
+
+
+/* Retrieve the suspended context of a thread */
+@REQ(get_suspend_context)
+@REPLY
+ VARARG(context,context); /* thread context */
+@END
+
+
+/* Store the suspend context of a thread */
+@REQ(set_suspend_context)
+ VARARG(context,context); /* thread context */
+@END
diff --git a/server/request.h b/server/request.h
index b08033e..cab8d30 100644
--- a/server/request.h
+++ b/server/request.h
@@ -354,6 +354,8 @@
DECL_HANDLER(alloc_user_handle);
DECL_HANDLER(free_user_handle);
DECL_HANDLER(set_cursor);
+DECL_HANDLER(get_suspend_context);
+DECL_HANDLER(set_suspend_context);
#ifdef WANT_REQUEST_HANDLERS
@@ -603,6 +605,8 @@
(req_handler)req_alloc_user_handle,
(req_handler)req_free_user_handle,
(req_handler)req_set_cursor,
+ (req_handler)req_get_suspend_context,
+ (req_handler)req_set_suspend_context,
};
C_ASSERT( sizeof(affinity_t) == 8 );
@@ -2108,6 +2112,9 @@
C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, new_clip) == 32 );
C_ASSERT( FIELD_OFFSET(struct set_cursor_reply, last_change) == 48 );
C_ASSERT( sizeof(struct set_cursor_reply) == 56 );
+C_ASSERT( sizeof(struct get_suspend_context_request) == 16 );
+C_ASSERT( sizeof(struct get_suspend_context_reply) == 8 );
+C_ASSERT( sizeof(struct set_suspend_context_request) == 16 );
#endif /* WANT_REQUEST_HANDLERS */
diff --git a/server/thread.c b/server/thread.c
index 392c4a4..7cfbc60 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1472,21 +1472,7 @@
}
if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
- if (req->suspend)
- {
- if (thread != current || !thread->suspend_context)
- {
- /* not suspended, shouldn't happen */
- set_error( STATUS_INVALID_PARAMETER );
- }
- else
- {
- if (thread->context == thread->suspend_context) thread->context = NULL;
- set_reply_data_ptr( thread->suspend_context, sizeof(context_t) );
- thread->suspend_context = NULL;
- }
- }
- else if (thread != current && !thread->context)
+ if (thread != current && !thread->context)
{
/* thread is not suspended, retry (if it's still running) */
if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
@@ -1518,21 +1504,7 @@
}
if (!(thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) return;
- if (req->suspend)
- {
- if (thread != current || thread->context || context->cpu != thread->process->cpu)
- {
- /* nested suspend or exception, shouldn't happen */
- set_error( STATUS_INVALID_PARAMETER );
- }
- else if ((thread->suspend_context = mem_alloc( sizeof(context_t) )))
- {
- memcpy( thread->suspend_context, get_req_data(), sizeof(context_t) );
- thread->context = thread->suspend_context;
- if (thread->debug_break) break_thread( thread );
- }
- }
- else if (thread != current && !thread->context)
+ if (thread != current && !thread->context)
{
/* thread is not suspended, retry (if it's still running) */
if (thread->state != RUNNING) set_error( STATUS_ACCESS_DENIED );
@@ -1552,6 +1524,48 @@
release_object( thread );
}
+/* retrieve the suspended context of a thread */
+DECL_HANDLER(get_suspend_context)
+{
+ if (get_reply_max_size() < sizeof(context_t))
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
+ if (current->suspend_context)
+ {
+ set_reply_data_ptr( current->suspend_context, sizeof(context_t) );
+ if (current->context == current->suspend_context) current->context = NULL;
+ current->suspend_context = NULL;
+ }
+ else set_error( STATUS_INVALID_PARAMETER ); /* not suspended, shouldn't happen */
+}
+
+/* store the suspended context of a thread */
+DECL_HANDLER(set_suspend_context)
+{
+ const context_t *context = get_req_data();
+
+ if (get_req_data_size() < sizeof(context_t))
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ return;
+ }
+
+ if (current->context || context->cpu != current->process->cpu)
+ {
+ /* nested suspend or exception, shouldn't happen */
+ set_error( STATUS_INVALID_PARAMETER );
+ }
+ else if ((current->suspend_context = mem_alloc( sizeof(context_t) )))
+ {
+ memcpy( current->suspend_context, get_req_data(), sizeof(context_t) );
+ current->context = current->suspend_context;
+ if (current->debug_break) break_thread( current );
+ }
+}
+
/* fetch a selector entry for a thread */
DECL_HANDLER(get_selector_entry)
{
diff --git a/server/trace.c b/server/trace.c
index a296341..e81df6a 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -3862,6 +3862,20 @@
fprintf( stderr, ", last_change=%08x", req->last_change );
}
+static void dump_get_suspend_context_request( const struct get_suspend_context_request *req )
+{
+}
+
+static void dump_get_suspend_context_reply( const struct get_suspend_context_reply *req )
+{
+ dump_varargs_context( " context=", cur_size );
+}
+
+static void dump_set_suspend_context_request( const struct set_suspend_context_request *req )
+{
+ dump_varargs_context( " context=", cur_size );
+}
+
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_get_new_process_info_request,
@@ -4106,6 +4120,8 @@
(dump_func)dump_alloc_user_handle_request,
(dump_func)dump_free_user_handle_request,
(dump_func)dump_set_cursor_request,
+ (dump_func)dump_get_suspend_context_request,
+ (dump_func)dump_set_suspend_context_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -4352,6 +4368,8 @@
(dump_func)dump_alloc_user_handle_reply,
NULL,
(dump_func)dump_set_cursor_reply,
+ (dump_func)dump_get_suspend_context_reply,
+ NULL,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -4598,6 +4616,8 @@
"alloc_user_handle",
"free_user_handle",
"set_cursor",
+ "get_suspend_context",
+ "set_suspend_context",
};
static const struct