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

Last change on this file since 4229 was 4229, checked in by sandervl, 25 years ago

exception handler changes/fixes (after ExitProcess has been called

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