Piotr Caban : ntdll: Add support for ExceptionCollidedUnwind return from exception handler.

Alexandre Julliard julliard at winehq.org
Thu Aug 18 10:23:24 CDT 2016


Module: wine
Branch: master
Commit: abebb8141264ee5e1b701f4e28f5275426ed0a0d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=abebb8141264ee5e1b701f4e28f5275426ed0a0d

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Aug 17 12:48:05 2016 +0200

ntdll: Add support for ExceptionCollidedUnwind return from exception handler.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/signal_x86_64.c | 99 +++++++++++++++++++++++++---------------------
 1 file changed, 55 insertions(+), 44 deletions(-)

diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 79ca846..e54f162 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -2256,31 +2256,15 @@ static RUNTIME_FUNCTION *lookup_function_info( ULONG64 pc, ULONG64 *base, LDR_MO
  * Call a single exception handler.
  * FIXME: Handle nested exceptions.
  */
-static NTSTATUS call_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch, CONTEXT *orig_context )
+static DWORD call_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch )
 {
     DWORD res;
 
-    dispatch->ControlPc = dispatch->ContextRecord->Rip;
-
     TRACE( "calling handler %p (rec=%p, frame=0x%lx context=%p, dispatch=%p)\n",
            dispatch->LanguageHandler, rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
     res = dispatch->LanguageHandler( rec, dispatch->EstablisherFrame, dispatch->ContextRecord, dispatch );
     TRACE( "handler at %p returned %u\n", dispatch->LanguageHandler, res );
-
-    switch (res)
-    {
-    case ExceptionContinueExecution:
-        if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION;
-        *orig_context = *dispatch->ContextRecord;
-        return STATUS_SUCCESS;
-    case ExceptionContinueSearch:
-        break;
-    case ExceptionNestedException:
-        break;
-    default:
-        return STATUS_INVALID_DISPOSITION;
-    }
-    return STATUS_UNHANDLED_EXCEPTION;
+    return res;
 }
 
 
@@ -2290,31 +2274,16 @@ static NTSTATUS call_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatc
  * Call a single exception handler from the TEB chain.
  * FIXME: Handle nested exceptions.
  */
-static NTSTATUS call_teb_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch,
-                                  EXCEPTION_REGISTRATION_RECORD *teb_frame, CONTEXT *orig_context )
+static DWORD call_teb_handler( EXCEPTION_RECORD *rec, DISPATCHER_CONTEXT *dispatch,
+                                  EXCEPTION_REGISTRATION_RECORD *teb_frame )
 {
-    EXCEPTION_REGISTRATION_RECORD *dispatcher;
     DWORD res;
 
-    TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatcher=%p)\n",
-           teb_frame->Handler, rec, teb_frame, dispatch->ContextRecord, &dispatcher );
-    res = teb_frame->Handler( rec, teb_frame, dispatch->ContextRecord, &dispatcher );
+    TRACE( "calling TEB handler %p (rec=%p, frame=%p context=%p, dispatch=%p)\n",
+           teb_frame->Handler, rec, teb_frame, dispatch->ContextRecord, dispatch );
+    res = teb_frame->Handler( rec, teb_frame, dispatch->ContextRecord, (EXCEPTION_REGISTRATION_RECORD**)dispatch );
     TRACE( "handler at %p returned %u\n", teb_frame->Handler, res );
-
-    switch (res)
-    {
-    case ExceptionContinueExecution:
-        if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION;
-        *orig_context = *dispatch->ContextRecord;
-        return STATUS_SUCCESS;
-    case ExceptionContinueSearch:
-        break;
-    case ExceptionNestedException:
-        break;
-    default:
-        return STATUS_INVALID_DISPOSITION;
-    }
-    return STATUS_UNHANDLED_EXCEPTION;
+    return res;
 }
 
 
@@ -2336,7 +2305,6 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
     dispatch.TargetIp      = 0;
     dispatch.ContextRecord = &context;
     dispatch.HistoryTable  = &table;
-    dispatch.ScopeIndex    = 0; /* FIXME */
     for (;;)
     {
         new_context = context;
@@ -2344,6 +2312,8 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
         /* FIXME: should use the history table to make things faster */
 
         dispatch.ImageBase = 0;
+        dispatch.ControlPc = context.Rip;
+        dispatch.ScopeIndex = 0;
 
         /* first look for PE exception information */
 
@@ -2415,8 +2385,28 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
 
         if (dispatch.LanguageHandler)
         {
-            status = call_handler( rec, &dispatch, orig_context );
-            if (status != STATUS_UNHANDLED_EXCEPTION) return status;
+            switch (call_handler( rec, &dispatch ))
+            {
+            case ExceptionContinueExecution:
+                if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION;
+                *orig_context = *dispatch.ContextRecord;
+                return STATUS_SUCCESS;
+            case ExceptionContinueSearch:
+            case ExceptionNestedException:
+                break;
+            case ExceptionCollidedUnwind: {
+                ULONG64 frame;
+
+                context = *dispatch.ContextRecord;
+                dispatch.ContextRecord = &context;
+                RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
+                        dispatch.ControlPc, dispatch.FunctionEntry,
+                        &context, NULL, &frame, NULL );
+                goto unwind_done;
+            }
+            default:
+                return STATUS_INVALID_DISPOSITION;
+            }
         }
         /* hack: call wine handlers registered in the tib list */
         else while ((ULONG64)teb_frame < new_context.Rsp)
@@ -2425,8 +2415,29 @@ static NTSTATUS call_stack_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_contex
                    teb_frame, new_context.Rsp, teb_frame->Handler );
             dispatch.EstablisherFrame = (ULONG64)teb_frame;
             context = *orig_context;
-            status = call_teb_handler( rec, &dispatch, teb_frame, orig_context );
-            if (status != STATUS_UNHANDLED_EXCEPTION) return status;
+            switch (call_teb_handler( rec, &dispatch, teb_frame ))
+            {
+            case ExceptionContinueExecution:
+                if (rec->ExceptionFlags & EH_NONCONTINUABLE) return STATUS_NONCONTINUABLE_EXCEPTION;
+                *orig_context = *dispatch.ContextRecord;
+                return STATUS_SUCCESS;
+            case ExceptionContinueSearch:
+            case ExceptionNestedException:
+                break;
+            case ExceptionCollidedUnwind: {
+                ULONG64 frame;
+
+                context = *dispatch.ContextRecord;
+                dispatch.ContextRecord = &context;
+                RtlVirtualUnwind( UNW_FLAG_NHANDLER, dispatch.ImageBase,
+                        dispatch.ControlPc, dispatch.FunctionEntry,
+                        &context, NULL, &frame, NULL );
+                teb_frame = teb_frame->Prev;
+                goto unwind_done;
+            }
+            default:
+                return STATUS_INVALID_DISPOSITION;
+            }
             teb_frame = teb_frame->Prev;
         }
 




More information about the wine-cvs mailing list