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

Last change on this file since 6496 was 6151, checked in by bird, 24 years ago

Improoved Unhandled exception message.

File size: 45.8 KB
Line 
1/* $Id: exceptions.cpp,v 1.55 2001-07-03 13:24:25 bird Exp $ */
2
3/*
4 * Win32 Exception 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 "exceptions.h"
61#include "exceptutil.h"
62#include <misc.h>
63#include "mmap.h"
64#include <wprocess.h>
65#include "oslibexcept.h"
66#include "exceptstackdump.h"
67
68#include "WinImageBase.h"
69#include "WinDllBase.h"
70#include "WinExeBase.h"
71
72#define DBG_LOCALLOG DBG_exceptions
73#include "dbglocal.h"
74
75/* Exception record for handling exceptions happening inside exception handlers */
76typedef struct
77{
78 WINEXCEPTION_FRAME frame;
79 WINEXCEPTION_FRAME *prevFrame;
80} EXC_NESTED_FRAME;
81
82//Global Process Unhandled exception filter
83static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL;
84static UINT CurrentErrorMode = SEM_FAILCRITICALERRORS;
85static PEXCEPTION_HANDLER StartupCodeHandler = NULL;
86
87extern "C" PWINEXCEPTION_FRAME GetExceptionRecord(ULONG offset, ULONG segment);
88
89LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo);
90void KillWin32Process(void);
91
92#ifdef DEBUG
93void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe);
94#else
95#define PrintWin32ExceptionChain(a)
96#endif
97
98/*****************************************************************************
99 * Name : UINT SetErrorMode
100 * Purpose :
101 * Parameters: UINT fuErrorMode
102 * Variables :
103 * Result :
104 * Remark :
105 * Status :
106 *
107 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
108 *****************************************************************************/
109
110UINT WIN32API SetErrorMode(UINT fuErrorMode)
111{
112 UINT oldmode = CurrentErrorMode;
113
114 dprintf(("KERNEL32: SetErrorMode(%08xh)\n",
115 fuErrorMode));
116 CurrentErrorMode = fuErrorMode;
117
118 if(fuErrorMode & SEM_FAILCRITICALERRORS || fuErrorMode & SEM_NOOPENFILEERRORBOX)
119 DosError(FERR_DISABLEHARDERR);
120 else
121 DosError(FERR_ENABLEHARDERR);
122
123 // SEM_NOGPFAULTERRORBOX and SEM_NOALIGNMENTFAULTEXCEPT --> UnhandledExceptionFilter()
124
125 return(oldmode);
126}
127
128#if 0
129static inline WINEXCEPTION_FRAME * EXC_push_frame( WINEXCEPTION_FRAME *frame )
130{
131 // TODO: rewrite in assembly
132 TEB *teb = GetThreadTEB();
133 frame->Prev = (PWINEXCEPTION_FRAME)teb->except;
134 teb->except = frame;
135 return frame->Prev;
136}
137
138static inline WINEXCEPTION_FRAME * EXC_pop_frame( WINEXCEPTION_FRAME *frame )
139{
140 // TODO: rewrite in assembly
141 TEB *teb = GetThreadTEB();
142 teb->except = frame->Prev;
143 return frame->Prev;
144}
145#endif
146
147/*****************************************************************************
148 * Name : VOID _Pascal OS2RaiseException
149 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
150 * Parameters: ...
151 * Variables :
152 * Result :
153 * Remark :
154 * Status :
155 *
156 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
157 *****************************************************************************/
158
159void WIN32API RtlRaiseException(WINEXCEPTION_RECORD *rec, WINCONTEXT *context);
160
161VOID _Pascal OS2RaiseException(DWORD dwExceptionCode,
162 DWORD dwExceptionFlags,
163 DWORD cArguments,
164 DWORD *lpArguments,
165 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
166 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
167 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
168 DWORD es, DWORD fs, DWORD gs, DWORD ss)
169{
170 WINEXCEPTION_RECORD record;
171 WINEXCEPTION_POINTERS ExceptionInfo;
172 WINCONTEXT context;
173 int rc;
174 int i;
175
176 dprintf(("KERNEL32: RaiseException(%08xh)\n",
177 dwExceptionCode));
178
179 memset(&record, 0, sizeof(record));
180
181 /* compose an exception record */
182 record.ExceptionCode = dwExceptionCode;
183 record.ExceptionFlags = dwExceptionFlags;
184 record.ExceptionRecord = NULL;
185 record.NumberParameters = cArguments;
186 record.ExceptionAddress = (LPVOID)eip;
187
188 memset(&context, 0, sizeof(context));
189 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
190 context.SegGs = gs;
191 context.SegFs = fs;
192 context.SegEs = es;
193 context.SegDs = ds;
194 context.Edi = edi;
195 context.Esi = esi;
196 context.Ebx = ebx;
197 context.Edx = edx;
198 context.Ecx = ecx;
199 context.Eax = eax;
200 context.Ebp = ebp;
201 context.Eip = eip;
202 context.SegCs = cs;
203 context.EFlags = flags;
204 context.Esp = esp;
205 context.SegSs = ss;
206
207 if(lpArguments)
208 {
209 for(i=0;
210 i<cArguments;
211 i++)
212 record.ExceptionInformation[i] = lpArguments[i];
213 }
214
215 rc = RtlDispatchException(&record, &context);
216
217 // and finally, the unhandled exception filter
218 if(rc == ExceptionContinueSearch && UnhandledExceptionFilter != NULL)
219 {
220 dprintf(("KERNEL32: RaiseException calling UnhandledExceptionFilter.\n"));
221
222 ExceptionInfo.ExceptionRecord = &record;
223 ExceptionInfo.ContextRecord = &context;
224
225 rc = UnhandledExceptionFilter(&ExceptionInfo);
226 //FIXME: UnhandledExceptionFilter does NOT return the same values as
227 // other filters!!
228 }
229
230 // terminate the process
231 if(rc != ExceptionContinueExecution ||
232 record.ExceptionFlags & EH_NONCONTINUABLE)
233 {
234 dprintf(("KERNEL32: RaiseException terminating process.\n"));
235 DosExit(EXIT_PROCESS, 0);
236 }
237
238 dprintf(("KERNEL32: RaiseException returns.\n"));
239 return;
240}
241
242/*******************************************************************
243 * EXC_RaiseHandler
244 *
245 * Handler for exceptions happening inside a handler.
246 */
247static DWORD WIN32API EXC_RaiseHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
248// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
249 WINCONTEXT *context, LPVOID dispatcher )
250{
251 if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
252 return ExceptionContinueSearch;
253 /* We shouldn't get here so we store faulty frame in dispatcher */
254 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
255 return ExceptionNestedException;
256}
257
258/*******************************************************************
259 * EXC_UnwindHandler
260 *
261 * Handler for exceptions happening inside an unwind handler.
262 */
263static DWORD WIN32API EXC_UnwindHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
264// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
265 WINCONTEXT *context, LPVOID dispatcher )
266{
267 if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
268 return ExceptionContinueSearch;
269 /* We shouldn't get here so we store faulty frame in dispatcher */
270 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
271 return ExceptionCollidedUnwind;
272}
273
274#if 1
275DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
276 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
277 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler);
278
279#else
280/*******************************************************************
281 * EXC_CallHandler
282 *
283 * Call an exception handler, setting up an exception frame to catch exceptions
284 * happening during the handler execution.
285 * WARNING:
286 * Please do not change the first 4 parameters order in any way - some exceptions handlers
287 * rely on Base Pointer (EBP) to have a fixed position related to the exception frame
288 */
289static DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
290 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
291 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler)
292{
293 EXC_NESTED_FRAME newframe;
294 DWORD ret;
295
296 newframe.frame.Handler = nested_handler;
297 newframe.prevFrame = frame;
298 EXC_push_frame( &newframe.frame );
299 dprintf(("KERNEL32: Calling handler at %p code=%lx flags=%lx\n",
300 handler, record->ExceptionCode, record->ExceptionFlags));
301 ret = handler( record, frame, context, dispatcher );
302 dprintf(("KERNEL32: Handler returned %lx\n", ret));
303 EXC_pop_frame( &newframe.frame );
304 return ret;
305}
306#endif
307//******************************************************************************
308//******************************************************************************
309DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext)
310{
311 PWINEXCEPTION_FRAME pFrame, dispatch, nested_frame;
312 int rc;
313
314 // get chain of exception frames
315 rc = ExceptionContinueSearch;
316
317 nested_frame = NULL;
318 TEB *winteb = GetThreadTEB();
319 pFrame = (PWINEXCEPTION_FRAME)winteb->except;
320
321 dprintf(("KERNEL32: RtlDispatchException entered"));
322
323 PrintWin32ExceptionChain(pFrame);
324
325 // walk the exception chain
326 while( (pFrame != NULL) && (pFrame != ((void *)0xFFFFFFFF)) )
327 {
328 dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", pFrame, pFrame->Prev));
329 if (pFrame == pFrame->Prev) {
330 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
331 return 0;
332 }
333
334 dispatch=0;
335
336 /* Check frame address */
337 if (((void*)pFrame < winteb->stack_low) ||
338 ((void*)(pFrame+1) > winteb->stack_top) ||
339 (int)pFrame & 3)
340 {
341 dprintf(("Invalid stack! low=%08X, top=%08X, pframe = %08X",
342 winteb->stack_low, winteb->stack_top, pFrame));
343
344 pRecord->ExceptionFlags |= EH_STACK_INVALID;
345 break;
346 }
347
348
349 /* call handler */
350 rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch, pFrame->Handler, EXC_RaiseHandler );
351
352 PrintWin32ExceptionChain(pFrame);
353
354 if (pFrame == nested_frame)
355 {
356 /* no longer nested */
357 nested_frame = NULL;
358 pRecord->ExceptionFlags &= ~EH_NESTED_CALL;
359 }
360
361
362 switch(rc)
363 {
364 case ExceptionContinueExecution:
365 if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE)) {
366 dprintf(("KERNEL32: RtlDispatchException returns %#x (ContinueExecution)", rc));
367 return rc;
368 }
369 break;
370 case ExceptionContinueSearch:
371 break;
372 case ExceptionNestedException:
373 if (nested_frame < dispatch) nested_frame = dispatch;
374 pRecord->ExceptionFlags |= EH_NESTED_CALL;
375 break;
376 default:
377 break;
378 }
379
380 dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", pFrame, pFrame->Prev));
381 if (pFrame == pFrame->Prev) {
382 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
383 break;
384 }
385 pFrame = pFrame->Prev;
386 }
387 dprintf(("KERNEL32: RtlDispatchException returns %#x", rc));
388 PrintWin32ExceptionChain(pFrame);
389 return rc;
390}
391/*****************************************************************************
392 * Name : int _Pascal OS2RtlUnwind
393 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
394 * Parameters: ...
395 * Variables :
396 * Result :
397 * Remark :
398 * Status :
399 *
400 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
401 *****************************************************************************/
402
403int _Pascal OS2RtlUnwind(PWINEXCEPTION_FRAME pEndFrame,
404 LPVOID unusedEip,
405 PWINEXCEPTION_RECORD pRecord,
406 DWORD returnEax,
407 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
408 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
409 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
410 DWORD es, DWORD fs, DWORD gs, DWORD ss)
411{
412 PWINEXCEPTION_FRAME frame, dispatch;
413 WINEXCEPTION_RECORD record, newrec;
414 WINCONTEXT context;
415 DWORD rc;
416
417 dprintf(("KERNEL32: RtlUnwind pEndFrame=%08X, unusedEip=%08X, pRecord=%08X, returnEax=%#x\n", pEndFrame, unusedEip, pRecord, returnEax));
418
419
420 memset(&context, 0, sizeof(context));
421 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
422 context.SegGs = gs;
423 context.SegFs = fs;
424 context.SegEs = es;
425 context.SegDs = ds;
426 context.Edi = edi;
427 context.Esi = esi;
428 context.Ebx = ebx;
429 context.Edx = edx;
430 context.Ecx = ecx;
431 context.Eax = returnEax;
432 context.Ebp = ebp;
433 context.Eip = eip;
434 context.SegCs = cs;
435 context.EFlags = flags;
436 context.Esp = esp;
437 context.SegSs = ss;
438
439 /* build an exception record, if we do not have one */
440 if(!pRecord)
441 {
442 memset(&record, 0, sizeof(record));
443 record.ExceptionCode = STATUS_UNWIND;
444 record.ExceptionFlags = 0;
445 record.ExceptionRecord = NULL;
446 record.ExceptionAddress = (LPVOID)eip;
447 record.NumberParameters = 0;
448 pRecord = &record;
449 }
450
451 if(pEndFrame) pRecord->ExceptionFlags |= EH_UNWINDING;
452 else pRecord->ExceptionFlags |= EH_UNWINDING | EH_EXIT_UNWIND;
453
454 /* get chain of exception frames */
455 TEB *winteb = GetThreadTEB();
456 frame = (PWINEXCEPTION_FRAME)winteb->except;
457
458 PrintWin32ExceptionChain(frame);
459
460 while ((frame != (PWINEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame))
461 {
462 /* Check frame address */
463 if (pEndFrame && (frame > pEndFrame))
464 {
465 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
466 newrec.ExceptionFlags = EH_NONCONTINUABLE;
467 newrec.ExceptionRecord = pRecord;
468 newrec.NumberParameters = 0;
469 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
470 DosExit(EXIT_THREAD, 0);
471 }
472 if (((void*)frame < winteb->stack_low) ||
473 ((void*)(frame+1) > winteb->stack_top) ||
474 (int)frame & 3)
475 {
476 newrec.ExceptionCode = STATUS_BAD_STACK;
477 newrec.ExceptionFlags = EH_NONCONTINUABLE;
478 newrec.ExceptionRecord = pRecord;
479 newrec.NumberParameters = 0;
480 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
481 DosExit(EXIT_THREAD, 0);
482 }
483
484 /* Call handler */
485 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler));
486 rc = EXC_CallHandler(pRecord, frame, &context, &dispatch, frame->Handler, EXC_UnwindHandler );
487 dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc));
488 switch (rc)
489 {
490 case ExceptionContinueSearch:
491 break;
492 case ExceptionCollidedUnwind:
493 frame = dispatch;
494 break;
495 default:
496 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;
497 newrec.ExceptionFlags = EH_NONCONTINUABLE;
498 newrec.ExceptionRecord = pRecord;
499 newrec.NumberParameters = 0;
500 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
501 DosExit(EXIT_THREAD, 0);
502 break;
503 }
504 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, frame->Prev));
505 SetExceptionChain((DWORD)frame->Prev);
506 frame = frame->Prev;
507 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame, frame->Prev));
508 }
509
510 dprintf(("KERNEL32: RtlUnwind returning.\n"));
511 PrintWin32ExceptionChain(frame);
512 return(0);
513}
514
515
516/*****************************************************************************
517 * Name : LONG WIN32API UnhandledExceptionFilter
518 * Purpose :
519 * Parameters: ...
520 * Variables :
521 * Result :
522 * Remark :
523 * Status :
524 *
525 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
526 *****************************************************************************/
527
528LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo)
529{
530 char szModName[16];
531 char message[128];
532 ULONG iObj;
533 ULONG offObj;
534 HMODULE hmod;
535 DWORD rc;
536
537#if 0 //not in use...
538 // @@@PH: experimental change to have more control over exception handling
539#pragma pack(4)
540 typedef struct
541 {
542 ULONG cb; /* Size of fixed part of structure */
543 HPOINTER hIcon; /* Icon handle */
544 ULONG cButtons; /* Number of buttons */
545 ULONG flStyle; /* Icon style flags (MB_ICONQUESTION, etc...)*/
546 HWND hwndNotify; /* Reserved */
547 MB2D mb2d[4]; /* Array of button definitions */
548 } myMB2INFO;
549#pragma pack()
550
551 myMB2INFO mb2InfoExceptionBox = { 20, // size of structure
552 NULLHANDLE, // icon handle
553 4, // number of buttons
554 MB_ICONHAND, // icon style
555 NULLHANDLE, // reserved
556 { {"continue ~search", 100, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE},
557 {"continue ~execution", 101, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE},
558 {"execute ~handler", 102, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE | BS_DEFAULT},
559 {"~terminate process", 103, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE} }
560 };
561#endif
562
563 dprintf(("KERNEL32: Default UnhandledExceptionFilter, CurrentErrorMode=%X", CurrentErrorMode));
564
565 // We must not care about ErrorMode here!! The app expects that its own
566 // UnhandledExceptionFilter will be cared even if it never touched ErrorMode.
567 if(CurrentUnhExceptionFlt) // && !(CurrentErrorMode & (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)))
568 {
569 dprintf(("KERNEL32: Calling user UnhandledExceptionFilter"));
570 rc = CurrentUnhExceptionFlt(lpexpExceptionInfo);
571 if(rc != WINEXCEPTION_CONTINUE_SEARCH)
572 return rc;
573 }
574
575
576 if (DosQueryModFromEIP(&hmod, &iObj, sizeof(szModName), szModName, &offObj, (ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress))
577 sprintf(message,
578 "Unhandled exception 0x%08lx at address 0x%08lx. (DQMFEIP rc=%d)",
579 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
580 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
581 else
582 {
583 if (iObj == -1)
584 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
585 Win32ImageBase * pMod;
586 if (WinExe && WinExe->insideModule((ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress))
587 pMod = WinExe;
588 else
589 pMod = Win32DllBase::findModuleByAddr((ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
590 if (pMod != NULL)
591 {
592 szModName[0] = '\0';
593 strncat(szModName, pMod->getModuleName(), sizeof(szModName) - 1);
594 iObj = 0xFF;
595 offObj = (ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress
596 - (ULONG)pMod->getInstanceHandle();
597 }
598 }
599 sprintf(message,
600 "Unhandled exception 0x%08lx at address 0x%08lx.\r"
601 "Mod: %s obj: 0x%2lx off:0x%08lx",
602 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
603 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress,
604 szModName, iObj, offObj);
605 }
606
607/*
608 rc = WinMessageBox2(HWND_DESKTOP,
609 HWND_DESKTOP,
610 message,
611 "Oh, nooo!",
612 0,
613 (PMB2INFO)&mb2InfoExceptionBox);
614 switch (rc)
615 {
616 case 100:
617 return WINEXCEPTION_CONTINUE_SEARCH;
618
619 case 101:
620 return WINEXCEPTION_CONTINUE_EXECUTION;
621
622 case 102:
623 return WINEXCEPTION_EXECUTE_HANDLER;
624
625 case 103:
626 KillWin32Process();
627 // fall-through
628
629 default:
630 return WINEXCEPTION_EXECUTE_HANDLER;
631 }
632*/
633 rc = WinMessageBox(HWND_DESKTOP,
634 HWND_DESKTOP,
635 message,
636 "Oh, nooo!",
637 0,
638 MB_ABORTRETRYIGNORE | MB_ERROR);
639 switch (rc)
640 {
641 case MBID_IGNORE:
642 return WINEXCEPTION_CONTINUE_EXECUTION;
643
644 case MBID_ABORT:
645 KillWin32Process();
646 // fall-through
647
648 case MBID_RETRY:
649 default:
650 return WINEXCEPTION_EXECUTE_HANDLER;
651 }
652}
653
654
655/*****************************************************************************
656 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
657 * Purpose :
658 * Parameters: ...
659 * Variables :
660 * Result :
661 * Remark :
662 * Status :
663 *
664 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
665 *****************************************************************************/
666
667LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
668{
669 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
670
671 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n",
672 lpTopLevelExceptionFilter));
673
674 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
675
676 return(old);
677}
678
679
680/*****************************************************************************
681 * Name : KillWin32Process
682 * Purpose :
683 * Parameters: ...
684 * Variables :
685 * Result :
686 * Remark :
687 * Status :
688 *
689 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
690 *****************************************************************************/
691
692
693//******************************************************************************
694extern "C" ULONG getEAX();
695extern "C" ULONG getEBX();
696VOID WIN32API ExitProcess(DWORD exitcode);
697//******************************************************************************
698void KillWin32Process(void)
699{
700 static BOOL fEntry = FALSE;
701
702 if(fEntry == FALSE) {
703 fEntry = TRUE;
704 ExitProcess(666);
705 return;
706 }
707 //Restore original OS/2 TIB selector
708 RestoreOS2FS();
709
710 SetExceptionChain((ULONG)-1);
711 DosExit(EXIT_PROCESS, 666);
712}
713
714
715/*****************************************************************************
716 * Name : void static dprintfException
717 * Purpose : log the exception to win32os2.log
718 * Parameters: ...
719 * Variables :
720 * Result :
721 * Remark :
722 * Status :
723 *
724 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
725 *****************************************************************************/
726
727static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
728 PEXCEPTIONREGISTRATIONRECORD pERegRec,
729 PCONTEXTRECORD pCtxRec,
730 PVOID p)
731{
732 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
733 char szData[128]; /* local storage for excpt dep. information */
734 char szData2[128]; /* local storage for excpt dep. information */
735 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
736 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
737 BOOL fExcptFatal = TRUE; /* fatal exception ? */
738 BOOL fExcptPortable = TRUE; /* portability of exception */
739 PPIB pPIB; /* process information block */
740 PTIB pTIB; /* thread information block */
741 ULONG ulModule; /* module number */
742 ULONG ulObject; /* object number within the module */
743 CHAR szModule[260]; /* buffer for the module name */
744 ULONG ulOffset; /* offset within the object within the module */
745
746 szData[0] = 0; /* initialize */
747 szData2[0] = 0; /* initialize */
748 switch(pERepRec->ExceptionNum) /* take according action */
749 {
750 /* portable, non-fatal software-generated exceptions */
751 case XCPT_GUARD_PAGE_VIOLATION:
752 pszExceptionName = "Guard Page Violation";
753 sprintf(szData,
754 "R/W %08xh at %08xh.",
755 pERepRec->ExceptionInfo[0],
756 pERepRec->ExceptionInfo[1]);
757 fExcptSoftware = TRUE;
758 fExcptFatal = FALSE;
759 rc = XCPT_CONTINUE_EXECUTION;
760 break;
761
762 case XCPT_UNABLE_TO_GROW_STACK:
763 pszExceptionName = "Unable To Grow Stack";
764 fExcptSoftware = TRUE;
765 fExcptFatal = FALSE;
766 rc = XCPT_CONTINUE_EXECUTION;
767 break;
768
769 /* portable, fatal, hardware-generated exceptions */
770 case XCPT_ACCESS_VIOLATION:
771 pszExceptionName = "Access Violation";
772 /* sprintf (szData, "Access type %08x at %08x.", pERepRec->ExceptionInfo[0],
773 pERepRec->ExceptionInfo[1]); */
774 switch (pERepRec->ExceptionInfo[0])
775 {
776 case XCPT_READ_ACCESS:
777 sprintf (szData,
778 "Read Access at address %08xh",
779 pERepRec->ExceptionInfo[1]);
780 break;
781
782 case XCPT_WRITE_ACCESS:
783 sprintf (szData,
784 "Write Access at address %08x",
785 pERepRec->ExceptionInfo[1]);
786 break;
787
788 case XCPT_SPACE_ACCESS:
789 sprintf (szData,
790 "Space Access at selector %08x",
791 pERepRec->ExceptionInfo[1]);
792 break;
793
794 case XCPT_LIMIT_ACCESS:
795 strcpy (szData,
796 "Limit Access");
797 break;
798
799 case XCPT_UNKNOWN_ACCESS:
800 strcpy (szData,
801 "Unknown Access");
802 break;
803
804 default:
805 strcpy (szData,
806 "(Invalid Access Code)");
807 break;
808 }
809 break;
810
811 case XCPT_INTEGER_DIVIDE_BY_ZERO:
812 pszExceptionName = "Division By Zero (Integer)";
813 break;
814
815 case XCPT_FLOAT_DIVIDE_BY_ZERO:
816 pszExceptionName = "Division By Zero (Float)";
817 break;
818
819 case XCPT_FLOAT_INVALID_OPERATION:
820 pszExceptionName = "Invalid Floating Point Operation";
821 break;
822
823 case XCPT_ILLEGAL_INSTRUCTION:
824 pszExceptionName = "Illegal Instruction";
825 break;
826
827 case XCPT_PRIVILEGED_INSTRUCTION:
828 pszExceptionName = "Privileged Instruction";
829 break;
830
831 case XCPT_INTEGER_OVERFLOW:
832 pszExceptionName = "Integer Overflow";
833 break;
834
835 case XCPT_FLOAT_OVERFLOW:
836 pszExceptionName = "Floating Point Overflow";
837 break;
838
839 case XCPT_FLOAT_UNDERFLOW:
840 pszExceptionName = "Floating Point Underflow";
841 break;
842
843 case XCPT_FLOAT_DENORMAL_OPERAND:
844 pszExceptionName = "Floating Point Denormal Operand";
845 break;
846
847 case XCPT_FLOAT_INEXACT_RESULT:
848 pszExceptionName = "Floating Point Inexact Result";
849 break;
850
851 case XCPT_FLOAT_STACK_CHECK:
852 pszExceptionName = "Floating Point Stack Check";
853 break;
854
855 case XCPT_DATATYPE_MISALIGNMENT:
856 pszExceptionName = "Datatype Misalignment";
857 sprintf(szData,
858 "R/W %08x alignment %08x at %08x.",
859 pERepRec->ExceptionInfo[0],
860 pERepRec->ExceptionInfo[1],
861 pERepRec->ExceptionInfo[2]);
862 break;
863
864 case XCPT_BREAKPOINT:
865 pszExceptionName = "Breakpoint (don't debug me! :)";
866 break;
867
868 case XCPT_SINGLE_STEP:
869 pszExceptionName = "Single Step (don't debug me! :)";
870 break;
871
872 /* portable, fatal, software-generated exceptions */
873 case XCPT_IN_PAGE_ERROR:
874 pszExceptionName = "In Page Error";
875 sprintf(szData,
876 "at %08x.",
877 pERepRec->ExceptionInfo[0]);
878 fExcptSoftware = TRUE;
879 break;
880
881 case XCPT_PROCESS_TERMINATE:
882 pszExceptionName = "Process Termination";
883 fExcptSoftware = TRUE;
884 break;
885
886 case XCPT_ASYNC_PROCESS_TERMINATE:
887 pszExceptionName = "Process Termination (async)";
888 sprintf(szData,
889 "terminating thread TID=%u",
890 pERepRec->ExceptionInfo[0]);
891 fExcptSoftware = TRUE;
892 break;
893
894 case XCPT_NONCONTINUABLE_EXCEPTION:
895 pszExceptionName = "Noncontinuable Exception";
896 fExcptSoftware = TRUE;
897 break;
898
899 case XCPT_INVALID_DISPOSITION:
900 pszExceptionName = "Invalid Disposition";
901 fExcptSoftware = TRUE;
902 break;
903
904 /* non-portable, fatal exceptions */
905 case XCPT_INVALID_LOCK_SEQUENCE:
906 pszExceptionName = "Invalid Lock Sequence";
907 fExcptSoftware = TRUE;
908 fExcptPortable = FALSE;
909 break;
910
911 case XCPT_ARRAY_BOUNDS_EXCEEDED:
912 pszExceptionName = "Array Bounds Exceeded";
913 fExcptSoftware = TRUE;
914 fExcptPortable = FALSE;
915 break;
916
917 /* unwind operation exceptions */
918 case XCPT_UNWIND:
919 pszExceptionName = "Unwind Exception";
920 fExcptSoftware = TRUE;
921 fExcptPortable = FALSE;
922 break;
923
924 case XCPT_BAD_STACK:
925 pszExceptionName = "Unwind Exception, Bad Stack";
926 fExcptSoftware = TRUE;
927 fExcptPortable = FALSE;
928 break;
929
930 case XCPT_INVALID_UNWIND_TARGET:
931 pszExceptionName = "Unwind Exception, Invalid Target";
932 fExcptSoftware = TRUE;
933 fExcptPortable = FALSE;
934 break;
935
936 /* fatal signal exceptions */
937 case XCPT_SIGNAL:
938 pszExceptionName = "Signal";
939 sprintf(szData,
940 "Signal Number = %08x",
941 pERepRec->ExceptionInfo[0]);
942 fExcptSoftware = TRUE;
943 fExcptPortable = FALSE;
944
945 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
946 {
947 case XCPT_SIGNAL_INTR:
948 pszExceptionName = "Signal (Interrupt)";
949 break;
950
951 case XCPT_SIGNAL_KILLPROC:
952 pszExceptionName = "Signal (Kill Process)";
953 break;
954
955 case XCPT_SIGNAL_BREAK:
956 pszExceptionName = "Signal (Break)";
957 break;
958 }
959 break;
960
961 default:
962 pszExceptionName = "(unknown exception code)";
963 sprintf(szData,
964 "Exception Code = %08x",
965 pERepRec->ExceptionNum);
966 }
967
968
969 /* now dump the information to the logfile */
970 dprintf(("---[Exception Information]------------\n"));
971 sprintf(szData2,
972 " %s (",
973 pszExceptionName);
974
975 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
976 strcat (szData2, "software generated,");
977 else
978 strcat (szData2, "hardware generated,");
979
980 if (fExcptPortable == TRUE) /* portable exception ? */
981 strcat (szData2, "portable,");
982 else
983 strcat (szData2, "non-portable,");
984
985 if (fExcptFatal == TRUE) /* fatal exception ? */
986 strcat (szData2, "fatal");
987 else
988 strcat (szData2, "non-fatal");
989
990 strcat (szData2, /* add trailing brace */
991 ")\n");
992
993
994 dprintf((szData2));
995
996 if (szData[0] != 0) /* see if there is an additional entry */
997 dprintf((" %s\n",
998 szData));
999
1000 rc = DosQueryModFromEIP(&ulModule,
1001 &ulObject,
1002 sizeof(szModule),
1003 szModule,
1004 &ulOffset,
1005 (ULONG)pERepRec->ExceptionAddress);
1006
1007 dprintf((" Exception Address = %08x ",
1008 pERepRec->ExceptionAddress));
1009
1010 if(rc == NO_ERROR && ulObject != -1)
1011 dprintf(("<%s> (#%u), obj #%u:%08x\n",
1012 szModule,
1013 ulModule,
1014 ulObject,
1015 ulOffset));
1016 else
1017 dprintf(("<win32 app>\n"));
1018
1019
1020 rc = DosGetInfoBlocks (&pTIB, /* query kernel information blocks */
1021 &pPIB);
1022 if (rc == NO_ERROR)
1023 {
1024 dprintf((" Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
1025 pTIB->tib_ordinal,
1026 pTIB->tib_ptib2->tib2_ultid,
1027 pTIB->tib_ptib2->tib2_ulpri));
1028
1029 dprintf((" Process: PID: %u, Parent: %u, Status: %u\n",
1030 pPIB->pib_ulpid,
1031 pPIB->pib_ulppid,
1032 pPIB->pib_flstatus));
1033 }
1034
1035 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
1036 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n",
1037 pCtxRec->ctx_SegSs,
1038 pCtxRec->ctx_RegEsp,
1039 pCtxRec->ctx_EFlags));
1040 dprintf((" CS:EIP=%04x:%08x EBP =%08x\n",
1041 pCtxRec->ctx_SegCs,
1042 pCtxRec->ctx_RegEip,
1043 pCtxRec->ctx_RegEbp));
1044
1045 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
1046 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n",
1047 pCtxRec->ctx_RegEax,
1048 pCtxRec->ctx_RegEbx,
1049 pCtxRec->ctx_RegEsi));
1050 dprintf((" ECX=%08x EDX=%08x EDI=%08x\n",
1051 pCtxRec->ctx_RegEcx,
1052 pCtxRec->ctx_RegEdx,
1053 pCtxRec->ctx_RegEdi));
1054
1055 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
1056 dprintf((" DS=%04x ES=%08x",
1057 pCtxRec->ctx_SegDs,
1058 pCtxRec->ctx_SegEs));
1059 dprintf((" FS=%04x GS=%04x\n",
1060 pCtxRec->ctx_SegFs,
1061 pCtxRec->ctx_SegGs));
1062
1063 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1064 {
1065 ULONG ulCounter; /* temporary local counter for fp stack */
1066
1067 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1068 pCtxRec->ctx_env[0],
1069 pCtxRec->ctx_env[1],
1070 pCtxRec->ctx_env[2],
1071 pCtxRec->ctx_env[3]));
1072
1073 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1074 pCtxRec->ctx_env[4],
1075 pCtxRec->ctx_env[5],
1076 pCtxRec->ctx_env[6]));
1077
1078 for (ulCounter = 0;
1079 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1080 ulCounter ++)
1081 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1082 ulCounter,
1083 pCtxRec->ctx_stack[0].losig,
1084 pCtxRec->ctx_stack[0].hisig,
1085 pCtxRec->ctx_stack[0].signexp));
1086 }
1087
1088 dprintf(("---[End Of Exception Information]-----\n"));
1089}
1090
1091/*****************************************************************************
1092 * Name : ERR _System OS2ExceptionHandler
1093 * Purpose :
1094 * Parameters: ...
1095 * Variables :
1096 * Result :
1097 * Remark :
1098 * Status :
1099 *
1100 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1101 *****************************************************************************/
1102 /* from PPC DDK */
1103#ifndef XCPT_CONTINUE_STOP
1104#define XCPT_CONTINUE_STOP 0x00716668
1105#endif
1106
1107ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1108 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1109 PCONTEXTRECORD pCtxRec,
1110 PVOID p)
1111{
1112 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1113 // next dprintf won't wait forever
1114 LogException(ENTER_EXCEPTION);
1115
1116 /* Access violation at a known location */
1117 switch(pERepRec->ExceptionNum)
1118 {
1119 case XCPT_FLOAT_DENORMAL_OPERAND:
1120 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1121 case XCPT_FLOAT_INEXACT_RESULT:
1122// case XCPT_FLOAT_INVALID_OPERATION:
1123 case XCPT_FLOAT_OVERFLOW:
1124 case XCPT_FLOAT_STACK_CHECK:
1125 case XCPT_FLOAT_UNDERFLOW:
1126 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1127 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1128 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1129 {
1130 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1131 {
1132 pCtxRec->ctx_env[0] |= 0x1F;
1133 pCtxRec->ctx_stack[0].losig = 0;
1134 pCtxRec->ctx_stack[0].hisig = 0;
1135 pCtxRec->ctx_stack[0].signexp = 0;
1136 }
1137 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1138 goto continueexecution;
1139 }
1140 else
1141 {
1142 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1143 goto continuesearch;
1144 }
1145
1146 case XCPT_PROCESS_TERMINATE:
1147 case XCPT_ASYNC_PROCESS_TERMINATE:
1148//// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1149 SetExceptionChain((ULONG)-1);
1150 goto continuesearch;
1151
1152 case XCPT_ACCESS_VIOLATION:
1153 {
1154 Win32MemMap *map;
1155 BOOL fWriteAccess = FALSE;
1156 ULONG offset, accessflag;
1157
1158 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1159 goto continueFail;
1160 }
1161
1162//------------->>> WARNING: potentially dangerous workaround!!
1163 /* Some apps set ES = FS and Odin doesn't like that! */
1164 /* Note: maybe we could even check for ES != DS? But maybe */
1165 /* that might cause more harm than good... */
1166 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1167 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1168 /* Let's just reset ES to the DS value and hope it's okay */
1169 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1170 goto continueexecution;
1171 }
1172
1173 switch(pERepRec->ExceptionInfo[0]) {
1174 case XCPT_READ_ACCESS:
1175 accessflag = MEMMAP_ACCESS_READ;
1176 break;
1177 case XCPT_WRITE_ACCESS:
1178 accessflag = MEMMAP_ACCESS_WRITE;
1179 fWriteAccess = TRUE;
1180 break;
1181 case XCPT_EXECUTE_ACCESS:
1182 accessflag = MEMMAP_ACCESS_EXECUTE;
1183 break;
1184 default:
1185 goto continueFail;
1186 }
1187
1188 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1189 if(map == NULL) {
1190 goto continueFail;
1191 }
1192 if(map->commitPage(offset, fWriteAccess) == TRUE)
1193 goto continueexecution;
1194
1195 //no break;
1196 }
1197continueFail:
1198
1199////#define DEBUGSTACK
1200#ifdef DEBUGSTACK
1201 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1202 ULONG *stackptr;
1203 APIRET rc;
1204 int i;
1205 ULONG ulOffset, ulModule, ulObject;
1206 CHAR szModule[CCHMAXPATH];
1207
1208 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1209 dprintf(("Stack DUMP:"));
1210 for(i=0;i<16;i++) {
1211 rc = DosQueryModFromEIP(&ulModule,
1212 &ulObject,
1213 sizeof(szModule),
1214 szModule,
1215 &ulOffset,
1216 (ULONG)*stackptr);
1217
1218 if (rc == NO_ERROR)
1219 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1220 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1221 stackptr++;
1222 }
1223 dprintf(("Stack DUMP END"));
1224 }
1225#endif
1226
1227 case XCPT_BREAKPOINT:
1228 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1229 case XCPT_DATATYPE_MISALIGNMENT:
1230 case XCPT_ILLEGAL_INSTRUCTION:
1231 case XCPT_PRIVILEGED_INSTRUCTION:
1232 case XCPT_INVALID_LOCK_SEQUENCE:
1233 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1234 case XCPT_INTEGER_OVERFLOW:
1235 case XCPT_SINGLE_STEP:
1236 case XCPT_UNABLE_TO_GROW_STACK:
1237 case XCPT_IN_PAGE_ERROR:
1238CrashAndBurn:
1239 //SvL: TODO: this may not always be the right thing to do
1240 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1241 // of this exception handler. We better bail out ASAP or we'll likely
1242 // recurse infinitely until we run out of stack space!!
1243 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1244 goto continuesearch;
1245
1246#ifdef DEBUG
1247 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1248 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1249 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1250 }
1251#endif
1252 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1253 {
1254 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1255 {
1256 goto continueexecution;
1257 }
1258 }
1259 else goto continuesearch; //pass on to OS/2 RTL or app exception handler
1260
1261 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1262 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1263 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1264 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1265 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1266 goto continueexecution;
1267
1268 //@@@PH: growing thread stacks might need special treatment
1269 case XCPT_GUARD_PAGE_VIOLATION:
1270 //SvL: don't print anything here -> fatal hang if happens inside fprintf
1271 //dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue search)"));
1272 goto continuesearch;
1273
1274 case XCPT_SIGNAL:
1275 if(pERepRec->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC) /* resolve signal information */
1276 {
1277 SetExceptionChain((ULONG)-1);
1278 goto continuesearch;
1279 }
1280 goto CrashAndBurn;
1281
1282 default: //non-continuable exceptions
1283 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1284 goto continuesearch;
1285 }
1286continuesearch:
1287 LogException(LEAVE_EXCEPTION);
1288 return XCPT_CONTINUE_SEARCH;
1289
1290continueexecution:
1291 LogException(LEAVE_EXCEPTION);
1292 return XCPT_CONTINUE_EXECUTION;
1293}
1294
1295/*****************************************************************************
1296 * Name : void OS2SetExceptionHandler
1297 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1298 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1299 * Variables :
1300 * Result :
1301 * Remark :
1302 * Status :
1303 *
1304 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1305 *****************************************************************************/
1306void OS2SetExceptionHandler(void *exceptframe)
1307{
1308 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1309
1310 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1311 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1312
1313 /* disable trap popups */
1314// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1315
1316 DosSetExceptionHandler(pExceptRec);
1317 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1318#ifdef DEBUG_ENABLELOG_LEVEL2
1319 PrintExceptionChain();
1320#endif
1321}
1322
1323#ifdef DEBUG
1324void PrintExceptionChain()
1325{
1326 USHORT sel = RestoreOS2FS();
1327 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1328
1329 dprintf(("Exception chain list:"));
1330 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1331 dprintf(("record %x", pExceptRec));
1332 pExceptRec = pExceptRec->prev_structure;
1333 }
1334 SetFS(sel);
1335}
1336
1337void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
1338{
1339 dprintf(("Win32 exception chain:"));
1340 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
1341 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
1342 if (pframe == pframe->Prev) {
1343 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
1344 break;
1345 }
1346 pframe = pframe->Prev;
1347 }
1348}
1349
1350#endif
1351
1352
1353/*****************************************************************************
1354 * Name : void OS2UnsetExceptionHandler
1355 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1356 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1357 * Variables :
1358 * Result :
1359 * Remark :
1360 * Status :
1361 *
1362 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1363 *****************************************************************************/
1364void OS2UnsetExceptionHandler(void *exceptframe)
1365{
1366 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1367
1368 DosUnsetExceptionHandler(pExceptRec);
1369 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1370#ifdef DEBUG_ENABLELOG_LEVEL2
1371 PrintExceptionChain();
1372#endif
1373}
1374
1375void SetOS2ExceptionChain(ULONG val)
1376{
1377 USHORT sel = GetFS();
1378
1379 SetExceptionChain(val);
1380 SetFS(sel);
1381}
1382
1383int _System CheckCurFS()
1384{
1385 USHORT sel = RestoreOS2FS();
1386 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1387
1388 if(sel == 0x150b) {
1389 SetFS(sel);
1390 return FALSE;
1391 }
1392 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1393 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1394 SetFS(sel);
1395 return FALSE;
1396 }
1397 SetFS(sel);
1398 return TRUE;
1399}
1400
Note: See TracBrowser for help on using the repository browser.