Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/mingw/samples/seh/eh3.c')
-rw-r--r--winsup/mingw/samples/seh/eh3.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/winsup/mingw/samples/seh/eh3.c b/winsup/mingw/samples/seh/eh3.c
new file mode 100644
index 000000000..e00201904
--- /dev/null
+++ b/winsup/mingw/samples/seh/eh3.c
@@ -0,0 +1,112 @@
+int
+__except_handler3(
+ struct _EXCEPTION_RECORD* pExceptionRecord,
+ struct EXCEPTION_REGISTRATION* pRegistrationFrame,
+ struct _CONTEXT* pContextRecord,
+ void* pDispatcherContext
+ )
+{
+ LONG filterFuncRet;
+ LONG trylevel;
+ EXCEPTION_POINTERS exceptPtrs;
+ PSCOPETABLE pScopeTable;
+
+
+ CLD // Clear the direction flag (make no assumptions!)
+
+ // if neither the EXCEPTION_UNWINDING nor EXCEPTION_EXIT_UNWIND bit
+ // is set... This is true the first time through the handler (the
+ // non-unwinding case)
+
+ if ( ! (pExceptionRecord->ExceptionFlags
+ & (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND)
+ ) )
+ {
+ // Build the EXCEPTION_POINTERS structure on the stack
+ exceptPtrs.ExceptionRecord = pExceptionRecord;
+ exceptPtrs.ContextRecord = pContextRecord;
+
+ // Put the pointer to the EXCEPTION_POINTERS 4 bytes below the
+ // establisher frame. See ASM code for GetExceptionInformation
+ *(PDWORD)((PBYTE)pRegistrationFrame - 4) = &exceptPtrs;
+
+ // Get initial "trylevel" value
+ trylevel = pRegistrationFrame->trylevel
+
+ // Get a pointer to the scopetable array
+ scopeTable = pRegistrationFrame->scopetable;
+
+search_for_handler:
+ if ( pRegistrationFrame->trylevel != TRYLEVEL_NONE )
+ {
+ if ( pRegistrationFrame->scopetable[trylevel].lpfnFilter )
+ {
+
+ PUSH EBP // Save this frame EBP
+
+ // !!!Very Important!!! Switch to original EBP. This is
+ // what allows all locals in the frame to have the same
+ // value as before the exception occurred.
+
+ EBP = &pRegistrationFrame->_ebp
+
+ // Call the filter function
+ filterFuncRet = scopetable[trylevel].lpfnFilter();
+
+ POP EBP // Restore handler frame EBP
+
+ if ( filterFuncRet != EXCEPTION_CONTINUE_SEARCH )
+ {
+ if ( filterFuncRet < 0 ) // EXCEPTION_CONTINUE_EXECUTION
+ return ExceptionContinueExecution;
+
+ // If we get here, EXCEPTION_EXECUTE_HANDLER was specified
+ scopetable == pRegistrationFrame->scopetable
+
+ // Does the actual OS cleanup of registration frames
+ // Causes this function to recurse
+ __global_unwind2( pRegistrationFrame );
+
+
+ // Once we get here, everything is all cleaned up, except
+ // for the last frame, where we'll continue execution
+ EBP = &pRegistrationFrame->_ebp
+
+ __local_unwind2( pRegistrationFrame, trylevel );
+
+ // NLG == "non-local-goto" (setjmp/longjmp stuff)
+ __NLG_Notify( 1 ); // EAX == scopetable->lpfnHandler
+
+ // Set the current trylevel to whatever SCOPETABLE entry
+ // was being used when a handler was found
+ pRegistrationFrame->trylevel = scopetable->previousTryLevel;
+
+ // Call the _except {} block. Never returns.
+ pRegistrationFrame->scopetable[trylevel].lpfnHandler();
+ }
+ }
+
+ scopeTable = pRegistrationFrame->scopetable;
+ trylevel = scopeTable->previousTryLevel
+
+ goto search_for_handler;
+ }
+ else // trylevel == TRYLEVEL_NONE
+ {
+ retvalue == DISPOSITION_CONTINUE_SEARCH;
+ }
+ }
+ else // EXCEPTION_UNWINDING or EXCEPTION_EXIT_UNWIND flags are set
+ {
+ PUSH EBP // Save EBP
+
+ EBP = pRegistrationFrame->_ebp // Set EBP for __local_unwind2
+
+ __local_unwind2( pRegistrationFrame, TRYLEVEL_NONE )
+
+ POP EBP // Restore EBP
+
+ retvalue == DISPOSITION_CONTINUE_SEARCH;
+ }
+}
+