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

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

Print win32 module name when exception occurs

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