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

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

kernel32: Typo.

File size: 66.9 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) : (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 // fall through
1263#endif
1264 case XCPT_UNWIND:
1265 // Note that printing through ODINCRT (VACRT) when handling XCPT_UNWIND
1266 // is known to create deadlocks
1267 goto continuesearch;
1268
1269 case XCPT_ACCESS_VIOLATION:
1270 {
1271 Win32MemMap *map;
1272 BOOL fWriteAccess = FALSE;
1273 ULONG offset, accessflag;
1274
1275#ifdef WITH_KLIB
1276 if ( pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS
1277 || pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS
1278 || pERepRec->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
1279 || pERepRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS
1280 )
1281 {
1282 ENMACCESS enmAccess = enmRead;
1283 switch (pERepRec->ExceptionInfo[0])
1284 {
1285 case XCPT_WRITE_ACCESS: enmAccess = enmWrite; break;
1286 case XCPT_UNKNOWN_ACCESS: enmAccess = enmUnknown; break;
1287 }
1288
1289 if (kHeapDbgException((void*)pERepRec->ExceptionInfo[1],
1290 enmAccess,
1291 pERepRec->ExceptionAddress,
1292 pERepRec))
1293 goto continueexecution;
1294 }
1295#endif
1296
1297 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1298 goto continueFail;
1299 }
1300
1301//------------->>> WARNING: potentially dangerous workaround!!
1302 /* Some apps set ES = FS and Odin doesn't like that! */
1303 /* Note: maybe we could even check for ES != DS? But maybe */
1304 /* that might cause more harm than good... */
1305 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1306 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1307 /* Let's just reset ES to the DS value and hope it's okay */
1308 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1309 goto continueexecution;
1310 }
1311
1312 switch(pERepRec->ExceptionInfo[0]) {
1313 case XCPT_READ_ACCESS:
1314 accessflag = MEMMAP_ACCESS_READ;
1315 break;
1316 case XCPT_WRITE_ACCESS:
1317 accessflag = MEMMAP_ACCESS_WRITE;
1318 fWriteAccess = TRUE;
1319 break;
1320 case XCPT_EXECUTE_ACCESS:
1321 accessflag = MEMMAP_ACCESS_EXECUTE;
1322 break;
1323 default:
1324 goto continueFail;
1325 }
1326
1327 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1328 if(map == NULL) {
1329 Win32MemMapNotify *map;
1330
1331 map = Win32MemMapNotify::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1332 if(!map)
1333 goto continueFail;
1334
1335 BOOL ret = map->notify(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1336 if(ret == TRUE) goto continueexecution;
1337 goto continueFail;
1338 }
1339 BOOL ret = map->commitPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1340 map->Release();
1341 if(ret == TRUE)
1342 goto continueexecution;
1343
1344 //no break;
1345 }
1346continueFail:
1347
1348 /*
1349 * vladest: OK, try to implement write AUTOCOMMIT
1350 * last chance after MMAP commit is failed
1351 */
1352 if (XCPT_ACCESS_VIOLATION == pERepRec->ExceptionNum &&
1353 (/*pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS ||*/
1354 pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS) &&
1355 pERepRec->ExceptionInfo[1] != XCPT_DATA_UNKNOWN)
1356 {
1357 ULONG offset, accessflag;
1358
1359 DosQueryMem((PVOID) pERepRec->ExceptionInfo[1],
1360 &offset, &accessflag);
1361 dprintf(("KERNEL32: OS2ExceptionHandler: failed address info 0x%X size 0x%X. flag %X\n",
1362 pERepRec->ExceptionInfo[1], offset, accessflag));
1363 /* check for valid address */
1364 if (!pERepRec->ExceptionInfo[1] ||
1365 pERepRec->ExceptionInfo[1] == 0xAAAAAAAA ||
1366 !offset || offset == 0xAAAAAAAA)
1367 goto CrashAndBurn;
1368 /* memory committed, but no write access */
1369 if (accessflag & PAG_GUARD)
1370 accessflag &=~PAG_GUARD;
1371
1372 /* set memory aligned on page size and with size counting alignment */
1373 ULONG rc = DosSetMem((PVOID) (pERepRec->ExceptionInfo[1] & 0xFFFFF000),
1374 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
1375 accessflag | PAG_WRITE | PAG_COMMIT);
1376 dprintf(("KERNEL32: OS2ExceptionHandler: commiting 0x%X size 0x%X. RC: %i\n",
1377 pERepRec->ExceptionInfo[1] & 0xFFFFF000,
1378 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
1379 rc));
1380 if (NO_ERROR == rc)
1381 goto continueexecution;
1382 else
1383 goto CrashAndBurn;
1384 }
1385
1386
1387////#define DEBUGSTACK
1388#ifdef DEBUGSTACK
1389 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1390 ULONG *stackptr;
1391 APIRET rc;
1392 int i;
1393 ULONG ulOffset, ulModule, ulObject;
1394 CHAR szModule[CCHMAXPATH];
1395
1396 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1397 dprintf(("Stack DUMP:"));
1398 for(i=0;i<16;i++) {
1399 rc = DosQueryModFromEIP(&ulModule,
1400 &ulObject,
1401 sizeof(szModule),
1402 szModule,
1403 &ulOffset,
1404 (ULONG)*stackptr);
1405
1406 if (rc == NO_ERROR)
1407 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1408 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1409 stackptr++;
1410 }
1411 dprintf(("Stack DUMP END"));
1412 }
1413#endif
1414 goto CrashAndBurn;
1415
1416 case XCPT_INVALID_LOCK_SEQUENCE:
1417 {
1418 TEB *teb = GetThreadTEB();
1419 USHORT *eip = (USHORT *)pCtxRec->ctx_RegEip;
1420
1421 if(teb && eip && *eip == SETTHREADCONTEXT_INVALID_LOCKOPCODE)
1422 {
1423 //Is this a pending SetThreadContext exception?
1424 //(see detailed description in the HMDeviceThreadClass::SetThreadContext method)
1425 if(teb->o.odin.context.ContextFlags)
1426 {
1427 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1428
1429 //NOTE: This will not work properly in case multiple threads execute this code
1430 dprintf(("Changing thread registers (SetThreadContext)!!"));
1431
1432 if(teb->o.odin.context.ContextFlags & WINCONTEXT_CONTROL) {
1433 pCtxRec->ctx_RegEbp = teb->o.odin.context.Ebp;
1434 pCtxRec->ctx_RegEip = teb->o.odin.context.Eip;
1435//// pCtxRec->ctx_SegCs = teb->o.odin.context.SegCs;
1436 pCtxRec->ctx_EFlags = teb->o.odin.context.EFlags;
1437 pCtxRec->ctx_RegEsp = teb->o.odin.context.Esp;
1438//// pCtxRec->ctx_SegSs = teb->o.odin.context.SegSs;
1439 }
1440 if(teb->o.odin.context.ContextFlags & WINCONTEXT_INTEGER) {
1441 pCtxRec->ctx_RegEdi = teb->o.odin.context.Edi;
1442 pCtxRec->ctx_RegEsi = teb->o.odin.context.Esi;
1443 pCtxRec->ctx_RegEbx = teb->o.odin.context.Ebx;
1444 pCtxRec->ctx_RegEdx = teb->o.odin.context.Edx;
1445 pCtxRec->ctx_RegEcx = teb->o.odin.context.Ecx;
1446 pCtxRec->ctx_RegEax = teb->o.odin.context.Eax;
1447 }
1448 if(teb->o.odin.context.ContextFlags & WINCONTEXT_SEGMENTS) {
1449 pCtxRec->ctx_SegGs = teb->o.odin.context.SegGs;
1450//// pCtxRec->ctx_SegFs = teb->o.odin.context.SegFs;
1451 pCtxRec->ctx_SegEs = teb->o.odin.context.SegEs;
1452 pCtxRec->ctx_SegDs = teb->o.odin.context.SegDs;
1453 }
1454 if(teb->o.odin.context.ContextFlags & WINCONTEXT_FLOATING_POINT) {
1455 //TODO: First 7 dwords the same?
1456 memcpy(pCtxRec->ctx_env, &teb->o.odin.context.FloatSave, sizeof(pCtxRec->ctx_env));
1457 memcpy(pCtxRec->ctx_stack, &teb->o.odin.context.FloatSave.RegisterArea, sizeof(pCtxRec->ctx_stack));
1458 }
1459 USHORT *lpAlias = (USHORT *)((char *)teb->o.odin.lpAlias + teb->o.odin.dwAliasOffset);
1460 *lpAlias = teb->o.odin.savedopcode;
1461
1462 //Clear SetThreadContext markers
1463 teb->o.odin.context.ContextFlags = 0;
1464
1465 OSLibDosFreeMem(teb->o.odin.lpAlias);
1466
1467 teb->o.odin.lpAlias = NULL;
1468 teb->o.odin.dwAliasOffset = 0;
1469
1470 //restore the original priority (we boosted it to ensure this thread was scheduled first)
1471 SetThreadPriority(teb->o.odin.hThread, GetThreadPriority(teb->o.odin.hThread));
1472 goto continueexecution;
1473 }
1474 else DebugInt3(); //oh, oh!!!!!
1475
1476 }
1477 //no break;
1478 }
1479
1480 case XCPT_PRIVILEGED_INSTRUCTION:
1481 case XCPT_ILLEGAL_INSTRUCTION:
1482 case XCPT_BREAKPOINT:
1483 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1484 case XCPT_DATATYPE_MISALIGNMENT:
1485 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1486 case XCPT_INTEGER_OVERFLOW:
1487 case XCPT_SINGLE_STEP:
1488 case XCPT_IN_PAGE_ERROR:
1489CrashAndBurn:
1490 //SvL: TODO: this may not always be the right thing to do
1491 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1492 // of this exception handler. We better bail out ASAP or we'll likely
1493 // recurse infinitely until we run out of stack space!!
1494 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1495 goto continuesearch;
1496
1497#if defined(DEBUG)
1498 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1499
1500 if(!fExitProcess && (pCtxRec->ContextFlags & CONTEXT_CONTROL)) {
1501 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1502 }
1503#endif
1504
1505 if((!fIsOS2Image || fSEHEnabled) && !fExitProcess) //Only for real win32 apps or if SEH enabled
1506 {
1507 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1508 {
1509 goto continueexecution;
1510 }
1511 }
1512 else {
1513 if(fExitProcess) {
1514 PPIB pPIB;
1515 PTIB pTIB;
1516 APIRET rc;
1517
1518 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1519 if(rc == NO_ERROR)
1520 {
1521 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill thread"));
1522
1523 pCtxRec->ctx_RegEip = (pTIB->tib_ptib2->tib2_ultid != 1) ? (ULONG)KillWin32Thread : (ULONG)KillWin32Process;
1524 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1525 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1526 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1527 goto continueexecution;
1528 }
1529 }
1530 goto continuesearch; //pass on to OS/2 RTL or app exception handler
1531 }
1532
1533 //Log fatal exception here
1534 logException(pERepRec, pERegRec, pCtxRec, p);
1535
1536 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1537
1538 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1539 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1540 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1541 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1542 goto continueexecution;
1543
1544 case XCPT_GUARD_PAGE_VIOLATION:
1545 {
1546 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1547 //Don't print anything here -> fatal hang if exception occurred
1548 //inside fprintf
1549 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1550 TEB *teb = GetThreadTEB();
1551 DWORD stacktop, stackbottom;
1552
1553 if(teb == NULL) {
1554 goto continueGuardException;
1555 }
1556
1557 stacktop = (DWORD)teb->stack_top;
1558 stackbottom = (DWORD)teb->stack_low;
1559
1560 stackbottom = stackbottom & ~0xFFF; //round down to page boundary
1561 stacktop = stacktop & ~0xFFF;
1562
1563 //Make sure we detect a stack overflow condition before the system does
1564 if(!fIsOS2Image &&
1565 pERepRec->ExceptionInfo[1] >= stackbottom &&
1566 pERepRec->ExceptionInfo[1] < stacktop
1567 )
1568 {//this is a guard page exception for the thread stack
1569 APIRET rc;
1570 ULONG ulAddress, cbSize, ulMemFlags;
1571
1572 //round down to page boundary
1573 ulAddress = pERepRec->ExceptionInfo[1] & ~0xFFF;
1574
1575#if 0
1576 rc = DosQueryMem((PVOID)ulAddress, &cbSize, &ulMemFlags);
1577 if(rc) {
1578 dprintf(("ERROR: DosQueryMem old guard page failed with rc %d", rc));
1579 goto continueGuardException;
1580 }
1581#endif
1582
1583 if(ulAddress == stackbottom + PAGE_SIZE)
1584 {//we don't have any stack left, throw an XCPT_UNABLE_TO_GROW_STACK
1585 //exception
1586 if(!fExitProcess) //Only for real win32 apps
1587 {
1588 EXCEPTIONREPORTRECORD recoutofstack;
1589
1590 recoutofstack = *pERepRec;
1591 recoutofstack.ExceptionNum = XCPT_UNABLE_TO_GROW_STACK;
1592 recoutofstack.fHandlerFlags = 0;
1593 recoutofstack.NestedExceptionReportRecord = NULL;
1594 recoutofstack.cParameters = 0;
1595
1596 if(OSLibDispatchException(&recoutofstack, pERegRec, pCtxRec, p) == TRUE)
1597 {
1598 goto continueexecution;
1599 }
1600 }
1601 }
1602 }
1603 else
1604 {//check for memory map guard page exception
1605 Win32MemMap *map;
1606 BOOL fWriteAccess = FALSE, ret;
1607 ULONG offset, accessflag;
1608
1609 switch(pERepRec->ExceptionInfo[0]) {
1610 case XCPT_READ_ACCESS:
1611 accessflag = MEMMAP_ACCESS_READ;
1612 break;
1613 case XCPT_WRITE_ACCESS:
1614 accessflag = MEMMAP_ACCESS_WRITE;
1615 fWriteAccess = TRUE;
1616 break;
1617 default:
1618 goto continueGuardException;
1619 }
1620
1621 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1622 if(map) {
1623 ret = map->commitGuardPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1624 map->Release();
1625 if(ret == TRUE)
1626 goto continueexecution;
1627 }
1628 }
1629
1630continueGuardException:
1631 goto continuesearch;
1632 }
1633
1634 case XCPT_UNABLE_TO_GROW_STACK:
1635 {
1636 //SvL: XCPT_UNABLE_TO_GROW_STACK is typically nested (failed guard page
1637 // exception), so don't ignore them
1638 // We should no longer receive those!!
1639// @@VP20040507: Isn't this a bit dangerous to call dprintfon such exception
1640//#ifdef DEBUG
1641// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1642//#endif
1643 goto continuesearch;
1644 }
1645
1646
1647 /*
1648 * In OS/2 VIO Ctrl-C and Ctrl-Break is special stuff which comes in
1649 * thru the exception handler. In Win32 CUI they are handled by a
1650 * ControlCtrlEvent procedure. So, if we receive one of those signals
1651 * we assume that this is a VIO program and let the handlers handle this.
1652 * (If they want to.)
1653 */
1654 case XCPT_SIGNAL:
1655 {
1656 //This is not a reliable way to distinguish between Ctrl-C & Ctrl-Break
1657 BOOL breakPressed = WinGetKeyState(HWND_DESKTOP,VK_BREAK) & 0x8000;
1658
1659 switch (pERepRec->ExceptionInfo[0])
1660 {
1661 case XCPT_SIGNAL_BREAK:
1662 breakPressed = TRUE;
1663 //no break
1664
1665 case XCPT_SIGNAL_INTR:
1666 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1667 if (InternalGenerateConsoleCtrlEvent((breakPressed) ? CTRL_BREAK_EVENT : CTRL_C_EVENT, 0))
1668 {
1669 DosAcknowledgeSignalException(pERepRec->ExceptionInfo[0]);
1670 goto continueexecution;
1671 }
1672 goto continuesearch;
1673
1674 case XCPT_SIGNAL_KILLPROC: /* resolve signal information */
1675 goto continuesearch;
1676 }
1677 goto CrashAndBurn;
1678 }
1679
1680 default: //non-continuable exceptions
1681 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1682 goto continuesearch;
1683 }
1684continuesearch:
1685#ifdef DEBUG
1686 LogException(LEAVE_EXCEPTION, prevlock);
1687#endif
1688 return XCPT_CONTINUE_SEARCH;
1689
1690continueexecution:
1691#ifdef DEBUG
1692 LogException(LEAVE_EXCEPTION, prevlock);
1693#endif
1694 return XCPT_CONTINUE_EXECUTION;
1695}
1696
1697/*****************************************************************************
1698 * Name : void OS2SetExceptionHandler
1699 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1700 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1701 * Variables :
1702 * Result :
1703 * Remark :
1704 * Status :
1705 *
1706 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1707 *****************************************************************************/
1708void OS2SetExceptionHandler(void *exceptframe)
1709{
1710 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1711
1712 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1713 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1714
1715 /* disable trap popups */
1716// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1717
1718 DosSetExceptionHandler(pExceptRec);
1719 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1720#ifdef DEBUG_ENABLELOG_LEVEL2
1721 PrintExceptionChain();
1722#endif
1723}
1724//*****************************************************************************
1725// Set exception handler if our handler has not yet been registered
1726//*****************************************************************************
1727void WIN32API ODIN_SetExceptionHandler(void *pExceptionRegRec)
1728{
1729 BOOL fFound = FALSE;
1730 USHORT sel = RestoreOS2FS();
1731 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1732
1733 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1734 {
1735 if(pExceptRec->ExceptionHandler == OS2ExceptionHandler)
1736 {
1737 fFound = TRUE;
1738 break;
1739 }
1740 pExceptRec = pExceptRec->prev_structure;
1741 }
1742 if(!fFound)
1743 {
1744 OS2SetExceptionHandler(pExceptionRegRec);
1745 }
1746 SetFS(sel);
1747}
1748//*****************************************************************************
1749// Remove exception handler if it was registered previously
1750//
1751//*****************************************************************************
1752void WIN32API ODIN_UnsetExceptionHandler(void *pExceptionRegRec)
1753{
1754 USHORT sel = RestoreOS2FS();
1755 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1756 BOOL fFound = FALSE;
1757
1758 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1759 {
1760 if(pExceptRec == pExceptionRegRec)
1761 {
1762 fFound = TRUE;
1763 break;
1764 }
1765 pExceptRec = pExceptRec->prev_structure;
1766 }
1767
1768#ifdef DEBUG
1769 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1770
1771 if(fFound && pExceptRec != (PEXCEPTIONREGISTRATIONRECORD)pExceptionRegRec)
1772 {
1773 dprintf(("ERROR: ODIN_UnsetExceptionHandler: INSIDE!!!: exc rec %p, head %p\n", pExceptionRegRec, pExceptRec));
1774 PrintExceptionChain ();
1775 }
1776#endif
1777 if(fFound) {
1778 OS2UnsetExceptionHandler(pExceptionRegRec);
1779 }
1780 SetFS(sel);
1781}
1782//*****************************************************************************
1783//*****************************************************************************
1784#ifdef DEBUG
1785void PrintExceptionChain()
1786{
1787 USHORT sel = RestoreOS2FS();
1788 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1789
1790 dprintf(("OS/2 Exception chain:"));
1791 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1792 {
1793 char szBuf[512];
1794 ULONG ulModule;
1795 ULONG ulObject, ulOffset;
1796 CHAR szModule[260];
1797
1798 *szBuf = '\0';
1799 APIRET rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
1800 szModule, &ulOffset, (ULONG)pExceptRec->ExceptionHandler);
1801 if(rc == NO_ERROR && ulObject != -1)
1802 {
1803 sprintf(szBuf, " <%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject + 1, ulOffset);
1804#ifdef RAS
1805 char szSYMInfo[260];
1806
1807 DosQueryModuleName(ulModule, sizeof(szModule), szModule);
1808
1809 int namelen = strlen(szModule);
1810 if(namelen > 3)
1811 {
1812 strcpy(szModule + namelen - 3, "SYM");
1813 dbgGetSYMInfo(szModule, ulObject, ulOffset,
1814 szSYMInfo, sizeof (szSYMInfo), TRUE);
1815 strcat(szBuf, " ");
1816 strcat(szBuf, szSYMInfo);
1817 // remove trailing \n or space
1818 szBuf[strlen(szBuf) - 1] = '\0';
1819 }
1820#endif
1821 }
1822 else
1823 {
1824 *szBuf = '\0';
1825 }
1826
1827 dprintf((" record %08X, prev %08X, handler %08X%s",
1828 pExceptRec, pExceptRec->prev_structure, pExceptRec->ExceptionHandler,
1829 szBuf));
1830
1831 pExceptRec = pExceptRec->prev_structure;
1832 }
1833 dprintf(("END of OS/2 Exception chain."));
1834 SetFS(sel);
1835}
1836//*****************************************************************************
1837//*****************************************************************************
1838void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pFrame)
1839{
1840 dprintf(("Win32 exception chain:"));
1841 while ((pFrame != NULL) && ((ULONG)pFrame != 0xFFFFFFFF))
1842 {
1843 PWINEXCEPTION_FRAME pPrevFrame = __seh_get_prev_frame(pFrame);
1844 dprintf((" Record at %08X, Prev at %08X, handler at %08X%s",
1845 pFrame, pPrevFrame, pFrame->Handler,
1846 pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler ?
1847 " (SEH)" : ""));
1848 if (pFrame == pPrevFrame)
1849 {
1850 dprintf(("Chain corrupted! Record at %08X pointing to itself!",
1851 pFrame));
1852 break;
1853 }
1854 pFrame = pPrevFrame;
1855 }
1856 dprintf(("END of Win32 exception chain."));
1857}
1858#endif
1859
1860/*****************************************************************************
1861 * Name : void OS2UnsetExceptionHandler
1862 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1863 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1864 * Variables :
1865 * Result :
1866 * Remark :
1867 * Status :
1868 *
1869 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1870 *****************************************************************************/
1871void OS2UnsetExceptionHandler(void *exceptframe)
1872{
1873 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1874
1875 DosUnsetExceptionHandler(pExceptRec);
1876 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1877#ifdef DEBUG_ENABLELOG_LEVEL2
1878 PrintExceptionChain();
1879#endif
1880}
1881//*****************************************************************************
1882//*****************************************************************************
1883int _System CheckCurFS()
1884{
1885 USHORT sel = RestoreOS2FS();
1886 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1887
1888 if(sel == 0x150b) {
1889 SetFS(sel);
1890 return FALSE;
1891 }
1892 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1893 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1894 SetFS(sel);
1895 return FALSE;
1896 }
1897 SetFS(sel);
1898 return TRUE;
1899}
1900//*****************************************************************************
1901//*****************************************************************************
1902
Note: See TracBrowser for help on using the repository browser.