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

Last change on this file since 8548 was 8548, checked in by sandervl, 23 years ago

LogExcpetion: check lockcount before changing it on entry

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