xref: /reactos/dll/ntdll/dispatch/amd64/dispatch.S (revision 886670e9)
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