Release 970112
[wine.git] / win32 / except.c
blob50186ee323d0b63c9553bef936826da53dc3772e
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 "stddebug.h"
39 #include "debug.h"
40 #include "except.h"
42 LPTOP_LEVEL_EXCEPTION_FILTER pTopExcHandler = NULL;
44 void EXC_Init(void)
46 pTopExcHandler = (LPTOP_LEVEL_EXCEPTION_FILTER)GetProcAddress32(
47 GetModuleHandle("KERNEL32"),
48 "UnhandledExceptionFilter" );
52 * EXC_RtlUnwind
54 * This function is undocumented. This is the general idea of
55 * RtlUnwind, though. Note that error handling is not yet implemented
59 void EXC_RtlUnwind(PEXCEPTION_FRAME pEndFrame,LPVOID unusedEip,
60 PEXCEPTION_RECORD pRecord, DWORD returnEax,
61 PCONTEXT pcontext)
63 EXCEPTION_RECORD record;
64 DWORD dispatch;
65 int retval;
67 pcontext->Eax=returnEax;
69 /* build an exception record, if we do not have one */
70 if(!pRecord)
72 record.ExceptionCode= 0xC0000026; /* invalid disposition */
73 record.ExceptionFlags= 0;
74 record.ExceptionRecord= NULL;
75 record.ExceptionAddress=(LPVOID) pcontext->Eip;
76 record.NumberParameters= 0;
77 pRecord=&record;
80 if(pEndFrame)
81 pRecord->ExceptionFlags|=EH_UNWINDING;
82 else
83 pRecord->ExceptionFlags|=EH_UNWINDING | EH_EXIT_UNWIND;
85 /* get chain of exception frames */
86 while((TebExceptionFrame!=NULL)&&
87 (TebExceptionFrame!=((void *)-1)) &&
88 (TebExceptionFrame!=pEndFrame))
90 dprintf_win32(stddeb,"calling exception handler at 0x%x\n",
91 (int) TebExceptionFrame->Handler);
93 dispatch=0;
94 retval=TebExceptionFrame->Handler(pRecord, TebExceptionFrame,
95 pcontext, &dispatch);
97 dprintf_win32(stddeb,"exception handler returns 0x%x, dispatch=0x%x\n",
98 retval, (int) dispatch);
100 if(retval==ExceptionCollidedUnwind)
101 TebExceptionFrame=(LPVOID) dispatch;
102 else if(TebExceptionFrame!=pEndFrame)
103 TebExceptionFrame=TebExceptionFrame->Prev;
104 else
105 break;
110 * EXC_RaiseException
114 VOID EXC_RaiseException(DWORD dwExceptionCode,
115 DWORD dwExceptionFlags,
116 DWORD cArguments,
117 const LPDWORD lpArguments,
118 PCONTEXT pcontext)
120 PEXCEPTION_FRAME pframe;
121 EXCEPTION_RECORD record;
122 DWORD dispatch; /* is this used in raising exceptions ?? */
123 int retval;
124 int i;
126 /* compose an exception record */
128 record.ExceptionCode = dwExceptionCode;
129 record.ExceptionFlags = dwExceptionFlags;
130 record.ExceptionRecord = NULL;
131 record.NumberParameters = cArguments;
132 record.ExceptionAddress = (LPVOID) pcontext->Eip;
134 for(i=0;i<cArguments;i++)
135 record.ExceptionInformation[i]=lpArguments[i];
137 /* get chain of exception frames */
139 retval=ExceptionContinueSearch;
140 pframe=TebExceptionFrame;
142 while((pframe!=NULL)&&(pframe!=((void *)0xFFFFFFFF)))
144 dprintf_win32(stddeb,"calling exception handler at 0x%x\n",
145 (int) pframe->Handler);
146 dispatch=0;
147 retval=pframe->Handler(&record,pframe,pcontext,&dispatch);
149 dprintf_win32(stddeb,"exception handler returns 0x%x, dispatch=0x%x\n",
150 retval, (int) dispatch);
152 if(retval==ExceptionContinueExecution)
153 break;
154 pframe=pframe->Prev;
157 if(retval!=ExceptionContinueExecution)
159 retval=EXC_CallUnhandledExceptionFilter(&record,pcontext);
160 if(retval!=EXCEPTION_CONTINUE_EXECUTION)
162 dprintf_win32(stddeb,"no handler wanted to handle "
163 "the exception, exiting\n" );
164 ExitProcess(dwExceptionCode); /* what status should be used here ? */
169 /*******************************************************************
170 * UnhandledExceptionFilter (KERNEL32.537)
172 * This is the unhandled exception code.
173 * Actually, this should show up a dialog box, with all kinds of
174 * fancy debugging information. It does nothing now!
177 DWORD UnhandledExceptionFilter(PEXCEPTION_POINTERS epointers)
179 PEXCEPTION_RECORD pRecord;
180 PCONTEXT pContext;
182 pRecord=epointers->ExceptionRecord;
183 pContext=epointers->ContextRecord;
185 if(pRecord->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND) )
187 dprintf_win32(stddeb,"UnhandledExceptionFilter: exiting\n");
188 ExitProcess(pRecord->ExceptionCode);
190 else
192 RtlUnwind(0,pRecord,0,-1 );
196 * This is just to avoid a warning, code should not get here
197 * if it does, EXC_RaiseException will terminate it.
199 return EXCEPTION_CONTINUE_SEARCH;
202 /*************************************************************
203 * SetUnhandledExceptionFilter (KERNEL32.516)
208 LPTOP_LEVEL_EXCEPTION_FILTER
209 SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER efilter)
211 pTopExcHandler=efilter;
212 return efilter;
215 #endif /* WINELIB */