Commit c244fe3d authored by Alexandre Julliard's avatar Alexandre Julliard

wow64: Keep track of APC stack frames, similarly to user callback frames.

And use the appropriate frame to restore the context in NtContinue.
parent 96841d03
...@@ -84,6 +84,13 @@ struct user_callback_frame ...@@ -84,6 +84,13 @@ struct user_callback_frame
__wine_jmp_buf jmpbuf; __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; SYSTEM_DLL_INIT_BLOCK *pLdrSystemDllInitBlock = NULL;
...@@ -416,8 +423,14 @@ NTSTATUS WINAPI wow64_NtContinue( UINT *args ) ...@@ -416,8 +423,14 @@ NTSTATUS WINAPI wow64_NtContinue( UINT *args )
BOOLEAN alertable = get_ulong( &args ); BOOLEAN alertable = get_ulong( &args );
NTSTATUS status = get_context_return_value( context ); NTSTATUS status = get_context_return_value( context );
struct user_apc_frame *frame = NtCurrentTeb()->TlsSlots[WOW64_TLS_APCLIST];
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, context ); 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(); if (alertable) NtTestAlert();
return status; return status;
} }
...@@ -981,13 +994,11 @@ void * WINAPI Wow64AllocateTemp( SIZE_T size ) ...@@ -981,13 +994,11 @@ void * WINAPI Wow64AllocateTemp( SIZE_T size )
*/ */
void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CONTEXT *context ) void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CONTEXT *context )
{ {
NTSTATUS retval; struct user_apc_frame frame;
#ifdef __x86_64__ frame.prev_frame = NtCurrentTeb()->TlsSlots[WOW64_TLS_APCLIST];
retval = context->Rax; frame.context = context;
#elif defined(__aarch64__) NtCurrentTeb()->TlsSlots[WOW64_TLS_APCLIST] = &frame;
retval = context->X0;
#endif
/* cf. 32-bit call_user_apc_dispatcher */ /* cf. 32-bit call_user_apc_dispatcher */
switch (current_machine) switch (current_machine)
...@@ -1014,10 +1025,11 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON ...@@ -1014,10 +1025,11 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON
stack->arg2 = arg2; stack->arg2 = arg2;
stack->arg3 = arg3; stack->arg3 = arg3;
stack->context = ctx; stack->context = ctx;
stack->context.Eax = retval;
ctx.Esp = PtrToUlong( stack ); ctx.Esp = PtrToUlong( stack );
ctx.Eip = pLdrSystemDllInitBlock->pKiUserApcDispatcher; ctx.Eip = pLdrSystemDllInitBlock->pKiUserApcDispatcher;
frame.wow_context = &stack->context;
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx ); pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx );
cpu_simulate();
} }
break; break;
...@@ -1035,14 +1047,15 @@ void WINAPI Wow64ApcRoutine( ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, CON ...@@ -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 = (struct apc_stack_layout *)ULongToPtr( ctx.Sp & ~15 ) - 1;
stack->func = arg1 >> 32; stack->func = arg1 >> 32;
stack->context = ctx; stack->context = ctx;
stack->context.R0 = retval;
ctx.Sp = PtrToUlong( stack ); ctx.Sp = PtrToUlong( stack );
ctx.Pc = pLdrSystemDllInitBlock->pKiUserApcDispatcher; ctx.Pc = pLdrSystemDllInitBlock->pKiUserApcDispatcher;
ctx.R0 = PtrToUlong( &stack->context ); ctx.R0 = PtrToUlong( &stack->context );
ctx.R1 = arg1; ctx.R1 = arg1;
ctx.R2 = arg2; ctx.R2 = arg2;
ctx.R3 = arg3; ctx.R3 = arg3;
frame.wow_context = &stack->context;
pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx ); pBTCpuSetContext( GetCurrentThread(), GetCurrentProcess(), NULL, &ctx );
cpu_simulate();
} }
break; break;
} }
...@@ -1112,7 +1125,7 @@ NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len, ...@@ -1112,7 +1125,7 @@ NTSTATUS WINAPI Wow64KiUserCallbackDispatcher( ULONG id, void *args, ULONG len,
memcpy( args_data, args, len ); memcpy( args_data, args, len );
ctx.R0 = id; ctx.R0 = id;
ctx.R1 = PtrToUlong( args ); ctx.R1 = PtrToUlong( args_data );
ctx.R2 = len; ctx.R2 = len;
ctx.Sp = PtrToUlong( args_data ); ctx.Sp = PtrToUlong( args_data );
ctx.Pc = pLdrSystemDllInitBlock->pKiUserCallbackDispatcher; ctx.Pc = pLdrSystemDllInitBlock->pKiUserCallbackDispatcher;
......
...@@ -1083,6 +1083,7 @@ typedef struct _TEB64 ...@@ -1083,6 +1083,7 @@ typedef struct _TEB64
#define WOW64_TLS_CPURESERVED 1 #define WOW64_TLS_CPURESERVED 1
#define WOW64_TLS_TEMPLIST 3 #define WOW64_TLS_TEMPLIST 3
#define WOW64_TLS_USERCALLBACKDATA 5 #define WOW64_TLS_USERCALLBACKDATA 5
#define WOW64_TLS_APCLIST 7
#define WOW64_TLS_FILESYSREDIR 8 #define WOW64_TLS_FILESYSREDIR 8
#define WOW64_TLS_MAX_NUMBER 19 #define WOW64_TLS_MAX_NUMBER 19
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment