Release 970824
[wine/multimedia.git] / win32 / except.c
blob4fbcd9d1b52a251ed7e615a145d416b2d4e51c53
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.
34 #include <assert.h>
35 #include <stdio.h>
36 #include "windows.h"
37 #include "winerror.h"
38 #include "ldt.h"
39 #include "process.h"
40 #include "thread.h"
41 #include "stddebug.h"
42 #include "debug.h"
43 #include "except.h"
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,
52 PCONTEXT pcontext)
54 fprintf(stderr,"CRTDLL__local_unwind2(%p,%ld)\n",endframe,nr);
55 return;
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);
64 return;
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;
78 DWORD dispatch;
79 int retval;
81 pcontext->Eax=returnEax;
83 /* build an exception record, if we do not have one */
84 if(!pRecord)
86 record.ExceptionCode = STATUS_INVALID_DISPOSITION;
87 record.ExceptionFlags = 0;
88 record.ExceptionRecord = NULL;
89 record.ExceptionAddress = (LPVOID)pcontext->Eip;
90 record.NumberParameters = 0;
91 pRecord = &record;
94 if(pEndFrame)
95 pRecord->ExceptionFlags|=EH_UNWINDING;
96 else
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 );
107 dispatch=0;
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;
123 else
124 break;
129 /*******************************************************************
130 * RaiseException (KERNEL32.418)
132 void WINAPI RaiseException(DWORD dwExceptionCode,
133 DWORD dwExceptionFlags,
134 DWORD cArguments,
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 ?? */
141 int retval;
142 int i;
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);
164 dispatch=0;
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)
171 break;
172 pframe=pframe->Prev;
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)
189 char message[80];
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;
217 return old;