Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- include/winnt.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+)
diff --git a/include/winnt.h b/include/winnt.h index 54bf11d..c41eff4 100644 --- a/include/winnt.h +++ b/include/winnt.h @@ -2112,6 +2112,96 @@ typedef CONTEXT *PCONTEXT;
NTSYSAPI void WINAPI RtlCaptureContext(CONTEXT*);
+#define WOW64_CONTEXT_i386 0x00010000 +#define WOW64_CONTEXT_i486 0x00010000 +#define WOW64_CONTEXT_CONTROL (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000001)) +#define WOW64_CONTEXT_INTEGER (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000002)) +#define WOW64_CONTEXT_SEGMENTS (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000004)) +#define WOW64_CONTEXT_FLOATING_POINT (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000008)) +#define WOW64_CONTEXT_DEBUG_REGISTERS (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000010)) +#define WOW64_CONTEXT_EXTENDED_REGISTERS (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000020)) +#define WOW64_CONTEXT_FULL (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS) +#define WOW64_CONTEXT_ALL (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | \ + WOW64_CONTEXT_SEGMENTS | WOW64_CONTEXT_FLOATING_POINT | \ + WOW64_CONTEXT_DEBUG_REGISTERS | WOW64_CONTEXT_EXTENDED_REGISTERS) + +#define WOW64_CONTEXT_XSTATE (WOW64_CONTEXT_i386 | __MSABI_LONG(0x00000040)) + +#define WOW64_CONTEXT_EXCEPTION_ACTIVE 0x08000000 +#define WOW64_CONTEXT_SERVICE_ACTIVE 0x10000000 +#define WOW64_CONTEXT_EXCEPTION_REQUEST 0x40000000 +#define WOW64_CONTEXT_EXCEPTION_REPORTING 0x80000000 + +#define WOW64_SIZE_OF_80387_REGISTERS 80 +#define WOW64_MAXIMUM_SUPPORTED_EXTENSION 512 + +typedef struct _WOW64_FLOATING_SAVE_AREA { + DWORD ControlWord; + DWORD StatusWord; + DWORD TagWord; + DWORD ErrorOffset; + DWORD ErrorSelector; + DWORD DataOffset; + DWORD DataSelector; + BYTE RegisterArea[WOW64_SIZE_OF_80387_REGISTERS]; + DWORD Cr0NpxState; +} WOW64_FLOATING_SAVE_AREA, *PWOW64_FLOATING_SAVE_AREA; + +#include "pshpack4.h" +typedef struct _WOW64_CONTEXT { + DWORD ContextFlags; + DWORD Dr0; + DWORD Dr1; + DWORD Dr2; + DWORD Dr3; + DWORD Dr6; + DWORD Dr7; + WOW64_FLOATING_SAVE_AREA FloatSave; + DWORD SegGs; + DWORD SegFs; + DWORD SegEs; + DWORD SegDs; + DWORD Edi; + DWORD Esi; + DWORD Ebx; + DWORD Edx; + DWORD Ecx; + DWORD Eax; + DWORD Ebp; + DWORD Eip; + DWORD SegCs; + DWORD EFlags; + DWORD Esp; + DWORD SegSs; + BYTE ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION]; +} WOW64_CONTEXT, *PWOW64_CONTEXT; +#include "poppack.h" + +typedef struct _WOW64_LDT_ENTRY { + WORD LimitLow; + WORD BaseLow; + union { + struct { + BYTE BaseMid; + BYTE Flags1; + BYTE Flags2; + BYTE BaseHi; + } Bytes; + struct { + DWORD BaseMid : 8; + DWORD Type : 5; + DWORD Dpl : 2; + DWORD Pres : 1; + DWORD LimitHi : 4; + DWORD Sys : 1; + DWORD Reserved_0 : 1; + DWORD Default_Big : 1; + DWORD Granularity : 1; + DWORD BaseHi : 8; + } Bits; + } HighWord; +} WOW64_LDT_ENTRY, *PWOW64_LDT_ENTRY; + /* * Product types */
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- v3: fix test failures on Vista
dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/tests/exception.c | 36 ++++++++++++++ dlls/ntdll/thread.c | 114 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 143 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index c0f5d6f..f1dd6ed 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -977,6 +977,7 @@ @ stdcall RtlWalkHeap(long ptr) @ stdcall RtlWow64EnableFsRedirection(long) @ stdcall RtlWow64EnableFsRedirectionEx(long ptr) +@ stdcall -arch=win64 RtlWow64GetThreadContext(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 c47c8cb..9310297 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -149,6 +149,7 @@ static PRUNTIME_FUNCTION (WINAPI *pRtlLookupFunctionEntry)(ULONG64, ULONG64*, UN static EXCEPTION_DISPOSITION (WINAPI *p__C_specific_handler)(EXCEPTION_RECORD*, ULONG64, CONTEXT*, DISPATCHER_CONTEXT*); static VOID (WINAPI *pRtlCaptureContext)(CONTEXT*); static VOID (CDECL *pRtlRestoreContext)(CONTEXT*, EXCEPTION_RECORD*); +static NTSTATUS (WINAPI *pRtlWow64GetThreadContext)(HANDLE, WOW64_CONTEXT *); static VOID (CDECL *pRtlUnwindEx)(VOID*, VOID*, EXCEPTION_RECORD*, VOID*, CONTEXT*, UNWIND_HISTORY_TABLE*); static int (CDECL *p_setjmp)(_JUMP_BUFFER*); #endif @@ -2490,6 +2491,38 @@ static void test_dpe_exceptions(void) pRtlRemoveVectoredExceptionHandler(handler); }
+static void test_wow64_context(void) +{ + char cmdline[] = "C:\windows\syswow64\notepad.exe"; + PROCESS_INFORMATION pi; + STARTUPINFOA si = {0}; + WOW64_CONTEXT ctx; + NTSTATUS ret; + + memset(&ctx, 0x55, sizeof(ctx)); + ctx.ContextFlags = WOW64_CONTEXT_ALL; + ret = pRtlWow64GetThreadContext( GetCurrentThread(), &ctx ); + ok(ret == STATUS_INVALID_PARAMETER || broken(ret == STATUS_PARTIAL_COPY), "got %#x\n", ret); + + CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi); + + ret = pRtlWow64GetThreadContext( pi.hThread, &ctx ); + ok(ret == STATUS_SUCCESS, "got %#x\n", ret); + ok(ctx.ContextFlags == WOW64_CONTEXT_ALL, "got context flags %#x\n", ctx.ContextFlags); + ok(!ctx.Ebp, "got ebp %08x\n", ctx.Ebp); + ok(!ctx.Ecx, "got ecx %08x\n", ctx.Ecx); + ok(!ctx.Edx, "got edx %08x\n", ctx.Edx); + ok(!ctx.Esi, "got esi %08x\n", ctx.Esi); + ok(!ctx.Edi, "got edi %08x\n", ctx.Edi); + ok((ctx.EFlags & ~2) == 0x200, "got eflags %08x\n", ctx.EFlags); + ok((WORD) ctx.FloatSave.ControlWord == 0x27f, "got control word %08x\n", + ctx.FloatSave.ControlWord); + ok(*(WORD *)ctx.ExtendedRegisters == 0x27f, "got SSE control word %04x\n", + *(WORD *)ctx.ExtendedRegisters); + + pNtTerminateProcess(pi.hProcess, 0); +} + #endif /* __x86_64__ */
#if defined(__i386__) || defined(__x86_64__) @@ -3128,6 +3161,8 @@ START_TEST(exception) "RtlRestoreContext" ); pRtlUnwindEx = (void *)GetProcAddress( hntdll, "RtlUnwindEx" ); + pRtlWow64GetThreadContext = (void *)GetProcAddress( hntdll, + "RtlWow64GetThreadContext" ); p_setjmp = (void *)GetProcAddress( hmsvcrt, "_setjmp" );
@@ -3143,6 +3178,7 @@ START_TEST(exception) test_restore_context(); test_prot_fault(); test_dpe_exceptions(); + test_wow64_context();
if (pRtlAddFunctionTable && pRtlDeleteFunctionTable && pRtlInstallFunctionTableCallback && pRtlLookupFunctionEntry) test_dynamic_unwind(); diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index 35e23d2..df04b33 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -924,22 +924,18 @@ static inline unsigned int get_server_context_flags( DWORD flags ) return ret; }
-/*********************************************************************** - * get_thread_context - */ -NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self ) +static NTSTATUS get_server_context( HANDLE handle, unsigned int server_flags, + context_t *context, BOOL *self ) { NTSTATUS ret; DWORD dummy, i; - unsigned int server_flags = get_server_context_flags( context->ContextFlags ); - context_t server_context;
SERVER_START_REQ( get_thread_context ) { req->handle = wine_server_obj_handle( handle ); req->flags = server_flags; req->suspend = 1; - wine_server_set_reply( req, &server_context, sizeof(server_context) ); + wine_server_set_reply( req, context, sizeof(*context) ); ret = wine_server_call( req ); *self = reply->self; } @@ -954,7 +950,7 @@ NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self ) req->handle = wine_server_obj_handle( handle ); req->flags = server_flags; req->suspend = 0; - wine_server_set_reply( req, &server_context, sizeof(server_context) ); + wine_server_set_reply( req, context, sizeof(*context) ); ret = wine_server_call( req ); } SERVER_END_REQ; @@ -969,10 +965,112 @@ NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self ) NtResumeThread( handle, &dummy ); if (ret == STATUS_PENDING) ret = STATUS_ACCESS_DENIED; } + return ret; +} + +NTSTATUS get_thread_context( HANDLE handle, CONTEXT *context, BOOL *self) +{ + context_t server_context; + unsigned int server_flags = get_server_context_flags( context->ContextFlags ); + NTSTATUS ret = get_server_context( handle, server_flags, &server_context, self); if (!ret) ret = context_from_server( context, &server_context ); return ret; }
+#ifdef _WIN64 +/* convert CPU-specific flags to generic server flags */ +static inline unsigned int wow64_get_server_context_flags( DWORD flags ) +{ + unsigned int ret = 0; + + flags &= 0x3f; /* mask CPU id flags */ + if (flags & WOW64_CONTEXT_CONTROL) ret |= SERVER_CTX_CONTROL; + if (flags & WOW64_CONTEXT_INTEGER) ret |= SERVER_CTX_INTEGER; + if (flags & WOW64_CONTEXT_SEGMENTS) ret |= SERVER_CTX_SEGMENTS; + if (flags & WOW64_CONTEXT_FLOATING_POINT) ret |= SERVER_CTX_FLOATING_POINT; + if (flags & WOW64_CONTEXT_DEBUG_REGISTERS) ret |= SERVER_CTX_DEBUG_REGISTERS; + if (flags & WOW64_CONTEXT_EXTENDED_REGISTERS) ret |= SERVER_CTX_EXTENDED_REGISTERS; + return ret; +} + +static NTSTATUS wow64_context_from_server( WOW64_CONTEXT *to, const context_t *from ) +{ + if (from->cpu != CPU_x86) return STATUS_INVALID_PARAMETER; + + to->ContextFlags = WOW64_CONTEXT_i386; + if (from->flags & SERVER_CTX_CONTROL) + { + to->ContextFlags |= WOW64_CONTEXT_CONTROL; + to->Ebp = from->ctl.i386_regs.ebp; + to->Esp = from->ctl.i386_regs.esp; + to->Eip = from->ctl.i386_regs.eip; + to->SegCs = from->ctl.i386_regs.cs; + to->SegSs = from->ctl.i386_regs.ss; + to->EFlags = from->ctl.i386_regs.eflags; + } + if (from->flags & SERVER_CTX_INTEGER) + { + to->ContextFlags |= WOW64_CONTEXT_INTEGER; + to->Eax = from->integer.i386_regs.eax; + to->Ebx = from->integer.i386_regs.ebx; + to->Ecx = from->integer.i386_regs.ecx; + to->Edx = from->integer.i386_regs.edx; + to->Esi = from->integer.i386_regs.esi; + to->Edi = from->integer.i386_regs.edi; + } + if (from->flags & SERVER_CTX_SEGMENTS) + { + to->ContextFlags |= WOW64_CONTEXT_SEGMENTS; + to->SegDs = from->seg.i386_regs.ds; + to->SegEs = from->seg.i386_regs.es; + to->SegFs = from->seg.i386_regs.fs; + to->SegGs = from->seg.i386_regs.gs; + } + if (from->flags & SERVER_CTX_FLOATING_POINT) + { + to->ContextFlags |= WOW64_CONTEXT_FLOATING_POINT; + to->FloatSave.ControlWord = from->fp.i386_regs.ctrl; + to->FloatSave.StatusWord = from->fp.i386_regs.status; + to->FloatSave.TagWord = from->fp.i386_regs.tag; + to->FloatSave.ErrorOffset = from->fp.i386_regs.err_off; + to->FloatSave.ErrorSelector = from->fp.i386_regs.err_sel; + to->FloatSave.DataOffset = from->fp.i386_regs.data_off; + to->FloatSave.DataSelector = from->fp.i386_regs.data_sel; + to->FloatSave.Cr0NpxState = from->fp.i386_regs.cr0npx; + memcpy( to->FloatSave.RegisterArea, from->fp.i386_regs.regs, sizeof(to->FloatSave.RegisterArea) ); + } + if (from->flags & SERVER_CTX_DEBUG_REGISTERS) + { + to->ContextFlags |= WOW64_CONTEXT_DEBUG_REGISTERS; + to->Dr0 = from->debug.i386_regs.dr0; + to->Dr1 = from->debug.i386_regs.dr1; + to->Dr2 = from->debug.i386_regs.dr2; + to->Dr3 = from->debug.i386_regs.dr3; + to->Dr6 = from->debug.i386_regs.dr6; + to->Dr7 = from->debug.i386_regs.dr7; + } + if (from->flags & SERVER_CTX_EXTENDED_REGISTERS) + { + to->ContextFlags |= WOW64_CONTEXT_EXTENDED_REGISTERS; + memcpy( to->ExtendedRegisters, from->ext.i386_regs, sizeof(to->ExtendedRegisters) ); + } + return STATUS_SUCCESS; +} + + +/****************************************************************************** + * RtlWow64GetThreadContext (NTDLL.@) + */ +NTSTATUS WINAPI RtlWow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context ) +{ + BOOL self; + context_t server_context; + unsigned int server_flags = wow64_get_server_context_flags( context->ContextFlags ); + NTSTATUS ret = get_server_context( handle, server_flags, &server_context, &self ); + if (!ret) ret = wow64_context_from_server( context, &server_context ); + return ret; +} +#endif
/****************************************************************************** * NtQueryInformationThread (NTDLL.@)
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 ) {
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernel32/kernel32.spec | 2 +- dlls/kernel32/thread.c | 18 ++++++++++++++++++ include/winbase.h | 1 + include/winternl.h | 3 +++ 4 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 9ed5dfb..1cb0b54 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -1600,7 +1600,7 @@ @ stdcall WinExec(str long) @ stdcall Wow64EnableWow64FsRedirection(long) @ stdcall Wow64DisableWow64FsRedirection(ptr) -# @ stub Wow64GetThreadContext +@ stdcall Wow64GetThreadContext(long ptr) # @ stub Wow64GetThreadSelectorEntry @ stdcall Wow64RevertWow64FsRedirection(ptr) # @ stub Wow64SetThreadContext diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c index b6ca9f260..3aa2887 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c @@ -251,6 +251,24 @@ BOOL WINAPI GetThreadContext( HANDLE handle, /* [in] Handle to thread with }
+/*********************************************************************** + * Wow64GetThreadContext [KERNEL32.@] + */ +BOOL WINAPI Wow64GetThreadContext( HANDLE handle, WOW64_CONTEXT *context) +{ +#ifdef __i386__ + NTSTATUS status = NtGetContextThread( handle, (CONTEXT *)context ); +#elif defined(_WIN64) + NTSTATUS status = RtlWow64GetThreadContext( handle, context ); +#else + NTSTATUS status = STATUS_NOT_IMPLEMENTED; + FIXME("not implemented on this platform\n"); +#endif + if (status) SetLastError( RtlNtStatusToDosError(status) ); + return !status; +} + + /********************************************************************** * SuspendThread [KERNEL32.@] Suspends a thread. * diff --git a/include/winbase.h b/include/winbase.h index 4ddc1d3..f7239b8 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2706,6 +2706,7 @@ WINBASEAPI VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE); WINBASEAPI UINT WINAPI WinExec(LPCSTR,UINT); WINBASEAPI BOOL WINAPI Wow64DisableWow64FsRedirection(PVOID*); WINBASEAPI BOOLEAN WINAPI Wow64EnableWow64FsRedirection(BOOLEAN); +WINBASEAPI BOOL WINAPI Wow64GetThreadContext(HANDLE, WOW64_CONTEXT *); WINBASEAPI BOOL WINAPI Wow64RevertWow64FsRedirection(PVOID); WINADVAPI DWORD WINAPI WriteEncryptedFileRaw(PFE_IMPORT_FUNC,PVOID,PVOID); WINBASEAPI BOOL WINAPI WriteFile(HANDLE,LPCVOID,DWORD,LPDWORD,LPOVERLAPPED); diff --git a/include/winternl.h b/include/winternl.h index 3ecd068..9361825 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2836,6 +2836,9 @@ NTSYSAPI void WINAPI RtlWakeConditionVariable(RTL_CONDITION_VARIABLE *); NTSYSAPI NTSTATUS WINAPI RtlWalkHeap(HANDLE,PVOID); NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirection(BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx(ULONG,ULONG*); +#ifdef _WIN64 +NTSYSAPI NTSTATUS WINAPI RtlWow64GetThreadContext(HANDLE, WOW64_CONTEXT *); +#endif NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG,PCWSTR,PCWSTR,ULONG,PVOID,ULONG); NTSYSAPI NTSTATUS WINAPI RtlZombifyActivationContext(HANDLE); NTSYSAPI NTSTATUS WINAPI RtlpNtCreateKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,const UNICODE_STRING*,ULONG,PULONG);
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/kernel32/kernel32.spec | 2 +- dlls/kernel32/thread.c | 17 +++++++++++++++++ include/winbase.h | 1 + include/winternl.h | 1 + 4 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 1cb0b54..de6f007 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -1603,7 +1603,7 @@ @ stdcall Wow64GetThreadContext(long ptr) # @ stub Wow64GetThreadSelectorEntry @ stdcall Wow64RevertWow64FsRedirection(ptr) -# @ stub Wow64SetThreadContext +@ stdcall Wow64SetThreadContext(long ptr) # @ stub Wow64SuspendThread @ stdcall WriteConsoleA(long ptr long ptr ptr) @ stdcall WriteConsoleInputA(long ptr long ptr) diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c index 3aa2887..eb304dc 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c @@ -236,6 +236,23 @@ BOOL WINAPI SetThreadContext( HANDLE handle, /* [in] Handle to thread
/*********************************************************************** + * Wow64SetThreadContext [KERNEL32.@] + */ +BOOL WINAPI Wow64SetThreadContext( HANDLE handle, const WOW64_CONTEXT *context) +{ +#ifdef __i386__ + NTSTATUS status = NtSetContextThread( handle, (const CONTEXT *)context ); +#elif defined(_WIN64) + NTSTATUS status = RtlWow64SetThreadContext( handle, context ); +#else + NTSTATUS status = STATUS_NOT_IMPLEMENTED; + FIXME("not implemented on this platform\n"); +#endif + if (status) SetLastError( RtlNtStatusToDosError(status) ); + return !status; +} + +/*********************************************************************** * GetThreadContext [KERNEL32.@] Retrieves context of thread. * * RETURNS diff --git a/include/winbase.h b/include/winbase.h index f7239b8..667df96 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2708,6 +2708,7 @@ WINBASEAPI BOOL WINAPI Wow64DisableWow64FsRedirection(PVOID*); WINBASEAPI BOOLEAN WINAPI Wow64EnableWow64FsRedirection(BOOLEAN); WINBASEAPI BOOL WINAPI Wow64GetThreadContext(HANDLE, WOW64_CONTEXT *); WINBASEAPI BOOL WINAPI Wow64RevertWow64FsRedirection(PVOID); +WINBASEAPI BOOL WINAPI Wow64SetThreadContext(HANDLE, const WOW64_CONTEXT *); WINADVAPI DWORD WINAPI WriteEncryptedFileRaw(PFE_IMPORT_FUNC,PVOID,PVOID); WINBASEAPI BOOL WINAPI WriteFile(HANDLE,LPCVOID,DWORD,LPDWORD,LPOVERLAPPED); WINBASEAPI BOOL WINAPI WriteFileEx(HANDLE,LPCVOID,DWORD,LPOVERLAPPED,LPOVERLAPPED_COMPLETION_ROUTINE); diff --git a/include/winternl.h b/include/winternl.h index 9361825..9341c40 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2838,6 +2838,7 @@ NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirection(BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlWow64EnableFsRedirectionEx(ULONG,ULONG*); #ifdef _WIN64 NTSYSAPI NTSTATUS WINAPI RtlWow64GetThreadContext(HANDLE, WOW64_CONTEXT *); +NTSYSAPI NTSTATUS WINAPI RtlWow64SetThreadContext(HANDLE, const WOW64_CONTEXT *); #endif NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG,PCWSTR,PCWSTR,ULONG,PVOID,ULONG); NTSYSAPI NTSTATUS WINAPI RtlZombifyActivationContext(HANDLE);