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

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

kernel32: Fixed: Parsing .SYM files when printing the stack trace in debug mode was not thread safe which caused garbage and nested crashes.

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