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

Last change on this file since 10409 was 10409, checked in by sandervl, 22 years ago

Assembly wrapper for clearing the direction flag before calling our real

File size: 55.7 KB
Line 
1/* $Id: exceptions.cpp,v 1.74 2004-01-20 13:41:10 sandervl Exp $ */
2
3/*
4 * Win32 Exception functions for OS/2
5 *
6 * Ported Wine exception handling code
7 *
8 * Copyright 1998 Sander van Leeuwen (OS/2 port)
9 *
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 *
14 * (dlls\ntdll\exception.c)
15 *
16 * Copyright 1999 Turchanov Sergey
17 * Copyright 1999 Alexandre Julliard
18 *
19 * (win32\except.c)
20 *
21 * Win32 exception functions
22 *
23 * Copyright (c) 1996 Onno Hovers, (onno@stack.urc.tue.nl)
24 *
25 * Notes:
26 * What really happens behind the scenes of those new
27 * __try{...}__except(..){....} and
28 * __try{...}__finally{...}
29 * statements is simply not documented by Microsoft. There could be different
30 * reasons for this:
31 * One reason could be that they try to hide the fact that exception
32 * handling in Win32 looks almost the same as in OS/2 2.x.
33 * Another reason could be that Microsoft does not want others to write
34 * binary compatible implementations of the Win32 API (like us).
35 *
36 * Whatever the reason, THIS SUCKS!! Ensuring portabilty or future
37 * compatability may be valid reasons to keep some things undocumented.
38 * But exception handling is so basic to Win32 that it should be
39 * documented!
40 *
41 * Fixmes:
42 * -Most functions need better parameter checking.
43 * -I do not know how to handle exceptions within an exception handler.
44 * or what is done when ExceptionNestedException is returned from an
45 * exception handler
46 * -Real exceptions are not yet implemented. only the exception functions
47 * are implemented. A real implementation needs some new code in
48 * loader/signal.c. There would also be a need for showing debugging
49 * information in UnhandledExceptionFilter.
50 *
51 */
52#define INCL_MISC
53#define INCL_BASE
54#define INCL_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/* This is very dangerous. Can hang PM.
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 case MBID_RETRY:
623 default:
624 return WINEXCEPTION_EXECUTE_HANDLER;
625 }
626*/
627 return WINEXCEPTION_EXECUTE_HANDLER;
628}
629/*****************************************************************************
630 * Name : LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter
631 * Purpose :
632 * Parameters: ...
633 * Variables :
634 * Result :
635 * Remark :
636 * Status :
637 *
638 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
639 *****************************************************************************/
640
641LPTOP_LEVEL_EXCEPTION_FILTER WIN32API SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
642{
643 LPTOP_LEVEL_EXCEPTION_FILTER old = CurrentUnhExceptionFlt;
644
645 dprintf(("KERNEL32: SetUnhandledExceptionFilter to %08X\n",
646 lpTopLevelExceptionFilter));
647
648 CurrentUnhExceptionFlt = lpTopLevelExceptionFilter;
649
650 return(old);
651}
652
653
654/*****************************************************************************
655 * Name : KillWin32Process
656 * Purpose :
657 * Parameters: ...
658 * Variables :
659 * Result :
660 * Remark :
661 * Status :
662 *
663 * Author : Sander van Leeuwen [Tue, 1999/07/01 09:00]
664 *****************************************************************************/
665
666
667//******************************************************************************
668VOID WIN32API ExitProcess(DWORD exitcode);
669//******************************************************************************
670void KillWin32Process(void)
671{
672 static BOOL fEntry = FALSE;
673
674 if(fEntry == FALSE) {
675 fEntry = TRUE;
676 ExitProcess(666);
677 return;
678 }
679 //Restore original OS/2 TIB selector
680 RestoreOS2FS();
681
682 SetExceptionChain((ULONG)-1);
683 DosExit(EXIT_PROCESS, 666);
684}
685//*****************************************************************************
686//*****************************************************************************
687void KillWin32Thread(void)
688{
689// ExitThread(666);
690 //Restore original OS/2 TIB selector
691 RestoreOS2FS();
692
693 SetExceptionChain((ULONG)-1);
694 DosExit(EXIT_THREAD, 666);
695}
696//*****************************************************************************
697//*****************************************************************************
698static void sprintfException(PEXCEPTIONREPORTRECORD pERepRec,
699 PEXCEPTIONREGISTRATIONRECORD pERegRec,
700 PCONTEXTRECORD pCtxRec,
701 PVOID p,
702 PSZ szTrapDump)
703{
704 PSZ pszExceptionName = "<unknown>"; /* points to name/type excpt */
705 APIRET rc = XCPT_CONTINUE_SEARCH; /* excpt-dep. code */
706 BOOL fExcptSoftware = FALSE; /* software/hardware gen. exceptn */
707 BOOL fExcptFatal = TRUE; /* fatal exception ? */
708 BOOL fExcptPortable = TRUE; /* portability of exception */
709 PPIB pPIB; /* process information block */
710 PTIB pTIB; /* thread information block */
711 ULONG ulModule; /* module number */
712 ULONG ulObject; /* object number within the module */
713 CHAR szModule[260]; /* buffer for the module name */
714 ULONG ulOffset; /* offset within the object within the module */
715 char szLineException[128];
716 char szLineExceptionType[128];
717
718 szLineException[0] = 0; /* initialize */
719 szLineExceptionType[0] = 0; /* initialize */
720 switch(pERepRec->ExceptionNum) /* take according action */
721 {
722 /* portable, non-fatal software-generated exceptions */
723 case XCPT_GUARD_PAGE_VIOLATION:
724 strcpy(szLineException, "Guard Page Violation");
725 sprintf(szLineExceptionType, "R/W %08xh at %08xh.", pERepRec->ExceptionInfo[0], pERepRec->ExceptionInfo[1]);
726 fExcptSoftware = TRUE;
727 fExcptFatal = FALSE;
728 rc = XCPT_CONTINUE_EXECUTION;
729 break;
730
731 case XCPT_UNABLE_TO_GROW_STACK:
732 strcpy(szLineException, "Unable To Grow Stack");
733 fExcptSoftware = TRUE;
734 fExcptFatal = FALSE;
735 rc = XCPT_CONTINUE_EXECUTION;
736 break;
737
738 /* portable, fatal, hardware-generated exceptions */
739 case XCPT_ACCESS_VIOLATION:
740 strcpy(szLineException, "Access Violation");
741 switch (pERepRec->ExceptionInfo[0])
742 {
743 case XCPT_READ_ACCESS:
744 sprintf (szLineExceptionType, "Read Access at address %08xh", pERepRec->ExceptionInfo[1]);
745 break;
746
747 case XCPT_WRITE_ACCESS:
748 sprintf (szLineExceptionType, "Write Access at address %08x", pERepRec->ExceptionInfo[1]);
749 break;
750
751 case XCPT_SPACE_ACCESS:
752 sprintf (szLineExceptionType, "Space Access at selector %08x", pERepRec->ExceptionInfo[1]);
753 break;
754
755 case XCPT_LIMIT_ACCESS:
756 strcpy (szLineExceptionType, "Limit Access");
757 break;
758
759 case XCPT_UNKNOWN_ACCESS:
760 strcpy (szLineExceptionType, "Unknown Access");
761 break;
762
763 default:
764 strcpy (szLineExceptionType, "(Invalid Access Code)");
765 break;
766 }
767 break;
768
769 case XCPT_INTEGER_DIVIDE_BY_ZERO:
770 strcpy(szLineException, "Division By Zero (Integer)");
771 break;
772
773 case XCPT_FLOAT_DIVIDE_BY_ZERO:
774 strcpy(szLineException, "Division By Zero (Float)");
775 break;
776
777 case XCPT_FLOAT_INVALID_OPERATION:
778 strcpy(szLineException, "Invalid Floating Point Operation");
779 break;
780
781 case XCPT_ILLEGAL_INSTRUCTION:
782 strcpy(szLineException, "Illegal Instruction");
783 break;
784
785 case XCPT_PRIVILEGED_INSTRUCTION:
786 strcpy(szLineException, "Privileged Instruction");
787 break;
788
789 case XCPT_INTEGER_OVERFLOW:
790 strcpy(szLineException, "Integer Overflow");
791 break;
792
793 case XCPT_FLOAT_OVERFLOW:
794 strcpy(szLineException, "Floating Point Overflow");
795 break;
796
797 case XCPT_FLOAT_UNDERFLOW:
798 strcpy(szLineException, "Floating Point Underflow");
799 break;
800
801 case XCPT_FLOAT_DENORMAL_OPERAND:
802 strcpy(szLineException, "Floating Point Denormal Operand");
803 break;
804
805 case XCPT_FLOAT_INEXACT_RESULT:
806 strcpy(szLineException, "Floating Point Inexact Result");
807 break;
808
809 case XCPT_FLOAT_STACK_CHECK:
810 strcpy(szLineException, "Floating Point Stack Check");
811 break;
812
813 case XCPT_DATATYPE_MISALIGNMENT:
814 strcpy(szLineException, "Datatype Misalignment");
815 sprintf(szLineExceptionType, "R/W %08x alignment %08x at %08x.", pERepRec->ExceptionInfo[0],
816 pERepRec->ExceptionInfo[1], pERepRec->ExceptionInfo[2]);
817 break;
818
819 case XCPT_BREAKPOINT:
820 strcpy(szLineException, "Breakpoint (DEBUG)");
821 break;
822
823 case XCPT_SINGLE_STEP:
824 strcpy(szLineException, "Single Step (DEBUG)");
825 break;
826
827 /* portable, fatal, software-generated exceptions */
828 case XCPT_IN_PAGE_ERROR:
829 strcpy(szLineException, "In Page Error");
830 sprintf(szLineExceptionType, "at %08x.", pERepRec->ExceptionInfo[0]);
831 fExcptSoftware = TRUE;
832 break;
833
834 case XCPT_PROCESS_TERMINATE:
835 strcpy(szLineException, "Process Termination");
836 fExcptSoftware = TRUE;
837 break;
838
839 case XCPT_ASYNC_PROCESS_TERMINATE:
840 strcpy(szLineException, "Process Termination (async)");
841 sprintf(szLineExceptionType, "terminating thread TID=%u", pERepRec->ExceptionInfo[0]);
842 fExcptSoftware = TRUE;
843 break;
844
845 case XCPT_NONCONTINUABLE_EXCEPTION:
846 strcpy(szLineException, "Noncontinuable Exception");
847 fExcptSoftware = TRUE;
848 break;
849
850 case XCPT_INVALID_DISPOSITION:
851 strcpy(szLineException, "Invalid Disposition");
852 fExcptSoftware = TRUE;
853 break;
854
855 /* non-portable, fatal exceptions */
856 case XCPT_INVALID_LOCK_SEQUENCE:
857 strcpy(szLineException, "Invalid Lock Sequence");
858 fExcptSoftware = TRUE;
859 fExcptPortable = FALSE;
860 break;
861
862 case XCPT_ARRAY_BOUNDS_EXCEEDED:
863 strcpy(szLineException, "Array Bounds Exceeded");
864 fExcptSoftware = TRUE;
865 fExcptPortable = FALSE;
866 break;
867
868 /* unwind operation exceptions */
869 case XCPT_UNWIND:
870 strcpy(szLineException, "Unwind Exception");
871 fExcptSoftware = TRUE;
872 fExcptPortable = FALSE;
873 break;
874
875 case XCPT_BAD_STACK:
876 strcpy(szLineException, "Unwind Exception, Bad Stack");
877 fExcptSoftware = TRUE;
878 fExcptPortable = FALSE;
879 break;
880
881 case XCPT_INVALID_UNWIND_TARGET:
882 strcpy(szLineException, "Unwind Exception, Invalid Target");
883 fExcptSoftware = TRUE;
884 fExcptPortable = FALSE;
885 break;
886
887 /* fatal signal exceptions */
888 case XCPT_SIGNAL:
889 strcpy(szLineException, "Signal");
890 sprintf(szLineExceptionType, "Signal Number = %08x", pERepRec->ExceptionInfo[0]);
891 fExcptSoftware = TRUE;
892 fExcptPortable = FALSE;
893
894 switch (pERepRec->ExceptionInfo[0]) /* resolve signal information */
895 {
896 case XCPT_SIGNAL_INTR:
897 strcpy(szLineException, "Signal (Interrupt)");
898 break;
899
900 case XCPT_SIGNAL_KILLPROC:
901 strcpy(szLineException, "Signal (Kill Process)");
902 break;
903
904 case XCPT_SIGNAL_BREAK:
905 strcpy(szLineException, "Signal (Break)");
906 break;
907 }
908 break;
909
910 default:
911 strcpy(szLineException, "(unknown exception code)");
912 sprintf(szLineExceptionType, "Exception Code = %08x", pERepRec->ExceptionNum);
913 break;
914 }
915
916 sprintf(szTrapDump, "---[Exception Information]------------\n %s (", szLineException);
917
918 if (fExcptSoftware == TRUE) /* software or hardware generated ? */
919 strcat (szTrapDump, "software generated,");
920 else
921 strcat (szTrapDump, "hardware generated,");
922
923 if (fExcptPortable == TRUE) /* portable exception ? */
924 strcat (szTrapDump, "portable,");
925 else
926 strcat (szTrapDump, "non-portable,");
927
928 if (fExcptFatal == TRUE) /* fatal exception ? */
929 strcat (szTrapDump, "fatal");
930 else
931 strcat (szTrapDump, "non-fatal");
932
933 strcat(szTrapDump, ")\n"); /* add trailing brace */
934
935 if (szLineExceptionType[0])
936 sprintf(szTrapDump + strlen(szTrapDump), " %s\n", szLineExceptionType);
937
938 rc = DosQueryModFromEIP(&ulModule, &ulObject, sizeof(szModule),
939 szModule, &ulOffset, (ULONG)pERepRec->ExceptionAddress);
940
941 sprintf(szLineException, " Exception Address = %08x ", pERepRec->ExceptionAddress);
942 strcat(szTrapDump, szLineException);
943
944 if(rc == NO_ERROR && ulObject != -1)
945 {
946 sprintf(szLineException, "<%.*s> (#%u) obj #%u:%08x\n", 64, szModule, ulModule, ulObject, ulOffset);
947 strcat(szTrapDump, szLineException);
948 }
949 else
950 { /* fault in DosAllocMem allocated memory, hence PE loader.. */
951 Win32ImageBase * pMod;
952 if (WinExe && WinExe->insideModule((ULONG)pERepRec->ExceptionAddress))
953 pMod = WinExe;
954 else
955 pMod = Win32DllBase::findModuleByAddr((ULONG)pERepRec->ExceptionAddress);
956 if (pMod != NULL)
957 {
958 szModule[0] = '\0';
959 strncat(szModule, pMod->getModuleName(), sizeof(szModule) - 1);
960 ulObject = 0xFF;
961 ulOffset = (ULONG)pERepRec->ExceptionAddress - (ULONG)pMod->getInstanceHandle();
962 sprintf(szLineException, "<%.*s> (#%u) obj #%u:%08x\n", 64, szModule, ulModule, ulObject, ulOffset);
963 }
964 else sprintf(szLineException, "<unknown win32 module>\n");
965
966 strcat(szTrapDump, szLineException);
967 }
968
969 rc = DosGetInfoBlocks (&pTIB, &pPIB);
970 if (rc == NO_ERROR)
971 {
972 sprintf(szLineException, " Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
973 pTIB->tib_ordinal, pTIB->tib_ptib2->tib2_ultid, pTIB->tib_ptib2->tib2_ulpri);
974 strcat(szTrapDump, szLineException);
975
976 sprintf(szLineException, " Process: PID: %u, Parent: %u, Status: %u\n", pPIB->pib_ulpid,
977 pPIB->pib_ulppid, pPIB->pib_flstatus);
978 strcat(szTrapDump, szLineException);
979 }
980
981 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) { /* check flags */
982 sprintf(szLineException, " SS:ESP=%04x:%08x EFLAGS=%08x\n", pCtxRec->ctx_SegSs, pCtxRec->ctx_RegEsp,
983 pCtxRec->ctx_EFlags);
984 strcat(szTrapDump, szLineException);
985 sprintf(szLineException, " CS:EIP=%04x:%08x EBP =%08x\n", pCtxRec->ctx_SegCs, pCtxRec->ctx_RegEip,
986 pCtxRec->ctx_RegEbp);
987 strcat(szTrapDump, szLineException);
988 }
989
990 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) { /* check flags */
991 sprintf(szLineException, " EAX=%08x EBX=%08x ESI=%08x\n", pCtxRec->ctx_RegEax, pCtxRec->ctx_RegEbx,
992 pCtxRec->ctx_RegEsi);
993 strcat(szTrapDump, szLineException);
994 sprintf(szLineException, " ECX=%08x EDX=%08x EDI=%08x\n", pCtxRec->ctx_RegEcx, pCtxRec->ctx_RegEdx,
995 pCtxRec->ctx_RegEdi);
996 strcat(szTrapDump, szLineException);
997 }
998
999 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) { /* check flags */
1000 sprintf(szLineException, " DS=%04x ES=%08x FS=%04x GS=%04x\n", pCtxRec->ctx_SegDs, pCtxRec->ctx_SegEs, pCtxRec->ctx_SegFs, pCtxRec->ctx_SegGs);
1001 strcat(szTrapDump, szLineException);
1002 }
1003
1004 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1005 {
1006 ULONG ulCounter; /* temporary local counter for fp stack */
1007
1008 sprintf(szLineException, " Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1009 pCtxRec->ctx_env[0], pCtxRec->ctx_env[1],
1010 pCtxRec->ctx_env[2], pCtxRec->ctx_env[3]);
1011 strcat(szTrapDump, szLineException);
1012
1013 sprintf(szLineException, " Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1014 pCtxRec->ctx_env[4], pCtxRec->ctx_env[5], pCtxRec->ctx_env[6]);
1015 strcat(szTrapDump, szLineException);
1016
1017 for (ulCounter = 0; ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1018 ulCounter ++)
1019 {
1020 sprintf(szLineException, " FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1021 ulCounter, pCtxRec->ctx_stack[0].losig, pCtxRec->ctx_stack[0].hisig,
1022 pCtxRec->ctx_stack[0].signexp);
1023 strcat(szTrapDump, szLineException);
1024 }
1025 }
1026 sprintf(szLineException, "---[End Of Exception Information]-----\n");
1027 strcat(szTrapDump, szLineException);
1028}
1029/*****************************************************************************
1030 * Name : void static dprintfException
1031 * Purpose : log the exception to win32os2.log
1032 * Parameters: ...
1033 * Variables :
1034 * Result :
1035 * Remark :
1036 * Status :
1037 *
1038 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1039 *****************************************************************************/
1040
1041static void dprintfException(PEXCEPTIONREPORTRECORD pERepRec,
1042 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1043 PCONTEXTRECORD pCtxRec,
1044 PVOID p)
1045{
1046 /* now dump the information to the logfile */
1047 dprintf(("\n%s", szTrapDump));
1048}
1049//*****************************************************************************
1050static char szExceptionLogFileName[CCHMAXPATH] = "";
1051static BOOL fExceptionLoggging = TRUE;
1052//*****************************************************************************
1053//Override filename of exception log (expects full path)
1054//*****************************************************************************
1055void WIN32API SetCustomExceptionLog(LPSTR lpszLogName)
1056{
1057 strcpy(szExceptionLogFileName, lpszLogName);
1058}
1059//*****************************************************************************
1060//*****************************************************************************
1061void WIN32API SetExceptionLogging(BOOL fEnable)
1062{
1063 fExceptionLoggging = fEnable;
1064}
1065//*****************************************************************************
1066//*****************************************************************************
1067static void logException()
1068{
1069 APIRET rc;
1070 HFILE hFile;
1071 ULONG ulAction, ulBytesWritten;
1072
1073 if(fExceptionLoggging == FALSE) {
1074 return;
1075 }
1076
1077 if(szExceptionLogFileName[0] == 0) {
1078 strcpy(szExceptionLogFileName, kernel32Path);
1079 strcat(szExceptionLogFileName, "\\except.log");
1080 }
1081 rc = DosOpen(szExceptionLogFileName, /* File path name */
1082 &hFile, /* File handle */
1083 &ulAction, /* Action taken */
1084 0L, /* File primary allocation */
1085 0L, /* File attribute */
1086 OPEN_ACTION_CREATE_IF_NEW |
1087 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
1088 OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
1089 0L); /* No extended attribute */
1090
1091 if(rc == NO_ERROR) {
1092 DosSetFilePtr(hFile, 0, FILE_END, &ulBytesWritten);
1093 if(WinExe) {
1094 LPSTR lpszExeName;
1095
1096 lpszExeName = WinExe->getModuleName();
1097
1098 if(lpszExeName) {
1099 DosWrite(hFile, "\n", 2, &ulBytesWritten);
1100 DosWrite(hFile, lpszExeName, strlen(lpszExeName), &ulBytesWritten);
1101 DosWrite(hFile, "\n", 2, &ulBytesWritten);
1102 }
1103 }
1104 LPSTR lpszTime;
1105 time_t curtime;
1106
1107 curtime = time(NULL);
1108 lpszTime = asctime(localtime(&curtime));
1109 if(lpszTime) {
1110 DosWrite(hFile, lpszTime, strlen(lpszTime), &ulBytesWritten);
1111 }
1112 DosWrite(hFile, szTrapDump, strlen(szTrapDump), &ulBytesWritten);
1113 DosClose(hFile);
1114 }
1115}
1116
1117/*****************************************************************************
1118 * Name : ERR _System OS2ExceptionHandler
1119 * Purpose :
1120 * Parameters: ...
1121 * Variables :
1122 * Result :
1123 * Remark :
1124 * Status :
1125 *
1126 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1127 *****************************************************************************/
1128 /* from PPC DDK */
1129#ifndef XCPT_CONTINUE_STOP
1130#define XCPT_CONTINUE_STOP 0x00716668
1131#endif
1132
1133// Assembly wrapper for clearing the direction flag before calling our real
1134// exception handler
1135ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1136 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1137 PCONTEXTRECORD pCtxRec,
1138 PVOID p);
1139
1140ULONG APIENTRY OS2ExceptionHandler2ndLevel(PEXCEPTIONREPORTRECORD pERepRec,
1141 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1142 PCONTEXTRECORD pCtxRec,
1143 PVOID p)
1144{
1145 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1146 // next dprintf won't wait forever
1147 int prevlock = LogException(ENTER_EXCEPTION);
1148
1149 //Print exception name & exception type
1150 //Not for a guard page exception as sprintfException uses a lot of stack
1151 //and can trigger nested guard page exceptions (crash)
1152 if(pERepRec->ExceptionNum != XCPT_GUARD_PAGE_VIOLATION) {
1153 sprintfException(pERepRec, pERegRec, pCtxRec, p, szTrapDump);
1154 }
1155
1156 /* Access violation at a known location */
1157 switch(pERepRec->ExceptionNum)
1158 {
1159 case XCPT_FLOAT_DENORMAL_OPERAND:
1160 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1161 case XCPT_FLOAT_INEXACT_RESULT:
1162// case XCPT_FLOAT_INVALID_OPERATION:
1163 case XCPT_FLOAT_OVERFLOW:
1164 case XCPT_FLOAT_STACK_CHECK:
1165 case XCPT_FLOAT_UNDERFLOW:
1166 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1167 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1168 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1169 {
1170 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1171 {
1172 pCtxRec->ctx_env[0] |= 0x1F;
1173 pCtxRec->ctx_stack[0].losig = 0;
1174 pCtxRec->ctx_stack[0].hisig = 0;
1175 pCtxRec->ctx_stack[0].signexp = 0;
1176 }
1177 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1178 goto continueexecution;
1179 }
1180 else
1181 {
1182 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1183 goto continuesearch;
1184 }
1185
1186 case XCPT_PROCESS_TERMINATE:
1187 case XCPT_ASYNC_PROCESS_TERMINATE:
1188//// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1189 SetExceptionChain((ULONG)-1);
1190 goto continuesearch;
1191
1192 case XCPT_ACCESS_VIOLATION:
1193 {
1194 Win32MemMap *map;
1195 BOOL fWriteAccess = FALSE;
1196 ULONG offset, accessflag;
1197
1198#ifdef WITH_KLIB
1199 if ( pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS
1200 || pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS
1201 || pERepRec->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
1202 || pERepRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS
1203 )
1204 {
1205 ENMACCESS enmAccess = enmRead;
1206 switch (pERepRec->ExceptionInfo[0])
1207 {
1208 case XCPT_WRITE_ACCESS: enmAccess = enmWrite; break;
1209 case XCPT_UNKNOWN_ACCESS: enmAccess = enmUnknown; break;
1210 }
1211
1212 if (kHeapDbgException((void*)pERepRec->ExceptionInfo[1],
1213 enmAccess,
1214 pERepRec->ExceptionAddress,
1215 pERepRec))
1216 goto continueexecution;
1217 }
1218#endif
1219
1220 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1221 goto continueFail;
1222 }
1223
1224//------------->>> WARNING: potentially dangerous workaround!!
1225 /* Some apps set ES = FS and Odin doesn't like that! */
1226 /* Note: maybe we could even check for ES != DS? But maybe */
1227 /* that might cause more harm than good... */
1228 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1229 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1230 /* Let's just reset ES to the DS value and hope it's okay */
1231 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1232 goto continueexecution;
1233 }
1234
1235 switch(pERepRec->ExceptionInfo[0]) {
1236 case XCPT_READ_ACCESS:
1237 accessflag = MEMMAP_ACCESS_READ;
1238 break;
1239 case XCPT_WRITE_ACCESS:
1240 accessflag = MEMMAP_ACCESS_WRITE;
1241 fWriteAccess = TRUE;
1242 break;
1243 case XCPT_EXECUTE_ACCESS:
1244 accessflag = MEMMAP_ACCESS_EXECUTE;
1245 break;
1246 default:
1247 goto continueFail;
1248 }
1249
1250 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1251 if(map == NULL) {
1252 Win32MemMapNotify *map;
1253
1254 map = Win32MemMapNotify::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1255 if(!map)
1256 goto continueFail;
1257
1258 BOOL ret = map->notify(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1259 if(ret == TRUE) goto continueexecution;
1260 goto continueFail;
1261 }
1262 BOOL ret = map->commitPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1263 map->Release();
1264 if(ret == TRUE)
1265 goto continueexecution;
1266
1267 //no break;
1268 }
1269continueFail:
1270
1271////#define DEBUGSTACK
1272#ifdef DEBUGSTACK
1273 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1274 ULONG *stackptr;
1275 APIRET rc;
1276 int i;
1277 ULONG ulOffset, ulModule, ulObject;
1278 CHAR szModule[CCHMAXPATH];
1279
1280 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1281 dprintf(("Stack DUMP:"));
1282 for(i=0;i<16;i++) {
1283 rc = DosQueryModFromEIP(&ulModule,
1284 &ulObject,
1285 sizeof(szModule),
1286 szModule,
1287 &ulOffset,
1288 (ULONG)*stackptr);
1289
1290 if (rc == NO_ERROR)
1291 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1292 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1293 stackptr++;
1294 }
1295 dprintf(("Stack DUMP END"));
1296 }
1297#endif
1298
1299 case XCPT_BREAKPOINT:
1300 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1301 case XCPT_DATATYPE_MISALIGNMENT:
1302 case XCPT_ILLEGAL_INSTRUCTION:
1303 case XCPT_PRIVILEGED_INSTRUCTION:
1304 case XCPT_INVALID_LOCK_SEQUENCE:
1305 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1306 case XCPT_INTEGER_OVERFLOW:
1307 case XCPT_SINGLE_STEP:
1308 case XCPT_UNABLE_TO_GROW_STACK:
1309 case XCPT_IN_PAGE_ERROR:
1310CrashAndBurn:
1311 //SvL: TODO: this may not always be the right thing to do
1312 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1313 // of this exception handler. We better bail out ASAP or we'll likely
1314 // recurse infinitely until we run out of stack space!!
1315 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1316 goto continuesearch;
1317
1318#ifdef DEBUG
1319 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1320 if(!fExitProcess && (pCtxRec->ContextFlags & CONTEXT_CONTROL)) {
1321 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1322 }
1323#endif
1324
1325 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1326 {
1327 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1328 {
1329 goto continueexecution;
1330 }
1331 }
1332 else {
1333 if(fExitProcess) {
1334 PPIB pPIB;
1335 PTIB pTIB;
1336 APIRET rc;
1337
1338 rc = DosGetInfoBlocks (&pTIB, &pPIB);
1339 if(rc == NO_ERROR && pTIB->tib_ptib2->tib2_ultid != 1)
1340 {
1341 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill thread"));
1342
1343 pCtxRec->ctx_RegEip = (ULONG)KillWin32Thread;
1344 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1345 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1346 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1347 goto continueexecution;
1348 }
1349 }
1350 goto continuesearch; //pass on to OS/2 RTL or app exception handler
1351 }
1352
1353 //Log fatal exception here
1354 logException();
1355
1356 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1357
1358 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1359 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1360 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1361 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1362 goto continueexecution;
1363
1364 //@@@PH: growing thread stacks might need special treatment
1365 case XCPT_GUARD_PAGE_VIOLATION:
1366 {
1367 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1368 //Don't print anything here -> fatal hang if exception occurred
1369 //inside fprintf
1370 //NOTE:!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1371
1372 Win32MemMap *map;
1373 BOOL fWriteAccess = FALSE, ret;
1374 ULONG offset, accessflag;
1375
1376 switch(pERepRec->ExceptionInfo[0]) {
1377 case XCPT_READ_ACCESS:
1378 accessflag = MEMMAP_ACCESS_READ;
1379 break;
1380 case XCPT_WRITE_ACCESS:
1381 accessflag = MEMMAP_ACCESS_WRITE;
1382 fWriteAccess = TRUE;
1383 break;
1384 default:
1385 goto continueGuardException;
1386 }
1387
1388 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1389 if(map == NULL) {
1390 goto continueGuardException;
1391 }
1392 ret = map->commitGuardPage(pERepRec->ExceptionInfo[1], offset, fWriteAccess);
1393 map->Release();
1394 if(ret == TRUE)
1395 goto continueexecution;
1396
1397continueGuardException:
1398 goto continuesearch;
1399 }
1400
1401
1402 /*
1403 * In OS/2 VIO Ctrl-C and Ctrl-Break is special stuff which comes in
1404 * thru the exception handler. In Win32 CUI they are handled by a
1405 * ControlCtrlEvent procedure. So, if we receive one of those signals
1406 * we assume that this is a VIO program and let the handlers handle this.
1407 * (If they want to.)
1408 */
1409 case XCPT_SIGNAL:
1410 switch (pERepRec->ExceptionInfo[0])
1411 {
1412 case XCPT_SIGNAL_BREAK:
1413 if (InternalGenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0))
1414 goto continueexecution;
1415 goto continuesearch;
1416 case XCPT_SIGNAL_INTR:
1417 if (InternalGenerateConsoleCtrlEvent(CTRL_C_EVENT, 0))
1418 goto continueexecution;
1419 goto continuesearch;
1420
1421 case XCPT_SIGNAL_KILLPROC: /* resolve signal information */
1422 SetExceptionChain((ULONG)-1);
1423 goto continuesearch;
1424 }
1425 goto CrashAndBurn;
1426
1427 default: //non-continuable exceptions
1428 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1429 goto continuesearch;
1430 }
1431continuesearch:
1432 LogException(LEAVE_EXCEPTION, prevlock);
1433 return XCPT_CONTINUE_SEARCH;
1434
1435continueexecution:
1436 LogException(LEAVE_EXCEPTION, prevlock);
1437 return XCPT_CONTINUE_EXECUTION;
1438}
1439
1440/*****************************************************************************
1441 * Name : void OS2SetExceptionHandler
1442 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1443 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1444 * Variables :
1445 * Result :
1446 * Remark :
1447 * Status :
1448 *
1449 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1450 *****************************************************************************/
1451void OS2SetExceptionHandler(void *exceptframe)
1452{
1453 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1454
1455 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1456 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1457
1458 /* disable trap popups */
1459// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1460
1461 DosSetExceptionHandler(pExceptRec);
1462 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1463#ifdef DEBUG_ENABLELOG_LEVEL2
1464 PrintExceptionChain();
1465#endif
1466}
1467//*****************************************************************************
1468// Set exception handler if our handler has not yet been registered
1469//*****************************************************************************
1470void WIN32API ODIN_SetExceptionHandler(void *pExceptionRegRec)
1471{
1472 BOOL fFound = FALSE;
1473 USHORT sel = RestoreOS2FS();
1474 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1475
1476 while(pExceptRec != 0 && (ULONG)pExceptRec != -1)
1477 {
1478 if(pExceptRec->ExceptionHandler == OS2ExceptionHandler)
1479 {
1480 fFound = TRUE;
1481 break;
1482 }
1483 pExceptRec = pExceptRec->prev_structure;
1484 }
1485 if(!fFound)
1486 {
1487 OS2SetExceptionHandler(pExceptionRegRec);
1488 }
1489 SetFS(sel);
1490}
1491//*****************************************************************************
1492// Remove exception handler if it was registered previously
1493//
1494//*****************************************************************************
1495void WIN32API ODIN_UnsetExceptionHandler(void *pExceptionRegRec)
1496{
1497 USHORT sel = RestoreOS2FS();
1498 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1499
1500 if(pExceptRec == (PEXCEPTIONREGISTRATIONRECORD)pExceptionRegRec) {
1501 OS2UnsetExceptionHandler(pExceptionRegRec);
1502 }
1503 SetFS(sel);
1504}
1505//*****************************************************************************
1506//*****************************************************************************
1507#ifdef DEBUG
1508void PrintExceptionChain()
1509{
1510 USHORT sel = RestoreOS2FS();
1511 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1512
1513 dprintf(("Exception chain list:"));
1514 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1515 dprintf(("record %x", pExceptRec));
1516 pExceptRec = pExceptRec->prev_structure;
1517 }
1518 SetFS(sel);
1519}
1520//*****************************************************************************
1521//*****************************************************************************
1522void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
1523{
1524 dprintf(("Win32 exception chain:"));
1525 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
1526 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
1527 if (pframe == pframe->Prev) {
1528 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
1529 break;
1530 }
1531 pframe = pframe->Prev;
1532 }
1533}
1534
1535#endif
1536
1537
1538/*****************************************************************************
1539 * Name : void OS2UnsetExceptionHandler
1540 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1541 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1542 * Variables :
1543 * Result :
1544 * Remark :
1545 * Status :
1546 *
1547 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1548 *****************************************************************************/
1549void OS2UnsetExceptionHandler(void *exceptframe)
1550{
1551 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1552
1553 DosUnsetExceptionHandler(pExceptRec);
1554 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1555#ifdef DEBUG_ENABLELOG_LEVEL2
1556 PrintExceptionChain();
1557#endif
1558}
1559//*****************************************************************************
1560//*****************************************************************************
1561void SetOS2ExceptionChain(ULONG val)
1562{
1563 USHORT sel = GetFS();
1564
1565 SetExceptionChain(val);
1566 SetFS(sel);
1567}
1568//*****************************************************************************
1569//*****************************************************************************
1570int _System CheckCurFS()
1571{
1572 USHORT sel = RestoreOS2FS();
1573 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1574
1575 if(sel == 0x150b) {
1576 SetFS(sel);
1577 return FALSE;
1578 }
1579 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1580 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1581 SetFS(sel);
1582 return FALSE;
1583 }
1584 SetFS(sel);
1585 return TRUE;
1586}
1587//*****************************************************************************
1588//*****************************************************************************
1589
Note: See TracBrowser for help on using the repository browser.