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.
42 #include "stackframe.h"
44 #define TEB_EXCEPTION_FRAME(pcontext) \
45 ((PEXCEPTION_FRAME)((TEB *)GET_SEL_BASE((pcontext)->SegFs))->except)
47 /*******************************************************************
48 * RtlUnwind (KERNEL32.443)
50 * This function is undocumented. This is the general idea of
51 * RtlUnwind, though. Note that error handling is not yet implemented.
53 * The real prototype is:
54 * void WINAPI EXC_RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip,
55 * PEXCEPTION_RECORD pRecord, DWORD returnEax );
57 REGS_ENTRYPOINT(RtlUnwind
)
59 EXCEPTION_RECORD record
;
62 PEXCEPTION_FRAME pEndFrame
;
63 PEXCEPTION_RECORD pRecord
;
65 /* get the arguments from the stack */
67 DWORD ret
= STACK32_POP(context
); /* return addr */
68 pEndFrame
= (PEXCEPTION_FRAME
)STACK32_POP(context
);
69 (void)STACK32_POP(context
); /* unused arg */
70 pRecord
= (PEXCEPTION_RECORD
)STACK32_POP(context
);
71 EAX_reg(context
) = STACK32_POP(context
);
72 STACK32_PUSH(context
,ret
); /* restore return addr */
74 /* build an exception record, if we do not have one */
77 record
.ExceptionCode
= STATUS_INVALID_DISPOSITION
;
78 record
.ExceptionFlags
= 0;
79 record
.ExceptionRecord
= NULL
;
80 record
.ExceptionAddress
= (LPVOID
)EIP_reg(context
);
81 record
.NumberParameters
= 0;
86 pRecord
->ExceptionFlags
|=EH_UNWINDING
;
88 pRecord
->ExceptionFlags
|=EH_UNWINDING
| EH_EXIT_UNWIND
;
90 /* get chain of exception frames */
91 while ((TEB_EXCEPTION_FRAME(context
) != NULL
) &&
92 (TEB_EXCEPTION_FRAME(context
) != ((void *)0xffffffff)) &&
93 (TEB_EXCEPTION_FRAME(context
) != pEndFrame
))
95 TRACE(win32
, "calling exception handler at 0x%x\n",
96 (int)TEB_EXCEPTION_FRAME(context
)->Handler
);
99 retval
= TEB_EXCEPTION_FRAME(context
)->Handler( pRecord
,
100 TEB_EXCEPTION_FRAME(context
),
103 TRACE(win32
,"exception handler returns 0x%x, dispatch=0x%x\n",
104 retval
, (int) dispatch
);
106 if ( (retval
== ExceptionCollidedUnwind
) &&
107 (TEB_EXCEPTION_FRAME(context
) != (LPVOID
)dispatch
)
109 TEB_EXCEPTION_FRAME(context
) = (LPVOID
)dispatch
;
110 else if ( (TEB_EXCEPTION_FRAME(context
) != pEndFrame
) &&
111 (TEB_EXCEPTION_FRAME(context
) != TEB_EXCEPTION_FRAME(context
)->Prev
)
113 TEB_EXCEPTION_FRAME(context
) = TEB_EXCEPTION_FRAME(context
)->Prev
;
120 /*******************************************************************
121 * RaiseException (KERNEL32.418)
123 * The real prototype is:
124 * void WINAPI EXC_RaiseException(DWORD dwExceptionCode,
125 * DWORD dwExceptionFlags,
127 * const LPDWORD lpArguments );
129 REGS_ENTRYPOINT(RaiseException
)
131 PEXCEPTION_FRAME pframe
;
132 EXCEPTION_RECORD record
;
133 DWORD dispatch
; /* is this used in raising exceptions ?? */
137 /* Get the arguments from the stack */
139 DWORD ret
= STACK32_POP(context
); /* return addr */
140 DWORD dwExceptionCode
= STACK32_POP(context
);
141 DWORD dwExceptionFlags
= STACK32_POP(context
);
142 DWORD cArguments
= STACK32_POP(context
);
143 const LPDWORD lpArguments
= (LPDWORD
)STACK32_POP(context
);
144 STACK32_PUSH(context
,ret
); /* Restore the return address */
146 /* compose an exception record */
148 record
.ExceptionCode
= dwExceptionCode
;
149 record
.ExceptionFlags
= dwExceptionFlags
;
150 record
.ExceptionRecord
= NULL
;
151 record
.NumberParameters
= cArguments
;
152 record
.ExceptionAddress
= (LPVOID
)EIP_reg(context
);
154 if (lpArguments
) for( i
= 0; i
< cArguments
; i
++)
155 record
.ExceptionInformation
[i
] = lpArguments
[i
];
157 /* get chain of exception frames */
159 retval
= ExceptionContinueSearch
;
160 pframe
= TEB_EXCEPTION_FRAME( context
);
162 while((pframe
!=NULL
)&&(pframe
!=((void *)0xFFFFFFFF)))
164 PEXCEPTION_FRAME prevframe
;
165 TRACE(win32
,"calling exception handler at 0x%x\n",
166 (int) pframe
->Handler
);
168 TRACE(relay
,"(except=%p,record=%p,frame=%p,context=%p,dispatch=%p)\n",
169 pframe
->Handler
, &record
, pframe
, context
, &dispatch
);
170 prevframe
= pframe
->Prev
;
171 retval
=pframe
->Handler(&record
,pframe
,context
,&dispatch
);
173 TRACE(win32
,"exception handler returns 0x%x, dispatch=0x%x\n",
174 retval
, (int) dispatch
);
176 if(retval
==ExceptionContinueExecution
)
181 if (retval
!=ExceptionContinueExecution
)
183 /* FIXME: what should we do here? */
184 TRACE(win32
,"no handler wanted to handle the exception, exiting\n");
185 ExitProcess(dwExceptionCode
); /* what status should be used here ? */
190 /*******************************************************************
191 * UnhandledExceptionFilter (KERNEL32.537)
193 DWORD WINAPI
UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers
)
196 PDB
*pdb
= PROCESS_Current();
198 /* FIXME: Should check if the process is being debugged */
202 DWORD ret
= pdb
->top_filter( epointers
);
203 if (ret
!= EXCEPTION_CONTINUE_SEARCH
) return ret
;
206 /* FIXME: Should check the current error mode */
208 sprintf( message
, "Unhandled exception 0x%08lx at address 0x%08lx.",
209 epointers
->ExceptionRecord
->ExceptionCode
,
210 (DWORD
)epointers
->ExceptionRecord
->ExceptionAddress
);
211 MessageBoxA( 0, message
, "Error", MB_OK
| MB_ICONHAND
);
212 return EXCEPTION_EXECUTE_HANDLER
;
216 /*************************************************************
217 * SetUnhandledExceptionFilter (KERNEL32.516)
219 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
SetUnhandledExceptionFilter(
220 LPTOP_LEVEL_EXCEPTION_FILTER filter
)
222 PDB
*pdb
= PROCESS_Current();
223 LPTOP_LEVEL_EXCEPTION_FILTER old
= pdb
->top_filter
;
224 pdb
->top_filter
= filter
;