[PSEH3]
[reactos.git] / reactos / lib / pseh / i386 / pseh3.c
index 13e5df1..8a3be57 100644 (file)
@@ -34,6 +34,8 @@
 #include <windef.h>
 #include <winnt.h>
 
+/* We need the full structure with all non-volatile */
+#define _SEH3$_FRAME_ALL_NONVOLATILES 1
 #include "pseh3.h"
 #include "pseh3_asmdef.h"
 
@@ -48,8 +50,9 @@ C_ASSERT(SEH3_REGISTRATION_FRAME_Ebp == FIELD_OFFSET(SEH3$_REGISTRATION_FRAME, E
 C_ASSERT(SEH3_SCOPE_TABLE_Filter == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Filter));
 C_ASSERT(SEH3_SCOPE_TABLE_Target == FIELD_OFFSET(SEH3$_SCOPE_TABLE, Target));
 
-static inline
-void _SEH3$_Unregister(
+void
+__attribute__((regparm(1)))
+_SEH3$_Unregister(
     volatile SEH3$_REGISTRATION_FRAME *Frame)
 {
     if (Frame->Handler)
@@ -60,8 +63,8 @@ void _SEH3$_Unregister(
 
 static inline
 LONG
-_SEH3$_InvokeFilter(
-    PVOID Record,
+_SEH3$_InvokeNestedFunctionFilter(
+    PSEH3$_REGISTRATION_FRAME RegistrationFrame,
     PVOID Filter)
 {
     LONG FilterResult;
@@ -75,18 +78,75 @@ _SEH3$_InvokeFilter(
         /* The result is the frame base address that we passed in (0) plus the
            offset to the registration record. */
         "negl %%eax\n\t"
-        "addl %[Record], %%eax\n\t"
+        "addl %[RegistrationFrame], %%eax\n\t"
 
         /* Second call to get the filter result */
         "mov $1, %%ecx\n\t"
-        "call *%[Filter]\n\t"
-        : "=a"(FilterResult)
-        : [Record] "m" (Record), [Filter] "m" (Filter)
+        "call *%[Filter]"
+        : "=a" (FilterResult)
+        : [RegistrationFrame] "m" (RegistrationFrame), [Filter] "m" (Filter)
         : "ecx", "edx");
 
     return FilterResult;
 }
 
+long
+__attribute__((regparm(1)))
+_SEH3$_InvokeEmbeddedFilter(
+    PSEH3$_REGISTRATION_FRAME RegistrationFrame);
+
+long
+__attribute__((regparm(1)))
+_SEH3$_InvokeEmbeddedFilterFromRegistration(
+    PSEH3$_REGISTRATION_FRAME RegistrationFrame);
+
+static inline
+LONG
+_SEH3$_InvokeFilter(
+    PSEH3$_REGISTRATION_FRAME RegistrationFrame,
+    PVOID Filter)
+{
+    LONG FilterResult;
+
+    if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_NESTED_HANDLER)
+    {
+        return _SEH3$_InvokeNestedFunctionFilter(RegistrationFrame, Filter);
+    }
+    else if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_CPP_HANDLER)
+    {
+        /* Call the embedded filter function */
+        return _SEH3$_InvokeEmbeddedFilter(RegistrationFrame);
+    }
+    else if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_CLANG_HANDLER)
+    {
+        return _SEH3$_InvokeEmbeddedFilterFromRegistration(RegistrationFrame);
+    }
+    else
+    {
+        /* Should not happen! Skip this handler */
+        FilterResult = EXCEPTION_CONTINUE_SEARCH;
+    }
+
+    return FilterResult;
+}
+
+void
+__attribute__((regparm(1)))
+_SEH3$_AutoCleanup(
+    SEH3$_REGISTRATION_FRAME *Frame)
+{
+    /* Check for __finally frames */
+    if (Frame->ScopeTable->Target == NULL)
+    {
+         _SEH3$_InvokeFilter(Frame, Frame->ScopeTable->Filter);
+    }
+
+    if (Frame->Handler)
+        _SEH3$_UnregisterFrame(Frame);
+    else
+        _SEH3$_UnregisterTryLevel(Frame);
+}
+
 static inline
 LONG
 _SEH3$_GetFilterResult(
@@ -133,45 +193,51 @@ void
 _SEH3$_JumpToTarget(
     PSEH3$_REGISTRATION_FRAME RegistrationFrame)
 {
-    asm volatile (
-        /* Load the registers */
-        "movl 20(%%ecx), %%esp\n"
-        "movl 24(%%ecx), %%ebp\n"
-
-        /* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
-        "addl $4, %%esp\n"
-
-        /* Jump into the exception handler */
-        "jmp *%[Target]\n"
-        : :
-        "c" (RegistrationFrame),
-        "a" (RegistrationFrame->ScopeTable),
-         [Target] "m" (RegistrationFrame->ScopeTable->Target)
-    );
+    if (RegistrationFrame->ScopeTable->HandlerType == _SEH3$_CLANG_HANDLER)
+    {
+        asm volatile (
+            /* Load the registers */
+            "movl 24(%%ecx), %%esp\n\t"
+            "movl 28(%%ecx), %%ebp\n\t"
+
+            /* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
+            "addl $4, %%esp\n\t"
+
+            /* Jump into the exception handler */
+            "jmp *%[Target]"
+            : :
+            "c" (RegistrationFrame),
+            "a" (RegistrationFrame->ScopeTable),
+             [Target] "m" (RegistrationFrame->ScopeTable->Target)
+        );
+    }
+    else
+    {
+        asm volatile (
+            /* Load the registers */
+            "movl 24(%%ecx), %%esp\n\t"
+            "movl 28(%%ecx), %%ebp\n\t"
+
+            /* Stack pointer is 4 off from the call to __SEH3$_RegisterFrame */
+            "addl $4, %%esp\n\t"
+
+            /* Jump into the exception handler */
+            "jmp *%[Target]"
+            : :
+            "c" (RegistrationFrame),
+            "a" (RegistrationFrame->ScopeTable),
+             [Target] "m" (RegistrationFrame->ScopeTable->Target)
+        );
+    }
 
     __builtin_unreachable();
 }
 
-static inline
 void
+__fastcall
 _SEH3$_CallRtlUnwind(
-    PSEH3$_REGISTRATION_FRAME RegistrationFrame)
-{
-    LONG ClobberedEax;
-
-    asm volatile(
-        "push %%ebp\n"
-        "push $0\n"
-        "push $0\n"
-        "push $0\n"
-        "push %[TargetFrame]\n"
-        "call _RtlUnwind@16\n"
-        "pop %%ebp\n"
-        : "=a" (ClobberedEax)
-        : [TargetFrame] "a" (RegistrationFrame)
-        : "ebx", "ecx", "edx", "esi",
-          "edi", "flags", "memory");
-}
+    PSEH3$_REGISTRATION_FRAME RegistrationFrame);
+
 
 EXCEPTION_DISPOSITION
 __cdecl
@@ -187,7 +253,11 @@ _SEH3$_except_handler(
     LONG FilterResult;
 
     /* Clear the direction flag. */
-    asm volatile ("cld\n" : : : "memory");
+    asm volatile ("cld" : : : "memory");
+
+    /* Save the exception pointers on the stack */
+    ExceptionPointers.ExceptionRecord = ExceptionRecord;
+    ExceptionPointers.ContextRecord = ContextRecord;
 
     /* Check if this is an unwind */
     if (ExceptionRecord->ExceptionFlags & EXCEPTION_UNWINDING)
@@ -197,10 +267,6 @@ _SEH3$_except_handler(
     }
     else
     {
-        /* Save the exception pointers on the stack */
-        ExceptionPointers.ExceptionRecord = ExceptionRecord;
-        ExceptionPointers.ContextRecord = ContextRecord;
-
         /* Loop all frames for this registration */
         CurrentFrame = EstablisherFrame->EndOfChain;
         for (;;)
@@ -208,8 +274,9 @@ _SEH3$_except_handler(
             /* Check if we have an exception handler */
             if (CurrentFrame->ScopeTable->Target != NULL)
             {
-                /* Set exception pointers for this frame */
+                /* Set exception pointers and code for this frame */
                 CurrentFrame->ExceptionPointers = &ExceptionPointers;
+                CurrentFrame->ExceptionCode = ExceptionRecord->ExceptionCode;
 
                 /* Get the filter result */
                 FilterResult = _SEH3$_GetFilterResult(CurrentFrame);
@@ -250,8 +317,9 @@ _SEH3$_except_handler(
         /* Check if this is an unwind frame */
         if (CurrentFrame->ScopeTable->Target == NULL)
         {
-            /* Set exception pointers for this frame */
+            /* Set exception pointers and code for this frame */
             CurrentFrame->ExceptionPointers = &ExceptionPointers;
+            CurrentFrame->ExceptionCode = ExceptionRecord->ExceptionCode;
 
             /* Call the finally function */
             _SEH3$_CallFinally(CurrentFrame);