Signed-off-by: Zebediah Figura zfigura@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 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" );
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 ) {