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

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

added fs check export

File size: 37.0 KB
Line 
1/* $Id: exceptions.cpp,v 1.32 2000-01-27 21:51:16 sandervl Exp $ */
2
3/*
4 * Win32 Device IOCTL API functions for OS/2
5 *
6 * Ported Wine exception handling code
7 *
8 * Copyright 1998 Sander van Leeuwen (OS/2 port)
9 *
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 *
14 * (dlls\ntdll\exception.c)
15 *
16 * Copyright 1999 Turchanov Sergey
17 * Copyright 1999 Alexandre Julliard
18 *
19 * (win32\except.c)
20 *
21 * Win32 exception functions
22 *
23 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
24 *
25 * Notes:
26 * What really happens behind the scenes of those new
27 * __try{...}__except(..){....} and
28 * __try{...}__finally{...}
29 * statements is simply not documented by Microsoft. There could be different
30 * reasons for this:
31 * One reason could be that they try to hide the fact that exception
32 * handling in Win32 looks almost the same as in OS/2 2.x.
33 * Another reason could be that Microsoft does not want others to write
34 * binary compatible implementations of the Win32 API (like us).
35 *
36 * Whatever the reason, THIS SUCKS!! Ensuring portabilty or future
37 * compatability may be valid reasons to keep some things undocumented.
38 * But exception handling is so basic to Win32 that it should be
39 * documented!
40 *
41 * Fixmes:
42 * -Most functions need better parameter checking.
43 * -I do not know how to handle exceptions within an exception handler.
44 * or what is done when ExceptionNestedException is returned from an
45 * exception handler
46 * -Real exceptions are not yet implemented. only the exception functions
47 * are implemented. A real implementation needs some new code in
48 * loader/signal.c. There would also be a need for showing debugging
49 * information in UnhandledExceptionFilter.
50 *
51 */
52#define INCL_MISC
53#define INCL_BASE
54#define INCL_WINBUTTONS
55#include <os2wrap.h> //Odin32 OS/2 api wrappers
56#include <stdio.h>
57#include <stdlib.h>
58#include <assert.h>
59#include <string.h>
60#include <builtin.h>
61#include "exceptions.h"
62#include "exceptutil.h"
63#include <misc.h>
64#include "mmap.h"
65#include <wprocess.h>
66#include "oslibexcept.h"
67
68//Global Process Unhandled exception filter
69static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL;
70static UINT CurrentErrorMode = 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 //Restore original OS/2 TIB selector
525 RestoreOS2FS();
526
527 SetExceptionChain((ULONG)-1);
528 DosExit(EXIT_PROCESS, 666);
529}
530
531
532//******************************************************************************
533APIRET APIENTRY DosQueryModFromEIP (PULONG pulModule,
534 PULONG pulObject,
535 ULONG ulBufferLength,
536 PSZ pszBuffer,
537 PULONG pulOffset,
538 ULONG ulEIP);
539//******************************************************************************
540
541
542/*****************************************************************************
543 * Name : void static dprintfException
544 * Purpose : log the exception to win32os2.log
545 * Parameters: ...
546 * Variables :
547 * Result :
548 * Remark :
549 * Status :
550 *
551 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
552 *****************************************************************************/
553
554void static dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
555 PEXCEPTIONREGISTRATIONRECORD pERegRec,
556 PCONTEXTRECORD pCtxRec,
557 PVOID p)
558{
559 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
560 char szData[128]; /* local storage for excpt dep. information */
561 char szData2[128]; /* local storage for excpt dep. information */
562 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
563 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
564 BOOL fExcptFatal = TRUE; /* fatal exception ? */
565 BOOL fExcptPortable = TRUE; /* portability of exception */
566 PPIB pPIB; /* process information block */
567 PTIB pTIB; /* thread information block */
568 ULONG ulModule; /* module number */
569 ULONG ulObject; /* object number within the module */
570 CHAR szModule[260]; /* buffer for the module name */
571 ULONG ulOffset; /* offset within the object within the module */
572
573 szData[0] = 0; /* initialize */
574 szData2[0] = 0; /* initialize */
575 switch(pERepRec->ExceptionNum) /* take according action */
576 {
577 /* portable, non-fatal software-generated exceptions */
578 case XCPT_GUARD_PAGE_VIOLATION:
579 pszExceptionName = "Guard Page Violation";
580 sprintf(szData,
581 "R/W %08xh at %08xh.",
582 pERepRec->ExceptionInfo[0],
583 pERepRec->ExceptionInfo[1]);
584 fExcptSoftware = TRUE;
585 fExcptFatal = FALSE;
586 rc = XCPT_CONTINUE_EXECUTION;
587 break;
588
589 case XCPT_UNABLE_TO_GROW_STACK:
590 pszExceptionName = "Unable To Grow Stack";
591 fExcptSoftware = TRUE;
592 fExcptFatal = FALSE;
593 rc = XCPT_CONTINUE_EXECUTION;
594 break;
595
596 /* portable, fatal, hardware-generated exceptions */
597 case XCPT_ACCESS_VIOLATION:
598 pszExceptionName = "Access Violation";
599 /* sprintf (szData, "Access type %08x at %08x.", pERepRec->ExceptionInfo[0],
600 pERepRec->ExceptionInfo[1]); */
601 switch (pERepRec->ExceptionInfo[0])
602 {
603 case XCPT_READ_ACCESS:
604 sprintf (szData,
605 "Read Access at address %08xh",
606 pERepRec->ExceptionInfo[1]);
607 break;
608
609 case XCPT_WRITE_ACCESS:
610 sprintf (szData,
611 "Write Access at address %08x",
612 pERepRec->ExceptionInfo[1]);
613 break;
614
615 case XCPT_SPACE_ACCESS:
616 sprintf (szData,
617 "Space Access at selector %08x",
618 pERepRec->ExceptionInfo[1]);
619 break;
620
621 case XCPT_LIMIT_ACCESS:
622 strcpy (szData,
623 "Limit Access");
624 break;
625
626 case XCPT_UNKNOWN_ACCESS:
627 strcpy (szData,
628 "Unknown Access");
629 break;
630
631 default:
632 strcpy (szData,
633 "(Invalid Access Code)");
634 break;
635 }
636 break;
637
638 case XCPT_INTEGER_DIVIDE_BY_ZERO:
639 pszExceptionName = "Division By Zero (Integer)";
640 break;
641
642 case XCPT_FLOAT_DIVIDE_BY_ZERO:
643 pszExceptionName = "Division By Zero (Float)";
644 break;
645
646 case XCPT_FLOAT_INVALID_OPERATION:
647 pszExceptionName = "Invalid Floating Point Operation";
648 break;
649
650 case XCPT_ILLEGAL_INSTRUCTION:
651 pszExceptionName = "Illegal Instruction";
652 break;
653
654 case XCPT_PRIVILEGED_INSTRUCTION:
655 pszExceptionName = "Privileged Instruction";
656 break;
657
658 case XCPT_INTEGER_OVERFLOW:
659 pszExceptionName = "Integer Overflow";
660 break;
661
662 case XCPT_FLOAT_OVERFLOW:
663 pszExceptionName = "Floating Point Overflow";
664 break;
665
666 case XCPT_FLOAT_UNDERFLOW:
667 pszExceptionName = "Floating Point Underflow";
668 break;
669
670 case XCPT_FLOAT_DENORMAL_OPERAND:
671 pszExceptionName = "Floating Point Denormal Operand";
672 break;
673
674 case XCPT_FLOAT_INEXACT_RESULT:
675 pszExceptionName = "Floating Point Inexact Result";
676 break;
677
678 case XCPT_FLOAT_STACK_CHECK:
679 pszExceptionName = "Floating Point Stack Check";
680 break;
681
682 case XCPT_DATATYPE_MISALIGNMENT:
683 pszExceptionName = "Datatype Misalignment";
684 sprintf(szData,
685 "R/W %08x alignment %08x at %08x.",
686 pERepRec->ExceptionInfo[0],
687 pERepRec->ExceptionInfo[1],
688 pERepRec->ExceptionInfo[2]);
689 break;
690
691 case XCPT_BREAKPOINT:
692 pszExceptionName = "Breakpoint (don't debug me! :)";
693 break;
694
695 case XCPT_SINGLE_STEP:
696 pszExceptionName = "Single Step (don't debug me! :)";
697 break;
698
699 /* portable, fatal, software-generated exceptions */
700 case XCPT_IN_PAGE_ERROR:
701 pszExceptionName = "In Page Error";
702 sprintf(szData,
703 "at %08x.",
704 pERepRec->ExceptionInfo[0]);
705 fExcptSoftware = TRUE;
706 break;
707
708 case XCPT_PROCESS_TERMINATE:
709 pszExceptionName = "Process Termination";
710 fExcptSoftware = TRUE;
711 break;
712
713 case XCPT_ASYNC_PROCESS_TERMINATE:
714 pszExceptionName = "Process Termination (async)";
715 sprintf(szData,
716 "terminating thread TID=%u",
717 pERepRec->ExceptionInfo[0]);
718 fExcptSoftware = TRUE;
719 break;
720
721 case XCPT_NONCONTINUABLE_EXCEPTION:
722 pszExceptionName = "Noncontinuable Exception";
723 fExcptSoftware = TRUE;
724 break;
725
726 case XCPT_INVALID_DISPOSITION:
727 pszExceptionName = "Invalid Disposition";
728 fExcptSoftware = TRUE;
729 break;
730
731 /* non-portable, fatal exceptions */
732 case XCPT_INVALID_LOCK_SEQUENCE:
733 pszExceptionName = "Invalid Lock Sequence";
734 fExcptSoftware = TRUE;
735 fExcptPortable = FALSE;
736 break;
737
738 case XCPT_ARRAY_BOUNDS_EXCEEDED:
739 pszExceptionName = "Array Bounds Exceeded";
740 fExcptSoftware = TRUE;
741 fExcptPortable = FALSE;
742 break;
743
744 /* unwind operation exceptions */
745 case XCPT_UNWIND:
746 pszExceptionName = "Unwind Exception";
747 fExcptSoftware = TRUE;
748 fExcptPortable = FALSE;
749 break;
750
751 case XCPT_BAD_STACK:
752 pszExceptionName = "Unwind Exception, Bad Stack";
753 fExcptSoftware = TRUE;
754 fExcptPortable = FALSE;
755 break;
756
757 case XCPT_INVALID_UNWIND_TARGET:
758 pszExceptionName = "Unwind Exception, Invalid Target";
759 fExcptSoftware = TRUE;
760 fExcptPortable = FALSE;
761 break;
762
763 /* fatal signal exceptions */
764 case XCPT_SIGNAL:
765 pszExceptionName = "Signal";
766 sprintf(szData,
767 "Signal Number = %08x",
768 pERepRec->ExceptionInfo[0]);
769 fExcptSoftware = TRUE;
770 fExcptPortable = FALSE;
771
772 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
773 {
774 case XCPT_SIGNAL_INTR:
775 pszExceptionName = "Signal (Interrupt)";
776 break;
777
778 case XCPT_SIGNAL_KILLPROC:
779 pszExceptionName = "Signal (Kill Process)";
780 break;
781
782 case XCPT_SIGNAL_BREAK:
783 pszExceptionName = "Signal (Break)";
784 break;
785 }
786 break;
787
788 default:
789 pszExceptionName = "(unknown exception code)";
790 sprintf(szData,
791 "Exception Code = %08x",
792 pERepRec->ExceptionNum);
793 }
794
795
796 /* now dump the information to the logfile */
797 dprintf(("---[Exception Information]------------\n"));
798 sprintf(szData2,
799 " %s (",
800 pszExceptionName);
801
802 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
803 strcat (szData2, "software generated,");
804 else
805 strcat (szData2, "hardware generated,");
806
807 if (fExcptPortable == TRUE) /* portable exception ? */
808 strcat (szData2, "portable,");
809 else
810 strcat (szData2, "non-portable,");
811
812 if (fExcptFatal == TRUE) /* fatal exception ? */
813 strcat (szData2, "fatal");
814 else
815 strcat (szData2, "non-fatal");
816
817 strcat (szData2, /* add trailing brace */
818 ")\n");
819
820
821 dprintf((szData2));
822
823 if (szData[0] != 0) /* see if there is an additional entry */
824 dprintf((" %s\n",
825 szData));
826
827 rc = DosQueryModFromEIP(&ulModule,
828 &ulObject,
829 sizeof(szModule),
830 szModule,
831 &ulOffset,
832 (ULONG)pERepRec->ExceptionAddress);
833
834 dprintf((" Exception Address = %08x ",
835 pERepRec->ExceptionAddress));
836
837 if (rc == NO_ERROR)
838 dprintf(("%s (#%u), obj #%u:%08x\n",
839 szModule,
840 ulModule,
841 ulObject,
842 ulOffset));
843 else
844 dprintf(("\n"));
845
846
847 rc = DosGetInfoBlocks (&pTIB, /* query kernel information blocks */
848 &pPIB);
849 if (rc == NO_ERROR)
850 {
851 dprintf((" Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
852 pTIB->tib_ordinal,
853 pTIB->tib_ptib2->tib2_ultid,
854 pTIB->tib_ptib2->tib2_ulpri));
855
856 dprintf((" Process: PID: %u, Parent: %u, Status: %u\n",
857 pPIB->pib_ulpid,
858 pPIB->pib_ulppid,
859 pPIB->pib_flstatus));
860 }
861
862 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
863 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n"
864 " CS:EIP=%04x:%08x EBP =%08x\n",
865 pCtxRec->ctx_SegSs,
866 pCtxRec->ctx_RegEsp,
867 pCtxRec->ctx_EFlags,
868 pCtxRec->ctx_SegCs,
869 pCtxRec->ctx_RegEip,
870 pCtxRec->ctx_RegEbp));
871
872 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
873 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n"
874 " ECX=%08x EDX=%08x EDI=%08x\n",
875 pCtxRec->ctx_RegEax,
876 pCtxRec->ctx_RegEbx,
877 pCtxRec->ctx_RegEsi,
878 pCtxRec->ctx_RegEcx,
879 pCtxRec->ctx_RegEdx,
880 pCtxRec->ctx_RegEdi));
881
882 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
883 dprintf((" DS=%04x ES=%08x"
884 " FS=%04x GS=%04x\n",
885 pCtxRec->ctx_SegDs,
886 pCtxRec->ctx_SegEs,
887 pCtxRec->ctx_SegFs,
888 pCtxRec->ctx_SegGs));
889
890 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
891 {
892 ULONG ulCounter; /* temporary local counter for fp stack */
893
894 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
895 pCtxRec->ctx_env[0],
896 pCtxRec->ctx_env[1],
897 pCtxRec->ctx_env[2],
898 pCtxRec->ctx_env[3]));
899
900 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
901 pCtxRec->ctx_env[4],
902 pCtxRec->ctx_env[5],
903 pCtxRec->ctx_env[6]));
904
905 for (ulCounter = 0;
906 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
907 ulCounter ++)
908 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
909 ulCounter,
910 pCtxRec->ctx_stack[0].losig,
911 pCtxRec->ctx_stack[0].hisig,
912 pCtxRec->ctx_stack[0].signexp));
913 }
914
915 dprintf(("---[End Of Exception Information]-----\n"));
916}
917
918
919/*****************************************************************************
920 * Name : ERR _System OS2ExceptionHandler
921 * Purpose :
922 * Parameters: ...
923 * Variables :
924 * Result :
925 * Remark :
926 * Status :
927 *
928 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
929 *****************************************************************************/
930 /* from PPC DDK */
931#ifndef XCPT_CONTINUE_STOP
932#define XCPT_CONTINUE_STOP 0x00716668
933#endif
934
935//in misc.cpp
936void CheckLogException();
937
938ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
939 PEXCEPTIONREGISTRATIONRECORD pERegRec,
940 PCONTEXTRECORD pCtxRec,
941 PVOID 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 dprintfException(pERepRec, pERegRec, pCtxRec, p);
954 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
955 if(fIsOS2Image == FALSE) //Only for real win32 apps
956 {
957 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
958 {
959 pCtxRec->ctx_env[0] |= 0x1F;
960 pCtxRec->ctx_stack[0].losig = 0;
961 pCtxRec->ctx_stack[0].hisig = 0;
962 pCtxRec->ctx_stack[0].signexp = 0;
963 }
964 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
965 return (XCPT_CONTINUE_EXECUTION);
966 }
967 else
968 {
969 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
970 return (XCPT_CONTINUE_SEARCH);
971 }
972
973 case XCPT_PROCESS_TERMINATE:
974 case XCPT_ASYNC_PROCESS_TERMINATE:
975 dprintfException(pERepRec, pERegRec, pCtxRec, p);
976 SetExceptionChain((ULONG)-1);
977 return (XCPT_CONTINUE_SEARCH);
978
979 case XCPT_ACCESS_VIOLATION:
980 {
981 Win32MemMap *map;
982 BOOL fWriteAccess = FALSE;
983 ULONG offset, accessflag;
984
985 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
986 goto continueFail;
987 }
988 switch(pERepRec->ExceptionInfo[0]) {
989 case XCPT_READ_ACCESS:
990 accessflag = MEMMAP_ACCESS_READ;
991 break;
992 case XCPT_WRITE_ACCESS:
993 accessflag = MEMMAP_ACCESS_WRITE;
994 fWriteAccess = TRUE;
995 break;
996 case XCPT_EXECUTE_ACCESS:
997 accessflag = MEMMAP_ACCESS_EXECUTE;
998 break;
999 default:
1000 goto continueFail;
1001 }
1002
1003 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1004 if(map == NULL) {
1005 goto continueFail;
1006 }
1007 if(map->commitPage(offset, fWriteAccess) == TRUE)
1008 return (XCPT_CONTINUE_EXECUTION);
1009
1010 //no break;
1011 }
1012continueFail:
1013
1014 case XCPT_BREAKPOINT:
1015 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1016 case XCPT_DATATYPE_MISALIGNMENT:
1017 case XCPT_ILLEGAL_INSTRUCTION:
1018 case XCPT_PRIVILEGED_INSTRUCTION:
1019 case XCPT_INVALID_LOCK_SEQUENCE:
1020 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1021 case XCPT_INTEGER_OVERFLOW:
1022 case XCPT_SINGLE_STEP:
1023 case XCPT_UNABLE_TO_GROW_STACK:
1024 case XCPT_IN_PAGE_ERROR:
1025CrashAndBurn:
1026 CheckLogException();
1027 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1028 if(fIsOS2Image == FALSE) //Only for real win32 apps
1029 {
1030 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1031 {
1032 return (XCPT_CONTINUE_EXECUTION);
1033 }
1034 }
1035 else return XCPT_CONTINUE_SEARCH; //pass on to OS/2 RTL or app exception handler
1036
1037 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1038 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1039 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1040 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1041 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1042 return (XCPT_CONTINUE_EXECUTION);
1043
1044 //@@@PH: growing thread stacks might need special treatment
1045 case XCPT_GUARD_PAGE_VIOLATION:
1046 dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue)\n"));
1047 return (XCPT_CONTINUE_SEARCH);
1048
1049 case XCPT_SIGNAL:
1050 if(pERepRec->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC) /* resolve signal information */
1051 {
1052 SetExceptionChain((ULONG)-1);
1053 return (XCPT_CONTINUE_SEARCH);
1054 }
1055 goto CrashAndBurn;
1056
1057 default: //non-continuable exceptions
1058 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1059 return (XCPT_CONTINUE_SEARCH);
1060 }
1061 return (XCPT_CONTINUE_SEARCH);
1062}
1063
1064/*****************************************************************************
1065 * Name : void OS2SetExceptionHandler
1066 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1067 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1068 * Variables :
1069 * Result :
1070 * Remark :
1071 * Status :
1072 *
1073 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1074 *****************************************************************************/
1075void OS2SetExceptionHandler(void *exceptframe)
1076{
1077 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1078
1079 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1080 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1081
1082 /* disable trap popups */
1083// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1084
1085 DosSetExceptionHandler(pExceptRec);
1086 dprintf(("OS2SetExceptionHandler: exception chain %x (old %x)", pExceptRec, pExceptRec->prev_structure));
1087}
1088
1089/*****************************************************************************
1090 * Name : void OS2UnsetExceptionHandler
1091 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1092 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1093 * Variables :
1094 * Result :
1095 * Remark :
1096 * Status :
1097 *
1098 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1099 *****************************************************************************/
1100void OS2UnsetExceptionHandler(void *exceptframe)
1101{
1102 DosUnsetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)exceptframe);
1103}
1104
1105void SetOS2ExceptionChain(ULONG val)
1106{
1107 USHORT sel = GetFS();
1108
1109 SetExceptionChain(val);
1110 SetFS(sel);
1111}
1112
1113int _System CheckCurFS()
1114{
1115 USHORT sel = RestoreOS2FS();
1116 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1117
1118 if(sel == 0x150b) {
1119 SetFS(sel);
1120 return FALSE;
1121 }
1122 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1123 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1124 SetFS(sel);
1125 return FALSE;
1126 }
1127 SetFS(sel);
1128 return TRUE;
1129}
1130
1131/*****************************************************************************
1132 * Name : void ReplaceExceptionHandler
1133 * Purpose :
1134 * Parameters: ...
1135 * Variables :
1136 * Result :
1137 * Remark :
1138 * Status :
1139 *
1140 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
1141 *****************************************************************************/
1142
1143//******************************************************************************
1144//SvL: Replace original startup code exception handler
1145extern BOOL fExeStarted;
1146//******************************************************************************
1147void ReplaceExceptionHandler()
1148{
1149 static BOOL fRegistered = FALSE;
1150 PWINEXCEPTION_FRAME orgframe;
1151 APIRET rc;
1152 ULONGULONG_W timerval;
1153
1154 DisableFPUExceptions();
1155
1156 if(fExeStarted == FALSE)
1157 return;
1158
1159 orgframe = (PWINEXCEPTION_FRAME)QueryExceptionChain();
1160 if((int)orgframe == 0 ||
1161 (int)orgframe == -1)
1162 return;
1163
1164 dprintf(("KERNEL32: ReplaceExceptionHandler\n"));
1165
1166 StartupCodeHandler = orgframe->Handler;
1167 orgframe->Handler = (PEXCEPTION_HANDLER)OS2ExceptionHandler;
1168 orgframe->Prev = (_WINEXCEPTION_FRAME *)0;
1169 SetExceptionChain((ULONG)-1);
1170
1171#if 0
1172 if(fRegistered == FALSE)
1173 {
1174#endif
1175
1176 dprintf(("KERNEL32: ReplaceExceptionHandler: New exception frame at %X\n",
1177 orgframe));
1178 rc = DosSetExceptionHandler((PEXCEPTIONREGISTRATIONRECORD)orgframe);
1179 fRegistered = TRUE;
1180
1181#if 0
1182 }
1183 else
1184 {
1185 while(orgframe && orgframe->Handler != (PEXCEPTION_HANDLER)OS2ExceptionHandler)
1186 {
1187 orgframe = orgframe->Prev;
1188 }
1189
1190 dprintf(("KERNEL32: ReplaceExceptionHandler: Restore old exception frame %X\n",
1191 orgframe));
1192 if(orgframe)
1193 {
1194 orgframe->Prev = (_WINEXCEPTION_FRAME *)0;
1195 SetExceptionChain((ULONG)orgframe);
1196 }
1197 }
1198#endif
1199}
1200
Note: See TracBrowser for help on using the repository browser.