2 * FILE: ntoskrnl/ke/i386/syscall.S
3 * COPYRIGHT: See COPYING in the top level directory
4 * PURPOSE: System Call Handler
5 * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
9 #include <internal/i386/ke.h>
13 #define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C
16 .globl _KiServiceExit2
17 .globl _KiFastCallEntry
18 .globl _KiSystemService
19 .globl _KiDebugService
20 .intel_syntax noprefix
23 * NOTE: I will create some macros for trap entry and exit,
24 * DR* register restoration, modified frame exit, etc, if GAS
25 * allows it/I find a way how. This would remove a lot of
26 * duplicated code in this file plus the other irq/trap asm files.
27 * I think this is similar to what NT does, if you look at teh
28 * Dr_kit*_a functions which look auto-generated.
32 * There are 3 main types of Trap Exits:
35 * - Clear interrupt flag
36 * - Common User APC Dispatching
37 * - Common exit code; segments and volatiles are not restored
38 * You use this for System Call return, when volatiles are irrelevant.
39 * (NtContinue, NtRaiseException, KiCallUserMode and all System Call returns)
42 * - Clear interrupt flag
43 * - Common User APC Dispatching
44 * - Common exit code; the entire frame is restored.
45 * You use this when volatiles and other registers need to be restored.
46 * For example, if debugging is active (NtContinue, NtRaiseException).
49 * - Clear interrupt flag
50 * - Common User APC Dispatching
51 * - Common exit code; the entire frame is restored but *NOT* the Previous Mode
52 * You use this in the same context as KiServiceExit2, but when the Previous Mode
53 * should be tampered with. Clearly, as its name suggests, this routine is mostly
54 * useful for End Of Interrupts.
55 * Note that this routine is EXPORTED.
56 * Note that this routine must called by a JMP, not a CALL.
60 * The common exit code has 3 modes of operation:
61 * - Whether or not to restore segments
62 * - Whether or not to restore volatiles
63 * - Whether or not to restore the previous mode
64 * All these are exemplified by the 3 trap exits shown above
68 * There is also common Debug Code present in the common exit code, which
69 * in turn calls common code to save the debug registers
74 * - Dig in trap code and see why we need to push/pop the segments,
75 * which -shouldn't- be needed on syscalls; one of the things
76 * missing for this to work is lazy loading in the GPF handler,
77 * but there are other things to consider.
78 * - Use macros and merge with trap.s nicely
82 * Entries will be discussed later.
85 /*** This file is a mess; it is being worked on. Please contact Alex:
86 *** alex@relsoft.net if you want to make any changes to it before this
90 /* FUNCTIONS ***************************************************************/
94 /* Restore ESP0 stack */
95 mov ecx, [fs:KPCR_TSS]
96 mov esp, ss:[ecx+KTSS_ESP0]
98 /* Generate V86M Stack for Trap 6 */
104 /* Generate interrupt stack for Trap 6 */
105 push KGDT_R3_DATA + RPL_MASK
108 push KGDT_R3_CODE + RPL_MASK
114 // ==================== UNIQUE SYSENTER STUB. DO NOT DUPLICATE ============//
119 /* Set DS/ES to Kernel Selector */
120 mov ecx, KGDT_R0_DATA
124 /* Set the current stack to Kernel Stack */
125 mov ecx, [fs:KPCR_TSS]
126 mov esp, ss:[ecx+KTSS_ESP0]
128 /* Set up a fake INT Stack. */
129 push KGDT_R3_DATA + RPL_MASK
130 push edx /* Ring 3 SS:ESP */
131 pushf /* Ring 3 EFLAGS */
132 push 2 /* Ring 0 EFLAGS */
133 add edx, 8 /* Skip user parameter list */
134 popf /* Set our EFLAGS */
135 or dword ptr [esp], X86_EFLAGS_IF /* Re-enable IRQs in EFLAGS, to fake INT */
136 push KGDT_R3_CODE + RPL_MASK
137 push KUSER_SHARED_SYSCALL_RET
139 /* Setup the Trap Frame stack */
145 push KGDT_R3_TEB + RPL_MASK
147 /* Save pointer to our PCR */
148 mov ebx, [fs:KPCR_SELF]
150 /* Get a pointer to the current thread */
151 mov esi, [ebx+KPCR_CURRENT_THREAD]
153 /* Set the exception handler chain terminator */
154 push [ebx+KPCR_EXCEPTION_LIST]
155 mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
157 /* Use the thread's stack */
158 mov ebp, [esi+KTHREAD_INITIAL_STACK]
160 /* Push previous mode */
164 /* Save other registers */
165 sub $0xC, %esp // + 0x70
166 pushl $KGDT_R3_DATA + RPL_MASK // + 0x40
167 pushl $KGDT_R3_DATA + RPL_MASK // + 0x44
169 sub $0x30, %esp // + 0x70
170 .intel_syntax noprefix
172 /* Make space for us on the stack */
175 /* Write the previous mode */
176 mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
183 and dword ptr [ebp+KTRAP_FRAME_DR7], 0
185 /* Check if the thread was being debugged */
186 test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
188 /* Jump to shared code or DR Save */
189 //jnz Dr_FastCallDrSave
194 // ==================== UNIQUE SYSCALL TRAP ENTRY DO NOT DUPLICATE ============//
195 /* Create a trap frame */
203 /* Load PCR Selector into fs */
207 /* Get a pointer to the current thread */
208 mov esi, [fs:KPCR_CURRENT_THREAD]
210 /* Save the previous exception list */
211 push [fs:KPCR_EXCEPTION_LIST]
213 /* Set the exception handler chain terminator */
214 mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1
216 /* Save the old previous mode */
217 push ss:[esi+KTHREAD_PREVIOUS_MODE]
220 /* Save other registers */
221 sub $0xC, %esp // + 0x70
225 sub $0x30, %esp // + 0x70
226 .intel_syntax noprefix
228 /* Set the new previous mode based on the saved CS selector */
231 mov byte ptr ss:[esi+KTHREAD_PREVIOUS_MODE], bl
233 /* Go on the Kernel stack frame */
236 /* Save the old trap frame pointer where EDX would be saved */
237 mov ebx, [esi+KTHREAD_TRAP_FRAME]
238 mov [ebp+KTRAP_FRAME_EDX], ebx
240 // ==================== COMMON DR SAVE CHECK.AND DEBUG FRAME SETUP ============//
242 and dword ptr [ebp+KTRAP_FRAME_DR7], 0
244 /* Check if the thread was being debugged */
245 test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
249 /* Save a pointer to the trap frame in the TCB */
251 mov [esi+KTHREAD_TRAP_FRAME], ebp
253 /* Get the Debug Trap Frame EBP/EIP */
254 mov ebx, [ebp+KTRAP_FRAME_EBP]
255 mov edi, [ebp+KTRAP_FRAME_EIP]
259 * We want to know the address from where the syscall stub was called.
260 * If PrevMode is KernelMode, that address is stored in our own (kernel)
261 * stack, at location KTRAP_FRAME_ESP.
262 * If we're coming from UserMode, we load the usermode stack pointer
263 * and go back two frames (first frame is the syscall stub, second call
264 * is the caller of the stub).
266 mov edi, [ebp+KTRAP_FRAME_ESP]
267 test byte ptr [esi+KTHREAD_PREVIOUS_MODE], 0x01
273 /* Write the debug data */
274 mov [ebp+KTRAP_FRAME_DEBUGPOINTER], edx
275 mov dword ptr [ebp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
276 mov [ebp+KTRAP_FRAME_DEBUGEBP], ebx
277 mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
279 // ============= END OF COMMON DR SAVE CHECK.AND DEBUG FRAME SETUP ============//
280 /* Enable interrupts */
286 * Find out which table offset to use. Converts 0x1124 into 0x10.
287 * The offset is related to the Table Index as such: Offset = TableIndex x 10
294 /* Now add the thread's base system table to the offset */
295 add edi, [esi+KTHREAD_SERVICE_TABLE]
297 /* Get the true syscall ID and check it */
302 /* Invalid ID, try to load Win32K Table */
303 jnb KiBBTUnexpectedRange
305 #if 0 // <== Disabled for two reasons: We don't save TEB in 0x18, but KPCR.
306 // <== We don't have a KeGdiFlushUserBatch callback yet (needs to be
307 // sent through the PsInitializeWin32Callouts structure)
308 /* Check if this was Win32K */
313 mov ecx, [fs:KPCR_TEB]
315 /* Check if we should flush the User Batch */
317 or ebx, [ecx+TEB_GDI_BATCH_COUNT]
323 call [_KeGdiFlushUserBatch]
329 /* Users's current stack frame pointer is source */
332 /* Allocate room for argument list from kernel stack */
337 /* Get pointer to function */
341 /* Allocate space on our stack */
345 * Copy the arguments from the user stack to our stack
346 * FIXME: This needs to be probed with MmSystemRangeStart
354 * The following lines are for the benefit of GDB. It will see the return
355 * address of the "call ebx" below, find the last label before it and
356 * thinks that that's the start of the function. It will then check to see
357 * if it starts with a standard function prolog (push ebp, mov ebp,esp).
358 * When that standard function prolog is not found, it will stop the
359 * stack backtrace. Since we do want to backtrace into usermode, let's
360 * make GDB happy and create a standard prolog.
368 /* Do the System Call */
371 /* Deallocate the kernel stack frame */
374 KeReturnFromSystemCall:
376 /* Get the Current Thread */
377 mov ecx, [fs:KPCR_CURRENT_THREAD]
379 /* Restore the old trap frame pointer */
380 mov edx, [ebp+KTRAP_FRAME_EDX]
381 mov [ecx+KTHREAD_TRAP_FRAME], edx
384 /* Disable interrupts */
387 // ================= COMMON USER-MODE APC DELIVERY CHECK ============//
388 /* Check for V86 mode */
389 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
392 /* Deliver APCs only if we were called from user mode */
393 test byte ptr [ebp+KTRAP_FRAME_CS], 1
396 /* Get the current thread */
398 mov ebx, [fs:KPCR_CURRENT_THREAD]
400 /* Make it non-alerted */
401 mov byte ptr [ebx+KTHREAD_ALERTED], 0
403 /* And only if any are actually pending */
404 cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
407 /* Save pointer to Trap Frame */
410 // ================= PRESENT ONLY IF VOLATILES NEEDED ============//
411 /* Save some stuff that raising IRQL will kill */
412 mov [ebx+KTRAP_FRAME_EAX], eax
413 mov dword ptr [ebx+KTRAP_FRAME_FS], KGDT_R3_TEB + RPL_MASK
414 mov dword ptr [ebx+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
415 mov dword ptr [ebx+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
416 mov dword ptr [ebx+KTRAP_FRAME_GS], 0
417 // ============= END PRESENT ONLY IF VOLATILES NEEDED ============//
419 /* Raise IRQL to APC_LEVEL */
431 call _KiDeliverApc@12
433 /* Return to old IRQL */
437 /* Restore EAX (only in volatile case) */
438 mov eax, [ebx+KTRAP_FRAME_EAX]
441 // ============== END COMMON USER-MODE APC DELIVERY CHECK ============//
444 // ========================= COMMON TRAP EXIT CODE ===================//
445 /* Restore exception list */
446 mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]
447 mov [fs:KPCR_EXCEPTION_LIST], edx
449 // ==================== ONLY IF PREVIOUS MODE NEEDED ==================//
450 /* Restore previous mode */
451 mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
452 mov esi, [fs:KPCR_CURRENT_THREAD]
453 mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
454 // ==================== END IF PREVIOUS MODE NEEDED ===================//
457 test dword ptr [esp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
460 /* Check if the frame was edited */
462 test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
465 // ==================== ONLY IF FULL RESTORE NEEDED ===================//
466 /* Check the old mode */
467 cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
468 bt word ptr [esp+KTRAP_FRAME_CS], 0
471 // ==================== END IF FULL RESTORE NEEDED ====================//
473 /* Skip debug information and unsaved registers */
484 //lea esp, [ebp+KTRAP_FRAME_FS] <= BUG IN WIN32K CALLBACKS! STACK GETS SMASHED
488 /* Skip debug information and unsaved registers */
489 //lea esp, [ebp+KTRAP_FRAME_EDI] <= BUG IN WIN32K CALLBACKS! STACK GETS SMASHED
495 /* Check for ABIOS */
496 cmp word ptr [esp+8], 0x80
503 /* Check if previous CS is from user-mode */
504 test dword ptr [esp+4], 1
506 /* It is, so use Fast Exit */
509 /* Jump back to stub */
520 /* Is SYSEXIT Supported/Wanted? */
521 cmp dword ptr ss:[_KiFastSystemCallDisable], 0
523 test dword ptr [esp+8], X86_EFLAGS_TF
526 /* Restore FS to TIB */
527 mov ecx, KGDT_R3_TEB + RPL_MASK
530 /* We will be cleaning up the stack ourselves */
531 pop edx /* New Ring 3 EIP */
532 add esp, 4 /* Skip Ring 3 DS */
533 /* and dword ptr [esp], ~X86_EFLAGS_IF Line below is equivalent to this,
534 but older binutils versions don't understand ~ */
535 and dword ptr [esp], 0xfffffdff /* Remove IRQ hack from EFLAGS */
536 popf /* Restore old EFLAGS */
537 pop ecx /* Old Ring 3 SS:ESP */
541 * ECX points to the old User Stack.
542 * EDX points to the instruction to execute in usermode after the sysenter
548 /* Move to EDX position */
549 add esp, KTRAP_FRAME_EDX
551 /* Restore volatiles */
558 /* Not yet supported */
563 mov eax, [esp+KTRAP_FRAME_EAX]
568 /* Restore segments and volatiles */
575 /* Jump back to mainline code */
579 /* Restore real CS value */
580 mov ebx, [esp+KTRAP_FRAME_TEMPCS]
581 mov [esp+KTRAP_FRAME_CS], ebx
584 * If ESP was modified, then a special interrupt exit stack
585 * must be created to "update" ESP's value in a legal manner
587 mov ebx, [esp+KTRAP_FRAME_TEMPESP]
589 mov [esp+KTRAP_FRAME_ERROR_CODE], ebx
591 /* Copy Interrupt Stack */
592 mov esi, [esp+KTRAP_FRAME_EFLAGS]
594 mov esi, [esp+KTRAP_FRAME_CS]
596 mov esi, [esp+KTRAP_FRAME_EIP]
600 add esp, KTRAP_FRAME_EDI
608 KiBBTUnexpectedRange:
610 /* If this isn't a Win32K call, fail */
614 /* Set up Win32K Table */
619 /* FIXME: Handle failure */
623 /* Try the Call again */
628 /* Invalid System Call */
629 mov eax, STATUS_INVALID_SYSTEM_SERVICE
630 jmp KeReturnFromSystemCall
634 /* Disable interrupts */
637 /* Check for V86 mode */
638 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
641 /* Deliver APCs only if we were called from user mode */
642 test byte ptr [ebp+KTRAP_FRAME_CS], 1
645 /* Get the current thread */
647 mov ebx, [fs:KPCR_CURRENT_THREAD]
649 /* Make it non-alerted */
650 mov byte ptr [ebx+KTHREAD_ALERTED], 0
652 /* And only if any are actually pending */
653 cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
656 /* Save pointer to Trap Frame */
659 /* Raise IRQL to APC_LEVEL */
671 call _KiDeliverApc@12
673 /* Return to old IRQL */
681 /* Restore exception list */
682 mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]
683 mov [fs:KPCR_EXCEPTION_LIST], edx
685 /* Restore previous mode */
686 mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
687 mov esi, [fs:KPCR_CURRENT_THREAD]
688 mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
691 test dword ptr [esp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
694 /* Check if the frame was edited */
696 test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
699 /* Restore volatiles */
700 mov edx, [esp+KTRAP_FRAME_EDX]
701 mov ecx, [esp+KTRAP_FRAME_ECX]
702 mov eax, [esp+KTRAP_FRAME_EAX]
704 /* Check if it was kernel */
705 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
709 lea esp, [ebp+KTRAP_FRAME_GS]
711 /* Restore segments and volatiles */
715 lea esp, [ebp+KTRAP_FRAME_FS]
719 /* Skip debug information and unsaved registers */
720 lea esp, [ebp+KTRAP_FRAME_EDI]
726 /* Check for ABIOS */
727 cmp word ptr [esp+8], 0x80
730 /* Pop error code and return */
735 /* Move to EDX position */
736 add esp, KTRAP_FRAME_EDX
738 /* Restore volatiles */
745 /* Restore real CS value */
746 mov ebx, [esp+KTRAP_FRAME_TEMPCS]
747 mov [esp+KTRAP_FRAME_CS], ebx
750 * If ESP was modified, then a special interrupt exit stack
751 * must be created to "update" ESP's value in a legal manner
753 mov ebx, [esp+KTRAP_FRAME_TEMPESP]
755 mov [esp+KTRAP_FRAME_ERROR_CODE], ebx
757 /* Copy Interrupt Stack */
758 mov esi, [esp+KTRAP_FRAME_EFLAGS]
760 mov esi, [esp+KTRAP_FRAME_CS]
762 mov esi, [esp+KTRAP_FRAME_EIP]
765 /* Restore volatiles */
766 mov eax, [esp+KTRAP_FRAME_EAX]
767 mov edx, [esp+KTRAP_FRAME_EDX]
768 mov ecx, [esp+KTRAP_FRAME_ECX]
771 add esp, KTRAP_FRAME_EDI
781 /* Create the Trap Frame */
789 /* Switch to correct FS */
793 /* Save Exception List */
794 push fs:[KPCR_EXCEPTION_LIST]
796 /* Traps don't need the previous mode */
799 /* Continue building the Trap Frame */
808 /* Switch Segments to Kernel */
816 /* Check if this was from V86 Mode */
817 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
820 /* Get current thread */
821 mov ecx, [fs:KPCR_CURRENT_THREAD]
825 and dword ptr [ebp+KTRAP_FRAME_DR7], 0
827 /* Check if the thread was being debugged */
828 test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
831 /* Get the Debug Trap Frame EBP/EIP */
832 mov ebx, [ebp+KTRAP_FRAME_EBP]
833 mov edi, [ebp+KTRAP_FRAME_EIP]
835 /* Write the debug data */
836 mov [ebp+KTRAP_FRAME_DEBUGPOINTER], edx
837 mov dword ptr [ebp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
838 mov [ebp+KTRAP_FRAME_DEBUGEBP], ebx
839 mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
841 /* Increase EIP so we skip the INT3 */
842 //inc dword ptr [ebp+KTRAP_FRAME_EIP]
844 /* Call debug service dispatcher */
845 mov eax, [ebp+KTRAP_FRAME_EAX]
846 mov ecx, [ebp+KTRAP_FRAME_ECX]
847 mov edx, [ebp+KTRAP_FRAME_EAX]
849 /* Check for V86 mode */
850 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
853 /* Check if this is kernel or user-mode */
854 test byte ptr [ebp+KTRAP_FRAME_CS], 1
856 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
859 /* Re-enable interrupts */
863 /* Call the debug routine */
872 call _KdpServiceDispatcher@12
876 /* Get the current process */
877 mov ebx, [fs:KPCR_CURRENT_THREAD]
878 mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
880 /* Check if this is a VDM Process */
881 //cmp dword ptr [ebx+KPROCESS_VDM_OBJECTS], 0
884 /* Exit through common routine */
885 jmp Kei386EoiHelper@0
889 /* Disable interrupts */
892 /* Check for V86 mode */
893 test dword ptr [ebp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
896 /* Deliver APCs only if we were called from user mode */
897 test byte ptr [ebp+KTRAP_FRAME_CS], 1
900 /* Get the current thread */
902 mov ebx, [fs:KPCR_CURRENT_THREAD]
904 /* Make it non-alerted */
905 mov byte ptr [ebx+KTHREAD_ALERTED], 0
907 /* And only if any are actually pending */
908 cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
911 /* Save pointer to Trap Frame */
914 /* Raise IRQL to APC_LEVEL */
926 call _KiDeliverApc@12
928 /* Return to old IRQL */
936 /* Restore exception list */
937 mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]
938 mov [fs:KPCR_EXCEPTION_LIST], edx
941 test dword ptr [esp+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
944 /* Check if the frame was edited */
946 test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
949 /* Restore volatiles */
950 mov edx, [esp+KTRAP_FRAME_EDX]
951 mov ecx, [esp+KTRAP_FRAME_ECX]
952 mov eax, [esp+KTRAP_FRAME_EAX]
954 /* Check if it was kernel */
955 cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
959 lea esp, [ebp+KTRAP_FRAME_GS]
961 /* Restore segments and volatiles */
965 lea esp, [ebp+KTRAP_FRAME_FS]
969 /* Skip debug information and unsaved registers */
970 lea esp, [ebp+KTRAP_FRAME_EDI]
976 /* Check for ABIOS */
977 cmp word ptr [esp+8], 0x80
980 /* Pop error code and return */
985 /* Move to EDX position */
986 add esp, KTRAP_FRAME_EDX
988 /* Restore volatiles */
995 /* Restore real CS value */
996 mov ebx, [esp+KTRAP_FRAME_TEMPCS]
997 mov [esp+KTRAP_FRAME_CS], ebx
1000 * If ESP was modified, then a special interrupt exit stack
1001 * must be created to "update" ESP's value in a legal manner
1003 mov ebx, [esp+KTRAP_FRAME_TEMPESP]
1005 mov [esp+KTRAP_FRAME_ERROR_CODE], ebx
1007 /* Copy Interrupt Stack */
1008 mov esi, [esp+KTRAP_FRAME_EFLAGS]
1010 mov esi, [esp+KTRAP_FRAME_CS]
1012 mov esi, [esp+KTRAP_FRAME_EIP]
1015 /* Restore volatiles */
1016 mov eax, [esp+KTRAP_FRAME_EAX]
1017 mov edx, [esp+KTRAP_FRAME_EDX]
1018 mov ecx, [esp+KTRAP_FRAME_ECX]
1021 add esp, KTRAP_FRAME_EDI
1029 .globl _NtRaiseException@12
1030 _NtRaiseException@12:
1032 /* NOTE: We -must- be called by Zw* to have the right frame! */
1033 /* Push the stack frame */
1036 /* Get the current thread and restore its trap frame */
1037 mov ebx, [fs:KPCR_CURRENT_THREAD]
1038 mov edx, [ebp+KTRAP_FRAME_EDX]
1039 mov [ebx+KTHREAD_TRAP_FRAME], edx
1041 /* Set up stack frame */
1044 /* Get the Trap Frame in EBX */
1047 /* Get the exception list and restore */
1048 mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
1049 mov [fs:KPCR_EXCEPTION_LIST], eax
1051 /* Get the parameters */
1052 mov edx, [ebp+16] /* Search frames */
1053 mov ecx, [ebp+12] /* Context */
1054 mov eax, [ebp+8] /* Exception Record */
1056 /* Raise the exception */
1062 call _KiRaiseException@20
1064 /* Restore trap frame in EBP */
1068 /* Check the result */
1072 /* Restore debug registers too */
1075 .globl _NtContinue@8
1078 /* NOTE: We -must- be called by Zw* to have the right frame! */
1079 /* Push the stack frame */
1082 /* Get the current thread and restore its trap frame */
1083 mov ebx, [fs:KPCR_CURRENT_THREAD]
1084 mov edx, [ebp+KTRAP_FRAME_EDX]
1085 mov [ebx+KTHREAD_TRAP_FRAME], edx
1087 /* Set up stack frame */
1090 /* Save the parameters */
1094 /* Call KiContinue */
1100 /* Check if we failed (bad context record) */
1104 /* Check if test alert was requested */
1105 cmp dword ptr [ebp+12], 0
1108 /* Test alert for the thread */
1109 mov al, [ebx+KTHREAD_PREVIOUS_MODE]
1111 call _KeTestAlertThread@4
1114 /* Return to previous context */