ntdll: Use KiUserApcDispatcher() to call user APCs.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
2a08e0e290
commit
7a71f98640
|
@ -96,6 +96,7 @@ extern IMAGE_NT_HEADERS __wine_spec_nt_header;
|
|||
|
||||
void (WINAPI *pDbgUiRemoteBreakin)( void *arg ) = NULL;
|
||||
void (WINAPI *pKiRaiseUserExceptionDispatcher)(void) = NULL;
|
||||
void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULONG_PTR,PNTAPCFUNC) = NULL;
|
||||
NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) = NULL;
|
||||
void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) = NULL;
|
||||
void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) = NULL;
|
||||
|
@ -841,6 +842,7 @@ static void fixup_ntdll_imports( const IMAGE_NT_HEADERS *nt )
|
|||
GET_FUNC( DbgUiRemoteBreakin );
|
||||
GET_FUNC( KiRaiseUserExceptionDispatcher );
|
||||
GET_FUNC( KiUserExceptionDispatcher );
|
||||
GET_FUNC( KiUserApcDispatcher );
|
||||
GET_FUNC( LdrInitializeThunk );
|
||||
GET_FUNC( RtlUserThreadStart );
|
||||
GET_FUNC( __wine_set_unix_funcs );
|
||||
|
|
|
@ -349,23 +349,19 @@ static int wait_select_reply( void *cookie )
|
|||
}
|
||||
|
||||
|
||||
static void invoke_apc( const user_apc_t *apc )
|
||||
static void invoke_apc( CONTEXT *context, const user_apc_t *apc )
|
||||
{
|
||||
switch( apc->type )
|
||||
{
|
||||
case APC_USER:
|
||||
{
|
||||
void (WINAPI *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR) = wine_server_get_ptr( apc->user.func );
|
||||
func( apc->user.args[0], apc->user.args[1], apc->user.args[2] );
|
||||
call_user_apc( context, apc->user.args[0], apc->user.args[1], apc->user.args[2],
|
||||
wine_server_get_ptr( apc->user.func ));
|
||||
break;
|
||||
}
|
||||
case APC_TIMER:
|
||||
{
|
||||
void (WINAPI *func)(void*, unsigned int, unsigned int) = wine_server_get_ptr( apc->user.func );
|
||||
func( wine_server_get_ptr( apc->user.args[1] ),
|
||||
(DWORD)apc->timer.time, (DWORD)(apc->timer.time >> 32) );
|
||||
call_user_apc( context, (ULONG_PTR)wine_server_get_ptr( apc->user.args[1] ),
|
||||
(DWORD)apc->timer.time, (DWORD)(apc->timer.time >> 32),
|
||||
wine_server_get_ptr( apc->user.func ));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
server_protocol_error( "get_apc_request: bad type %d\n", apc->type );
|
||||
break;
|
||||
|
@ -672,7 +668,6 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f
|
|||
const LARGE_INTEGER *timeout )
|
||||
{
|
||||
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
|
||||
BOOL user_apc = FALSE;
|
||||
unsigned int ret;
|
||||
user_apc_t apc;
|
||||
|
||||
|
@ -684,33 +679,31 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f
|
|||
abs_timeout -= now.QuadPart;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ret = server_select( select_op, size, flags, abs_timeout, NULL, NULL, &apc );
|
||||
if (ret != STATUS_USER_APC) break;
|
||||
invoke_apc( &apc );
|
||||
|
||||
/* if we ran a user apc we have to check once more if additional apcs are queued,
|
||||
* but we don't want to wait */
|
||||
abs_timeout = 0;
|
||||
user_apc = TRUE;
|
||||
size = 0;
|
||||
/* don't signal multiple times */
|
||||
if (size >= sizeof(select_op->signal_and_wait) && select_op->op == SELECT_SIGNAL_AND_WAIT)
|
||||
size = offsetof( select_op_t, signal_and_wait.signal );
|
||||
}
|
||||
|
||||
if (ret == STATUS_TIMEOUT && user_apc) ret = STATUS_USER_APC;
|
||||
ret = server_select( select_op, size, flags, abs_timeout, NULL, NULL, &apc );
|
||||
if (ret == STATUS_USER_APC) invoke_apc( NULL, &apc );
|
||||
|
||||
/* A test on Windows 2000 shows that Windows always yields during
|
||||
a wait, but a wait that is hit by an event gets a priority
|
||||
boost as well. This seems to model that behavior the closest. */
|
||||
if (ret == STATUS_TIMEOUT) NtYieldExecution();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* NtContinue (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable )
|
||||
{
|
||||
user_apc_t apc;
|
||||
NTSTATUS status;
|
||||
|
||||
status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, NULL, &apc );
|
||||
if (status == STATUS_USER_APC) invoke_apc( context, &apc );
|
||||
return NtSetContextThread( GetCurrentThread(), context );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* server_queue_process_apc
|
||||
*/
|
||||
|
|
|
@ -575,6 +575,29 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
|
|||
REGn_sig(2, sigcontext) = (DWORD)pKiUserExceptionDispatcher;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_user_apc
|
||||
*/
|
||||
void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
|
||||
ULONG_PTR arg2, PNTAPCFUNC func )
|
||||
{
|
||||
CONTEXT context;
|
||||
|
||||
if (!context_ptr)
|
||||
{
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
NtGetContextThread( GetCurrentThread(), &context );
|
||||
context.R0 = STATUS_USER_APC;
|
||||
context_ptr = &context;
|
||||
}
|
||||
pKiUserApcDispatcher( context_ptr, ctx, arg1, arg2, func );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_user_exception_dispatcher
|
||||
*/
|
||||
void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
|
||||
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) )
|
||||
{
|
||||
|
|
|
@ -579,6 +579,29 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
|
|||
REGn_sig(18, sigcontext) = (ULONG_PTR)NtCurrentTeb();
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_user_apc
|
||||
*/
|
||||
void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
|
||||
ULONG_PTR arg2, PNTAPCFUNC func )
|
||||
{
|
||||
CONTEXT context;
|
||||
|
||||
if (!context_ptr)
|
||||
{
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
NtGetContextThread( GetCurrentThread(), &context );
|
||||
context.u.s.X0 = STATUS_USER_APC;
|
||||
context_ptr = &context;
|
||||
}
|
||||
pKiUserApcDispatcher( context_ptr, ctx, arg1, arg2, func );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_user_exception_dispatcher
|
||||
*/
|
||||
void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
|
||||
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) )
|
||||
{
|
||||
|
|
|
@ -1181,7 +1181,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
|||
}
|
||||
if (needed_flags & CONTEXT_CONTROL)
|
||||
{
|
||||
context->Esp = (DWORD)&frame->thunk_addr;
|
||||
context->Esp = (DWORD)&frame->ret_addr;
|
||||
context->Ebp = frame->ebp;
|
||||
context->Eip = frame->thunk_addr;
|
||||
context->EFlags = 0x202;
|
||||
|
@ -1535,6 +1535,29 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
|
|||
setup_raise_exception( sigcontext, stack, rec, &context );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_user_apc
|
||||
*/
|
||||
void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
|
||||
ULONG_PTR arg2, PNTAPCFUNC func )
|
||||
{
|
||||
CONTEXT context;
|
||||
|
||||
if (!context_ptr)
|
||||
{
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
NtGetContextThread( GetCurrentThread(), &context );
|
||||
context.Eax = STATUS_USER_APC;
|
||||
context_ptr = &context;
|
||||
}
|
||||
pKiUserApcDispatcher( context_ptr, ctx, arg1, arg2, func );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_user_exception_dispatcher
|
||||
*/
|
||||
__ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
|
||||
"add $4,%esp\n\t"
|
||||
"movl (%esp),%eax\n\t" /* rec */
|
||||
|
|
|
@ -1887,6 +1887,30 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
|
|||
setup_raise_exception( sigcontext, rec, &context );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_user_apc
|
||||
*/
|
||||
void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
|
||||
ULONG_PTR arg2, PNTAPCFUNC func )
|
||||
{
|
||||
CONTEXT context;
|
||||
|
||||
if (!context_ptr)
|
||||
{
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
NtGetContextThread( GetCurrentThread(), &context );
|
||||
context.Rax = STATUS_USER_APC;
|
||||
context_ptr = &context;
|
||||
}
|
||||
pKiUserApcDispatcher( context_ptr, ctx, arg1, arg2, func );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* call_user_exception_dispatcher
|
||||
*/
|
||||
|
||||
extern void WINAPI user_exception_dispatcher_trampoline( struct stack_layout *stack,
|
||||
void *pKiUserExceptionDispatcher );
|
||||
|
||||
|
|
|
@ -519,18 +519,6 @@ NTSTATUS WINAPI NtTerminateThread( HANDLE handle, LONG exit_code )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* NtContinue (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable )
|
||||
{
|
||||
static const LARGE_INTEGER zero_timeout;
|
||||
|
||||
if (alertable) server_wait( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, &zero_timeout );
|
||||
return NtSetContextThread( GetCurrentThread(), context );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* NtQueueApcThread (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -85,6 +85,7 @@ static const SIZE_T signal_stack_size = 0x10000 - 0x3000;
|
|||
/* callbacks to PE ntdll from the Unix side */
|
||||
extern void (WINAPI *pDbgUiRemoteBreakin)( void *arg ) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pKiRaiseUserExceptionDispatcher)(void) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pKiUserApcDispatcher)(CONTEXT*,ULONG_PTR,ULONG_PTR,ULONG_PTR,PNTAPCFUNC) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) DECLSPEC_HIDDEN;
|
||||
extern void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) DECLSPEC_HIDDEN;
|
||||
|
@ -257,6 +258,8 @@ extern void init_cpu_info(void) DECLSPEC_HIDDEN;
|
|||
|
||||
extern void dbg_init(void) DECLSPEC_HIDDEN;
|
||||
|
||||
extern void WINAPI call_user_apc( CONTEXT *context_ptr, ULONG_PTR ctx, ULONG_PTR arg1,
|
||||
ULONG_PTR arg2, PNTAPCFUNC func ) DECLSPEC_HIDDEN;
|
||||
extern void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
|
||||
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) ) DECLSPEC_HIDDEN;
|
||||
|
||||
|
|
Loading…
Reference in New Issue