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

Last change on this file since 21618 was 21618, checked in by dmik, 14 years ago

kernel32/SEH: Fixed a couple of bugs in SEH processing that could cause a bunch of various crashes when unwinding the Win32 exception chain (usually at process termination, as a result of both a fatal exception or a clean exit).

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