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

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

Cleaned up memory map code

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