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

Last change on this file since 5120 was 5037, checked in by bird, 25 years ago

Corrected bogus syntax. (strict compiler)

File size: 43.6 KB
Line 
1/* $Id: exceptions.cpp,v 1.49 2001-01-29 01:22:21 bird Exp $ */
2
3/* WARNING: Compiling this module with ICC with optimizations turned on */
4/* currently breaks this module. To get correct code, it is not necessary */
5/* to turn all optimizations off, just use the -Op- flag. */
6
7/*
8 * Win32 Exception functions for OS/2
9 *
10 * Ported Wine exception handling code
11 *
12 * Copyright 1998 Sander van Leeuwen (OS/2 port)
13 *
14 *
15 * Project Odin Software License can be found in LICENSE.TXT
16 *
17 *
18 * (dlls\ntdll\exception.c)
19 *
20 * Copyright 1999 Turchanov Sergey
21 * Copyright 1999 Alexandre Julliard
22 *
23 * (win32\except.c)
24 *
25 * Win32 exception functions
26 *
27 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
28 *
29 * Notes:
30 * What really happens behind the scenes of those new
31 * __try{...}__except(..){....} and
32 * __try{...}__finally{...}
33 * statements is simply not documented by Microsoft. There could be different
34 * reasons for this:
35 * One reason could be that they try to hide the fact that exception
36 * handling in Win32 looks almost the same as in OS/2 2.x.
37 * Another reason could be that Microsoft does not want others to write
38 * binary compatible implementations of the Win32 API (like us).
39 *
40 * Whatever the reason, THIS SUCKS!! Ensuring portabilty or future
41 * compatability may be valid reasons to keep some things undocumented.
42 * But exception handling is so basic to Win32 that it should be
43 * documented!
44 *
45 * Fixmes:
46 * -Most functions need better parameter checking.
47 * -I do not know how to handle exceptions within an exception handler.
48 * or what is done when ExceptionNestedException is returned from an
49 * exception handler
50 * -Real exceptions are not yet implemented. only the exception functions
51 * are implemented. A real implementation needs some new code in
52 * loader/signal.c. There would also be a need for showing debugging
53 * information in UnhandledExceptionFilter.
54 *
55 */
56#define INCL_MISC
57#define INCL_BASE
58#define INCL_WINBUTTONS
59#include <os2wrap.h> //Odin32 OS/2 api wrappers
60#include <stdio.h>
61#include <stdlib.h>
62#include <assert.h>
63#include <string.h>
64#include <builtin.h>
65#include "exceptions.h"
66#include "exceptutil.h"
67#include <misc.h>
68#include "mmap.h"
69#include <wprocess.h>
70#include "oslibexcept.h"
71#include "exceptstackdump.h"
72
73#define DBG_LOCALLOG DBG_exceptions
74#include "dbglocal.h"
75
76/* Exception record for handling exceptions happening inside exception handlers */
77typedef struct
78{
79 WINEXCEPTION_FRAME frame;
80 WINEXCEPTION_FRAME *prevFrame;
81} EXC_NESTED_FRAME;
82
83//Global Process Unhandled exception filter
84static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL;
85static UINT CurrentErrorMode = SEM_FAILCRITICALERRORS;
86static PEXCEPTION_HANDLER StartupCodeHandler = NULL;
87
88extern "C" PWINEXCEPTION_FRAME GetExceptionRecord(ULONG offset, ULONG segment);
89
90LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo);
91void KillWin32Process(void);
92
93#ifdef DEBUG
94void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe);
95#else
96#define PrintWin32ExceptionChain(a)
97#endif
98
99/*****************************************************************************
100 * Name : UINT SetErrorMode
101 * Purpose :
102 * Parameters: UINT fuErrorMode
103 * Variables :
104 * Result :
105 * Remark :
106 * Status :
107 *
108 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
109 *****************************************************************************/
110
111UINT WIN32API SetErrorMode(UINT fuErrorMode)
112{
113 UINT oldmode = CurrentErrorMode;
114
115 dprintf(("KERNEL32: SetErrorMode(%08xh)\n",
116 fuErrorMode));
117 CurrentErrorMode = fuErrorMode;
118
119 if(fuErrorMode & SEM_FAILCRITICALERRORS || fuErrorMode & SEM_NOOPENFILEERRORBOX)
120 DosError(FERR_DISABLEHARDERR);
121 else
122 DosError(FERR_ENABLEHARDERR);
123
124 // SEM_NOGPFAULTERRORBOX and SEM_NOALIGNMENTFAULTEXCEPT --> UnhandledExceptionFilter()
125
126 return(oldmode);
127}
128
129static inline WINEXCEPTION_FRAME * EXC_push_frame( WINEXCEPTION_FRAME *frame )
130{
131 // TODO: rewrite in assembly
132 TEB *teb = GetThreadTEB();
133 frame->Prev = (PWINEXCEPTION_FRAME)teb->except;
134 teb->except = frame;
135 return frame->Prev;
136}
137
138static inline WINEXCEPTION_FRAME * EXC_pop_frame( WINEXCEPTION_FRAME *frame )
139{
140 // TODO: rewrite in assembly
141 TEB *teb = GetThreadTEB();
142 teb->except = frame->Prev;
143 return frame->Prev;
144}
145
146/*****************************************************************************
147 * Name : VOID _Pascal OS2RaiseException
148 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
149 * Parameters: ...
150 * Variables :
151 * Result :
152 * Remark :
153 * Status :
154 *
155 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
156 *****************************************************************************/
157
158void WIN32API RtlRaiseException(WINEXCEPTION_RECORD *rec, WINCONTEXT *context);
159
160VOID _Pascal OS2RaiseException(DWORD dwExceptionCode,
161 DWORD dwExceptionFlags,
162 DWORD cArguments,
163 DWORD *lpArguments,
164 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
165 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
166 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
167 DWORD es, DWORD fs, DWORD gs, DWORD ss)
168{
169 WINEXCEPTION_RECORD record;
170 WINEXCEPTION_POINTERS ExceptionInfo;
171 WINCONTEXT context;
172 int rc;
173 int i;
174
175 dprintf(("KERNEL32: RaiseException(%08xh)\n",
176 dwExceptionCode));
177
178 memset(&record, 0, sizeof(record));
179
180 /* compose an exception record */
181 record.ExceptionCode = dwExceptionCode;
182 record.ExceptionFlags = dwExceptionFlags;
183 record.ExceptionRecord = NULL;
184 record.NumberParameters = cArguments;
185 record.ExceptionAddress = (LPVOID)eip;
186
187 memset(&context, 0, sizeof(context));
188 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
189 context.SegGs = gs;
190 context.SegFs = fs;
191 context.SegEs = es;
192 context.SegDs = ds;
193 context.Edi = edi;
194 context.Esi = esi;
195 context.Ebx = ebx;
196 context.Edx = edx;
197 context.Ecx = ecx;
198 context.Eax = eax;
199 context.Ebp = ebp;
200 context.Eip = eip;
201 context.SegCs = cs;
202 context.EFlags = flags;
203 context.Esp = esp;
204 context.SegSs = ss;
205
206 if(lpArguments)
207 {
208 for(i=0;
209 i<cArguments;
210 i++)
211 record.ExceptionInformation[i] = lpArguments[i];
212 }
213
214 rc = RtlDispatchException(&record, &context);
215
216 // and finally, the unhandled exception filter
217 if(rc == ExceptionContinueSearch && UnhandledExceptionFilter != NULL)
218 {
219 dprintf(("KERNEL32: RaiseException calling UnhandledExceptionFilter.\n"));
220
221 ExceptionInfo.ExceptionRecord = &record;
222 ExceptionInfo.ContextRecord = &context;
223
224 rc = UnhandledExceptionFilter(&ExceptionInfo);
225 //FIXME: UnhandledExceptionFilter does NOT return the same values as
226 // other filters!!
227 }
228
229 // terminate the process
230 if(rc != ExceptionContinueExecution ||
231 record.ExceptionFlags & EH_NONCONTINUABLE)
232 {
233 dprintf(("KERNEL32: RaiseException terminating process.\n"));
234 DosExit(EXIT_PROCESS, 0);
235 }
236
237 dprintf(("KERNEL32: RaiseException returns.\n"));
238 return;
239}
240
241/*******************************************************************
242 * EXC_RaiseHandler
243 *
244 * Handler for exceptions happening inside a handler.
245 */
246static DWORD WIN32API EXC_RaiseHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
247// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
248 WINCONTEXT *context, LPVOID dispatcher )
249{
250 if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
251 return ExceptionContinueSearch;
252 /* We shouldn't get here so we store faulty frame in dispatcher */
253 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
254 return ExceptionNestedException;
255}
256
257/*******************************************************************
258 * EXC_CallHandler
259 *
260 * Call an exception handler, setting up an exception frame to catch exceptions
261 * happening during the handler execution.
262 * WARNING:
263 * Please do not change the first 4 parameters order in any way - some exceptions handlers
264 * rely on Base Pointer (EBP) to have a fixed position related to the exception frame
265 */
266static DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
267 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
268 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler)
269{
270 EXC_NESTED_FRAME newframe;
271 DWORD ret;
272
273 newframe.frame.Handler = nested_handler;
274 newframe.prevFrame = frame;
275 EXC_push_frame( &newframe.frame );
276 dprintf(("KERNEL32: Calling handler at %p code=%lx flags=%lx\n",
277 handler, record->ExceptionCode, record->ExceptionFlags));
278 ret = handler( record, frame, context, dispatcher );
279 dprintf(("KERNEL32: Handler returned %lx\n", ret));
280 EXC_pop_frame( &newframe.frame );
281 return ret;
282}
283
284//******************************************************************************
285//******************************************************************************
286DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext)
287{
288 PWINEXCEPTION_FRAME pFrame, dispatch, nested_frame;
289 int rc;
290
291 // get chain of exception frames
292 rc = ExceptionContinueSearch;
293
294 nested_frame = NULL;
295 TEB *winteb = GetThreadTEB();
296 pFrame = (PWINEXCEPTION_FRAME)winteb->except;
297
298 dprintf(("KERNEL32: RtlDispatchException entered"));
299
300 PrintWin32ExceptionChain(pFrame);
301
302 // walk the exception chain
303 while( (pFrame != NULL) && (pFrame != ((void *)0xFFFFFFFF)) )
304 {
305 dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", pFrame, pFrame->Prev));
306 if (pFrame == pFrame->Prev) {
307 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
308 return 0;
309 }
310
311 dispatch=0;
312
313 /* Check frame address */
314 if (((void*)pFrame < winteb->stack_low) ||
315 ((void*)(pFrame+1) > winteb->stack_top) ||
316 (int)pFrame & 3)
317 {
318 dprintf(("Invalid stack! low=%08X, top=%08X, pframe = %08X",
319 winteb->stack_low, winteb->stack_top, pFrame));
320
321 pRecord->ExceptionFlags |= EH_STACK_INVALID;
322 break;
323 }
324
325
326 /* call handler */
327 rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch, pFrame->Handler, EXC_RaiseHandler );
328
329 PrintWin32ExceptionChain(pFrame);
330
331 if (pFrame == nested_frame)
332 {
333 /* no longer nested */
334 nested_frame = NULL;
335 pRecord->ExceptionFlags &= ~EH_NESTED_CALL;
336 }
337
338
339 switch(rc)
340 {
341 case ExceptionContinueExecution:
342 if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE)) {
343 dprintf(("KERNEL32: RtlDispatchException returns %#x (ContinueExecution)", rc));
344 return rc;
345 }
346 break;
347 case ExceptionContinueSearch:
348 break;
349 case ExceptionNestedException:
350 if (nested_frame < dispatch) nested_frame = dispatch;
351 pRecord->ExceptionFlags |= EH_NESTED_CALL;
352 break;
353 default:
354 break;
355 }
356
357 dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", pFrame, pFrame->Prev));
358 if (pFrame == pFrame->Prev) {
359 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
360 break;
361 }
362 pFrame = pFrame->Prev;
363 }
364 dprintf(("KERNEL32: RtlDispatchException returns %#x", rc));
365 PrintWin32ExceptionChain(pFrame);
366 return rc;
367}
368/*****************************************************************************
369 * Name : int _Pascal OS2RtlUnwind
370 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
371 * Parameters: ...
372 * Variables :
373 * Result :
374 * Remark :
375 * Status :
376 *
377 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
378 *****************************************************************************/
379
380int _Pascal OS2RtlUnwind(PWINEXCEPTION_FRAME pEndFrame,
381 LPVOID unusedEip,
382 PWINEXCEPTION_RECORD pRecord,
383 DWORD returnEax,
384 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
385 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
386 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
387 DWORD es, DWORD fs, DWORD gs, DWORD ss)
388{
389 PWINEXCEPTION_FRAME frame, dispatch;
390 WINEXCEPTION_RECORD record, newrec;
391 WINCONTEXT context;
392 DWORD rc;
393
394 dprintf(("KERNEL32: RtlUnwind pEndFrame=%08X, unusedEip=%08X, pRecord=%08X, returnEax=%#x\n", pEndFrame, unusedEip, pRecord, returnEax));
395
396
397 memset(&context, 0, sizeof(context));
398 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
399 context.SegGs = gs;
400 context.SegFs = fs;
401 context.SegEs = es;
402 context.SegDs = ds;
403 context.Edi = edi;
404 context.Esi = esi;
405 context.Ebx = ebx;
406 context.Edx = edx;
407 context.Ecx = ecx;
408 context.Eax = returnEax;
409 context.Ebp = ebp;
410 context.Eip = eip;
411 context.SegCs = cs;
412 context.EFlags = flags;
413 context.Esp = esp;
414 context.SegSs = ss;
415
416 /* build an exception record, if we do not have one */
417 if(!pRecord)
418 {
419 memset(&record, 0, sizeof(record));
420 record.ExceptionCode = STATUS_UNWIND;
421 record.ExceptionFlags = 0;
422 record.ExceptionRecord = NULL;
423 record.ExceptionAddress = (LPVOID)eip;
424 record.NumberParameters = 0;
425 pRecord = &record;
426 }
427
428 if(pEndFrame) pRecord->ExceptionFlags |= EH_UNWINDING;
429 else pRecord->ExceptionFlags |= EH_UNWINDING | EH_EXIT_UNWIND;
430
431 /* get chain of exception frames */
432 TEB *winteb = GetThreadTEB();
433 frame = (PWINEXCEPTION_FRAME)winteb->except;
434
435 PrintWin32ExceptionChain(frame);
436
437 while ((frame != (PWINEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame))
438 {
439 /* Check frame address */
440 if (pEndFrame && (frame > pEndFrame))
441 {
442 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
443 newrec.ExceptionFlags = EH_NONCONTINUABLE;
444 newrec.ExceptionRecord = pRecord;
445 newrec.NumberParameters = 0;
446 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
447 DosExit(EXIT_THREAD, 0);
448 }
449 if (((void*)frame < winteb->stack_low) ||
450 ((void*)(frame+1) > winteb->stack_top) ||
451 (int)frame & 3)
452 {
453 newrec.ExceptionCode = STATUS_BAD_STACK;
454 newrec.ExceptionFlags = EH_NONCONTINUABLE;
455 newrec.ExceptionRecord = pRecord;
456 newrec.NumberParameters = 0;
457 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
458 DosExit(EXIT_THREAD, 0);
459 }
460
461 /* Call handler */
462 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler));
463 rc = frame->Handler(pRecord, frame, &context, &dispatch);
464 dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc));
465 switch (rc)
466 {
467 case ExceptionContinueSearch:
468 break;
469 case ExceptionCollidedUnwind:
470 frame = dispatch;
471 break;
472 default:
473 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;
474 newrec.ExceptionFlags = EH_NONCONTINUABLE;
475 newrec.ExceptionRecord = pRecord;
476 newrec.NumberParameters = 0;
477 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
478 DosExit(EXIT_THREAD, 0);
479 break;
480 }
481 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, frame->Prev));
482 SetExceptionChain((DWORD)frame->Prev);
483 frame = frame->Prev;
484 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame, frame->Prev));
485 }
486
487 dprintf(("KERNEL32: RtlUnwind returning.\n"));
488 PrintWin32ExceptionChain(frame);
489 return(0);
490}
491
492
493/*****************************************************************************
494 * Name : LONG WIN32API UnhandledExceptionFilter
495 * Purpose :
496 * Parameters: ...
497 * Variables :
498 * Result :
499 * Remark :
500 * Status :
501 *
502 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
503 *****************************************************************************/
504
505LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo)
506{
507 char message[72];
508 DWORD rc;
509
510 // @@@PH: experimental change to have more control over exception handling
511#pragma pack(4)
512 typedef struct
513 {
514 ULONG cb; /* Size of fixed part of structure */
515 HPOINTER hIcon; /* Icon handle */
516 ULONG cButtons; /* Number of buttons */
517 ULONG flStyle; /* Icon style flags (MB_ICONQUESTION, etc...)*/
518 HWND hwndNotify; /* Reserved */
519 MB2D mb2d[4]; /* Array of button definitions */
520 } myMB2INFO;
521#pragma pack()
522
523 myMB2INFO mb2InfoExceptionBox = { 20, // size of structure
524 NULLHANDLE, // icon handle
525 4, // number of buttons
526 MB_ICONHAND, // icon style
527 NULLHANDLE, // reserved
528 { {"continue ~search", 100, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE},
529 {"continue ~execution", 101, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE},
530 {"execute ~handler", 102, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE | BS_DEFAULT},
531 {"~terminate process", 103, BS_PUSHBUTTON | BS_TEXT | BS_AUTOSIZE} }
532 };
533
534 dprintf(("KERNEL32: Default UnhandledExceptionFilter, CurrentErrorMode=%X", CurrentErrorMode));
535
536 // We must not care about ErrorMode here!! The app expects that its own
537 // UnhandledExceptionFilter will be cared even if it never touched ErrorMode.
538 if(CurrentUnhExceptionFlt) // && !(CurrentErrorMode & (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)))
539 {
540 dprintf(("KERNEL32: Calling user UnhandledExceptionFilter"));
541 rc = CurrentUnhExceptionFlt(lpexpExceptionInfo);
542 if(rc != WINEXCEPTION_CONTINUE_SEARCH)
543 return rc;
544 }
545
546 sprintf(message,
547 "Unhandled exception 0x%08lx at address 0x%08lx.",
548 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
549 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
550/*
551 rc = WinMessageBox2(HWND_DESKTOP,
552 HWND_DESKTOP,
553 message,
554 "Oh, nooo!",
555 0,
556 (PMB2INFO)&mb2InfoExceptionBox);
557 switch (rc)
558 {
559 case 100:
560 return WINEXCEPTION_CONTINUE_SEARCH;
561
562 case 101:
563 return WINEXCEPTION_CONTINUE_EXECUTION;
564
565 case 102:
566 return WINEXCEPTION_EXECUTE_HANDLER;
567
568 case 103:
569 KillWin32Process();
570 // fall-through
571
572 default:
573 return WINEXCEPTION_EXECUTE_HANDLER;
574 }
575*/
576 rc = WinMessageBox(HWND_DESKTOP,
577 HWND_DESKTOP,
578 message,
579 "Oh, nooo!",
580 0,
581 MB_ABORTRETRYIGNORE | MB_ERROR);
582 switch (rc)
583 {
584 case MBID_IGNORE:
585 return WINEXCEPTION_CONTINUE_EXECUTION;
586
587 case MBID_ABORT:
588 KillWin32Process();
589 // fall-through
590
591 case MBID_RETRY:
592 default:
593 return WINEXCEPTION_EXECUTE_HANDLER;
594 }
595}
596
597
598/*****************************************************************************
599 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
600 * Purpose :
601 * Parameters: ...
602 * Variables :
603 * Result :
604 * Remark :
605 * Status :
606 *
607 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
608 *****************************************************************************/
609
610LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
611{
612 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
613
614 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n",
615 lpTopLevelExceptionFilter));
616
617 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
618
619 return(old);
620}
621
622
623/*****************************************************************************
624 * Name : KillWin32Process
625 * Purpose :
626 * Parameters: ...
627 * Variables :
628 * Result :
629 * Remark :
630 * Status :
631 *
632 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
633 *****************************************************************************/
634
635
636//******************************************************************************
637extern "C" ULONG getEAX();
638extern "C" ULONG getEBX();
639VOID WIN32API ExitProcess(DWORD exitcode);
640//******************************************************************************
641void KillWin32Process(void)
642{
643 static BOOL fEntry = FALSE;
644
645 if(fEntry == FALSE) {
646 fEntry = TRUE;
647 ExitProcess(666);
648 return;
649 }
650 //Restore original OS/2 TIB selector
651 RestoreOS2FS();
652
653 SetExceptionChain((ULONG)-1);
654 DosExit(EXIT_PROCESS, 666);
655}
656
657
658/*****************************************************************************
659 * Name : void static dprintfException
660 * Purpose : log the exception to win32os2.log
661 * Parameters: ...
662 * Variables :
663 * Result :
664 * Remark :
665 * Status :
666 *
667 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
668 *****************************************************************************/
669
670static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
671 PEXCEPTIONREGISTRATIONRECORD pERegRec,
672 PCONTEXTRECORD pCtxRec,
673 PVOID p)
674{
675 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
676 char szData[128]; /* local storage for excpt dep. information */
677 char szData2[128]; /* local storage for excpt dep. information */
678 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
679 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
680 BOOL fExcptFatal = TRUE; /* fatal exception ? */
681 BOOL fExcptPortable = TRUE; /* portability of exception */
682 PPIB pPIB; /* process information block */
683 PTIB pTIB; /* thread information block */
684 ULONG ulModule; /* module number */
685 ULONG ulObject; /* object number within the module */
686 CHAR szModule[260]; /* buffer for the module name */
687 ULONG ulOffset; /* offset within the object within the module */
688
689 szData[0] = 0; /* initialize */
690 szData2[0] = 0; /* initialize */
691 switch(pERepRec->ExceptionNum) /* take according action */
692 {
693 /* portable, non-fatal software-generated exceptions */
694 case XCPT_GUARD_PAGE_VIOLATION:
695 pszExceptionName = "Guard Page Violation";
696 sprintf(szData,
697 "R/W %08xh at %08xh.",
698 pERepRec->ExceptionInfo[0],
699 pERepRec->ExceptionInfo[1]);
700 fExcptSoftware = TRUE;
701 fExcptFatal = FALSE;
702 rc = XCPT_CONTINUE_EXECUTION;
703 break;
704
705 case XCPT_UNABLE_TO_GROW_STACK:
706 pszExceptionName = "Unable To Grow Stack";
707 fExcptSoftware = TRUE;
708 fExcptFatal = FALSE;
709 rc = XCPT_CONTINUE_EXECUTION;
710 break;
711
712 /* portable, fatal, hardware-generated exceptions */
713 case XCPT_ACCESS_VIOLATION:
714 pszExceptionName = "Access Violation";
715 /* sprintf (szData, "Access type %08x at %08x.", pERepRec->ExceptionInfo[0],
716 pERepRec->ExceptionInfo[1]); */
717 switch (pERepRec->ExceptionInfo[0])
718 {
719 case XCPT_READ_ACCESS:
720 sprintf (szData,
721 "Read Access at address %08xh",
722 pERepRec->ExceptionInfo[1]);
723 break;
724
725 case XCPT_WRITE_ACCESS:
726 sprintf (szData,
727 "Write Access at address %08x",
728 pERepRec->ExceptionInfo[1]);
729 break;
730
731 case XCPT_SPACE_ACCESS:
732 sprintf (szData,
733 "Space Access at selector %08x",
734 pERepRec->ExceptionInfo[1]);
735 break;
736
737 case XCPT_LIMIT_ACCESS:
738 strcpy (szData,
739 "Limit Access");
740 break;
741
742 case XCPT_UNKNOWN_ACCESS:
743 strcpy (szData,
744 "Unknown Access");
745 break;
746
747 default:
748 strcpy (szData,
749 "(Invalid Access Code)");
750 break;
751 }
752 break;
753
754 case XCPT_INTEGER_DIVIDE_BY_ZERO:
755 pszExceptionName = "Division By Zero (Integer)";
756 break;
757
758 case XCPT_FLOAT_DIVIDE_BY_ZERO:
759 pszExceptionName = "Division By Zero (Float)";
760 break;
761
762 case XCPT_FLOAT_INVALID_OPERATION:
763 pszExceptionName = "Invalid Floating Point Operation";
764 break;
765
766 case XCPT_ILLEGAL_INSTRUCTION:
767 pszExceptionName = "Illegal Instruction";
768 break;
769
770 case XCPT_PRIVILEGED_INSTRUCTION:
771 pszExceptionName = "Privileged Instruction";
772 break;
773
774 case XCPT_INTEGER_OVERFLOW:
775 pszExceptionName = "Integer Overflow";
776 break;
777
778 case XCPT_FLOAT_OVERFLOW:
779 pszExceptionName = "Floating Point Overflow";
780 break;
781
782 case XCPT_FLOAT_UNDERFLOW:
783 pszExceptionName = "Floating Point Underflow";
784 break;
785
786 case XCPT_FLOAT_DENORMAL_OPERAND:
787 pszExceptionName = "Floating Point Denormal Operand";
788 break;
789
790 case XCPT_FLOAT_INEXACT_RESULT:
791 pszExceptionName = "Floating Point Inexact Result";
792 break;
793
794 case XCPT_FLOAT_STACK_CHECK:
795 pszExceptionName = "Floating Point Stack Check";
796 break;
797
798 case XCPT_DATATYPE_MISALIGNMENT:
799 pszExceptionName = "Datatype Misalignment";
800 sprintf(szData,
801 "R/W %08x alignment %08x at %08x.",
802 pERepRec->ExceptionInfo[0],
803 pERepRec->ExceptionInfo[1],
804 pERepRec->ExceptionInfo[2]);
805 break;
806
807 case XCPT_BREAKPOINT:
808 pszExceptionName = "Breakpoint (don't debug me! :)";
809 break;
810
811 case XCPT_SINGLE_STEP:
812 pszExceptionName = "Single Step (don't debug me! :)";
813 break;
814
815 /* portable, fatal, software-generated exceptions */
816 case XCPT_IN_PAGE_ERROR:
817 pszExceptionName = "In Page Error";
818 sprintf(szData,
819 "at %08x.",
820 pERepRec->ExceptionInfo[0]);
821 fExcptSoftware = TRUE;
822 break;
823
824 case XCPT_PROCESS_TERMINATE:
825 pszExceptionName = "Process Termination";
826 fExcptSoftware = TRUE;
827 break;
828
829 case XCPT_ASYNC_PROCESS_TERMINATE:
830 pszExceptionName = "Process Termination (async)";
831 sprintf(szData,
832 "terminating thread TID=%u",
833 pERepRec->ExceptionInfo[0]);
834 fExcptSoftware = TRUE;
835 break;
836
837 case XCPT_NONCONTINUABLE_EXCEPTION:
838 pszExceptionName = "Noncontinuable Exception";
839 fExcptSoftware = TRUE;
840 break;
841
842 case XCPT_INVALID_DISPOSITION:
843 pszExceptionName = "Invalid Disposition";
844 fExcptSoftware = TRUE;
845 break;
846
847 /* non-portable, fatal exceptions */
848 case XCPT_INVALID_LOCK_SEQUENCE:
849 pszExceptionName = "Invalid Lock Sequence";
850 fExcptSoftware = TRUE;
851 fExcptPortable = FALSE;
852 break;
853
854 case XCPT_ARRAY_BOUNDS_EXCEEDED:
855 pszExceptionName = "Array Bounds Exceeded";
856 fExcptSoftware = TRUE;
857 fExcptPortable = FALSE;
858 break;
859
860 /* unwind operation exceptions */
861 case XCPT_UNWIND:
862 pszExceptionName = "Unwind Exception";
863 fExcptSoftware = TRUE;
864 fExcptPortable = FALSE;
865 break;
866
867 case XCPT_BAD_STACK:
868 pszExceptionName = "Unwind Exception, Bad Stack";
869 fExcptSoftware = TRUE;
870 fExcptPortable = FALSE;
871 break;
872
873 case XCPT_INVALID_UNWIND_TARGET:
874 pszExceptionName = "Unwind Exception, Invalid Target";
875 fExcptSoftware = TRUE;
876 fExcptPortable = FALSE;
877 break;
878
879 /* fatal signal exceptions */
880 case XCPT_SIGNAL:
881 pszExceptionName = "Signal";
882 sprintf(szData,
883 "Signal Number = %08x",
884 pERepRec->ExceptionInfo[0]);
885 fExcptSoftware = TRUE;
886 fExcptPortable = FALSE;
887
888 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
889 {
890 case XCPT_SIGNAL_INTR:
891 pszExceptionName = "Signal (Interrupt)";
892 break;
893
894 case XCPT_SIGNAL_KILLPROC:
895 pszExceptionName = "Signal (Kill Process)";
896 break;
897
898 case XCPT_SIGNAL_BREAK:
899 pszExceptionName = "Signal (Break)";
900 break;
901 }
902 break;
903
904 default:
905 pszExceptionName = "(unknown exception code)";
906 sprintf(szData,
907 "Exception Code = %08x",
908 pERepRec->ExceptionNum);
909 }
910
911
912 /* now dump the information to the logfile */
913 dprintf(("---[Exception Information]------------\n"));
914 sprintf(szData2,
915 " %s (",
916 pszExceptionName);
917
918 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
919 strcat (szData2, "software generated,");
920 else
921 strcat (szData2, "hardware generated,");
922
923 if (fExcptPortable == TRUE) /* portable exception ? */
924 strcat (szData2, "portable,");
925 else
926 strcat (szData2, "non-portable,");
927
928 if (fExcptFatal == TRUE) /* fatal exception ? */
929 strcat (szData2, "fatal");
930 else
931 strcat (szData2, "non-fatal");
932
933 strcat (szData2, /* add trailing brace */
934 ")\n");
935
936
937 dprintf((szData2));
938
939 if (szData[0] != 0) /* see if there is an additional entry */
940 dprintf((" %s\n",
941 szData));
942
943 rc = DosQueryModFromEIP(&ulModule,
944 &ulObject,
945 sizeof(szModule),
946 szModule,
947 &ulOffset,
948 (ULONG)pERepRec->ExceptionAddress);
949
950 dprintf((" Exception Address = %08x ",
951 pERepRec->ExceptionAddress));
952
953 if(rc == NO_ERROR && ulObject != -1)
954 dprintf(("<%s> (#%u), obj #%u:%08x\n",
955 szModule,
956 ulModule,
957 ulObject,
958 ulOffset));
959 else
960 dprintf(("<win32 app>\n"));
961
962
963 rc = DosGetInfoBlocks (&pTIB, /* query kernel information blocks */
964 &pPIB);
965 if (rc == NO_ERROR)
966 {
967 dprintf((" Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
968 pTIB->tib_ordinal,
969 pTIB->tib_ptib2->tib2_ultid,
970 pTIB->tib_ptib2->tib2_ulpri));
971
972 dprintf((" Process: PID: %u, Parent: %u, Status: %u\n",
973 pPIB->pib_ulpid,
974 pPIB->pib_ulppid,
975 pPIB->pib_flstatus));
976 }
977
978 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
979 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n",
980 pCtxRec->ctx_SegSs,
981 pCtxRec->ctx_RegEsp,
982 pCtxRec->ctx_EFlags));
983 dprintf((" CS:EIP=%04x:%08x EBP =%08x\n",
984 pCtxRec->ctx_SegCs,
985 pCtxRec->ctx_RegEip,
986 pCtxRec->ctx_RegEbp));
987
988 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
989 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n",
990 pCtxRec->ctx_RegEax,
991 pCtxRec->ctx_RegEbx,
992 pCtxRec->ctx_RegEsi));
993 dprintf((" ECX=%08x EDX=%08x EDI=%08x\n",
994 pCtxRec->ctx_RegEcx,
995 pCtxRec->ctx_RegEdx,
996 pCtxRec->ctx_RegEdi));
997
998 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
999 dprintf((" DS=%04x ES=%08x",
1000 pCtxRec->ctx_SegDs,
1001 pCtxRec->ctx_SegEs));
1002 dprintf((" FS=%04x GS=%04x\n",
1003 pCtxRec->ctx_SegFs,
1004 pCtxRec->ctx_SegGs));
1005
1006 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1007 {
1008 ULONG ulCounter; /* temporary local counter for fp stack */
1009
1010 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1011 pCtxRec->ctx_env[0],
1012 pCtxRec->ctx_env[1],
1013 pCtxRec->ctx_env[2],
1014 pCtxRec->ctx_env[3]));
1015
1016 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1017 pCtxRec->ctx_env[4],
1018 pCtxRec->ctx_env[5],
1019 pCtxRec->ctx_env[6]));
1020
1021 for (ulCounter = 0;
1022 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1023 ulCounter ++)
1024 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1025 ulCounter,
1026 pCtxRec->ctx_stack[0].losig,
1027 pCtxRec->ctx_stack[0].hisig,
1028 pCtxRec->ctx_stack[0].signexp));
1029 }
1030
1031 dprintf(("---[End Of Exception Information]-----\n"));
1032}
1033
1034/*****************************************************************************
1035 * Name : ERR _System OS2ExceptionHandler
1036 * Purpose :
1037 * Parameters: ...
1038 * Variables :
1039 * Result :
1040 * Remark :
1041 * Status :
1042 *
1043 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1044 *****************************************************************************/
1045 /* from PPC DDK */
1046#ifndef XCPT_CONTINUE_STOP
1047#define XCPT_CONTINUE_STOP 0x00716668
1048#endif
1049
1050ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1051 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1052 PCONTEXTRECORD pCtxRec,
1053 PVOID p)
1054{
1055 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1056 // next dprintf won't wait forever
1057 LogException(ENTER_EXCEPTION);
1058
1059 /* Access violation at a known location */
1060 switch(pERepRec->ExceptionNum)
1061 {
1062 case XCPT_FLOAT_DENORMAL_OPERAND:
1063 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1064 case XCPT_FLOAT_INEXACT_RESULT:
1065// case XCPT_FLOAT_INVALID_OPERATION:
1066 case XCPT_FLOAT_OVERFLOW:
1067 case XCPT_FLOAT_STACK_CHECK:
1068 case XCPT_FLOAT_UNDERFLOW:
1069 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1070 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1071 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1072 {
1073 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1074 {
1075 pCtxRec->ctx_env[0] |= 0x1F;
1076 pCtxRec->ctx_stack[0].losig = 0;
1077 pCtxRec->ctx_stack[0].hisig = 0;
1078 pCtxRec->ctx_stack[0].signexp = 0;
1079 }
1080 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1081 goto continueexecution;
1082 }
1083 else
1084 {
1085 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1086 goto continuesearch;
1087 }
1088
1089 case XCPT_PROCESS_TERMINATE:
1090 case XCPT_ASYNC_PROCESS_TERMINATE:
1091 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1092 SetExceptionChain((ULONG)-1);
1093 goto continuesearch;
1094
1095 case XCPT_ACCESS_VIOLATION:
1096 {
1097 Win32MemMap *map;
1098 BOOL fWriteAccess = FALSE;
1099 ULONG offset, accessflag;
1100
1101 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1102 goto continueFail;
1103 }
1104//------------->>> WARNING: potentially dangerous workaround!!
1105 /* Some apps set ES = FS and Odin doesn't like that! */
1106 /* Note: maybe we could even check for ES != DS? But maybe */
1107 /* that might cause more harm than good... */
1108 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1109 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1110 /* Let's just reset ES to the DS value and hope it's okay */
1111 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1112 goto continueexecution;
1113 }
1114
1115 switch(pERepRec->ExceptionInfo[0]) {
1116 case XCPT_READ_ACCESS:
1117 accessflag = MEMMAP_ACCESS_READ;
1118 break;
1119 case XCPT_WRITE_ACCESS:
1120 accessflag = MEMMAP_ACCESS_WRITE;
1121 fWriteAccess = TRUE;
1122 break;
1123 case XCPT_EXECUTE_ACCESS:
1124 accessflag = MEMMAP_ACCESS_EXECUTE;
1125 break;
1126 default:
1127 goto continueFail;
1128 }
1129
1130 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1131 if(map == NULL) {
1132 goto continueFail;
1133 }
1134 if(map->commitPage(offset, fWriteAccess) == TRUE)
1135 goto continueexecution;
1136
1137 //no break;
1138 }
1139continueFail:
1140
1141////#define DEBUGSTACK
1142#ifdef DEBUGSTACK
1143 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1144 ULONG *stackptr;
1145 APIRET rc;
1146 int i;
1147 ULONG ulOffset, ulModule, ulObject;
1148 CHAR szModule[CCHMAXPATH];
1149
1150 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1151 dprintf(("Stack DUMP:"));
1152 for(i=0;i<16;i++) {
1153 rc = DosQueryModFromEIP(&ulModule,
1154 &ulObject,
1155 sizeof(szModule),
1156 szModule,
1157 &ulOffset,
1158 (ULONG)*stackptr);
1159
1160 if (rc == NO_ERROR)
1161 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1162 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1163 stackptr++;
1164 }
1165 dprintf(("Stack DUMP END"));
1166 }
1167#endif
1168
1169 case XCPT_BREAKPOINT:
1170 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1171 case XCPT_DATATYPE_MISALIGNMENT:
1172 case XCPT_ILLEGAL_INSTRUCTION:
1173 case XCPT_PRIVILEGED_INSTRUCTION:
1174 case XCPT_INVALID_LOCK_SEQUENCE:
1175 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1176 case XCPT_INTEGER_OVERFLOW:
1177 case XCPT_SINGLE_STEP:
1178 case XCPT_UNABLE_TO_GROW_STACK:
1179 case XCPT_IN_PAGE_ERROR:
1180CrashAndBurn:
1181 //SvL: TODO: this may not always be the right thing to do
1182 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1183 // of this exception handler. We better bail out ASAP or we'll likely
1184 // recurse infinitely until we run out of stack space!!
1185 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1186 goto continuesearch;
1187
1188#ifdef DEBUG
1189 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1190 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1191 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1192 }
1193#endif
1194 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1195 {
1196 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1197 {
1198 goto continueexecution;
1199 }
1200 }
1201 else goto continuesearch; //pass on to OS/2 RTL or app exception handler
1202
1203 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1204 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1205 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1206 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1207 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1208 goto continueexecution;
1209
1210 //@@@PH: growing thread stacks might need special treatment
1211 case XCPT_GUARD_PAGE_VIOLATION:
1212 //SvL: don't print anything here -> fatal hang if happens inside fprintf
1213 //dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue search)"));
1214 goto continuesearch;
1215
1216 case XCPT_SIGNAL:
1217 if(pERepRec->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC) /* resolve signal information */
1218 {
1219 SetExceptionChain((ULONG)-1);
1220 goto continuesearch;
1221 }
1222 goto CrashAndBurn;
1223
1224 default: //non-continuable exceptions
1225 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1226 goto continuesearch;
1227 }
1228continuesearch:
1229 LogException(LEAVE_EXCEPTION);
1230 return XCPT_CONTINUE_SEARCH;
1231
1232continueexecution:
1233 LogException(LEAVE_EXCEPTION);
1234 return XCPT_CONTINUE_EXECUTION;
1235}
1236
1237/*****************************************************************************
1238 * Name : void OS2SetExceptionHandler
1239 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1240 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1241 * Variables :
1242 * Result :
1243 * Remark :
1244 * Status :
1245 *
1246 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1247 *****************************************************************************/
1248void OS2SetExceptionHandler(void *exceptframe)
1249{
1250 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1251
1252 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1253 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1254
1255 /* disable trap popups */
1256// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1257
1258 DosSetExceptionHandler(pExceptRec);
1259 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1260#ifdef DEBUG_ENABLELOG_LEVEL2
1261 PrintExceptionChain();
1262#endif
1263}
1264
1265#ifdef DEBUG
1266void PrintExceptionChain()
1267{
1268 USHORT sel = RestoreOS2FS();
1269 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1270
1271 dprintf(("Exception chain list:"));
1272 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1273 dprintf(("record %x", pExceptRec));
1274 pExceptRec = pExceptRec->prev_structure;
1275 }
1276 SetFS(sel);
1277}
1278
1279void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
1280{
1281 dprintf(("Win32 exception chain:"));
1282 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
1283 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
1284 if (pframe == pframe->Prev) {
1285 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
1286 break;
1287 }
1288 pframe = pframe->Prev;
1289 }
1290}
1291
1292#endif
1293
1294
1295/*****************************************************************************
1296 * Name : void OS2UnsetExceptionHandler
1297 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1298 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1299 * Variables :
1300 * Result :
1301 * Remark :
1302 * Status :
1303 *
1304 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1305 *****************************************************************************/
1306void OS2UnsetExceptionHandler(void *exceptframe)
1307{
1308 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1309
1310 DosUnsetExceptionHandler(pExceptRec);
1311 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1312#ifdef DEBUG_ENABLELOG_LEVEL2
1313 PrintExceptionChain();
1314#endif
1315}
1316
1317void SetOS2ExceptionChain(ULONG val)
1318{
1319 USHORT sel = GetFS();
1320
1321 SetExceptionChain(val);
1322 SetFS(sel);
1323}
1324
1325int _System CheckCurFS()
1326{
1327 USHORT sel = RestoreOS2FS();
1328 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1329
1330 if(sel == 0x150b) {
1331 SetFS(sel);
1332 return FALSE;
1333 }
1334 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1335 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1336 SetFS(sel);
1337 return FALSE;
1338 }
1339 SetFS(sel);
1340 return TRUE;
1341}
1342
Note: See TracBrowser for help on using the repository browser.