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

Last change on this file since 21605 was 21568, checked in by dmik, 15 years ago

kernel32: Disable logging exceptions in release builds through RAS since this involves .sym file reading and significantly slows down applications that use exception handlers like traps for implementing application logic (e.g. JVM uses it for catching NullPointerExceptions).

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