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

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

kernel32: Removed the dirty hack that would reset the exception handler chain before calling DosExit(). This prevented exception handlers in the chain from being called at thread termination and performing the necessary cleanup which is sometimes vital (like releasing locked resources etc).

File size: 66.8 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 DosExit(EXIT_PROCESS, 666);
710}
711//*****************************************************************************
712//*****************************************************************************
713void KillWin32Thread(void)
714{
715// ExitThread(666);
716 //Restore original OS/2 TIB selector
717 RestoreOS2FS();
718
719 DosExit(EXIT_THREAD, 666);
720}
721//*****************************************************************************
722//*****************************************************************************
723static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec,
724 PEXCEPTIONREGISTRATIONRECORD pERegRec,
725 PCONTEXTRECORD pCtxRec,
726 PVOID p,
727 PSZ szTrapDump)
728{
729 if(pERepRec->ExceptionNum == XCPT_GUARD_PAGE_VIOLATION)
730 {
731 strcpy(szTrapDump, "Guard Page Violation");
732 return;
733 }
734
735 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
736 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
737 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
738 BOOL fExcptFatal = TRUE; /* fatal exception ? */
739 BOOL fExcptPortable = TRUE; /* portability of exception */
740 PPIB pPIB; /* process information block */
741 PTIB pTIB; /* thread information block */
742 ULONG ulModule; /* module number */
743 ULONG ulObject; /* object number within the module */
744 CHAR szModule[260]; /* buffer for the module name */
745 ULONG ulOffset; /* offset within the object within the module */
746 char szLineException[512];
747 char szLineExceptionType[128];
748
749 szLineException[0] = 0; /* initialize */
750 szLineExceptionType[0] = 0; /* initialize */
751 switch(pERepRec->ExceptionNum) /* take according action */
752 {
753 /* portable, non-fatal software-generated exceptions */
754 case XCPT_GUARD_PAGE_VIOLATION:
755 strcpy(szLineException, "Guard Page Violation");
756 sprintf(szLineExceptionType, "R/W %08xh at %08xh.", pERepRec->ExceptionInfo[0], pERepRec->ExceptionInfo[1]);
757 fExcptSoftware = TRUE;
758 fExcptFatal = FALSE;
759 rc = XCPT_CONTINUE_EXECUTION;
760 break;
761
762 case XCPT_UNABLE_TO_GROW_STACK:
763 strcpy(szLineException, "Unable To Grow Stack");
764 fExcptSoftware = TRUE;
765 fExcptFatal = FALSE;
766 rc = XCPT_CONTINUE_EXECUTION;
767 break;
768
769 /* portable, fatal, hardware-generated exceptions */
770 case XCPT_ACCESS_VIOLATION:
771 strcpy(szLineException, "Access Violation");
772 switch (pERepRec->ExceptionInfo[0])
773 {
774 case XCPT_READ_ACCESS:
775 sprintf (szLineExceptionType, "Read Access at address %08xh", pERepRec->ExceptionInfo[1]);
776 break;
777
778 case XCPT_WRITE_ACCESS:
779 sprintf (szLineExceptionType, "Write Access at address %08x", pERepRec->ExceptionInfo[1]);
780 break;
781
782 case XCPT_SPACE_ACCESS:
783 sprintf (szLineExceptionType, "Space Access at selector %08x", pERepRec->ExceptionInfo[1]);
784 break;
785
786 case XCPT_LIMIT_ACCESS:
787 strcpy (szLineExceptionType, "Limit Access");
788 break;
789
790 case XCPT_UNKNOWN_ACCESS:
791 strcpy (szLineExceptionType, "Unknown Access");
792 break;
793
794 default:
795 strcpy (szLineExceptionType, "(Invalid Access Code)");
796 break;
797 }
798 break;
799
800 case XCPT_INTEGER_DIVIDE_BY_ZERO:
801 strcpy(szLineException, "Division By Zero (Integer)");
802 break;
803
804 case XCPT_FLOAT_DIVIDE_BY_ZERO:
805 strcpy(szLineException, "Division By Zero (Float)");
806 break;
807
808 case XCPT_FLOAT_INVALID_OPERATION:
809 strcpy(szLineException, "Invalid Floating Point Operation");
810 break;
811
812 case XCPT_ILLEGAL_INSTRUCTION:
813 strcpy(szLineException, "Illegal Instruction");
814 break;
815
816 case XCPT_PRIVILEGED_INSTRUCTION:
817 strcpy(szLineException, "Privileged Instruction");
818 break;
819
820 case XCPT_INTEGER_OVERFLOW:
821 strcpy(szLineException, "Integer Overflow");
822 break;
823
824 case XCPT_FLOAT_OVERFLOW:
825 strcpy(szLineException, "Floating Point Overflow");
826 break;
827
828 case XCPT_FLOAT_UNDERFLOW:
829 strcpy(szLineException, "Floating Point Underflow");
830 break;
831
832 case XCPT_FLOAT_DENORMAL_OPERAND:
833 strcpy(szLineException, "Floating Point Denormal Operand");
834 break;
835
836 case XCPT_FLOAT_INEXACT_RESULT:
837 strcpy(szLineException, "Floating Point Inexact Result");
838 break;
839
840 case XCPT_FLOAT_STACK_CHECK:
841 strcpy(szLineException, "Floating Point Stack Check");
842 break;
843
844 case XCPT_DATATYPE_MISALIGNMENT:
845 strcpy(szLineException, "Datatype Misalignment");
846 sprintf(szLineExceptionType, "R/W %08x alignment %08x at %08x.", pERepRec->ExceptionInfo[0],
847 pERepRec->ExceptionInfo[1], pERepRec->ExceptionInfo[2]);
848 break;
849
850 case XCPT_BREAKPOINT:
851 strcpy(szLineException, "Breakpoint (DEBUG)");
852 break;
853
854 case XCPT_SINGLE_STEP:
855 strcpy(szLineException, "Single Step (DEBUG)");
856 break;
857
858 /* portable, fatal, software-generated exceptions */
859 case XCPT_IN_PAGE_ERROR:
860 strcpy(szLineException, "In Page Error");
861 sprintf(szLineExceptionType, "at %08x.", pERepRec->ExceptionInfo[0]);
862 fExcptSoftware = TRUE;
863 break;
864
865 case XCPT_PROCESS_TERMINATE:
866 strcpy(szLineException, "Process Termination");
867 fExcptSoftware = TRUE;
868 break;
869
870 case XCPT_ASYNC_PROCESS_TERMINATE:
871 strcpy(szLineException, "Process Termination (async)");
872 sprintf(szLineExceptionType, "terminating thread TID=%u", pERepRec->ExceptionInfo[0]);
873 fExcptSoftware = TRUE;
874 break;
875
876 case XCPT_NONCONTINUABLE_EXCEPTION:
877 strcpy(szLineException, "Noncontinuable Exception");
878 fExcptSoftware = TRUE;
879 break;
880
881 case XCPT_INVALID_DISPOSITION:
882 strcpy(szLineException, "Invalid Disposition");
883 fExcptSoftware = TRUE;
884 break;
885
886 /* non-portable, fatal exceptions */
887 case XCPT_INVALID_LOCK_SEQUENCE:
888 strcpy(szLineException, "Invalid Lock Sequence");
889 fExcptSoftware = TRUE;
890 fExcptPortable = FALSE;
891 break;
892
893 case XCPT_ARRAY_BOUNDS_EXCEEDED:
894 strcpy(szLineException, "Array Bounds Exceeded");
895 fExcptSoftware = TRUE;
896 fExcptPortable = FALSE;
897 break;
898
899 /* unwind operation exceptions */
900 case XCPT_UNWIND:
901 strcpy(szLineException, "Unwind Exception");
902 fExcptSoftware = TRUE;
903 fExcptPortable = FALSE;
904 break;
905
906 case XCPT_BAD_STACK:
907 strcpy(szLineException, "Unwind Exception, Bad Stack");
908 fExcptSoftware = TRUE;
909 fExcptPortable = FALSE;
910 break;
911
912 case XCPT_INVALID_UNWIND_TARGET:
913 strcpy(szLineException, "Unwind Exception, Invalid Target");
914 fExcptSoftware = TRUE;
915 fExcptPortable = FALSE;
916 break;
917
918 /* fatal signal exceptions */
919 case XCPT_SIGNAL:
920 strcpy(szLineException, "Signal");
921 sprintf(szLineExceptionType, "Signal Number = %08x", pERepRec->ExceptionInfo[0]);
922 fExcptSoftware = TRUE;
923 fExcptPortable = FALSE;
924
925 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
926 {
927 case XCPT_SIGNAL_INTR:
928 strcpy(szLineException, "Signal (Interrupt)");
929 break;
930
931 case XCPT_SIGNAL_KILLPROC:
932 strcpy(szLineException, "Signal (Kill Process)");
933 break;
934
935 case XCPT_SIGNAL_BREAK:
936 strcpy(szLineException, "Signal (Break)");
937 break;
938 }
939 break;
940
941 default:
942 strcpy(szLineException, "(unknown exception code)");
943 sprintf(szLineExceptionType, "Exception Code = %08x", pERepRec->ExceptionNum);
944 break;
945 }
946
947 sprintf(szTrapDump, "---[Exception Information]------------\n %s (", szLineException);
948
949 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
950 strcat (szTrapDump, "software generated,");
951 else
952 strcat (szTrapDump, "hardware generated,");
953
954 if (fExcptPortable == TRUE) /* portable exception ? */
955 strcat (szTrapDump, "portable,");
956 else
957 strcat (szTrapDump, "non-portable,");
958
959 if (fExcptFatal == TRUE) /* fatal exception ? */
960 strcat (szTrapDump, "fatal");
961 else
962 strcat (szTrapDump, "non-fatal");
963
964 strcat(szTrapDump, ")\n"); /* add trailing brace */
965
966 if (szLineExceptionType[0])
967 sprintf(szTrapDump + strlen(szTrapDump), " %s\n", szLineExceptionType);
968
969 sprintf(szLineException, " Exception Address = %08x ", pERepRec->ExceptionAddress);
970 strcat(szTrapDump, szLineException);
971
972 rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
973 szModule, &ulOffset, (ULONG)pERepRec->ExceptionAddress);
974
975 if(rc == NO_ERROR && ulObject != -1)
976 {
977 sprintf(szLineException, "<%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject + 1, ulOffset);
978#ifdef RAS
979 char szSYMInfo[260];
980
981 DosQueryModuleName(ulModule, sizeof(szModule), szModule);
982
983 int namelen = strlen(szModule);
984 if(namelen > 3)
985 {
986 strcpy(szModule + namelen - 3, "SYM");
987 dbgGetSYMInfo(szModule, ulObject, ulOffset, szSYMInfo, sizeof (szSYMInfo),
988 FALSE);
989 strcat(szLineException, " ");
990 strcat(szLineException, szSYMInfo);
991 }
992#else
993 strcat(szLineException, "\n");
994#endif
995 strcat(szTrapDump, szLineException);
996 }
997 else
998 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
999 Win32ImageBase * pMod;
1000 if (WinExe && WinExe->insideModule((ULONG)pERepRec->ExceptionAddress))
1001 pMod = WinExe;
1002 else
1003 pMod = Win32DllBase::findModuleByAddr((ULONG)pERepRec->ExceptionAddress);
1004 if (pMod != NULL)
1005 {
1006 szModule[0] = '\0';
1007 strncat(szModule, pMod->getModuleName(), sizeof(szModule) - 1);
1008 ulObject = 0xFF;
1009 ulOffset = (ULONG)pERepRec->ExceptionAddress - (ULONG)pMod->getInstanceHandle();
1010 sprintf(szLineException, "<%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject, ulOffset);
1011 }
1012 else sprintf(szLineException, "<unknown win32 module>\n");
1013
1014 strcat(szTrapDump, szLineException);
1015 }
1016
1017 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1018 if (rc == NO_ERROR)
1019 {
1020 sprintf(szLineException, " Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
1021 pTIB->tib_ordinal, pTIB->tib_ptib2->tib2_ultid, pTIB->tib_ptib2->tib2_ulpri);
1022 strcat(szTrapDump, szLineException);
1023
1024 sprintf(szLineException, " Process: PID: %u, Parent: %u, Status: %u\n", pPIB->pib_ulpid,
1025 pPIB->pib_ulppid, pPIB->pib_flstatus);
1026 strcat(szTrapDump, szLineException);
1027 }
1028
1029 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) { /* check flags */
1030 sprintf(szLineException, " SS:ESP=%04x:%08x EFLAGS=%08x\n", pCtxRec->ctx_SegSs, pCtxRec->ctx_RegEsp,
1031 pCtxRec->ctx_EFlags);
1032 strcat(szTrapDump, szLineException);
1033 sprintf(szLineException, " CS:EIP=%04x:%08x EBP =%08x\n", pCtxRec->ctx_SegCs, pCtxRec->ctx_RegEip,
1034 pCtxRec->ctx_RegEbp);
1035 strcat(szTrapDump, szLineException);
1036 }
1037
1038 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) { /* check flags */
1039 sprintf(szLineException, " EAX=%08x EBX=%08x ESI=%08x\n", pCtxRec->ctx_RegEax, pCtxRec->ctx_RegEbx,
1040 pCtxRec->ctx_RegEsi);
1041 strcat(szTrapDump, szLineException);
1042 sprintf(szLineException, " ECX=%08x EDX=%08x EDI=%08x\n", pCtxRec->ctx_RegEcx, pCtxRec->ctx_RegEdx,
1043 pCtxRec->ctx_RegEdi);
1044 strcat(szTrapDump, szLineException);
1045 }
1046
1047 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) { /* check flags */
1048 sprintf(szLineException, " DS=%04x ES=%08x FS=%04x GS=%04x\n", pCtxRec->ctx_SegDs, pCtxRec->ctx_SegEs, pCtxRec->ctx_SegFs, pCtxRec->ctx_SegGs);
1049 strcat(szTrapDump, szLineException);
1050 }
1051
1052 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1053 {
1054 ULONG ulCounter; /* temporary local counter for fp stack */
1055
1056 sprintf(szLineException, " Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1057 pCtxRec->ctx_env[0], pCtxRec->ctx_env[1],
1058 pCtxRec->ctx_env[2], pCtxRec->ctx_env[3]);
1059 strcat(szTrapDump, szLineException);
1060
1061 sprintf(szLineException, " Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1062 pCtxRec->ctx_env[4], pCtxRec->ctx_env[5], pCtxRec->ctx_env[6]);
1063 strcat(szTrapDump, szLineException);
1064
1065 for (ulCounter = 0; ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1066 ulCounter ++)
1067 {
1068 sprintf(szLineException, " FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1069 ulCounter, pCtxRec->ctx_stack[0].losig, pCtxRec->ctx_stack[0].hisig,
1070 pCtxRec->ctx_stack[0].signexp);
1071 strcat(szTrapDump, szLineException);
1072 }
1073 }
1074 sprintf(szLineException, "---[End Of Exception Information]-----\n");
1075 strcat(szTrapDump, szLineException);
1076}
1077/*****************************************************************************
1078 * Name : void static dprintfException
1079 * Purpose : log the exception to win32os2.log
1080 * Parameters: ...
1081 * Variables :
1082 * Result :
1083 * Remark :
1084 * Status :
1085 *
1086 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1087 *****************************************************************************/
1088
1089#ifdef DEBUG
1090
1091static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
1092 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1093 PCONTEXTRECORD pCtxRec,
1094 PVOID p)
1095{
1096 char szTrapDump[2048];
1097 szTrapDump[0] = '\0';
1098 sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1099#ifdef RAS
1100 RasLog (szTrapDump);
1101#endif
1102 /* now dump the information to the logfile */
1103 dprintf(("\n%s", szTrapDump));
1104}
1105
1106#else // DEBUG
1107#define dprintfException(a,b,c,d) do {} while (0)
1108#endif // DEBUG
1109
1110//*****************************************************************************
1111static char szExceptionLogFileName[CCHMAXPATH] = "";
1112static BOOL fExceptionLoggging = TRUE;
1113//*****************************************************************************
1114//Override filename of exception log (expects full path)
1115//*****************************************************************************
1116void WIN32API SetCustomExceptionLog(LPSTR lpszLogName)
1117{
1118 strcpy(szExceptionLogFileName, lpszLogName);
1119}
1120//*****************************************************************************
1121//*****************************************************************************
1122void WIN32API SetExceptionLogging(BOOL fEnable)
1123{
1124 fExceptionLoggging = fEnable;
1125}
1126//*****************************************************************************
1127//*****************************************************************************
1128static void logException(PEXCEPTIONREPORTRECORD pERepRec, PEXCEPTIONREGISTRATIONRECORD pERegRec, PCONTEXTRECORD pCtxRec, PVOID p)
1129{
1130 APIRET rc;
1131 HFILE hFile;
1132 ULONG ulAction, ulBytesWritten;
1133
1134 if(fExceptionLoggging == FALSE) {
1135 return;
1136 }
1137
1138 if(szExceptionLogFileName[0] == 0) {
1139 strcpy(szExceptionLogFileName, kernel32Path);
1140 strcat(szExceptionLogFileName, "\\except.log");
1141 }
1142 rc = DosOpen(szExceptionLogFileName, /* File path name */
1143 &hFile, /* File handle */
1144 &ulAction, /* Action taken */
1145 0L, /* File primary allocation */
1146 0L, /* File attribute */
1147 OPEN_ACTION_CREATE_IF_NEW |
1148 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
1149 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
1150 0L); /* No extended attribute */
1151
1152 if(rc == NO_ERROR) {
1153 DosSetFilePtr(hFile, 0, FILE_END, &ulBytesWritten);
1154 if(WinExe) {
1155 LPSTR lpszExeName;
1156
1157 lpszExeName = WinExe->getModuleName();
1158
1159 if(lpszExeName) {
1160 DosWrite(hFile, "\n", 2, &ulBytesWritten);
1161 DosWrite(hFile, lpszExeName, strlen(lpszExeName), &ulBytesWritten);
1162 DosWrite(hFile, "\n", 2, &ulBytesWritten);
1163 }
1164 }
1165 LPSTR lpszTime;
1166 time_t curtime;
1167
1168 curtime = time(NULL);
1169 lpszTime = asctime(localtime(&curtime));
1170 if(lpszTime) {
1171 DosWrite(hFile, lpszTime, strlen(lpszTime), &ulBytesWritten);
1172 }
1173
1174 char szTrapDump[2048];
1175 szTrapDump[0] = '\0';
1176 sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1177#ifdef RAS
1178 RasLog (szTrapDump);
1179#endif
1180 DosWrite(hFile, szTrapDump, strlen(szTrapDump), &ulBytesWritten);
1181 DosClose(hFile);
1182 }
1183}
1184
1185/*****************************************************************************
1186 * Name : ERR _System OS2ExceptionHandler
1187 * Purpose :
1188 * Parameters: ...
1189 * Variables :
1190 * Result :
1191 * Remark :
1192 * Status :
1193 *
1194 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1195 *****************************************************************************/
1196 /* from PPC DDK */
1197#ifndef XCPT_CONTINUE_STOP
1198#define XCPT_CONTINUE_STOP 0x00716668
1199#endif
1200
1201// Assembly wrapper for clearing the direction flag before calling our real
1202// exception handler
1203ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1204 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1205 PCONTEXTRECORD pCtxRec,
1206 PVOID p);
1207
1208ULONG APIENTRY OS2ExceptionHandler2ndLevel(PEXCEPTIONREPORTRECORD pERepRec,
1209 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1210 PCONTEXTRECORD pCtxRec,
1211 PVOID p)
1212{
1213#ifdef DEBUG
1214 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1215 // next dprintf won't wait forever
1216 int prevlock = LogException(ENTER_EXCEPTION);
1217#endif
1218
1219// @@VP20040507: no need to sprintf every exception
1220// //Print exception name & exception type
1221// //Not for a guard page exception as sprintfException uses a lot of stack
1222// //and can trigger nested guard page exceptions (crash)
1223// if(pERepRec->ExceptionNum != XCPT_GUARD_PAGE_VIOLATION) {
1224// sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1225// }
1226
1227 /* Access violation at a known location */
1228 switch(pERepRec->ExceptionNum)
1229 {
1230 case XCPT_FLOAT_DENORMAL_OPERAND:
1231 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1232 case XCPT_FLOAT_INEXACT_RESULT:
1233// case XCPT_FLOAT_INVALID_OPERATION:
1234 case XCPT_FLOAT_OVERFLOW:
1235 case XCPT_FLOAT_STACK_CHECK:
1236 case XCPT_FLOAT_UNDERFLOW:
1237 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1238 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1239 if((!fIsOS2Image || fSEHEnabled) && !fExitProcess) //Only for real win32 apps or if SEH enabled
1240 {
1241 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1242 {
1243 pCtxRec->ctx_env[0] |= 0x1F;
1244 pCtxRec->ctx_stack[0].losig = 0;
1245 pCtxRec->ctx_stack[0].hisig = 0;
1246 pCtxRec->ctx_stack[0].signexp = 0;
1247 }
1248 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1249 goto continueexecution;
1250 }
1251 else
1252 {
1253 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1254 goto continuesearch;
1255 }
1256
1257 case XCPT_PROCESS_TERMINATE:
1258 case XCPT_ASYNC_PROCESS_TERMINATE:
1259#if 0
1260 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1261 PrintExceptionChain();
1262#endif
1263 goto continuesearch;
1264
1265 case XCPT_ACCESS_VIOLATION:
1266 {
1267 Win32MemMap *map;
1268 BOOL fWriteAccess = FALSE;
1269 ULONG offset, accessflag;
1270
1271#ifdef WITH_KLIB
1272 if ( pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS
1273 || pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS
1274 || pERepRec->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
1275 || pERepRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS
1276 )
1277 {
1278 ENMACCESS enmAccess = enmRead;
1279 switch (pERepRec->ExceptionInfo[0])
1280 {
1281 case XCPT_WRITE_ACCESS: enmAccess = enmWrite; break;
1282 case XCPT_UNKNOWN_ACCESS: enmAccess = enmUnknown; break;
1283 }
1284
1285 if (kHeapDbgException((void*)pERepRec->ExceptionInfo[1],
1286 enmAccess,
1287 pERepRec->ExceptionAddress,
1288 pERepRec))
1289 goto continueexecution;
1290 }
1291#endif
1292
1293 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1294 goto continueFail;
1295 }
1296
1297//------------->>> WARNING: potentially dangerous workaround!!
1298 /* Some apps set ES = FS and Odin doesn't like that! */
1299 /* Note: maybe we could even check for ES != DS? But maybe */
1300 /* that might cause more harm than good... */
1301 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1302 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1303 /* Let's just reset ES to the DS value and hope it's okay */
1304 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1305 goto continueexecution;
1306 }
1307
1308 switch(pERepRec->ExceptionInfo[0]) {
1309 case XCPT_READ_ACCESS:
1310 accessflag = MEMMAP_ACCESS_READ;
1311 break;
1312 case XCPT_WRITE_ACCESS:
1313 accessflag = MEMMAP_ACCESS_WRITE;
1314 fWriteAccess = TRUE;
1315 break;
1316 case XCPT_EXECUTE_ACCESS:
1317 accessflag = MEMMAP_ACCESS_EXECUTE;
1318 break;
1319 default:
1320 goto continueFail;
1321 }
1322
1323 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1324 if(map == NULL) {
1325 Win32MemMapNotify *map;
1326
1327 map = Win32MemMapNotify::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1328 if(!map)
1329 goto continueFail;
1330
1331 BOOL ret = map->notify(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1332 if(ret == TRUE) goto continueexecution;
1333 goto continueFail;
1334 }
1335 BOOL ret = map->commitPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1336 map->Release();
1337 if(ret == TRUE)
1338 goto continueexecution;
1339
1340 //no break;
1341 }
1342continueFail:
1343
1344 /*
1345 * vladest: OK, try to implement write AUTOCOMMIT
1346 * last chance after MMAP commit is failed
1347 */
1348 if (XCPT_ACCESS_VIOLATION == pERepRec->ExceptionNum &&
1349 (/*pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS ||*/
1350 pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS) &&
1351 pERepRec->ExceptionInfo[1] != XCPT_DATA_UNKNOWN)
1352 {
1353 ULONG offset, accessflag;
1354
1355 DosQueryMem((PVOID) pERepRec->ExceptionInfo[1],
1356 &offset, &accessflag);
1357 dprintf(("KERNEL32: OS2ExceptionHandler: failed address info 0x%X size 0x%X. flag %X\n",
1358 pERepRec->ExceptionInfo[1], offset, accessflag));
1359 /* check for valid address */
1360 if (!pERepRec->ExceptionInfo[1] ||
1361 pERepRec->ExceptionInfo[1] == 0xAAAAAAAA ||
1362 !offset || offset == 0xAAAAAAAA)
1363 goto CrashAndBurn;
1364 /* memory committed, but no write access */
1365 if (accessflag & PAG_GUARD)
1366 accessflag &=~PAG_GUARD;
1367
1368 /* set memory aligned on page size and with size counting alignment */
1369 ULONG rc = DosSetMem((PVOID) (pERepRec->ExceptionInfo[1] & 0xFFFFF000),
1370 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
1371 accessflag | PAG_WRITE | PAG_COMMIT);
1372 dprintf(("KERNEL32: OS2ExceptionHandler: commiting 0x%X size 0x%X. RC: %i\n",
1373 pERepRec->ExceptionInfo[1] & 0xFFFFF000,
1374 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
1375 rc));
1376 if (NO_ERROR == rc)
1377 goto continueexecution;
1378 else
1379 goto CrashAndBurn;
1380 }
1381
1382
1383////#define DEBUGSTACK
1384#ifdef DEBUGSTACK
1385 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1386 ULONG *stackptr;
1387 APIRET rc;
1388 int i;
1389 ULONG ulOffset, ulModule, ulObject;
1390 CHAR szModule[CCHMAXPATH];
1391
1392 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1393 dprintf(("Stack DUMP:"));
1394 for(i=0;i<16;i++) {
1395 rc = DosQueryModFromEIP(&ulModule,
1396 &ulObject,
1397 sizeof(szModule),
1398 szModule,
1399 &ulOffset,
1400 (ULONG)*stackptr);
1401
1402 if (rc == NO_ERROR)
1403 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1404 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1405 stackptr++;
1406 }
1407 dprintf(("Stack DUMP END"));
1408 }
1409#endif
1410 goto CrashAndBurn;
1411
1412 case XCPT_INVALID_LOCK_SEQUENCE:
1413 {
1414 TEB *teb = GetThreadTEB();
1415 USHORT *eip = (USHORT *)pCtxRec->ctx_RegEip;
1416
1417 if(teb && eip && *eip == SETTHREADCONTEXT_INVALID_LOCKOPCODE)
1418 {
1419 //Is this a pending SetThreadContext exception?
1420 //(see detailed description in the HMDeviceThreadClass::SetThreadContext method)
1421 if(teb->o.odin.context.ContextFlags)
1422 {
1423 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1424
1425 //NOTE: This will not work properly in case multiple threads execute this code
1426 dprintf(("Changing thread registers (SetThreadContext)!!"));
1427
1428 if(teb->o.odin.context.ContextFlags & WINCONTEXT_CONTROL) {
1429 pCtxRec->ctx_RegEbp = teb->o.odin.context.Ebp;
1430 pCtxRec->ctx_RegEip = teb->o.odin.context.Eip;
1431//// pCtxRec->ctx_SegCs = teb->o.odin.context.SegCs;
1432 pCtxRec->ctx_EFlags = teb->o.odin.context.EFlags;
1433 pCtxRec->ctx_RegEsp = teb->o.odin.context.Esp;
1434//// pCtxRec->ctx_SegSs = teb->o.odin.context.SegSs;
1435 }
1436 if(teb->o.odin.context.ContextFlags & WINCONTEXT_INTEGER) {
1437 pCtxRec->ctx_RegEdi = teb->o.odin.context.Edi;
1438 pCtxRec->ctx_RegEsi = teb->o.odin.context.Esi;
1439 pCtxRec->ctx_RegEbx = teb->o.odin.context.Ebx;
1440 pCtxRec->ctx_RegEdx = teb->o.odin.context.Edx;
1441 pCtxRec->ctx_RegEcx = teb->o.odin.context.Ecx;
1442 pCtxRec->ctx_RegEax = teb->o.odin.context.Eax;
1443 }
1444 if(teb->o.odin.context.ContextFlags & WINCONTEXT_SEGMENTS) {
1445 pCtxRec->ctx_SegGs = teb->o.odin.context.SegGs;
1446//// pCtxRec->ctx_SegFs = teb->o.odin.context.SegFs;
1447 pCtxRec->ctx_SegEs = teb->o.odin.context.SegEs;
1448 pCtxRec->ctx_SegDs = teb->o.odin.context.SegDs;
1449 }
1450 if(teb->o.odin.context.ContextFlags & WINCONTEXT_FLOATING_POINT) {
1451 //TODO: First 7 dwords the same?
1452 memcpy(pCtxRec->ctx_env, &teb->o.odin.context.FloatSave, sizeof(pCtxRec->ctx_env));
1453 memcpy(pCtxRec->ctx_stack, &teb->o.odin.context.FloatSave.RegisterArea, sizeof(pCtxRec->ctx_stack));
1454 }
1455 USHORT *lpAlias = (USHORT *)((char *)teb->o.odin.lpAlias + teb->o.odin.dwAliasOffset);
1456 *lpAlias = teb->o.odin.savedopcode;
1457
1458 //Clear SetThreadContext markers
1459 teb->o.odin.context.ContextFlags = 0;
1460
1461 OSLibDosFreeMem(teb->o.odin.lpAlias);
1462
1463 teb->o.odin.lpAlias = NULL;
1464 teb->o.odin.dwAliasOffset = 0;
1465
1466 //restore the original priority (we boosted it to ensure this thread was scheduled first)
1467 SetThreadPriority(teb->o.odin.hThread, GetThreadPriority(teb->o.odin.hThread));
1468 goto continueexecution;
1469 }
1470 else DebugInt3(); //oh, oh!!!!!
1471
1472 }
1473 //no break;
1474 }
1475
1476 case XCPT_PRIVILEGED_INSTRUCTION:
1477 case XCPT_ILLEGAL_INSTRUCTION:
1478 case XCPT_BREAKPOINT:
1479 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1480 case XCPT_DATATYPE_MISALIGNMENT:
1481 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1482 case XCPT_INTEGER_OVERFLOW:
1483 case XCPT_SINGLE_STEP:
1484 case XCPT_IN_PAGE_ERROR:
1485CrashAndBurn:
1486 //SvL: TODO: this may not always be the right thing to do
1487 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1488 // of this exception handler. We better bail out ASAP or we'll likely
1489 // recurse infinitely until we run out of stack space!!
1490 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1491 goto continuesearch;
1492
1493#if defined(DEBUG)
1494 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1495
1496 if(!fExitProcess && (pCtxRec->ContextFlags & CONTEXT_CONTROL)) {
1497 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1498 }
1499#endif
1500
1501 if((!fIsOS2Image || fSEHEnabled) && !fExitProcess) //Only for real win32 apps or if SEH enabled
1502 {
1503 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1504 {
1505 goto continueexecution;
1506 }
1507 }
1508 else {
1509 if(fExitProcess) {
1510 PPIB pPIB;
1511 PTIB pTIB;
1512 APIRET rc;
1513
1514 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1515 if(rc == NO_ERROR)
1516 {
1517 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill thread"));
1518
1519 pCtxRec->ctx_RegEip = (pTIB->tib_ptib2->tib2_ultid != 1) ? (ULONG)KillWin32Thread : (ULONG)KillWin32Process;
1520 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1521 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1522 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1523 goto continueexecution;
1524 }
1525 }
1526 goto continuesearch; //pass on to OS/2 RTL or app exception handler
1527 }
1528
1529 //Log fatal exception here
1530 logException(pERepRec, pERegRec, pCtxRec, p);
1531
1532 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1533
1534 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1535 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1536 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1537 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1538 goto continueexecution;
1539
1540 case XCPT_GUARD_PAGE_VIOLATION:
1541 {
1542 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1543 //Don't print anything here -> fatal hang if exception occurred
1544 //inside fprintf
1545 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1546 TEB *teb = GetThreadTEB();
1547 DWORD stacktop, stackbottom;
1548
1549 if(teb == NULL) {
1550 goto continueGuardException;
1551 }
1552
1553 stacktop = (DWORD)teb->stack_top;
1554 stackbottom = (DWORD)teb->stack_low;
1555
1556 stackbottom = stackbottom & ~0xFFF; //round down to page boundary
1557 stacktop = stacktop & ~0xFFF;
1558
1559 //Make sure we detect a stack overflow condition before the system does
1560 if(!fIsOS2Image &&
1561 pERepRec->ExceptionInfo[1] >= stackbottom &&
1562 pERepRec->ExceptionInfo[1] < stacktop
1563 )
1564 {//this is a guard page exception for the thread stack
1565 APIRET rc;
1566 ULONG ulAddress, cbSize, ulMemFlags;
1567
1568 //round down to page boundary
1569 ulAddress = pERepRec->ExceptionInfo[1] & ~0xFFF;
1570
1571#if 0
1572 rc = DosQueryMem((PVOID)ulAddress, &cbSize, &ulMemFlags);
1573 if(rc) {
1574 dprintf(("ERROR: DosQueryMem old guard page failed with rc %d", rc));
1575 goto continueGuardException;
1576 }
1577#endif
1578
1579 if(ulAddress == stackbottom + PAGE_SIZE)
1580 {//we don't have any stack left, throw an XCPT_UNABLE_TO_GROW_STACK
1581 //exception
1582 if(!fExitProcess) //Only for real win32 apps
1583 {
1584 EXCEPTIONREPORTRECORD recoutofstack;
1585
1586 recoutofstack = *pERepRec;
1587 recoutofstack.ExceptionNum = XCPT_UNABLE_TO_GROW_STACK;
1588 recoutofstack.fHandlerFlags = 0;
1589 recoutofstack.NestedExceptionReportRecord = NULL;
1590 recoutofstack.cParameters = 0;
1591
1592 if(OSLibDispatchException(&recoutofstack, pERegRec, pCtxRec, p) == TRUE)
1593 {
1594 goto continueexecution;
1595 }
1596 }
1597 }
1598 }
1599 else
1600 {//check for memory map guard page exception
1601 Win32MemMap *map;
1602 BOOL fWriteAccess = FALSE, ret;
1603 ULONG offset, accessflag;
1604
1605 switch(pERepRec->ExceptionInfo[0]) {
1606 case XCPT_READ_ACCESS:
1607 accessflag = MEMMAP_ACCESS_READ;
1608 break;
1609 case XCPT_WRITE_ACCESS:
1610 accessflag = MEMMAP_ACCESS_WRITE;
1611 fWriteAccess = TRUE;
1612 break;
1613 default:
1614 goto continueGuardException;
1615 }
1616
1617 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1618 if(map) {
1619 ret = map->commitGuardPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1620 map->Release();
1621 if(ret == TRUE)
1622 goto continueexecution;
1623 }
1624 }
1625
1626continueGuardException:
1627 goto continuesearch;
1628 }
1629
1630 case XCPT_UNABLE_TO_GROW_STACK:
1631 {
1632 //SvL: XCPT_UNABLE_TO_GROW_STACK is typically nested (failed guard page
1633 // exception), so don't ignore them
1634 // We should no longer receive those!!
1635// @@VP20040507: Isn't this a bit dangerous to call dprintfon such exception
1636//#ifdef DEBUG
1637// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1638//#endif
1639 goto continuesearch;
1640 }
1641
1642
1643 /*
1644 * In OS/2 VIO Ctrl-C and Ctrl-Break is special stuff which comes in
1645 * thru the exception handler. In Win32 CUI they are handled by a
1646 * ControlCtrlEvent procedure. So, if we receive one of those signals
1647 * we assume that this is a VIO program and let the handlers handle this.
1648 * (If they want to.)
1649 */
1650 case XCPT_SIGNAL:
1651 {
1652 //This is not a reliable way to distinguish between Ctrl-C & Ctrl-Break
1653 BOOL breakPressed = WinGetKeyState(HWND_DESKTOP,VK_BREAK) & 0x8000;
1654
1655 switch (pERepRec->ExceptionInfo[0])
1656 {
1657 case XCPT_SIGNAL_BREAK:
1658 breakPressed = TRUE;
1659 //no break
1660
1661 case XCPT_SIGNAL_INTR:
1662 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1663 if (InternalGenerateConsoleCtrlEvent((breakPressed) ? CTRL_BREAK_EVENT : CTRL_C_EVENT, 0))
1664 {
1665 DosAcknowledgeSignalException(pERepRec->ExceptionInfo[0]);
1666 goto continueexecution;
1667 }
1668 goto continuesearch;
1669
1670 case XCPT_SIGNAL_KILLPROC: /* resolve signal information */
1671 goto continuesearch;
1672 }
1673 goto CrashAndBurn;
1674 }
1675
1676 default: //non-continuable exceptions
1677 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1678 goto continuesearch;
1679 }
1680continuesearch:
1681#ifdef DEBUG
1682 LogException(LEAVE_EXCEPTION, prevlock);
1683#endif
1684 return XCPT_CONTINUE_SEARCH;
1685
1686continueexecution:
1687#ifdef DEBUG
1688 LogException(LEAVE_EXCEPTION, prevlock);
1689#endif
1690 return XCPT_CONTINUE_EXECUTION;
1691}
1692
1693/*****************************************************************************
1694 * Name : void OS2SetExceptionHandler
1695 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1696 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1697 * Variables :
1698 * Result :
1699 * Remark :
1700 * Status :
1701 *
1702 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1703 *****************************************************************************/
1704void OS2SetExceptionHandler(void *exceptframe)
1705{
1706 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1707
1708 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1709 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1710
1711 /* disable trap popups */
1712// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1713
1714 DosSetExceptionHandler(pExceptRec);
1715 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1716#ifdef DEBUG_ENABLELOG_LEVEL2
1717 PrintExceptionChain();
1718#endif
1719}
1720//*****************************************************************************
1721// Set exception handler if our handler has not yet been registered
1722//*****************************************************************************
1723void WIN32API ODIN_SetExceptionHandler(void *pExceptionRegRec)
1724{
1725 BOOL fFound = FALSE;
1726 USHORT sel = RestoreOS2FS();
1727 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1728
1729 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1730 {
1731 if(pExceptRec->ExceptionHandler == OS2ExceptionHandler)
1732 {
1733 fFound = TRUE;
1734 break;
1735 }
1736 pExceptRec = pExceptRec->prev_structure;
1737 }
1738 if(!fFound)
1739 {
1740 OS2SetExceptionHandler(pExceptionRegRec);
1741 }
1742 SetFS(sel);
1743}
1744//*****************************************************************************
1745// Remove exception handler if it was registered previously
1746//
1747//*****************************************************************************
1748void WIN32API ODIN_UnsetExceptionHandler(void *pExceptionRegRec)
1749{
1750 USHORT sel = RestoreOS2FS();
1751 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1752 BOOL fFound = FALSE;
1753
1754 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1755 {
1756 if(pExceptRec == pExceptionRegRec)
1757 {
1758 fFound = TRUE;
1759 break;
1760 }
1761 pExceptRec = pExceptRec->prev_structure;
1762 }
1763
1764#ifdef DEBUG
1765 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1766
1767 if(fFound && pExceptRec != (PEXCEPTIONREGISTRATIONRECORD)pExceptionRegRec)
1768 {
1769 dprintf(("ERROR: ODIN_UnsetExceptionHandler: INSIDE!!!: exc rec %p, head %p\n", pExceptionRegRec, pExceptRec));
1770 PrintExceptionChain ();
1771 }
1772#endif
1773 if(fFound) {
1774 OS2UnsetExceptionHandler(pExceptionRegRec);
1775 }
1776 SetFS(sel);
1777}
1778//*****************************************************************************
1779//*****************************************************************************
1780#ifdef DEBUG
1781void PrintExceptionChain()
1782{
1783 USHORT sel = RestoreOS2FS();
1784 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1785
1786 dprintf(("OS/2 Exception chain:"));
1787 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1788 {
1789 char szBuf[512];
1790 ULONG ulModule;
1791 ULONG ulObject, ulOffset;
1792 CHAR szModule[260];
1793
1794 *szBuf = '\0';
1795 APIRET rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
1796 szModule, &ulOffset, (ULONG)pExceptRec->ExceptionHandler);
1797 if(rc == NO_ERROR && ulObject != -1)
1798 {
1799 sprintf(szBuf, " <%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject + 1, ulOffset);
1800#ifdef RAS
1801 char szSYMInfo[260];
1802
1803 DosQueryModuleName(ulModule, sizeof(szModule), szModule);
1804
1805 int namelen = strlen(szModule);
1806 if(namelen > 3)
1807 {
1808 strcpy(szModule + namelen - 3, "SYM");
1809 dbgGetSYMInfo(szModule, ulObject, ulOffset,
1810 szSYMInfo, sizeof (szSYMInfo), TRUE);
1811 strcat(szBuf, " ");
1812 strcat(szBuf, szSYMInfo);
1813 // remove trailing \n or space
1814 szBuf[strlen(szBuf) - 1] = '\0';
1815 }
1816#endif
1817 }
1818 else
1819 {
1820 *szBuf = '\0';
1821 }
1822
1823 dprintf((" record %08X, prev %08X, handler %08X%s",
1824 pExceptRec, pExceptRec->prev_structure, pExceptRec->ExceptionHandler,
1825 szBuf));
1826
1827 pExceptRec = pExceptRec->prev_structure;
1828 }
1829 dprintf(("END of OS/2 Exception chain."));
1830 SetFS(sel);
1831}
1832//*****************************************************************************
1833//*****************************************************************************
1834void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pFrame)
1835{
1836 dprintf(("Win32 exception chain:"));
1837 while ((pFrame != NULL) && ((ULONG)pFrame != 0xFFFFFFFF))
1838 {
1839 PWINEXCEPTION_FRAME pPrevFrame = __seh_get_prev_frame(pFrame);
1840 dprintf((" Record at %08X, Prev at %08X, handler at %08X%s",
1841 pFrame, pPrevFrame, pFrame->Handler,
1842 pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler ?
1843 " (SEH)" : ""));
1844 if (pFrame == pPrevFrame)
1845 {
1846 dprintf(("Chain corrupted! Record at %08X pointing to itself!",
1847 pFrame));
1848 break;
1849 }
1850 pFrame = pPrevFrame;
1851 }
1852 dprintf(("END of Win32 exception chain."));
1853}
1854#endif
1855
1856/*****************************************************************************
1857 * Name : void OS2UnsetExceptionHandler
1858 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1859 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1860 * Variables :
1861 * Result :
1862 * Remark :
1863 * Status :
1864 *
1865 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1866 *****************************************************************************/
1867void OS2UnsetExceptionHandler(void *exceptframe)
1868{
1869 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1870
1871 DosUnsetExceptionHandler(pExceptRec);
1872 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1873#ifdef DEBUG_ENABLELOG_LEVEL2
1874 PrintExceptionChain();
1875#endif
1876}
1877//*****************************************************************************
1878//*****************************************************************************
1879int _System CheckCurFS()
1880{
1881 USHORT sel = RestoreOS2FS();
1882 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1883
1884 if(sel == 0x150b) {
1885 SetFS(sel);
1886 return FALSE;
1887 }
1888 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1889 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1890 SetFS(sel);
1891 return FALSE;
1892 }
1893 SetFS(sel);
1894 return TRUE;
1895}
1896//*****************************************************************************
1897//*****************************************************************************
1898
Note: See TracBrowser for help on using the repository browser.