source: trunk/src/kernel32/exceptions.cpp

Last change on this file was 22004, checked in by dmik, 13 years ago

kernel32: Pick up register changes in try/except filter.

This is a regression of r21999. Fixes endless exceptions eventually
leading to program termination.

File size: 72.2 KB
Line 
1/* $Id: exceptions.cpp,v 1.74 2004-01-20 13:41:10 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_WIN
55#define INCL_WINBUTTONS
56#include <os2wrap.h> //Odin32 OS/2 api wrappers
57#include <stdio.h>
58#include <stdlib.h>
59#include <assert.h>
60#include <time.h>
61#include <string.h>
62#include <pmscan.h>
63#include "exceptions.h"
64#include "exceptutil.h"
65#include <misc.h>
66#include "mmap.h"
67#include <wprocess.h>
68#include <win32api.h>
69#include "oslibexcept.h"
70#include "oslibmem.h"
71#include "exceptstackdump.h"
72#include "hmthread.h"
73
74#include "WinImageBase.h"
75#include "WinDllBase.h"
76#include "WinExeBase.h"
77
78/* Really lazy! But, including wincon.h means lot's of missing COORD. */
79#define CTRL_C_EVENT 0 //#include <wincon.h>
80#define CTRL_BREAK_EVENT 1 //#include <wincon.h>
81#include "console.h"
82#include "initterm.h"
83
84
85#define DBG_LOCALLOG DBG_exceptions
86#include "dbglocal.h"
87
88#include <_ras.h>
89
90#ifdef WITH_KLIB
91/* quick and dirty - don't wanna mess with includes. */
92typedef enum { enmRead, enmWrite, enmUnknown } ENMACCESS;
93BOOL _Optlink kHeapDbgException(void * pvAccess,
94 ENMACCESS enmAccess,
95 void * pvIP,
96 void * pvOS);
97#endif
98
99/* Exception record for handling exceptions happening inside exception handlers */
100typedef struct
101{
102 WINEXCEPTION_FRAME frame;
103 WINEXCEPTION_FRAME *prevFrame;
104} EXC_NESTED_FRAME;
105
106//Global Process Unhandled exception filter
107static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL;
108static UINT CurrentErrorMode = 0;
109static PEXCEPTION_HANDLER StartupCodeHandler = NULL;
110
111extern "C" {
112
113PWINEXCEPTION_FRAME GetExceptionRecord(ULONG offset, ULONG segment);
114
115LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo);
116void KillWin32Process(void);
117
118static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec,
119 PEXCEPTIONREGISTRATIONRECORD pERegRec,
120 PCONTEXTRECORD pCtxRec, PVOID p, PSZ szTrapDump);
121
122int __cdecl __seh_handler(PVOID pRec, PVOID pFrame,
123 PVOID pContext, PVOID pVoid);
124
125int __cdecl __seh_handler_win32(PWINEXCEPTION_RECORD pRec,
126 PWINEXCEPTION_FRAME pFrame,
127 PCONTEXTRECORD pContext, PVOID pVoid);
128
129PWINEXCEPTION_FRAME __cdecl __seh_get_prev_frame_win32(PWINEXCEPTION_FRAME pFrame);
130
131#ifdef DEBUG
132static void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe);
133#else
134#define PrintWin32ExceptionChain(a)
135#endif
136
137/*****************************************************************************
138 * Name : UINT SetErrorMode
139 * Purpose :
140 * Parameters: UINT fuErrorMode
141 * Variables :
142 * Result :
143 * Remark :
144 * Status :
145 *
146 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
147 *****************************************************************************/
148
149UINT WIN32API SetErrorMode(UINT fuErrorMode)
150{
151 UINT oldmode = CurrentErrorMode;
152
153 dprintf(("KERNEL32: SetErrorMode(%08xh)\n",
154 fuErrorMode));
155 CurrentErrorMode = fuErrorMode;
156
157 if(fuErrorMode & SEM_FAILCRITICALERRORS || fuErrorMode & SEM_NOOPENFILEERRORBOX)
158 DosError(FERR_DISABLEHARDERR);
159 else
160 DosError(FERR_ENABLEHARDERR);
161
162 // SEM_NOGPFAULTERRORBOX and SEM_NOALIGNMENTFAULTEXCEPT --> UnhandledExceptionFilter()
163
164 return(oldmode);
165}
166
167#ifdef __EMX__
168static inline WINEXCEPTION_FRAME * EXC_push_frame( WINEXCEPTION_FRAME *frame )
169{
170 // TODO: rewrite in assembly
171 TEB *teb = GetThreadTEB();
172 frame->Prev = (PWINEXCEPTION_FRAME)teb->except;
173 teb->except = frame;
174 return frame->Prev;
175}
176
177static inline WINEXCEPTION_FRAME * EXC_pop_frame( WINEXCEPTION_FRAME *frame )
178{
179 // TODO: rewrite in assembly
180 TEB *teb = GetThreadTEB();
181 teb->except = frame->Prev;
182 return frame->Prev;
183}
184#endif
185
186/*****************************************************************************
187 * Name : VOID __cdecl OS2RaiseException
188 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
189 * Parameters: ...
190 * Variables :
191 * Result :
192 * Remark :
193 * Status :
194 *
195 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
196 *****************************************************************************/
197
198void WIN32API RtlRaiseException(WINEXCEPTION_RECORD *rec, WINCONTEXT *context);
199
200VOID __cdecl OS2RaiseException(DWORD dwExceptionCode,
201 DWORD dwExceptionFlags,
202 DWORD cArguments,
203 DWORD *lpArguments,
204 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
205 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
206 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
207 DWORD es, DWORD fs, DWORD gs, DWORD ss)
208{
209 WINEXCEPTION_RECORD record;
210 WINEXCEPTION_POINTERS ExceptionInfo;
211 WINCONTEXT context;
212 int rc;
213 int i;
214
215 dprintf(("KERNEL32: RaiseException(%08xh)\n",
216 dwExceptionCode));
217
218 memset(&record, 0, sizeof(record));
219
220 /* compose an exception record */
221 record.ExceptionCode = dwExceptionCode;
222 record.ExceptionFlags = dwExceptionFlags;
223 record.ExceptionRecord = NULL;
224 record.NumberParameters = cArguments;
225 record.ExceptionAddress = (LPVOID)eip;
226
227 memset(&context, 0, sizeof(context));
228 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
229 context.SegGs = gs;
230 context.SegFs = fs;
231 context.SegEs = es;
232 context.SegDs = ds;
233 context.Edi = edi;
234 context.Esi = esi;
235 context.Ebx = ebx;
236 context.Edx = edx;
237 context.Ecx = ecx;
238 context.Eax = eax;
239 context.Ebp = ebp;
240 context.Eip = eip;
241 context.SegCs = cs;
242 context.EFlags = flags;
243 context.Esp = esp;
244 context.SegSs = ss;
245
246 if(lpArguments)
247 {
248 for(i=0;
249 i<cArguments;
250 i++)
251 record.ExceptionInformation[i] = lpArguments[i];
252 }
253
254 rc = RtlDispatchException(&record, &context);
255
256 // and finally, the unhandled exception filter
257 if(rc == ExceptionContinueSearch && UnhandledExceptionFilter != NULL)
258 {
259 dprintf(("KERNEL32: RaiseException calling UnhandledExceptionFilter.\n"));
260
261 ExceptionInfo.ExceptionRecord = &record;
262 ExceptionInfo.ContextRecord = &context;
263
264 rc = UnhandledExceptionFilter(&ExceptionInfo);
265 //FIXME: UnhandledExceptionFilter does NOT return the same values as
266 // other filters!!
267 }
268
269 // terminate the process
270 if(rc != ExceptionContinueExecution ||
271 record.ExceptionFlags & EH_NONCONTINUABLE)
272 {
273 dprintf(("KERNEL32: RaiseException terminating process.\n"));
274 DosExit(EXIT_PROCESS, 0);
275 }
276
277 dprintf(("KERNEL32: RaiseException returns.\n"));
278 return;
279}
280
281/*******************************************************************
282 * EXC_RaiseHandler
283 *
284 * Handler for exceptions happening inside a handler.
285 */
286static DWORD WIN32API EXC_RaiseHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
287// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
288 WINCONTEXT *context, LPVOID dispatcher )
289{
290 if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
291 return ExceptionContinueSearch;
292 /* We shouldn't get here so we store faulty frame in dispatcher */
293 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
294 return ExceptionNestedException;
295}
296
297/*******************************************************************
298 * EXC_UnwindHandler
299 *
300 * Handler for exceptions happening inside an unwind handler.
301 */
302static DWORD WIN32API EXC_UnwindHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
303// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
304 WINCONTEXT *context, LPVOID dispatcher )
305{
306 if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
307 return ExceptionContinueSearch;
308 /* We shouldn't get here so we store faulty frame in dispatcher */
309 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
310 return ExceptionCollidedUnwind;
311}
312
313#ifndef __EMX__
314extern "C"
315DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
316 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
317 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler);
318
319#else
320/*******************************************************************
321 * EXC_CallHandler
322 *
323 * Call an exception handler, setting up an exception frame to catch exceptions
324 * happening during the handler execution.
325 * WARNING:
326 * Please do not change the first 4 parameters order in any way - some exceptions handlers
327 * rely on Base Pointer (EBP) to have a fixed position related to the exception frame
328 */
329static DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
330 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
331 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler)
332{
333 EXC_NESTED_FRAME newframe;
334 DWORD ret;
335
336 newframe.frame.Handler = nested_handler;
337 newframe.prevFrame = frame;
338 EXC_push_frame( &newframe.frame );
339 dprintf(("KERNEL32: Calling handler at %p code=%lx flags=%lx\n",
340 handler, record->ExceptionCode, record->ExceptionFlags));
341 ret = handler( record, frame, context, dispatcher );
342 dprintf(("KERNEL32: Handler returned %lx\n", ret));
343 EXC_pop_frame( &newframe.frame );
344 return ret;
345}
346#endif
347//******************************************************************************
348//******************************************************************************
349DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext)
350{
351 PWINEXCEPTION_FRAME pFrame, pPrevFrame, dispatch, nested_frame;
352 int rc;
353
354 // get chain of exception frames
355 rc = ExceptionContinueSearch;
356
357 nested_frame = NULL;
358 TEB *winteb = GetThreadTEB();
359 pFrame = (PWINEXCEPTION_FRAME)winteb->except;
360
361 dprintf(("KERNEL32: RtlDispatchException entered"));
362
363 PrintWin32ExceptionChain(pFrame);
364
365 // walk the exception chain
366 while( (pFrame != NULL) && ((ULONG)((ULONG)pFrame & 0xFFFFF000) != 0xFFFFF000) )
367 {
368 pPrevFrame = __seh_get_prev_frame_win32(pFrame);
369
370 dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X",
371 pFrame, pPrevFrame));
372 if (pFrame == pPrevFrame) {
373 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
374 return 0;
375 }
376
377 dispatch=0;
378
379 /* Check frame address */
380 if (((void*)pFrame < winteb->stack_low) ||
381 ((void*)(pFrame+1) > winteb->stack_top) ||
382 (int)pFrame & 3)
383 {
384 dprintf(("Invalid stack! low=%08X, top=%08X, pframe = %08X",
385 winteb->stack_low, winteb->stack_top, pFrame));
386
387 pRecord->ExceptionFlags |= EH_STACK_INVALID;
388 break;
389 }
390
391
392 /* call handler */
393 if (pFrame->Handler)
394 {
395 rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch,
396 pFrame->Handler, EXC_RaiseHandler);
397 }
398 else
399 {
400 dprintf(("pFrame->Handler is NULL!!!!!"));
401 rc = ExceptionContinueSearch;
402 }
403
404 PrintWin32ExceptionChain(pFrame);
405
406 if (pFrame == nested_frame)
407 {
408 /* no longer nested */
409 nested_frame = NULL;
410 pRecord->ExceptionFlags &= ~EH_NESTED_CALL;
411 }
412
413
414 switch(rc)
415 {
416 case ExceptionContinueExecution:
417 if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE))
418 {
419 dprintf(("KERNEL32: RtlDispatchException returns %#x (ContinueExecution)", rc));
420 return rc;
421 }
422 break;
423 case ExceptionContinueSearch:
424 break;
425 case ExceptionNestedException:
426 if (nested_frame < dispatch) nested_frame = dispatch;
427 pRecord->ExceptionFlags |= EH_NESTED_CALL;
428 break;
429 default:
430 break;
431 }
432
433 dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X",
434 pFrame, pPrevFrame));
435 if (pFrame == pPrevFrame)
436 {
437 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
438 break;
439 }
440 pFrame = pPrevFrame;
441 }
442 dprintf(("KERNEL32: RtlDispatchException returns %#x", rc));
443 PrintWin32ExceptionChain(pFrame);
444 return rc;
445}
446/*****************************************************************************
447 * Name : int __cdecl OS2RtlUnwind
448 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
449 * Parameters: ...
450 * Variables :
451 * Result :
452 * Remark :
453 * Status :
454 *
455 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
456 *****************************************************************************/
457
458int __cdecl OS2RtlUnwind(PWINEXCEPTION_FRAME pEndFrame,
459 LPVOID unusedEip,
460 PWINEXCEPTION_RECORD pRecord,
461 DWORD returnEax,
462 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
463 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
464 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
465 DWORD es, DWORD fs, DWORD gs, DWORD ss)
466{
467 PWINEXCEPTION_FRAME frame, prevFrame, dispatch;
468 WINEXCEPTION_RECORD record; //, newrec;
469 WINCONTEXT context;
470 DWORD rc;
471
472 dprintf(("KERNEL32: RtlUnwind pEndFrame=%08X, unusedEip=%08X, pRecord=%08X, returnEax=%#x\n", pEndFrame, unusedEip, pRecord, returnEax));
473
474 TEB *winteb = GetThreadTEB();
475 if (!winteb)
476 {
477 dprintf(("KERNEL32: RtlUnwind TEB is NULL\n"));
478 DebugInt3();
479 return 0;
480 }
481
482 memset(&context, 0, sizeof(context));
483 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
484 context.SegGs = gs;
485 context.SegFs = fs;
486 context.SegEs = es;
487 context.SegDs = ds;
488 context.Edi = edi;
489 context.Esi = esi;
490 context.Ebx = ebx;
491 context.Edx = edx;
492 context.Ecx = ecx;
493 context.Eax = returnEax;
494 context.Ebp = ebp;
495 context.Eip = eip;
496 context.SegCs = cs;
497 context.EFlags = flags;
498 context.Esp = esp;
499 context.SegSs = ss;
500
501 /* build an exception record, if we do not have one */
502 if(!pRecord)
503 {
504 memset(&record, 0, sizeof(record));
505 record.ExceptionCode = STATUS_UNWIND;
506 record.ExceptionFlags = 0;
507 record.ExceptionRecord = NULL;
508 record.ExceptionAddress = (LPVOID)eip;
509 record.NumberParameters = 0;
510 pRecord = &record;
511 }
512
513 if(pEndFrame) pRecord->ExceptionFlags |= EH_UNWINDING;
514 else pRecord->ExceptionFlags |= EH_UNWINDING | EH_EXIT_UNWIND;
515
516 /* get chain of exception frames */
517 frame = (PWINEXCEPTION_FRAME)winteb->except;
518
519 PrintWin32ExceptionChain(frame);
520
521 while (((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) && (frame != pEndFrame))
522 {
523 prevFrame = __seh_get_prev_frame_win32(frame);
524
525 /* Check frame address */
526 if (pEndFrame && (frame > pEndFrame))
527 {
528#if 0
529 // TODO
530 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
531 newrec.ExceptionFlags = EH_NONCONTINUABLE;
532 newrec.ExceptionRecord = pRecord;
533 newrec.NumberParameters = 0;
534 RtlRaiseException(&newrec, NULL);
535#else
536 dprintf(("KERNEL32: RtlUnwind terminating thread (invalid target).\n"));
537 DosExit(EXIT_THREAD, 0);
538#endif
539 }
540 if (((void*)frame < winteb->stack_low) ||
541 ((void*)(frame+1) > winteb->stack_top) ||
542 (int)frame & 3)
543 {
544#if 0
545 // TODO
546 newrec.ExceptionCode = STATUS_BAD_STACK;
547 newrec.ExceptionFlags = EH_NONCONTINUABLE;
548 newrec.ExceptionRecord = pRecord;
549 newrec.NumberParameters = 0;
550#else
551 dprintf(("KERNEL32: RtlUnwind terminating thread (bad stack).\n"));
552 DosExit(EXIT_THREAD, 0);
553#endif
554 }
555
556 /* Call handler */
557 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler));
558 if(frame->Handler) {
559 // ensure the Win32 FS (may be accessed directly in the handler)
560 DWORD oldsel = SetReturnFS(winteb->teb_sel);
561 rc = EXC_CallHandler(pRecord, frame, &context, &dispatch, frame->Handler, EXC_UnwindHandler );
562 // restore FS
563 SetFS(oldsel);
564 }
565 else {
566 dprintf(("pFrame->Handler is NULL!!!!!"));
567 rc = ExceptionContinueSearch;
568 }
569 dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc));
570 switch (rc)
571 {
572 case ExceptionContinueSearch:
573 break;
574 case ExceptionCollidedUnwind:
575 frame = dispatch;
576 break;
577 default:
578#if 0
579 // TODO
580 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;
581 newrec.ExceptionFlags = EH_NONCONTINUABLE;
582 newrec.ExceptionRecord = pRecord;
583 newrec.NumberParameters = 0;
584#else
585 dprintf(("KERNEL32: RtlUnwind terminating thread (invalid disposition).\n"));
586 DosExit(EXIT_THREAD, 0);
587#endif
588 break;
589 }
590 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, prevFrame));
591 winteb->except = (void*)prevFrame;
592 frame = prevFrame;
593 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame,
594 ((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) ?
595 __seh_get_prev_frame_win32(frame) : (void*)0xFFFFFFFF));
596 }
597
598 dprintf(("KERNEL32: RtlUnwind returning.\n"));
599 PrintWin32ExceptionChain(frame);
600 return(0);
601}
602
603
604/*****************************************************************************
605 * Name : LONG WIN32API UnhandledExceptionFilter
606 * Purpose :
607 * Parameters: ...
608 * Variables :
609 * Result :
610 * Remark :
611 * Status :
612 *
613 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
614 *****************************************************************************/
615
616LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo)
617{
618 char szModName[16];
619 char message[128];
620 ULONG iObj;
621 ULONG offObj;
622 HMODULE hmod;
623 DWORD rc;
624
625 dprintf(("KERNEL32: Default UnhandledExceptionFilter, CurrentErrorMode=%X", CurrentErrorMode));
626
627 // We must not care about ErrorMode here!! The app expects that its own
628 // UnhandledExceptionFilter will be cared even if it never touched ErrorMode.
629 if(CurrentUnhExceptionFlt) // && !(CurrentErrorMode & (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)))
630 {
631 dprintf(("KERNEL32: Calling user UnhandledExceptionFilter"));
632 rc = CurrentUnhExceptionFlt(lpexpExceptionInfo);
633 if(rc != WINEXCEPTION_CONTINUE_SEARCH)
634 return rc;
635 }
636
637 if (DosQueryModFromEIP(&hmod, &iObj, sizeof(szModName), szModName, &offObj, (ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress))
638 sprintf(message, "Unhandled exception 0x%08lx at address 0x%08lx. (DQMFEIP rc=%d)",
639 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
640 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
641 else
642 {
643 if (iObj == -1)
644 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
645 Win32ImageBase * pMod;
646 if (WinExe && WinExe->insideModule((ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress))
647 pMod = WinExe;
648 else
649 pMod = Win32DllBase::findModuleByAddr((ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
650 if (pMod != NULL)
651 {
652 szModName[0] = '\0';
653 strncat(szModName, pMod->getModuleName(), sizeof(szModName) - 1);
654 iObj = 0xFF;
655 offObj = (ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress
656 - (ULONG)pMod->getInstanceHandle();
657 }
658 }
659 sprintf(message,
660 "Unhandled exception 0x%08lx at address 0x%08lx.\r"
661 "Mod: %s obj: 0x%2lx off:0x%08lx",
662 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
663 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress,
664 szModName, iObj, offObj);
665 }
666
667/* This is very dangerous. Can hang PM.
668 rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, message, "Application Error",
669 0, MB_ABORTRETRYIGNORE | MB_ERROR);
670 switch (rc)
671 {
672 case MBID_IGNORE:
673 return WINEXCEPTION_CONTINUE_EXECUTION;
674
675 case MBID_ABORT:
676 case MBID_RETRY:
677 default:
678 return WINEXCEPTION_EXECUTE_HANDLER;
679 }
680*/
681 return WINEXCEPTION_EXECUTE_HANDLER;
682}
683/*****************************************************************************
684 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
685 * Purpose :
686 * Parameters: ...
687 * Variables :
688 * Result :
689 * Remark :
690 * Status :
691 *
692 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
693 *****************************************************************************/
694
695LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
696{
697 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
698
699 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n",
700 lpTopLevelExceptionFilter));
701
702 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
703
704 return(old);
705}
706
707
708/*****************************************************************************
709 * Name : KillWin32Process
710 * Purpose :
711 * Parameters: ...
712 * Variables :
713 * Result :
714 * Remark :
715 * Status :
716 *
717 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
718 *****************************************************************************/
719
720
721//******************************************************************************
722VOID WIN32API ExitProcess(DWORD exitcode);
723//******************************************************************************
724void KillWin32Process(void)
725{
726 static BOOL fEntry = FALSE;
727
728 if(!fExitProcess && fEntry == FALSE) {
729 fEntry = TRUE;
730 ExitProcess(666);
731 return;
732 }
733 //Restore original OS/2 TIB selector
734 RestoreOS2FS();
735
736 DosExit(EXIT_PROCESS, 666);
737}
738//*****************************************************************************
739//*****************************************************************************
740void KillWin32Thread(void)
741{
742// ExitThread(666);
743 //Restore original OS/2 TIB selector
744 RestoreOS2FS();
745
746 DosExit(EXIT_THREAD, 666);
747}
748//*****************************************************************************
749//*****************************************************************************
750static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec,
751 PEXCEPTIONREGISTRATIONRECORD pERegRec,
752 PCONTEXTRECORD pCtxRec,
753 PVOID p,
754 PSZ szTrapDump)
755{
756 if(pERepRec->ExceptionNum == XCPT_GUARD_PAGE_VIOLATION)
757 {
758 strcpy(szTrapDump, "Guard Page Violation");
759 return;
760 }
761
762 PCSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
763 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
764 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
765 BOOL fExcptFatal = TRUE; /* fatal exception ? */
766 BOOL fExcptPortable = TRUE; /* portability of exception */
767 PPIB pPIB; /* process information block */
768 PTIB pTIB; /* thread information block */
769 ULONG ulModule; /* module number */
770 ULONG ulObject; /* object number within the module */
771 CHAR szModule[260]; /* buffer for the module name */
772 ULONG ulOffset; /* offset within the object within the module */
773 char szLineException[512];
774 char szLineExceptionType[128];
775
776 szLineException[0] = 0; /* initialize */
777 szLineExceptionType[0] = 0; /* initialize */
778 switch(pERepRec->ExceptionNum) /* take according action */
779 {
780 /* portable, non-fatal software-generated exceptions */
781 case XCPT_GUARD_PAGE_VIOLATION:
782 strcpy(szLineException, "Guard Page Violation");
783 sprintf(szLineExceptionType, "R/W %08xh at %08xh.", pERepRec->ExceptionInfo[0], pERepRec->ExceptionInfo[1]);
784 fExcptSoftware = TRUE;
785 fExcptFatal = FALSE;
786 rc = XCPT_CONTINUE_EXECUTION;
787 break;
788
789 case XCPT_UNABLE_TO_GROW_STACK:
790 strcpy(szLineException, "Unable To Grow Stack");
791 fExcptSoftware = TRUE;
792 fExcptFatal = FALSE;
793 rc = XCPT_CONTINUE_EXECUTION;
794 break;
795
796 /* portable, fatal, hardware-generated exceptions */
797 case XCPT_ACCESS_VIOLATION:
798 strcpy(szLineException, "Access Violation");
799 switch (pERepRec->ExceptionInfo[0])
800 {
801 case XCPT_READ_ACCESS:
802 sprintf (szLineExceptionType, "Read Access at address %08xh", pERepRec->ExceptionInfo[1]);
803 break;
804
805 case XCPT_WRITE_ACCESS:
806 sprintf (szLineExceptionType, "Write Access at address %08x", pERepRec->ExceptionInfo[1]);
807 break;
808
809 case XCPT_SPACE_ACCESS:
810 sprintf (szLineExceptionType, "Space Access at selector %08x", pERepRec->ExceptionInfo[1]);
811 break;
812
813 case XCPT_LIMIT_ACCESS:
814 strcpy (szLineExceptionType, "Limit Access");
815 break;
816
817 case XCPT_UNKNOWN_ACCESS:
818 strcpy (szLineExceptionType, "Unknown Access");
819 break;
820
821 default:
822 strcpy (szLineExceptionType, "(Invalid Access Code)");
823 break;
824 }
825 break;
826
827 case XCPT_INTEGER_DIVIDE_BY_ZERO:
828 strcpy(szLineException, "Division By Zero (Integer)");
829 break;
830
831 case XCPT_FLOAT_DIVIDE_BY_ZERO:
832 strcpy(szLineException, "Division By Zero (Float)");
833 break;
834
835 case XCPT_FLOAT_INVALID_OPERATION:
836 strcpy(szLineException, "Invalid Floating Point Operation");
837 break;
838
839 case XCPT_ILLEGAL_INSTRUCTION:
840 strcpy(szLineException, "Illegal Instruction");
841 break;
842
843 case XCPT_PRIVILEGED_INSTRUCTION:
844 strcpy(szLineException, "Privileged Instruction");
845 break;
846
847 case XCPT_INTEGER_OVERFLOW:
848 strcpy(szLineException, "Integer Overflow");
849 break;
850
851 case XCPT_FLOAT_OVERFLOW:
852 strcpy(szLineException, "Floating Point Overflow");
853 break;
854
855 case XCPT_FLOAT_UNDERFLOW:
856 strcpy(szLineException, "Floating Point Underflow");
857 break;
858
859 case XCPT_FLOAT_DENORMAL_OPERAND:
860 strcpy(szLineException, "Floating Point Denormal Operand");
861 break;
862
863 case XCPT_FLOAT_INEXACT_RESULT:
864 strcpy(szLineException, "Floating Point Inexact Result");
865 break;
866
867 case XCPT_FLOAT_STACK_CHECK:
868 strcpy(szLineException, "Floating Point Stack Check");
869 break;
870
871 case XCPT_DATATYPE_MISALIGNMENT:
872 strcpy(szLineException, "Datatype Misalignment");
873 sprintf(szLineExceptionType, "R/W %08x alignment %08x at %08x.", pERepRec->ExceptionInfo[0],
874 pERepRec->ExceptionInfo[1], pERepRec->ExceptionInfo[2]);
875 break;
876
877 case XCPT_BREAKPOINT:
878 strcpy(szLineException, "Breakpoint (DEBUG)");
879 break;
880
881 case XCPT_SINGLE_STEP:
882 strcpy(szLineException, "Single Step (DEBUG)");
883 break;
884
885 /* portable, fatal, software-generated exceptions */
886 case XCPT_IN_PAGE_ERROR:
887 strcpy(szLineException, "In Page Error");
888 sprintf(szLineExceptionType, "at %08x.", pERepRec->ExceptionInfo[0]);
889 fExcptSoftware = TRUE;
890 break;
891
892 case XCPT_PROCESS_TERMINATE:
893 strcpy(szLineException, "Process Termination");
894 fExcptSoftware = TRUE;
895 break;
896
897 case XCPT_ASYNC_PROCESS_TERMINATE:
898 strcpy(szLineException, "Process Termination (async)");
899 sprintf(szLineExceptionType, "terminating thread TID=%u", pERepRec->ExceptionInfo[0]);
900 fExcptSoftware = TRUE;
901 break;
902
903 case XCPT_NONCONTINUABLE_EXCEPTION:
904 strcpy(szLineException, "Noncontinuable Exception");
905 fExcptSoftware = TRUE;
906 break;
907
908 case XCPT_INVALID_DISPOSITION:
909 strcpy(szLineException, "Invalid Disposition");
910 fExcptSoftware = TRUE;
911 break;
912
913 /* non-portable, fatal exceptions */
914 case XCPT_INVALID_LOCK_SEQUENCE:
915 strcpy(szLineException, "Invalid Lock Sequence");
916 fExcptSoftware = TRUE;
917 fExcptPortable = FALSE;
918 break;
919
920 case XCPT_ARRAY_BOUNDS_EXCEEDED:
921 strcpy(szLineException, "Array Bounds Exceeded");
922 fExcptSoftware = TRUE;
923 fExcptPortable = FALSE;
924 break;
925
926 /* unwind operation exceptions */
927 case XCPT_UNWIND:
928 strcpy(szLineException, "Unwind Exception");
929 fExcptSoftware = TRUE;
930 fExcptPortable = FALSE;
931 break;
932
933 case XCPT_BAD_STACK:
934 strcpy(szLineException, "Unwind Exception, Bad Stack");
935 fExcptSoftware = TRUE;
936 fExcptPortable = FALSE;
937 break;
938
939 case XCPT_INVALID_UNWIND_TARGET:
940 strcpy(szLineException, "Unwind Exception, Invalid Target");
941 fExcptSoftware = TRUE;
942 fExcptPortable = FALSE;
943 break;
944
945 /* fatal signal exceptions */
946 case XCPT_SIGNAL:
947 strcpy(szLineException, "Signal");
948 sprintf(szLineExceptionType, "Signal Number = %08x", pERepRec->ExceptionInfo[0]);
949 fExcptSoftware = TRUE;
950 fExcptPortable = FALSE;
951
952 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
953 {
954 case XCPT_SIGNAL_INTR:
955 strcpy(szLineException, "Signal (Interrupt)");
956 break;
957
958 case XCPT_SIGNAL_KILLPROC:
959 strcpy(szLineException, "Signal (Kill Process)");
960 break;
961
962 case XCPT_SIGNAL_BREAK:
963 strcpy(szLineException, "Signal (Break)");
964 break;
965 }
966 break;
967
968 default:
969 strcpy(szLineException, "(unknown exception code)");
970 sprintf(szLineExceptionType, "Exception Code = %08x", pERepRec->ExceptionNum);
971 break;
972 }
973
974 sprintf(szTrapDump, "---[Exception Information]------------\n %s (", szLineException);
975
976 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
977 strcat (szTrapDump, "software generated,");
978 else
979 strcat (szTrapDump, "hardware generated,");
980
981 if (fExcptPortable == TRUE) /* portable exception ? */
982 strcat (szTrapDump, "portable,");
983 else
984 strcat (szTrapDump, "non-portable,");
985
986 if (fExcptFatal == TRUE) /* fatal exception ? */
987 strcat (szTrapDump, "fatal");
988 else
989 strcat (szTrapDump, "non-fatal");
990
991 strcat(szTrapDump, ")\n"); /* add trailing brace */
992
993 if (szLineExceptionType[0])
994 sprintf(szTrapDump + strlen(szTrapDump), " %s\n", szLineExceptionType);
995
996 sprintf(szLineException, " Exception Address = %08x ", pERepRec->ExceptionAddress);
997 strcat(szTrapDump, szLineException);
998
999 rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
1000 szModule, &ulOffset, (ULONG)pERepRec->ExceptionAddress);
1001
1002 if(rc == NO_ERROR && ulObject != -1)
1003 {
1004 sprintf(szLineException, "<%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject + 1, ulOffset);
1005#ifdef RAS
1006 char szSYMInfo[260];
1007
1008 DosQueryModuleName(ulModule, sizeof(szModule), szModule);
1009
1010 int namelen = strlen(szModule);
1011 if(namelen > 3)
1012 {
1013 strcpy(szModule + namelen - 3, "SYM");
1014 dbgGetSYMInfo(szModule, ulObject, ulOffset, szSYMInfo, sizeof (szSYMInfo),
1015 FALSE);
1016 strcat(szLineException, " ");
1017 strcat(szLineException, szSYMInfo);
1018 }
1019#else
1020 strcat(szLineException, "\n");
1021#endif
1022 strcat(szTrapDump, szLineException);
1023 }
1024 else
1025 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
1026 Win32ImageBase * pMod;
1027 if (WinExe && WinExe->insideModule((ULONG)pERepRec->ExceptionAddress))
1028 pMod = WinExe;
1029 else
1030 pMod = Win32DllBase::findModuleByAddr((ULONG)pERepRec->ExceptionAddress);
1031 if (pMod != NULL)
1032 {
1033 szModule[0] = '\0';
1034 strncat(szModule, pMod->getModuleName(), sizeof(szModule) - 1);
1035 ulObject = 0xFF;
1036 ulOffset = (ULONG)pERepRec->ExceptionAddress - (ULONG)pMod->getInstanceHandle();
1037 sprintf(szLineException, "<%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject, ulOffset);
1038 }
1039 else sprintf(szLineException, "<unknown win32 module>\n");
1040
1041 strcat(szTrapDump, szLineException);
1042 }
1043
1044 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1045 if (rc == NO_ERROR)
1046 {
1047 sprintf(szLineException, " Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
1048 pTIB->tib_ordinal, pTIB->tib_ptib2->tib2_ultid, pTIB->tib_ptib2->tib2_ulpri);
1049 strcat(szTrapDump, szLineException);
1050
1051 sprintf(szLineException, " Process: PID: %u, Parent: %u, Status: %u\n", pPIB->pib_ulpid,
1052 pPIB->pib_ulppid, pPIB->pib_flstatus);
1053 strcat(szTrapDump, szLineException);
1054 }
1055
1056 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) { /* check flags */
1057 sprintf(szLineException, " SS:ESP=%04x:%08x EFLAGS=%08x\n", pCtxRec->ctx_SegSs, pCtxRec->ctx_RegEsp,
1058 pCtxRec->ctx_EFlags);
1059 strcat(szTrapDump, szLineException);
1060 sprintf(szLineException, " CS:EIP=%04x:%08x EBP =%08x\n", pCtxRec->ctx_SegCs, pCtxRec->ctx_RegEip,
1061 pCtxRec->ctx_RegEbp);
1062 strcat(szTrapDump, szLineException);
1063 }
1064
1065 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) { /* check flags */
1066 sprintf(szLineException, " EAX=%08x EBX=%08x ESI=%08x\n", pCtxRec->ctx_RegEax, pCtxRec->ctx_RegEbx,
1067 pCtxRec->ctx_RegEsi);
1068 strcat(szTrapDump, szLineException);
1069 sprintf(szLineException, " ECX=%08x EDX=%08x EDI=%08x\n", pCtxRec->ctx_RegEcx, pCtxRec->ctx_RegEdx,
1070 pCtxRec->ctx_RegEdi);
1071 strcat(szTrapDump, szLineException);
1072 }
1073
1074 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) { /* check flags */
1075 sprintf(szLineException, " DS=%04x ES=%08x FS=%04x GS=%04x\n", pCtxRec->ctx_SegDs, pCtxRec->ctx_SegEs, pCtxRec->ctx_SegFs, pCtxRec->ctx_SegGs);
1076 strcat(szTrapDump, szLineException);
1077 }
1078
1079 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1080 {
1081 ULONG ulCounter; /* temporary local counter for fp stack */
1082
1083 sprintf(szLineException, " Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1084 pCtxRec->ctx_env[0], pCtxRec->ctx_env[1],
1085 pCtxRec->ctx_env[2], pCtxRec->ctx_env[3]);
1086 strcat(szTrapDump, szLineException);
1087
1088 sprintf(szLineException, " Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1089 pCtxRec->ctx_env[4], pCtxRec->ctx_env[5], pCtxRec->ctx_env[6]);
1090 strcat(szTrapDump, szLineException);
1091
1092 for (ulCounter = 0; ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1093 ulCounter ++)
1094 {
1095 sprintf(szLineException, " FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1096 ulCounter, pCtxRec->ctx_stack[0].losig, pCtxRec->ctx_stack[0].hisig,
1097 pCtxRec->ctx_stack[0].signexp);
1098 strcat(szTrapDump, szLineException);
1099 }
1100 }
1101 sprintf(szLineException, "---[End Of Exception Information]-----\n");
1102 strcat(szTrapDump, szLineException);
1103}
1104/*****************************************************************************
1105 * Name : void static dprintfException
1106 * Purpose : log the exception to win32os2.log
1107 * Parameters: ...
1108 * Variables :
1109 * Result :
1110 * Remark :
1111 * Status :
1112 *
1113 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1114 *****************************************************************************/
1115
1116#ifdef DEBUG
1117
1118static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
1119 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1120 PCONTEXTRECORD pCtxRec,
1121 PVOID p,
1122 BOOL fSEH)
1123{
1124 char szTrapDump[2048];
1125 szTrapDump[0] = '\0';
1126 sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1127#ifdef RAS
1128 RasLog (szTrapDump);
1129#endif
1130 /* now dump the information to the logfile */
1131 dprintf(("OS2ExceptionHandler: fSEH=%d\n%s", fSEH, szTrapDump));
1132}
1133
1134#else // DEBUG
1135#define dprintfException(a,b,c,d,e) do {} while (0)
1136#endif // DEBUG
1137
1138//*****************************************************************************
1139static char szExceptionLogFileName[CCHMAXPATH] = "";
1140static BOOL fExceptionLoggging = TRUE;
1141//*****************************************************************************
1142//Override filename of exception log (expects full path)
1143//*****************************************************************************
1144void WIN32API SetCustomExceptionLog(LPSTR lpszLogName)
1145{
1146 strcpy(szExceptionLogFileName, lpszLogName);
1147}
1148//*****************************************************************************
1149//*****************************************************************************
1150void WIN32API SetExceptionLogging(BOOL fEnable)
1151{
1152 fExceptionLoggging = fEnable;
1153}
1154//*****************************************************************************
1155//*****************************************************************************
1156static void logException(PEXCEPTIONREPORTRECORD pERepRec, PEXCEPTIONREGISTRATIONRECORD pERegRec, PCONTEXTRECORD pCtxRec, PVOID p)
1157{
1158 APIRET rc;
1159 HFILE hFile;
1160 ULONG ulAction, ulBytesWritten;
1161
1162 if(fExceptionLoggging == FALSE) {
1163 return;
1164 }
1165
1166 if(szExceptionLogFileName[0] == 0) {
1167 strcpy(szExceptionLogFileName, kernel32Path);
1168 strcat(szExceptionLogFileName, "\\except.log");
1169 }
1170 rc = DosOpen(szExceptionLogFileName, /* File path name */
1171 &hFile, /* File handle */
1172 &ulAction, /* Action taken */
1173 0L, /* File primary allocation */
1174 0L, /* File attribute */
1175 OPEN_ACTION_CREATE_IF_NEW |
1176 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
1177 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
1178 0L); /* No extended attribute */
1179
1180 if(rc == NO_ERROR) {
1181 DosSetFilePtr(hFile, 0, FILE_END, &ulBytesWritten);
1182 if(WinExe) {
1183 LPSTR lpszExeName;
1184
1185 lpszExeName = WinExe->getModuleName();
1186
1187 if(lpszExeName) {
1188 DosWrite(hFile, (PVOID)"\n", 2, &ulBytesWritten);
1189 DosWrite(hFile, lpszExeName, strlen(lpszExeName), &ulBytesWritten);
1190 DosWrite(hFile, (PVOID)"\n", 2, &ulBytesWritten);
1191 }
1192 }
1193 LPSTR lpszTime;
1194 time_t curtime;
1195
1196 curtime = time(NULL);
1197 lpszTime = asctime(localtime(&curtime));
1198 if(lpszTime) {
1199 DosWrite(hFile, lpszTime, strlen(lpszTime), &ulBytesWritten);
1200 }
1201
1202 char szTrapDump[2048];
1203 szTrapDump[0] = '\0';
1204 sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1205#ifdef RAS
1206 RasLog (szTrapDump);
1207#endif
1208 DosWrite(hFile, szTrapDump, strlen(szTrapDump), &ulBytesWritten);
1209 DosClose(hFile);
1210 }
1211}
1212
1213/*****************************************************************************
1214 * Name : ERR _System OS2ExceptionHandler
1215 * Purpose :
1216 * Parameters: ...
1217 * Variables :
1218 * Result :
1219 * Remark :
1220 * Status :
1221 *
1222 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1223 *****************************************************************************/
1224 /* from PPC DDK */
1225#ifndef XCPT_CONTINUE_STOP
1226#define XCPT_CONTINUE_STOP 0x00716668
1227#endif
1228
1229// borrowed from ntddk.h
1230extern "C"
1231void WIN32API RtlUnwind(
1232 LPVOID,
1233 LPVOID,
1234 LPVOID,DWORD);
1235
1236// Assembly wrapper for clearing the direction flag before calling our real
1237// exception handler
1238ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1239 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1240 PCONTEXTRECORD pCtxRec,
1241 PVOID p);
1242
1243ULONG APIENTRY OS2ExceptionHandler2ndLevel(PEXCEPTIONREPORTRECORD pERepRec,
1244 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1245 PCONTEXTRECORD pCtxRec,
1246 PVOID p)
1247{
1248 // we need special processing when reused from ___seh_handler
1249 BOOL fSEH = pERegRec->ExceptionHandler == (_ERR *)__seh_handler;
1250
1251#ifdef DEBUG
1252 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1253 // next dprintf won't wait forever
1254 int prevlock = LogException(ENTER_EXCEPTION);
1255#endif
1256
1257// @@VP20040507: no need to sprintf every exception
1258// //Print exception name & exception type
1259// //Not for a guard page exception as sprintfException uses a lot of stack
1260// //and can trigger nested guard page exceptions (crash)
1261// if(pERepRec->ExceptionNum != XCPT_GUARD_PAGE_VIOLATION) {
1262// sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1263// }
1264
1265 // We have to disable unwinding of the Win32 exception handlers because
1266 // experiments have shown that when running under SMP kernel the stack
1267 // becomes corrupt at the time when unwinding takes place: attempts to
1268 // to follow the exception chain crash when accessing one of the the
1269 // previous frame. Although it may seem that performing unwinding here
1270 // (when we are definitely above any Win32 exception frames installed by
1271 // the application so that the OS could theoretically already discard lower
1272 // stack areas) is wrong, it's not the case of the crash. First, doing the
1273 // very same thing from the SEH handler (see comments in sehutil.s), i.e.
1274 // when the given Win32 stack frame (and all previous ones) is definitely
1275 // alive, crahes due to the same stack corruption too. Second, when running
1276 // under UNI kernel, BOTH approaches don't crash (i.e. the stack is fine).
1277 // This looks like the SMP kernel doesn't manage the stack right during
1278 // exception handling :( See also http://svn.netlabs.org/odin32/ticket/37.
1279 //
1280 // Note that disabling unwinding also breaks support for performing
1281 // setjmp()/lonjmp() that crosses the bounds of the __try {} block.
1282#if 0
1283 if (pERepRec->fHandlerFlags & EH_UNWINDING)
1284 {
1285 // unwind the appropriate portion of the Win32 exception chain
1286 if (pERepRec->fHandlerFlags & EH_EXIT_UNWIND)
1287 {
1288 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): EH_EXIT_UNWIND, "
1289 "unwinding all the Win32 exception chain", fSEH));
1290 RtlUnwind(NULL, 0, 0, 0);
1291 }
1292 else
1293 {
1294 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): EH_UNWINDING, "
1295 "unwinding the Win32 exception chain up to 0x%p", fSEH, pERegRec));
1296
1297 // find a Win32 exception frame closest to the OS/2 one (pERegRec)
1298 // and unwind up to the previous one (to unwind the closest frame
1299 // itself too as we are definitely jumping out of it)
1300 TEB *winteb = GetThreadTEB();
1301 PWINEXCEPTION_FRAME frame = (PWINEXCEPTION_FRAME)winteb->except;
1302 while (frame != NULL && ((ULONG)frame)!= 0xFFFFFFFF &&
1303 ((ULONG)frame) <= ((ULONG)pERegRec))
1304 frame = __seh_get_prev_frame_win32(frame);
1305 if (((ULONG)frame) == 0xFFFFFFFF)
1306 frame = NULL;
1307
1308 RtlUnwind(frame, 0, 0, 0);
1309 }
1310 goto continuesearch;
1311 }
1312#endif
1313
1314 /* Access violation at a known location */
1315 switch(pERepRec->ExceptionNum)
1316 {
1317 case XCPT_FLOAT_DENORMAL_OPERAND:
1318 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1319 case XCPT_FLOAT_INEXACT_RESULT:
1320// case XCPT_FLOAT_INVALID_OPERATION:
1321 case XCPT_FLOAT_OVERFLOW:
1322 case XCPT_FLOAT_STACK_CHECK:
1323 case XCPT_FLOAT_UNDERFLOW:
1324 dprintfException(pERepRec, pERegRec, pCtxRec, p, fSEH);
1325 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): FPU exception\n", fSEH));
1326 if((!fIsOS2Image || fForceWin32TIB || fSEH) && !fExitProcess) //Only for real win32 apps or when forced
1327 {
1328 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p, fSEH) == FALSE)
1329 {
1330 pCtxRec->ctx_env[0] |= 0x1F;
1331 pCtxRec->ctx_stack[0].losig = 0;
1332 pCtxRec->ctx_stack[0].hisig = 0;
1333 pCtxRec->ctx_stack[0].signexp = 0;
1334 }
1335 else
1336 {
1337 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): fix and continue\n", fSEH));
1338 goto continueexecution;
1339 }
1340 }
1341 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): continue search\n", fSEH));
1342 goto continuesearch;
1343
1344 case XCPT_PROCESS_TERMINATE:
1345 case XCPT_ASYNC_PROCESS_TERMINATE:
1346#if 0
1347 dprintfException(pERepRec, pERegRec, pCtxRec, p, fSEH);
1348 PrintExceptionChain();
1349 // fall through
1350#endif
1351 case XCPT_UNWIND:
1352 // Note that printing through ODINCRT (VACRT) when handling XCPT_UNWIND
1353 // is known to create deadlocks
1354 goto continuesearch;
1355
1356 case XCPT_ACCESS_VIOLATION:
1357 {
1358 Win32MemMap *map;
1359 BOOL fWriteAccess = FALSE;
1360 ULONG offset, accessflag;
1361
1362#ifdef WITH_KLIB
1363 if ( pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS
1364 || pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS
1365 || pERepRec->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
1366 || pERepRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS
1367 )
1368 {
1369 ENMACCESS enmAccess = enmRead;
1370 switch (pERepRec->ExceptionInfo[0])
1371 {
1372 case XCPT_WRITE_ACCESS: enmAccess = enmWrite; break;
1373 case XCPT_UNKNOWN_ACCESS: enmAccess = enmUnknown; break;
1374 }
1375
1376 if (kHeapDbgException((void*)pERepRec->ExceptionInfo[1],
1377 enmAccess,
1378 pERepRec->ExceptionAddress,
1379 pERepRec))
1380 goto continueexecution;
1381 }
1382#endif
1383
1384 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1385 goto continueFail;
1386 }
1387
1388//------------->>> WARNING: potentially dangerous workaround!!
1389 /* Some apps set ES = FS and Odin doesn't like that! */
1390 /* Note: maybe we could even check for ES != DS? But maybe */
1391 /* that might cause more harm than good... */
1392 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1393 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1394 /* Let's just reset ES to the DS value and hope it's okay */
1395 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1396 goto continueexecution;
1397 }
1398
1399 switch(pERepRec->ExceptionInfo[0]) {
1400 case XCPT_READ_ACCESS:
1401 accessflag = MEMMAP_ACCESS_READ;
1402 break;
1403 case XCPT_WRITE_ACCESS:
1404 accessflag = MEMMAP_ACCESS_WRITE;
1405 fWriteAccess = TRUE;
1406 break;
1407 case XCPT_EXECUTE_ACCESS:
1408 accessflag = MEMMAP_ACCESS_EXECUTE;
1409 break;
1410 default:
1411 goto continueFail;
1412 }
1413
1414 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1415 if(map == NULL) {
1416 Win32MemMapNotify *map;
1417
1418 map = Win32MemMapNotify::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1419 if(!map)
1420 goto continueFail;
1421
1422 BOOL ret = map->notify(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1423 if(ret == TRUE) goto continueexecution;
1424 goto continueFail;
1425 }
1426 BOOL ret = map->commitPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1427 map->Release();
1428 if(ret == TRUE)
1429 goto continueexecution;
1430
1431 //no break;
1432 }
1433continueFail:
1434
1435 /*
1436 * vladest: OK, try to implement write AUTOCOMMIT
1437 * last chance after MMAP commit is failed
1438 */
1439 if (XCPT_ACCESS_VIOLATION == pERepRec->ExceptionNum &&
1440 (/*pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS ||*/
1441 pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS) &&
1442 pERepRec->ExceptionInfo[1] != XCPT_DATA_UNKNOWN)
1443 {
1444 ULONG offset, accessflag;
1445
1446 DosQueryMem((PVOID) pERepRec->ExceptionInfo[1],
1447 &offset, &accessflag);
1448 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): failed address info 0x%X size 0x%X. flag %X\n",
1449 fSEH, pERepRec->ExceptionInfo[1], offset, accessflag));
1450 /* check for valid address */
1451 if (!pERepRec->ExceptionInfo[1] ||
1452 pERepRec->ExceptionInfo[1] == 0xAAAAAAAA ||
1453 !offset || offset == 0xAAAAAAAA)
1454 goto CrashAndBurn;
1455 /* memory committed, but no write access */
1456 if (accessflag & PAG_GUARD)
1457 accessflag &=~PAG_GUARD;
1458
1459 /* set memory aligned on page size and with size counting alignment */
1460 ULONG rc = DosSetMem((PVOID) (pERepRec->ExceptionInfo[1] & 0xFFFFF000),
1461 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
1462 accessflag | PAG_WRITE | PAG_COMMIT);
1463 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): commiting 0x%X size 0x%X. RC: %i\n",
1464 fSEH, pERepRec->ExceptionInfo[1] & 0xFFFFF000,
1465 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
1466 rc));
1467 if (NO_ERROR == rc)
1468 goto continueexecution;
1469 else
1470 goto CrashAndBurn;
1471 }
1472
1473
1474////#define DEBUGSTACK
1475#ifdef DEBUGSTACK
1476 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1477 ULONG *stackptr;
1478 APIRET rc;
1479 int i;
1480 ULONG ulOffset, ulModule, ulObject;
1481 CHAR szModule[CCHMAXPATH];
1482
1483 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1484 dprintf(("Stack DUMP:"));
1485 for(i=0;i<16;i++) {
1486 rc = DosQueryModFromEIP(&ulModule,
1487 &ulObject,
1488 sizeof(szModule),
1489 szModule,
1490 &ulOffset,
1491 (ULONG)*stackptr);
1492
1493 if (rc == NO_ERROR)
1494 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1495 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1496 stackptr++;
1497 }
1498 dprintf(("Stack DUMP END"));
1499 }
1500#endif
1501 goto CrashAndBurn;
1502
1503 case XCPT_INVALID_LOCK_SEQUENCE:
1504 {
1505 TEB *teb = GetThreadTEB();
1506 USHORT *eip = (USHORT *)pCtxRec->ctx_RegEip;
1507
1508 if(teb && eip && *eip == SETTHREADCONTEXT_INVALID_LOCKOPCODE)
1509 {
1510 //Is this a pending SetThreadContext exception?
1511 //(see detailed description in the HMDeviceThreadClass::SetThreadContext method)
1512 if(teb->o.odin.context.ContextFlags)
1513 {
1514 dprintfException(pERepRec, pERegRec, pCtxRec, p, fSEH);
1515
1516 //NOTE: This will not work properly in case multiple threads execute this code
1517 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): Changing thread registers (SetThreadContext)!!", fSEH));
1518
1519 if(teb->o.odin.context.ContextFlags & WINCONTEXT_CONTROL) {
1520 pCtxRec->ctx_RegEbp = teb->o.odin.context.Ebp;
1521 pCtxRec->ctx_RegEip = teb->o.odin.context.Eip;
1522//// pCtxRec->ctx_SegCs = teb->o.odin.context.SegCs;
1523 pCtxRec->ctx_EFlags = teb->o.odin.context.EFlags;
1524 pCtxRec->ctx_RegEsp = teb->o.odin.context.Esp;
1525//// pCtxRec->ctx_SegSs = teb->o.odin.context.SegSs;
1526 }
1527 if(teb->o.odin.context.ContextFlags & WINCONTEXT_INTEGER) {
1528 pCtxRec->ctx_RegEdi = teb->o.odin.context.Edi;
1529 pCtxRec->ctx_RegEsi = teb->o.odin.context.Esi;
1530 pCtxRec->ctx_RegEbx = teb->o.odin.context.Ebx;
1531 pCtxRec->ctx_RegEdx = teb->o.odin.context.Edx;
1532 pCtxRec->ctx_RegEcx = teb->o.odin.context.Ecx;
1533 pCtxRec->ctx_RegEax = teb->o.odin.context.Eax;
1534 }
1535 if(teb->o.odin.context.ContextFlags & WINCONTEXT_SEGMENTS) {
1536 pCtxRec->ctx_SegGs = teb->o.odin.context.SegGs;
1537//// pCtxRec->ctx_SegFs = teb->o.odin.context.SegFs;
1538 pCtxRec->ctx_SegEs = teb->o.odin.context.SegEs;
1539 pCtxRec->ctx_SegDs = teb->o.odin.context.SegDs;
1540 }
1541 if(teb->o.odin.context.ContextFlags & WINCONTEXT_FLOATING_POINT) {
1542 //TODO: First 7 dwords the same?
1543 memcpy(pCtxRec->ctx_env, &teb->o.odin.context.FloatSave, sizeof(pCtxRec->ctx_env));
1544 memcpy(pCtxRec->ctx_stack, &teb->o.odin.context.FloatSave.RegisterArea, sizeof(pCtxRec->ctx_stack));
1545 }
1546 USHORT *lpAlias = (USHORT *)((char *)teb->o.odin.lpAlias + teb->o.odin.dwAliasOffset);
1547 *lpAlias = teb->o.odin.savedopcode;
1548
1549 //Clear SetThreadContext markers
1550 teb->o.odin.context.ContextFlags = 0;
1551
1552 OSLibDosFreeMem(teb->o.odin.lpAlias);
1553
1554 teb->o.odin.lpAlias = NULL;
1555 teb->o.odin.dwAliasOffset = 0;
1556
1557 //restore the original priority (we boosted it to ensure this thread was scheduled first)
1558 SetThreadPriority(teb->o.odin.hThread, GetThreadPriority(teb->o.odin.hThread));
1559 goto continueexecution;
1560 }
1561 else DebugInt3(); //oh, oh!!!!!
1562
1563 }
1564 //no break;
1565 }
1566
1567 case XCPT_PRIVILEGED_INSTRUCTION:
1568 case XCPT_ILLEGAL_INSTRUCTION:
1569 case XCPT_BREAKPOINT:
1570 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1571 case XCPT_DATATYPE_MISALIGNMENT:
1572 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1573 case XCPT_INTEGER_OVERFLOW:
1574 case XCPT_SINGLE_STEP:
1575 case XCPT_IN_PAGE_ERROR:
1576CrashAndBurn:
1577 //SvL: TODO: this may not always be the right thing to do
1578 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1579 // of this exception handler. We better bail out ASAP or we'll likely
1580 // recurse infinitely until we run out of stack space!!
1581 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1582 goto continuesearch;
1583
1584#if defined(DEBUG)
1585 dprintfException(pERepRec, pERegRec, pCtxRec, p, fSEH);
1586
1587 if(!fExitProcess && (pCtxRec->ContextFlags & CONTEXT_CONTROL)) {
1588 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1589 }
1590#endif
1591
1592 if((!fIsOS2Image || fForceWin32TIB || fSEH) && !fExitProcess) //Only for real win32 apps or when forced
1593 {
1594 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p, fSEH) == TRUE)
1595 {
1596 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): fix and continue\n", fSEH));
1597 goto continueexecution;
1598 }
1599 else
1600 {
1601 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): continue search\n", fSEH));
1602 goto continuesearch;
1603 }
1604 }
1605 else {
1606 if(fExitProcess) {
1607 PPIB pPIB;
1608 PTIB pTIB;
1609 APIRET rc;
1610
1611 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1612 if(rc == NO_ERROR)
1613 {
1614 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): Continue and kill thread", fSEH));
1615
1616 pCtxRec->ctx_RegEip = (pTIB->tib_ptib2->tib2_ultid != 1) ? (ULONG)KillWin32Thread : (ULONG)KillWin32Process;
1617 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1618 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1619 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1620 goto continueexecution;
1621 }
1622 }
1623 goto continuesearch; //pass on to OS/2 RTL or app exception handler
1624 }
1625
1626 //Log fatal exception here
1627 logException(pERepRec, pERegRec, pCtxRec, p);
1628
1629 dprintf(("KERNEL32: OS2ExceptionHandler (fSEH=%d): Continue and kill\n", fSEH));
1630
1631 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1632 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1633 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1634 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1635 goto continueexecution;
1636
1637 case XCPT_GUARD_PAGE_VIOLATION:
1638 {
1639 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1640 //Don't print anything here -> fatal hang if exception occurred
1641 //inside fprintf
1642 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1643 TEB *teb = GetThreadTEB();
1644 DWORD stacktop, stackbottom;
1645
1646 if(teb == NULL) {
1647 goto continuesearch;
1648 }
1649
1650 stacktop = (DWORD)teb->stack_top;
1651 stackbottom = (DWORD)teb->stack_low;
1652
1653 stackbottom = stackbottom & ~0xFFF; //round down to page boundary
1654 stacktop = stacktop & ~0xFFF;
1655
1656 // Make sure we detect a stack overflow condition before the system does
1657 if ((!fIsOS2Image || fForceWin32TIB || fSEH) && //Only for real win32 apps or when forced
1658 pERepRec->ExceptionInfo[1] >= stackbottom &&
1659 pERepRec->ExceptionInfo[1] < stacktop
1660 )
1661 {
1662 // this is a guard page exception for the thread stack
1663
1664 // In order to imitate Windows behavior, we must raise
1665 // EXCEPTION_STACK_OVERFLOW in the Win32 context in two cases:
1666 // 1. When we run out of stack.
1667 // 2. When a guard page not immediately following the committed
1668 // stack area is touched.
1669
1670 APIRET rc;
1671 BOOL bRaise = FALSE;
1672
1673 // round down to page boundary
1674 ULONG ulAddress = pERepRec->ExceptionInfo[1] & ~0xFFF;
1675
1676 if (ulAddress == stackbottom + PAGE_SIZE)
1677 {
1678 // we are about to run out of stack
1679 bRaise = TRUE;
1680 }
1681 else
1682 {
1683 // check if it's an adjacent guard page used to grow stack
1684 ULONG cbSize = ~0, ulMemFlags;
1685 rc = DosQueryMem((PVOID)ulAddress, &cbSize, &ulMemFlags);
1686 if (rc)
1687 {
1688 dprintf(("ERROR: DosQueryMem old guard page failed with rc %d", rc));
1689 goto continueGuardException;
1690 }
1691
1692 if (ulAddress + cbSize == stacktop)
1693 {
1694 // yes, we must pass it on to the system to do the grow magic
1695 goto continuesearch;
1696 }
1697
1698 bRaise = TRUE;
1699 }
1700
1701 if (bRaise)
1702 {
1703 if (!fExitProcess)
1704 {
1705 EXCEPTIONREPORTRECORD recoutofstack;
1706
1707 recoutofstack = *pERepRec;
1708 recoutofstack.ExceptionNum = XCPT_UNABLE_TO_GROW_STACK;
1709 recoutofstack.fHandlerFlags = 0;
1710 recoutofstack.NestedExceptionReportRecord = NULL;
1711 recoutofstack.cParameters = 0;
1712
1713 if(OSLibDispatchException(&recoutofstack, pERegRec, pCtxRec, p, fSEH) == TRUE)
1714 {
1715 goto continueexecution;
1716 }
1717 }
1718 }
1719 }
1720 else
1721 {
1722 // Throw EXCEPTION_GUARD_PAGE_VIOLATION in the Win32 context
1723 if((!fIsOS2Image || fForceWin32TIB || fSEH) && !fExitProcess) //Only for real win32 apps or when forced
1724 {
1725 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p, fSEH) == TRUE)
1726 {
1727 goto continueexecution;
1728 }
1729 }
1730
1731 //check for memory map guard page exception
1732 Win32MemMap *map;
1733 BOOL fWriteAccess = FALSE, ret;
1734 ULONG offset, accessflag;
1735
1736 switch(pERepRec->ExceptionInfo[0]) {
1737 case XCPT_READ_ACCESS:
1738 accessflag = MEMMAP_ACCESS_READ;
1739 break;
1740 case XCPT_WRITE_ACCESS:
1741 accessflag = MEMMAP_ACCESS_WRITE;
1742 fWriteAccess = TRUE;
1743 break;
1744 default:
1745 goto continueGuardException;
1746 }
1747
1748 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1749 if(map) {
1750 ret = map->commitGuardPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1751 map->Release();
1752 if(ret == TRUE)
1753 goto continueexecution;
1754 }
1755 }
1756
1757continueGuardException:
1758 goto continuesearch;
1759 }
1760
1761 case XCPT_UNABLE_TO_GROW_STACK:
1762 {
1763 //SvL: XCPT_UNABLE_TO_GROW_STACK is typically nested (failed guard page
1764 // exception), so don't ignore them
1765 // We should no longer receive those!!
1766// @@VP20040507: Isn't this a bit dangerous to call dprintfon such exception
1767//#ifdef DEBUG
1768// dprintfException(pERepRec, pERegRec, pCtxRec, p, fSEH);
1769//#endif
1770 goto continuesearch;
1771 }
1772
1773
1774 /*
1775 * In OS/2 VIO Ctrl-C and Ctrl-Break is special stuff which comes in
1776 * thru the exception handler. In Win32 CUI they are handled by a
1777 * ControlCtrlEvent procedure. So, if we receive one of those signals
1778 * we assume that this is a VIO program and let the handlers handle this.
1779 * (If they want to.)
1780 */
1781 case XCPT_SIGNAL:
1782 {
1783 //This is not a reliable way to distinguish between Ctrl-C & Ctrl-Break
1784 BOOL breakPressed = WinGetKeyState(HWND_DESKTOP,VK_BREAK) & 0x8000;
1785
1786 switch (pERepRec->ExceptionInfo[0])
1787 {
1788 case XCPT_SIGNAL_BREAK:
1789 breakPressed = TRUE;
1790 //no break
1791
1792 case XCPT_SIGNAL_INTR:
1793 dprintfException(pERepRec, pERegRec, pCtxRec, p, fSEH);
1794 if (InternalGenerateConsoleCtrlEvent((breakPressed) ? CTRL_BREAK_EVENT : CTRL_C_EVENT, 0))
1795 {
1796 DosAcknowledgeSignalException(pERepRec->ExceptionInfo[0]);
1797 goto continueexecution;
1798 }
1799 goto continuesearch;
1800
1801 case XCPT_SIGNAL_KILLPROC: /* resolve signal information */
1802 goto continuesearch;
1803 }
1804 goto CrashAndBurn;
1805 }
1806
1807 default: //non-continuable exceptions
1808 dprintfException(pERepRec, pERegRec, pCtxRec, p, fSEH);
1809 goto continuesearch;
1810 }
1811continuesearch:
1812#ifdef DEBUG
1813 LogException(LEAVE_EXCEPTION, prevlock);
1814#endif
1815 return XCPT_CONTINUE_SEARCH;
1816
1817continueexecution:
1818#ifdef DEBUG
1819 LogException(LEAVE_EXCEPTION, prevlock);
1820#endif
1821 return XCPT_CONTINUE_EXECUTION;
1822}
1823
1824/*****************************************************************************
1825 * Name : void OS2SetExceptionHandler
1826 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1827 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1828 * Variables :
1829 * Result :
1830 * Remark :
1831 * Status :
1832 *
1833 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1834 *****************************************************************************/
1835void SYSTEM OS2SetExceptionHandler(void *exceptframe)
1836{
1837 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1838
1839 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1840 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1841
1842 /* disable trap popups */
1843// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1844
1845 DosSetExceptionHandler(pExceptRec);
1846 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1847#ifdef DEBUG_ENABLELOG_LEVEL2
1848 PrintExceptionChain();
1849#endif
1850}
1851//*****************************************************************************
1852// Set exception handler if our handler has not yet been registered
1853//*****************************************************************************
1854void WIN32API ODIN_SetExceptionHandler(void *pExceptionRegRec)
1855{
1856 BOOL fFound = FALSE;
1857 USHORT sel = RestoreOS2FS();
1858 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1859
1860 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1861 {
1862 if(pExceptRec->ExceptionHandler == OS2ExceptionHandler)
1863 {
1864 fFound = TRUE;
1865 break;
1866 }
1867 pExceptRec = pExceptRec->prev_structure;
1868 }
1869 if(!fFound)
1870 {
1871 OS2SetExceptionHandler(pExceptionRegRec);
1872 }
1873 SetFS(sel);
1874}
1875//*****************************************************************************
1876// Remove exception handler if it was registered previously
1877//
1878//*****************************************************************************
1879void WIN32API ODIN_UnsetExceptionHandler(void *pExceptionRegRec)
1880{
1881 USHORT sel = RestoreOS2FS();
1882 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1883 BOOL fFound = FALSE;
1884
1885 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1886 {
1887 if(pExceptRec == pExceptionRegRec)
1888 {
1889 fFound = TRUE;
1890 break;
1891 }
1892 pExceptRec = pExceptRec->prev_structure;
1893 }
1894
1895#ifdef DEBUG
1896 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1897
1898 if(fFound && pExceptRec != (PEXCEPTIONREGISTRATIONRECORD)pExceptionRegRec)
1899 {
1900 dprintf(("ERROR: ODIN_UnsetExceptionHandler: INSIDE!!!: exc rec %p, head %p\n", pExceptionRegRec, pExceptRec));
1901 PrintExceptionChain ();
1902 }
1903#endif
1904 if(fFound) {
1905 OS2UnsetExceptionHandler(pExceptionRegRec);
1906 }
1907 SetFS(sel);
1908}
1909//*****************************************************************************
1910//*****************************************************************************
1911#ifdef DEBUG
1912void PrintExceptionChain()
1913{
1914 USHORT sel = RestoreOS2FS();
1915 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1916
1917 dprintf(("OS/2 Exception chain:"));
1918 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1919 {
1920 char szBuf[512];
1921 ULONG ulModule;
1922 ULONG ulObject, ulOffset;
1923 CHAR szModule[260];
1924
1925 *szBuf = '\0';
1926 APIRET rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
1927 szModule, &ulOffset, (ULONG)pExceptRec->ExceptionHandler);
1928 if(rc == NO_ERROR && ulObject != -1)
1929 {
1930 sprintf(szBuf, " <%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject + 1, ulOffset);
1931#ifdef RAS
1932 char szSYMInfo[260];
1933
1934 DosQueryModuleName(ulModule, sizeof(szModule), szModule);
1935
1936 int namelen = strlen(szModule);
1937 if(namelen > 3)
1938 {
1939 strcpy(szModule + namelen - 3, "SYM");
1940 dbgGetSYMInfo(szModule, ulObject, ulOffset,
1941 szSYMInfo, sizeof (szSYMInfo), TRUE);
1942 strcat(szBuf, " ");
1943 strcat(szBuf, szSYMInfo);
1944 // remove trailing \n or space
1945 szBuf[strlen(szBuf) - 1] = '\0';
1946 }
1947#endif
1948 }
1949 else
1950 {
1951 *szBuf = '\0';
1952 }
1953
1954 dprintf((" record %08X, prev %08X, handler %08X%s",
1955 pExceptRec, pExceptRec->prev_structure, pExceptRec->ExceptionHandler,
1956 szBuf));
1957
1958 pExceptRec = pExceptRec->prev_structure;
1959 }
1960 dprintf(("END of OS/2 Exception chain."));
1961 SetFS(sel);
1962}
1963//*****************************************************************************
1964//*****************************************************************************
1965void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pFrame)
1966{
1967 dprintf(("Win32 exception chain:"));
1968 while ((pFrame != NULL) && ((ULONG)pFrame != 0xFFFFFFFF))
1969 {
1970 PWINEXCEPTION_FRAME pPrevFrame = __seh_get_prev_frame_win32(pFrame);
1971 dprintf((" Record at %08X, Prev at %08X, handler at %08X%s",
1972 pFrame, pPrevFrame, pFrame->Handler,
1973 pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler ? " (SEH)" :
1974 pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler_win32 ? " (SEH Win32)" : ""));
1975 if (pFrame == pPrevFrame)
1976 {
1977 dprintf(("Chain corrupted! Record at %08X pointing to itself!",
1978 pFrame));
1979 break;
1980 }
1981 pFrame = pPrevFrame;
1982 }
1983 dprintf(("END of Win32 exception chain."));
1984}
1985#endif
1986
1987/*****************************************************************************
1988 * Name : void OS2UnsetExceptionHandler
1989 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1990 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1991 * Variables :
1992 * Result :
1993 * Remark :
1994 * Status :
1995 *
1996 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1997 *****************************************************************************/
1998void SYSTEM OS2UnsetExceptionHandler(void *exceptframe)
1999{
2000 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
2001
2002 DosUnsetExceptionHandler(pExceptRec);
2003 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
2004#ifdef DEBUG_ENABLELOG_LEVEL2
2005 PrintExceptionChain();
2006#endif
2007}
2008//*****************************************************************************
2009//*****************************************************************************
2010int _System CheckCurFS()
2011{
2012 USHORT sel = RestoreOS2FS();
2013 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
2014
2015 if(sel == 0x150b) {
2016 SetFS(sel);
2017 return FALSE;
2018 }
2019 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
2020 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
2021 SetFS(sel);
2022 return FALSE;
2023 }
2024 SetFS(sel);
2025 return TRUE;
2026}
2027//*****************************************************************************
2028//*****************************************************************************
2029
2030} // extern "C"
2031
Note: See TracBrowser for help on using the repository browser.