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

Last change on this file since 21473 was 21473, checked in by dmik, 15 years ago

kernel32: Do not attempt to dereference a certainly invalid pointer in the debug message.

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