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

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

rewrote EXC_CallHandler in assembly + workaround for high addresses in stdout WriteFile

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