diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index bfc5b34a464..d02a7946945 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1957,12 +1957,15 @@ NTSTATUS set_thread_wow64_context( HANDLE handle, const void *ctx, ULONG size ) } if (flags & CONTEXT_I386_CONTROL) { + WOW64_CPURESERVED *cpu = NtCurrentTeb()->TlsSlots[WOW64_TLS_CPURESERVED]; + wow_frame->Esp = context->Esp; wow_frame->Ebp = context->Ebp; wow_frame->Eip = context->Eip; wow_frame->EFlags = context->EFlags; wow_frame->SegCs = cs32_sel; wow_frame->SegSs = ds64_sel; + cpu->Flags |= WOW64_CPURESERVED_FLAG_RESET_STATE; } if (flags & CONTEXT_I386_SEGMENTS) { diff --git a/dlls/wow64cpu/cpu.c b/dlls/wow64cpu/cpu.c index df292221117..8293d596ec4 100644 --- a/dlls/wow64cpu/cpu.c +++ b/dlls/wow64cpu/cpu.c @@ -82,13 +82,33 @@ __ASM_GLOBAL_FUNC( syscall_32to64, "movl 0xa0(%r13),%esi\n\t" /* context->Esi */ "movl 0xa4(%r13),%ebx\n\t" /* context->Ebx */ "movl 0xb4(%r13),%ebp\n\t" /* context->Ebp */ + "btrl $0,-4(%r13)\n\t" /* cpu->Flags & WOW64_CPURESERVED_FLAG_RESET_STATE */ + "jc 1f\n\t" "movl 0xb8(%r13),%edx\n\t" /* context->Eip */ "movl %edx,(%rsp)\n\t" "movl 0xbc(%r13),%edx\n\t" /* context->SegCs */ "movl %edx,4(%rsp)\n\t" "movl 0xc4(%r13),%r14d\n\t" /* context->Esp */ "xchgq %r14,%rsp\n\t" - "ljmp *(%r14)" ) + "ljmp *(%r14)\n" + "1:\tmovq %rsp,%r14\n\t" + "movl 0xa8(%r13),%edx\n\t" /* context->Edx */ + "movl 0xac(%r13),%ecx\n\t" /* context->Ecx */ + "movl 0xc8(%r13),%eax\n\t" /* context->SegSs */ + "movq %rax,0x20(%rsp)\n\t" + "mov %ax,%ds\n\t" + "mov %ax,%es\n\t" + "mov 0x90(%r13),%fs\n\t" /* context->SegFs */ + "movl 0xc4(%r13),%eax\n\t" /* context->Esp */ + "movq %rax,0x18(%rsp)\n\t" + "movl 0xc0(%r13),%eax\n\t" /* context->EFlags */ + "movq %rax,0x10(%rsp)\n\t" + "movl 0xbc(%r13),%eax\n\t" /* context->SegCs */ + "movq %rax,0x8(%rsp)\n\t" + "movl 0xb8(%r13),%eax\n\t" /* context->Eip */ + "movq %rax,(%rsp)\n\t" + "movl 0xb0(%r13),%eax\n\t" /* context->Eax */ + "iretq" ) /********************************************************************** @@ -137,3 +157,21 @@ void * WINAPI BTCpuGetBopCode(void) { return code_buffer; } + + +/********************************************************************** + * BTCpuGetContext (wow64cpu.@) + */ +NTSTATUS WINAPI BTCpuGetContext( HANDLE thread, HANDLE process, void *unknown, I386_CONTEXT *ctx ) +{ + return NtQueryInformationThread( thread, ThreadWow64Context, ctx, sizeof(*ctx), NULL ); +} + + +/********************************************************************** + * BTCpuSetContext (wow64cpu.@) + */ +NTSTATUS WINAPI BTCpuSetContext( HANDLE thread, HANDLE process, void *unknown, I386_CONTEXT *ctx ) +{ + return NtSetInformationThread( thread, ThreadWow64Context, ctx, sizeof(*ctx) ); +} diff --git a/dlls/wow64cpu/wow64cpu.spec b/dlls/wow64cpu/wow64cpu.spec index ba0abb7a8ed..b86481563f2 100644 --- a/dlls/wow64cpu/wow64cpu.spec +++ b/dlls/wow64cpu/wow64cpu.spec @@ -1,8 +1,8 @@ @ stdcall BTCpuGetBopCode() -#@ stub BTCpuGetContext +@ stdcall BTCpuGetContext(long long ptr ptr) @ stdcall BTCpuProcessInit() #@ stub BTCpuResetToConsistentState -#@ stub BTCpuSetContext +@ stdcall BTCpuSetContext(long long ptr ptr) @ stdcall BTCpuSimulate() #@ stub BTCpuTurboThunkControl #@ stub TurboDispatchJumpAddressEnd diff --git a/include/winternl.h b/include/winternl.h index 9dff3a98bed..a048b9546ee 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3727,6 +3727,8 @@ typedef struct _WOW64_CPURESERVED /* CONTEXT_EX *context_ex */ } WOW64_CPURESERVED, *PWOW64_CPURESERVED; +#define WOW64_CPURESERVED_FLAG_RESET_STATE 1 + typedef struct _WOW64_CPU_AREA_INFO { void *Context;