source: branches/gcc-kmk/src/kernel32/exceptions.cpp@ 21838

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