From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/unix/server.c | 2 +- dlls/ntdll/unix/signal_arm.c | 4 +++- dlls/ntdll/unix/signal_arm64.c | 4 +++- dlls/ntdll/unix/signal_i386.c | 4 +++- dlls/ntdll/unix/signal_x86_64.c | 4 +++- dlls/ntdll/unix/thread.c | 4 +++- dlls/ntdll/unix/unix_private.h | 4 ++-- server/protocol.def | 5 ++++- 8 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c index 3969c2bb898..0c99e9c2e66 100644 --- a/dlls/ntdll/unix/server.c +++ b/dlls/ntdll/unix/server.c @@ -385,7 +385,7 @@ static int wait_select_reply( void *cookie ) */ static NTSTATUS invoke_user_apc( CONTEXT *context, const struct user_apc *apc, NTSTATUS status ) { - return call_user_apc_dispatcher( context, apc->args[0], apc->args[1], apc->args[2], + return call_user_apc_dispatcher( context, apc->flags, apc->args[0], apc->args[1], apc->args[2], wine_server_get_ptr( apc->func ), status ); }
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index 45ca9f02c58..e429750925c 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -562,13 +562,15 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ) /*********************************************************************** * call_user_apc_dispatcher */ -NTSTATUS call_user_apc_dispatcher( CONTEXT *context, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, +NTSTATUS call_user_apc_dispatcher( CONTEXT *context, unsigned int flags, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ) { struct syscall_frame *frame = get_syscall_frame(); ULONG sp = context ? context->Sp : frame->sp; struct apc_stack_layout *stack;
+ if (flags) FIXME( "flags %#x are not supported.\n", flags ); + sp &= ~7; stack = (struct apc_stack_layout *)sp - 1; if (context) diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 9964d0a9224..f5bd47d597a 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -747,13 +747,15 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ) /*********************************************************************** * call_user_apc_dispatcher */ -NTSTATUS call_user_apc_dispatcher( CONTEXT *context, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, +NTSTATUS call_user_apc_dispatcher( CONTEXT *context, unsigned int flags, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ) { struct syscall_frame *frame = get_syscall_frame(); ULONG64 sp = context ? context->Sp : frame->sp; struct apc_stack_layout *stack;
+ if (flags) FIXME( "flags %#x are not supported.\n", flags ); + sp &= ~15; stack = (struct apc_stack_layout *)sp - 1; if (context) diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 6eaffbc39c9..db72829bd1f 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1508,13 +1508,15 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ) /*********************************************************************** * call_user_apc_dispatcher */ -NTSTATUS call_user_apc_dispatcher( CONTEXT *context, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, +NTSTATUS call_user_apc_dispatcher( CONTEXT *context, unsigned int flags, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ) { struct syscall_frame *frame = get_syscall_frame(); ULONG esp = context ? context->Esp : frame->esp; struct apc_stack_layout *stack = (struct apc_stack_layout *)esp - 1;
+ if (flags) FIXME( "flags %#x are not supported.\n", flags ); + if (!context) { stack->context.ContextFlags = CONTEXT_FULL; diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 58496685398..59815a47497 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1532,13 +1532,15 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ) /*********************************************************************** * call_user_apc_dispatcher */ -NTSTATUS call_user_apc_dispatcher( CONTEXT *context, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, +NTSTATUS call_user_apc_dispatcher( CONTEXT *context, unsigned int flags, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ) { struct syscall_frame *frame = get_syscall_frame(); ULONG64 rsp = context ? context->Rsp : frame->rsp; struct apc_stack_layout *stack;
+ if (flags) FIXME( "flags %#x are not supported.\n", flags ); + rsp &= ~15; stack = (struct apc_stack_layout *)rsp - 1; if (context) diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 71d1b62803c..e93d75a4bc8 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1729,7 +1729,6 @@ NTSTATUS WINAPI NtQueueApcThreadEx2( HANDLE handle, HANDLE reserve_handle, ULONG union apc_call call;
TRACE( "%p %p %#x %p %p %p %p.\n", handle, reserve_handle, flags, func, (void *)arg1, (void *)arg2, (void *)arg3 ); - if (flags) FIXME( "Unsupported flags %#x.\n", flags );
if (flags & QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC && is_wow64()) return STATUS_NOT_SUPPORTED;
@@ -1741,6 +1740,9 @@ NTSTATUS WINAPI NtQueueApcThreadEx2( HANDLE handle, HANDLE reserve_handle, ULONG { call.type = APC_USER; call.user.func = wine_server_client_ptr( func ); + call.user.flags = 0; + if (flags & QUEUE_USER_APC_FLAGS_SPECIAL_USER_APC) call.user.flags |= SERVER_USER_APC_SPECIAL; + if (flags & QUEUE_USER_APC_CALLBACK_DATA_CONTEXT) call.user.flags |= SERVER_USER_APC_CALLBACK_DATA_CONTEXT; call.user.args[0] = arg1; call.user.args[1] = arg2; call.user.args[2] = arg3; diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 7773c84e333..9a6584efacf 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -387,8 +387,8 @@ extern NTSTATUS wow64_wine_spawnvp( void *args );
extern void dbg_init(void);
-extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, ULONG_PTR arg1, ULONG_PTR arg2, ULONG_PTR arg3, - PNTAPCFUNC func, NTSTATUS status ); +extern NTSTATUS call_user_apc_dispatcher( CONTEXT *context_ptr, unsigned int flags, ULONG_PTR arg1, ULONG_PTR arg2, + ULONG_PTR arg3, PNTAPCFUNC func, NTSTATUS status ); extern NTSTATUS call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context ); extern void call_raise_user_exception_dispatcher(void);
diff --git a/server/protocol.def b/server/protocol.def index 09b6f189162..4e604cc7084 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -507,11 +507,14 @@ enum apc_type struct user_apc { enum apc_type type; /* APC_USER */ - int __pad; + unsigned int flags; /* SERVER_USER_APC_* flags */ client_ptr_t func; /* void (__stdcall *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR); */ apc_param_t args[3]; /* arguments for user function */ };
+#define SERVER_USER_APC_SPECIAL 0x01 +#define SERVER_USER_APC_CALLBACK_DATA_CONTEXT 0x02 + union apc_call { enum apc_type type;