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

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

Call ExitProcess in KillWin32Process

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