Some work-in-progress improvements and rethought of system-level code...notable improvemnts till now are: -The KTHREAD alterted flag is now properly set to FALSE during APC delivery during traps, -More support for PKEXCEPTION_FRAME has been added for future PPC/IA64/etc compatibility -Context to/from TrapFrame functions have been greatly fixed to allow for edited frames, special cases, exceptions and also have the necessary support for supporting sanitation based on PreviousMode - KDBG now shows the proper CS/SS at all times, previous hack was removed. - Systemcall code was optimized a bit and the trap code was made a lot more generic so that in can be made into macros (it currently isn't, for debugging purposes). - V86 Mode trap frame bias has now been added to make trap code a lot more generic and shareable in the future. -More support and fixes for future Debugging capabilities have been added. - Random other scalability and stability code. This is st!
 ill being worked on, syscall.S looks nasty for now (visually)
Modified: trunk/reactos/lib/ntdll/ldr/startup.c
Modified: trunk/reactos/lib/rtl/i386/exception.c
Modified: trunk/reactos/ntoskrnl/ex/init.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
Modified: trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c
Modified: trunk/reactos/ntoskrnl/kdbg/kdb.c
Modified: trunk/reactos/ntoskrnl/kdbg/kdb_cli.c
Modified: trunk/reactos/ntoskrnl/ke/apc.c
Modified: trunk/reactos/ntoskrnl/ke/exception.c
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
Modified: trunk/reactos/ntoskrnl/ke/i386/fpu.c
Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
Modified: trunk/reactos/ntoskrnl/mm/i386/pfault.c
Modified: trunk/reactos/ntoskrnl/ps/debug.c

Modified: trunk/reactos/lib/ntdll/ldr/startup.c
--- trunk/reactos/lib/ntdll/ldr/startup.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/lib/ntdll/ldr/startup.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -256,13 +256,13 @@
    SYSTEM_BASIC_INFORMATION SystemInformation;
    NTSTATUS Status;
 
-   DPRINT("LdrpInit()\n");
+   DPRINT1("LdrpInit()\n");
    if (NtCurrentPeb()->Ldr == NULL || NtCurrentPeb()->Ldr->Initialized == FALSE)
      {
        Peb = (PPEB)(PEB_BASE);
-       DPRINT("Peb %x\n", Peb);
+       DPRINT1("Peb %x\n", Peb);
        ImageBase = Peb->ImageBaseAddress;
-       DPRINT("ImageBase %x\n", ImageBase);
+       DPRINT1("ImageBase %x\n", ImageBase);
        if (ImageBase <= (PVOID)0x1000)
          {
            DPRINT("ImageBase is null\n");
@@ -271,7 +271,7 @@
 
        /*  If MZ header exists  */
        PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
-       DPRINT("PEDosHeader %x\n", PEDosHeader);
+       DPRINT1("PEDosHeader %x\n", PEDosHeader);
 
        if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
            PEDosHeader->e_lfanew == 0L ||
@@ -294,10 +294,12 @@
        NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew);
 
        /* Get number of processors */
+       DPRINT1("Here\n");
        Status = ZwQuerySystemInformation(SystemBasicInformation,
 	                                 &SystemInformation,
 					 sizeof(SYSTEM_BASIC_INFORMATION),
 					 NULL);
+        DPRINT1("Here2\n");
        if (!NT_SUCCESS(Status))
          {
 	   ZwTerminateProcess(NtCurrentProcess(), Status);

Modified: trunk/reactos/lib/rtl/i386/exception.c
--- trunk/reactos/lib/rtl/i386/exception.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/lib/rtl/i386/exception.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -165,7 +165,7 @@
     }
 
     /* Unhandled, return false */
-    DPRINT1("FALSE:(\n");
+    DPRINT1("FALSE\n");
     return FALSE;
 }
 

Modified: trunk/reactos/ntoskrnl/ex/init.c
--- trunk/reactos/ntoskrnl/ex/init.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ex/init.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -241,7 +241,6 @@
     ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
     ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
     ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
-    ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);

Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
--- trunk/reactos/ntoskrnl/include/internal/i386/ke.h	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h	2005-09-13 19:33:49 UTC (rev 17838)
@@ -40,11 +40,15 @@
 #define X86_EXT_FEATURE_SSE3    0x00000001 /* SSE3 extension present */
 #define X86_EXT_FEATURE_3DNOW   0x40000000 /* 3DNOW! extension present */
 
+#define DR7_ACTIVE              0x00000055  /* If any of these bits are set, a Dr is active */
+
 /* Possible values for KTHREAD's NpxState */
 #define NPX_STATE_INVALID   0x01
 #define NPX_STATE_VALID     0x02
 #define NPX_STATE_DIRTY     0x04
 
+#define FRAME_EDITED        0xFFF8
+
 #ifndef __ASM__
 
 typedef struct _KIRQ_TRAPFRAME

Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
--- trunk/reactos/ntoskrnl/include/internal/ke.h	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h	2005-09-13 19:33:49 UTC (rev 17838)
@@ -287,7 +287,10 @@
 VOID FASTCALL KiWaitTest(PDISPATCHER_HEADER Object, KPRIORITY Increment);
 
 PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
-BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame);
+BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context,
+                                     PKEXCEPTION_FRAME ExeptionFrame,
+                                     PKTRAP_FRAME TrapFrame,
+                                     KPROCESSOR_MODE PreviousMode);
 VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
                   PVOID Reserved,
                   PKTRAP_FRAME TrapFrame);
@@ -368,9 +371,12 @@
             PKTRAP_FRAME Tf,
 		    KPROCESSOR_MODE PreviousMode,
 		    BOOLEAN SearchFrames);
-VOID KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
-			  PCONTEXT Context);
 VOID
+NTAPI
+KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
+                     IN PKEXCEPTION_FRAME ExceptionFrame,
+                     IN OUT PCONTEXT Context);
+VOID
 KeApplicationProcessorInit(VOID);
 VOID
 KePrepareForApplicationProcessorInit(ULONG id);

Modified: trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c
--- trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -1321,7 +1321,7 @@
 #error Unknown compiler for inline assembler
 #endif
 
-                KeContextToTrapFrame(Context, NULL, TrapFrame);
+                KeContextToTrapFrame(Context, NULL, TrapFrame, KernelMode);
                 return ((SigVal == 5) ? (kdContinue) : (kdHandleException));
                 break;
               }
@@ -1430,11 +1430,11 @@
 
   TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
 
-  KeTrapFrameToContext (TrapFrame, &Context);
+  KeTrapFrameToContext (TrapFrame, NULL, &Context);
 
   KdpGdbEnterDebuggerException (NULL, &Context, TrapFrame);
 
-  KeContextToTrapFrame (&Context, NULL, TrapFrame);
+  KeContextToTrapFrame (&Context, NULL, TrapFrame, KernelMode);
 
   KeLowerIrql (OldIrql);
 

Modified: trunk/reactos/ntoskrnl/kdbg/kdb.c
--- trunk/reactos/ntoskrnl/kdbg/kdb.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/kdbg/kdb.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -15,10 +15,6 @@
 
 /* TYPES *********************************************************************/
 
-/* FIXME: NDK headers */
-#define TempEsp TempEip
-#define TempSegSs TempCs
-
 /* DEFINES *******************************************************************/
 
 #define KDB_STACK_SIZE                   (4096*3)
@@ -108,6 +104,24 @@
    "SIMD Fault"
 };
 
+ULONG
+NTAPI
+KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame);
+
+ULONG
+NTAPI
+KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame);
+
+VOID
+NTAPI
+KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                IN ULONG Ss);
+
+VOID
+NTAPI
+KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                 IN ULONG Esp);
+
 /* FUNCTIONS *****************************************************************/
 
 STATIC VOID
@@ -124,22 +138,11 @@
       "movl %%cr4, %3"    "\n\t"
       : "=r"(KdbTrapFrame->Cr0), "=r"(KdbTrapFrame->Cr2),
         "=r"(KdbTrapFrame->Cr3), "=r"(KdbTrapFrame->Cr4));
-   
-   if (TrapFrame->PreviousMode == KernelMode)
-   {
-      /* If the trapframe is a kmode one use the temp ss:esp */
-      KdbTrapFrame->Tf.Esp = (ULONG)TrapFrame->TempEsp;
-      KdbTrapFrame->Tf.Ss = (USHORT)((ULONG)TrapFrame->TempSegSs & 0xFFFF);
-   }
-   else
-   {
-      /* Otherwise use ss:esp pushed by the CPU */
-      /* FIXME: maybe change all trapframes to always put ss:esp into tempss:tempesp so we
-       *        can handle umode and kmode the same way */
-      KdbTrapFrame->Tf.Esp = TrapFrame->Esp;
-      KdbTrapFrame->Tf.Ss = TrapFrame->Ss;
-   }
-   
+
+    KdbTrapFrame->Tf.Esp = KiEspFromTrapFrame(TrapFrame);
+    KdbTrapFrame->Tf.Ss = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
+
+
    /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
 }
 
@@ -151,20 +154,8 @@
    
    /* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
    
-   if (TrapFrame->PreviousMode == KernelMode)
-   {
-      /* If the trapframe is a kmode one write to the temp ss:esp */
-      TrapFrame->TempEsp = (PVOID)KdbTrapFrame->Tf.Esp;
-      TrapFrame->TempSegSs = (PVOID)(((ULONG)TrapFrame->TempSegSs & ~0xffff) | KdbTrapFrame->Tf.Ss);
-   }
-   else
-   {
-      /* Otherwise write to ss:esp pushed by the CPU */
-      /* FIXME: maybe change all trap-epilogs to always put temp ss:esp into ss:esp so we
-       *        can handle umode and kmode the same way */
-      TrapFrame->Esp = KdbTrapFrame->Tf.Esp;
-      TrapFrame->Ss = KdbTrapFrame->Tf.Ss;
-   }
+    KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Ss);
+    KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Esp);
    
    /* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
 }

Modified: trunk/reactos/ntoskrnl/kdbg/kdb_cli.c
--- trunk/reactos/ntoskrnl/kdbg/kdb_cli.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/kdbg/kdb_cli.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -35,10 +35,6 @@
 
 /* DEFINES *******************************************************************/
 
-/* FIXME: NDK headers */
-#define TempEsp TempEip
-#define TempSegSs TempCs
-
 #define KEY_BS          8
 #define KEY_ESC         27
 #define KEY_DEL         127

Modified: trunk/reactos/ntoskrnl/ke/apc.c
--- trunk/reactos/ntoskrnl/ke/apc.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/apc.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -812,7 +812,7 @@
 
     /* Save the full context */
     Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
-    KeTrapFrameToContext(TrapFrame, &Context);
+    KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
 
     /* Protect with SEH */
     _SEH_TRY

Modified: trunk/reactos/ntoskrnl/ke/exception.c
--- trunk/reactos/ntoskrnl/ke/exception.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/exception.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -28,7 +28,7 @@
     Context = &LocalContext;
 
     /* Convert the context into Exception/Trap Frames */
-    KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame);
+    KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame, UserMode);
 }
 
 NTSTATUS
@@ -62,7 +62,7 @@
         else
         {
             /* Convert the context into Exception/Trap Frames */
-            KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
+            KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, KernelMode);
         }
     }
     _SEH_HANDLE
@@ -142,7 +142,7 @@
     if (NT_SUCCESS(Status))
     {
         /* Convert the context record */
-        KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
+        KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, PreviousMode);
 
         /* Dispatch the exception */
         KiDispatchException(ExceptionRecord,

Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S	2005-09-13 19:33:49 UTC (rev 17838)
@@ -114,7 +114,7 @@
 .globl @KiSwapContextInternal@0
 @KiSwapContextInternal@0:
 #ifdef KDBG
-    jmp SaveTrapFrameForKDB
+    //jmp SaveTrapFrameForKDB
 SaveTrapFrameForKDB_Return:
 #endif
 
@@ -130,12 +130,14 @@
     /* Switching, disable interrupts now */
     cli
 
+    /* Save the initial stack in EAX */
+    mov eax, [edi+KTHREAD_INITIAL_STACK]
+
 #ifdef CONFIG_SMP
     /* Save FPU state if the thread has used it. */
     mov dword ptr [ebx+KPCR_NPX_THREAD], 0
     test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY
     jz 3f
-    mov eax, [edi+KTHREAD_INITIAL_STACK]
     cmp dword ptr _FxsrSupport, 0
     je 1f
     fxsave [eax-SIZEOF_FX_SAVE_AREA]
@@ -149,8 +151,18 @@
     
     /* Save the stack pointer in this processors TSS */
     mov ebp, [ebx+KPCR_TSS]
+
+    /* Check if this isn't V86 Mode, so we can bias the Esp0 */
+    test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
+    jnz NoAdjust
+
+    /* Bias esp */
+    //sub dword ptr ss:[ebp+KTSS_ESP0], KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
+
+NoAdjust:
+    /* Push ESP0 Value */
     push ss:[ebp+KTSS_ESP0]
-    
+
     /* Check if address space switch is needed */
     mov eax, [esi+KTHREAD_APCSTATE_PROCESS]
     cmp eax, [edi+KTHREAD_APCSTATE_PROCESS]

Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
--- trunk/reactos/ntoskrnl/ke/i386/exp.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/i386/exp.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -17,14 +17,18 @@
 
 /*
  * FIXMES:
+ *  - Put back VEH.
  *  - Clean up file.
- *  - Add more exception frame support for non-i386 compatibility.
+ *  - Sanitize some context fields.
  *  - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
  *  - Implement official stack trace functions (exported) and remove stuff here.
  *  - Forward exceptions to user-mode debugger.
- *  - Wrap Ki NTDLL callbacks in SEH.
  */
 
+VOID
+NTAPI
+Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
+
 /* GLOBALS *****************************************************************/
 
 #define FLAG_IF (1<<9)
@@ -485,14 +489,14 @@
    ASSERT(ExceptionNr != 14);
 
    /* Store the exception number in an unused field in the trap frame. */
-   Tf->DebugArgMark = (PVOID)ExceptionNr;
+   Tf->DebugArgMark = ExceptionNr;
 
    /* Use the address of the trap frame as approximation to the ring0 esp */
    Esp0 = (ULONG)&Tf->Eip;
 
    /* Get CR2 */
    cr2 = Ke386GetCr2();
-   Tf->DebugPointer = (PVOID)cr2;
+   Tf->DebugPointer = cr2;
 
    /*
     * If this was a V86 mode exception then handle it specially
@@ -566,21 +570,172 @@
     }
 }
 
+ULONG
+NTAPI
+KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
+{
+    /* Check if this is user-mode or V86 */
+    if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+    {
+        /* Return it directly */
+        return TrapFrame->Esp;
+    }
+    else
+    {
+        /* Edited frame */
+        if (!(TrapFrame->Cs & FRAME_EDITED))
+        {
+            /* Return edited value */
+            return TrapFrame->TempEsp;
+        }
+        else
+        {
+            /* Virgin frame, calculate */
+            return (ULONG)&TrapFrame->Esp;
+        }
+    }
+}
+
+VOID
+NTAPI
+KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                 IN ULONG Esp)
+{
+    ULONG Previous = KiEspFromTrapFrame(TrapFrame);
+
+    /* Check if this is user-mode or V86 */
+    if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+    {
+        /* Write it directly */
+        TrapFrame->Esp = Esp;
+    }
+    else
+    {
+        /* Don't allow ESP to be lowered, this is illegal */
+        if (Esp < Previous)
+        {
+            //KeBugCheck(SET_OF_INVALID_CONTEXT);
+        }
+
+        /* Create an edit frame, check if it was alrady */
+        if (!(TrapFrame->Cs & FRAME_EDITED))
+        {
+            /* Update the value */
+            TrapFrame->TempEsp = Esp;
+        }
+        else
+        {
+            /* Check if ESP changed */
+            if (Previous != Esp)
+            {
+                /* Save CS */
+                TrapFrame->TempCs = TrapFrame->Cs;
+                TrapFrame->Cs &= ~FRAME_EDITED;
+
+                /* Save ESP */
+                TrapFrame->TempEsp = Esp;
+            }
+        }
+    }
+}
+
+ULONG
+NTAPI
+KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
+{
+    /* If this was V86 Mode */
+    if (TrapFrame->Eflags & X86_EFLAGS_VM)
+    {
+        /* Just return it */
+        return TrapFrame->Ss;
+    }
+    else if (TrapFrame->Cs & 1)
+    {
+        /* Usermode, return the User SS */
+        return TrapFrame->Ss | 3;
+    }
+    else
+    {
+        /* Kernel mode */
+        return KERNEL_DS;
+    }
+}
+
+VOID
+NTAPI
+KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
+                IN ULONG Ss)
+{
+    /* Remove the high-bits */
+    Ss &= 0xFFFF;
+
+    /* If this was V86 Mode */
+    if (TrapFrame->Eflags & X86_EFLAGS_VM)
+    {
+        /* Just write it */
+        TrapFrame->Ss = Ss;
+    }
+    else if (TrapFrame->Cs & 1)
+    {
+        /* Usermode, save the User SS */
+        TrapFrame->Ss = Ss | 3;
+    }
+}
+
 BOOLEAN
-STDCALL
-KeContextToTrapFrame(PCONTEXT Context,
-                     PKEXCEPTION_FRAME ExceptionFrame,
-                     PKTRAP_FRAME TrapFrame)
+NTAPI
+KeContextToTrapFrame(IN PCONTEXT Context,
+                     IN OUT PKEXCEPTION_FRAME ExceptionFrame,
+                     IN OUT PKTRAP_FRAME TrapFrame,
+                     IN KPROCESSOR_MODE PreviousMode)
 {
+    BOOLEAN V86Switch = FALSE;
+
     /* Start with the basic Registers */
     if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
     {
-        TrapFrame->Esp = Context->Esp;
-        TrapFrame->Ss = Context->SegSs;
-        TrapFrame->Cs = Context->SegCs;
-        TrapFrame->Eip = Context->Eip;
+        /* Check if we went through a V86 switch */
+        if ((Context->EFlags & X86_EFLAGS_VM) !=
+            (TrapFrame->Eflags & X86_EFLAGS_VM))
+        {
+            /* We did, remember this for later */
+            V86Switch = TRUE;
+        }
+
+        /* Copy EFLAGS. FIXME: Needs to be sanitized */
         TrapFrame->Eflags = Context->EFlags;
+
+        /* Copy EBP and EIP */
         TrapFrame->Ebp = Context->Ebp;
+        TrapFrame->Eip = Context->Eip;
+
+        /* Check if we were in V86 Mode */
+        if (TrapFrame->Eflags & X86_EFLAGS_VM)
+        {
+            /* Simply copy the CS value */
+            TrapFrame->Cs = Context->SegCs;
+        }
+        else
+        {
+            /* We weren't in V86, so sanitize the CS (FIXME!) */
+            TrapFrame->Cs = Context->SegCs;
+
+            /* Don't let it under 8, that's invalid */
+            if ((PreviousMode !=KernelMode) && (TrapFrame->Cs < 8))
+            {
+                /* Force it to User CS */
+                TrapFrame->Cs = USER_CS;
+            }
+        }
+
+        /* Handle SS Specially for validation */
+        KiSsToTrapFrame(TrapFrame, Context->SegSs);
+
+        /* Write ESP back; take into account Edited Trap Frames */
+        KiEspToTrapFrame(TrapFrame, Context->Esp);
+
+        /* Handle our V86 Bias if we went through a switch */
+        if (V86Switch) Ki386AdjustEsp0(TrapFrame);
     }
 
     /* Process the Integer Registers */
@@ -597,21 +752,62 @@
     /* Process the Context Segments */
     if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
     {
-        TrapFrame->Ds = Context->SegDs;
-        TrapFrame->Es = Context->SegEs;
-        TrapFrame->Fs = Context->SegFs;
-        TrapFrame->Gs = Context->SegGs;
+        /* Check if we were in V86 Mode */
+        if (TrapFrame->Eflags & X86_EFLAGS_VM)
+        {
+            /* Copy the V86 Segments directlry */
+            TrapFrame->V86_Ds = Context->SegDs;
+            TrapFrame->V86_Es = Context->SegEs;
+            TrapFrame->V86_Fs = Context->SegFs;
+            TrapFrame->V86_Gs = Context->SegGs;
+        }
+        else if (!(TrapFrame->Cs & 1))
+        {
+            /* For user mode, write the values directly */
+            TrapFrame->Ds = USER_DS;
+            TrapFrame->Es = USER_DS;
+            TrapFrame->Fs = Context->SegFs;
+            KEBUGCHECK(0);
+            TrapFrame->Gs = 0;
+        }
+        else
+        {
+            /* For kernel-mode, return the values */
+            TrapFrame->Ds = Context->SegDs;
+            TrapFrame->Es = Context->SegEs;
+            TrapFrame->Fs = Context->SegFs;
+
+            /* Handle GS specially */
+            if (TrapFrame->Cs == USER_CS)
+            {
+                /* Don't use it, if user */
+                TrapFrame->Gs = 0;
+            }
+            else
+            {
+                /* Copy it if kernel */
+                TrapFrame->Gs = Context->SegGs;
+            }
+        }
     }
 
     /* Handle the Debug Registers */
     if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
     {
+        /* FIXME: All these should be sanitized */
         TrapFrame->Dr0 = Context->Dr0;
         TrapFrame->Dr1 = Context->Dr1;
         TrapFrame->Dr2 = Context->Dr2;
         TrapFrame->Dr3 = Context->Dr3;
         TrapFrame->Dr6 = Context->Dr6;
         TrapFrame->Dr7 = Context->Dr7;
+
+        /* Check if usermode */
+        if (PreviousMode != KernelMode)
+        {
+            /* Set the Debug Flag */
+            KeGetCurrentThread()->DebugActive = (Context->Dr7 & DR7_ACTIVE);
+        }
     }
 
     /* Handle FPU and Extended Registers */
@@ -619,51 +815,90 @@
 }
 
 VOID
-KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
-		     PCONTEXT Context)
+NTAPI
+KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
+                     IN PKEXCEPTION_FRAME ExceptionFrame,
+                     IN OUT PCONTEXT Context)
 {
-   if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
-     {
-	Context->SegSs = TrapFrame->Ss;
-	Context->Esp = TrapFrame->Esp;
-	Context->SegCs = TrapFrame->Cs;
-	Context->Eip = TrapFrame->Eip;
-	Context->EFlags = TrapFrame->Eflags;
-	Context->Ebp = TrapFrame->Ebp;
-     }
-   if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
-     {
-	Context->Eax = TrapFrame->Eax;
-	Context->Ebx = TrapFrame->Ebx;
-	Context->Ecx = TrapFrame->Ecx;
-	/*
-	 * NOTE: In the trap frame which is built on entry to a system
-	 * call TrapFrame->Edx will actually hold the address of the
-	 * previous TrapFrame. I don't believe leaking this information
-	 * has security implications. Also EDX holds the address of the
-	 * arguments to the system call in progress so it isn't of much
-	 * interest to the debugger.
-	 */
-	Context->Edx = TrapFrame->Edx;
-	Context->Esi = TrapFrame->Esi;
-	Context->Edi = TrapFrame->Edi;
-     }
-   if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
-     {
-	Context->SegDs = TrapFrame->Ds;
-	Context->SegEs = TrapFrame->Es;
-	Context->SegFs = TrapFrame->Fs;
-	Context->SegGs = TrapFrame->Gs;
-     }
+    /* Start with the Control flags */
+    if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
+    {
+        /* EBP, EIP and EFLAGS */
+        Context->Ebp = TrapFrame->Ebp;
+        Context->Eip = TrapFrame->Eip;
+        Context->EFlags = TrapFrame->Eflags;
+
+        /* Return the correct CS */
+        if (!(TrapFrame->Cs & FRAME_EDITED) &&
+            !(TrapFrame->Eflags & X86_EFLAGS_VM))
+        {
+            /* Get it from the Temp location */
+            Context->SegCs = TrapFrame->TempCs & 0xFFFF;
+        }
+        else
+        {
+            /* Return it directly */
+            Context->SegCs = TrapFrame->Cs & 0xFFFF;
+        }
+
+        /* Get the Ss and ESP */
+        Context->SegSs = KiSsFromTrapFrame(TrapFrame);
+        Context->Esp = KiEspFromTrapFrame(TrapFrame);
+    }
+
+    /* Handle the Segments */
+    if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
+    {
+        /* Do V86 Mode first */
+        if (TrapFrame->Eflags & X86_EFLAGS_VM)
+        {
+            /* Return from the V86 location */
+            Context->SegGs = TrapFrame->V86_Gs & 0xFFFF;
+            Context->SegFs = TrapFrame->V86_Fs & 0xFFFF;
+            Context->SegEs = TrapFrame->V86_Es & 0xFFFF;
+            Context->SegDs = TrapFrame->V86_Ds & 0xFFFF;
+        }
+        else
+        {
+            /* Check if this was a Kernel Trap */
+            if (TrapFrame->Cs == KERNEL_CS)
+            {
+                /* Set valid selectors */
+                TrapFrame->Gs = 0;
+                TrapFrame->Fs = PCR_SELECTOR;
+                TrapFrame->Es = USER_DS;
+                TrapFrame->Ds = USER_DS;
+            }
+
+            /* Return the segments */
+            Context->SegGs = TrapFrame->Gs & 0xFFFF;
+            Context->SegFs = TrapFrame->Fs & 0xFFFF;
+            Context->SegEs = TrapFrame->Es & 0xFFFF;
+            Context->SegDs = TrapFrame->Ds & 0xFFFF;
+        }
+    }
+
+    /* Handle the simple registers */
+    if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+    {
+        /* Return them directly */
+        Context->Eax = TrapFrame->Eax;
+        Context->Ebx = TrapFrame->Ebx;
+        Context->Ecx = TrapFrame->Ecx;
+        Context->Edx = TrapFrame->Edx;
+        Context->Esi = TrapFrame->Esi;
+        Context->Edi = TrapFrame->Edi;
+    }
+
    if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
-     {
+   {
 	/*
 	 * FIXME: Implement this case
 	 */
 	Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
      }
    if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
-     {
+   {
 	/*
 	 * FIXME: Implement this case
 	 *
@@ -676,7 +911,7 @@
      }
 #if 0
    if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
-     {
+   {
 	/*
 	 * FIXME: Investigate this
 	 *
@@ -931,7 +1166,7 @@
     ULONG_PTR Stack, NewStack;
     ULONG Size;
     BOOLEAN UserDispatch = FALSE;
-    DPRINT1("KiDispatchException() called\n");
+    DPRINT("KiDispatchException() called\n");
 
     /* Increase number of Exception Dispatches */
     KeGetCurrentPrcb()->KeExceptionDispatchCount++;
@@ -947,7 +1182,7 @@
     }
 
     /* Get a Context */
-    KeTrapFrameToContext(TrapFrame, &Context);
+    KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
 
     /* Handle kernel-mode first, it's simpler */
     if (PreviousMode == KernelMode)
@@ -1017,7 +1252,7 @@
                 /* Align context size and get stack pointer */
                 Size = (sizeof(CONTEXT) + 3) & ~3;
                 Stack = (Context.Esp & ~3) - Size;
-                DPRINT1("Stack: %lx\n", Stack);
+                DPRINT("Stack: %lx\n", Stack);
 
                 /* Probe stack and copy Context */
                 ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
@@ -1028,7 +1263,7 @@
                         (EXCEPTION_MAXIMUM_PARAMETERS - ExceptionRecord->NumberParameters) *
                         sizeof(ULONG) + 3) & ~3;
                 NewStack = Stack - Size;
-                DPRINT1("NewStack: %lx\n", NewStack);
+                DPRINT("NewStack: %lx\n", NewStack);
 
                 /* Probe stack and copy exception record. Don't forget to add the two params */
                 ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
@@ -1041,7 +1276,7 @@
                 *(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
 
                 /* Set new Stack Pointer */
-                TrapFrame->Esp = NewStack - 2 * sizeof(ULONG_PTR);
+                KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
 
                 /* Set EIP to the User-mode Dispathcer */
                 TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
@@ -1073,7 +1308,7 @@
 
 Handled:
     /* Convert the context back into Trap/Exception Frames */
-    KeContextToTrapFrame(&Context, NULL, TrapFrame);
+    KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
     return;
 }
 

Modified: trunk/reactos/ntoskrnl/ke/i386/fpu.c
--- trunk/reactos/ntoskrnl/ke/i386/fpu.c	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/i386/fpu.c	2005-09-13 19:33:49 UTC (rev 17838)
@@ -528,7 +528,7 @@
 
       /* Fill the rest of the context */
       Context->ContextFlags = CONTEXT_FULL;
-      KeTrapFrameToContext(Tf, Context);
+      KeTrapFrameToContext(Tf, NULL, Context);
       Context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
 
       /* Determine exception code */

Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
--- trunk/reactos/ntoskrnl/ke/i386/syscall.S	2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/i386/syscall.S	2005-09-13 19:33:49 UTC (rev 17838)
@@ -1,13 +1,8 @@
-/* $Id$
- *
+/*
  * FILE:            ntoskrnl/ke/i386/syscall.S
  * COPYRIGHT:       See COPYING in the top level directory
  * PURPOSE:         System Call Handler
  * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
- * UPDATE HISTORY:
- *                  ??-??-??: Original Version - David Welch(?)
- *                  13-01-05: Complete rewrite, added support for SYSENTER, direct kmode syscalls
- *                            and re-wrote most of handler code. - Alex Ionescu
  */
 
 #include <roscfg.h>
@@ -16,275 +11,491 @@
 #include <ndk/i386/segment.h>
 
 #define UserMode  (1)
+#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C
 
-.globl KeReturnFromSystemCallWithHook
 .globl _KiServiceExit
 .globl _KiServiceExit2
 .globl _KiFastCallEntry
 .globl _KiSystemService
 .globl _KiDebugService
+.intel_syntax noprefix
 
+/*
+ * NOTE: I will create some macros for trap entry and exit,
+ * DR* register restoration, modified frame exit, etc, if GAS
+ * allows it/I find a way how. This would remove a lot of
+ * duplicated code in this file plus the other irq/trap asm files.
+ * I think this is similar to what NT does, if you look at teh
+ * Dr_kit*_a functions which look auto-generated.
+ */
+
+/*
+ * There are 3 main types of Trap Exits:
+ *
+ * - KiServiceExit
+ *     - Clear interrupt flag
+ *     - Common User APC Dispatching
+ *     - Common exit code; segments and volatiles are not restored
+ * You use this for System Call return, when volatiles are irrelevant.
+ * (NtContinue, NtRaiseException, KiCallUserMode and all System Call returns)
+ *
+ * - KiServiceExit2
+ *     - Clear interrupt flag
+ *     - Common User APC Dispatching
+ *     - Common exit code; the entire frame is restored.
+ * You use this when volatiles and other registers need to be restored.
+ * For example, if debugging is active (NtContinue, NtRaiseException).
+ *
+ * - Kei386EoiHelper
+ *     - Clear interrupt flag
+ *     - Common User APC Dispatching
+ *     - Common exit code; the entire frame is restored but *NOT* the Previous Mode
+ * You use this in the same context as KiServiceExit2, but when the Previous Mode
+ * should be tampered with. Clearly, as its name suggests, this routine is mostly
+ * useful for End Of Interrupts.
+ * Note that this routine is EXPORTED.
+ * Note that this routine must called by a JMP, not a CALL.
+ */
+
+/*
+ * The common exit code has 3 modes of operation:
+ *    - Whether or not to restore segments
+ *    - Whether or not to restore volatiles
+ *    - Whether or not to restore the previous mode
+ * All these are exemplified by the 3 trap exits shown above
+ */
+
+/*
+ * There is also common Debug Code present in the common exit code, which
+ * in turn calls common code to save the debug registers
+ */
+ 
+ /*
+  * FIXMEs:
+  *         - Fix Win32k Callbacks so we can optimize stack usage.
+  *         - Dig in trap code and see why we need to push/pop the segments,
+  *           which -shouldn't- be needed on syscalls; one of the things
+  *           missing for this to work is lazy loading in the GPF handler,
+  *           but there are other things to consider.
+  *         - Use macros and merge with trap.s nicely
+  */
+
+/*
+ * Entries will be discussed later.
+ */
+ 
+ /*** This file is a mess; it is being worked on. Please contact Alex:
+  *** alex@relsoft.net if you want to make any changes to it before this
+  *** message goes away
+  */
+
+/* FUNCTIONS ***************************************************************/
+
+BadStack:
+
+    /* Restore ESP0 stack */
+    mov ecx, [fs:KPCR_TSS]
+    mov esp, ss:[ecx+KTSS_ESP0]
+
+    /* FIXME: Generate Trap 6*/
+    int 3
+
 _KiFastCallEntry:
 
+// ==================== UNIQUE SYSENTER STUB. DO NOT DUPLICATE ============//
     /* Set FS to PCR */
-    movl $PCR_SELECTOR, %ecx
-    movw %cx, %fs
+    mov ecx, PCR_SELECTOR
+    mov fs, cx
 
+    /* Set DS/ES to Kernel Selector */
+    mov ecx, KERNEL_DS
+    mov ds, cx
+    mov es, cx
+
     /* Set the current stack to Kernel Stack */
-    movl %fs:KPCR_TSS, %ecx
-    movl %ss:KTSS_ESP0(%ecx), %ecx
-    movl %ecx, %esp
+    mov ecx, [fs:KPCR_TSS]
+    mov esp, ss:[ecx+KTSS_ESP0]
+    /*
+     * ^^^^^ Normally we should be able to use KTHREAD.InitialStack - sizeof
+     *       KTRAP_FRAME - sizeof(NPX_AREA) and that will give us exactly
+     *       our esp (ie: ebp == esp by the way the system is organized).
+     *       This didn't work until I added v86m trap frame bias, which was
+     *       needed anways. It works NICELY until we hit a Win32K Callback,
+     *       which also messes up a lea esp, [ebp+...] below. It seems the
+     *       stack for callbacks isn't properly set up (it's missing sizeof
+     *       KTRAP_FRAME), which is understandable since the whole code is
+     *       messed up and smashes new stacks instead of using the kernel
+     *       assigned one.
+     */
 
     /* Set up a fake INT Stack. */
-    pushl $USER_DS
-    pushl %edx                  /* Ring 3 SS:ESP */
-    pushfl
-    orl $X86_EFLAGS_IF, (%esp)  /* Re-enable IRQs in EFLAGS, to fake INT */
-    pushl $USER_CS
-    pushl $KUSER_SHARED_SYSCALL_RET
+    push USER_DS
+    push edx                            /* Ring 3 SS:ESP */
+    pushf                               /* Ring 3 EFLAGS */
+    push 2                              /* Ring 0 EFLAGS */
+    add edx, 8                          /* Skip user parameter list */
+    popf                                /* Set our EFLAGS */
+    or dword ptr [esp], X86_EFLAGS_IF   /* Re-enable IRQs in EFLAGS, to fake INT */
+    push USER_CS
[truncated at 1000 lines; 1168 more skipped]