source: trunk/src/kernel32/exceptions.cpp@ 5308

Last change on this file since 5308 was 5308, checked in by sandervl, 24 years ago

removed builtin.h include + initterm update

File size: 44.3 KB
Line 
1/* $Id: exceptions.cpp,v 1.51 2001-03-13 18:45:33 sandervl Exp $ */
2
3/* WARNING: Compiling this module with ICC with optimizations turned on */
4/* currently breaks this module. To get correct code, it is not necessary */
5/* to turn all optimizations off, just use the -Op- flag. */
6
7/*
8 * Win32 Exception functions for OS/2
9 *
10 * Ported Wine exception handling code
11 *
12 * Copyright 1998 Sander van Leeuwen (OS/2 port)
13 *
14 *
15 * Project Odin Software License can be found in LICENSE.TXT
16 *
17 *
18 * (dlls\ntdll\exception.c)
19 *
20 * Copyright 1999 Turchanov Sergey
21 * Copyright 1999 Alexandre Julliard
22 *
23 * (win32\except.c)
24 *
25 * Win32 exception functions
26 *
27 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
28 *
29 * Notes:
30 * What really happens behind the scenes of those new
31 * __try{...}__except(..){....} and
32 * __try{...}__finally{...}
33 * statements is simply not documented by Microsoft. There could be different
34 * reasons for this:
35 * One reason could be that they try to hide the fact that exception
36 * handling in Win32 looks almost the same as in OS/2 2.x.
37 * Another reason could be that Microsoft does not want others to write
38 * binary compatible implementations of the Win32 API (like us).
39 *
40 * Whatever the reason, THIS SUCKS!! Ensuring portabilty or future
41 * compatability may be valid reasons to keep some things undocumented.
42 * But exception handling is so basic to Win32 that it should be
43 * documented!
44 *
45 * Fixmes:
46 * -Most functions need better parameter checking.
47 * -I do not know how to handle exceptions within an exception handler.
48 * or what is done when ExceptionNestedException is returned from an
49 * exception handler
50 * -Real exceptions are not yet implemented. only the exception functions
51 * are implemented. A real implementation needs some new code in
52 * loader/signal.c. There would also be a need for showing debugging
53 * information in UnhandledExceptionFilter.
54 *
55 */
56#define INCL_MISC
57#define INCL_BASE
58#define INCL_WINBUTTONS
59#include <os2wrap.h> //Odin32 OS/2 api wrappers
60#include <stdio.h>
61#include <stdlib.h>
62#include <assert.h>
63#include <string.h>
64#include "exceptions.h"
65#include "exceptutil.h"
66#include <misc.h>
67#include "mmap.h"
68#include <wprocess.h>
69#include "oslibexcept.h"
70#include "exceptstackdump.h"
71
72#define DBG_LOCALLOG DBG_exceptions
73#include "dbglocal.h"
74
75/* Exception record for handling exceptions happening inside exception handlers */
76typedef struct
77{
78 WINEXCEPTION_FRAME frame;
79 WINEXCEPTION_FRAME *prevFrame;
80} EXC_NESTED_FRAME;
81
82//Global Process Unhandled exception filter
83static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL;
84static UINT CurrentErrorMode = SEM_FAILCRITICALERRORS;
85static PEXCEPTION_HANDLER StartupCodeHandler = NULL;
86
87extern "C" PWINEXCEPTION_FRAME GetExceptionRecord(ULONG offset, ULONG segment);
88
89LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo);
90void KillWin32Process(void);
91
92#ifdef DEBUG
93void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe);
94#else
95#define PrintWin32ExceptionChain(a)
96#endif
97
98/*****************************************************************************
99 * Name : UINT SetErrorMode
100 * Purpose :
101 * Parameters: UINT fuErrorMode
102 * Variables :
103 * Result :
104 * Remark :
105 * Status :
106 *
107 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
108 *****************************************************************************/
109
110UINT WIN32API SetErrorMode(UINT fuErrorMode)
111{
112 UINT oldmode = CurrentErrorMode;
113
114 dprintf(("KERNEL32: SetErrorMode(%08xh)\n",
115 fuErrorMode));
116 CurrentErrorMode = fuErrorMode;
117
118 if(fuErrorMode & SEM_FAILCRITICALERRORS || fuErrorMode & SEM_NOOPENFILEERRORBOX)
119 DosError(FERR_DISABLEHARDERR);
120 else
121 DosError(FERR_ENABLEHARDERR);
122
123 // SEM_NOGPFAULTERRORBOX and SEM_NOALIGNMENTFAULTEXCEPT --> UnhandledExceptionFilter()
124
125 return(oldmode);
126}
127
128static inline WINEXCEPTION_FRAME * EXC_push_frame( WINEXCEPTION_FRAME *frame )
129{
130 // TODO: rewrite in assembly
131 TEB *teb = GetThreadTEB();
132 frame->Prev = (PWINEXCEPTION_FRAME)teb->except;
133 teb->except = frame;
134 return frame->Prev;
135}
136
137static inline WINEXCEPTION_FRAME * EXC_pop_frame( WINEXCEPTION_FRAME *frame )
138{
139 // TODO: rewrite in assembly
140 TEB *teb = GetThreadTEB();
141 teb->except = frame->Prev;
142 return frame->Prev;
143}
144
145/*****************************************************************************
146 * Name : VOID _Pascal OS2RaiseException
147 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
148 * Parameters: ...
149 * Variables :
150 * Result :
151 * Remark :
152 * Status :
153 *
154 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
155 *****************************************************************************/
156
157void WIN32API RtlRaiseException(WINEXCEPTION_RECORD *rec, WINCONTEXT *context);
158
159VOID _Pascal OS2RaiseException(DWORD dwExceptionCode,
160 DWORD dwExceptionFlags,
161 DWORD cArguments,
162 DWORD *lpArguments,
163 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
164 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
165 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
166 DWORD es, DWORD fs, DWORD gs, DWORD ss)
167{
168 WINEXCEPTION_RECORD record;
169 WINEXCEPTION_POINTERS ExceptionInfo;
170 WINCONTEXT context;
171 int rc;
172 int i;
173
174 dprintf(("KERNEL32: RaiseException(%08xh)\n",
175 dwExceptionCode));
176
177 memset(&record, 0, sizeof(record));
178
179 /* compose an exception record */
180 record.ExceptionCode = dwExceptionCode;
181 record.ExceptionFlags = dwExceptionFlags;
182 record.ExceptionRecord = NULL;
183 record.NumberParameters = cArguments;
184 record.ExceptionAddress = (LPVOID)eip;
185
186 memset(&context, 0, sizeof(context));
187 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
188 context.SegGs = gs;
189 context.SegFs = fs;
190 context.SegEs = es;
191 context.SegDs = ds;
192 context.Edi = edi;
193 context.Esi = esi;
194 context.Ebx = ebx;
195 context.Edx = edx;
196 context.Ecx = ecx;
197 context.Eax = eax;
198 context.Ebp = ebp;
199 context.Eip = eip;
200 context.SegCs = cs;
201 context.EFlags = flags;
202 context.Esp = esp;
203 context.SegSs = ss;
204
205 if(lpArguments)
206 {
207 for(i=0;
208 i<cArguments;
209 i++)
210 record.ExceptionInformation[i] = lpArguments[i];
211 }
212
213 rc = RtlDispatchException(&record, &context);
214
215 // and finally, the unhandled exception filter
216 if(rc == ExceptionContinueSearch && UnhandledExceptionFilter != NULL)
217 {
218 dprintf(("KERNEL32: RaiseException calling UnhandledExceptionFilter.\n"));
219
220 ExceptionInfo.ExceptionRecord = &record;
221 ExceptionInfo.ContextRecord = &context;
222
223 rc = UnhandledExceptionFilter(&ExceptionInfo);
224 //FIXME: UnhandledExceptionFilter does NOT return the same values as
225 // other filters!!
226 }
227
228 // terminate the process
229 if(rc != ExceptionContinueExecution ||
230 record.ExceptionFlags & EH_NONCONTINUABLE)
231 {
232 dprintf(("KERNEL32: RaiseException terminating process.\n"));
233 DosExit(EXIT_PROCESS, 0);
234 }
235
236 dprintf(("KERNEL32: RaiseException returns.\n"));
237 return;
238}
239
240/*******************************************************************
241 * EXC_RaiseHandler
242 *
243 * Handler for exceptions happening inside a handler.
244 */
245static DWORD WIN32API EXC_RaiseHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
246// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
247 WINCONTEXT *context, LPVOID dispatcher )
248{
249 if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
250 return ExceptionContinueSearch;
251 /* We shouldn't get here so we store faulty frame in dispatcher */
252 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
253 return ExceptionNestedException;
254}
255
256/*******************************************************************
257 * EXC_UnwindHandler
258 *
259 * Handler for exceptions happening inside an unwind handler.
260 */
261static DWORD WIN32API EXC_UnwindHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
262// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
263 WINCONTEXT *context, LPVOID dispatcher )
264{
265 if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
266 return ExceptionContinueSearch;
267 /* We shouldn't get here so we store faulty frame in dispatcher */
268 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
269 return ExceptionCollidedUnwind;
270}
271
272/*******************************************************************
273 * EXC_CallHandler
274 *
275 * Call an exception handler, setting up an exception frame to catch exceptions
276 * happening during the handler execution.
277 * WARNING:
278 * Please do not change the first 4 parameters order in any way - some exceptions handlers
279 * rely on Base Pointer (EBP) to have a fixed position related to the exception frame
280 */
281static DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
282 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
283 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler)
284{
285 EXC_NESTED_FRAME newframe;
286 DWORD ret;
287
288 newframe.frame.Handler = nested_handler;
289 newframe.prevFrame = frame;
290 EXC_push_frame( &newframe.frame );
291 dprintf(("KERNEL32: Calling handler at %p code=%lx flags=%lx\n",
292 handler, record->ExceptionCode, record->ExceptionFlags));
293 ret = handler( record, frame, context, dispatcher );
294 dprintf(("KERNEL32: Handler returned %lx\n", ret));
295 EXC_pop_frame( &newframe.frame );
296 return ret;
297}
298
299//******************************************************************************
300//******************************************************************************
301DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext)
302{
303 PWINEXCEPTION_FRAME pFrame, dispatch, nested_frame;
304 int rc;
305
306 // get chain of exception frames
307 rc = ExceptionContinueSearch;
308
309 nested_frame = NULL;
310 TEB *winteb = GetThreadTEB();
311 pFrame = (PWINEXCEPTION_FRAME)winteb->except;
312
313 dprintf(("KERNEL32: RtlDispatchException entered"));
314
315 PrintWin32ExceptionChain(pFrame);
316
317 // walk the exception chain
318 while( (pFrame != NULL) && (pFrame != ((void *)0xFFFFFFFF)) )
319 {
320 dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", pFrame, pFrame->Prev));
321 if (pFrame == pFrame->Prev) {
322 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
323 return 0;
324 }
325
326 dispatch=0;
327
328 /* Check frame address */
329 if (((void*)pFrame < winteb->stack_low) ||
330 ((void*)(pFrame+1) > winteb->stack_top) ||
331 (int)pFrame & 3)
332 {
333 dprintf(("Invalid stack! low=%08X, top=%08X, pframe = %08X",
334 winteb->stack_low, winteb->stack_top, pFrame));
335
336 pRecord->ExceptionFlags |= EH_STACK_INVALID;
337 break;
338 }
339
340
341 /* call handler */
342 rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch, pFrame->Handler, EXC_RaiseHandler );
343
344 PrintWin32ExceptionChain(pFrame);
345
346 if (pFrame == nested_frame)
347 {
348 /* no longer nested */
349 nested_frame = NULL;
350 pRecord->ExceptionFlags &= ~EH_NESTED_CALL;
351 }
352
353
354 switch(rc)
355 {
356 case ExceptionContinueExecution:
357 if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE)) {
358 dprintf(("KERNEL32: RtlDispatchException returns %#x (ContinueExecution)", rc));
359 return rc;
360 }
361 break;
362 case ExceptionContinueSearch:
363 break;
364 case ExceptionNestedException:
365 if (nested_frame < dispatch) nested_frame = dispatch;
366 pRecord->ExceptionFlags |= EH_NESTED_CALL;
367 break;
368 default:
369 break;
370 }
371
372 dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", pFrame, pFrame->Prev));
373 if (pFrame == pFrame->Prev) {
374 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
375 break;
376 }
377 pFrame = pFrame->Prev;
378 }
379 dprintf(("KERNEL32: RtlDispatchException returns %#x", rc));
380 PrintWin32ExceptionChain(pFrame);
381 return rc;
382}
383/*****************************************************************************
384 * Name : int _Pascal OS2RtlUnwind
385 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
386 * Parameters: ...
387 * Variables :
388 * Result :
389 * Remark :
390 * Status :
391 *
392 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
393 *****************************************************************************/
394
395int _Pascal OS2RtlUnwind(PWINEXCEPTION_FRAME pEndFrame,
396 LPVOID unusedEip,
397 PWINEXCEPTION_RECORD pRecord,
398 DWORD returnEax,
399 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
400 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
401 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
402 DWORD es, DWORD fs, DWORD gs, DWORD ss)
403{
404 PWINEXCEPTION_FRAME frame, dispatch;
405 WINEXCEPTION_RECORD record, newrec;
406 WINCONTEXT context;
407 DWORD rc;
408
409 dprintf(("KERNEL32: RtlUnwind pEndFrame=%08X, unusedEip=%08X, pRecord=%08X, returnEax=%#x\n", pEndFrame, unusedEip, pRecord, returnEax));
410
411
412 memset(&context, 0, sizeof(context));
413 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
414 context.SegGs = gs;
415 context.SegFs = fs;
416 context.SegEs = es;
417 context.SegDs = ds;
418 context.Edi = edi;
419 context.Esi = esi;
420 context.Ebx = ebx;
421 context.Edx = edx;
422 context.Ecx = ecx;
423 context.Eax = returnEax;
424 context.Ebp = ebp;
425 context.Eip = eip;
426 context.SegCs = cs;
427 context.EFlags = flags;
428 context.Esp = esp;
429 context.SegSs = ss;
430
431 /* build an exception record, if we do not have one */
432 if(!pRecord)
433 {
434 memset(&record, 0, sizeof(record));
435 record.ExceptionCode = STATUS_UNWIND;
436 record.ExceptionFlags = 0;
437 record.ExceptionRecord = NULL;
438 record.ExceptionAddress = (LPVOID)eip;
439 record.NumberParameters = 0;
440 pRecord = &record;
441 }
442
443 if(pEndFrame) pRecord->ExceptionFlags |= EH_UNWINDING;
444 else pRecord->ExceptionFlags |= EH_UNWINDING | EH_EXIT_UNWIND;
445
446 /* get chain of exception frames */
447 TEB *winteb = GetThreadTEB();
448 frame = (PWINEXCEPTION_FRAME)winteb->except;
449
450 PrintWin32ExceptionChain(frame);
451
452 while ((frame != (PWINEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame))
453 {
454 /* Check frame address */
455 if (pEndFrame && (frame > pEndFrame))
456 {
457 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
458 newrec.ExceptionFlags = EH_NONCONTINUABLE;
459 newrec.ExceptionRecord = pRecord;
460 newrec.NumberParameters = 0;
461 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
462 DosExit(EXIT_THREAD, 0);
463 }
464 if (((void*)frame < winteb->stack_low) ||
465 ((void*)(frame+1) > winteb->stack_top) ||
466 (int)frame & 3)
467 {
468 newrec.ExceptionCode = STATUS_BAD_STACK;
469 newrec.ExceptionFlags = EH_NONCONTINUABLE;
470 newrec.ExceptionRecord = pRecord;
471 newrec.NumberParameters = 0;
472 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
473 DosExit(EXIT_THREAD, 0);
474 }
475
476 /* Call handler */
477 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler));
478 rc = EXC_CallHandler(pRecord, frame, &context, &dispatch, frame->Handler, EXC_UnwindHandler );
479 dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc));
480 switch (rc)
481 {
482 case ExceptionContinueSearch:
483 break;
484 case ExceptionCollidedUnwind:
485 frame = dispatch;
486 break;
487 default:
488 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;
489 newrec.ExceptionFlags = EH_NONCONTINUABLE;
490 newrec.ExceptionRecord = pRecord;
491 newrec.NumberParameters = 0;
492 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
493 DosExit(EXIT_THREAD, 0);
494 break;
495 }
496 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, frame->Prev));
497 SetExceptionChain((DWORD)frame->Prev);
498 frame = frame->Prev;
499 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame, frame->Prev));
500 }
501
502 dprintf(("KERNEL32: RtlUnwind returning.\n"));
503 PrintWin32ExceptionChain(frame);
504 return(0);
505}
506
507
508/*****************************************************************************
509 * Name : LONG WIN32API UnhandledExceptionFilter
510 * Purpose :
511 * Parameters: ...
512 * Variables :
513 * Result :
514 * Remark :
515 * Status :
516 *
517 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
518 *****************************************************************************/
519
520LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo)
521{
522 char message[72];
523 DWORD rc;
524
525 // @@@PH: experimental change to have more control over exception handling
526#pragma pack(4)
527 typedef struct
528 {
529 ULONG cb; /* Size of fixed part of structure */
530 HPOINTER hIcon; /* Icon handle */
531 ULONG cButtons; /* Number of buttons */
532 ULONG flStyle; /* Icon style flags (MB_ICONQUESTION, etc...)*/
533 HWND hwndNotify; /* Reserved */
534 MB2D mb2d[4]; /* Array of button definitions */
535 } myMB2INFO;
536#pragma pack()
537
538 myMB2INFO mb2InfoExceptionBox = { 20, // size of structure
539 NULLHANDLE, // icon handle
540 4, // number of buttons
541 MB_ICONHAND, // icon style
542 NULLHANDLE, // reserved
543 { {"continue ~search", 100, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE},
544 {"continue ~execution", 101, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE},
545 {"execute ~handler", 102, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE | BS_DEFAULT},
546 {"~terminate process", 103, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE} }
547 };
548
549 dprintf(("KERNEL32: Default UnhandledExceptionFilter, CurrentErrorMode=%X", CurrentErrorMode));
550
551 // We must not care about ErrorMode here!! The app expects that its own
552 // UnhandledExceptionFilter will be cared even if it never touched ErrorMode.
553 if(CurrentUnhExceptionFlt) // && !(CurrentErrorMode & (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)))
554 {
555 dprintf(("KERNEL32: Calling user UnhandledExceptionFilter"));
556 rc = CurrentUnhExceptionFlt(lpexpExceptionInfo);
557 if(rc != WINEXCEPTION_CONTINUE_SEARCH)
558 return rc;
559 }
560
561 sprintf(message,
562 "Unhandled exception 0x%08lx at address 0x%08lx.",
563 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
564 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
565/*
566 rc = WinMessageBox2(HWND_DESKTOP,
567 HWND_DESKTOP,
568 message,
569 "Oh, nooo!",
570 0,
571 (PMB2INFO)&mb2InfoExceptionBox);
572 switch (rc)
573 {
574 case 100:
575 return WINEXCEPTION_CONTINUE_SEARCH;
576
577 case 101:
578 return WINEXCEPTION_CONTINUE_EXECUTION;
579
580 case 102:
581 return WINEXCEPTION_EXECUTE_HANDLER;
582
583 case 103:
584 KillWin32Process();
585 // fall-through
586
587 default:
588 return WINEXCEPTION_EXECUTE_HANDLER;
589 }
590*/
591 rc = WinMessageBox(HWND_DESKTOP,
592 HWND_DESKTOP,
593 message,
594 "Oh, nooo!",
595 0,
596 MB_ABORTRETRYIGNORE | MB_ERROR);
597 switch (rc)
598 {
599 case MBID_IGNORE:
600 return WINEXCEPTION_CONTINUE_EXECUTION;
601
602 case MBID_ABORT:
603 KillWin32Process();
604 // fall-through
605
606 case MBID_RETRY:
607 default:
608 return WINEXCEPTION_EXECUTE_HANDLER;
609 }
610}
611
612
613/*****************************************************************************
614 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
615 * Purpose :
616 * Parameters: ...
617 * Variables :
618 * Result :
619 * Remark :
620 * Status :
621 *
622 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
623 *****************************************************************************/
624
625LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
626{
627 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
628
629 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n",
630 lpTopLevelExceptionFilter));
631
632 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
633
634 return(old);
635}
636
637
638/*****************************************************************************
639 * Name : KillWin32Process
640 * Purpose :
641 * Parameters: ...
642 * Variables :
643 * Result :
644 * Remark :
645 * Status :
646 *
647 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
648 *****************************************************************************/
649
650
651//******************************************************************************
652extern "C" ULONG getEAX();
653extern "C" ULONG getEBX();
654VOID WIN32API ExitProcess(DWORD exitcode);
655//******************************************************************************
656void KillWin32Process(void)
657{
658 static BOOL fEntry = FALSE;
659
660 if(fEntry == FALSE) {
661 fEntry = TRUE;
662 ExitProcess(666);
663 return;
664 }
665 //Restore original OS/2 TIB selector
666 RestoreOS2FS();
667
668 SetExceptionChain((ULONG)-1);
669 DosExit(EXIT_PROCESS, 666);
670}
671
672
673/*****************************************************************************
674 * Name : void static dprintfException
675 * Purpose : log the exception to win32os2.log
676 * Parameters: ...
677 * Variables :
678 * Result :
679 * Remark :
680 * Status :
681 *
682 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
683 *****************************************************************************/
684
685static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
686 PEXCEPTIONREGISTRATIONRECORD pERegRec,
687 PCONTEXTRECORD pCtxRec,
688 PVOID p)
689{
690 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
691 char szData[128]; /* local storage for excpt dep. information */
692 char szData2[128]; /* local storage for excpt dep. information */
693 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
694 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
695 BOOL fExcptFatal = TRUE; /* fatal exception ? */
696 BOOL fExcptPortable = TRUE; /* portability of exception */
697 PPIB pPIB; /* process information block */
698 PTIB pTIB; /* thread information block */
699 ULONG ulModule; /* module number */
700 ULONG ulObject; /* object number within the module */
701 CHAR szModule[260]; /* buffer for the module name */
702 ULONG ulOffset; /* offset within the object within the module */
703
704 szData[0] = 0; /* initialize */
705 szData2[0] = 0; /* initialize */
706 switch(pERepRec->ExceptionNum) /* take according action */
707 {
708 /* portable, non-fatal software-generated exceptions */
709 case XCPT_GUARD_PAGE_VIOLATION:
710 pszExceptionName = "Guard Page Violation";
711 sprintf(szData,
712 "R/W %08xh at %08xh.",
713 pERepRec->ExceptionInfo[0],
714 pERepRec->ExceptionInfo[1]);
715 fExcptSoftware = TRUE;
716 fExcptFatal = FALSE;
717 rc = XCPT_CONTINUE_EXECUTION;
718 break;
719
720 case XCPT_UNABLE_TO_GROW_STACK:
721 pszExceptionName = "Unable To Grow Stack";
722 fExcptSoftware = TRUE;
723 fExcptFatal = FALSE;
724 rc = XCPT_CONTINUE_EXECUTION;
725 break;
726
727 /* portable, fatal, hardware-generated exceptions */
728 case XCPT_ACCESS_VIOLATION:
729 pszExceptionName = "Access Violation";
730 /* sprintf (szData, "Access type %08x at %08x.", pERepRec->ExceptionInfo[0],
731 pERepRec->ExceptionInfo[1]); */
732 switch (pERepRec->ExceptionInfo[0])
733 {
734 case XCPT_READ_ACCESS:
735 sprintf (szData,
736 "Read Access at address %08xh",
737 pERepRec->ExceptionInfo[1]);
738 break;
739
740 case XCPT_WRITE_ACCESS:
741 sprintf (szData,
742 "Write Access at address %08x",
743 pERepRec->ExceptionInfo[1]);
744 break;
745
746 case XCPT_SPACE_ACCESS:
747 sprintf (szData,
748 "Space Access at selector %08x",
749 pERepRec->ExceptionInfo[1]);
750 break;
751
752 case XCPT_LIMIT_ACCESS:
753 strcpy (szData,
754 "Limit Access");
755 break;
756
757 case XCPT_UNKNOWN_ACCESS:
758 strcpy (szData,
759 "Unknown Access");
760 break;
761
762 default:
763 strcpy (szData,
764 "(Invalid Access Code)");
765 break;
766 }
767 break;
768
769 case XCPT_INTEGER_DIVIDE_BY_ZERO:
770 pszExceptionName = "Division By Zero (Integer)";
771 break;
772
773 case XCPT_FLOAT_DIVIDE_BY_ZERO:
774 pszExceptionName = "Division By Zero (Float)";
775 break;
776
777 case XCPT_FLOAT_INVALID_OPERATION:
778 pszExceptionName = "Invalid Floating Point Operation";
779 break;
780
781 case XCPT_ILLEGAL_INSTRUCTION:
782 pszExceptionName = "Illegal Instruction";
783 break;
784
785 case XCPT_PRIVILEGED_INSTRUCTION:
786 pszExceptionName = "Privileged Instruction";
787 break;
788
789 case XCPT_INTEGER_OVERFLOW:
790 pszExceptionName = "Integer Overflow";
791 break;
792
793 case XCPT_FLOAT_OVERFLOW:
794 pszExceptionName = "Floating Point Overflow";
795 break;
796
797 case XCPT_FLOAT_UNDERFLOW:
798 pszExceptionName = "Floating Point Underflow";
799 break;
800
801 case XCPT_FLOAT_DENORMAL_OPERAND:
802 pszExceptionName = "Floating Point Denormal Operand";
803 break;
804
805 case XCPT_FLOAT_INEXACT_RESULT:
806 pszExceptionName = "Floating Point Inexact Result";
807 break;
808
809 case XCPT_FLOAT_STACK_CHECK:
810 pszExceptionName = "Floating Point Stack Check";
811 break;
812
813 case XCPT_DATATYPE_MISALIGNMENT:
814 pszExceptionName = "Datatype Misalignment";
815 sprintf(szData,
816 "R/W %08x alignment %08x at %08x.",
817 pERepRec->ExceptionInfo[0],
818 pERepRec->ExceptionInfo[1],
819 pERepRec->ExceptionInfo[2]);
820 break;
821
822 case XCPT_BREAKPOINT:
823 pszExceptionName = "Breakpoint (don't debug me! :)";
824 break;
825
826 case XCPT_SINGLE_STEP:
827 pszExceptionName = "Single Step (don't debug me! :)";
828 break;
829
830 /* portable, fatal, software-generated exceptions */
831 case XCPT_IN_PAGE_ERROR:
832 pszExceptionName = "In Page Error";
833 sprintf(szData,
834 "at %08x.",
835 pERepRec->ExceptionInfo[0]);
836 fExcptSoftware = TRUE;
837 break;
838
839 case XCPT_PROCESS_TERMINATE:
840 pszExceptionName = "Process Termination";
841 fExcptSoftware = TRUE;
842 break;
843
844 case XCPT_ASYNC_PROCESS_TERMINATE:
845 pszExceptionName = "Process Termination (async)";
846 sprintf(szData,
847 "terminating thread TID=%u",
848 pERepRec->ExceptionInfo[0]);
849 fExcptSoftware = TRUE;
850 break;
851
852 case XCPT_NONCONTINUABLE_EXCEPTION:
853 pszExceptionName = "Noncontinuable Exception";
854 fExcptSoftware = TRUE;
855 break;
856
857 case XCPT_INVALID_DISPOSITION:
858 pszExceptionName = "Invalid Disposition";
859 fExcptSoftware = TRUE;
860 break;
861
862 /* non-portable, fatal exceptions */
863 case XCPT_INVALID_LOCK_SEQUENCE:
864 pszExceptionName = "Invalid Lock Sequence";
865 fExcptSoftware = TRUE;
866 fExcptPortable = FALSE;
867 break;
868
869 case XCPT_ARRAY_BOUNDS_EXCEEDED:
870 pszExceptionName = "Array Bounds Exceeded";
871 fExcptSoftware = TRUE;
872 fExcptPortable = FALSE;
873 break;
874
875 /* unwind operation exceptions */
876 case XCPT_UNWIND:
877 pszExceptionName = "Unwind Exception";
878 fExcptSoftware = TRUE;
879 fExcptPortable = FALSE;
880 break;
881
882 case XCPT_BAD_STACK:
883 pszExceptionName = "Unwind Exception, Bad Stack";
884 fExcptSoftware = TRUE;
885 fExcptPortable = FALSE;
886 break;
887
888 case XCPT_INVALID_UNWIND_TARGET:
889 pszExceptionName = "Unwind Exception, Invalid Target";
890 fExcptSoftware = TRUE;
891 fExcptPortable = FALSE;
892 break;
893
894 /* fatal signal exceptions */
895 case XCPT_SIGNAL:
896 pszExceptionName = "Signal";
897 sprintf(szData,
898 "Signal Number = %08x",
899 pERepRec->ExceptionInfo[0]);
900 fExcptSoftware = TRUE;
901 fExcptPortable = FALSE;
902
903 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
904 {
905 case XCPT_SIGNAL_INTR:
906 pszExceptionName = "Signal (Interrupt)";
907 break;
908
909 case XCPT_SIGNAL_KILLPROC:
910 pszExceptionName = "Signal (Kill Process)";
911 break;
912
913 case XCPT_SIGNAL_BREAK:
914 pszExceptionName = "Signal (Break)";
915 break;
916 }
917 break;
918
919 default:
920 pszExceptionName = "(unknown exception code)";
921 sprintf(szData,
922 "Exception Code = %08x",
923 pERepRec->ExceptionNum);
924 }
925
926
927 /* now dump the information to the logfile */
928 dprintf(("---[Exception Information]------------\n"));
929 sprintf(szData2,
930 " %s (",
931 pszExceptionName);
932
933 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
934 strcat (szData2, "software generated,");
935 else
936 strcat (szData2, "hardware generated,");
937
938 if (fExcptPortable == TRUE) /* portable exception ? */
939 strcat (szData2, "portable,");
940 else
941 strcat (szData2, "non-portable,");
942
943 if (fExcptFatal == TRUE) /* fatal exception ? */
944 strcat (szData2, "fatal");
945 else
946 strcat (szData2, "non-fatal");
947
948 strcat (szData2, /* add trailing brace */
949 ")\n");
950
951
952 dprintf((szData2));
953
954 if (szData[0] != 0) /* see if there is an additional entry */
955 dprintf((" %s\n",
956 szData));
957
958 rc = DosQueryModFromEIP(&ulModule,
959 &ulObject,
960 sizeof(szModule),
961 szModule,
962 &ulOffset,
963 (ULONG)pERepRec->ExceptionAddress);
964
965 dprintf((" Exception Address = %08x ",
966 pERepRec->ExceptionAddress));
967
968 if(rc == NO_ERROR && ulObject != -1)
969 dprintf(("<%s> (#%u), obj #%u:%08x\n",
970 szModule,
971 ulModule,
972 ulObject,
973 ulOffset));
974 else
975 dprintf(("<win32 app>\n"));
976
977
978 rc = DosGetInfoBlocks (&pTIB, /* query kernel information blocks */
979 &pPIB);
980 if (rc == NO_ERROR)
981 {
982 dprintf((" Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
983 pTIB->tib_ordinal,
984 pTIB->tib_ptib2->tib2_ultid,
985 pTIB->tib_ptib2->tib2_ulpri));
986
987 dprintf((" Process: PID: %u, Parent: %u, Status: %u\n",
988 pPIB->pib_ulpid,
989 pPIB->pib_ulppid,
990 pPIB->pib_flstatus));
991 }
992
993 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
994 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n",
995 pCtxRec->ctx_SegSs,
996 pCtxRec->ctx_RegEsp,
997 pCtxRec->ctx_EFlags));
998 dprintf((" CS:EIP=%04x:%08x EBP =%08x\n",
999 pCtxRec->ctx_SegCs,
1000 pCtxRec->ctx_RegEip,
1001 pCtxRec->ctx_RegEbp));
1002
1003 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
1004 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n",
1005 pCtxRec->ctx_RegEax,
1006 pCtxRec->ctx_RegEbx,
1007 pCtxRec->ctx_RegEsi));
1008 dprintf((" ECX=%08x EDX=%08x EDI=%08x\n",
1009 pCtxRec->ctx_RegEcx,
1010 pCtxRec->ctx_RegEdx,
1011 pCtxRec->ctx_RegEdi));
1012
1013 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
1014 dprintf((" DS=%04x ES=%08x",
1015 pCtxRec->ctx_SegDs,
1016 pCtxRec->ctx_SegEs));
1017 dprintf((" FS=%04x GS=%04x\n",
1018 pCtxRec->ctx_SegFs,
1019 pCtxRec->ctx_SegGs));
1020
1021 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1022 {
1023 ULONG ulCounter; /* temporary local counter for fp stack */
1024
1025 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1026 pCtxRec->ctx_env[0],
1027 pCtxRec->ctx_env[1],
1028 pCtxRec->ctx_env[2],
1029 pCtxRec->ctx_env[3]));
1030
1031 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1032 pCtxRec->ctx_env[4],
1033 pCtxRec->ctx_env[5],
1034 pCtxRec->ctx_env[6]));
1035
1036 for (ulCounter = 0;
1037 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1038 ulCounter ++)
1039 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1040 ulCounter,
1041 pCtxRec->ctx_stack[0].losig,
1042 pCtxRec->ctx_stack[0].hisig,
1043 pCtxRec->ctx_stack[0].signexp));
1044 }
1045
1046 dprintf(("---[End Of Exception Information]-----\n"));
1047}
1048
1049/*****************************************************************************
1050 * Name : ERR _System OS2ExceptionHandler
1051 * Purpose :
1052 * Parameters: ...
1053 * Variables :
1054 * Result :
1055 * Remark :
1056 * Status :
1057 *
1058 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1059 *****************************************************************************/
1060 /* from PPC DDK */
1061#ifndef XCPT_CONTINUE_STOP
1062#define XCPT_CONTINUE_STOP 0x00716668
1063#endif
1064
1065ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1066 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1067 PCONTEXTRECORD pCtxRec,
1068 PVOID p)
1069{
1070 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1071 // next dprintf won't wait forever
1072 LogException(ENTER_EXCEPTION);
1073
1074 /* Access violation at a known location */
1075 switch(pERepRec->ExceptionNum)
1076 {
1077 case XCPT_FLOAT_DENORMAL_OPERAND:
1078 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1079 case XCPT_FLOAT_INEXACT_RESULT:
1080// case XCPT_FLOAT_INVALID_OPERATION:
1081 case XCPT_FLOAT_OVERFLOW:
1082 case XCPT_FLOAT_STACK_CHECK:
1083 case XCPT_FLOAT_UNDERFLOW:
1084 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1085 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1086 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1087 {
1088 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1089 {
1090 pCtxRec->ctx_env[0] |= 0x1F;
1091 pCtxRec->ctx_stack[0].losig = 0;
1092 pCtxRec->ctx_stack[0].hisig = 0;
1093 pCtxRec->ctx_stack[0].signexp = 0;
1094 }
1095 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1096 goto continueexecution;
1097 }
1098 else
1099 {
1100 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1101 goto continuesearch;
1102 }
1103
1104 case XCPT_PROCESS_TERMINATE:
1105 case XCPT_ASYNC_PROCESS_TERMINATE:
1106 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1107 SetExceptionChain((ULONG)-1);
1108 goto continuesearch;
1109
1110 case XCPT_ACCESS_VIOLATION:
1111 {
1112 Win32MemMap *map;
1113 BOOL fWriteAccess = FALSE;
1114 ULONG offset, accessflag;
1115
1116 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1117 goto continueFail;
1118 }
1119//------------->>> WARNING: potentially dangerous workaround!!
1120 /* Some apps set ES = FS and Odin doesn't like that! */
1121 /* Note: maybe we could even check for ES != DS? But maybe */
1122 /* that might cause more harm than good... */
1123 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1124 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1125 /* Let's just reset ES to the DS value and hope it's okay */
1126 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1127 goto continueexecution;
1128 }
1129
1130 switch(pERepRec->ExceptionInfo[0]) {
1131 case XCPT_READ_ACCESS:
1132 accessflag = MEMMAP_ACCESS_READ;
1133 break;
1134 case XCPT_WRITE_ACCESS:
1135 accessflag = MEMMAP_ACCESS_WRITE;
1136 fWriteAccess = TRUE;
1137 break;
1138 case XCPT_EXECUTE_ACCESS:
1139 accessflag = MEMMAP_ACCESS_EXECUTE;
1140 break;
1141 default:
1142 goto continueFail;
1143 }
1144
1145 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1146 if(map == NULL) {
1147 goto continueFail;
1148 }
1149 if(map->commitPage(offset, fWriteAccess) == TRUE)
1150 goto continueexecution;
1151
1152 //no break;
1153 }
1154continueFail:
1155
1156////#define DEBUGSTACK
1157#ifdef DEBUGSTACK
1158 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1159 ULONG *stackptr;
1160 APIRET rc;
1161 int i;
1162 ULONG ulOffset, ulModule, ulObject;
1163 CHAR szModule[CCHMAXPATH];
1164
1165 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1166 dprintf(("Stack DUMP:"));
1167 for(i=0;i<16;i++) {
1168 rc = DosQueryModFromEIP(&ulModule,
1169 &ulObject,
1170 sizeof(szModule),
1171 szModule,
1172 &ulOffset,
1173 (ULONG)*stackptr);
1174
1175 if (rc == NO_ERROR)
1176 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1177 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1178 stackptr++;
1179 }
1180 dprintf(("Stack DUMP END"));
1181 }
1182#endif
1183
1184 case XCPT_BREAKPOINT:
1185 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1186 case XCPT_DATATYPE_MISALIGNMENT:
1187 case XCPT_ILLEGAL_INSTRUCTION:
1188 case XCPT_PRIVILEGED_INSTRUCTION:
1189 case XCPT_INVALID_LOCK_SEQUENCE:
1190 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1191 case XCPT_INTEGER_OVERFLOW:
1192 case XCPT_SINGLE_STEP:
1193 case XCPT_UNABLE_TO_GROW_STACK:
1194 case XCPT_IN_PAGE_ERROR:
1195CrashAndBurn:
1196 //SvL: TODO: this may not always be the right thing to do
1197 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1198 // of this exception handler. We better bail out ASAP or we'll likely
1199 // recurse infinitely until we run out of stack space!!
1200 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1201 goto continuesearch;
1202
1203#ifdef DEBUG
1204 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1205 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1206 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1207 }
1208#endif
1209 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1210 {
1211 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1212 {
1213 goto continueexecution;
1214 }
1215 }
1216 else goto continuesearch; //pass on to OS/2 RTL or app exception handler
1217
1218 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1219 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1220 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1221 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1222 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1223 goto continueexecution;
1224
1225 //@@@PH: growing thread stacks might need special treatment
1226 case XCPT_GUARD_PAGE_VIOLATION:
1227 //SvL: don't print anything here -> fatal hang if happens inside fprintf
1228 //dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue search)"));
1229 goto continuesearch;
1230
1231 case XCPT_SIGNAL:
1232 if(pERepRec->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC) /* resolve signal information */
1233 {
1234 SetExceptionChain((ULONG)-1);
1235 goto continuesearch;
1236 }
1237 goto CrashAndBurn;
1238
1239 default: //non-continuable exceptions
1240 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1241 goto continuesearch;
1242 }
1243continuesearch:
1244 LogException(LEAVE_EXCEPTION);
1245 return XCPT_CONTINUE_SEARCH;
1246
1247continueexecution:
1248 LogException(LEAVE_EXCEPTION);
1249 return XCPT_CONTINUE_EXECUTION;
1250}
1251
1252/*****************************************************************************
1253 * Name : void OS2SetExceptionHandler
1254 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1255 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1256 * Variables :
1257 * Result :
1258 * Remark :
1259 * Status :
1260 *
1261 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1262 *****************************************************************************/
1263void OS2SetExceptionHandler(void *exceptframe)
1264{
1265 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1266
1267 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1268 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1269
1270 /* disable trap popups */
1271// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1272
1273 DosSetExceptionHandler(pExceptRec);
1274 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1275#ifdef DEBUG_ENABLELOG_LEVEL2
1276 PrintExceptionChain();
1277#endif
1278}
1279
1280#ifdef DEBUG
1281void PrintExceptionChain()
1282{
1283 USHORT sel = RestoreOS2FS();
1284 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1285
1286 dprintf(("Exception chain list:"));
1287 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1288 dprintf(("record %x", pExceptRec));
1289 pExceptRec = pExceptRec->prev_structure;
1290 }
1291 SetFS(sel);
1292}
1293
1294void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
1295{
1296 dprintf(("Win32 exception chain:"));
1297 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
1298 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
1299 if (pframe == pframe->Prev) {
1300 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
1301 break;
1302 }
1303 pframe = pframe->Prev;
1304 }
1305}
1306
1307#endif
1308
1309
1310/*****************************************************************************
1311 * Name : void OS2UnsetExceptionHandler
1312 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1313 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1314 * Variables :
1315 * Result :
1316 * Remark :
1317 * Status :
1318 *
1319 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1320 *****************************************************************************/
1321void OS2UnsetExceptionHandler(void *exceptframe)
1322{
1323 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1324
1325 DosUnsetExceptionHandler(pExceptRec);
1326 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1327#ifdef DEBUG_ENABLELOG_LEVEL2
1328 PrintExceptionChain();
1329#endif
1330}
1331
1332void SetOS2ExceptionChain(ULONG val)
1333{
1334 USHORT sel = GetFS();
1335
1336 SetExceptionChain(val);
1337 SetFS(sel);
1338}
1339
1340int _System CheckCurFS()
1341{
1342 USHORT sel = RestoreOS2FS();
1343 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1344
1345 if(sel == 0x150b) {
1346 SetFS(sel);
1347 return FALSE;
1348 }
1349 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1350 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1351 SetFS(sel);
1352 return FALSE;
1353 }
1354 SetFS(sel);
1355 return TRUE;
1356}
1357
Note: See TracBrowser for help on using the repository browser.