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

Last change on this file since 1580 was 1580, checked in by phaller, 26 years ago

Fix: initialization of CurrentErrorMode

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