1 /* $Id: usercall.c,v 1.8 2000/02/22 20:50:07 ekohl Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/hal/x86/usercall.c
6 * PURPOSE: 2E interrupt handler
7 * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk)
12 #include <ddk/ntddk.h>
13 #include <internal/ntoskrnl.h>
14 #include <internal/ke.h>
15 #include <internal/symbol.h>
16 #include <internal/i386/segment.h>
17 #include <internal/mmhal.h>
20 #include <internal/debug.h>
21 #include <internal/service.h>
23 #include <ddk/defines.h>
26 extern KE_SERVICE_DESCRIPTOR_TABLE_ENTRY KeServiceDescriptorTable
[];
27 extern KE_SERVICE_DESCRIPTOR_TABLE_ENTRY KeServiceDescriptorTableShadow
[];
31 #define STR(x) _STR(x)
33 void PsBeginThreadWithContextInternal(void);
35 "\n\t.global _PsBeginThreadWithContextInternal\n\t"
36 "_PsBeginThreadWithContextInternal:\n\t"
38 // "call _KeLowerIrql\n\t"
39 "call _PiBeforeBeginThread\n\t"
62 VOID
KiSystemCallHook(ULONG Nr
, ...)
64 #ifdef TRACE_SYSTEM_CALLS
70 DbgPrint("%x/%d ", _SystemServiceTable
[Nr
].Function
,Nr
);
71 DbgPrint("%x (", _SystemServiceTable
[Nr
].ParametersSize
);
72 for (i
= 0; i
< _SystemServiceTable
[Nr
].ParametersSize
/ 4; i
++)
74 DbgPrint("%x, ", va_arg(ap
, ULONG
));
77 assert_irql(PASSIVE_LEVEL
);
82 ULONG
KiAfterSystemCallHook(ULONG NtStatus
, PCONTEXT Context
)
84 if (NtStatus
!= STATUS_USER_APC
)
88 KiTestAlert(KeGetCurrentThread(), Context
);
92 // This function should be used by win32k.sys to add its own user32/gdi32 services
93 // TableIndex is 0 based
94 // ServiceCountTable its not used at the moment
96 KeAddSystemServiceTable (
98 PULONG ServiceCounterTable
,
99 ULONG NumberOfServices
,
104 if (TableIndex
> SSDT_MAX_ENTRIES
- 1)
107 /* check if descriptor table entry is free */
108 if ((KeServiceDescriptorTable
[TableIndex
].SSDT
!= NULL
) ||
109 (KeServiceDescriptorTableShadow
[TableIndex
].SSDT
!= NULL
))
112 /* initialize the shadow service descriptor table */
113 KeServiceDescriptorTableShadow
[TableIndex
].SSDT
= SSDT
;
114 KeServiceDescriptorTableShadow
[TableIndex
].SSPT
= SSPT
;
115 KeServiceDescriptorTableShadow
[TableIndex
].NumberOfServices
= NumberOfServices
;
116 KeServiceDescriptorTableShadow
[TableIndex
].ServiceCounterTable
= ServiceCounterTable
;
118 /* initialize the service descriptor table (not for win32k services) */
121 KeServiceDescriptorTable
[TableIndex
].SSDT
= SSDT
;
122 KeServiceDescriptorTable
[TableIndex
].SSPT
= SSPT
;
123 KeServiceDescriptorTable
[TableIndex
].NumberOfServices
= NumberOfServices
;
124 KeServiceDescriptorTable
[TableIndex
].ServiceCounterTable
= ServiceCounterTable
;
131 void interrupt_handler2e(void);
132 __asm__("\n\t.global _interrupt_handler2e\n\t"
133 "_interrupt_handler2e:\n\t"
135 /* Save the user context */
136 "pushl %ebp\n\t" /* Ebp */
138 "pushl %eax\n\t" /* Eax */
139 "pushl %ecx\n\t" /* Ecx */
140 "pushl %edx\n\t" /* Edx */
141 "pushl %ebx\n\t" /* Ebx */
142 "pushl %esi\n\t" /* Esi */
143 "pushl %edi\n\t" /* Edi */
145 "pushl %ds\n\t" /* SegDs */
146 "pushl %es\n\t" /* SegEs */
147 "pushl %fs\n\t" /* SegFs */
148 "pushl %gs\n\t" /* SegGs */
150 "subl $112,%esp\n\t" /* FloatSave */
152 "pushl $0\n\t" /* Dr7 */
153 "pushl $0\n\t" /* Dr6 */
154 "pushl $0\n\t" /* Dr3 */
155 "pushl $0\n\t" /* Dr2 */
156 "pushl $0\n\t" /* Dr1 */
157 "pushl $0\n\t" /* Dr0 */
159 "pushl $0\n\t" /* ContextFlags */
161 /* Set ES to kernel segment */
162 "movw $"STR(KERNEL_DS
)",%bx\n\t"
165 /* Save pointer to user context as argument to system call */
168 /* Allocate new Kernel stack frame */
171 /* Users's current stack frame pointer is source */
174 /* Determine system service table to use */
175 "cmpl $0x0fff, %eax\n\t"
176 "ja useShadowTable\n\t"
178 /* Check to see if EAX is valid/inrange */
179 "cmpl %es:_KeServiceDescriptorTable + 8, %eax\n\t"
180 "jbe serviceInRange\n\t"
181 "movl $"STR(STATUS_INVALID_SYSTEM_SERVICE
)", %eax\n\t"
184 "serviceInRange:\n\t"
186 /* Allocate room for argument list from kernel stack */
187 "movl %es:_KeServiceDescriptorTable + 12, %ecx\n\t"
188 "movl %es:(%ecx, %eax, 4), %ecx\n\t"
189 "subl %ecx, %esp\n\t"
191 /* Copy the arguments from the user stack to the kernel stack */
195 /* DS is now also kernel segment */
198 /* Call system call hook */
200 "call _KiSystemCallHook\n\t"
203 /* Make the system service call */
204 "movl %es:_KeServiceDescriptorTable, %ecx\n\t"
205 "movl %es:(%ecx, %eax, 4), %eax\n\t"
209 /* Bump Service Counter */
212 /* Deallocate the kernel stack frame */
215 /* Call the post system call hook and deliver any pending APCs */
217 "call _KiAfterSystemCallHook\n\t"
222 "useShadowTable:\n\t"
224 "subl $0x1000, %eax\n\t"
226 /* Check to see if EAX is valid/inrange */
227 "cmpl %es:_KeServiceDescriptorTableShadow + 24, %eax\n\t"
228 "jbe shadowServiceInRange\n\t"
229 "movl $"STR(STATUS_INVALID_SYSTEM_SERVICE
)", %eax\n\t"
232 "shadowServiceInRange:\n\t"
234 /* Allocate room for argument list from kernel stack */
235 "movl %es:_KeServiceDescriptorTableShadow + 28, %ecx\n\t"
236 "movl %es:(%ecx, %eax, 4), %ecx\n\t"
237 "subl %ecx, %esp\n\t"
239 /* Copy the arguments from the user stack to the kernel stack */
243 /* DS is now also kernel segment */
246 /* Call system call hook */
248 "call _KiSystemCallHook\n\t"
251 /* Make the system service call */
252 "movl %es:_KeServiceDescriptorTableShadow + 16, %ecx\n\t"
253 "movl %es:(%ecx, %eax, 4), %eax\n\t"
257 /* Bump Service Counter */
260 /* Deallocate the kernel stack frame */
263 /* Call the post system call hook and deliver any pending APCs */
265 "call _KiAfterSystemCallHook\n\t"
270 /* Restore the user context */
271 "addl $4,%esp\n\t" /* UserContext */
272 "addl $24,%esp\n\t" /* Dr[0-3,6-7] */
273 "addl $112,%esp\n\t" /* FloatingSave */
274 "popl %gs\n\t" /* SegGs */
275 "popl %fs\n\t" /* SegFs */
276 "popl %es\n\t" /* SegEs */
277 "popl %ds\n\t" /* SegDs */
279 "popl %edi\n\t" /* Edi */
280 "popl %esi\n\t" /* Esi */
281 "popl %ebx\n\t" /* Ebx */
282 "popl %edx\n\t" /* Edx */
283 "popl %ecx\n\t" /* Ecx */
284 "addl $4,%esp\n\t" /* Eax (Not restored) */
286 "popl %ebp\n\t" /* Ebp */