xref: /reactos/dll/ntdll/dispatch/i386/dispatch.S (revision 32d615fc)
1/*
2 * COPYRIGHT:       See COPYING in the top level directory
3 * PROJECT:         ReactOS NT Library
4 * FILE:            dl/ntdll/dispatch/i386/dispatch.S
5 * PURPOSE:         User-Mode NT Dispatchers
6 * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <asm.inc>
12#include <ks386.inc>
13
14EXTERN _LdrpInit@12:PROC
15EXTERN _NtTestAlert@0:PROC
16EXTERN _RtlDispatchException@8:PROC
17EXTERN _RtlRaiseException@4:PROC
18EXTERN _RtlRaiseStatus@4:PROC
19EXTERN _ZwCallbackReturn@12:PROC
20EXTERN _ZwContinue@8:PROC
21EXTERN _ZwRaiseException@12:PROC
22
23/* FUNCTIONS ****************************************************************/
24.code
25
26PUBLIC _LdrInitializeThunk@16
27_LdrInitializeThunk@16:
28
29    /* Get the APC Context */
30    lea eax, [esp+16]
31
32    /* Send it as the first parameter */
33    mov [esp+4], eax
34
35    /* Terminate the frame list */
36    xor ebp, ebp
37
38    /* Jump into the C initialization routine */
39    jmp _LdrpInit@12
40
41
42_KiUserApcExceptionHandler:
43
44    /* Put the exception record in ECX and check the Flags */
45    mov ecx, [esp+4]
46    test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
47    jz .return
48
49    /* Test alert the thread */
50    call _NtTestAlert@0
51
52.return:
53    /* We'll execute handler */
54    mov eax, EXCEPTION_EXECUTE_HANDLER
55    ret 16
56
57
58PUBLIC _KiUserApcDispatcher@16
59_KiUserApcDispatcher@16:
60
61    /* Setup SEH stack */
62    lea eax, [esp+CONTEXT_ALIGNED_SIZE+16]
63    mov ecx, fs:[TEB_EXCEPTION_LIST]
64    mov edx, offset _KiUserApcExceptionHandler
65    mov [eax], ecx
66    mov [eax+4], edx
67
68    /* Enable SEH */
69    mov fs:[TEB_EXCEPTION_LIST], eax
70
71    /* Put the Context in EDI */
72    pop eax
73    lea edi, [esp+12]
74
75    /* Call the APC Routine */
76    call eax
77
78    /* Restore exception list */
79    mov ecx, [edi+CONTEXT_ALIGNED_SIZE]
80    mov fs:[TEB_EXCEPTION_LIST], ecx
81
82    /* Switch back to the context */
83    push 1
84    push edi
85    call _ZwContinue@8
86
87    /* Save callback return value */
88    mov esi, eax
89
90    /* Raise status */
91StatusRaiseApc:
92    push esi
93    call _RtlRaiseStatus@4
94    jmp StatusRaiseApc
95    ret 16
96
97
98_KiUserCallbackExceptionHandler:
99
100    /* Put the exception record in ECX and check the Flags */
101    mov ecx, [esp+4]
102    test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_EXIT_UNWIND + EXCEPTION_UNWINDING
103    jz return
104
105    /* Tell the kernel to invalidate the stack */
106    push STATUS_CALLBACK_POP_STACK
107    push 0
108    push 0
109    call _ZwCallbackReturn@12
110
111return:
112    /* We'll execute the handler */
113    mov eax, EXCEPTION_EXECUTE_HANDLER
114    ret 16
115
116
117PUBLIC _KiUserCallbackDispatcher@12
118_KiUserCallbackDispatcher@12:
119
120    /* Setup SEH stack */
121    mov ecx, fs:[TEB_EXCEPTION_LIST]
122    mov edx, offset _KiUserCallbackExceptionHandler
123    lea eax, [esp+16]
124    mov [esp+16], ecx
125    mov [esp+20], edx
126
127    /* Enable SEH */
128    mov fs:[TEB_EXCEPTION_LIST], eax
129
130    /* Get the callback Index */
131    add esp, 4
132    pop edx
133
134    /* Get the callback table */
135    mov eax, [fs:TEB_PEB]
136    mov eax, [eax+PEB_KERNEL_CALLBACK_TABLE]
137
138    /* Call the routine */
139    call dword ptr [eax+edx*4]
140
141    /* Return from callback */
142    push eax
143    push 0
144    push 0
145    call _ZwCallbackReturn@12
146
147    /* Save callback return value */
148    mov esi, eax
149
150    /* Raise status */
151StatusRaise:
152    push esi
153    call _RtlRaiseStatus@4
154    jmp StatusRaise
155    ret 12
156
157
158PUBLIC _KiRaiseUserExceptionDispatcher@0
159_KiRaiseUserExceptionDispatcher@0:
160
161    /* Setup stack for EXCEPTION_RECORD */
162    push ebp
163    mov ebp, esp
164    sub esp, EXCEPTION_RECORD_LENGTH
165
166    /* Fill out the record */
167    mov [esp+EXCEPTION_RECORD_EXCEPTION_ADDRESS], eax
168    mov eax, [fs:KPCR_TEB]
169    mov eax, [eax+TEB_EXCEPTION_CODE]
170    mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
171    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], 0
172    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], 0
173    mov dword ptr [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0
174
175    /* Raise the exception */
176    push esp
177    call _RtlRaiseException@4
178
179    /* Return exception code */
180    mov eax, [esp+EXCEPTION_RECORD_EXCEPTION_CODE]
181    mov esp, ebp
182    pop ebp
183    ret
184
185
186PUBLIC _KiUserExceptionDispatcher@8
187.PROC _KiUserExceptionDispatcher@8
188    FPO 0, 0, 0, 0, 0, FRAME_FPO
189
190    /* Clear direction flag */
191    cld
192
193    /* Save the Context and Exception Records */
194    mov ecx, [esp+4]
195    mov ebx, [esp]
196
197    /* Dispatch the exception */
198    push ecx
199    push ebx
200    call _RtlDispatchException@8
201
202    /* Check for success */
203    or al, al
204    jz RaiseException
205
206    /* Pop off the records */
207    pop ebx
208    pop ecx
209
210    /* We're fine, continue execution */
211    push 0
212    push ecx
213    call _ZwContinue@8
214
215    /* Exit */
216    jmp Exit
217
218RaiseException:
219    /* Pop off the records */
220    pop ebx
221    pop ecx
222
223    /* Raise the exception */
224    push 0
225    push ecx
226    push ebx
227    call _ZwRaiseException@12
228
229Exit:
230    /* Allocate space for the nested exception record */
231    add esp, -SIZEOF_EXCEPTION_RECORD
232
233    /* Set it up */
234    mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax
235    mov dword ptr [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_NONCONTINUABLE
236    mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], ebx
237    mov dword ptr [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], 0
238
239    /* Raise the exception */
240    push esp
241    call _RtlRaiseException@4
242    ret 8
243
244.ENDP
245
246PUBLIC _KiIntSystemCall@0
247.PROC _KiIntSystemCall@0
248    FPO 0, 0, 0, 0, 0, FRAME_FPO
249
250    /* Set stack in EDX and do the interrupt */
251    lea edx, [esp+8]
252    int HEX(2E)
253
254    /* Return to caller */
255    ret
256
257.ENDP
258
259PUBLIC _KiFastSystemCall@0
260.PROC _KiFastSystemCall@0
261    FPO 0, 0, 0, 0, 0, FRAME_FPO
262
263    /* Put ESP in EDX and do the SYSENTER */
264    mov edx, esp
265    sysenter
266
267.ENDP
268
269PUBLIC _KiFastSystemCallRet@0
270.PROC _KiFastSystemCallRet@0
271    FPO 0, 0, 0, 0, 0, FRAME_FPO
272
273    /* Just return to caller */
274    ret
275
276.ENDP
277
278END
279