Alexandre Julliard : ntdll:
Get registers on the client side for NtGetContextThread on the current
thread .
Alexandre Julliard
julliard at wine.codeweavers.com
Thu Apr 20 08:46:18 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: d2ad6f83556449bcd8a798191cfc8f0ae8b6d950
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=d2ad6f83556449bcd8a798191cfc8f0ae8b6d950
Author: Alexandre Julliard <julliard at winehq.org>
Date: Thu Apr 20 15:40:28 2006 +0200
ntdll: Get registers on the client side for NtGetContextThread on the current thread.
---
dlls/ntdll/ntdll_misc.h | 1 +
dlls/ntdll/signal_i386.c | 32 ++++++++++++++++---
dlls/ntdll/signal_powerpc.c | 11 ++++++
dlls/ntdll/signal_sparc.c | 11 ++++++
dlls/ntdll/signal_x86_64.c | 11 ++++++
dlls/ntdll/thread.c | 74 ++++++++++++++++++++++++++-----------------
server/context_i386.c | 5 +--
7 files changed, 109 insertions(+), 36 deletions(-)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 35cbd5b..fa18e46 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -32,6 +32,7 @@ #define MAX_NT_PATH_LENGTH 277
/* 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 */
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 39b20d0..398dbdf 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -704,6 +704,20 @@ #endif
/***********************************************************************
+ * 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
*
* Restore the FPU context to a sigcontext.
@@ -762,10 +776,7 @@ #ifdef FPU_sig
else
#endif
{
-#ifdef __GNUC__
- context->ContextFlags |= CONTEXT_FLOATING_POINT;
- __asm__ __volatile__( "fnsave %0; fwait" : "=m" (context->FloatSave) );
-#endif
+ save_fpu( context );
}
}
@@ -824,6 +835,19 @@ #endif
/***********************************************************************
+ * 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
*
* Set the new CPU context. Used by NtSetContextThread.
diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c
index 50d48d4..cbe4f80 100644
--- a/dlls/ntdll/signal_powerpc.c
+++ b/dlls/ntdll/signal_powerpc.c
@@ -269,6 +269,17 @@ #undef C
/***********************************************************************
+ * get_cpu_context
+ *
+ * Get the context of the current thread.
+ */
+void get_cpu_context( CONTEXT *context )
+{
+ FIXME("not implemented\n");
+}
+
+
+/***********************************************************************
* set_cpu_context
*
* Set the new CPU context.
diff --git a/dlls/ntdll/signal_sparc.c b/dlls/ntdll/signal_sparc.c
index 4ae3340..0bf8dac 100644
--- a/dlls/ntdll/signal_sparc.c
+++ b/dlls/ntdll/signal_sparc.c
@@ -149,6 +149,17 @@ static void restore_fpu( CONTEXT *contex
/***********************************************************************
+ * get_cpu_context
+ *
+ * Get the context of the current thread.
+ */
+void get_cpu_context( CONTEXT *context )
+{
+ FIXME("not implemented\n");
+}
+
+
+/***********************************************************************
* set_cpu_context
*
* Set the new CPU context.
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 87d40b5..4ae61e7 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -199,6 +199,17 @@ static void restore_context( const CONTE
/***********************************************************************
+ * get_cpu_context
+ *
+ * Get the context of the current thread.
+ */
+void get_cpu_context( CONTEXT *context )
+{
+ FIXME("not implemented\n");
+}
+
+
+/***********************************************************************
* set_cpu_context
*
* Set the new CPU context.
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index b4226f9..67e6930 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -921,47 +921,64 @@ NTSTATUS WINAPI NtGetContextThread( HAND
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 )
+ {
+ 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)
{
- for (i = 0; i < 100; i++)
+ if (NtSuspendThread( handle, &dummy ) == STATUS_SUCCESS)
{
- SERVER_START_REQ( get_thread_context )
+ for (i = 0; i < 100; i++)
{
- req->handle = handle;
- req->flags = context->ContextFlags;
- req->suspend = 0;
- wine_server_set_reply( req, &ctx, sizeof(ctx) );
- ret = wine_server_call( req );
+ 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();
}
- SERVER_END_REQ;
- if (ret != STATUS_PENDING) break;
- NtYieldExecution();
+ NtResumeThread( handle, &dummy );
}
- 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 @@ #ifdef __i386__
}
#endif
}
- else if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED;
- return ret;
+ return STATUS_SUCCESS;
}
diff --git a/server/context_i386.c b/server/context_i386.c
index ce7fd9b..0a3a329 100644
--- a/server/context_i386.c
+++ b/server/context_i386.c
@@ -550,10 +550,9 @@ void get_thread_context( struct thread *
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 ))
{
More information about the wine-cvs
mailing list