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

Last change on this file since 7202 was 7202, checked in by sandervl, 24 years ago

No longer use DosError; IOCTL_DISK_GET_DRIVE_GEOMETRY must return ERROR_MEDIA_CHANGED when floppy has been changed

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