Release 960606
[wine.git] / win32 / except.c
blobe98ce4a1ccb9f5058e8e20565a6b604e71202e42
1 /*
2 * Win32 exception functions
4 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
6 * Notes:
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
11 * reasons for this:
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
20 * documented!
22 * Fixmes:
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
26 * exception handler
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.
33 #ifndef WINELIB
35 #include <stdio.h>
36 #include "windows.h"
37 #include "winerror.h"
38 #include "kernel32.h"
39 #include "stddebug.h"
40 #include "debug.h"
41 #include "except.h"
43 LPTOP_LEVEL_EXCEPTION_FILTER pTopExcHandler = NULL;
45 void EXC_Init(void)
47 pTopExcHandler = (LPTOP_LEVEL_EXCEPTION_FILTER)PE_GetProcAddress(
48 GetModuleHandle("KERNEL32"),
49 "UnhandledExceptionFilter" );
53 * EXC_RtlUnwind
55 * This function is undocumented. This is the general idea of
56 * RtlUnwind, though. Note that error handling is not yet implemented
60 void EXC_RtlUnwind(PEXCEPTION_FRAME pEndFrame,PVOID unusedEip,
61 PEXCEPTION_RECORD pRecord, DWORD returnEax,
62 PCONTEXT pcontext)
64 EXCEPTION_RECORD record;
65 DWORD dispatch;
66 int retval;
68 pcontext->Eax=returnEax;
70 /* build an exception record, if we do not have one */
71 if(!pRecord)
73 record.ExceptionCode= 0xC0000026; /* invalid disposition */
74 record.ExceptionFlags= 0;
75 record.ExceptionRecord= NULL;
76 record.ExceptionAddress=(PVOID) pcontext->Eip;
77 record.NumberParameters= 0;
78 pRecord=&record;
81 if(pEndFrame)
82 pRecord->ExceptionFlags|=EH_UNWINDING;
83 else
84 pRecord->ExceptionFlags|=EH_UNWINDING | EH_EXIT_UNWIND;
86 /* get chain of exception frames */
87 while((TebExceptionFrame!=NULL)&&
88 (TebExceptionFrame!=((void *)-1)) &&
89 (TebExceptionFrame!=pEndFrame))
91 dprintf_win32(stddeb,"calling exception handler at 0x%x\n",
92 (int) TebExceptionFrame->Handler);
94 dispatch=0;
95 retval=TebExceptionFrame->Handler(pRecord, TebExceptionFrame,
96 pcontext, &dispatch);
98 dprintf_win32(stddeb,"exception handler returns 0x%x, dispatch=0x%x\n",
99 retval, (int) dispatch);
101 if(retval==ExceptionCollidedUnwind)
102 TebExceptionFrame=(PVOID) dispatch;
103 else if(TebExceptionFrame!=pEndFrame)
104 TebExceptionFrame=TebExceptionFrame->Prev;
105 else
106 break;
111 * EXC_RaiseException
115 VOID EXC_RaiseException(DWORD dwExceptionCode,
116 DWORD dwExceptionFlags,
117 DWORD cArguments,
118 const LPDWORD lpArguments,
119 PCONTEXT pcontext)
121 PEXCEPTION_FRAME pframe;
122 EXCEPTION_RECORD record;
123 DWORD dispatch; /* is this used in raising exceptions ?? */
124 int retval;
125 int i;
127 /* compose an exception record */
129 record.ExceptionCode = dwExceptionCode;
130 record.ExceptionFlags = dwExceptionFlags;
131 record.ExceptionRecord = NULL;
132 record.NumberParameters = cArguments;
133 record.ExceptionAddress = (PVOID) pcontext->Eip;
135 for(i=0;i<cArguments;i++)
136 record.ExceptionInformation[i]=lpArguments[i];
138 /* get chain of exception frames */
140 retval=ExceptionContinueSearch;
141 pframe=TebExceptionFrame;
143 while((pframe!=NULL)&&(pframe!=((void *)0xFFFFFFFF)))
145 dprintf_win32(stddeb,"calling exception handler at 0x%x\n",
146 (int) pframe->Handler);
147 dispatch=0;
148 retval=pframe->Handler(&record,pframe,pcontext,&dispatch);
150 dprintf_win32(stddeb,"exception handler returns 0x%x, dispatch=0x%x\n",
151 retval, (int) dispatch);
153 if(retval==ExceptionContinueExecution)
154 break;
155 pframe=pframe->Prev;
158 if(retval!=ExceptionContinueExecution)
160 retval=EXC_CallUnhandledExceptionFilter(&record,pcontext);
161 if(retval!=EXCEPTION_CONTINUE_EXECUTION)
163 dprintf_win32(stddeb,"no handler wanted to handle "
164 "the exception, exiting\n" );
165 ExitProcess(dwExceptionCode); /* what status should be used here ? */
170 /*******************************************************************
171 * UnhandledExceptionFilter (KERNEL32.537)
173 * This is the unhandled exception code.
174 * Actually, this should show up a dialog box, with all kinds of
175 * fancy debugging information. It does nothing now!
178 DWORD UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
180 PEXCEPTION_RECORD pRecord;
181 PCONTEXT pContext;
183 pRecord=epointers->ExceptionRecord;
184 pContext=epointers->ContextRecord;
186 if(pRecord->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND) )
188 dprintf_win32(stddeb,"UnhandledExceptionFilter: exiting\n");
189 ExitProcess(pRecord->ExceptionCode);
191 else
193 RtlUnwind(0,pRecord,0,-1 );
197 * This is just to avoid a warning, code should not get here
198 * if it does, EXC_RaiseException will terminate it.
200 return EXCEPTION_CONTINUE_SEARCH;
203 /*************************************************************
204 * SetUnhandledExceptionFilter (KERNEL32.516)
209 LPTOP_LEVEL_EXCEPTION_FILTER
210 SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER efilter)
212 pTopExcHandler=efilter;
213 return efilter;
216 #endif /* WINELIB */