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

Last change on this file since 21329 was 21329, checked in by vladest, 16 years ago

Added functionality, required for Flash10 to kernel32

File size: 64.5 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 DosSetMem((PVOID) pERepRec->ExceptionInfo[1], offset,
1337 accessflag | PAG_WRITE | PAG_COMMIT);
1338 dprintf(("KERNEL32: OS2ExceptionHandler: commiting 0x%X size 0x%X\n",
1339 pERepRec->ExceptionInfo[1], offset));
1340 goto continueexecution;
1341 }
1342
1343
1344////#define DEBUGSTACK
1345#ifdef DEBUGSTACK
1346 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1347 ULONG *stackptr;
1348 APIRET rc;
1349 int i;
1350 ULONG ulOffset, ulModule, ulObject;
1351 CHAR szModule[CCHMAXPATH];
1352
1353 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1354 dprintf(("Stack DUMP:"));
1355 for(i=0;i<16;i++) {
1356 rc = DosQueryModFromEIP(&ulModule,
1357 &ulObject,
1358 sizeof(szModule),
1359 szModule,
1360 &ulOffset,
1361 (ULONG)*stackptr);
1362
1363 if (rc == NO_ERROR)
1364 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1365 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1366 stackptr++;
1367 }
1368 dprintf(("Stack DUMP END"));
1369 }
1370#endif
1371 goto CrashAndBurn;
1372
1373 case XCPT_INVALID_LOCK_SEQUENCE:
1374 {
1375 TEB *teb = GetThreadTEB();
1376 USHORT *eip = (USHORT *)pCtxRec->ctx_RegEip;
1377
1378 if(teb && eip && *eip == SETTHREADCONTEXT_INVALID_LOCKOPCODE)
1379 {
1380 //Is this a pending SetThreadContext exception?
1381 //(see detailed description in the HMDeviceThreadClass::SetThreadContext method)
1382 if(teb->o.odin.context.ContextFlags)
1383 {
1384 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1385
1386 //NOTE: This will not work properly in case multiple threads execute this code
1387 dprintf(("Changing thread registers (SetThreadContext)!!"));
1388
1389 if(teb->o.odin.context.ContextFlags & WINCONTEXT_CONTROL) {
1390 pCtxRec->ctx_RegEbp = teb->o.odin.context.Ebp;
1391 pCtxRec->ctx_RegEip = teb->o.odin.context.Eip;
1392//// pCtxRec->ctx_SegCs = teb->o.odin.context.SegCs;
1393 pCtxRec->ctx_EFlags = teb->o.odin.context.EFlags;
1394 pCtxRec->ctx_RegEsp = teb->o.odin.context.Esp;
1395//// pCtxRec->ctx_SegSs = teb->o.odin.context.SegSs;
1396 }
1397 if(teb->o.odin.context.ContextFlags & WINCONTEXT_INTEGER) {
1398 pCtxRec->ctx_RegEdi = teb->o.odin.context.Edi;
1399 pCtxRec->ctx_RegEsi = teb->o.odin.context.Esi;
1400 pCtxRec->ctx_RegEbx = teb->o.odin.context.Ebx;
1401 pCtxRec->ctx_RegEdx = teb->o.odin.context.Edx;
1402 pCtxRec->ctx_RegEcx = teb->o.odin.context.Ecx;
1403 pCtxRec->ctx_RegEax = teb->o.odin.context.Eax;
1404 }
1405 if(teb->o.odin.context.ContextFlags & WINCONTEXT_SEGMENTS) {
1406 pCtxRec->ctx_SegGs = teb->o.odin.context.SegGs;
1407//// pCtxRec->ctx_SegFs = teb->o.odin.context.SegFs;
1408 pCtxRec->ctx_SegEs = teb->o.odin.context.SegEs;
1409 pCtxRec->ctx_SegDs = teb->o.odin.context.SegDs;
1410 }
1411 if(teb->o.odin.context.ContextFlags & WINCONTEXT_FLOATING_POINT) {
1412 //TODO: First 7 dwords the same?
1413 memcpy(pCtxRec->ctx_env, &teb->o.odin.context.FloatSave, sizeof(pCtxRec->ctx_env));
1414 memcpy(pCtxRec->ctx_stack, &teb->o.odin.context.FloatSave.RegisterArea, sizeof(pCtxRec->ctx_stack));
1415 }
1416 USHORT *lpAlias = (USHORT *)((char *)teb->o.odin.lpAlias + teb->o.odin.dwAliasOffset);
1417 *lpAlias = teb->o.odin.savedopcode;
1418
1419 //Clear SetThreadContext markers
1420 teb->o.odin.context.ContextFlags = 0;
1421
1422 OSLibDosFreeMem(teb->o.odin.lpAlias);
1423
1424 teb->o.odin.lpAlias = NULL;
1425 teb->o.odin.dwAliasOffset = 0;
1426
1427 //restore the original priority (we boosted it to ensure this thread was scheduled first)
1428 SetThreadPriority(teb->o.odin.hThread, GetThreadPriority(teb->o.odin.hThread));
1429 goto continueexecution;
1430 }
1431 else DebugInt3(); //oh, oh!!!!!
1432
1433 }
1434 //no break;
1435 }
1436
1437 case XCPT_PRIVILEGED_INSTRUCTION:
1438 case XCPT_ILLEGAL_INSTRUCTION:
1439 case XCPT_BREAKPOINT:
1440 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1441 case XCPT_DATATYPE_MISALIGNMENT:
1442 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1443 case XCPT_INTEGER_OVERFLOW:
1444 case XCPT_SINGLE_STEP:
1445 case XCPT_IN_PAGE_ERROR:
1446CrashAndBurn:
1447 //SvL: TODO: this may not always be the right thing to do
1448 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1449 // of this exception handler. We better bail out ASAP or we'll likely
1450 // recurse infinitely until we run out of stack space!!
1451 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1452 goto continuesearch;
1453
1454#if defined(DEBUG) || defined(RAS)
1455 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1456
1457 if(!fExitProcess && (pCtxRec->ContextFlags & CONTEXT_CONTROL)) {
1458 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1459 }
1460#endif
1461
1462 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1463 {
1464 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1465 {
1466 goto continueexecution;
1467 }
1468 }
1469 else {
1470 if(fExitProcess) {
1471 PPIB pPIB;
1472 PTIB pTIB;
1473 APIRET rc;
1474
1475 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1476 if(rc == NO_ERROR)
1477 {
1478 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill thread"));
1479
1480 pCtxRec->ctx_RegEip = (pTIB->tib_ptib2->tib2_ultid != 1) ? (ULONG)KillWin32Thread : (ULONG)KillWin32Process;
1481 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1482 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1483 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1484 goto continueexecution;
1485 }
1486 }
1487 goto continuesearch; //pass on to OS/2 RTL or app exception handler
1488 }
1489
1490 //Log fatal exception here
1491 logException(pERepRec, pERegRec, pCtxRec, p);
1492
1493 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1494
1495 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1496 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1497 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1498 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1499 goto continueexecution;
1500
1501 case XCPT_GUARD_PAGE_VIOLATION:
1502 {
1503 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1504 //Don't print anything here -> fatal hang if exception occurred
1505 //inside fprintf
1506 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1507 TEB *teb = GetThreadTEB();
1508 DWORD stacktop, stackbottom;
1509
1510 if(teb == NULL) {
1511 goto continueGuardException;
1512 }
1513
1514 stacktop = (DWORD)teb->stack_top;
1515 stackbottom = (DWORD)teb->stack_low;
1516
1517 stackbottom = stackbottom & ~0xFFF; //round down to page boundary
1518 stacktop = stacktop & ~0xFFF;
1519
1520 //Make sure we detect a stack overflow condition before the system does
1521 if(!fIsOS2Image &&
1522 pERepRec->ExceptionInfo[1] >= stackbottom &&
1523 pERepRec->ExceptionInfo[1] < stacktop
1524 )
1525 {//this is a guard page exception for the thread stack
1526 APIRET rc;
1527 ULONG ulAddress, cbSize, ulMemFlags;
1528
1529 //round down to page boundary
1530 ulAddress = pERepRec->ExceptionInfo[1] & ~0xFFF;
1531
1532#if 0
1533 rc = DosQueryMem((PVOID)ulAddress, &cbSize, &ulMemFlags);
1534 if(rc) {
1535 dprintf(("ERROR: DosQueryMem old guard page failed with rc %d", rc));
1536 goto continueGuardException;
1537 }
1538#endif
1539
1540 if(ulAddress == stackbottom + PAGE_SIZE)
1541 {//we don't have any stack left, throw an XCPT_UNABLE_TO_GROW_STACK
1542 //exception
1543 if(!fExitProcess) //Only for real win32 apps
1544 {
1545 EXCEPTIONREPORTRECORD recoutofstack;
1546
1547 recoutofstack = *pERepRec;
1548 recoutofstack.ExceptionNum = XCPT_UNABLE_TO_GROW_STACK;
1549 recoutofstack.fHandlerFlags = 0;
1550 recoutofstack.NestedExceptionReportRecord = NULL;
1551 recoutofstack.cParameters = 0;
1552
1553 if(OSLibDispatchException(&recoutofstack, pERegRec, pCtxRec, p) == TRUE)
1554 {
1555 goto continueexecution;
1556 }
1557 }
1558 }
1559 }
1560 else
1561 {//check for memory map guard page exception
1562 Win32MemMap *map;
1563 BOOL fWriteAccess = FALSE, ret;
1564 ULONG offset, accessflag;
1565
1566 switch(pERepRec->ExceptionInfo[0]) {
1567 case XCPT_READ_ACCESS:
1568 accessflag = MEMMAP_ACCESS_READ;
1569 break;
1570 case XCPT_WRITE_ACCESS:
1571 accessflag = MEMMAP_ACCESS_WRITE;
1572 fWriteAccess = TRUE;
1573 break;
1574 default:
1575 goto continueGuardException;
1576 }
1577
1578 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1579 if(map) {
1580 ret = map->commitGuardPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1581 map->Release();
1582 if(ret == TRUE)
1583 goto continueexecution;
1584 }
1585 }
1586
1587continueGuardException:
1588 goto continuesearch;
1589 }
1590
1591 case XCPT_UNABLE_TO_GROW_STACK:
1592 {
1593 //SvL: XCPT_UNABLE_TO_GROW_STACK is typically nested (failed guard page
1594 // exception), so don't ignore them
1595 // We should no longer receive those!!
1596// @@VP20040507: Isn't this a bit dangerous to call dprintfon such exception
1597//#ifdef DEBUG
1598// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1599//#endif
1600 goto continuesearch;
1601 }
1602
1603
1604 /*
1605 * In OS/2 VIO Ctrl-C and Ctrl-Break is special stuff which comes in
1606 * thru the exception handler. In Win32 CUI they are handled by a
1607 * ControlCtrlEvent procedure. So, if we receive one of those signals
1608 * we assume that this is a VIO program and let the handlers handle this.
1609 * (If they want to.)
1610 */
1611 case XCPT_SIGNAL:
1612 {
1613 //This is not a reliable way to distinguish between Ctrl-C & Ctrl-Break
1614 BOOL breakPressed = WinGetKeyState(HWND_DESKTOP,VK_BREAK) & 0x8000;
1615
1616 switch (pERepRec->ExceptionInfo[0])
1617 {
1618 case XCPT_SIGNAL_BREAK:
1619 breakPressed = TRUE;
1620 //no break
1621
1622 case XCPT_SIGNAL_INTR:
1623 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1624 if (InternalGenerateConsoleCtrlEvent((breakPressed) ? CTRL_BREAK_EVENT : CTRL_C_EVENT, 0))
1625 {
1626 DosAcknowledgeSignalException(pERepRec->ExceptionInfo[0]);
1627 goto continueexecution;
1628 }
1629 goto continuesearch;
1630
1631 case XCPT_SIGNAL_KILLPROC: /* resolve signal information */
1632 SetExceptionChain((ULONG)-1);
1633 goto continuesearch;
1634 }
1635 goto CrashAndBurn;
1636 }
1637
1638 default: //non-continuable exceptions
1639 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1640 goto continuesearch;
1641 }
1642continuesearch:
1643 LogException(LEAVE_EXCEPTION, prevlock);
1644 return XCPT_CONTINUE_SEARCH;
1645
1646continueexecution:
1647 LogException(LEAVE_EXCEPTION, prevlock);
1648 return XCPT_CONTINUE_EXECUTION;
1649}
1650
1651/*****************************************************************************
1652 * Name : void OS2SetExceptionHandler
1653 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1654 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1655 * Variables :
1656 * Result :
1657 * Remark :
1658 * Status :
1659 *
1660 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1661 *****************************************************************************/
1662void OS2SetExceptionHandler(void *exceptframe)
1663{
1664 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1665
1666 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1667 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1668
1669 /* disable trap popups */
1670// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1671
1672 DosSetExceptionHandler(pExceptRec);
1673 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1674#ifdef DEBUG_ENABLELOG_LEVEL2
1675 PrintExceptionChain();
1676#endif
1677}
1678//*****************************************************************************
1679// Set exception handler if our handler has not yet been registered
1680//*****************************************************************************
1681void WIN32API ODIN_SetExceptionHandler(void *pExceptionRegRec)
1682{
1683 BOOL fFound = FALSE;
1684 USHORT sel = RestoreOS2FS();
1685 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1686
1687 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1688 {
1689 if(pExceptRec->ExceptionHandler == OS2ExceptionHandler)
1690 {
1691 fFound = TRUE;
1692 break;
1693 }
1694 pExceptRec = pExceptRec->prev_structure;
1695 }
1696 if(!fFound)
1697 {
1698 OS2SetExceptionHandler(pExceptionRegRec);
1699 }
1700 SetFS(sel);
1701}
1702//*****************************************************************************
1703// Remove exception handler if it was registered previously
1704//
1705//*****************************************************************************
1706void WIN32API ODIN_UnsetExceptionHandler(void *pExceptionRegRec)
1707{
1708 USHORT sel = RestoreOS2FS();
1709 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1710 BOOL fFound = FALSE;
1711
1712 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1713 {
1714 if(pExceptRec == pExceptionRegRec)
1715 {
1716 fFound = TRUE;
1717 break;
1718 }
1719 pExceptRec = pExceptRec->prev_structure;
1720 }
1721
1722#ifdef DEBUG
1723 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1724
1725 if(fFound && pExceptRec != (PEXCEPTIONREGISTRATIONRECORD)pExceptionRegRec)
1726 {
1727 dprintf(("ERROR: ODIN_UnsetExceptionHandler: INSIDE!!!: exc rec %p, head %p\n", pExceptionRegRec, pExceptRec));
1728 PrintExceptionChain ();
1729 }
1730#endif
1731 if(fFound) {
1732 OS2UnsetExceptionHandler(pExceptionRegRec);
1733 }
1734 SetFS(sel);
1735}
1736//*****************************************************************************
1737//*****************************************************************************
1738#ifdef DEBUG
1739void PrintExceptionChain()
1740{
1741 USHORT sel = RestoreOS2FS();
1742 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1743
1744 dprintf(("Exception chain list:"));
1745 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1746 dprintf(("record %x", pExceptRec));
1747 pExceptRec = pExceptRec->prev_structure;
1748 }
1749 SetFS(sel);
1750}
1751//*****************************************************************************
1752//*****************************************************************************
1753void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
1754{
1755 dprintf(("Win32 exception chain:"));
1756 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
1757 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
1758 if (pframe == pframe->Prev) {
1759 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
1760 break;
1761 }
1762 pframe = pframe->Prev;
1763 }
1764}
1765
1766#endif
1767
1768
1769/*****************************************************************************
1770 * Name : void OS2UnsetExceptionHandler
1771 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1772 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1773 * Variables :
1774 * Result :
1775 * Remark :
1776 * Status :
1777 *
1778 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1779 *****************************************************************************/
1780void OS2UnsetExceptionHandler(void *exceptframe)
1781{
1782 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1783
1784 DosUnsetExceptionHandler(pExceptRec);
1785 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1786#ifdef DEBUG_ENABLELOG_LEVEL2
1787 PrintExceptionChain();
1788#endif
1789}
1790//*****************************************************************************
1791//*****************************************************************************
1792void SetOS2ExceptionChain(ULONG val)
1793{
1794 USHORT sel = GetFS();
1795
1796 SetExceptionChain(val);
1797 SetFS(sel);
1798}
1799//*****************************************************************************
1800//*****************************************************************************
1801int _System CheckCurFS()
1802{
1803 USHORT sel = RestoreOS2FS();
1804 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1805
1806 if(sel == 0x150b) {
1807 SetFS(sel);
1808 return FALSE;
1809 }
1810 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1811 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1812 SetFS(sel);
1813 return FALSE;
1814 }
1815 SetFS(sel);
1816 return TRUE;
1817}
1818//*****************************************************************************
1819//*****************************************************************************
1820
Note: See TracBrowser for help on using the repository browser.