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

Last change on this file since 1224 was 1224, checked in by sandervl, 26 years ago

Exception handling changes

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