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

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

Improoved Unhandled exception message.

File size: 45.6 KB
Line 
1/* $Id: exceptions.cpp,v 1.54 2001-07-03 13:17:42 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 }
595 }
596 sprintf(message,
597 "Unhandled exception 0x%08lx at address 0x%08lx.\r"
598 "Mod: %s obj: 0x%2lx off:0x%08lx",
599 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
600 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress,
601 szModName, iObj, offObj);
602 }
603
604/*
605 rc = WinMessageBox2(HWND_DESKTOP,
606 HWND_DESKTOP,
607 message,
608 "Oh, nooo!",
609 0,
610 (PMB2INFO)&mb2InfoExceptionBox);
611 switch (rc)
612 {
613 case 100:
614 return WINEXCEPTION_CONTINUE_SEARCH;
615
616 case 101:
617 return WINEXCEPTION_CONTINUE_EXECUTION;
618
619 case 102:
620 return WINEXCEPTION_EXECUTE_HANDLER;
621
622 case 103:
623 KillWin32Process();
624 // fall-through
625
626 default:
627 return WINEXCEPTION_EXECUTE_HANDLER;
628 }
629*/
630 rc = WinMessageBox(HWND_DESKTOP,
631 HWND_DESKTOP,
632 message,
633 "Oh, nooo!",
634 0,
635 MB_ABORTRETRYIGNORE | MB_ERROR);
636 switch (rc)
637 {
638 case MBID_IGNORE:
639 return WINEXCEPTION_CONTINUE_EXECUTION;
640
641 case MBID_ABORT:
642 KillWin32Process();
643 // fall-through
644
645 case MBID_RETRY:
646 default:
647 return WINEXCEPTION_EXECUTE_HANDLER;
648 }
649}
650
651
652/*****************************************************************************
653 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
654 * Purpose :
655 * Parameters: ...
656 * Variables :
657 * Result :
658 * Remark :
659 * Status :
660 *
661 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
662 *****************************************************************************/
663
664LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
665{
666 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
667
668 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n",
669 lpTopLevelExceptionFilter));
670
671 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
672
673 return(old);
674}
675
676
677/*****************************************************************************
678 * Name : KillWin32Process
679 * Purpose :
680 * Parameters: ...
681 * Variables :
682 * Result :
683 * Remark :
684 * Status :
685 *
686 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
687 *****************************************************************************/
688
689
690//******************************************************************************
691extern "C" ULONG getEAX();
692extern "C" ULONG getEBX();
693VOID WIN32API ExitProcess(DWORD exitcode);
694//******************************************************************************
695void KillWin32Process(void)
696{
697 static BOOL fEntry = FALSE;
698
699 if(fEntry == FALSE) {
700 fEntry = TRUE;
701 ExitProcess(666);
702 return;
703 }
704 //Restore original OS/2 TIB selector
705 RestoreOS2FS();
706
707 SetExceptionChain((ULONG)-1);
708 DosExit(EXIT_PROCESS, 666);
709}
710
711
712/*****************************************************************************
713 * Name : void static dprintfException
714 * Purpose : log the exception to win32os2.log
715 * Parameters: ...
716 * Variables :
717 * Result :
718 * Remark :
719 * Status :
720 *
721 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
722 *****************************************************************************/
723
724static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
725 PEXCEPTIONREGISTRATIONRECORD pERegRec,
726 PCONTEXTRECORD pCtxRec,
727 PVOID p)
728{
729 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
730 char szData[128]; /* local storage for excpt dep. information */
731 char szData2[128]; /* local storage for excpt dep. information */
732 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
733 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
734 BOOL fExcptFatal = TRUE; /* fatal exception ? */
735 BOOL fExcptPortable = TRUE; /* portability of exception */
736 PPIB pPIB; /* process information block */
737 PTIB pTIB; /* thread information block */
738 ULONG ulModule; /* module number */
739 ULONG ulObject; /* object number within the module */
740 CHAR szModule[260]; /* buffer for the module name */
741 ULONG ulOffset; /* offset within the object within the module */
742
743 szData[0] = 0; /* initialize */
744 szData2[0] = 0; /* initialize */
745 switch(pERepRec->ExceptionNum) /* take according action */
746 {
747 /* portable, non-fatal software-generated exceptions */
748 case XCPT_GUARD_PAGE_VIOLATION:
749 pszExceptionName = "Guard Page Violation";
750 sprintf(szData,
751 "R/W %08xh at %08xh.",
752 pERepRec->ExceptionInfo[0],
753 pERepRec->ExceptionInfo[1]);
754 fExcptSoftware = TRUE;
755 fExcptFatal = FALSE;
756 rc = XCPT_CONTINUE_EXECUTION;
757 break;
758
759 case XCPT_UNABLE_TO_GROW_STACK:
760 pszExceptionName = "Unable To Grow Stack";
761 fExcptSoftware = TRUE;
762 fExcptFatal = FALSE;
763 rc = XCPT_CONTINUE_EXECUTION;
764 break;
765
766 /* portable, fatal, hardware-generated exceptions */
767 case XCPT_ACCESS_VIOLATION:
768 pszExceptionName = "Access Violation";
769 /* sprintf (szData, "Access type %08x at %08x.", pERepRec->ExceptionInfo[0],
770 pERepRec->ExceptionInfo[1]); */
771 switch (pERepRec->ExceptionInfo[0])
772 {
773 case XCPT_READ_ACCESS:
774 sprintf (szData,
775 "Read Access at address %08xh",
776 pERepRec->ExceptionInfo[1]);
777 break;
778
779 case XCPT_WRITE_ACCESS:
780 sprintf (szData,
781 "Write Access at address %08x",
782 pERepRec->ExceptionInfo[1]);
783 break;
784
785 case XCPT_SPACE_ACCESS:
786 sprintf (szData,
787 "Space Access at selector %08x",
788 pERepRec->ExceptionInfo[1]);
789 break;
790
791 case XCPT_LIMIT_ACCESS:
792 strcpy (szData,
793 "Limit Access");
794 break;
795
796 case XCPT_UNKNOWN_ACCESS:
797 strcpy (szData,
798 "Unknown Access");
799 break;
800
801 default:
802 strcpy (szData,
803 "(Invalid Access Code)");
804 break;
805 }
806 break;
807
808 case XCPT_INTEGER_DIVIDE_BY_ZERO:
809 pszExceptionName = "Division By Zero (Integer)";
810 break;
811
812 case XCPT_FLOAT_DIVIDE_BY_ZERO:
813 pszExceptionName = "Division By Zero (Float)";
814 break;
815
816 case XCPT_FLOAT_INVALID_OPERATION:
817 pszExceptionName = "Invalid Floating Point Operation";
818 break;
819
820 case XCPT_ILLEGAL_INSTRUCTION:
821 pszExceptionName = "Illegal Instruction";
822 break;
823
824 case XCPT_PRIVILEGED_INSTRUCTION:
825 pszExceptionName = "Privileged Instruction";
826 break;
827
828 case XCPT_INTEGER_OVERFLOW:
829 pszExceptionName = "Integer Overflow";
830 break;
831
832 case XCPT_FLOAT_OVERFLOW:
833 pszExceptionName = "Floating Point Overflow";
834 break;
835
836 case XCPT_FLOAT_UNDERFLOW:
837 pszExceptionName = "Floating Point Underflow";
838 break;
839
840 case XCPT_FLOAT_DENORMAL_OPERAND:
841 pszExceptionName = "Floating Point Denormal Operand";
842 break;
843
844 case XCPT_FLOAT_INEXACT_RESULT:
845 pszExceptionName = "Floating Point Inexact Result";
846 break;
847
848 case XCPT_FLOAT_STACK_CHECK:
849 pszExceptionName = "Floating Point Stack Check";
850 break;
851
852 case XCPT_DATATYPE_MISALIGNMENT:
853 pszExceptionName = "Datatype Misalignment";
854 sprintf(szData,
855 "R/W %08x alignment %08x at %08x.",
856 pERepRec->ExceptionInfo[0],
857 pERepRec->ExceptionInfo[1],
858 pERepRec->ExceptionInfo[2]);
859 break;
860
861 case XCPT_BREAKPOINT:
862 pszExceptionName = "Breakpoint (don't debug me! :)";
863 break;
864
865 case XCPT_SINGLE_STEP:
866 pszExceptionName = "Single Step (don't debug me! :)";
867 break;
868
869 /* portable, fatal, software-generated exceptions */
870 case XCPT_IN_PAGE_ERROR:
871 pszExceptionName = "In Page Error";
872 sprintf(szData,
873 "at %08x.",
874 pERepRec->ExceptionInfo[0]);
875 fExcptSoftware = TRUE;
876 break;
877
878 case XCPT_PROCESS_TERMINATE:
879 pszExceptionName = "Process Termination";
880 fExcptSoftware = TRUE;
881 break;
882
883 case XCPT_ASYNC_PROCESS_TERMINATE:
884 pszExceptionName = "Process Termination (async)";
885 sprintf(szData,
886 "terminating thread TID=%u",
887 pERepRec->ExceptionInfo[0]);
888 fExcptSoftware = TRUE;
889 break;
890
891 case XCPT_NONCONTINUABLE_EXCEPTION:
892 pszExceptionName = "Noncontinuable Exception";
893 fExcptSoftware = TRUE;
894 break;
895
896 case XCPT_INVALID_DISPOSITION:
897 pszExceptionName = "Invalid Disposition";
898 fExcptSoftware = TRUE;
899 break;
900
901 /* non-portable, fatal exceptions */
902 case XCPT_INVALID_LOCK_SEQUENCE:
903 pszExceptionName = "Invalid Lock Sequence";
904 fExcptSoftware = TRUE;
905 fExcptPortable = FALSE;
906 break;
907
908 case XCPT_ARRAY_BOUNDS_EXCEEDED:
909 pszExceptionName = "Array Bounds Exceeded";
910 fExcptSoftware = TRUE;
911 fExcptPortable = FALSE;
912 break;
913
914 /* unwind operation exceptions */
915 case XCPT_UNWIND:
916 pszExceptionName = "Unwind Exception";
917 fExcptSoftware = TRUE;
918 fExcptPortable = FALSE;
919 break;
920
921 case XCPT_BAD_STACK:
922 pszExceptionName = "Unwind Exception, Bad Stack";
923 fExcptSoftware = TRUE;
924 fExcptPortable = FALSE;
925 break;
926
927 case XCPT_INVALID_UNWIND_TARGET:
928 pszExceptionName = "Unwind Exception, Invalid Target";
929 fExcptSoftware = TRUE;
930 fExcptPortable = FALSE;
931 break;
932
933 /* fatal signal exceptions */
934 case XCPT_SIGNAL:
935 pszExceptionName = "Signal";
936 sprintf(szData,
937 "Signal Number = %08x",
938 pERepRec->ExceptionInfo[0]);
939 fExcptSoftware = TRUE;
940 fExcptPortable = FALSE;
941
942 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
943 {
944 case XCPT_SIGNAL_INTR:
945 pszExceptionName = "Signal (Interrupt)";
946 break;
947
948 case XCPT_SIGNAL_KILLPROC:
949 pszExceptionName = "Signal (Kill Process)";
950 break;
951
952 case XCPT_SIGNAL_BREAK:
953 pszExceptionName = "Signal (Break)";
954 break;
955 }
956 break;
957
958 default:
959 pszExceptionName = "(unknown exception code)";
960 sprintf(szData,
961 "Exception Code = %08x",
962 pERepRec->ExceptionNum);
963 }
964
965
966 /* now dump the information to the logfile */
967 dprintf(("---[Exception Information]------------\n"));
968 sprintf(szData2,
969 " %s (",
970 pszExceptionName);
971
972 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
973 strcat (szData2, "software generated,");
974 else
975 strcat (szData2, "hardware generated,");
976
977 if (fExcptPortable == TRUE) /* portable exception ? */
978 strcat (szData2, "portable,");
979 else
980 strcat (szData2, "non-portable,");
981
982 if (fExcptFatal == TRUE) /* fatal exception ? */
983 strcat (szData2, "fatal");
984 else
985 strcat (szData2, "non-fatal");
986
987 strcat (szData2, /* add trailing brace */
988 ")\n");
989
990
991 dprintf((szData2));
992
993 if (szData[0] != 0) /* see if there is an additional entry */
994 dprintf((" %s\n",
995 szData));
996
997 rc = DosQueryModFromEIP(&ulModule,
998 &ulObject,
999 sizeof(szModule),
1000 szModule,
1001 &ulOffset,
1002 (ULONG)pERepRec->ExceptionAddress);
1003
1004 dprintf((" Exception Address = %08x ",
1005 pERepRec->ExceptionAddress));
1006
1007 if(rc == NO_ERROR && ulObject != -1)
1008 dprintf(("<%s> (#%u), obj #%u:%08x\n",
1009 szModule,
1010 ulModule,
1011 ulObject,
1012 ulOffset));
1013 else
1014 dprintf(("<win32 app>\n"));
1015
1016
1017 rc = DosGetInfoBlocks (&pTIB, /* query kernel information blocks */
1018 &pPIB);
1019 if (rc == NO_ERROR)
1020 {
1021 dprintf((" Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
1022 pTIB->tib_ordinal,
1023 pTIB->tib_ptib2->tib2_ultid,
1024 pTIB->tib_ptib2->tib2_ulpri));
1025
1026 dprintf((" Process: PID: %u, Parent: %u, Status: %u\n",
1027 pPIB->pib_ulpid,
1028 pPIB->pib_ulppid,
1029 pPIB->pib_flstatus));
1030 }
1031
1032 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
1033 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n",
1034 pCtxRec->ctx_SegSs,
1035 pCtxRec->ctx_RegEsp,
1036 pCtxRec->ctx_EFlags));
1037 dprintf((" CS:EIP=%04x:%08x EBP =%08x\n",
1038 pCtxRec->ctx_SegCs,
1039 pCtxRec->ctx_RegEip,
1040 pCtxRec->ctx_RegEbp));
1041
1042 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
1043 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n",
1044 pCtxRec->ctx_RegEax,
1045 pCtxRec->ctx_RegEbx,
1046 pCtxRec->ctx_RegEsi));
1047 dprintf((" ECX=%08x EDX=%08x EDI=%08x\n",
1048 pCtxRec->ctx_RegEcx,
1049 pCtxRec->ctx_RegEdx,
1050 pCtxRec->ctx_RegEdi));
1051
1052 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
1053 dprintf((" DS=%04x ES=%08x",
1054 pCtxRec->ctx_SegDs,
1055 pCtxRec->ctx_SegEs));
1056 dprintf((" FS=%04x GS=%04x\n",
1057 pCtxRec->ctx_SegFs,
1058 pCtxRec->ctx_SegGs));
1059
1060 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1061 {
1062 ULONG ulCounter; /* temporary local counter for fp stack */
1063
1064 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1065 pCtxRec->ctx_env[0],
1066 pCtxRec->ctx_env[1],
1067 pCtxRec->ctx_env[2],
1068 pCtxRec->ctx_env[3]));
1069
1070 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1071 pCtxRec->ctx_env[4],
1072 pCtxRec->ctx_env[5],
1073 pCtxRec->ctx_env[6]));
1074
1075 for (ulCounter = 0;
1076 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1077 ulCounter ++)
1078 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1079 ulCounter,
1080 pCtxRec->ctx_stack[0].losig,
1081 pCtxRec->ctx_stack[0].hisig,
1082 pCtxRec->ctx_stack[0].signexp));
1083 }
1084
1085 dprintf(("---[End Of Exception Information]-----\n"));
1086}
1087
1088/*****************************************************************************
1089 * Name : ERR _System OS2ExceptionHandler
1090 * Purpose :
1091 * Parameters: ...
1092 * Variables :
1093 * Result :
1094 * Remark :
1095 * Status :
1096 *
1097 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1098 *****************************************************************************/
1099 /* from PPC DDK */
1100#ifndef XCPT_CONTINUE_STOP
1101#define XCPT_CONTINUE_STOP 0x00716668
1102#endif
1103
1104ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1105 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1106 PCONTEXTRECORD pCtxRec,
1107 PVOID p)
1108{
1109 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1110 // next dprintf won't wait forever
1111 LogException(ENTER_EXCEPTION);
1112
1113 /* Access violation at a known location */
1114 switch(pERepRec->ExceptionNum)
1115 {
1116 case XCPT_FLOAT_DENORMAL_OPERAND:
1117 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1118 case XCPT_FLOAT_INEXACT_RESULT:
1119// case XCPT_FLOAT_INVALID_OPERATION:
1120 case XCPT_FLOAT_OVERFLOW:
1121 case XCPT_FLOAT_STACK_CHECK:
1122 case XCPT_FLOAT_UNDERFLOW:
1123 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1124 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1125 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1126 {
1127 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1128 {
1129 pCtxRec->ctx_env[0] |= 0x1F;
1130 pCtxRec->ctx_stack[0].losig = 0;
1131 pCtxRec->ctx_stack[0].hisig = 0;
1132 pCtxRec->ctx_stack[0].signexp = 0;
1133 }
1134 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1135 goto continueexecution;
1136 }
1137 else
1138 {
1139 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1140 goto continuesearch;
1141 }
1142
1143 case XCPT_PROCESS_TERMINATE:
1144 case XCPT_ASYNC_PROCESS_TERMINATE:
1145//// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1146 SetExceptionChain((ULONG)-1);
1147 goto continuesearch;
1148
1149 case XCPT_ACCESS_VIOLATION:
1150 {
1151 Win32MemMap *map;
1152 BOOL fWriteAccess = FALSE;
1153 ULONG offset, accessflag;
1154
1155 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1156 goto continueFail;
1157 }
1158
1159//------------->>> WARNING: potentially dangerous workaround!!
1160 /* Some apps set ES = FS and Odin doesn't like that! */
1161 /* Note: maybe we could even check for ES != DS? But maybe */
1162 /* that might cause more harm than good... */
1163 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1164 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1165 /* Let's just reset ES to the DS value and hope it's okay */
1166 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1167 goto continueexecution;
1168 }
1169
1170 switch(pERepRec->ExceptionInfo[0]) {
1171 case XCPT_READ_ACCESS:
1172 accessflag = MEMMAP_ACCESS_READ;
1173 break;
1174 case XCPT_WRITE_ACCESS:
1175 accessflag = MEMMAP_ACCESS_WRITE;
1176 fWriteAccess = TRUE;
1177 break;
1178 case XCPT_EXECUTE_ACCESS:
1179 accessflag = MEMMAP_ACCESS_EXECUTE;
1180 break;
1181 default:
1182 goto continueFail;
1183 }
1184
1185 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1186 if(map == NULL) {
1187 goto continueFail;
1188 }
1189 if(map->commitPage(offset, fWriteAccess) == TRUE)
1190 goto continueexecution;
1191
1192 //no break;
1193 }
1194continueFail:
1195
1196////#define DEBUGSTACK
1197#ifdef DEBUGSTACK
1198 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1199 ULONG *stackptr;
1200 APIRET rc;
1201 int i;
1202 ULONG ulOffset, ulModule, ulObject;
1203 CHAR szModule[CCHMAXPATH];
1204
1205 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1206 dprintf(("Stack DUMP:"));
1207 for(i=0;i<16;i++) {
1208 rc = DosQueryModFromEIP(&ulModule,
1209 &ulObject,
1210 sizeof(szModule),
1211 szModule,
1212 &ulOffset,
1213 (ULONG)*stackptr);
1214
1215 if (rc == NO_ERROR)
1216 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1217 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1218 stackptr++;
1219 }
1220 dprintf(("Stack DUMP END"));
1221 }
1222#endif
1223
1224 case XCPT_BREAKPOINT:
1225 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1226 case XCPT_DATATYPE_MISALIGNMENT:
1227 case XCPT_ILLEGAL_INSTRUCTION:
1228 case XCPT_PRIVILEGED_INSTRUCTION:
1229 case XCPT_INVALID_LOCK_SEQUENCE:
1230 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1231 case XCPT_INTEGER_OVERFLOW:
1232 case XCPT_SINGLE_STEP:
1233 case XCPT_UNABLE_TO_GROW_STACK:
1234 case XCPT_IN_PAGE_ERROR:
1235CrashAndBurn:
1236 //SvL: TODO: this may not always be the right thing to do
1237 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1238 // of this exception handler. We better bail out ASAP or we'll likely
1239 // recurse infinitely until we run out of stack space!!
1240 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1241 goto continuesearch;
1242
1243#ifdef DEBUG
1244 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1245 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1246 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1247 }
1248#endif
1249 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1250 {
1251 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1252 {
1253 goto continueexecution;
1254 }
1255 }
1256 else goto continuesearch; //pass on to OS/2 RTL or app exception handler
1257
1258 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1259 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1260 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1261 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1262 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1263 goto continueexecution;
1264
1265 //@@@PH: growing thread stacks might need special treatment
1266 case XCPT_GUARD_PAGE_VIOLATION:
1267 //SvL: don't print anything here -> fatal hang if happens inside fprintf
1268 //dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue search)"));
1269 goto continuesearch;
1270
1271 case XCPT_SIGNAL:
1272 if(pERepRec->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC) /* resolve signal information */
1273 {
1274 SetExceptionChain((ULONG)-1);
1275 goto continuesearch;
1276 }
1277 goto CrashAndBurn;
1278
1279 default: //non-continuable exceptions
1280 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1281 goto continuesearch;
1282 }
1283continuesearch:
1284 LogException(LEAVE_EXCEPTION);
1285 return XCPT_CONTINUE_SEARCH;
1286
1287continueexecution:
1288 LogException(LEAVE_EXCEPTION);
1289 return XCPT_CONTINUE_EXECUTION;
1290}
1291
1292/*****************************************************************************
1293 * Name : void OS2SetExceptionHandler
1294 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1295 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1296 * Variables :
1297 * Result :
1298 * Remark :
1299 * Status :
1300 *
1301 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1302 *****************************************************************************/
1303void OS2SetExceptionHandler(void *exceptframe)
1304{
1305 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1306
1307 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1308 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1309
1310 /* disable trap popups */
1311// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1312
1313 DosSetExceptionHandler(pExceptRec);
1314 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1315#ifdef DEBUG_ENABLELOG_LEVEL2
1316 PrintExceptionChain();
1317#endif
1318}
1319
1320#ifdef DEBUG
1321void PrintExceptionChain()
1322{
1323 USHORT sel = RestoreOS2FS();
1324 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1325
1326 dprintf(("Exception chain list:"));
1327 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1328 dprintf(("record %x", pExceptRec));
1329 pExceptRec = pExceptRec->prev_structure;
1330 }
1331 SetFS(sel);
1332}
1333
1334void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
1335{
1336 dprintf(("Win32 exception chain:"));
1337 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
1338 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
1339 if (pframe == pframe->Prev) {
1340 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
1341 break;
1342 }
1343 pframe = pframe->Prev;
1344 }
1345}
1346
1347#endif
1348
1349
1350/*****************************************************************************
1351 * Name : void OS2UnsetExceptionHandler
1352 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1353 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1354 * Variables :
1355 * Result :
1356 * Remark :
1357 * Status :
1358 *
1359 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1360 *****************************************************************************/
1361void OS2UnsetExceptionHandler(void *exceptframe)
1362{
1363 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1364
1365 DosUnsetExceptionHandler(pExceptRec);
1366 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1367#ifdef DEBUG_ENABLELOG_LEVEL2
1368 PrintExceptionChain();
1369#endif
1370}
1371
1372void SetOS2ExceptionChain(ULONG val)
1373{
1374 USHORT sel = GetFS();
1375
1376 SetExceptionChain(val);
1377 SetFS(sel);
1378}
1379
1380int _System CheckCurFS()
1381{
1382 USHORT sel = RestoreOS2FS();
1383 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1384
1385 if(sel == 0x150b) {
1386 SetFS(sel);
1387 return FALSE;
1388 }
1389 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1390 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1391 SetFS(sel);
1392 return FALSE;
1393 }
1394 SetFS(sel);
1395 return TRUE;
1396}
1397
Note: See TracBrowser for help on using the repository browser.