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 *pDbgUiRemoteBreakin)( void *arg ) = NULL;
|
||||||
void (WINAPI *pKiRaiseUserExceptionDispatcher)(void) = 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;
|
NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) = NULL;
|
||||||
void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) = NULL;
|
void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) = NULL;
|
||||||
void (WINAPI *pRtlUserThreadStart)( PRTL_THREAD_START_ROUTINE entry, void *arg ) = 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( DbgUiRemoteBreakin );
|
||||||
GET_FUNC( KiRaiseUserExceptionDispatcher );
|
GET_FUNC( KiRaiseUserExceptionDispatcher );
|
||||||
GET_FUNC( KiUserExceptionDispatcher );
|
GET_FUNC( KiUserExceptionDispatcher );
|
||||||
|
GET_FUNC( KiUserApcDispatcher );
|
||||||
GET_FUNC( LdrInitializeThunk );
|
GET_FUNC( LdrInitializeThunk );
|
||||||
GET_FUNC( RtlUserThreadStart );
|
GET_FUNC( RtlUserThreadStart );
|
||||||
GET_FUNC( __wine_set_unix_funcs );
|
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 )
|
switch( apc->type )
|
||||||
{
|
{
|
||||||
case APC_USER:
|
case APC_USER:
|
||||||
{
|
call_user_apc( context, apc->user.args[0], apc->user.args[1], apc->user.args[2],
|
||||||
void (WINAPI *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR) = wine_server_get_ptr( apc->user.func );
|
wine_server_get_ptr( apc->user.func ));
|
||||||
func( apc->user.args[0], apc->user.args[1], apc->user.args[2] );
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case APC_TIMER:
|
case APC_TIMER:
|
||||||
{
|
call_user_apc( context, (ULONG_PTR)wine_server_get_ptr( apc->user.args[1] ),
|
||||||
void (WINAPI *func)(void*, unsigned int, unsigned int) = wine_server_get_ptr( apc->user.func );
|
(DWORD)apc->timer.time, (DWORD)(apc->timer.time >> 32),
|
||||||
func( wine_server_get_ptr( apc->user.args[1] ),
|
wine_server_get_ptr( apc->user.func ));
|
||||||
(DWORD)apc->timer.time, (DWORD)(apc->timer.time >> 32) );
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
server_protocol_error( "get_apc_request: bad type %d\n", apc->type );
|
server_protocol_error( "get_apc_request: bad type %d\n", apc->type );
|
||||||
break;
|
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 )
|
const LARGE_INTEGER *timeout )
|
||||||
{
|
{
|
||||||
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
|
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
|
||||||
BOOL user_apc = FALSE;
|
|
||||||
unsigned int ret;
|
unsigned int ret;
|
||||||
user_apc_t apc;
|
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;
|
abs_timeout -= now.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;)
|
ret = server_select( select_op, size, flags, abs_timeout, NULL, NULL, &apc );
|
||||||
{
|
if (ret == STATUS_USER_APC) invoke_apc( NULL, &apc );
|
||||||
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;
|
|
||||||
|
|
||||||
/* A test on Windows 2000 shows that Windows always yields during
|
/* 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
|
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. */
|
boost as well. This seems to model that behavior the closest. */
|
||||||
if (ret == STATUS_TIMEOUT) NtYieldExecution();
|
if (ret == STATUS_TIMEOUT) NtYieldExecution();
|
||||||
|
|
||||||
return ret;
|
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
|
* server_queue_process_apc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -575,6 +575,29 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
|
||||||
REGn_sig(2, sigcontext) = (DWORD)pKiUserExceptionDispatcher;
|
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,
|
void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
|
||||||
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,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();
|
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,
|
void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
|
||||||
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) )
|
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1181,7 +1181,7 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
|
||||||
}
|
}
|
||||||
if (needed_flags & CONTEXT_CONTROL)
|
if (needed_flags & CONTEXT_CONTROL)
|
||||||
{
|
{
|
||||||
context->Esp = (DWORD)&frame->thunk_addr;
|
context->Esp = (DWORD)&frame->ret_addr;
|
||||||
context->Ebp = frame->ebp;
|
context->Ebp = frame->ebp;
|
||||||
context->Eip = frame->thunk_addr;
|
context->Eip = frame->thunk_addr;
|
||||||
context->EFlags = 0x202;
|
context->EFlags = 0x202;
|
||||||
|
@ -1535,6 +1535,29 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
|
||||||
setup_raise_exception( sigcontext, stack, rec, &context );
|
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,
|
__ASM_GLOBAL_FUNC( call_user_exception_dispatcher,
|
||||||
"add $4,%esp\n\t"
|
"add $4,%esp\n\t"
|
||||||
"movl (%esp),%eax\n\t" /* rec */
|
"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 );
|
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,
|
extern void WINAPI user_exception_dispatcher_trampoline( struct stack_layout *stack,
|
||||||
void *pKiUserExceptionDispatcher );
|
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.@)
|
* NtQueueApcThread (NTDLL.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -85,6 +85,7 @@ static const SIZE_T signal_stack_size = 0x10000 - 0x3000;
|
||||||
/* callbacks to PE ntdll from the Unix side */
|
/* callbacks to PE ntdll from the Unix side */
|
||||||
extern void (WINAPI *pDbgUiRemoteBreakin)( void *arg ) DECLSPEC_HIDDEN;
|
extern void (WINAPI *pDbgUiRemoteBreakin)( void *arg ) DECLSPEC_HIDDEN;
|
||||||
extern void (WINAPI *pKiRaiseUserExceptionDispatcher)(void) 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 NTSTATUS (WINAPI *pKiUserExceptionDispatcher)(EXCEPTION_RECORD*,CONTEXT*) DECLSPEC_HIDDEN;
|
||||||
extern void (WINAPI *pLdrInitializeThunk)(CONTEXT*,void**,ULONG_PTR,ULONG_PTR) 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;
|
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 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,
|
extern void WINAPI call_user_exception_dispatcher( EXCEPTION_RECORD *rec, CONTEXT *context,
|
||||||
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) ) DECLSPEC_HIDDEN;
|
NTSTATUS (WINAPI *dispatcher)(EXCEPTION_RECORD*,CONTEXT*) ) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue