1/* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntdll/dispatch/amd64/dispatch.S 5 * PURPOSE: Usermode dispatcher stubs 6 * 7 * PROGRAMMER: Timo kreuzer (timo.kreuzer@reactos.org) 8 */ 9 10/* INCLUDES ******************************************************************/ 11 12#include <asm.inc> 13#include <ksamd64.inc> 14 15EXTERN NtContinue:PROC 16EXTERN LdrpInit:PROC 17EXTERN ZwCallbackReturn:PROC 18EXTERN RtlRaiseStatus:PROC 19 20.code 21 22PUBLIC LdrInitializeThunk 23.PROC LdrInitializeThunk 24 mov rbp, 0 25 .setframe rbp, 0 26 .endprolog 27 28 /* First parameter is the APC context */ 29 mov rcx, r9 30 jmp LdrpInit 31 32.ENDP 33 34PUBLIC KiUserApcDispatcher 35.PROC KiUserApcDispatcher 36 .endprolog 37 /* We enter with a 16 byte aligned stack */ 38 39 mov rcx, [rsp + CONTEXT_P1Home] /* NormalContext */ 40 mov rdx, [rsp + CONTEXT_P2Home] /* SystemArgument1 */ 41 mov r8, [rsp + CONTEXT_P3Home] /* SystemArgument2 */ 42 lea r9, [rsp] /* Context */ 43 call qword ptr [rsp + CONTEXT_P4Home] /* NormalRoutine */ 44 45 /* NtContinue(Context, TRUE); */ 46 lea rcx, [rsp] 47 mov dl, 1 48 call NtContinue 49 50 nop 51 int 3 52.ENDP 53 54 55PUBLIC KiRaiseUserExceptionDispatcher 56.PROC KiRaiseUserExceptionDispatcher 57 .endprolog 58 int 3 59 60.ENDP 61 62PUBLIC KiUserCallbackDispatcher 63.PROC KiUserCallbackDispatcher 64 65 /* The stack is set up with a UCALLOUT_FRAME */ 66 /* The frame ends with a MACHINE_FRAME. */ 67 .PUSHFRAME 68 69 /* This is for the Home space, Buffer, Length and ApiNumber */ 70 .ALLOCSTACK (6 * 8) 71 .ENDPROLOG 72 73#if DBG 74 /* We enter the function with a fully setup stack, so it must be aligned! */ 75 test rsp, 15 76 jz AlignmentOk 77 int HEX(2C) 78AlignmentOk: 79#endif 80 81 /* Get the parameters from the callout frame */ 82 mov rcx, [rsp + CkBuffer] 83 mov edx, [rsp + CkLength] 84 mov r8d, [rsp + CkApiNumber] 85 86 /* Get the callback table */ 87 mov rax, gs:[TePeb] 88 mov r9, [rax + PeKernelCallbackTable] 89 90 /* Call the routine */ 91 call qword ptr [r9 + r8 * 8] 92 93 /* Return from callback */ 94 xor ecx, ecx 95 xor edx, edx 96 mov r8d, eax 97 call ZwCallbackReturn 98 99 /* Save callback return value */ 100 mov esi, eax 101 102 /* Raise status */ 103StatusRaise: 104 mov ecx, esi 105 call RtlRaiseStatus 106 jmp StatusRaise 107 108.ENDP 109 110/* 111 BOOLEAN 112 NTAPI 113 RtlDispatchException( 114 _In_ PEXCEPTION_RECORD ExceptionRecord, 115 _In_ PCONTEXT ContextRecord); 116 */ 117EXTERN RtlDispatchException:PROC 118 119/* 120 NTSTATUS 121 NTAPI 122 ZwContinue( 123 _In_ PCONTEXT Context, 124 _In_ BOOLEAN TestAlert); 125 */ 126EXTERN ZwContinue:PROC 127 128/* 129 NTSTATUS 130 NTAPI 131 ZwRaiseException( 132 _In_ PEXCEPTION_RECORD ExceptionRecord, 133 _In_ PCONTEXT Context, 134 _In_ BOOLEAN SearchFrames); 135 */ 136EXTERN ZwRaiseException:PROC 137 138/* 139 VOID 140 NTAPI 141 RtlRaiseStatus( 142 _In_ PEXCEPTION_RECORD ExceptionRecord); 143 */ 144EXTERN RtlRaiseException:PROC 145 146/* 147 VOID 148 KiUserExceptionDispatcher( 149 CONTEXT ContextRecord<rcx>, 150 PEXCEPTION_RECORD ExceptionRecord<rdx>); 151 152 This function is called with the following stack layout: 153 CONTEXT ContextRecord <- RSP, RCX 154 EXCEPTION_RECORD ExceptionRecord <- RDX 155 ULONG64 Alignment 156 MACHINE_FRAME MachineFrame 157 */ 158PUBLIC KiUserExceptionDispatcher 159.PROC KiUserExceptionDispatcher 160 161 /* The stack is set up with a KUSER_EXCEPTION_STACK */ 162 /* The frame ends with a MACHINE_FRAME. */ 163 .PUSHFRAME 164 165 /* This is for the alignment, EXCEPTION_RECORD and CONTEXT */ 166 .ALLOCSTACK 8 + EXCEPTION_RECORD_LENGTH + CONTEXT_FRAME_LENGTH 167 .ENDPROLOG 168 169 /* Clear direction flag */ 170 cld 171 172 /* Dispatch the exception */ 173 call RtlDispatchException 174 175 /* Check for success */ 176 or al, al 177 jz RaiseException 178 179 /* We're fine, continue execution */ 180 lea rcx, [rsp] /* ContextRecord */ 181 mov dl, 0 /* TestAlert */ 182 call ZwContinue 183 184 /* Exit */ 185 jmp Exit 186 187RaiseException: 188 189 /* Raise the exception */ 190 lea rcx, [rsp + CONTEXT_FRAME_LENGTH] /* ExceptionRecord */ 191 lea rdx, [rsp] /* ContextRecord */ 192 xor r8, r8 193 call ZwRaiseException 194 195Exit: 196 lea rcx, [rsp + CONTEXT_FRAME_LENGTH] /* ExceptionRecord */ 197 mov rdx, rax 198 call KiUserExceptionDispatcherNested 199 ret 200 201.ENDP 202 203/* 204 VOID 205 KiUserExceptionDispatcherNested( 206 _In_ ExceptionRecord<rcx>, 207 _In_ Status<edx> 208 ) 209 */ 210.PROC KiUserExceptionDispatcherNested 211 /* Allocate space for the nested exception record */ 212 sub rsp, EXCEPTION_RECORD_LENGTH 213 .ALLOCSTACK EXCEPTION_RECORD_LENGTH 214 .ENDPROLOG 215 216 /* Set it up */ 217 mov dword ptr [rsp + ErNumberParameters], 0 218 mov dword ptr [rsp + ErExceptionFlags], EXCEPTION_NONCONTINUABLE 219 mov [rsp + ErExceptionRecord], rcx 220 mov [rsp + ErExceptionCode], edx 221 222 /* Raise the exception */ 223 mov rcx, rsp 224 call RtlRaiseException 225 226 /* Cleanup stack and return */ 227 add rsp, EXCEPTION_RECORD_LENGTH 228 ret 229.ENDP 230 231END 232 233