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

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

Exception changes + fixes; don't switch FS selectors for Odin32 OS/2 apps

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