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

Last change on this file since 21647 was 21647, checked in by dmik, 14 years ago

kernel32: Propagate exceptions further along the OS/2 chain instead of terminating the application if the last Win32 exception handler (eg the SEH one) returns ExceptionContinueSearch. This lets unhandled exceptions be seen by eg PROCDUMP.

File size: 67.5 KB
Line 
1/* $Id: exceptions.cpp,v 1.74 2004-01-20 13:41:10 sandervl Exp $ */
2
3/*
4 * Win32 Exception functions for OS/2
5 *
6 * Ported Wine exception handling code
7 *
8 * Copyright 1998 Sander van Leeuwen (OS/2 port)
9 *
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 *
14 * (dlls\ntdll\exception.c)
15 *
16 * Copyright 1999 Turchanov Sergey
17 * Copyright 1999 Alexandre Julliard
18 *
19 * (win32\except.c)
20 *
21 * Win32 exception functions
22 *
23 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
24 *
25 * Notes:
26 * What really happens behind the scenes of those new
27 * __try{...}__except(..){....} and
28 * __try{...}__finally{...}
29 * statements is simply not documented by Microsoft. There could be different
30 * reasons for this:
31 * One reason could be that they try to hide the fact that exception
32 * handling in Win32 looks almost the same as in OS/2 2.x.
33 * Another reason could be that Microsoft does not want others to write
34 * binary compatible implementations of the Win32 API (like us).
35 *
36 * Whatever the reason, THIS SUCKS!! Ensuring portabilty or future
37 * compatability may be valid reasons to keep some things undocumented.
38 * But exception handling is so basic to Win32 that it should be
39 * documented!
40 *
41 * Fixmes:
42 * -Most functions need better parameter checking.
43 * -I do not know how to handle exceptions within an exception handler.
44 * or what is done when ExceptionNestedException is returned from an
45 * exception handler
46 * -Real exceptions are not yet implemented. only the exception functions
47 * are implemented. A real implementation needs some new code in
48 * loader/signal.c. There would also be a need for showing debugging
49 * information in UnhandledExceptionFilter.
50 *
51 */
52#define INCL_MISC
53#define INCL_BASE
54#define INCL_WIN
55#define INCL_WINBUTTONS
56#include <os2wrap.h> //Odin32 OS/2 api wrappers
57#include <stdio.h>
58#include <stdlib.h>
59#include <assert.h>
60#include <time.h>
61#include <string.h>
62#include <pmscan.h>
63#include "exceptions.h"
64#include "exceptutil.h"
65#include <misc.h>
66#include "mmap.h"
67#include <wprocess.h>
68#include <win32api.h>
69#include "oslibexcept.h"
70#include "oslibmem.h"
71#include "exceptstackdump.h"
72#include "hmthread.h"
73
74#include "WinImageBase.h"
75#include "WinDllBase.h"
76#include "WinExeBase.h"
77
78/* Really lazy! But, including wincon.h means lot's of missing COORD. */
79#define CTRL_C_EVENT 0 //#include <wincon.h>
80#define CTRL_BREAK_EVENT 1 //#include <wincon.h>
81#include "console.h"
82#include "initterm.h"
83
84
85#define DBG_LOCALLOG DBG_exceptions
86#include "dbglocal.h"
87
88#include <_ras.h>
89
90#ifdef WITH_KLIB
91/* quick and dirty - don't wanna mess with includes. */
92typedef enum { enmRead, enmWrite, enmUnknown } ENMACCESS;
93BOOL _Optlink kHeapDbgException(void * pvAccess,
94 ENMACCESS enmAccess,
95 void * pvIP,
96 void * pvOS);
97#endif
98
99/* Exception record for handling exceptions happening inside exception handlers */
100typedef struct
101{
102 WINEXCEPTION_FRAME frame;
103 WINEXCEPTION_FRAME *prevFrame;
104} EXC_NESTED_FRAME;
105
106//Global Process Unhandled exception filter
107static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL;
108static UINT CurrentErrorMode = 0;
109static PEXCEPTION_HANDLER StartupCodeHandler = NULL;
110
111extern "C" PWINEXCEPTION_FRAME GetExceptionRecord(ULONG offset, ULONG segment);
112
113LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo);
114void KillWin32Process(void);
115
116static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec,
117 PEXCEPTIONREGISTRATIONRECORD pERegRec,
118 PCONTEXTRECORD pCtxRec, PVOID p, PSZ szTrapDump);
119
120extern "C"
121int __cdecl __seh_handler(PWINEXCEPTION_RECORD pRec,
122 PWINEXCEPTION_FRAME pFrame,
123 PCONTEXTRECORD pContext, PVOID pVoid);
124
125extern "C"
126PWINEXCEPTION_FRAME __cdecl __seh_get_prev_frame(PWINEXCEPTION_FRAME pFrame);
127
128#ifdef DEBUG
129static void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe);
130#else
131#define PrintWin32ExceptionChain(a)
132#endif
133
134/*****************************************************************************
135 * Name : UINT SetErrorMode
136 * Purpose :
137 * Parameters: UINT fuErrorMode
138 * Variables :
139 * Result :
140 * Remark :
141 * Status :
142 *
143 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
144 *****************************************************************************/
145
146UINT WIN32API SetErrorMode(UINT fuErrorMode)
147{
148 UINT oldmode = CurrentErrorMode;
149
150 dprintf(("KERNEL32: SetErrorMode(%08xh)\n",
151 fuErrorMode));
152 CurrentErrorMode = fuErrorMode;
153
154 if(fuErrorMode & SEM_FAILCRITICALERRORS || fuErrorMode & SEM_NOOPENFILEERRORBOX)
155 DosError(FERR_DISABLEHARDERR);
156 else
157 DosError(FERR_ENABLEHARDERR);
158
159 // SEM_NOGPFAULTERRORBOX and SEM_NOALIGNMENTFAULTEXCEPT --> UnhandledExceptionFilter()
160
161 return(oldmode);
162}
163
164#if 0
165static inline WINEXCEPTION_FRAME * EXC_push_frame( WINEXCEPTION_FRAME *frame )
166{
167 // TODO: rewrite in assembly
168 TEB *teb = GetThreadTEB();
169 frame->Prev = (PWINEXCEPTION_FRAME)teb->except;
170 teb->except = frame;
171 return frame->Prev;
172}
173
174static inline WINEXCEPTION_FRAME * EXC_pop_frame( WINEXCEPTION_FRAME *frame )
175{
176 // TODO: rewrite in assembly
177 TEB *teb = GetThreadTEB();
178 teb->except = frame->Prev;
179 return frame->Prev;
180}
181#endif
182
183/*****************************************************************************
184 * Name : VOID _Pascal OS2RaiseException
185 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
186 * Parameters: ...
187 * Variables :
188 * Result :
189 * Remark :
190 * Status :
191 *
192 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
193 *****************************************************************************/
194
195void WIN32API RtlRaiseException(WINEXCEPTION_RECORD *rec, WINCONTEXT *context);
196
197VOID _Pascal OS2RaiseException(DWORD dwExceptionCode,
198 DWORD dwExceptionFlags,
199 DWORD cArguments,
200 DWORD *lpArguments,
201 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
202 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
203 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
204 DWORD es, DWORD fs, DWORD gs, DWORD ss)
205{
206 WINEXCEPTION_RECORD record;
207 WINEXCEPTION_POINTERS ExceptionInfo;
208 WINCONTEXT context;
209 int rc;
210 int i;
211
212 dprintf(("KERNEL32: RaiseException(%08xh)\n",
213 dwExceptionCode));
214
215 memset(&record, 0, sizeof(record));
216
217 /* compose an exception record */
218 record.ExceptionCode = dwExceptionCode;
219 record.ExceptionFlags = dwExceptionFlags;
220 record.ExceptionRecord = NULL;
221 record.NumberParameters = cArguments;
222 record.ExceptionAddress = (LPVOID)eip;
223
224 memset(&context, 0, sizeof(context));
225 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
226 context.SegGs = gs;
227 context.SegFs = fs;
228 context.SegEs = es;
229 context.SegDs = ds;
230 context.Edi = edi;
231 context.Esi = esi;
232 context.Ebx = ebx;
233 context.Edx = edx;
234 context.Ecx = ecx;
235 context.Eax = eax;
236 context.Ebp = ebp;
237 context.Eip = eip;
238 context.SegCs = cs;
239 context.EFlags = flags;
240 context.Esp = esp;
241 context.SegSs = ss;
242
243 if(lpArguments)
244 {
245 for(i=0;
246 i<cArguments;
247 i++)
248 record.ExceptionInformation[i] = lpArguments[i];
249 }
250
251 rc = RtlDispatchException(&record, &context);
252
253 // and finally, the unhandled exception filter
254 if(rc == ExceptionContinueSearch && UnhandledExceptionFilter != NULL)
255 {
256 dprintf(("KERNEL32: RaiseException calling UnhandledExceptionFilter.\n"));
257
258 ExceptionInfo.ExceptionRecord = &record;
259 ExceptionInfo.ContextRecord = &context;
260
261 rc = UnhandledExceptionFilter(&ExceptionInfo);
262 //FIXME: UnhandledExceptionFilter does NOT return the same values as
263 // other filters!!
264 }
265
266 // terminate the process
267 if(rc != ExceptionContinueExecution ||
268 record.ExceptionFlags & EH_NONCONTINUABLE)
269 {
270 dprintf(("KERNEL32: RaiseException terminating process.\n"));
271 DosExit(EXIT_PROCESS, 0);
272 }
273
274 dprintf(("KERNEL32: RaiseException returns.\n"));
275 return;
276}
277
278/*******************************************************************
279 * EXC_RaiseHandler
280 *
281 * Handler for exceptions happening inside a handler.
282 */
283static DWORD WIN32API EXC_RaiseHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
284// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
285 WINCONTEXT *context, LPVOID dispatcher )
286{
287 if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
288 return ExceptionContinueSearch;
289 /* We shouldn't get here so we store faulty frame in dispatcher */
290 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
291 return ExceptionNestedException;
292}
293
294/*******************************************************************
295 * EXC_UnwindHandler
296 *
297 * Handler for exceptions happening inside an unwind handler.
298 */
299static DWORD WIN32API EXC_UnwindHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
300// WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
301 WINCONTEXT *context, LPVOID dispatcher )
302{
303 if (!(rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))
304 return ExceptionContinueSearch;
305 /* We shouldn't get here so we store faulty frame in dispatcher */
306 *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
307 return ExceptionCollidedUnwind;
308}
309
310#if 1
311DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
312 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
313 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler);
314
315#else
316/*******************************************************************
317 * EXC_CallHandler
318 *
319 * Call an exception handler, setting up an exception frame to catch exceptions
320 * happening during the handler execution.
321 * WARNING:
322 * Please do not change the first 4 parameters order in any way - some exceptions handlers
323 * rely on Base Pointer (EBP) to have a fixed position related to the exception frame
324 */
325static DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
326 WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
327 PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler)
328{
329 EXC_NESTED_FRAME newframe;
330 DWORD ret;
331
332 newframe.frame.Handler = nested_handler;
333 newframe.prevFrame = frame;
334 EXC_push_frame( &newframe.frame );
335 dprintf(("KERNEL32: Calling handler at %p code=%lx flags=%lx\n",
336 handler, record->ExceptionCode, record->ExceptionFlags));
337 ret = handler( record, frame, context, dispatcher );
338 dprintf(("KERNEL32: Handler returned %lx\n", ret));
339 EXC_pop_frame( &newframe.frame );
340 return ret;
341}
342#endif
343//******************************************************************************
344//******************************************************************************
345DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext)
346{
347 PWINEXCEPTION_FRAME pFrame, pPrevFrame, dispatch, nested_frame;
348 int rc;
349
350 // get chain of exception frames
351 rc = ExceptionContinueSearch;
352
353 nested_frame = NULL;
354 TEB *winteb = GetThreadTEB();
355 pFrame = (PWINEXCEPTION_FRAME)winteb->except;
356
357 dprintf(("KERNEL32: RtlDispatchException entered"));
358
359 PrintWin32ExceptionChain(pFrame);
360
361 // walk the exception chain
362 while( (pFrame != NULL) && ((ULONG)((ULONG)pFrame & 0xFFFFF000) != 0xFFFFF000) )
363 {
364 pPrevFrame = __seh_get_prev_frame(pFrame);
365
366 dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X",
367 pFrame, pPrevFrame));
368 if (pFrame == pPrevFrame) {
369 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
370 return 0;
371 }
372
373 dispatch=0;
374
375 /* Check frame address */
376 if (((void*)pFrame < winteb->stack_low) ||
377 ((void*)(pFrame+1) > winteb->stack_top) ||
378 (int)pFrame & 3)
379 {
380 dprintf(("Invalid stack! low=%08X, top=%08X, pframe = %08X",
381 winteb->stack_low, winteb->stack_top, pFrame));
382
383 pRecord->ExceptionFlags |= EH_STACK_INVALID;
384 break;
385 }
386
387
388 /* call handler */
389 if (pFrame->Handler)
390 {
391 rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch,
392 pFrame->Handler, EXC_RaiseHandler);
393 }
394 else
395 {
396 dprintf(("pFrame->Handler is NULL!!!!!"));
397 rc = ExceptionContinueSearch;
398 }
399
400 PrintWin32ExceptionChain(pFrame);
401
402 if (pFrame == nested_frame)
403 {
404 /* no longer nested */
405 nested_frame = NULL;
406 pRecord->ExceptionFlags &= ~EH_NESTED_CALL;
407 }
408
409
410 switch(rc)
411 {
412 case ExceptionContinueExecution:
413 if (!(pRecord->ExceptionFlags & EH_NONCONTINUABLE))
414 {
415 dprintf(("KERNEL32: RtlDispatchException returns %#x (ContinueExecution)", rc));
416 return rc;
417 }
418 break;
419 case ExceptionContinueSearch:
420 break;
421 case ExceptionNestedException:
422 if (nested_frame < dispatch) nested_frame = dispatch;
423 pRecord->ExceptionFlags |= EH_NESTED_CALL;
424 break;
425 default:
426 break;
427 }
428
429 dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X",
430 pFrame, pPrevFrame));
431 if (pFrame == pPrevFrame)
432 {
433 dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
434 break;
435 }
436 pFrame = pPrevFrame;
437 }
438 dprintf(("KERNEL32: RtlDispatchException returns %#x", rc));
439 PrintWin32ExceptionChain(pFrame);
440 return rc;
441}
442/*****************************************************************************
443 * Name : int _Pascal OS2RtlUnwind
444 * Purpose : Unwinds exception handlers (heavily influenced by Wine)
445 * Parameters: ...
446 * Variables :
447 * Result :
448 * Remark :
449 * Status :
450 *
451 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
452 *****************************************************************************/
453
454int _Pascal OS2RtlUnwind(PWINEXCEPTION_FRAME pEndFrame,
455 LPVOID unusedEip,
456 PWINEXCEPTION_RECORD pRecord,
457 DWORD returnEax,
458 DWORD eip, DWORD esp, DWORD ebp, DWORD flags,
459 DWORD eax, DWORD ebx, DWORD ecx, DWORD edx,
460 DWORD edi, DWORD esi, DWORD cs, DWORD ds,
461 DWORD es, DWORD fs, DWORD gs, DWORD ss)
462{
463 PWINEXCEPTION_FRAME frame, prevFrame, dispatch;
464 WINEXCEPTION_RECORD record, newrec;
465 WINCONTEXT context;
466 DWORD rc;
467
468 dprintf(("KERNEL32: RtlUnwind pEndFrame=%08X, unusedEip=%08X, pRecord=%08X, returnEax=%#x\n", pEndFrame, unusedEip, pRecord, returnEax));
469
470 TEB *winteb = GetThreadTEB();
471 if (!winteb)
472 {
473 /* We're being called from __seh_handler called upon unwinding the OS/2
474 * exception chain after the Win32 TIB structure is destroyed. This for
475 * example happens when we terminate the thread or the process from within
476 * the __try block. Just ignore this call retur (note that the Win32
477 * exception chain should be already unwound by this moment). */
478 dprintf(("KERNEL32: RtlUnwind returning due to zero Win32 TEB.\n"));
479 return 0;
480 }
481
482 memset(&context, 0, sizeof(context));
483 context.ContextFlags = WINCONTEXT_FULL; //segments, integer, control
484 context.SegGs = gs;
485 context.SegFs = fs;
486 context.SegEs = es;
487 context.SegDs = ds;
488 context.Edi = edi;
489 context.Esi = esi;
490 context.Ebx = ebx;
491 context.Edx = edx;
492 context.Ecx = ecx;
493 context.Eax = returnEax;
494 context.Ebp = ebp;
495 context.Eip = eip;
496 context.SegCs = cs;
497 context.EFlags = flags;
498 context.Esp = esp;
499 context.SegSs = ss;
500
501 /* build an exception record, if we do not have one */
502 if(!pRecord)
503 {
504 memset(&record, 0, sizeof(record));
505 record.ExceptionCode = STATUS_UNWIND;
506 record.ExceptionFlags = 0;
507 record.ExceptionRecord = NULL;
508 record.ExceptionAddress = (LPVOID)eip;
509 record.NumberParameters = 0;
510 pRecord = &record;
511 }
512
513 if(pEndFrame) pRecord->ExceptionFlags |= EH_UNWINDING;
514 else pRecord->ExceptionFlags |= EH_UNWINDING | EH_EXIT_UNWIND;
515
516 /* get chain of exception frames */
517 frame = (PWINEXCEPTION_FRAME)winteb->except;
518
519 PrintWin32ExceptionChain(frame);
520
521 while (((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) && (frame != pEndFrame))
522 {
523 prevFrame = __seh_get_prev_frame(frame);
524
525 /* Check frame address */
526 if (pEndFrame && (frame > pEndFrame))
527 {
528 newrec.ExceptionCode = STATUS_INVALID_UNWIND_TARGET;
529 newrec.ExceptionFlags = EH_NONCONTINUABLE;
530 newrec.ExceptionRecord = pRecord;
531 newrec.NumberParameters = 0;
532 dprintf(("KERNEL32: RtlUnwind terminating thread (invalid target).\n"));
533 DosExit(EXIT_THREAD, 0);
534 }
535 if (((void*)frame < winteb->stack_low) ||
536 ((void*)(frame+1) > winteb->stack_top) ||
537 (int)frame & 3)
538 {
539 newrec.ExceptionCode = STATUS_BAD_STACK;
540 newrec.ExceptionFlags = EH_NONCONTINUABLE;
541 newrec.ExceptionRecord = pRecord;
542 newrec.NumberParameters = 0;
543 dprintf(("KERNEL32: RtlUnwind terminating thread (bad stack).\n"));
544 DosExit(EXIT_THREAD, 0);
545 }
546
547 /* Call handler */
548 dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler));
549 if(frame->Handler) {
550 rc = EXC_CallHandler(pRecord, frame, &context, &dispatch, frame->Handler, EXC_UnwindHandler );
551 }
552 else {
553 dprintf(("pFrame->Handler is NULL!!!!!"));
554 rc = ExceptionContinueSearch;
555 }
556 dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc));
557 switch (rc)
558 {
559 case ExceptionContinueSearch:
560 break;
561 case ExceptionCollidedUnwind:
562 frame = dispatch;
563 break;
564 default:
565 newrec.ExceptionCode = STATUS_INVALID_DISPOSITION;
566 newrec.ExceptionFlags = EH_NONCONTINUABLE;
567 newrec.ExceptionRecord = pRecord;
568 newrec.NumberParameters = 0;
569 dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
570 DosExit(EXIT_THREAD, 0);
571 break;
572 }
573 dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, prevFrame));
574 SetExceptionChain((DWORD)prevFrame);
575 frame = prevFrame;
576 dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame,
577 ((ULONG)((ULONG)frame & 0xFFFFF000) != 0xFFFFF000) ?
578 __seh_get_prev_frame(frame) : (void*)0xFFFFFFFF));
579 }
580
581 dprintf(("KERNEL32: RtlUnwind returning.\n"));
582 PrintWin32ExceptionChain(frame);
583 return(0);
584}
585
586
587/*****************************************************************************
588 * Name : LONG WIN32API UnhandledExceptionFilter
589 * Purpose :
590 * Parameters: ...
591 * Variables :
592 * Result :
593 * Remark :
594 * Status :
595 *
596 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
597 *****************************************************************************/
598
599LONG WIN32API UnhandledExceptionFilter(PWINEXCEPTION_POINTERS lpexpExceptionInfo)
600{
601 char szModName[16];
602 char message[128];
603 ULONG iObj;
604 ULONG offObj;
605 HMODULE hmod;
606 DWORD rc;
607
608 dprintf(("KERNEL32: Default UnhandledExceptionFilter, CurrentErrorMode=%X", CurrentErrorMode));
609
610 // We must not care about ErrorMode here!! The app expects that its own
611 // UnhandledExceptionFilter will be cared even if it never touched ErrorMode.
612 if(CurrentUnhExceptionFlt) // && !(CurrentErrorMode & (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX)))
613 {
614 dprintf(("KERNEL32: Calling user UnhandledExceptionFilter"));
615 rc = CurrentUnhExceptionFlt(lpexpExceptionInfo);
616 if(rc != WINEXCEPTION_CONTINUE_SEARCH)
617 return rc;
618 }
619
620 if (DosQueryModFromEIP(&hmod, &iObj, sizeof(szModName), szModName, &offObj, (ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress))
621 sprintf(message, "Unhandled exception 0x%08lx at address 0x%08lx. (DQMFEIP rc=%d)",
622 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
623 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
624 else
625 {
626 if (iObj == -1)
627 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
628 Win32ImageBase * pMod;
629 if (WinExe && WinExe->insideModule((ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress))
630 pMod = WinExe;
631 else
632 pMod = Win32DllBase::findModuleByAddr((ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
633 if (pMod != NULL)
634 {
635 szModName[0] = '\0';
636 strncat(szModName, pMod->getModuleName(), sizeof(szModName) - 1);
637 iObj = 0xFF;
638 offObj = (ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress
639 - (ULONG)pMod->getInstanceHandle();
640 }
641 }
642 sprintf(message,
643 "Unhandled exception 0x%08lx at address 0x%08lx.\r"
644 "Mod: %s obj: 0x%2lx off:0x%08lx",
645 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
646 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress,
647 szModName, iObj, offObj);
648 }
649
650/* This is very dangerous. Can hang PM.
651 rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, message, "Application Error",
652 0, MB_ABORTRETRYIGNORE | MB_ERROR);
653 switch (rc)
654 {
655 case MBID_IGNORE:
656 return WINEXCEPTION_CONTINUE_EXECUTION;
657
658 case MBID_ABORT:
659 case MBID_RETRY:
660 default:
661 return WINEXCEPTION_EXECUTE_HANDLER;
662 }
663*/
664 return WINEXCEPTION_EXECUTE_HANDLER;
665}
666/*****************************************************************************
667 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
668 * Purpose :
669 * Parameters: ...
670 * Variables :
671 * Result :
672 * Remark :
673 * Status :
674 *
675 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
676 *****************************************************************************/
677
678LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
679{
680 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
681
682 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n",
683 lpTopLevelExceptionFilter));
684
685 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
686
687 return(old);
688}
689
690
691/*****************************************************************************
692 * Name : KillWin32Process
693 * Purpose :
694 * Parameters: ...
695 * Variables :
696 * Result :
697 * Remark :
698 * Status :
699 *
700 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
701 *****************************************************************************/
702
703
704//******************************************************************************
705VOID WIN32API ExitProcess(DWORD exitcode);
706//******************************************************************************
707void KillWin32Process(void)
708{
709 static BOOL fEntry = FALSE;
710
711 if(!fExitProcess && fEntry == FALSE) {
712 fEntry = TRUE;
713 ExitProcess(666);
714 return;
715 }
716 //Restore original OS/2 TIB selector
717 RestoreOS2FS();
718
719 DosExit(EXIT_PROCESS, 666);
720}
721//*****************************************************************************
722//*****************************************************************************
723void KillWin32Thread(void)
724{
725// ExitThread(666);
726 //Restore original OS/2 TIB selector
727 RestoreOS2FS();
728
729 DosExit(EXIT_THREAD, 666);
730}
731//*****************************************************************************
732//*****************************************************************************
733static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec,
734 PEXCEPTIONREGISTRATIONRECORD pERegRec,
735 PCONTEXTRECORD pCtxRec,
736 PVOID p,
737 PSZ szTrapDump)
738{
739 if(pERepRec->ExceptionNum == XCPT_GUARD_PAGE_VIOLATION)
740 {
741 strcpy(szTrapDump, "Guard Page Violation");
742 return;
743 }
744
745 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
746 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
747 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
748 BOOL fExcptFatal = TRUE; /* fatal exception ? */
749 BOOL fExcptPortable = TRUE; /* portability of exception */
750 PPIB pPIB; /* process information block */
751 PTIB pTIB; /* thread information block */
752 ULONG ulModule; /* module number */
753 ULONG ulObject; /* object number within the module */
754 CHAR szModule[260]; /* buffer for the module name */
755 ULONG ulOffset; /* offset within the object within the module */
756 char szLineException[512];
757 char szLineExceptionType[128];
758
759 szLineException[0] = 0; /* initialize */
760 szLineExceptionType[0] = 0; /* initialize */
761 switch(pERepRec->ExceptionNum) /* take according action */
762 {
763 /* portable, non-fatal software-generated exceptions */
764 case XCPT_GUARD_PAGE_VIOLATION:
765 strcpy(szLineException, "Guard Page Violation");
766 sprintf(szLineExceptionType, "R/W %08xh at %08xh.", pERepRec->ExceptionInfo[0], pERepRec->ExceptionInfo[1]);
767 fExcptSoftware = TRUE;
768 fExcptFatal = FALSE;
769 rc = XCPT_CONTINUE_EXECUTION;
770 break;
771
772 case XCPT_UNABLE_TO_GROW_STACK:
773 strcpy(szLineException, "Unable To Grow Stack");
774 fExcptSoftware = TRUE;
775 fExcptFatal = FALSE;
776 rc = XCPT_CONTINUE_EXECUTION;
777 break;
778
779 /* portable, fatal, hardware-generated exceptions */
780 case XCPT_ACCESS_VIOLATION:
781 strcpy(szLineException, "Access Violation");
782 switch (pERepRec->ExceptionInfo[0])
783 {
784 case XCPT_READ_ACCESS:
785 sprintf (szLineExceptionType, "Read Access at address %08xh", pERepRec->ExceptionInfo[1]);
786 break;
787
788 case XCPT_WRITE_ACCESS:
789 sprintf (szLineExceptionType, "Write Access at address %08x", pERepRec->ExceptionInfo[1]);
790 break;
791
792 case XCPT_SPACE_ACCESS:
793 sprintf (szLineExceptionType, "Space Access at selector %08x", pERepRec->ExceptionInfo[1]);
794 break;
795
796 case XCPT_LIMIT_ACCESS:
797 strcpy (szLineExceptionType, "Limit Access");
798 break;
799
800 case XCPT_UNKNOWN_ACCESS:
801 strcpy (szLineExceptionType, "Unknown Access");
802 break;
803
804 default:
805 strcpy (szLineExceptionType, "(Invalid Access Code)");
806 break;
807 }
808 break;
809
810 case XCPT_INTEGER_DIVIDE_BY_ZERO:
811 strcpy(szLineException, "Division By Zero (Integer)");
812 break;
813
814 case XCPT_FLOAT_DIVIDE_BY_ZERO:
815 strcpy(szLineException, "Division By Zero (Float)");
816 break;
817
818 case XCPT_FLOAT_INVALID_OPERATION:
819 strcpy(szLineException, "Invalid Floating Point Operation");
820 break;
821
822 case XCPT_ILLEGAL_INSTRUCTION:
823 strcpy(szLineException, "Illegal Instruction");
824 break;
825
826 case XCPT_PRIVILEGED_INSTRUCTION:
827 strcpy(szLineException, "Privileged Instruction");
828 break;
829
830 case XCPT_INTEGER_OVERFLOW:
831 strcpy(szLineException, "Integer Overflow");
832 break;
833
834 case XCPT_FLOAT_OVERFLOW:
835 strcpy(szLineException, "Floating Point Overflow");
836 break;
837
838 case XCPT_FLOAT_UNDERFLOW:
839 strcpy(szLineException, "Floating Point Underflow");
840 break;
841
842 case XCPT_FLOAT_DENORMAL_OPERAND:
843 strcpy(szLineException, "Floating Point Denormal Operand");
844 break;
845
846 case XCPT_FLOAT_INEXACT_RESULT:
847 strcpy(szLineException, "Floating Point Inexact Result");
848 break;
849
850 case XCPT_FLOAT_STACK_CHECK:
851 strcpy(szLineException, "Floating Point Stack Check");
852 break;
853
854 case XCPT_DATATYPE_MISALIGNMENT:
855 strcpy(szLineException, "Datatype Misalignment");
856 sprintf(szLineExceptionType, "R/W %08x alignment %08x at %08x.", pERepRec->ExceptionInfo[0],
857 pERepRec->ExceptionInfo[1], pERepRec->ExceptionInfo[2]);
858 break;
859
860 case XCPT_BREAKPOINT:
861 strcpy(szLineException, "Breakpoint (DEBUG)");
862 break;
863
864 case XCPT_SINGLE_STEP:
865 strcpy(szLineException, "Single Step (DEBUG)");
866 break;
867
868 /* portable, fatal, software-generated exceptions */
869 case XCPT_IN_PAGE_ERROR:
870 strcpy(szLineException, "In Page Error");
871 sprintf(szLineExceptionType, "at %08x.", pERepRec->ExceptionInfo[0]);
872 fExcptSoftware = TRUE;
873 break;
874
875 case XCPT_PROCESS_TERMINATE:
876 strcpy(szLineException, "Process Termination");
877 fExcptSoftware = TRUE;
878 break;
879
880 case XCPT_ASYNC_PROCESS_TERMINATE:
881 strcpy(szLineException, "Process Termination (async)");
882 sprintf(szLineExceptionType, "terminating thread TID=%u", pERepRec->ExceptionInfo[0]);
883 fExcptSoftware = TRUE;
884 break;
885
886 case XCPT_NONCONTINUABLE_EXCEPTION:
887 strcpy(szLineException, "Noncontinuable Exception");
888 fExcptSoftware = TRUE;
889 break;
890
891 case XCPT_INVALID_DISPOSITION:
892 strcpy(szLineException, "Invalid Disposition");
893 fExcptSoftware = TRUE;
894 break;
895
896 /* non-portable, fatal exceptions */
897 case XCPT_INVALID_LOCK_SEQUENCE:
898 strcpy(szLineException, "Invalid Lock Sequence");
899 fExcptSoftware = TRUE;
900 fExcptPortable = FALSE;
901 break;
902
903 case XCPT_ARRAY_BOUNDS_EXCEEDED:
904 strcpy(szLineException, "Array Bounds Exceeded");
905 fExcptSoftware = TRUE;
906 fExcptPortable = FALSE;
907 break;
908
909 /* unwind operation exceptions */
910 case XCPT_UNWIND:
911 strcpy(szLineException, "Unwind Exception");
912 fExcptSoftware = TRUE;
913 fExcptPortable = FALSE;
914 break;
915
916 case XCPT_BAD_STACK:
917 strcpy(szLineException, "Unwind Exception, Bad Stack");
918 fExcptSoftware = TRUE;
919 fExcptPortable = FALSE;
920 break;
921
922 case XCPT_INVALID_UNWIND_TARGET:
923 strcpy(szLineException, "Unwind Exception, Invalid Target");
924 fExcptSoftware = TRUE;
925 fExcptPortable = FALSE;
926 break;
927
928 /* fatal signal exceptions */
929 case XCPT_SIGNAL:
930 strcpy(szLineException, "Signal");
931 sprintf(szLineExceptionType, "Signal Number = %08x", pERepRec->ExceptionInfo[0]);
932 fExcptSoftware = TRUE;
933 fExcptPortable = FALSE;
934
935 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
936 {
937 case XCPT_SIGNAL_INTR:
938 strcpy(szLineException, "Signal (Interrupt)");
939 break;
940
941 case XCPT_SIGNAL_KILLPROC:
942 strcpy(szLineException, "Signal (Kill Process)");
943 break;
944
945 case XCPT_SIGNAL_BREAK:
946 strcpy(szLineException, "Signal (Break)");
947 break;
948 }
949 break;
950
951 default:
952 strcpy(szLineException, "(unknown exception code)");
953 sprintf(szLineExceptionType, "Exception Code = %08x", pERepRec->ExceptionNum);
954 break;
955 }
956
957 sprintf(szTrapDump, "---[Exception Information]------------\n %s (", szLineException);
958
959 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
960 strcat (szTrapDump, "software generated,");
961 else
962 strcat (szTrapDump, "hardware generated,");
963
964 if (fExcptPortable == TRUE) /* portable exception ? */
965 strcat (szTrapDump, "portable,");
966 else
967 strcat (szTrapDump, "non-portable,");
968
969 if (fExcptFatal == TRUE) /* fatal exception ? */
970 strcat (szTrapDump, "fatal");
971 else
972 strcat (szTrapDump, "non-fatal");
973
974 strcat(szTrapDump, ")\n"); /* add trailing brace */
975
976 if (szLineExceptionType[0])
977 sprintf(szTrapDump + strlen(szTrapDump), " %s\n", szLineExceptionType);
978
979 sprintf(szLineException, " Exception Address = %08x ", pERepRec->ExceptionAddress);
980 strcat(szTrapDump, szLineException);
981
982 rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
983 szModule, &ulOffset, (ULONG)pERepRec->ExceptionAddress);
984
985 if(rc == NO_ERROR && ulObject != -1)
986 {
987 sprintf(szLineException, "<%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject + 1, ulOffset);
988#ifdef RAS
989 char szSYMInfo[260];
990
991 DosQueryModuleName(ulModule, sizeof(szModule), szModule);
992
993 int namelen = strlen(szModule);
994 if(namelen > 3)
995 {
996 strcpy(szModule + namelen - 3, "SYM");
997 dbgGetSYMInfo(szModule, ulObject, ulOffset, szSYMInfo, sizeof (szSYMInfo),
998 FALSE);
999 strcat(szLineException, " ");
1000 strcat(szLineException, szSYMInfo);
1001 }
1002#else
1003 strcat(szLineException, "\n");
1004#endif
1005 strcat(szTrapDump, szLineException);
1006 }
1007 else
1008 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
1009 Win32ImageBase * pMod;
1010 if (WinExe && WinExe->insideModule((ULONG)pERepRec->ExceptionAddress))
1011 pMod = WinExe;
1012 else
1013 pMod = Win32DllBase::findModuleByAddr((ULONG)pERepRec->ExceptionAddress);
1014 if (pMod != NULL)
1015 {
1016 szModule[0] = '\0';
1017 strncat(szModule, pMod->getModuleName(), sizeof(szModule) - 1);
1018 ulObject = 0xFF;
1019 ulOffset = (ULONG)pERepRec->ExceptionAddress - (ULONG)pMod->getInstanceHandle();
1020 sprintf(szLineException, "<%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject, ulOffset);
1021 }
1022 else sprintf(szLineException, "<unknown win32 module>\n");
1023
1024 strcat(szTrapDump, szLineException);
1025 }
1026
1027 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1028 if (rc == NO_ERROR)
1029 {
1030 sprintf(szLineException, " Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
1031 pTIB->tib_ordinal, pTIB->tib_ptib2->tib2_ultid, pTIB->tib_ptib2->tib2_ulpri);
1032 strcat(szTrapDump, szLineException);
1033
1034 sprintf(szLineException, " Process: PID: %u, Parent: %u, Status: %u\n", pPIB->pib_ulpid,
1035 pPIB->pib_ulppid, pPIB->pib_flstatus);
1036 strcat(szTrapDump, szLineException);
1037 }
1038
1039 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) { /* check flags */
1040 sprintf(szLineException, " SS:ESP=%04x:%08x EFLAGS=%08x\n", pCtxRec->ctx_SegSs, pCtxRec->ctx_RegEsp,
1041 pCtxRec->ctx_EFlags);
1042 strcat(szTrapDump, szLineException);
1043 sprintf(szLineException, " CS:EIP=%04x:%08x EBP =%08x\n", pCtxRec->ctx_SegCs, pCtxRec->ctx_RegEip,
1044 pCtxRec->ctx_RegEbp);
1045 strcat(szTrapDump, szLineException);
1046 }
1047
1048 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) { /* check flags */
1049 sprintf(szLineException, " EAX=%08x EBX=%08x ESI=%08x\n", pCtxRec->ctx_RegEax, pCtxRec->ctx_RegEbx,
1050 pCtxRec->ctx_RegEsi);
1051 strcat(szTrapDump, szLineException);
1052 sprintf(szLineException, " ECX=%08x EDX=%08x EDI=%08x\n", pCtxRec->ctx_RegEcx, pCtxRec->ctx_RegEdx,
1053 pCtxRec->ctx_RegEdi);
1054 strcat(szTrapDump, szLineException);
1055 }
1056
1057 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) { /* check flags */
1058 sprintf(szLineException, " DS=%04x ES=%08x FS=%04x GS=%04x\n", pCtxRec->ctx_SegDs, pCtxRec->ctx_SegEs, pCtxRec->ctx_SegFs, pCtxRec->ctx_SegGs);
1059 strcat(szTrapDump, szLineException);
1060 }
1061
1062 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1063 {
1064 ULONG ulCounter; /* temporary local counter for fp stack */
1065
1066 sprintf(szLineException, " Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1067 pCtxRec->ctx_env[0], pCtxRec->ctx_env[1],
1068 pCtxRec->ctx_env[2], pCtxRec->ctx_env[3]);
1069 strcat(szTrapDump, szLineException);
1070
1071 sprintf(szLineException, " Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1072 pCtxRec->ctx_env[4], pCtxRec->ctx_env[5], pCtxRec->ctx_env[6]);
1073 strcat(szTrapDump, szLineException);
1074
1075 for (ulCounter = 0; ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1076 ulCounter ++)
1077 {
1078 sprintf(szLineException, " FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1079 ulCounter, pCtxRec->ctx_stack[0].losig, pCtxRec->ctx_stack[0].hisig,
1080 pCtxRec->ctx_stack[0].signexp);
1081 strcat(szTrapDump, szLineException);
1082 }
1083 }
1084 sprintf(szLineException, "---[End Of Exception Information]-----\n");
1085 strcat(szTrapDump, szLineException);
1086}
1087/*****************************************************************************
1088 * Name : void static dprintfException
1089 * Purpose : log the exception to win32os2.log
1090 * Parameters: ...
1091 * Variables :
1092 * Result :
1093 * Remark :
1094 * Status :
1095 *
1096 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1097 *****************************************************************************/
1098
1099#ifdef DEBUG
1100
1101static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
1102 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1103 PCONTEXTRECORD pCtxRec,
1104 PVOID p)
1105{
1106 char szTrapDump[2048];
1107 szTrapDump[0] = '\0';
1108 sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1109#ifdef RAS
1110 RasLog (szTrapDump);
1111#endif
1112 /* now dump the information to the logfile */
1113 dprintf(("\n%s", szTrapDump));
1114}
1115
1116#else // DEBUG
1117#define dprintfException(a,b,c,d) do {} while (0)
1118#endif // DEBUG
1119
1120//*****************************************************************************
1121static char szExceptionLogFileName[CCHMAXPATH] = "";
1122static BOOL fExceptionLoggging = TRUE;
1123//*****************************************************************************
1124//Override filename of exception log (expects full path)
1125//*****************************************************************************
1126void WIN32API SetCustomExceptionLog(LPSTR lpszLogName)
1127{
1128 strcpy(szExceptionLogFileName, lpszLogName);
1129}
1130//*****************************************************************************
1131//*****************************************************************************
1132void WIN32API SetExceptionLogging(BOOL fEnable)
1133{
1134 fExceptionLoggging = fEnable;
1135}
1136//*****************************************************************************
1137//*****************************************************************************
1138static void logException(PEXCEPTIONREPORTRECORD pERepRec, PEXCEPTIONREGISTRATIONRECORD pERegRec, PCONTEXTRECORD pCtxRec, PVOID p)
1139{
1140 APIRET rc;
1141 HFILE hFile;
1142 ULONG ulAction, ulBytesWritten;
1143
1144 if(fExceptionLoggging == FALSE) {
1145 return;
1146 }
1147
1148 if(szExceptionLogFileName[0] == 0) {
1149 strcpy(szExceptionLogFileName, kernel32Path);
1150 strcat(szExceptionLogFileName, "\\except.log");
1151 }
1152 rc = DosOpen(szExceptionLogFileName, /* File path name */
1153 &hFile, /* File handle */
1154 &ulAction, /* Action taken */
1155 0L, /* File primary allocation */
1156 0L, /* File attribute */
1157 OPEN_ACTION_CREATE_IF_NEW |
1158 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
1159 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
1160 0L); /* No extended attribute */
1161
1162 if(rc == NO_ERROR) {
1163 DosSetFilePtr(hFile, 0, FILE_END, &ulBytesWritten);
1164 if(WinExe) {
1165 LPSTR lpszExeName;
1166
1167 lpszExeName = WinExe->getModuleName();
1168
1169 if(lpszExeName) {
1170 DosWrite(hFile, "\n", 2, &ulBytesWritten);
1171 DosWrite(hFile, lpszExeName, strlen(lpszExeName), &ulBytesWritten);
1172 DosWrite(hFile, "\n", 2, &ulBytesWritten);
1173 }
1174 }
1175 LPSTR lpszTime;
1176 time_t curtime;
1177
1178 curtime = time(NULL);
1179 lpszTime = asctime(localtime(&curtime));
1180 if(lpszTime) {
1181 DosWrite(hFile, lpszTime, strlen(lpszTime), &ulBytesWritten);
1182 }
1183
1184 char szTrapDump[2048];
1185 szTrapDump[0] = '\0';
1186 sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1187#ifdef RAS
1188 RasLog (szTrapDump);
1189#endif
1190 DosWrite(hFile, szTrapDump, strlen(szTrapDump), &ulBytesWritten);
1191 DosClose(hFile);
1192 }
1193}
1194
1195/*****************************************************************************
1196 * Name : ERR _System OS2ExceptionHandler
1197 * Purpose :
1198 * Parameters: ...
1199 * Variables :
1200 * Result :
1201 * Remark :
1202 * Status :
1203 *
1204 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1205 *****************************************************************************/
1206 /* from PPC DDK */
1207#ifndef XCPT_CONTINUE_STOP
1208#define XCPT_CONTINUE_STOP 0x00716668
1209#endif
1210
1211// Assembly wrapper for clearing the direction flag before calling our real
1212// exception handler
1213ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1214 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1215 PCONTEXTRECORD pCtxRec,
1216 PVOID p);
1217
1218ULONG APIENTRY OS2ExceptionHandler2ndLevel(PEXCEPTIONREPORTRECORD pERepRec,
1219 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1220 PCONTEXTRECORD pCtxRec,
1221 PVOID p)
1222{
1223#ifdef DEBUG
1224 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1225 // next dprintf won't wait forever
1226 int prevlock = LogException(ENTER_EXCEPTION);
1227#endif
1228
1229// @@VP20040507: no need to sprintf every exception
1230// //Print exception name & exception type
1231// //Not for a guard page exception as sprintfException uses a lot of stack
1232// //and can trigger nested guard page exceptions (crash)
1233// if(pERepRec->ExceptionNum != XCPT_GUARD_PAGE_VIOLATION) {
1234// sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1235// }
1236
1237 /* Access violation at a known location */
1238 switch(pERepRec->ExceptionNum)
1239 {
1240 case XCPT_FLOAT_DENORMAL_OPERAND:
1241 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1242 case XCPT_FLOAT_INEXACT_RESULT:
1243// case XCPT_FLOAT_INVALID_OPERATION:
1244 case XCPT_FLOAT_OVERFLOW:
1245 case XCPT_FLOAT_STACK_CHECK:
1246 case XCPT_FLOAT_UNDERFLOW:
1247 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1248 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1249 if((!fIsOS2Image || fSEHEnabled) && !fExitProcess) //Only for real win32 apps or if SEH enabled
1250 {
1251 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1252 {
1253 pCtxRec->ctx_env[0] |= 0x1F;
1254 pCtxRec->ctx_stack[0].losig = 0;
1255 pCtxRec->ctx_stack[0].hisig = 0;
1256 pCtxRec->ctx_stack[0].signexp = 0;
1257 }
1258 else
1259 {
1260 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1261 goto continueexecution;
1262 }
1263 }
1264 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1265 goto continuesearch;
1266
1267 case XCPT_PROCESS_TERMINATE:
1268 case XCPT_ASYNC_PROCESS_TERMINATE:
1269#if 0
1270 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1271 PrintExceptionChain();
1272 // fall through
1273#endif
1274 case XCPT_UNWIND:
1275 // Note that printing through ODINCRT (VACRT) when handling XCPT_UNWIND
1276 // is known to create deadlocks
1277 goto continuesearch;
1278
1279 case XCPT_ACCESS_VIOLATION:
1280 {
1281 Win32MemMap *map;
1282 BOOL fWriteAccess = FALSE;
1283 ULONG offset, accessflag;
1284
1285#ifdef WITH_KLIB
1286 if ( pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS
1287 || pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS
1288 || pERepRec->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
1289 || pERepRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS
1290 )
1291 {
1292 ENMACCESS enmAccess = enmRead;
1293 switch (pERepRec->ExceptionInfo[0])
1294 {
1295 case XCPT_WRITE_ACCESS: enmAccess = enmWrite; break;
1296 case XCPT_UNKNOWN_ACCESS: enmAccess = enmUnknown; break;
1297 }
1298
1299 if (kHeapDbgException((void*)pERepRec->ExceptionInfo[1],
1300 enmAccess,
1301 pERepRec->ExceptionAddress,
1302 pERepRec))
1303 goto continueexecution;
1304 }
1305#endif
1306
1307 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1308 goto continueFail;
1309 }
1310
1311//------------->>> WARNING: potentially dangerous workaround!!
1312 /* Some apps set ES = FS and Odin doesn't like that! */
1313 /* Note: maybe we could even check for ES != DS? But maybe */
1314 /* that might cause more harm than good... */
1315 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1316 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1317 /* Let's just reset ES to the DS value and hope it's okay */
1318 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1319 goto continueexecution;
1320 }
1321
1322 switch(pERepRec->ExceptionInfo[0]) {
1323 case XCPT_READ_ACCESS:
1324 accessflag = MEMMAP_ACCESS_READ;
1325 break;
1326 case XCPT_WRITE_ACCESS:
1327 accessflag = MEMMAP_ACCESS_WRITE;
1328 fWriteAccess = TRUE;
1329 break;
1330 case XCPT_EXECUTE_ACCESS:
1331 accessflag = MEMMAP_ACCESS_EXECUTE;
1332 break;
1333 default:
1334 goto continueFail;
1335 }
1336
1337 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1338 if(map == NULL) {
1339 Win32MemMapNotify *map;
1340
1341 map = Win32MemMapNotify::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1342 if(!map)
1343 goto continueFail;
1344
1345 BOOL ret = map->notify(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1346 if(ret == TRUE) goto continueexecution;
1347 goto continueFail;
1348 }
1349 BOOL ret = map->commitPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1350 map->Release();
1351 if(ret == TRUE)
1352 goto continueexecution;
1353
1354 //no break;
1355 }
1356continueFail:
1357
1358 /*
1359 * vladest: OK, try to implement write AUTOCOMMIT
1360 * last chance after MMAP commit is failed
1361 */
1362 if (XCPT_ACCESS_VIOLATION == pERepRec->ExceptionNum &&
1363 (/*pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS ||*/
1364 pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS) &&
1365 pERepRec->ExceptionInfo[1] != XCPT_DATA_UNKNOWN)
1366 {
1367 ULONG offset, accessflag;
1368
1369 DosQueryMem((PVOID) pERepRec->ExceptionInfo[1],
1370 &offset, &accessflag);
1371 dprintf(("KERNEL32: OS2ExceptionHandler: failed address info 0x%X size 0x%X. flag %X\n",
1372 pERepRec->ExceptionInfo[1], offset, accessflag));
1373 /* check for valid address */
1374 if (!pERepRec->ExceptionInfo[1] ||
1375 pERepRec->ExceptionInfo[1] == 0xAAAAAAAA ||
1376 !offset || offset == 0xAAAAAAAA)
1377 goto CrashAndBurn;
1378 /* memory committed, but no write access */
1379 if (accessflag & PAG_GUARD)
1380 accessflag &=~PAG_GUARD;
1381
1382 /* set memory aligned on page size and with size counting alignment */
1383 ULONG rc = DosSetMem((PVOID) (pERepRec->ExceptionInfo[1] & 0xFFFFF000),
1384 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
1385 accessflag | PAG_WRITE | PAG_COMMIT);
1386 dprintf(("KERNEL32: OS2ExceptionHandler: commiting 0x%X size 0x%X. RC: %i\n",
1387 pERepRec->ExceptionInfo[1] & 0xFFFFF000,
1388 offset + (pERepRec->ExceptionInfo[1] - (pERepRec->ExceptionInfo[1] & 0xFFFFF000)),
1389 rc));
1390 if (NO_ERROR == rc)
1391 goto continueexecution;
1392 else
1393 goto CrashAndBurn;
1394 }
1395
1396
1397////#define DEBUGSTACK
1398#ifdef DEBUGSTACK
1399 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1400 ULONG *stackptr;
1401 APIRET rc;
1402 int i;
1403 ULONG ulOffset, ulModule, ulObject;
1404 CHAR szModule[CCHMAXPATH];
1405
1406 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1407 dprintf(("Stack DUMP:"));
1408 for(i=0;i<16;i++) {
1409 rc = DosQueryModFromEIP(&ulModule,
1410 &ulObject,
1411 sizeof(szModule),
1412 szModule,
1413 &ulOffset,
1414 (ULONG)*stackptr);
1415
1416 if (rc == NO_ERROR)
1417 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1418 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1419 stackptr++;
1420 }
1421 dprintf(("Stack DUMP END"));
1422 }
1423#endif
1424 goto CrashAndBurn;
1425
1426 case XCPT_INVALID_LOCK_SEQUENCE:
1427 {
1428 TEB *teb = GetThreadTEB();
1429 USHORT *eip = (USHORT *)pCtxRec->ctx_RegEip;
1430
1431 if(teb && eip && *eip == SETTHREADCONTEXT_INVALID_LOCKOPCODE)
1432 {
1433 //Is this a pending SetThreadContext exception?
1434 //(see detailed description in the HMDeviceThreadClass::SetThreadContext method)
1435 if(teb->o.odin.context.ContextFlags)
1436 {
1437 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1438
1439 //NOTE: This will not work properly in case multiple threads execute this code
1440 dprintf(("Changing thread registers (SetThreadContext)!!"));
1441
1442 if(teb->o.odin.context.ContextFlags & WINCONTEXT_CONTROL) {
1443 pCtxRec->ctx_RegEbp = teb->o.odin.context.Ebp;
1444 pCtxRec->ctx_RegEip = teb->o.odin.context.Eip;
1445//// pCtxRec->ctx_SegCs = teb->o.odin.context.SegCs;
1446 pCtxRec->ctx_EFlags = teb->o.odin.context.EFlags;
1447 pCtxRec->ctx_RegEsp = teb->o.odin.context.Esp;
1448//// pCtxRec->ctx_SegSs = teb->o.odin.context.SegSs;
1449 }
1450 if(teb->o.odin.context.ContextFlags & WINCONTEXT_INTEGER) {
1451 pCtxRec->ctx_RegEdi = teb->o.odin.context.Edi;
1452 pCtxRec->ctx_RegEsi = teb->o.odin.context.Esi;
1453 pCtxRec->ctx_RegEbx = teb->o.odin.context.Ebx;
1454 pCtxRec->ctx_RegEdx = teb->o.odin.context.Edx;
1455 pCtxRec->ctx_RegEcx = teb->o.odin.context.Ecx;
1456 pCtxRec->ctx_RegEax = teb->o.odin.context.Eax;
1457 }
1458 if(teb->o.odin.context.ContextFlags & WINCONTEXT_SEGMENTS) {
1459 pCtxRec->ctx_SegGs = teb->o.odin.context.SegGs;
1460//// pCtxRec->ctx_SegFs = teb->o.odin.context.SegFs;
1461 pCtxRec->ctx_SegEs = teb->o.odin.context.SegEs;
1462 pCtxRec->ctx_SegDs = teb->o.odin.context.SegDs;
1463 }
1464 if(teb->o.odin.context.ContextFlags & WINCONTEXT_FLOATING_POINT) {
1465 //TODO: First 7 dwords the same?
1466 memcpy(pCtxRec->ctx_env, &teb->o.odin.context.FloatSave, sizeof(pCtxRec->ctx_env));
1467 memcpy(pCtxRec->ctx_stack, &teb->o.odin.context.FloatSave.RegisterArea, sizeof(pCtxRec->ctx_stack));
1468 }
1469 USHORT *lpAlias = (USHORT *)((char *)teb->o.odin.lpAlias + teb->o.odin.dwAliasOffset);
1470 *lpAlias = teb->o.odin.savedopcode;
1471
1472 //Clear SetThreadContext markers
1473 teb->o.odin.context.ContextFlags = 0;
1474
1475 OSLibDosFreeMem(teb->o.odin.lpAlias);
1476
1477 teb->o.odin.lpAlias = NULL;
1478 teb->o.odin.dwAliasOffset = 0;
1479
1480 //restore the original priority (we boosted it to ensure this thread was scheduled first)
1481 SetThreadPriority(teb->o.odin.hThread, GetThreadPriority(teb->o.odin.hThread));
1482 goto continueexecution;
1483 }
1484 else DebugInt3(); //oh, oh!!!!!
1485
1486 }
1487 //no break;
1488 }
1489
1490 case XCPT_PRIVILEGED_INSTRUCTION:
1491 case XCPT_ILLEGAL_INSTRUCTION:
1492 case XCPT_BREAKPOINT:
1493 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1494 case XCPT_DATATYPE_MISALIGNMENT:
1495 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1496 case XCPT_INTEGER_OVERFLOW:
1497 case XCPT_SINGLE_STEP:
1498 case XCPT_IN_PAGE_ERROR:
1499CrashAndBurn:
1500 //SvL: TODO: this may not always be the right thing to do
1501 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1502 // of this exception handler. We better bail out ASAP or we'll likely
1503 // recurse infinitely until we run out of stack space!!
1504 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1505 goto continuesearch;
1506
1507#if defined(DEBUG)
1508 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1509
1510 if(!fExitProcess && (pCtxRec->ContextFlags & CONTEXT_CONTROL)) {
1511 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1512 }
1513#endif
1514
1515 if((!fIsOS2Image || fSEHEnabled) && !fExitProcess) //Only for real win32 apps or if SEH enabled
1516 {
1517 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1518 {
1519 goto continueexecution;
1520 }
1521 else
1522 {
1523 goto continuesearch;
1524 }
1525 }
1526 else {
1527 if(fExitProcess) {
1528 PPIB pPIB;
1529 PTIB pTIB;
1530 APIRET rc;
1531
1532 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1533 if(rc == NO_ERROR)
1534 {
1535 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill thread"));
1536
1537 pCtxRec->ctx_RegEip = (pTIB->tib_ptib2->tib2_ultid != 1) ? (ULONG)KillWin32Thread : (ULONG)KillWin32Process;
1538 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1539 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1540 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1541 goto continueexecution;
1542 }
1543 }
1544 goto continuesearch; //pass on to OS/2 RTL or app exception handler
1545 }
1546
1547 //Log fatal exception here
1548 logException(pERepRec, pERegRec, pCtxRec, p);
1549
1550 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1551
1552 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1553 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1554 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1555 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1556 goto continueexecution;
1557
1558 case XCPT_GUARD_PAGE_VIOLATION:
1559 {
1560 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1561 //Don't print anything here -> fatal hang if exception occurred
1562 //inside fprintf
1563 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1564 TEB *teb = GetThreadTEB();
1565 DWORD stacktop, stackbottom;
1566
1567 if(teb == NULL) {
1568 goto continueGuardException;
1569 }
1570
1571 stacktop = (DWORD)teb->stack_top;
1572 stackbottom = (DWORD)teb->stack_low;
1573
1574 stackbottom = stackbottom & ~0xFFF; //round down to page boundary
1575 stacktop = stacktop & ~0xFFF;
1576
1577 //Make sure we detect a stack overflow condition before the system does
1578 if(!fIsOS2Image &&
1579 pERepRec->ExceptionInfo[1] >= stackbottom &&
1580 pERepRec->ExceptionInfo[1] < stacktop
1581 )
1582 {//this is a guard page exception for the thread stack
1583 APIRET rc;
1584 ULONG ulAddress, cbSize, ulMemFlags;
1585
1586 //round down to page boundary
1587 ulAddress = pERepRec->ExceptionInfo[1] & ~0xFFF;
1588
1589#if 0
1590 rc = DosQueryMem((PVOID)ulAddress, &cbSize, &ulMemFlags);
1591 if(rc) {
1592 dprintf(("ERROR: DosQueryMem old guard page failed with rc %d", rc));
1593 goto continueGuardException;
1594 }
1595#endif
1596
1597 if(ulAddress == stackbottom + PAGE_SIZE)
1598 {//we don't have any stack left, throw an XCPT_UNABLE_TO_GROW_STACK
1599 //exception
1600 if(!fExitProcess) //Only for real win32 apps
1601 {
1602 EXCEPTIONREPORTRECORD recoutofstack;
1603
1604 recoutofstack = *pERepRec;
1605 recoutofstack.ExceptionNum = XCPT_UNABLE_TO_GROW_STACK;
1606 recoutofstack.fHandlerFlags = 0;
1607 recoutofstack.NestedExceptionReportRecord = NULL;
1608 recoutofstack.cParameters = 0;
1609
1610 if(OSLibDispatchException(&recoutofstack, pERegRec, pCtxRec, p) == TRUE)
1611 {
1612 goto continueexecution;
1613 }
1614 }
1615 }
1616 }
1617 else
1618 {//check for memory map guard page exception
1619 Win32MemMap *map;
1620 BOOL fWriteAccess = FALSE, ret;
1621 ULONG offset, accessflag;
1622
1623 switch(pERepRec->ExceptionInfo[0]) {
1624 case XCPT_READ_ACCESS:
1625 accessflag = MEMMAP_ACCESS_READ;
1626 break;
1627 case XCPT_WRITE_ACCESS:
1628 accessflag = MEMMAP_ACCESS_WRITE;
1629 fWriteAccess = TRUE;
1630 break;
1631 default:
1632 goto continueGuardException;
1633 }
1634
1635 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1636 if(map) {
1637 ret = map->commitGuardPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1638 map->Release();
1639 if(ret == TRUE)
1640 goto continueexecution;
1641 }
1642 }
1643
1644continueGuardException:
1645 goto continuesearch;
1646 }
1647
1648 case XCPT_UNABLE_TO_GROW_STACK:
1649 {
1650 //SvL: XCPT_UNABLE_TO_GROW_STACK is typically nested (failed guard page
1651 // exception), so don't ignore them
1652 // We should no longer receive those!!
1653// @@VP20040507: Isn't this a bit dangerous to call dprintfon such exception
1654//#ifdef DEBUG
1655// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1656//#endif
1657 goto continuesearch;
1658 }
1659
1660
1661 /*
1662 * In OS/2 VIO Ctrl-C and Ctrl-Break is special stuff which comes in
1663 * thru the exception handler. In Win32 CUI they are handled by a
1664 * ControlCtrlEvent procedure. So, if we receive one of those signals
1665 * we assume that this is a VIO program and let the handlers handle this.
1666 * (If they want to.)
1667 */
1668 case XCPT_SIGNAL:
1669 {
1670 //This is not a reliable way to distinguish between Ctrl-C & Ctrl-Break
1671 BOOL breakPressed = WinGetKeyState(HWND_DESKTOP,VK_BREAK) & 0x8000;
1672
1673 switch (pERepRec->ExceptionInfo[0])
1674 {
1675 case XCPT_SIGNAL_BREAK:
1676 breakPressed = TRUE;
1677 //no break
1678
1679 case XCPT_SIGNAL_INTR:
1680 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1681 if (InternalGenerateConsoleCtrlEvent((breakPressed) ? CTRL_BREAK_EVENT : CTRL_C_EVENT, 0))
1682 {
1683 DosAcknowledgeSignalException(pERepRec->ExceptionInfo[0]);
1684 goto continueexecution;
1685 }
1686 goto continuesearch;
1687
1688 case XCPT_SIGNAL_KILLPROC: /* resolve signal information */
1689 goto continuesearch;
1690 }
1691 goto CrashAndBurn;
1692 }
1693
1694 default: //non-continuable exceptions
1695 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1696 goto continuesearch;
1697 }
1698continuesearch:
1699#ifdef DEBUG
1700 LogException(LEAVE_EXCEPTION, prevlock);
1701#endif
1702 return XCPT_CONTINUE_SEARCH;
1703
1704continueexecution:
1705#ifdef DEBUG
1706 LogException(LEAVE_EXCEPTION, prevlock);
1707#endif
1708 return XCPT_CONTINUE_EXECUTION;
1709}
1710
1711/*****************************************************************************
1712 * Name : void OS2SetExceptionHandler
1713 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1714 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1715 * Variables :
1716 * Result :
1717 * Remark :
1718 * Status :
1719 *
1720 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1721 *****************************************************************************/
1722void OS2SetExceptionHandler(void *exceptframe)
1723{
1724 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1725
1726 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1727 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1728
1729 /* disable trap popups */
1730// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1731
1732 DosSetExceptionHandler(pExceptRec);
1733 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1734#ifdef DEBUG_ENABLELOG_LEVEL2
1735 PrintExceptionChain();
1736#endif
1737}
1738//*****************************************************************************
1739// Set exception handler if our handler has not yet been registered
1740//*****************************************************************************
1741void WIN32API ODIN_SetExceptionHandler(void *pExceptionRegRec)
1742{
1743 BOOL fFound = FALSE;
1744 USHORT sel = RestoreOS2FS();
1745 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1746
1747 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1748 {
1749 if(pExceptRec->ExceptionHandler == OS2ExceptionHandler)
1750 {
1751 fFound = TRUE;
1752 break;
1753 }
1754 pExceptRec = pExceptRec->prev_structure;
1755 }
1756 if(!fFound)
1757 {
1758 OS2SetExceptionHandler(pExceptionRegRec);
1759 }
1760 SetFS(sel);
1761}
1762//*****************************************************************************
1763// Remove exception handler if it was registered previously
1764//
1765//*****************************************************************************
1766void WIN32API ODIN_UnsetExceptionHandler(void *pExceptionRegRec)
1767{
1768 USHORT sel = RestoreOS2FS();
1769 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1770 BOOL fFound = FALSE;
1771
1772 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1773 {
1774 if(pExceptRec == pExceptionRegRec)
1775 {
1776 fFound = TRUE;
1777 break;
1778 }
1779 pExceptRec = pExceptRec->prev_structure;
1780 }
1781
1782#ifdef DEBUG
1783 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1784
1785 if(fFound && pExceptRec != (PEXCEPTIONREGISTRATIONRECORD)pExceptionRegRec)
1786 {
1787 dprintf(("ERROR: ODIN_UnsetExceptionHandler: INSIDE!!!: exc rec %p, head %p\n", pExceptionRegRec, pExceptRec));
1788 PrintExceptionChain ();
1789 }
1790#endif
1791 if(fFound) {
1792 OS2UnsetExceptionHandler(pExceptionRegRec);
1793 }
1794 SetFS(sel);
1795}
1796//*****************************************************************************
1797//*****************************************************************************
1798#ifdef DEBUG
1799void PrintExceptionChain()
1800{
1801 USHORT sel = RestoreOS2FS();
1802 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1803
1804 dprintf(("OS/2 Exception chain:"));
1805 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1806 {
1807 char szBuf[512];
1808 ULONG ulModule;
1809 ULONG ulObject, ulOffset;
1810 CHAR szModule[260];
1811
1812 *szBuf = '\0';
1813 APIRET rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
1814 szModule, &ulOffset, (ULONG)pExceptRec->ExceptionHandler);
1815 if(rc == NO_ERROR && ulObject != -1)
1816 {
1817 sprintf(szBuf, " <%8.8s> (%04X) obj %04X:%08X", szModule, ulModule, ulObject + 1, ulOffset);
1818#ifdef RAS
1819 char szSYMInfo[260];
1820
1821 DosQueryModuleName(ulModule, sizeof(szModule), szModule);
1822
1823 int namelen = strlen(szModule);
1824 if(namelen > 3)
1825 {
1826 strcpy(szModule + namelen - 3, "SYM");
1827 dbgGetSYMInfo(szModule, ulObject, ulOffset,
1828 szSYMInfo, sizeof (szSYMInfo), TRUE);
1829 strcat(szBuf, " ");
1830 strcat(szBuf, szSYMInfo);
1831 // remove trailing \n or space
1832 szBuf[strlen(szBuf) - 1] = '\0';
1833 }
1834#endif
1835 }
1836 else
1837 {
1838 *szBuf = '\0';
1839 }
1840
1841 dprintf((" record %08X, prev %08X, handler %08X%s",
1842 pExceptRec, pExceptRec->prev_structure, pExceptRec->ExceptionHandler,
1843 szBuf));
1844
1845 pExceptRec = pExceptRec->prev_structure;
1846 }
1847 dprintf(("END of OS/2 Exception chain."));
1848 SetFS(sel);
1849}
1850//*****************************************************************************
1851//*****************************************************************************
1852void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pFrame)
1853{
1854 dprintf(("Win32 exception chain:"));
1855 while ((pFrame != NULL) && ((ULONG)pFrame != 0xFFFFFFFF))
1856 {
1857 PWINEXCEPTION_FRAME pPrevFrame = __seh_get_prev_frame(pFrame);
1858 dprintf((" Record at %08X, Prev at %08X, handler at %08X%s",
1859 pFrame, pPrevFrame, pFrame->Handler,
1860 pFrame->Handler == (PEXCEPTION_HANDLER)__seh_handler ?
1861 " (SEH)" : ""));
1862 if (pFrame == pPrevFrame)
1863 {
1864 dprintf(("Chain corrupted! Record at %08X pointing to itself!",
1865 pFrame));
1866 break;
1867 }
1868 pFrame = pPrevFrame;
1869 }
1870 dprintf(("END of Win32 exception chain."));
1871}
1872#endif
1873
1874/*****************************************************************************
1875 * Name : void OS2UnsetExceptionHandler
1876 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1877 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1878 * Variables :
1879 * Result :
1880 * Remark :
1881 * Status :
1882 *
1883 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1884 *****************************************************************************/
1885void OS2UnsetExceptionHandler(void *exceptframe)
1886{
1887 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1888
1889 DosUnsetExceptionHandler(pExceptRec);
1890 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1891#ifdef DEBUG_ENABLELOG_LEVEL2
1892 PrintExceptionChain();
1893#endif
1894}
1895//*****************************************************************************
1896//*****************************************************************************
1897int _System CheckCurFS()
1898{
1899 USHORT sel = RestoreOS2FS();
1900 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1901
1902 if(sel == 0x150b) {
1903 SetFS(sel);
1904 return FALSE;
1905 }
1906 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1907 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1908 SetFS(sel);
1909 return FALSE;
1910 }
1911 SetFS(sel);
1912 return TRUE;
1913}
1914//*****************************************************************************
1915//*****************************************************************************
1916
Note: See TracBrowser for help on using the repository browser.