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 DECLARE_DEBUG_CHANNEL(relay
)
45 DECLARE_DEBUG_CHANNEL(win32
)
47 #define TEB_EXCEPTION_FRAME(pcontext) \
48 ((PEXCEPTION_FRAME)((TEB *)GET_SEL_BASE((pcontext)->SegFs))->except)
50 /*******************************************************************
51 * RtlUnwind (KERNEL32.443)
53 * This function is undocumented. This is the general idea of
54 * RtlUnwind, though. Note that error handling is not yet implemented.
56 * The real prototype is:
57 * void WINAPI EXC_RtlUnwind( PEXCEPTION_FRAME pEndFrame, LPVOID unusedEip,
58 * PEXCEPTION_RECORD pRecord, DWORD returnEax );
60 REGS_ENTRYPOINT(RtlUnwind
)
62 EXCEPTION_RECORD record
;
65 PEXCEPTION_FRAME pEndFrame
;
66 PEXCEPTION_RECORD pRecord
;
68 /* get the arguments from the stack */
70 DWORD ret
= STACK32_POP(context
); /* return addr */
71 pEndFrame
= (PEXCEPTION_FRAME
)STACK32_POP(context
);
72 (void)STACK32_POP(context
); /* unused arg */
73 pRecord
= (PEXCEPTION_RECORD
)STACK32_POP(context
);
74 EAX_reg(context
) = STACK32_POP(context
);
75 STACK32_PUSH(context
,ret
); /* restore return addr */
77 /* build an exception record, if we do not have one */
80 record
.ExceptionCode
= STATUS_INVALID_DISPOSITION
;
81 record
.ExceptionFlags
= 0;
82 record
.ExceptionRecord
= NULL
;
83 record
.ExceptionAddress
= (LPVOID
)EIP_reg(context
);
84 record
.NumberParameters
= 0;
89 pRecord
->ExceptionFlags
|=EH_UNWINDING
;
91 pRecord
->ExceptionFlags
|=EH_UNWINDING
| EH_EXIT_UNWIND
;
93 /* get chain of exception frames */
94 while ((TEB_EXCEPTION_FRAME(context
) != NULL
) &&
95 (TEB_EXCEPTION_FRAME(context
) != ((void *)0xffffffff)) &&
96 (TEB_EXCEPTION_FRAME(context
) != pEndFrame
))
98 TRACE(win32
, "calling exception handler at 0x%x\n",
99 (int)TEB_EXCEPTION_FRAME(context
)->Handler
);
102 retval
= TEB_EXCEPTION_FRAME(context
)->Handler( pRecord
,
103 TEB_EXCEPTION_FRAME(context
),
106 TRACE(win32
,"exception handler returns 0x%x, dispatch=0x%x\n",
107 retval
, (int) dispatch
);
109 if ( (retval
== ExceptionCollidedUnwind
) &&
110 (TEB_EXCEPTION_FRAME(context
) != (LPVOID
)dispatch
)
112 TEB_EXCEPTION_FRAME(context
) = (LPVOID
)dispatch
;
113 else if ( (TEB_EXCEPTION_FRAME(context
) != pEndFrame
) &&
114 (TEB_EXCEPTION_FRAME(context
) != TEB_EXCEPTION_FRAME(context
)->Prev
)
116 TEB_EXCEPTION_FRAME(context
) = TEB_EXCEPTION_FRAME(context
)->Prev
;
123 /*******************************************************************
124 * RaiseException (KERNEL32.418)
126 * The real prototype is:
127 * void WINAPI EXC_RaiseException(DWORD dwExceptionCode,
128 * DWORD dwExceptionFlags,
130 * const LPDWORD lpArguments );
132 REGS_ENTRYPOINT(RaiseException
)
134 PEXCEPTION_FRAME pframe
;
135 EXCEPTION_RECORD record
;
136 DWORD dispatch
; /* is this used in raising exceptions ?? */
140 /* Get the arguments from the stack */
142 DWORD ret
= STACK32_POP(context
); /* return addr */
143 DWORD dwExceptionCode
= STACK32_POP(context
);
144 DWORD dwExceptionFlags
= STACK32_POP(context
);
145 DWORD cArguments
= STACK32_POP(context
);
146 const LPDWORD lpArguments
= (LPDWORD
)STACK32_POP(context
);
147 STACK32_PUSH(context
,ret
); /* Restore the return address */
149 /* compose an exception record */
151 record
.ExceptionCode
= dwExceptionCode
;
152 record
.ExceptionFlags
= dwExceptionFlags
;
153 record
.ExceptionRecord
= NULL
;
154 record
.NumberParameters
= cArguments
;
155 record
.ExceptionAddress
= (LPVOID
)EIP_reg(context
);
157 if (lpArguments
) for( i
= 0; i
< cArguments
; i
++)
158 record
.ExceptionInformation
[i
] = lpArguments
[i
];
160 /* get chain of exception frames */
162 retval
= ExceptionContinueSearch
;
163 pframe
= TEB_EXCEPTION_FRAME( context
);
165 while((pframe
!=NULL
)&&(pframe
!=((void *)0xFFFFFFFF)))
167 PEXCEPTION_FRAME prevframe
;
168 TRACE(win32
,"calling exception handler at 0x%x\n",
169 (int) pframe
->Handler
);
171 TRACE(relay
,"(except=%p,record=%p,frame=%p,context=%p,dispatch=%p)\n",
172 pframe
->Handler
, &record
, pframe
, context
, &dispatch
);
173 prevframe
= pframe
->Prev
;
174 retval
=pframe
->Handler(&record
,pframe
,context
,&dispatch
);
176 TRACE(win32
,"exception handler returns 0x%x, dispatch=0x%x\n",
177 retval
, (int) dispatch
);
179 if(retval
==ExceptionContinueExecution
)
184 if (retval
!=ExceptionContinueExecution
)
186 /* FIXME: what should we do here? */
187 TRACE(win32
,"no handler wanted to handle the exception, exiting\n");
188 ExitProcess(dwExceptionCode
); /* what status should be used here ? */
193 /*******************************************************************
194 * UnhandledExceptionFilter (KERNEL32.537)
196 DWORD WINAPI
UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers
)
199 PDB
*pdb
= PROCESS_Current();
201 /* FIXME: Should check if the process is being debugged */
205 DWORD ret
= pdb
->top_filter( epointers
);
206 if (ret
!= EXCEPTION_CONTINUE_SEARCH
) return ret
;
209 /* FIXME: Should check the current error mode */
211 sprintf( message
, "Unhandled exception 0x%08lx at address 0x%08lx.",
212 epointers
->ExceptionRecord
->ExceptionCode
,
213 (DWORD
)epointers
->ExceptionRecord
->ExceptionAddress
);
214 MessageBoxA( 0, message
, "Error", MB_OK
| MB_ICONHAND
);
215 return EXCEPTION_EXECUTE_HANDLER
;
219 /*************************************************************
220 * SetUnhandledExceptionFilter (KERNEL32.516)
222 LPTOP_LEVEL_EXCEPTION_FILTER WINAPI
SetUnhandledExceptionFilter(
223 LPTOP_LEVEL_EXCEPTION_FILTER filter
)
225 PDB
*pdb
= PROCESS_Current();
226 LPTOP_LEVEL_EXCEPTION_FILTER old
= pdb
->top_filter
;
227 pdb
->top_filter
= filter
;