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

Last change on this file since 8835 was 8835, checked in by sandervl, 23 years ago

dump exception to exception.log in system32 dir

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