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

Last change on this file since 5128 was 5128, checked in by sandervl, 25 years ago

TLS index allocation + RtlUnwind fixes

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