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

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

only log fatal exceptions

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