[RTL]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 7 Nov 2009 15:26:12 +0000 (15:26 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 7 Nov 2009 15:26:12 +0000 (15:26 +0000)
- Implement RtlRaiseException

svn path=/branches/ros-amd64-bringup/; revision=44001

reactos/lib/rtl/amd64/unwind.c
reactos/lib/rtl/exception.c

index 276981d..fabda83 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS system libraries
- * PURPOSE:         Exception related functions
+ * PURPOSE:         Unwinding related functions
  * PROGRAMMER:      Timo Kreuzer (timo.kreuzer@reactos.org)
  */
 
 #define UWOP_SAVE_XMM128_FAR 9
 #define UWOP_PUSH_MACHFRAME 10
 
+#define UNW_FLAG_NHANDLER 0
+#define UNW_FLAG_EHANDLER 1
+#define UNW_FLAG_UHANDLER 2
+#define UNW_FLAG_CHAININFO 4
+
 typedef unsigned char UBYTE;
 
 typedef union _UNWIND_CODE
@@ -611,3 +616,69 @@ RtlGetCallersAddress(
 
     return;
 }
+
+// FIXME: move to different file
+VOID
+NTAPI
+RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
+{
+    CONTEXT Context;
+    NTSTATUS Status;
+    ULONG64 ImageBase;
+    PRUNTIME_FUNCTION FunctionEntry;
+    PVOID HandlerData;
+    ULONG64 EstablisherFrame;
+
+    /* Capture the context */
+    RtlCaptureContext(&Context);
+
+    /* Get the function entry for this function */
+    FunctionEntry = RtlLookupFunctionEntry(Context.Rip,
+                                           &ImageBase,
+                                           NULL);
+
+    /* Check if we found it */
+    if (FunctionEntry)
+    {
+        /* Unwind to the caller of this function */
+        RtlVirtualUnwind(UNW_FLAG_NHANDLER,
+                         ImageBase,
+                         Context.Rip,
+                         FunctionEntry,
+                         &Context,
+                         &HandlerData,
+                         &EstablisherFrame,
+                         NULL);
+
+        /* Save the exception address */
+        ExceptionRecord->ExceptionAddress = (PVOID)Context.Rip;
+
+        /* Write the context flag */
+        Context.ContextFlags = CONTEXT_FULL;
+
+        /* Check if user mode debugger is active */
+        if (RtlpCheckForActiveDebugger())
+        {
+            /* Raise an exception immediately */
+            Status = ZwRaiseException(ExceptionRecord, &Context, TRUE);
+        }
+        else
+        {
+            /* Dispatch the exception and check if we should continue */
+            if (!RtlDispatchException(ExceptionRecord, &Context))
+            {
+                /* Raise the exception */
+                Status = ZwRaiseException(ExceptionRecord, &Context, FALSE);
+            }
+            else
+            {
+                /* Continue, go back to previous context */
+                Status = ZwContinue(&Context, FALSE);
+            }
+        }
+    }
+
+    /* If we returned, raise a status */
+    RtlRaiseStatus(Status);
+}
+
index d4462e3..e0970d1 100644 (file)
@@ -17,7 +17,7 @@
 
 /* FUNCTIONS ***************************************************************/
 
-#if !defined(_M_IX86)
+#if !defined(_M_IX86) && !defined(_M_AMD64)
 
 /*
  * @implemented
@@ -63,6 +63,10 @@ RtlRaiseException(IN PEXCEPTION_RECORD ExceptionRecord)
     RtlRaiseStatus(Status);
 }
 
+#endif
+
+#if !defined(_M_IX86)
+
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4717) // RtlRaiseStatus is recursive by design