diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index 33868c76911..41ffec90c47 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -72,10 +72,8 @@ void wait_suspend( CONTEXT *context ) 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 @@ void wait_suspend( CONTEXT *context ) 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 6fdae05fea7..6e96f977f01 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -4815,6 +4815,32 @@ struct set_cursor_reply #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 @@ enum request 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 @@ union generic_request 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 @@ union generic_reply 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 6984bc51656..f5ebbe7c2ca 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1863,7 +1863,7 @@ enum char_info_mode @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 @@ enum char_info_mode /* 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 @@ enum coords_relative #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 b08033ede24..cab8d3030ad 100644 --- a/server/request.h +++ b/server/request.h @@ -354,6 +354,8 @@ DECL_HANDLER(set_window_layered_info); 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 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (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_y) == 28 ); 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 392c4a487cf..7cfbc6043ff 100644 --- a/server/thread.c +++ b/server/thread.c @@ -1472,21 +1472,7 @@ DECL_HANDLER(get_thread_context) } 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 @@ DECL_HANDLER(set_thread_context) } 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 @@ DECL_HANDLER(set_thread_context) 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 a296341b9de..e81df6af941 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3862,6 +3862,20 @@ static void dump_set_cursor_reply( const struct set_cursor_reply *req ) 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 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (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 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (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 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "alloc_user_handle", "free_user_handle", "set_cursor", + "get_suspend_context", + "set_suspend_context", }; static const struct