/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntdll/dispatch/amd64/dispatch.S * PURPOSE: Usermode dispatcher stubs * * PROGRAMMER: Timo kreuzer (timo.kreuzer@reactos.org) */ /* INCLUDES ******************************************************************/ #include #include EXTERN NtContinue:PROC EXTERN LdrpInit:PROC EXTERN ZwCallbackReturn:PROC EXTERN RtlRaiseStatus:PROC .code PUBLIC LdrInitializeThunk .PROC LdrInitializeThunk mov rbp, 0 .setframe rbp, 0 .endprolog /* First parameter is the APC context */ mov rcx, r9 jmp LdrpInit .ENDP PUBLIC KiUserApcDispatcher .PROC KiUserApcDispatcher .endprolog /* We enter with a 16 byte aligned stack */ mov rcx, [rsp + CONTEXT_P1Home] /* NormalContext */ mov rdx, [rsp + CONTEXT_P2Home] /* SystemArgument1 */ mov r8, [rsp + CONTEXT_P3Home] /* SystemArgument2 */ lea r9, [rsp] /* Context */ call qword ptr [rsp + CONTEXT_P4Home] /* NormalRoutine */ /* NtContinue(Context, TRUE); */ lea rcx, [rsp] mov dl, 1 call NtContinue nop int 3 .ENDP PUBLIC KiRaiseUserExceptionDispatcher .PROC KiRaiseUserExceptionDispatcher .endprolog int 3 .ENDP PUBLIC KiUserCallbackDispatcher .PROC KiUserCallbackDispatcher /* The stack is set up with a UCALLOUT_FRAME */ /* The frame ends with a MACHINE_FRAME. */ .PUSHFRAME /* This is for the Home space, Buffer, Length and ApiNumber */ .ALLOCSTACK (6 * 8) .ENDPROLOG #if DBG /* We enter the function with a fully setup stack, so it must be aligned! */ test rsp, 15 jz AlignmentOk int HEX(2C) AlignmentOk: #endif /* Get the parameters from the callout frame */ mov rcx, [rsp + CkBuffer] mov edx, [rsp + CkLength] mov r8d, [rsp + CkApiNumber] /* Get the callback table */ mov rax, gs:[TePeb] mov r9, [rax + PeKernelCallbackTable] /* Call the routine */ call qword ptr [r9 + r8 * 8] /* Return from callback */ xor ecx, ecx xor edx, edx mov r8d, eax call ZwCallbackReturn /* Save callback return value */ mov esi, eax /* Raise status */ StatusRaise: mov ecx, esi call RtlRaiseStatus jmp StatusRaise .ENDP /* BOOLEAN NTAPI RtlDispatchException( _In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT ContextRecord); */ EXTERN RtlDispatchException:PROC /* NTSTATUS NTAPI ZwContinue( _In_ PCONTEXT Context, _In_ BOOLEAN TestAlert); */ EXTERN ZwContinue:PROC /* NTSTATUS NTAPI ZwRaiseException( _In_ PEXCEPTION_RECORD ExceptionRecord, _In_ PCONTEXT Context, _In_ BOOLEAN SearchFrames); */ EXTERN ZwRaiseException:PROC /* VOID NTAPI RtlRaiseStatus( _In_ PEXCEPTION_RECORD ExceptionRecord); */ EXTERN RtlRaiseException:PROC /* VOID KiUserExceptionDispatcher( CONTEXT ContextRecord, PEXCEPTION_RECORD ExceptionRecord); This function is called with the following stack layout: CONTEXT ContextRecord <- RSP, RCX EXCEPTION_RECORD ExceptionRecord <- RDX ULONG64 Alignment MACHINE_FRAME MachineFrame */ PUBLIC KiUserExceptionDispatcher .PROC KiUserExceptionDispatcher /* The stack is set up with a KUSER_EXCEPTION_STACK */ /* The frame ends with a MACHINE_FRAME. */ .PUSHFRAME /* This is for the alignment, EXCEPTION_RECORD and CONTEXT */ .ALLOCSTACK 8 + EXCEPTION_RECORD_LENGTH + CONTEXT_FRAME_LENGTH .ENDPROLOG /* Clear direction flag */ cld /* Dispatch the exception */ call RtlDispatchException /* Check for success */ or al, al jz RaiseException /* We're fine, continue execution */ lea rcx, [rsp] /* ContextRecord */ mov dl, 0 /* TestAlert */ call ZwContinue /* Exit */ jmp Exit RaiseException: /* Raise the exception */ lea rcx, [rsp + CONTEXT_FRAME_LENGTH] /* ExceptionRecord */ lea rdx, [rsp] /* ContextRecord */ xor r8, r8 call ZwRaiseException Exit: lea rcx, [rsp + CONTEXT_FRAME_LENGTH] /* ExceptionRecord */ mov rdx, rax call KiUserExceptionDispatcherNested ret .ENDP /* VOID KiUserExceptionDispatcherNested( _In_ ExceptionRecord, _In_ Status ) */ .PROC KiUserExceptionDispatcherNested /* Allocate space for the nested exception record */ sub rsp, EXCEPTION_RECORD_LENGTH .ALLOCSTACK EXCEPTION_RECORD_LENGTH .ENDPROLOG /* Set it up */ mov dword ptr [rsp + ErNumberParameters], 0 mov dword ptr [rsp + ErExceptionFlags], EXCEPTION_NONCONTINUABLE mov [rsp + ErExceptionRecord], rcx mov [rsp + ErExceptionCode], edx /* Raise the exception */ mov rcx, rsp call RtlRaiseException /* Cleanup stack and return */ add rsp, EXCEPTION_RECORD_LENGTH ret .ENDP END