2 * Win32 exception functions
4 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
7 * What really happens behind the scenes of those new
8 * __try{...}__except(..){....} and
9 * __try{...}__finally{...}
10 * statements is simply not documented by Microsoft. There could be different
12 * One reason could be that they try to hide the fact that exception
13 * handling in Win32 looks almost the same as in OS/2 2.x.
14 * Another reason could be that Microsoft does not want others to write
15 * binary compatible implementations of the Win32 API (like us).
17 * Whatever the reason, THIS SUCKS!! Ensuring portabilty or future
18 * compatability may be valid reasons to keep some things undocumented.
19 * But exception handling is so basic to Win32 that it should be
23 * -Most functions need better parameter checking.
24 * -I do not know how to handle exceptions within an exception handler.
25 * or what is done when ExceptionNestedException is returned from an
27 * -Real exceptions are not yet implemented. only the exception functions
28 * are implemented. A real implementation needs some new code in
29 * loader/signal.c. There would also be a need for showing debugging
30 * information in UnhandledExceptionFilter.
45 #define TEB_EXCEPTION_FRAME(pcontext) \
46 ((PEXCEPTION_FRAME)((TEB *)GET_SEL_BASE((pcontext)->SegFs))->except)
48 /*******************************************************************
49 * _local_unwind2 (CRTDLL)
51 void WINAPI
CRTDLL__local_unwind2(PEXCEPTION_FRAME endframe
,DWORD nr
,
54 fprintf(stderr
,"CRTDLL__local_unwind2(%p,%ld)\n",endframe
,nr
);
58 /*******************************************************************
59 * _global_unwind2 (CRTDLL)
61 void WINAPI
CRTDLL__global_unwind2(PEXCEPTION_FRAME endframe
,PCONTEXT pcontext
)
63 RtlUnwind(endframe
,NULL
/*should point to the return;*/,NULL
,0,pcontext
);
67 /*******************************************************************
68 * RtlUnwind (KERNEL32.443)
70 * This function is undocumented. This is the general idea of
71 * RtlUnwind, though. Note that error handling is not yet implemented.
73 void WINAPI
RtlUnwind( PEXCEPTION_FRAME pEndFrame
, LPVOID unusedEip
,
74 PEXCEPTION_RECORD pRecord
, DWORD returnEax
,
75 PCONTEXT pcontext
/* Wine additional parameter */ )
77 EXCEPTION_RECORD record
;
81 pcontext
->Eax
=returnEax
;
83 /* build an exception record, if we do not have one */
86 record
.ExceptionCode
= STATUS_INVALID_DISPOSITION
;
87 record
.ExceptionFlags
= 0;
88 record
.ExceptionRecord
= NULL
;
89 record
.ExceptionAddress
= (LPVOID
)pcontext
->Eip
;
90 record
.NumberParameters
= 0;
95 pRecord
->ExceptionFlags
|=EH_UNWINDING
;
97 pRecord
->ExceptionFlags
|=EH_UNWINDING
| EH_EXIT_UNWIND
;
99 /* get chain of exception frames */
100 while ((TEB_EXCEPTION_FRAME(pcontext
) != NULL
) &&
101 (TEB_EXCEPTION_FRAME(pcontext
) != ((void *)0xffffffff)) &&
102 (TEB_EXCEPTION_FRAME(pcontext
) != pEndFrame
))
104 dprintf_win32( stddeb
, "calling exception handler at 0x%x\n",
105 (int)TEB_EXCEPTION_FRAME(pcontext
)->Handler
);
108 retval
= TEB_EXCEPTION_FRAME(pcontext
)->Handler( pRecord
,
109 TEB_EXCEPTION_FRAME(pcontext
),
110 pcontext
, &dispatch
);
112 dprintf_win32(stddeb
,"exception handler returns 0x%x, dispatch=0x%x\n",
113 retval
, (int) dispatch
);
115 if ( (retval
== ExceptionCollidedUnwind
) &&
116 (TEB_EXCEPTION_FRAME(pcontext
) != (LPVOID
)dispatch
)
118 TEB_EXCEPTION_FRAME(pcontext
) = (LPVOID
)dispatch
;
119 else if ( (TEB_EXCEPTION_FRAME(pcontext
) != pEndFrame
) &&
120 (TEB_EXCEPTION_FRAME(pcontext
) != TEB_EXCEPTION_FRAME(pcontext
)->Prev
)
122 TEB_EXCEPTION_FRAME(pcontext
) = TEB_EXCEPTION_FRAME(pcontext
)->Prev
;
129 /*******************************************************************
130 * RaiseException (KERNEL32.418)
132 void WINAPI
RaiseException(DWORD dwExceptionCode
,
133 DWORD dwExceptionFlags
,
135 const LPDWORD lpArguments
,
136 PCONTEXT pcontext
/* Wine additional parameter */ )
138 PEXCEPTION_FRAME pframe
;
139 EXCEPTION_RECORD record
;
140 DWORD dispatch
; /* is this used in raising exceptions ?? */
144 /* compose an exception record */
146 record
.ExceptionCode
= dwExceptionCode
;
147 record
.ExceptionFlags
= dwExceptionFlags
;
148 record
.ExceptionRecord
= NULL
;
149 record
.NumberParameters
= cArguments
;
150 record
.ExceptionAddress
= (LPVOID
) pcontext
->Eip
;
152 if (lpArguments
) for( i
= 0; i
< cArguments
; i
++)
153 record
.ExceptionInformation
[i
] = lpArguments
[i
];
155 /* get chain of exception frames */
157 retval
= ExceptionContinueSearch
;
158 pframe
= TEB_EXCEPTION_FRAME( pcontext
);
160 while((pframe
!=NULL
)&&(pframe
!=((void *)0xFFFFFFFF)))
162 dprintf_win32(stddeb
,"calling exception handler at 0x%x\n",
163 (int) pframe
->Handler
);
165 retval
=pframe
->Handler(&record
,pframe
,pcontext
,&dispatch
);
167 dprintf_win32(stddeb
,"exception handler returns 0x%x, dispatch=0x%x\n",
168 retval
, (int) dispatch
);
170 if(retval
==ExceptionContinueExecution
)
175 if (retval
!=ExceptionContinueExecution
)
177 /* FIXME: what should we do here? */
178 dprintf_win32(stddeb
,"no handler wanted to handle the exception, exiting\n");
179 ExitProcess(dwExceptionCode
); /* what status should be used here ? */
184 /*******************************************************************
185 * UnhandledExceptionFilter (KERNEL32.537)
187 DWORD WINAPI
UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers
)
191 /* FIXME: Should check if the process is being debugged */
193 if (pCurrentProcess
&& pCurrentProcess
->top_filter
)
195 DWORD ret
= pCurrentProcess
->top_filter( epointers
);
196 if (ret
!= EXCEPTION_CONTINUE_SEARCH
) return ret
;
199 /* FIXME: Should check the current error mode */
201 sprintf( message
, "Unhandled exception 0x%08lx at address 0x%08lx.",
202 epointers
->ExceptionRecord
->ExceptionCode
,
203 (DWORD
)epointers
->ExceptionRecord
->ExceptionAddress
);
204 MessageBox32A( 0, message
, "Error", MB_OK
| MB_ICONHAND
);
205 return EXCEPTION_EXECUTE_HANDLER
;
209 /*************************************************************
210 * SetUnhandledExceptionFilter (KERNEL32.516)
212 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
SetUnhandledExceptionFilter(
213 LPTOP_LEVEL_EXCEPTION_FILTER filter
)
215 LPTOP_LEVEL_EXCEPTION_FILTER old
= pCurrentProcess
->top_filter
;
216 pCurrentProcess
->top_filter
= filter
;