ntdll: Add helper functions for getting and setting thread context through the server.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2017-07-18 11:07:48 +02:00
parent da6ca91e28
commit 1e48417567
1 changed files with 101 additions and 79 deletions

View File

@ -768,6 +768,55 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1
}
/***********************************************************************
* set_thread_context
*/
static NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
{
NTSTATUS ret;
DWORD dummy, i;
context_t server_context;
context_to_server( &server_context, context );
SERVER_START_REQ( set_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->suspend = 1;
wine_server_add_data( req, &server_context, sizeof(server_context) );
ret = wine_server_call( req );
*self = reply->self;
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
for (i = 0; i < 100; i++)
{
SERVER_START_REQ( set_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->suspend = 0;
wine_server_add_data( req, &server_context, sizeof(server_context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10000;
NtDelayExecution( FALSE, &timeout );
}
else break;
}
NtResumeThread( handle, &dummy );
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
}
return ret;
}
/***********************************************************************
* NtSetContextThread (NTDLL.@)
* ZwSetContextThread (NTDLL.@)
@ -775,7 +824,6 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1
NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
{
NTSTATUS ret;
DWORD dummy, i;
BOOL self;
#ifdef __i386__
@ -796,44 +844,7 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
if (!self)
{
context_t server_context;
context_to_server( &server_context, context );
SERVER_START_REQ( set_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->suspend = 1;
wine_server_add_data( req, &server_context, sizeof(server_context) );
ret = wine_server_call( req );
self = reply->self;
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
for (i = 0; i < 100; i++)
{
SERVER_START_REQ( set_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->suspend = 0;
wine_server_add_data( req, &server_context, sizeof(server_context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10000;
NtDelayExecution( FALSE, &timeout );
}
else break;
}
NtResumeThread( handle, &dummy );
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
}
ret = set_thread_context( handle, context, &self );
if (ret) return ret;
}
@ -865,6 +876,56 @@ static inline unsigned int get_server_context_flags( DWORD flags )
return ret;
}
/***********************************************************************
* get_thread_context
*/
static NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self )
{
NTSTATUS ret;
DWORD dummy, i;
unsigned int server_flags = get_server_context_flags( context->ContextFlags );
context_t server_context;
SERVER_START_REQ( get_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->flags = server_flags;
req->suspend = 1;
wine_server_set_reply( req, &server_context, sizeof(server_context) );
ret = wine_server_call( req );
*self = reply->self;
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
for (i = 0; i < 100; i++)
{
SERVER_START_REQ( get_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->flags = server_flags;
req->suspend = 0;
wine_server_set_reply( req, &server_context, sizeof(server_context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10000;
NtDelayExecution( FALSE, &timeout );
}
else break;
}
NtResumeThread( handle, &dummy );
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
}
if (!ret) ret = context_from_server( context, &server_context );
return ret;
}
/***********************************************************************
* NtGetContextThread (NTDLL.@)
* ZwGetContextThread (NTDLL.@)
@ -872,7 +933,6 @@ static inline unsigned int get_server_context_flags( DWORD flags )
NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
{
NTSTATUS ret;
DWORD dummy, i;
DWORD needed_flags = context->ContextFlags;
BOOL self = (handle == GetCurrentThread());
@ -885,45 +945,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
if (!self)
{
unsigned int server_flags = get_server_context_flags( context->ContextFlags );
context_t server_context;
SERVER_START_REQ( get_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->flags = server_flags;
req->suspend = 1;
wine_server_set_reply( req, &server_context, sizeof(server_context) );
ret = wine_server_call( req );
self = reply->self;
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
for (i = 0; i < 100; i++)
{
SERVER_START_REQ( get_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->flags = server_flags;
req->suspend = 0;
wine_server_set_reply( req, &server_context, sizeof(server_context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
LARGE_INTEGER timeout;
timeout.QuadPart = -10000;
NtDelayExecution( FALSE, &timeout );
}
else break;
}
NtResumeThread( handle, &dummy );
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
}
if (!ret) ret = context_from_server( context, &server_context );
ret = get_thread_context( handle, context, &self );
if (ret) return ret;
needed_flags &= ~context->ContextFlags;
}