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

eh3.c « seh « samples « mingw « winsup - cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 49a06ceab978d12fbc6068d1fbc9dd5901c7a6fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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;
	}
}