[PATCH v2 3/5] ntdll: Implement RtlWow64SetThreadContext().

Zebediah Figura zfigura at codeweavers.com
Wed Jun 6 12:43:33 CDT 2018


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/ntdll/ntdll.spec        |  1 +
 dlls/ntdll/tests/exception.c |  6 +++
 dlls/ntdll/thread.c          | 96 +++++++++++++++++++++++++++++++++++++++-----
 3 files changed, 93 insertions(+), 10 deletions(-)

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index f1dd6ed..77cc1ae 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -978,6 +978,7 @@
 @ stdcall RtlWow64EnableFsRedirection(long)
 @ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
 @ stdcall -arch=win64 RtlWow64GetThreadContext(long ptr)
+@ stdcall -arch=win64 RtlWow64SetThreadContext(long ptr)
 @ stub RtlWriteMemoryStream
 @ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long)
 @ stub RtlZeroHeap
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 0ab3812..f09e86d 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -150,6 +150,7 @@ static EXCEPTION_DISPOSITION (WINAPI *p__C_specific_handler)(EXCEPTION_RECORD*,
 static VOID      (WINAPI *pRtlCaptureContext)(CONTEXT*);
 static VOID      (CDECL *pRtlRestoreContext)(CONTEXT*, EXCEPTION_RECORD*);
 static NTSTATUS  (WINAPI *pRtlWow64GetThreadContext)(HANDLE, WOW64_CONTEXT *);
+static NTSTATUS  (WINAPI *pRtlWow64SetThreadContext)(HANDLE, const WOW64_CONTEXT *);
 static VOID      (CDECL *pRtlUnwindEx)(VOID*, VOID*, EXCEPTION_RECORD*, VOID*, CONTEXT*, UNWIND_HISTORY_TABLE*);
 static int       (CDECL *p_setjmp)(_JUMP_BUFFER*);
 #endif
@@ -2520,6 +2521,9 @@ static void test_wow64_context(void)
     ok(*(WORD *)ctx.ExtendedRegisters == 0x27f, "got SSE control word %04x\n",
        *(WORD *)ctx.ExtendedRegisters);
 
+    ret = pRtlWow64SetThreadContext( pi.hThread, &ctx );
+    ok(ret == STATUS_SUCCESS, "got %#x\n", ret);
+
     pNtTerminateProcess(pi.hProcess, 0);
 }
 
@@ -3163,6 +3167,8 @@ START_TEST(exception)
                                                                  "RtlUnwindEx" );
     pRtlWow64GetThreadContext          = (void *)GetProcAddress( hntdll,
                                                                  "RtlWow64GetThreadContext" );
+    pRtlWow64SetThreadContext          = (void *)GetProcAddress( hntdll,
+                                                                 "RtlWow64SetThreadContext" );
     p_setjmp                           = (void *)GetProcAddress( hmsvcrt,
                                                                  "_setjmp" );
 
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index df04b33..52c7953 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -851,23 +851,16 @@ TEB_ACTIVE_FRAME * WINAPI RtlGetFrame(void)
     return NtCurrentTeb()->ActiveFrame;
 }
 
-
-/***********************************************************************
- *              set_thread_context
- */
-NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
+static NTSTATUS set_server_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 +874,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;
@@ -900,6 +893,12 @@ NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
     return ret;
 }
 
+NTSTATUS set_thread_context( HANDLE handle, const CONTEXT *context, BOOL *self )
+{
+    context_t server_context;
+    context_to_server( &server_context, context );
+    return set_server_context( handle, &server_context, self );
+}
 
 /* convert CPU-specific flags to generic server flags */
 static inline unsigned int get_server_context_flags( DWORD flags )
@@ -978,6 +977,83 @@ NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self)
 }
 
 #ifdef _WIN64
+static NTSTATUS wow64_context_to_server( context_t *to, const WOW64_CONTEXT *from )
+{
+    DWORD flags = from->ContextFlags & ~WOW64_CONTEXT_i386;  /* get rid of CPU id */
+
+    memset( to, 0, sizeof(*to) );
+    to->cpu = CPU_x86;
+
+    if (flags & WOW64_CONTEXT_CONTROL)
+    {
+        to->flags |= SERVER_CTX_CONTROL;
+        to->ctl.i386_regs.ebp    = from->Ebp;
+        to->ctl.i386_regs.esp    = from->Esp;
+        to->ctl.i386_regs.eip    = from->Eip;
+        to->ctl.i386_regs.cs     = from->SegCs;
+        to->ctl.i386_regs.ss     = from->SegSs;
+        to->ctl.i386_regs.eflags = from->EFlags;
+    }
+    if (flags & WOW64_CONTEXT_INTEGER)
+    {
+        to->flags |= SERVER_CTX_INTEGER;
+        to->integer.i386_regs.eax = from->Eax;
+        to->integer.i386_regs.ebx = from->Ebx;
+        to->integer.i386_regs.ecx = from->Ecx;
+        to->integer.i386_regs.edx = from->Edx;
+        to->integer.i386_regs.esi = from->Esi;
+        to->integer.i386_regs.edi = from->Edi;
+    }
+    if (flags & WOW64_CONTEXT_SEGMENTS)
+    {
+        to->flags |= SERVER_CTX_SEGMENTS;
+        to->seg.i386_regs.ds = from->SegDs;
+        to->seg.i386_regs.es = from->SegEs;
+        to->seg.i386_regs.fs = from->SegFs;
+        to->seg.i386_regs.gs = from->SegGs;
+    }
+    if (flags & WOW64_CONTEXT_FLOATING_POINT)
+    {
+        to->flags |= SERVER_CTX_FLOATING_POINT;
+        to->fp.i386_regs.ctrl     = from->FloatSave.ControlWord;
+        to->fp.i386_regs.status   = from->FloatSave.StatusWord;
+        to->fp.i386_regs.tag      = from->FloatSave.TagWord;
+        to->fp.i386_regs.err_off  = from->FloatSave.ErrorOffset;
+        to->fp.i386_regs.err_sel  = from->FloatSave.ErrorSelector;
+        to->fp.i386_regs.data_off = from->FloatSave.DataOffset;
+        to->fp.i386_regs.data_sel = from->FloatSave.DataSelector;
+        to->fp.i386_regs.cr0npx   = from->FloatSave.Cr0NpxState;
+        memcpy( to->fp.i386_regs.regs, from->FloatSave.RegisterArea, sizeof(to->fp.i386_regs.regs) );
+    }
+    if (flags & WOW64_CONTEXT_DEBUG_REGISTERS)
+    {
+        to->flags |= SERVER_CTX_DEBUG_REGISTERS;
+        to->debug.i386_regs.dr0 = from->Dr0;
+        to->debug.i386_regs.dr1 = from->Dr1;
+        to->debug.i386_regs.dr2 = from->Dr2;
+        to->debug.i386_regs.dr3 = from->Dr3;
+        to->debug.i386_regs.dr6 = from->Dr6;
+        to->debug.i386_regs.dr7 = from->Dr7;
+    }
+    if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS)
+    {
+        to->flags |= SERVER_CTX_EXTENDED_REGISTERS;
+        memcpy( to->ext.i386_regs, from->ExtendedRegisters, sizeof(to->ext.i386_regs) );
+    }
+    return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ *              RtlWow64SetThreadContext  (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlWow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context )
+{
+    BOOL self;
+    context_t server_context;
+    wow64_context_to_server( &server_context, context );
+    return set_server_context( handle, &server_context, &self );
+}
+
 /* convert CPU-specific flags to generic server flags */
 static inline unsigned int wow64_get_server_context_flags( DWORD flags )
 {
-- 
2.7.4




More information about the wine-devel mailing list