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

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