- Small patch to fix (delayed) loading of floating point state. Enables the special...
[reactos.git] / reactos / ntoskrnl / ke / i386 / traphdlr.c
index 80ab637..9e5defe 100644 (file)
@@ -15,6 +15,9 @@
 VOID KiFastCallEntry(VOID);
 VOID KiFastCallEntryWithSingleStep(VOID);
 
+extern PVOID FrRestore;
+VOID FASTCALL Ke386LoadFpuState(IN PFX_SAVE_AREA SaveArea);
+
 /* GLOBALS ********************************************************************/
 
 UCHAR KiTrapPrefixTable[] =
@@ -49,7 +52,7 @@ UCHAR KiTrapIoTable[] =
 };
 
 PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
-#if DBG && !defined(_WINKD_)
+#if DBG && defined(_M_IX86) && !defined(_WINKD_)
 PKDBG_PRESERVICEHOOK KeWin32PreServiceHook = NULL;
 PKDBG_POSTSERVICEHOOK KeWin32PostServiceHook = NULL;
 #endif
@@ -223,6 +226,7 @@ KiDebugHandler(IN PKTRAP_FRAME TrapFrame,
 
     /* Dispatch the exception  */
     KiDispatchExceptionFromTrapFrame(STATUS_BREAKPOINT,
+                                     0,
                                      TrapFrame->Eip - 1,
                                      3,
                                      Parameter1,
@@ -250,16 +254,16 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
         SaveArea->Cr0NpxState |= CR0_TS;
 
         /* Only valid if it happened during a restore */
-        //if ((PVOID)TrapFrame->Eip == FrRestore)
+        if ((PVOID)TrapFrame->Eip == FrRestore)
         {
             /* It did, so just skip the instruction */
-            //TrapFrame->Eip += 3; /* sizeof(FRSTOR) */
-            //KiEoiHelper(TrapFrame);
+            TrapFrame->Eip += 3; /* Size of FRSTOR instruction */
+            KiEoiHelper(TrapFrame);
         }
     }
 
     /* User or kernel trap -- get ready to issue an exception */
-    //if (Thread->NpxState == NPX_STATE_NOT_LOADED)
+    if (Thread->NpxState == NPX_STATE_NOT_LOADED)
     {
         /* Update CR0 */
         Cr0 = __readcr0();
@@ -743,7 +747,7 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
     KiEnterTrap(TrapFrame);
 
     /* Try to handle NPX delay load */
-    while (TRUE)
+    for (;;)
     {
         /* Get the current thread */
         Thread = KeGetCurrentThread();
@@ -774,15 +778,14 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
                 NpxSaveArea = KiGetThreadNpxArea(NpxThread);
 
                 /* Save FPU state */
-                DPRINT("FIXME: Save FPU state: %p\n", NpxSaveArea);
-                //Ke386SaveFpuState(NpxSaveArea);
+                Ke386SaveFpuState(NpxSaveArea);
 
                 /* Update NPX state */
                 NpxThread->NpxState = NPX_STATE_NOT_LOADED;
            }
 
             /* Load FPU state */
-            //Ke386LoadFpuState(SaveArea);
+            Ke386LoadFpuState(SaveArea);
 
             /* Update NPX state */
             Thread->NpxState = NPX_STATE_LOADED;
@@ -822,7 +825,7 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
     {
         /*
          * If it's incorrectly set, then maybe the state is actually still valid
-         * but we could've lock track of that due to a BIOS call.
+         * but we could have lost track of that due to a BIOS call.
          * Make sure MP is still set, which should verify the theory.
          */
         if (Cr0 & CR0_MP)
@@ -1274,7 +1277,15 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
                            (PVOID)Cr2,
                            KiUserTrap(TrapFrame),
                            TrapFrame);
-    if (NT_SUCCESS(Status)) KiEoiHelper(TrapFrame);
+    if (NT_SUCCESS(Status))
+    {
+#ifdef _WINKD_
+        /* Check whether the kernel debugger has owed breakpoints to be inserted */
+        KdSetOwedBreakpoints();
+#endif
+        /* We succeeded, return */
+        KiEoiHelper(TrapFrame);
+    }
 
     /* Check for syscall fault */
 #if 0
@@ -1311,6 +1322,7 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame)
 
     /* Only other choice is an in-page error, with 3 parameters */
     KiDispatchExceptionFromTrapFrame(STATUS_IN_PAGE_ERROR,
+                                     0,
                                      TrapFrame->Eip,
                                      3,
                                      TrapFrame->ErrCode & 2 ? TRUE : FALSE,
@@ -1474,10 +1486,14 @@ KiRaiseSecurityCheckFailureHandler(IN PKTRAP_FRAME TrapFrame)
     if (KiUserTrap(TrapFrame))
     {
         /* Dispatch exception to user mode */
-        KiDispatchException1Args(STATUS_STACK_BUFFER_OVERRUN,
-                                 TrapFrame->Eip,
-                                 TrapFrame->Ecx,
-                                 TrapFrame);
+        KiDispatchExceptionFromTrapFrame(STATUS_STACK_BUFFER_OVERRUN,
+                                         EXCEPTION_NONCONTINUABLE,
+                                         TrapFrame->Eip,
+                                         1,
+                                         TrapFrame->Ecx,
+                                         0,
+                                         0,
+                                         TrapFrame);
     }
     else
     {
@@ -1511,8 +1527,18 @@ VOID
 FASTCALL
 KiCallbackReturnHandler(IN PKTRAP_FRAME TrapFrame)
 {
+    PKTHREAD Thread;
     NTSTATUS Status;
 
+    /* Save the SEH chain, NtCallbackReturn will restore this */
+    TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
+
+    /* Set thread fields */
+    Thread = KeGetCurrentThread();
+    Thread->TrapFrame = TrapFrame;
+    Thread->PreviousMode = KiUserTrap(TrapFrame);
+    NT_ASSERT(Thread->PreviousMode != KernelMode);
+
     /* Pass the register parameters to NtCallbackReturn.
        Result pointer is in ecx, result length in edx, status in eax */
     Status = NtCallbackReturn((PVOID)TrapFrame->Ecx,
@@ -1657,7 +1683,6 @@ KiSystemServiceHandler(IN PKTRAP_FRAME TrapFrame,
         if (!NT_SUCCESS(Result))
         {
             /* Set the last error and fail */
-            //SetLastWin32Error(RtlNtStatusToDosError(Result));
             goto ExitCall;
         }