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

Last change on this file since 21302 was 21302, checked in by ydario, 16 years ago

Kernel32 updates.

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