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

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

kernel32: SEH: Fixed crashes at process termination (exceptions c0010001 and c0010002 in POPUPLOG.OS2) caused by attempting to unwind the Win32 exception chain twice, the second time after destroying the Win32 TEB block.

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