Module: wine Branch: master Commit: b8927cf1365e80986c5377e742c1fd72079167fe URL: https://source.winehq.org/git/wine.git/?a=commit;h=b8927cf1365e80986c5377e74...
Author: Zebediah Figura zfigura@codeweavers.com Date: Wed Jun 6 13:30:18 2018 -0500
ntdll: Implement RtlWow64SetThreadContext().
Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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" );