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

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

kernel32: Prevent accessing dprintf's FILE members in release builds: it is seen to access freed data when handling process termination exceptions (dprintf functionality is completely useless in release builds).

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