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/async.c | 1 + server/protocol.def | 5 ++++- server/timer.c | 1 + 10 files changed, 24 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 1929cfa098e..06f4fa2471b 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 );
SERVER_START_REQ( queue_apc ) { @@ -1739,6 +1738,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 fa38f4b87ca..1f6396bee0c 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -388,8 +388,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/async.c b/server/async.c index 1ed241dcb65..4068f744567 100644 --- a/server/async.c +++ b/server/async.c @@ -519,6 +519,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota union apc_call data; memset( &data, 0, sizeof(data) ); data.type = APC_USER; + data.user.flags = 0; data.user.func = async->data.apc; data.user.args[0] = async->data.apc_context; data.user.args[1] = async->data.iosb; 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; diff --git a/server/timer.c b/server/timer.c index 6357569ccba..522fc6a7113 100644 --- a/server/timer.c +++ b/server/timer.c @@ -136,6 +136,7 @@ static void timer_callback( void *private ) assert (timer->callback); memset( &data, 0, sizeof(data) ); data.type = APC_USER; + data.user.flags = 0; data.user.func = timer->callback; data.user.args[0] = timer->arg; data.user.args[1] = (unsigned int)timer->when;