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

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

debug updates + added OSLibDosGetTickCount

File size: 48.2 KB
Line 
1/* $Id: exceptions.cpp,v 1.60 2002-06-26 07:14:18 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 dprintf(("<%s> (#%u), obj #%u:%08x\n",
1039 szModule,
1040 ulModule,
1041 ulObject,
1042 ulOffset));
1043 else
1044 dprintf(("<win32 app>\n"));
1045
1046
1047 rc = DosGetInfoBlocks (&pTIB, /* query kernel information blocks */
1048 &pPIB);
1049 if (rc == NO_ERROR)
1050 {
1051 dprintf((" Thread: Ordinal TID: %u, TID: %u, Priority: %04xh\n",
1052 pTIB->tib_ordinal,
1053 pTIB->tib_ptib2->tib2_ultid,
1054 pTIB->tib_ptib2->tib2_ulpri));
1055
1056 dprintf((" Process: PID: %u, Parent: %u, Status: %u\n",
1057 pPIB->pib_ulpid,
1058 pPIB->pib_ulppid,
1059 pPIB->pib_flstatus));
1060 }
1061
1062 if (pCtxRec->ContextFlags & CONTEXT_CONTROL) /* check flags */
1063 dprintf((" SS:ESP=%04x:%08x EFLAGS=%08x\n",
1064 pCtxRec->ctx_SegSs,
1065 pCtxRec->ctx_RegEsp,
1066 pCtxRec->ctx_EFlags));
1067 dprintf((" CS:EIP=%04x:%08x EBP =%08x\n",
1068 pCtxRec->ctx_SegCs,
1069 pCtxRec->ctx_RegEip,
1070 pCtxRec->ctx_RegEbp));
1071
1072 if (pCtxRec->ContextFlags & CONTEXT_INTEGER) /* check flags */
1073 dprintf((" EAX=%08x EBX=%08x ESI=%08x\n",
1074 pCtxRec->ctx_RegEax,
1075 pCtxRec->ctx_RegEbx,
1076 pCtxRec->ctx_RegEsi));
1077 dprintf((" ECX=%08x EDX=%08x EDI=%08x\n",
1078 pCtxRec->ctx_RegEcx,
1079 pCtxRec->ctx_RegEdx,
1080 pCtxRec->ctx_RegEdi));
1081
1082 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS) /* check flags */
1083 dprintf((" DS=%04x ES=%08x",
1084 pCtxRec->ctx_SegDs,
1085 pCtxRec->ctx_SegEs));
1086 dprintf((" FS=%04x GS=%04x\n",
1087 pCtxRec->ctx_SegFs,
1088 pCtxRec->ctx_SegGs));
1089
1090 if (pCtxRec->ContextFlags & CONTEXT_FLOATING_POINT) /* check flags */
1091 {
1092 ULONG ulCounter; /* temporary local counter for fp stack */
1093
1094 dprintf((" Env[0]=%08x Env[1]=%08x Env[2]=%08x Env[3]=%08x\n",
1095 pCtxRec->ctx_env[0],
1096 pCtxRec->ctx_env[1],
1097 pCtxRec->ctx_env[2],
1098 pCtxRec->ctx_env[3]));
1099
1100 dprintf((" Env[4]=%08x Env[5]=%08x Env[6]=%08x\n",
1101 pCtxRec->ctx_env[4],
1102 pCtxRec->ctx_env[5],
1103 pCtxRec->ctx_env[6]));
1104
1105 for (ulCounter = 0;
1106 ulCounter < 8; /* see TOOLKIT\INCLUDE\BSEEXPT.H, _CONTEXT structure */
1107 ulCounter ++)
1108 dprintf((" FP-Stack[%u] losig=%08x hisig=%08x signexp=%04x\n",
1109 ulCounter,
1110 pCtxRec->ctx_stack[0].losig,
1111 pCtxRec->ctx_stack[0].hisig,
1112 pCtxRec->ctx_stack[0].signexp));
1113 }
1114
1115 dprintf(("---[End Of Exception Information]-----\n"));
1116}
1117
1118/*****************************************************************************
1119 * Name : ERR _System OS2ExceptionHandler
1120 * Purpose :
1121 * Parameters: ...
1122 * Variables :
1123 * Result :
1124 * Remark :
1125 * Status :
1126 *
1127 * Author : Patrick Haller [Tue, 1999/07/01 09:00]
1128 *****************************************************************************/
1129 /* from PPC DDK */
1130#ifndef XCPT_CONTINUE_STOP
1131#define XCPT_CONTINUE_STOP 0x00716668
1132#endif
1133
1134ULONG APIENTRY OS2ExceptionHandler(PEXCEPTIONREPORTRECORD pERepRec,
1135 PEXCEPTIONREGISTRATIONRECORD pERegRec,
1136 PCONTEXTRECORD pCtxRec,
1137 PVOID p)
1138{
1139 //SvL: Check if exception inside debug fprintf -> if so, clear lock so
1140 // next dprintf won't wait forever
1141 int prevlock = LogException(ENTER_EXCEPTION);
1142
1143 /* Access violation at a known location */
1144 switch(pERepRec->ExceptionNum)
1145 {
1146 case XCPT_FLOAT_DENORMAL_OPERAND:
1147 case XCPT_FLOAT_DIVIDE_BY_ZERO:
1148 case XCPT_FLOAT_INEXACT_RESULT:
1149// case XCPT_FLOAT_INVALID_OPERATION:
1150 case XCPT_FLOAT_OVERFLOW:
1151 case XCPT_FLOAT_STACK_CHECK:
1152 case XCPT_FLOAT_UNDERFLOW:
1153 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1154 dprintf(("KERNEL32: OS2ExceptionHandler: FPU exception\n"));
1155 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1156 {
1157 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == FALSE)
1158 {
1159 pCtxRec->ctx_env[0] |= 0x1F;
1160 pCtxRec->ctx_stack[0].losig = 0;
1161 pCtxRec->ctx_stack[0].hisig = 0;
1162 pCtxRec->ctx_stack[0].signexp = 0;
1163 }
1164 dprintf(("KERNEL32: OS2ExceptionHandler: fix and continue\n"));
1165 goto continueexecution;
1166 }
1167 else
1168 {
1169 dprintf(("KERNEL32: OS2ExceptionHandler: continue search\n"));
1170 goto continuesearch;
1171 }
1172
1173 case XCPT_PROCESS_TERMINATE:
1174 case XCPT_ASYNC_PROCESS_TERMINATE:
1175//// dprintfException(pERepRec, pERegRec, pCtxRec, p);
1176 SetExceptionChain((ULONG)-1);
1177 goto continuesearch;
1178
1179 case XCPT_ACCESS_VIOLATION:
1180 {
1181 Win32MemMap *map;
1182 BOOL fWriteAccess = FALSE;
1183 ULONG offset, accessflag;
1184
1185#ifdef WITH_KLIB
1186 if ( pERepRec->ExceptionInfo[0] == XCPT_READ_ACCESS
1187 || pERepRec->ExceptionInfo[0] == XCPT_WRITE_ACCESS
1188 || pERepRec->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
1189 || pERepRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS
1190 )
1191 {
1192 ENMACCESS enmAccess = enmRead;
1193 switch (pERepRec->ExceptionInfo[0])
1194 {
1195 case XCPT_WRITE_ACCESS: enmAccess = enmWrite; break;
1196 case XCPT_UNKNOWN_ACCESS: enmAccess = enmUnknown; break;
1197 }
1198
1199 if (kHeapDbgException((void*)pERepRec->ExceptionInfo[1],
1200 enmAccess,
1201 pERepRec->ExceptionAddress,
1202 pERepRec))
1203 goto continueexecution;
1204 }
1205#endif
1206
1207 if(pERepRec->ExceptionInfo[1] == 0 && pERepRec->ExceptionInfo[1] == XCPT_DATA_UNKNOWN) {
1208 goto continueFail;
1209 }
1210
1211//------------->>> WARNING: potentially dangerous workaround!!
1212 /* Some apps set ES = FS and Odin doesn't like that! */
1213 /* Note: maybe we could even check for ES != DS? But maybe */
1214 /* that might cause more harm than good... */
1215 if (pCtxRec->ContextFlags & CONTEXT_SEGMENTS)
1216 if (pCtxRec->ctx_SegEs == pCtxRec->ctx_SegFs) {
1217 /* Let's just reset ES to the DS value and hope it's okay */
1218 pCtxRec->ctx_SegEs = pCtxRec->ctx_SegDs;
1219 goto continueexecution;
1220 }
1221
1222 switch(pERepRec->ExceptionInfo[0]) {
1223 case XCPT_READ_ACCESS:
1224 accessflag = MEMMAP_ACCESS_READ;
1225 break;
1226 case XCPT_WRITE_ACCESS:
1227 accessflag = MEMMAP_ACCESS_WRITE;
1228 fWriteAccess = TRUE;
1229 break;
1230 case XCPT_EXECUTE_ACCESS:
1231 accessflag = MEMMAP_ACCESS_EXECUTE;
1232 break;
1233 default:
1234 goto continueFail;
1235 }
1236
1237 map = Win32MemMapView::findMapByView(pERepRec->ExceptionInfo[1], &offset, accessflag);
1238 if(map == NULL) {
1239 goto continueFail;
1240 }
1241 if(map->commitPage(offset, fWriteAccess) == TRUE)
1242 goto continueexecution;
1243
1244 //no break;
1245 }
1246continueFail:
1247
1248////#define DEBUGSTACK
1249#ifdef DEBUGSTACK
1250 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1251 ULONG *stackptr;
1252 APIRET rc;
1253 int i;
1254 ULONG ulOffset, ulModule, ulObject;
1255 CHAR szModule[CCHMAXPATH];
1256
1257 stackptr = (ULONG *)pCtxRec->ctx_RegEsp;
1258 dprintf(("Stack DUMP:"));
1259 for(i=0;i<16;i++) {
1260 rc = DosQueryModFromEIP(&ulModule,
1261 &ulObject,
1262 sizeof(szModule),
1263 szModule,
1264 &ulOffset,
1265 (ULONG)*stackptr);
1266
1267 if (rc == NO_ERROR)
1268 dprintf(("0x%8x: 0x%8x %s (#%u), obj #%u:%08x", stackptr, *stackptr, szModule, ulModule, ulObject, ulOffset));
1269 else dprintf(("0x%8x: 0x%8x", stackptr, *stackptr));
1270 stackptr++;
1271 }
1272 dprintf(("Stack DUMP END"));
1273 }
1274#endif
1275
1276 case XCPT_BREAKPOINT:
1277 case XCPT_ARRAY_BOUNDS_EXCEEDED:
1278 case XCPT_DATATYPE_MISALIGNMENT:
1279 case XCPT_ILLEGAL_INSTRUCTION:
1280 case XCPT_PRIVILEGED_INSTRUCTION:
1281 case XCPT_INVALID_LOCK_SEQUENCE:
1282 case XCPT_INTEGER_DIVIDE_BY_ZERO:
1283 case XCPT_INTEGER_OVERFLOW:
1284 case XCPT_SINGLE_STEP:
1285 case XCPT_UNABLE_TO_GROW_STACK:
1286 case XCPT_IN_PAGE_ERROR:
1287CrashAndBurn:
1288 //SvL: TODO: this may not always be the right thing to do
1289 //MN: If EH_NESTED_CALL is set, an exception occurred during the execution
1290 // of this exception handler. We better bail out ASAP or we'll likely
1291 // recurse infinitely until we run out of stack space!!
1292 if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
1293 goto continuesearch;
1294
1295#ifdef DEBUG
1296 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1297 if(pCtxRec->ContextFlags & CONTEXT_CONTROL) {
1298 dbgPrintStack(pERepRec, pERegRec, pCtxRec, p);
1299 }
1300#endif
1301 if(!fIsOS2Image && !fExitProcess) //Only for real win32 apps
1302 {
1303 if(OSLibDispatchException(pERepRec, pERegRec, pCtxRec, p) == TRUE)
1304 {
1305 goto continueexecution;
1306 }
1307 }
1308 else goto continuesearch; //pass on to OS/2 RTL or app exception handler
1309
1310 dprintf(("KERNEL32: OS2ExceptionHandler: Continue and kill\n"));
1311 pCtxRec->ctx_RegEip = (ULONG)KillWin32Process;
1312 pCtxRec->ctx_RegEsp = pCtxRec->ctx_RegEsp + 0x10;
1313 pCtxRec->ctx_RegEax = pERepRec->ExceptionNum;
1314 pCtxRec->ctx_RegEbx = pCtxRec->ctx_RegEip;
1315 goto continueexecution;
1316
1317 //@@@PH: growing thread stacks might need special treatment
1318 case XCPT_GUARD_PAGE_VIOLATION:
1319 //SvL: don't print anything here -> fatal hang if happens inside fprintf
1320 //dprintf(("KERNEL32: OS2ExceptionHandler: trying to grow stack (continue search)"));
1321 goto continuesearch;
1322
1323
1324 /*
1325 * In OS/2 VIO Ctrl-C and Ctrl-Break is special stuff which comes in
1326 * thru the exception handler. In Win32 CUI they are handled by a
1327 * ControlCtrlEvent procedure. So, if we receive one of those signals
1328 * we assume that this is a VIO program and let the handlers handle this.
1329 * (If they want to.)
1330 */
1331 case XCPT_SIGNAL:
1332 switch (pERepRec->ExceptionInfo[0])
1333 {
1334 case XCPT_SIGNAL_BREAK:
1335 if (InternalGenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0))
1336 goto continueexecution;
1337 goto continuesearch;
1338 case XCPT_SIGNAL_INTR:
1339 if (InternalGenerateConsoleCtrlEvent(CTRL_C_EVENT, 0))
1340 goto continueexecution;
1341 goto continuesearch;
1342
1343 case XCPT_SIGNAL_KILLPROC: /* resolve signal information */
1344 SetExceptionChain((ULONG)-1);
1345 goto continuesearch;
1346 }
1347 goto CrashAndBurn;
1348
1349 default: //non-continuable exceptions
1350 dprintfException(pERepRec, pERegRec, pCtxRec, p);
1351 goto continuesearch;
1352 }
1353continuesearch:
1354 LogException(LEAVE_EXCEPTION, prevlock);
1355 return XCPT_CONTINUE_SEARCH;
1356
1357continueexecution:
1358 LogException(LEAVE_EXCEPTION, prevlock);
1359 return XCPT_CONTINUE_EXECUTION;
1360}
1361
1362/*****************************************************************************
1363 * Name : void OS2SetExceptionHandler
1364 * Purpose : Sets the main thread exception handler in FS:[0] (original OS/2 FS selector)
1365 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1366 * Variables :
1367 * Result :
1368 * Remark :
1369 * Status :
1370 *
1371 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1372 *****************************************************************************/
1373void OS2SetExceptionHandler(void *exceptframe)
1374{
1375 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1376
1377 pExceptRec->prev_structure = (PEXCEPTIONREGISTRATIONRECORD)0;
1378 pExceptRec->ExceptionHandler = OS2ExceptionHandler;
1379
1380 /* disable trap popups */
1381// DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR);
1382
1383 DosSetExceptionHandler(pExceptRec);
1384 dprintf(("OS2SetExceptionHandler: exception chain %x", pExceptRec));
1385#ifdef DEBUG_ENABLELOG_LEVEL2
1386 PrintExceptionChain();
1387#endif
1388}
1389
1390#ifdef DEBUG
1391void PrintExceptionChain()
1392{
1393 USHORT sel = RestoreOS2FS();
1394 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1395
1396 dprintf(("Exception chain list:"));
1397 while(pExceptRec != 0 && (ULONG)pExceptRec != -1) {
1398 dprintf(("record %x", pExceptRec));
1399 pExceptRec = pExceptRec->prev_structure;
1400 }
1401 SetFS(sel);
1402}
1403
1404void PrintWin32ExceptionChain(PWINEXCEPTION_FRAME pframe)
1405{
1406 dprintf(("Win32 exception chain:"));
1407 while ((pframe != NULL) && ((ULONG)pframe != 0xFFFFFFFF)) {
1408 dprintf(("Record at %08X, Prev at %08X, handler at %08X", pframe, pframe->Prev, pframe->Handler));
1409 if (pframe == pframe->Prev) {
1410 dprintf(("Chain corrupted! Record at %08X pointing to itself!", pframe));
1411 break;
1412 }
1413 pframe = pframe->Prev;
1414 }
1415}
1416
1417#endif
1418
1419
1420/*****************************************************************************
1421 * Name : void OS2UnsetExceptionHandler
1422 * Purpose : Removes the main thread exception handler in FS:[0] (original OS/2 FS selector)
1423 * Parameters: exceptframe: pointer to exception handler frame on stack (2 ULONGs)
1424 * Variables :
1425 * Result :
1426 * Remark :
1427 * Status :
1428 *
1429 * Author : Sander van Leeuwen [Sun, 1999/08/21 12:16]
1430 *****************************************************************************/
1431void OS2UnsetExceptionHandler(void *exceptframe)
1432{
1433 PEXCEPTIONREGISTRATIONRECORD pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)exceptframe;
1434
1435 DosUnsetExceptionHandler(pExceptRec);
1436 dprintf(("OS2UnsetExceptionHandler: exception chain %x", pExceptRec));
1437#ifdef DEBUG_ENABLELOG_LEVEL2
1438 PrintExceptionChain();
1439#endif
1440}
1441
1442void SetOS2ExceptionChain(ULONG val)
1443{
1444 USHORT sel = GetFS();
1445
1446 SetExceptionChain(val);
1447 SetFS(sel);
1448}
1449
1450int _System CheckCurFS()
1451{
1452 USHORT sel = RestoreOS2FS();
1453 PEXCEPTIONREGISTRATIONRECORD pExceptRec;
1454
1455 if(sel == 0x150b) {
1456 SetFS(sel);
1457 return FALSE;
1458 }
1459 pExceptRec = (PEXCEPTIONREGISTRATIONRECORD)QueryExceptionChain();
1460 if(pExceptRec->ExceptionHandler != OS2ExceptionHandler) {
1461 SetFS(sel);
1462 return FALSE;
1463 }
1464 SetFS(sel);
1465 return TRUE;
1466}
1467
Note: See TracBrowser for help on using the repository browser.