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

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

minor updates

File size: 51.3 KB
Line 
1/* $Id: exceptions.cpp,v 1.64 2002-07-05 17:59:30 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 if (DosQueryModFromEIP(&hmod, &iObj, sizeof(szModName), szModName, &offObj, (ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress))
584 sprintf(message, "Unhandled exception 0x%08lx at address 0x%08lx. (DQMFEIP rc=%d)",
585 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
586 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
587 else
588 {
589 if (iObj == -1)
590 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
591 Win32ImageBase * pMod;
592 if (WinExe && WinExe->insideModule((ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress))
593 pMod = WinExe;
594 else
595 pMod = Win32DllBase::findModuleByAddr((ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress);
596 if (pMod != NULL)
597 {
598 szModName[0] = '\0';
599 strncat(szModName, pMod->getModuleName(), sizeof(szModName) - 1);
600 iObj = 0xFF;
601 offObj = (ULONG)lpexpExceptionInfo->ExceptionRecord->ExceptionAddress
602 - (ULONG)pMod->getInstanceHandle();
603 }
604 }
605 sprintf(message,
606 "Unhandled exception 0x%08lx at address 0x%08lx.\r"
607 "Mod: %s obj: 0x%2lx off:0x%08lx",
608 lpexpExceptionInfo->ExceptionRecord->ExceptionCode,
609 lpexpExceptionInfo->ExceptionRecord->ExceptionAddress,
610 szModName, iObj, offObj);
611 }
612
613 rc = WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, message, "Application Error",
614 0, MB_ABORTRETRYIGNORE | MB_ERROR);
615 switch (rc)
616 {
617 case MBID_IGNORE:
618 return WINEXCEPTION_CONTINUE_EXECUTION;
619
620 case MBID_ABORT:
621 case MBID_RETRY:
622 default:
623 return WINEXCEPTION_EXECUTE_HANDLER;
624 }
625}
626/*****************************************************************************
627 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
628 * Purpose :
629 * Parameters: ...
630 * Variables :
631 * Result :
632 * Remark :
633 * Status :
634 *
635 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
636 *****************************************************************************/
637
638LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
639{
640 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
641
642 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n",
643 lpTopLevelExceptionFilter));
644
645 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
646
647 return(old);
648}
649
650
651/*****************************************************************************
652 * Name : KillWin32Process
653 * Purpose :
654 * Parameters: ...
655 * Variables :
656 * Result :
657 * Remark :
658 * Status :
659 *
660 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
661 *****************************************************************************/
662
663
664//******************************************************************************
665VOID WIN32API ExitProcess(DWORD exitcode);
666//******************************************************************************
667void KillWin32Process(void)
668{
669 static BOOL fEntry = FALSE;
670
671 if(fEntry == FALSE) {
672 fEntry = TRUE;
673 ExitProcess(666);
674 return;
675 }
676 //Restore original OS/2 TIB selector
677 RestoreOS2FS();
678
679 SetExceptionChain((ULONG)-1);
680 DosExit(EXIT_PROCESS, 666);
681}
682//*****************************************************************************
683//*****************************************************************************
684static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec,
685 PEXCEPTIONREGISTRATIONRECORD pERegRec,
686 PCONTEXTRECORD pCtxRec,
687 PVOID p,
688 PSZ szTrapDump)
689{
690 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
691 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
692 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
693 BOOL fExcptFatal = TRUE; /* fatal exception ? */
694 BOOL fExcptPortable = TRUE; /* portability of exception */
695 PPIB pPIB; /* process information block */
696 PTIB pTIB; /* thread information block */
697 ULONG ulModule; /* module number */
698 ULONG ulObject; /* object number within the module */
699 CHAR szModule[260]; /* buffer for the module name */
700 ULONG ulOffset; /* offset within the object within the module */
701 char szLineException[128];
702 char szLineExceptionType[128];
703
704 szLineException[0] = 0; /* initialize */
705 szLineExceptionType[0] = 0; /* initialize */
706 switch(pERepRec->ExceptionNum) /* take according action */
707 {
708 /* portable, non-fatal software-generated exceptions */
709 case XCPT_GUARD_PAGE_VIOLATION:
710 strcpy(szLineException, "Guard Page Violation");
711 sprintf(szLineExceptionType, "R/W %08xh at %08xh.", pERepRec->ExceptionInfo[0], pERepRec->ExceptionInfo[1]);
712 fExcptSoftware = TRUE;
713 fExcptFatal = FALSE;
714 rc = XCPT_CONTINUE_EXECUTION;
715 break;
716
717 case XCPT_UNABLE_TO_GROW_STACK:
718 strcpy(szLineException, "Unable To Grow Stack");
719 fExcptSoftware = TRUE;
720 fExcptFatal = FALSE;
721 rc = XCPT_CONTINUE_EXECUTION;
722 break;
723
724 /* portable, fatal, hardware-generated exceptions */
725 case XCPT_ACCESS_VIOLATION:
726 strcpy(szLineException, "Access Violation");
727 switch (pERepRec->ExceptionInfo[0])
728 {
729 case XCPT_READ_ACCESS:
730 sprintf (szLineExceptionType, "Read Access at address %08xh", pERepRec->ExceptionInfo[1]);
731 break;
732
733 case XCPT_WRITE_ACCESS:
734 sprintf (szLineExceptionType, "Write Access at address %08x", pERepRec->ExceptionInfo[1]);
735 break;
736
737 case XCPT_SPACE_ACCESS:
738 sprintf (szLineExceptionType, "Space Access at selector %08x", pERepRec->ExceptionInfo[1]);
739 break;
740
741 case XCPT_LIMIT_ACCESS:
742 strcpy (szLineExceptionType, "Limit Access");
743 break;
744
745 case XCPT_UNKNOWN_ACCESS:
746 strcpy (szLineExceptionType, "Unknown Access");
747 break;
748
749 default:
750 strcpy (szLineExceptionType, "(Invalid Access Code)");
751 break;
752 }
753 break;
754
755 case XCPT_INTEGER_DIVIDE_BY_ZERO:
756 strcpy(szLineException, "Division By Zero (Integer)");
757 break;
758
759 case XCPT_FLOAT_DIVIDE_BY_ZERO:
760 strcpy(szLineException, "Division By Zero (Float)");
761 break;
762
763 case XCPT_FLOAT_INVALID_OPERATION:
764 strcpy(szLineException, "Invalid Floating Point Operation");
765 break;
766
767 case XCPT_ILLEGAL_INSTRUCTION:
768 strcpy(szLineException, "Illegal Instruction");
769 break;
770
771 case XCPT_PRIVILEGED_INSTRUCTION:
772 strcpy(szLineException, "Privileged Instruction");
773 break;
774
775 case XCPT_INTEGER_OVERFLOW:
776 strcpy(szLineException, "Integer Overflow");
777 break;
778
779 case XCPT_FLOAT_OVERFLOW:
780 strcpy(szLineException, "Floating Point Overflow");
781 break;
782
783 case XCPT_FLOAT_UNDERFLOW:
784 strcpy(szLineException, "Floating Point Underflow");
785 break;
786
787 case XCPT_FLOAT_DENORMAL_OPERAND:
788 strcpy(szLineException, "Floating Point Denormal Operand");
789 break;
790
791 case XCPT_FLOAT_INEXACT_RESULT:
792 strcpy(szLineException, "Floating Point Inexact Result");
793 break;
794
795 case XCPT_FLOAT_STACK_CHECK:
796 strcpy(szLineException, "Floating Point Stack Check");
797 break;
798
799 case XCPT_DATATYPE_MISALIGNMENT:
800 strcpy(szLineException, "Datatype Misalignment");
801 sprintf(szLineExceptionType, "R/W %08x alignment %08x at %08x.", pERepRec->ExceptionInfo[0],
802 pERepRec->ExceptionInfo[1], pERepRec->ExceptionInfo[2]);
803 break;
804
805 case XCPT_BREAKPOINT:
806 strcpy(szLineException, "Breakpoint (DEBUG)");
807 break;
808
809 case XCPT_SINGLE_STEP:
810 strcpy(szLineException, "Single Step (DEBUG)");
811 break;
812
813 /* portable, fatal, software-generated exceptions */
814 case XCPT_IN_PAGE_ERROR:
815 strcpy(szLineException, "In Page Error");
816 sprintf(szLineExceptionType, "at %08x.", pERepRec->ExceptionInfo[0]);
817 fExcptSoftware = TRUE;
818 break;
819
820 case XCPT_PROCESS_TERMINATE:
821 strcpy(szLineException, "Process Termination");
822 fExcptSoftware = TRUE;
823 break;
824
825 case XCPT_ASYNC_PROCESS_TERMINATE:
826 strcpy(szLineException, "Process Termination (async)");
827 sprintf(szLineExceptionType, "terminating thread TID=%u", pERepRec->ExceptionInfo[0]);
828 fExcptSoftware = TRUE;
829 break;
830
831 case XCPT_NONCONTINUABLE_EXCEPTION:
832 strcpy(szLineException, "Noncontinuable Exception");
833 fExcptSoftware = TRUE;
834 break;
835
836 case XCPT_INVALID_DISPOSITION:
837 strcpy(szLineException, "Invalid Disposition");
838 fExcptSoftware = TRUE;
839 break;
840
841 /* non-portable, fatal exceptions */
842 case XCPT_INVALID_LOCK_SEQUENCE:
843 strcpy(szLineException, "Invalid Lock Sequence");
844 fExcptSoftware = TRUE;
845 fExcptPortable = FALSE;
846 break;
847
848 case XCPT_ARRAY_BOUNDS_EXCEEDED:
849 strcpy(szLineException, "Array Bounds Exceeded");
850 fExcptSoftware = TRUE;
851 fExcptPortable = FALSE;
852 break;
853
854 /* unwind operation exceptions */
855 case XCPT_UNWIND:
856 strcpy(szLineException, "Unwind Exception");
857 fExcptSoftware = TRUE;
858 fExcptPortable = FALSE;
859 break;
860
861 case XCPT_BAD_STACK:
862 strcpy(szLineException, "Unwind Exception, Bad Stack");
863 fExcptSoftware = TRUE;
864 fExcptPortable = FALSE;
865 break;
866
867 case XCPT_INVALID_UNWIND_TARGET:
868 strcpy(szLineException, "Unwind Exception, Invalid Target");
869 fExcptSoftware = TRUE;
870 fExcptPortable = FALSE;
871 break;
872
873 /* fatal signal exceptions */
874 case XCPT_SIGNAL:
875 strcpy(szLineException, "Signal");
876 sprintf(szLineExceptionType, "Signal Number = %08x", pERepRec->ExceptionInfo[0]);
877 fExcptSoftware = TRUE;
878 fExcptPortable = FALSE;
879
880 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
881 {
882 case XCPT_SIGNAL_INTR:
883 strcpy(szLineException, "Signal (Interrupt)");
884 break;
885
886 case XCPT_SIGNAL_KILLPROC:
887 strcpy(szLineException, "Signal (Kill Process)");
888 break;
889
890 case XCPT_SIGNAL_BREAK:
891 strcpy(szLineException, "Signal (Break)");
892 break;
893 }
894 break;
895
896 default:
897 strcpy(szLineException, "(unknown exception code)");
898 sprintf(szLineExceptionType, "Exception Code = %08x", pERepRec->ExceptionNum);
899 break;
900 }
901
902 sprintf(szTrapDump, "---[Exception Information]------------\n %s", szLineException);
903
904 strcat(szTrapDump, " (");
905
906 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
907 strcat (szTrapDump, "software generated,");
908 else
909 strcat (szTrapDump, "hardware generated,");
910
911 if (fExcptPortable == TRUE) /* portable exception ? */
912 strcat (szTrapDump, "portable,");
913 else
914 strcat (szTrapDump, "non-portable,");
915
916 if (fExcptFatal == TRUE) /* fatal exception ? */
917 strcat (szTrapDump, "fatal");
918 else
919 strcat (szTrapDump, "non-fatal");
920
921 strcat(szTrapDump, ")\n"); /* add trailing brace */
922
923
924 rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
925 szModule, &ulOffset, (ULONG)pERepRec->ExceptionAddress);
926
927 sprintf(szLineException, " Exception Address = %08x ", pERepRec->ExceptionAddress);
928 strcat(szTrapDump, szLineException);
929
930 if(rc == NO_ERROR && ulObject != -1)
931 {
932 sprintf(szLineException, "<%.*s> (#%u) obj #%u:%08x\n", 64, szModule, ulModule, ulObject, ulOffset);
933 strcat(szTrapDump, szLineException);
934 }
935 else
936 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
937 Win32ImageBase * pMod;
938 if (WinExe && WinExe->insideModule((ULONG)pERepRec->ExceptionAddress))
939 pMod = WinExe;
940 else
941 pMod = Win32DllBase::findModuleByAddr((ULONG)pERepRec->ExceptionAddress);
942 if (pMod != NULL)
943 {
944 szModule[0] = '\0';
945 strncat(szModule, pMod->getModuleName(), sizeof(szModule) - 1);
946 ulObject = 0xFF;
947 ulOffset = (ULONG)pERepRec->ExceptionAddress - (ULONG)pMod->getInstanceHandle();
948 sprintf(szLineException, "<%.*s> (#%u) obj #%u:%08x\n", 64, szModule, ulModule, ulObject, ulOffset);
949 }
950 else sprintf(szLineException, "<unknown win32 module>\n");
951
952 strcat(szTrapDump, szLineException);
953 }
954
955 rc = DosGetInfoBlocks (&pTIB, &pPIB);
956 if (rc == NO_ERROR)
957 {
958 sprintf(szLineException, " Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
959 pTIB->tib_ordinal, pTIB->tib_ptib2->tib2_ultid, pTIB->tib_ptib2->tib2_ulpri);
960 strcat(szTrapDump, szLineException);
961
962 sprintf(szLineException, " Process: PID: %u, Parent: %u, Status: %u\n", pPIB->pib_ulpid,
963 pPIB->pib_ulppid, pPIB->pib_flstatus);
964 strcat(szTrapDump, szLineException);
965 }
966
967 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) { /* check flags */
968 sprintf(szLineException, " SS:ESP=%04x:%08x EFLAGS=%08x\n", pCtxRec->ctx_SegSs, pCtxRec->ctx_RegEsp,
969 pCtxRec->ctx_EFlags);
970 strcat(szTrapDump, szLineException);
971 sprintf(szLineException, " CS:EIP=%04x:%08x EBP =%08x\n", pCtxRec->ctx_SegCs, pCtxRec->ctx_RegEip,
972 pCtxRec->ctx_RegEbp);
973 strcat(szTrapDump, szLineException);
974 }
975
976 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) { /* check flags */
977 sprintf(szLineException, " EAX=%08x EBX=%08x ESI=%08x\n", pCtxRec->ctx_RegEax, pCtxRec->ctx_RegEbx,
978 pCtxRec->ctx_RegEsi);
979 strcat(szTrapDump, szLineException);
980 sprintf(szLineException, " ECX=%08x EDX=%08x EDI=%08x\n", pCtxRec->ctx_RegEcx, pCtxRec->ctx_RegEdx,
981 pCtxRec->ctx_RegEdi);
982 strcat(szTrapDump, szLineException);
983 }
984
985 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) { /* check flags */
986 sprintf(szLineException, " DS=%04x ES=%08x FS=%04x GS=%04x\n", pCtxRec->ctx_SegDs, pCtxRec->ctx_SegEs, pCtxRec->ctx_SegFs, pCtxRec->ctx_SegGs);
987 strcat(szTrapDump, szLineException);
988 }
989
990 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
991 {
992 ULONG ulCounter; /* temporary local counter for fp stack */
993
994 sprintf(szLineException, " Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
995 pCtxRec->ctx_env[0], pCtxRec->ctx_env[1],
996 pCtxRec->ctx_env[2], pCtxRec->ctx_env[3]);
997 strcat(szTrapDump, szLineException);
998
999 sprintf(szLineException, " Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1000 pCtxRec->ctx_env[4], pCtxRec->ctx_env[5], pCtxRec->ctx_env[6]);
1001 strcat(szTrapDump, szLineException);
1002
1003 for (ulCounter = 0; ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1004 ulCounter ++)
1005 {
1006 sprintf(szLineException, " FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1007 ulCounter, pCtxRec->ctx_stack[0].losig, pCtxRec->ctx_stack[0].hisig,
1008 pCtxRec->ctx_stack[0].signexp);
1009 strcat(szTrapDump, szLineException);
1010 }
1011 }
1012 sprintf(szLineException, "---[End Of Exception Information]-----\n");
1013 strcat(szTrapDump, szLineException);
1014}
1015/*****************************************************************************
1016 * Name : void static dprintfException
1017 * Purpose : log the exception to win32os2.log
1018 * Parameters: ...
1019 * Variables :
1020 * Result :
1021 * Remark :
1022 * Status :
1023 *
1024 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1025 *****************************************************************************/
1026
1027static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
1028 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1029 PCONTEXTRECORD pCtxRec,
1030 PVOID p)
1031{
1032 /* now dump the information to the logfile */
1033 dprintf(("\n%s", szTrapDump));
1034}
1035//*****************************************************************************
1036static char szExceptionLogFileName[CCHMAXPATH] = "";
1037static BOOL fExceptionLoggging = TRUE;
1038//*****************************************************************************
1039//Override filename of exception log (expects full path)
1040//*****************************************************************************
1041void WIN32API SetCustomExceptionLog(LPSTR lpszLogName)
1042{
1043 strcpy(szExceptionLogFileName, lpszLogName);
1044}
1045//*****************************************************************************
1046//*****************************************************************************
1047void WIN32API SetExceptionLogging(BOOL fEnable)
1048{
1049 fExceptionLoggging = fEnable;
1050}
1051//*****************************************************************************
1052//*****************************************************************************
1053static void logException()
1054{
1055 APIRET rc;
1056 HFILE hFile;
1057 ULONG ulAction, ulBytesWritten;
1058
1059 if(fExceptionLoggging == FALSE) {
1060 return;
1061 }
1062
1063 if(szExceptionLogFileName[0] == 0) {
1064 strcpy(szExceptionLogFileName, kernel32Path);
1065 strcat(szExceptionLogFileName, "\\except.log");
1066 }
1067 rc = DosOpen(szExceptionLogFileName, /* File path name */
1068 &hFile, /* File handle */
1069 &ulAction, /* Action taken */
1070 0L, /* File primary allocation */
1071 0L, /* File attribute */
1072 OPEN_ACTION_CREATE_IF_NEW |
1073 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
1074 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
1075 0L); /* No extended attribute */
1076
1077 if(rc == NO_ERROR) {
1078 DosSetFilePtr(hFile, 0, FILE_END, &ulBytesWritten);
1079 if(WinExe) {
1080 LPSTR lpszExeName;
1081
1082 lpszExeName = WinExe->getModuleName();
1083
1084 if(lpszExeName) {
1085 DosWrite(hFile, "\n", 2, &ulBytesWritten);
1086 DosWrite(hFile, lpszExeName, strlen(lpszExeName), &ulBytesWritten);
1087 DosWrite(hFile, "\n", 2, &ulBytesWritten);
1088 }
1089 }
1090 LPSTR lpszTime;
1091 time_t curtime;
1092
1093 curtime = time(NULL);
1094 lpszTime = asctime(localtime(&curtime));
1095 if(lpszTime) {
1096 DosWrite(hFile, lpszTime, strlen(lpszTime), &ulBytesWritten);
1097 }
1098 DosWrite(hFile, szTrapDump, strlen(szTrapDump), &ulBytesWritten);
1099 DosClose(hFile);
1100 }
1101}
1102
1103/*****************************************************************************
1104 * Name : ERR _System OS2ExceptionHandler
1105 * Purpose :
1106 * Parameters: ...
1107 * Variables :
1108 * Result :
1109 * Remark :
1110 * Status :
1111 *
1112 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1113 *****************************************************************************/
1114 /* from PPC DDK */
1115#ifndef XCPT_CONTINUE_STOP
1116#define XCPT_CONTINUE_STOP 0x00716668
1117#endif
1118
1119ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1120 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1121 PCONTEXTRECORD pCtxRec,
1122 PVOID p)
1123{
1124 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1125 // next dprintf won't wait forever
1126 int prevlock = LogException(ENTER_EXCEPTION);
1127
1128 //print exception name & exception type
1129 sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1130
1131 /* Access violation at a known location */
1132 switch(pERepRec->ExceptionNum)
1133 {
1134 case XCPT_FLOAT_DENORMAL_OPERAND:
1135 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1136 case XCPT_FLOAT_INEXACT_RESULT:
1137// case XCPT_FLOAT_INVALID_OPERATION:
1138 case XCPT_FLOAT_OVERFLOW:
1139 case XCPT_FLOAT_STACK_CHECK:
1140 case XCPT_FLOAT_UNDERFLOW:
1141 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1142 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1143 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1144 {
1145 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1146 {
1147 pCtxRec->ctx_env[0] |= 0x1F;
1148 pCtxRec->ctx_stack[0].losig = 0;
1149 pCtxRec->ctx_stack[0].hisig = 0;
1150 pCtxRec->ctx_stack[0].signexp = 0;
1151 }
1152 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1153 goto continueexecution;
1154 }
1155 else
1156 {
1157 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1158 goto continuesearch;
1159 }
1160
1161 case XCPT_PROCESS_TERMINATE:
1162 case XCPT_ASYNC_PROCESS_TERMINATE:
1163//// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1164 SetExceptionChain((ULONG)-1);
1165 goto continuesearch;
1166
1167 case XCPT_ACCESS_VIOLATION:
1168 {
1169 Win32MemMap *map;
1170 BOOL fWriteAccess = FALSE;
1171 ULONG offset, accessflag;
1172
1173#ifdef WITH_KLIB
1174 if ( pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS
1175 || pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS
1176 || pERepRec->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
1177 || pERepRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS
1178 )
1179 {
1180 ENMACCESS enmAccess = enmRead;
1181 switch (pERepRec->ExceptionInfo[0])
1182 {
1183 case XCPT_WRITE_ACCESS: enmAccess = enmWrite; break;
1184 case XCPT_UNKNOWN_ACCESS: enmAccess = enmUnknown; break;
1185 }
1186
1187 if (kHeapDbgException((void*)pERepRec->ExceptionInfo[1],
1188 enmAccess,
1189 pERepRec->ExceptionAddress,
1190 pERepRec))
1191 goto continueexecution;
1192 }
1193#endif
1194
1195 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1196 goto continueFail;
1197 }
1198
1199//------------->>> WARNING: potentially dangerous workaround!!
1200 /* Some apps set ES = FS and Odin doesn't like that! */
1201 /* Note: maybe we could even check for ES != DS? But maybe */
1202 /* that might cause more harm than good... */
1203 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1204 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1205 /* Let's just reset ES to the DS value and hope it's okay */
1206 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1207 goto continueexecution;
1208 }
1209
1210 switch(pERepRec->ExceptionInfo[0]) {
1211 case XCPT_READ_ACCESS:
1212 accessflag = MEMMAP_ACCESS_READ;
1213 break;
1214 case XCPT_WRITE_ACCESS:
1215 accessflag = MEMMAP_ACCESS_WRITE;
1216 fWriteAccess = TRUE;
1217 break;
1218 case XCPT_EXECUTE_ACCESS:
1219 accessflag = MEMMAP_ACCESS_EXECUTE;
1220 break;
1221 default:
1222 goto continueFail;
1223 }
1224
1225 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1226 if(map == NULL) {
1227 goto continueFail;
1228 }
1229 if(map->commitPage(offset, fWriteAccess) == TRUE)
1230 goto continueexecution;
1231
1232 //no break;
1233 }
1234continueFail:
1235
1236////#define DEBUGSTACK
1237#ifdef DEBUGSTACK
1238 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1239 ULONG *stackptr;
1240 APIRET rc;
1241 int i;
1242 ULONG ulOffset, ulModule, ulObject;
1243 CHAR szModule[CCHMAXPATH];
1244
1245 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1246 dprintf(("Stack DUMP:"));
1247 for(i=0;i<16;i++) {
1248 rc = DosQueryModFromEIP(&ulModule,
1249 &ulObject,
1250 sizeof(szModule),
1251 szModule,
1252 &ulOffset,
1253 (ULONG)*stackptr);
1254
1255 if (rc == NO_ERROR)
1256 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1257 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1258 stackptr++;
1259 }
1260 dprintf(("Stack DUMP END"));
1261 }
1262#endif
1263
1264 case XCPT_BREAKPOINT:
1265 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1266 case XCPT_DATATYPE_MISALIGNMENT:
1267 case XCPT_ILLEGAL_INSTRUCTION:
1268 case XCPT_PRIVILEGED_INSTRUCTION:
1269 case XCPT_INVALID_LOCK_SEQUENCE:
1270 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1271 case XCPT_INTEGER_OVERFLOW:
1272 case XCPT_SINGLE_STEP:
1273 case XCPT_UNABLE_TO_GROW_STACK:
1274 case XCPT_IN_PAGE_ERROR:
1275CrashAndBurn:
1276 //SvL: TODO: this may not always be the right thing to do
1277 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1278 // of this exception handler. We better bail out ASAP or we'll likely
1279 // recurse infinitely until we run out of stack space!!
1280 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1281 goto continuesearch;
1282
1283#ifdef DEBUG
1284 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1285 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1286 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1287 }
1288#endif
1289
1290 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1291 {
1292 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1293 {
1294 goto continueexecution;
1295 }
1296 }
1297 else goto continuesearch; //pass on to OS/2 RTL or app exception handler
1298
1299 //Log fatal exception here
1300 logException();
1301
1302 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1303
1304 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1305 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1306 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1307 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1308 goto continueexecution;
1309
1310 //@@@PH: growing thread stacks might need special treatment
1311 case XCPT_GUARD_PAGE_VIOLATION:
1312 //SvL: don't print anything here -> fatal hang if happens inside fprintf
1313 //dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue search)"));
1314 goto continuesearch;
1315
1316
1317 /*
1318 * In OS/2 VIO Ctrl-C and Ctrl-Break is special stuff which comes in
1319 * thru the exception handler. In Win32 CUI they are handled by a
1320 * ControlCtrlEvent procedure. So, if we receive one of those signals
1321 * we assume that this is a VIO program and let the handlers handle this.
1322 * (If they want to.)
1323 */
1324 case XCPT_SIGNAL:
1325 switch (pERepRec->ExceptionInfo[0])
1326 {
1327 case XCPT_SIGNAL_BREAK:
1328 if (InternalGenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0))
1329 goto continueexecution;
1330 goto continuesearch;
1331 case XCPT_SIGNAL_INTR:
1332 if (InternalGenerateConsoleCtrlEvent(CTRL_C_EVENT, 0))
1333 goto continueexecution;
1334 goto continuesearch;
1335
1336 case XCPT_SIGNAL_KILLPROC: /* resolve signal information */
1337 SetExceptionChain((ULONG)-1);
1338 goto continuesearch;
1339 }
1340 goto CrashAndBurn;
1341
1342 default: //non-continuable exceptions
1343 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1344 goto continuesearch;
1345 }
1346continuesearch:
1347 LogException(LEAVE_EXCEPTION, prevlock);
1348 return XCPT_CONTINUE_SEARCH;
1349
1350continueexecution:
1351 LogException(LEAVE_EXCEPTION, prevlock);
1352 return XCPT_CONTINUE_EXECUTION;
1353}
1354
1355/*****************************************************************************
1356 * Name : void OS2SetExceptionHandler
1357 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1358 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1359 * Variables :
1360 * Result :
1361 * Remark :
1362 * Status :
1363 *
1364 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1365 *****************************************************************************/
1366void OS2SetExceptionHandler(void *exceptframe)
1367{
1368 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1369
1370 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1371 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1372
1373 /* disable trap popups */
1374// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1375
1376 DosSetExceptionHandler(pExceptRec);
1377 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1378#ifdef DEBUG_ENABLELOG_LEVEL2
1379 PrintExceptionChain();
1380#endif
1381}
1382//*****************************************************************************
1383//*****************************************************************************
1384#ifdef DEBUG
1385void PrintExceptionChain()
1386{
1387 USHORT sel = RestoreOS2FS();
1388 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1389
1390 dprintf(("Exception chain list:"));
1391 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1392 dprintf(("record %x", pExceptRec));
1393 pExceptRec = pExceptRec->prev_structure;
1394 }
1395 SetFS(sel);
1396}
1397//*****************************************************************************
1398//*****************************************************************************
1399void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
1400{
1401 dprintf(("Win32 exception chain:"));
1402 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
1403 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
1404 if (pframe == pframe->Prev) {
1405 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
1406 break;
1407 }
1408 pframe = pframe->Prev;
1409 }
1410}
1411
1412#endif
1413
1414
1415/*****************************************************************************
1416 * Name : void OS2UnsetExceptionHandler
1417 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1418 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1419 * Variables :
1420 * Result :
1421 * Remark :
1422 * Status :
1423 *
1424 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1425 *****************************************************************************/
1426void OS2UnsetExceptionHandler(void *exceptframe)
1427{
1428 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1429
1430 DosUnsetExceptionHandler(pExceptRec);
1431 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1432#ifdef DEBUG_ENABLELOG_LEVEL2
1433 PrintExceptionChain();
1434#endif
1435}
1436//*****************************************************************************
1437//*****************************************************************************
1438void SetOS2ExceptionChain(ULONG val)
1439{
1440 USHORT sel = GetFS();
1441
1442 SetExceptionChain(val);
1443 SetFS(sel);
1444}
1445//*****************************************************************************
1446//*****************************************************************************
1447int _System CheckCurFS()
1448{
1449 USHORT sel = RestoreOS2FS();
1450 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1451
1452 if(sel == 0x150b) {
1453 SetFS(sel);
1454 return FALSE;
1455 }
1456 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1457 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1458 SetFS(sel);
1459 return FALSE;
1460 }
1461 SetFS(sel);
1462 return TRUE;
1463}
1464//*****************************************************************************
1465//*****************************************************************************
1466
Note: See TracBrowser for help on using the repository browser.