ntdll: Pass the server context to get/set_thread_context().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2018-06-12 10:46:27 +02:00
parent e470221dca
commit 36371075f8
7 changed files with 147 additions and 50 deletions

View File

@ -55,8 +55,8 @@ extern LONG call_vectored_handlers( EXCEPTION_RECORD *rec, CONTEXT *context ) DE
extern void raise_status( NTSTATUS status, EXCEPTION_RECORD *rec ) DECLSPEC_NORETURN DECLSPEC_HIDDEN;
extern NTSTATUS context_to_server( context_t *to, const CONTEXT *from ) DECLSPEC_HIDDEN;
extern NTSTATUS context_from_server( CONTEXT *to, const context_t *from ) DECLSPEC_HIDDEN;
extern NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self ) DECLSPEC_HIDDEN;
extern NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self ) DECLSPEC_HIDDEN;
extern NTSTATUS set_thread_context( HANDLE handle, const context_t *context, BOOL *self ) DECLSPEC_HIDDEN;
extern NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, BOOL *self ) DECLSPEC_HIDDEN;
/* debug helpers */
extern LPCSTR debugstr_us( const UNICODE_STRING *str ) DECLSPEC_HIDDEN;

View File

@ -293,6 +293,24 @@ __ASM_GLOBAL_FUNC( set_cpu_context,
"pop {pc}" )
/***********************************************************************
* get_server_context_flags
*
* Convert CPU-specific flags to generic server flags
*/
static unsigned int get_server_context_flags( DWORD flags )
{
unsigned int ret = 0;
flags &= ~CONTEXT_ARM; /* get rid of CPU id */
if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
return ret;
}
/***********************************************************************
* copy_context
*
@ -449,8 +467,10 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
{
NTSTATUS ret;
BOOL self;
context_t server_context;
ret = set_thread_context( handle, context, &self );
context_to_server( &server_context, context );
ret = set_thread_context( handle, &server_context, &self );
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
return ret;
}
@ -468,7 +488,11 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
if (!self)
{
if ((ret = get_thread_context( handle, context, &self ))) return ret;
context_t server_context;
unsigned int server_flags = get_server_context_flags( context->ContextFlags );
if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret;
if ((ret = context_from_server( context, &server_context ))) return ret;
needed_flags &= ~context->ContextFlags;
}

View File

@ -231,6 +231,23 @@ static void set_cpu_context( const CONTEXT *context )
FIXME( "Not implemented on ARM64\n" );
}
/***********************************************************************
* get_server_context_flags
*
* Convert CPU-specific flags to generic server flags
*/
static unsigned int get_server_context_flags( DWORD flags )
{
unsigned int ret = 0;
flags &= ~CONTEXT_ARM64; /* get rid of CPU id */
if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
return ret;
}
/***********************************************************************
* copy_context
*
@ -363,8 +380,10 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
{
NTSTATUS ret;
BOOL self;
context_t server_context;
ret = set_thread_context( handle, context, &self );
context_to_server( &server_context, context );
ret = set_thread_context( handle, &server_context, &self );
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
return ret;
}
@ -382,7 +401,11 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
if (!self)
{
if ((ret = get_thread_context( handle, context, &self ))) return ret;
context_t server_context;
unsigned int server_flags = get_server_context_flags( context->ContextFlags );
if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret;
if ((ret = context_from_server( context, &server_context ))) return ret;
needed_flags &= ~context->ContextFlags;
}

View File

@ -1168,6 +1168,26 @@ void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context )
}
/***********************************************************************
* get_server_context_flags
*
* Convert CPU-specific flags to generic server flags
*/
static unsigned int get_server_context_flags( DWORD flags )
{
unsigned int ret = 0;
flags &= ~CONTEXT_i386; /* get rid of CPU id */
if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS;
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
if (flags & CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS;
return ret;
}
/***********************************************************************
* context_to_server
*
@ -1328,7 +1348,12 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
x86_thread_data()->dr6 == context->Dr6 &&
x86_thread_data()->dr7 == context->Dr7);
if (!self) ret = set_thread_context( handle, context, &self );
if (!self)
{
context_t server_context;
context_to_server( &server_context, context );
ret = set_thread_context( handle, &server_context, &self );
}
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
return ret;
@ -1355,7 +1380,11 @@ NTSTATUS CDECL DECLSPEC_HIDDEN __regs_NtGetContextThread( DWORD edi, DWORD esi,
if (!self)
{
if ((ret = get_thread_context( handle, context, &self ))) return ret;
context_t server_context;
unsigned int server_flags = get_server_context_flags( context->ContextFlags );
if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret;
if ((ret = context_from_server( context, &server_context ))) return ret;
needed_flags &= ~context->ContextFlags;
}

View File

@ -274,6 +274,23 @@ static void set_cpu_context( const CONTEXT *context )
}
/***********************************************************************
* get_server_context_flags
*
* Convert CPU-specific flags to generic server flags
*/
static unsigned int get_server_context_flags( DWORD flags )
{
unsigned int ret = 0;
if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
return ret;
}
/***********************************************************************
* copy_context
*
@ -577,8 +594,10 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
{
NTSTATUS ret;
BOOL self;
context_t server_context;
ret = set_thread_context( handle, context, &self );
context_to_server( &server_context, context );
ret = set_thread_context( handle, &server_context, &self );
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
return ret;
}
@ -596,7 +615,11 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
if (!self)
{
if ((ret = get_thread_context( handle, context, &self ))) return ret;
context_t server_context;
unsigned int server_flags = get_server_context_flags( context->ContextFlags );
if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret;
if ((ret = context_from_server( context, &server_context ))) return ret;
needed_flags &= ~context->ContextFlags;
}

View File

@ -1913,6 +1913,25 @@ void DECLSPEC_HIDDEN set_cpu_context( const CONTEXT *context )
}
/***********************************************************************
* get_server_context_flags
*
* Convert CPU-specific flags to generic server flags
*/
static unsigned int get_server_context_flags( DWORD flags )
{
unsigned int ret = 0;
flags &= ~CONTEXT_AMD64; /* get rid of CPU id */
if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS;
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
return ret;
}
/***********************************************************************
* copy_context
*
@ -2123,8 +2142,12 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
amd64_thread_data()->dr6 == context->Dr6 &&
amd64_thread_data()->dr7 == context->Dr7);
if (!self) ret = set_thread_context( handle, context, &self );
if (!self)
{
context_t server_context;
context_to_server( &server_context, context );
ret = set_thread_context( handle, &server_context, &self );
}
if (self && ret == STATUS_SUCCESS) set_cpu_context( context );
return ret;
}
@ -2145,7 +2168,11 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
if (!self)
{
if ((ret = get_thread_context( handle, context, &self ))) return ret;
context_t server_context;
unsigned int server_flags = get_server_context_flags( context->ContextFlags );
if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret;
if ((ret = context_from_server( context, &server_context ))) return ret;
needed_flags &= ~context->ContextFlags;
}

View File

@ -855,19 +855,16 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void)
/***********************************************************************
* set_thread_context
*/
NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
NTSTATUS set_thread_context( HANDLE handle, const context_t *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) );
wine_server_add_data( req, context, sizeof(*context) );
ret = wine_server_call( req );
*self = reply->self;
}
@ -881,7 +878,7 @@ NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
{
req->handle = wine_server_obj_handle( handle );
req->suspend = 0;
wine_server_add_data( req, &server_context, sizeof(server_context) );
wine_server_add_data( req, context, sizeof(*context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
@ -901,45 +898,20 @@ NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
}
/* convert CPU-specific flags to generic server flags */
static inline unsigned int get_server_context_flags( DWORD flags )
{
unsigned int ret = 0;
flags &= 0x3f; /* mask CPU id flags */
if (flags & CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL;
if (flags & CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER;
#ifdef CONTEXT_SEGMENTS
if (flags & CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS;
#endif
#ifdef CONTEXT_FLOATING_POINT
if (flags & CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT;
#endif
#ifdef CONTEXT_DEBUG_REGISTERS
if (flags & CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS;
#endif
#ifdef CONTEXT_EXTENDED_REGISTERS
if (flags & CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS;
#endif
return ret;
}
/***********************************************************************
* get_thread_context
*/
NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self )
NTSTATUS get_thread_context( HANDLE handle, context_t *context, unsigned int flags, 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->flags = flags;
req->suspend = 1;
wine_server_set_reply( req, &server_context, sizeof(server_context) );
wine_server_set_reply( req, context, sizeof(*context) );
ret = wine_server_call( req );
*self = reply->self;
}
@ -952,9 +924,9 @@ NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self )
SERVER_START_REQ( get_thread_context )
{
req->handle = wine_server_obj_handle( handle );
req->flags = server_flags;
req->flags = flags;
req->suspend = 0;
wine_server_set_reply( req, &server_context, sizeof(server_context) );
wine_server_set_reply( req, context, sizeof(*context) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
@ -969,7 +941,6 @@ NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self )
NtResumeThread( handle, &dummy );
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
}
if (!ret) ret = context_from_server( context, &server_context );
return ret;
}