diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c index de5a42aec4f..d2bb054b6d0 100644 --- a/dlls/wow64/syscall.c +++ b/dlls/wow64/syscall.c @@ -84,6 +84,13 @@ struct user_callback_frame __wine_jmp_buf jmpbuf; }; +/* stack frame for user APCs */ +struct user_apc_frame +{ + struct user_apc_frame *prev_frame; + CONTEXT *context; + void *wow_context; +}; SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock = NULL; @@ -416,8 +423,14 @@ NTSTATUS WINAPI wow64_NtContinue( UINT *args ) BOOLEAN alertable = get_ulong( &args ); NTSTATUS status = get_context_return_value( context ); + struct user_apc_frame *frame = NtCurrentTeb()->TlsSlots[WOW64_TLS_APCLIST]; pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, context ); + + while (frame && frame->wow_context != context) frame = frame->prev_frame; + NtCurrentTeb()->TlsSlots[WOW64_TLS_APCLIST] = frame ? frame->prev_frame : NULL; + if (frame) NtContinue( frame->context, alertable ); + if (alertable) NtTestAlert(); return status; } @@ -981,13 +994,11 @@ void * WINAPI Wow64AllocateTemp( SIZE_T size ) */ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CONTEXT *context ) { - NTSTATUS retval; + struct user_apc_frame frame; -#ifdef __x86_64__ - retval = context->Rax; -#elif defined(__aarch64__) - retval = context->X0; -#endif + frame.prev_frame = NtCurrentTeb()->TlsSlots[WOW64_TLS_APCLIST]; + frame.context = context; + NtCurrentTeb()->TlsSlots[WOW64_TLS_APCLIST] = &frame; /* cf. 32-bit call_user_apc_dispatcher */ switch (current_machine) @@ -1014,10 +1025,11 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON stack->arg2 = arg2; stack->arg3 = arg3; stack->context = ctx; - stack->context.Eax = retval; ctx.Esp = PtrToUlong( stack ); ctx.Eip = pLdrSystemDllInitBlock->pKiUserApcDispatcher; + frame.wow_context = &stack->context; pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx ); + cpu_simulate(); } break; @@ -1035,14 +1047,15 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON stack = (struct apc_stack_layout *)ULongToPtr( ctx.Sp & ~15 ) - 1; stack->func = arg1 >> 32; stack->context = ctx; - stack->context.R0 = retval; ctx.Sp = PtrToUlong( stack ); ctx.Pc = pLdrSystemDllInitBlock->pKiUserApcDispatcher; ctx.R0 = PtrToUlong( &stack->context ); ctx.R1 = arg1; ctx.R2 = arg2; ctx.R3 = arg3; + frame.wow_context = &stack->context; pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx ); + cpu_simulate(); } break; } @@ -1112,7 +1125,7 @@ NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len, memcpy( args_data, args, len ); ctx.R0 = id; - ctx.R1 = PtrToUlong( args ); + ctx.R1 = PtrToUlong( args_data ); ctx.R2 = len; ctx.Sp = PtrToUlong( args_data ); ctx.Pc = pLdrSystemDllInitBlock->pKiUserCallbackDispatcher; diff --git a/include/winternl.h b/include/winternl.h index 95abf79812b..f2992b82857 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1083,6 +1083,7 @@ typedef struct _TEB64 #define WOW64_TLS_CPURESERVED 1 #define WOW64_TLS_TEMPLIST 3 #define WOW64_TLS_USERCALLBACKDATA 5 +#define WOW64_TLS_APCLIST 7 #define WOW64_TLS_FILESYSREDIR 8 #define WOW64_TLS_MAX_NUMBER 19