Zebediah Figura : ntdll: Implement RtlWow64SetThreadContext().

Alexandre Julliard julliard at winehq.org
Tue Jun 12 17:36:03 CDT 2018


Module: wine
Branch: master
Commit: b8927cf1365e80986c5377e742c1fd72079167fe
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=b8927cf1365e80986c5377e742c1fd72079167fe

Author: Zebediah Figura <zfigura at codeweavers.com>
Date:   Wed Jun  6 13:30:18 2018 -0500

ntdll: Implement RtlWow64SetThreadContext().

Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/ntdll.spec        |  1 +
 dlls/ntdll/signal_x86_64.c   | 82 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/tests/exception.c |  6 ++++
 3 files changed, 89 insertions(+)

diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index d493e4f..45cedb7 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -979,6 +979,7 @@
 @ stdcall RtlWow64EnableFsRedirection(long)
 @ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
 @ stdcall -arch=x86_64 RtlWow64GetThreadContext(long ptr)
+@ stdcall -arch=x86_64 RtlWow64SetThreadContext(long ptr)
 @ stub RtlWriteMemoryStream
 @ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long)
 @ stub RtlZeroHeap
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 8d45ba8..0d25360 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -2284,6 +2284,74 @@ static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *f
     return STATUS_SUCCESS;
 }
 
+/***********************************************************************
+ *           wow64_context_to_server
+ */
+static void 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) );
+    }
+}
+
 
 /******************************************************************************
  *              RtlWow64GetThreadContext  (NTDLL.@)
@@ -2300,6 +2368,20 @@ NTSTATUS WINAPI RtlWow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context
     return wow64_context_from_server( context, &server_context );
 }
 
+
+/******************************************************************************
+ *              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_thread_context( handle, &server_context, &self );
+}
+
+
 extern void raise_func_trampoline( EXCEPTION_RECORD *rec, CONTEXT *context, raise_func func );
 __ASM_GLOBAL_FUNC( raise_func_trampoline,
                    __ASM_CFI(".cfi_signal_frame\n\t")
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 9310297..e30cd59 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" );
 




More information about the wine-cvs mailing list