ntdll: Implement RtlWow64GetThreadContext().
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
36371075f8
commit
f135c81b31
|
@ -978,6 +978,7 @@
|
|||
@ stdcall RtlWalkHeap(long ptr)
|
||||
@ stdcall RtlWow64EnableFsRedirection(long)
|
||||
@ stdcall RtlWow64EnableFsRedirectionEx(long ptr)
|
||||
@ stdcall -arch=x86_64 RtlWow64GetThreadContext(long ptr)
|
||||
@ stub RtlWriteMemoryStream
|
||||
@ stdcall RtlWriteRegistryValue(long ptr ptr long ptr long)
|
||||
@ stub RtlZeroHeap
|
||||
|
|
|
@ -2200,6 +2200,106 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* wow64_get_server_context_flags
|
||||
*/
|
||||
static unsigned int wow64_get_server_context_flags( DWORD flags )
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
|
||||
flags &= ~WOW64_CONTEXT_i386; /* get rid of CPU id */
|
||||
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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* wow64_context_from_server
|
||||
*/
|
||||
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;
|
||||
NTSTATUS ret;
|
||||
context_t server_context;
|
||||
unsigned int server_flags = wow64_get_server_context_flags( context->ContextFlags );
|
||||
|
||||
if ((ret = get_thread_context( handle, &server_context, server_flags, &self ))) return ret;
|
||||
if (self) return STATUS_INVALID_PARAMETER;
|
||||
return wow64_context_from_server( context, &server_context );
|
||||
}
|
||||
|
||||
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")
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue