ntdll: Get registers on the client side for NtGetContextThread on the current thread.

This commit is contained in:
Alexandre Julliard 2006-04-20 15:40:28 +02:00
parent 63ef9788dd
commit d2ad6f8355
7 changed files with 113 additions and 40 deletions

View File

@ -32,6 +32,7 @@
/* exceptions */
extern void wait_suspend( CONTEXT *context );
extern void WINAPI __regs_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
extern void get_cpu_context( CONTEXT *context );
extern void set_cpu_context( const CONTEXT *context );
/* debug helper */

View File

@ -703,6 +703,20 @@ inline static void *init_handler( const SIGCONTEXT *sigcontext, WORD *fs, WORD *
}
/***********************************************************************
* save_fpu
*
* Save the thread FPU context.
*/
inline static void save_fpu( CONTEXT *context )
{
#ifdef __GNUC__
context->ContextFlags |= CONTEXT_FLOATING_POINT;
__asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
#endif
}
/***********************************************************************
* restore_fpu
*
@ -762,10 +776,7 @@ inline static void save_context( CONTEXT *context, const SIGCONTEXT *sigcontext,
else
#endif
{
#ifdef __GNUC__
context->ContextFlags |= CONTEXT_FLOATING_POINT;
__asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
#endif
save_fpu( context );
}
}
@ -823,6 +834,19 @@ inline static void restore_context( const CONTEXT *context, SIGCONTEXT *sigconte
}
/***********************************************************************
* get_cpu_context
*
* Register function to get the context of the current thread.
*/
void WINAPI __regs_get_cpu_context( CONTEXT *context, CONTEXT *regs )
{
*context = *regs;
save_fpu( context );
}
DEFINE_REGS_ENTRYPOINT( get_cpu_context, 4, 4 );
/***********************************************************************
* set_cpu_context
*

View File

@ -268,6 +268,17 @@ inline static void restore_fpu( CONTEXT *context, const SIGCONTEXT *sigcontext )
}
/***********************************************************************
* get_cpu_context
*
* Get the context of the current thread.
*/
void get_cpu_context( CONTEXT *context )
{
FIXME("not implemented\n");
}
/***********************************************************************
* set_cpu_context
*

View File

@ -148,6 +148,17 @@ static void restore_fpu( CONTEXT *context, ucontext_t *ucontext )
}
/***********************************************************************
* get_cpu_context
*
* Get the context of the current thread.
*/
void get_cpu_context( CONTEXT *context )
{
FIXME("not implemented\n");
}
/***********************************************************************
* set_cpu_context
*

View File

@ -198,6 +198,17 @@ static void restore_context( const CONTEXT *context, SIGCONTEXT *sigcontext )
}
/***********************************************************************
* get_cpu_context
*
* Get the context of the current thread.
*/
void get_cpu_context( CONTEXT *context )
{
FIXME("not implemented\n");
}
/***********************************************************************
* set_cpu_context
*

View File

@ -921,47 +921,64 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
NTSTATUS ret;
CONTEXT ctx;
DWORD dummy, i;
BOOL self = FALSE;
DWORD needed_flags = context->ContextFlags;
BOOL self = (handle == GetCurrentThread());
SERVER_START_REQ( get_thread_context )
{
req->handle = handle;
req->flags = context->ContextFlags;
req->suspend = 0;
wine_server_set_reply( req, &ctx, sizeof(ctx) );
ret = wine_server_call( req );
self = reply->self;
}
SERVER_END_REQ;
#ifdef __i386__
/* on i386 debug registers always require a server call */
if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)) self = FALSE;
#endif
if (ret == STATUS_PENDING)
if (!self)
{
if (NtSuspendThread( handle, &dummy ) == STATUS_SUCCESS)
SERVER_START_REQ( get_thread_context )
{
for (i = 0; i < 100; i++)
{
SERVER_START_REQ( get_thread_context )
{
req->handle = handle;
req->flags = context->ContextFlags;
req->suspend = 0;
wine_server_set_reply( req, &ctx, sizeof(ctx) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
if (ret != STATUS_PENDING) break;
NtYieldExecution();
}
NtResumeThread( handle, &dummy );
req->handle = handle;
req->flags = context->ContextFlags;
req->suspend = 0;
wine_server_set_reply( req, &ctx, sizeof(ctx) );
ret = wine_server_call( req );
self = reply->self;
}
SERVER_END_REQ;
if (ret == STATUS_PENDING)
{
if (NtSuspendThread( handle, &dummy ) == STATUS_SUCCESS)
{
for (i = 0; i < 100; i++)
{
SERVER_START_REQ( get_thread_context )
{
req->handle = handle;
req->flags = context->ContextFlags;
req->suspend = 0;
wine_server_set_reply( req, &ctx, sizeof(ctx) );
ret = wine_server_call( req );
}
SERVER_END_REQ;
if (ret != STATUS_PENDING) break;
NtYieldExecution();
}
NtResumeThread( handle, &dummy );
}
if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
}
if (ret) return ret;
copy_context( context, &ctx, context->ContextFlags & ctx.ContextFlags );
needed_flags &= ~ctx.ContextFlags;
}
if (ret == STATUS_SUCCESS)
if (self)
{
copy_context( context, &ctx, context->ContextFlags );
if (needed_flags)
{
get_cpu_context( &ctx );
copy_context( context, &ctx, ctx.ContextFlags & needed_flags );
}
#ifdef __i386__
/* update the cached version of the debug registers */
if (self && (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386)))
if (context->ContextFlags & (CONTEXT_DEBUG_REGISTERS & ~CONTEXT_i386))
{
struct ntdll_thread_regs * const regs = ntdll_get_thread_regs();
regs->dr0 = context->Dr0;
@ -973,8 +990,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
}
#endif
}
else if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
return ret;
return STATUS_SUCCESS;
}

View File

@ -550,10 +550,9 @@ void get_thread_context( struct thread *thread, CONTEXT *context, unsigned int f
flags &= ~CONTEXT_i386; /* get rid of CPU id */
if (thread->context) /* thread is inside an exception event or suspended */
{
copy_context( context, thread->context, flags );
flags &= CONTEXT_DEBUG_REGISTERS;
}
flags &= CONTEXT_DEBUG_REGISTERS;
if (flags && suspend_for_ptrace( thread ))
{