- Fix a bug in KiRaiseException from 42923 -- a _SEH2_LEAVE wasn't converted to _SEH2...
[reactos.git] / reactos / ntoskrnl / ke / except.c
index 86ad261..7a7713b 100644 (file)
-/*\r
- * PROJECT:         ReactOS Kernel\r
- * LICENSE:         GPL - See COPYING in the top level directory\r
- * FILE:            ntoskrnl/ke/except.c\r
- * PURPOSE:         Platform independent exception handling\r
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <ntoskrnl.h>\r
-#define NDEBUG\r
-#include <internal/debug.h>\r
-\r
-/* FUNCTIONS *****************************************************************/\r
-\r
-VOID\r
-NTAPI\r
-KiContinuePreviousModeUser(IN PCONTEXT Context,\r
-                           IN PKEXCEPTION_FRAME ExceptionFrame,\r
-                           IN PKTRAP_FRAME TrapFrame)\r
-{\r
-    CONTEXT LocalContext;\r
-\r
-    /* We'll have to make a copy and probe it */\r
-    ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));\r
-    RtlMoveMemory(&LocalContext, Context, sizeof(CONTEXT));\r
-    Context = &LocalContext;\r
-\r
-    /* Convert the context into Exception/Trap Frames */\r
-    KeContextToTrapFrame(&LocalContext,\r
-                         ExceptionFrame,\r
-                         TrapFrame,\r
-                         LocalContext.ContextFlags,\r
-                         UserMode);\r
-}\r
-\r
-NTSTATUS\r
-NTAPI\r
-KiContinue(IN PCONTEXT Context,\r
-           IN PKEXCEPTION_FRAME ExceptionFrame,\r
-           IN PKTRAP_FRAME TrapFrame)\r
-{\r
-    NTSTATUS Status = STATUS_SUCCESS;\r
-    KIRQL OldIrql = APC_LEVEL;\r
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();\r
-\r
-    /* Raise to APC_LEVEL, only if needed */\r
-    if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);\r
-\r
-    /* Set up SEH to validate the context */\r
-    _SEH_TRY\r
-    {\r
-        /* Check the previous mode */\r
-        if (PreviousMode != KernelMode)\r
-        {\r
-            /* Validate from user-mode */\r
-            KiContinuePreviousModeUser(Context,\r
-                                       ExceptionFrame,\r
-                                       TrapFrame);\r
-        }\r
-        else\r
-        {\r
-            /* Convert the context into Exception/Trap Frames */\r
-            KeContextToTrapFrame(Context,\r
-                                 ExceptionFrame,\r
-                                 TrapFrame,\r
-                                 Context->ContextFlags,\r
-                                 KernelMode);\r
-        }\r
-    }\r
-    _SEH_HANDLE\r
-    {\r
-        /* Save the exception code */\r
-        Status = _SEH_GetExceptionCode();\r
-    }\r
-    _SEH_END;\r
-\r
-    /* Lower the IRQL if needed */\r
-    if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);\r
-\r
-    /* Return status */\r
-    return Status;\r
-}\r
-\r
-NTSTATUS\r
-NTAPI\r
-KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,\r
-                 IN PCONTEXT Context,\r
-                 IN PKEXCEPTION_FRAME ExceptionFrame,\r
-                 IN PKTRAP_FRAME TrapFrame,\r
-                 IN BOOLEAN SearchFrames)\r
-{\r
-    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();\r
-    CONTEXT LocalContext;\r
-    EXCEPTION_RECORD LocalExceptionRecord;\r
-    ULONG ParameterCount, Size;\r
-    NTSTATUS Status = STATUS_SUCCESS;\r
-\r
-    /* Set up SEH */\r
-    _SEH_TRY\r
-    {\r
-        /* Check the previous mode */\r
-        if (PreviousMode != KernelMode)\r
-        {\r
-#if 0\r
-            /* Probe the context */\r
-            ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));\r
-\r
-            /* Probe the Exception Record */\r
-            ProbeForRead(ExceptionRecord,\r
-                         FIELD_OFFSET(EXCEPTION_RECORD, NumberParameters) +\r
-                         sizeof(ULONG),\r
-                         sizeof(ULONG));\r
-#endif\r
-            /* Validate the maximum parameters */\r
-            if ((ParameterCount = ExceptionRecord->NumberParameters) >\r
-                EXCEPTION_MAXIMUM_PARAMETERS)\r
-            {\r
-                /* Too large */\r
-                Status = STATUS_INVALID_PARAMETER;\r
-                _SEH_LEAVE;\r
-            }\r
-\r
-            /* Probe the entire parameters now*/\r
-            Size = (sizeof(EXCEPTION_RECORD) - \r
-                    ((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));\r
-            ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));\r
-\r
-            /* Now make copies in the stack */\r
-            RtlMoveMemory(&LocalContext, Context, sizeof(CONTEXT));\r
-            RtlMoveMemory(&LocalExceptionRecord, ExceptionRecord, Size);\r
-            Context = &LocalContext;\r
-            ExceptionRecord = &LocalExceptionRecord;\r
-\r
-            /* Update the parameter count */\r
-            ExceptionRecord->NumberParameters = ParameterCount;\r
-        }\r
-    }\r
-    _SEH_HANDLE\r
-    {\r
-        /* Get the exception code */\r
-        Status = _SEH_GetExceptionCode();\r
-    }\r
-    _SEH_END;\r
-\r
-    /* Make sure we didn't crash in SEH */\r
-    if (NT_SUCCESS(Status))\r
-    {\r
-        /* Convert the context record */\r
-        KeContextToTrapFrame(Context,\r
-                             ExceptionFrame,\r
-                             TrapFrame,\r
-                             Context->ContextFlags,\r
-                             PreviousMode);\r
-\r
-        /* Dispatch the exception */\r
-        KiDispatchException(ExceptionRecord,\r
-                            ExceptionFrame,\r
-                            TrapFrame,\r
-                            PreviousMode,\r
-                            SearchFrames);\r
-    }\r
-\r
-    /* Return the status */\r
-    return Status;\r
-}\r
-\r
-/* EOF */\r
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            ntoskrnl/ke/except.c
+ * PURPOSE:         Platform independent exception handling
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+NTAPI
+KiContinuePreviousModeUser(IN PCONTEXT Context,
+                           IN PKEXCEPTION_FRAME ExceptionFrame,
+                           IN PKTRAP_FRAME TrapFrame)
+{
+    CONTEXT LocalContext;
+
+    /* We'll have to make a copy and probe it */
+    ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
+    RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
+    Context = &LocalContext;
+
+    /* Convert the context into Exception/Trap Frames */
+    KeContextToTrapFrame(&LocalContext,
+                         ExceptionFrame,
+                         TrapFrame,
+                         LocalContext.ContextFlags,
+                         UserMode);
+}
+
+NTSTATUS
+NTAPI
+KiContinue(IN PCONTEXT Context,
+           IN PKEXCEPTION_FRAME ExceptionFrame,
+           IN PKTRAP_FRAME TrapFrame)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    KIRQL OldIrql = APC_LEVEL;
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+
+    /* Raise to APC_LEVEL, only if needed */
+    if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
+
+    /* Set up SEH to validate the context */
+    _SEH2_TRY
+    {
+        /* Check the previous mode */
+        if (PreviousMode != KernelMode)
+        {
+            /* Validate from user-mode */
+            KiContinuePreviousModeUser(Context,
+                                       ExceptionFrame,
+                                       TrapFrame);
+        }
+        else
+        {
+            /* Convert the context into Exception/Trap Frames */
+            KeContextToTrapFrame(Context,
+                                 ExceptionFrame,
+                                 TrapFrame,
+                                 Context->ContextFlags,
+                                 KernelMode);
+        }
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Save the exception code */
+        Status = _SEH2_GetExceptionCode();
+    }
+    _SEH2_END;
+
+    /* Lower the IRQL if needed */
+    if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
+
+    /* Return status */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+KiRaiseException(IN PEXCEPTION_RECORD ExceptionRecord,
+                 IN PCONTEXT Context,
+                 IN PKEXCEPTION_FRAME ExceptionFrame,
+                 IN PKTRAP_FRAME TrapFrame,
+                 IN BOOLEAN SearchFrames)
+{
+    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
+    CONTEXT LocalContext;
+    EXCEPTION_RECORD LocalExceptionRecord;
+    ULONG ParameterCount, Size;
+
+    /* Check if we need to probe */
+    if (PreviousMode != KernelMode)
+    {
+        /* Set up SEH */
+        _SEH2_TRY
+        {
+            /* Probe the context */
+            ProbeForRead(Context, sizeof(CONTEXT), sizeof(ULONG));
+
+            /* Probe the Exception Record */
+            ProbeForRead(ExceptionRecord,
+                         FIELD_OFFSET(EXCEPTION_RECORD, NumberParameters) +
+                         sizeof(ULONG),
+                         sizeof(ULONG));
+
+            /* Validate the maximum parameters */
+            if ((ParameterCount = ExceptionRecord->NumberParameters) >
+                EXCEPTION_MAXIMUM_PARAMETERS)
+            {
+                /* Too large */
+                _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
+            }
+
+            /* Probe the entire parameters now*/
+            Size = (sizeof(EXCEPTION_RECORD) - 
+                    ((EXCEPTION_MAXIMUM_PARAMETERS - ParameterCount) * sizeof(ULONG)));
+            ProbeForRead(ExceptionRecord, Size, sizeof(ULONG));
+
+            /* Now make copies in the stack */
+            RtlCopyMemory(&LocalContext, Context, sizeof(CONTEXT));
+            RtlCopyMemory(&LocalExceptionRecord, ExceptionRecord, Size);
+            Context = &LocalContext;
+            ExceptionRecord = &LocalExceptionRecord;
+
+            /* Update the parameter count */
+            ExceptionRecord->NumberParameters = ParameterCount;
+        }
+        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+        {
+            /* Don't fail silently */
+            DPRINT1("KiRaiseException: Failed to Probe\n");
+            DbgBreakPoint();
+
+            /* Return the exception code */
+            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+        }
+        _SEH2_END;
+    }
+
+    /* Convert the context record */
+    KeContextToTrapFrame(Context,
+                         ExceptionFrame,
+                         TrapFrame,
+                         Context->ContextFlags,
+                         PreviousMode);
+
+    /* Dispatch the exception */
+    ExceptionRecord->ExceptionCode &= ~KI_EXCEPTION_INTERNAL;
+    KiDispatchException(ExceptionRecord,
+                        ExceptionFrame,
+                        TrapFrame,
+                        PreviousMode,
+                        SearchFrames);
+
+    /* We are done */
+    return STATUS_SUCCESS;
+}
+
+/* EOF */