Ignore:
Timestamp:
Oct 5, 2000, 8:36:49 PM (25 years ago)
Author:
sandervl
Message:

MN: exception fixes

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kernel32/exceptions.cpp

    r4264 r4433  
    1 /* $Id: exceptions.cpp,v 1.45 2000-09-15 13:24:29 sandervl Exp $ */
     1/* $Id: exceptions.cpp,v 1.46 2000-10-05 18:36:49 sandervl Exp $ */
    22
    33/* WARNING: Compiling this module with ICC with optimizations turned on   */
     
    7474#include "dbglocal.h"
    7575
     76/* Exception record for handling exceptions happening inside exception handlers */
     77typedef struct
     78{
     79    WINEXCEPTION_FRAME frame;
     80    WINEXCEPTION_FRAME *prevFrame;
     81} EXC_NESTED_FRAME;
     82
    7683//Global Process Unhandled exception filter
    7784static LPTOP_LEVEL_EXCEPTION_FILTER CurrentUnhExceptionFlt = NULL;
     
    118125
    119126  return(oldmode);
     127}
     128
     129static inline WINEXCEPTION_FRAME * EXC_push_frame( WINEXCEPTION_FRAME *frame )
     130{
     131    // TODO: rewrite in assembly
     132    TEB *teb = GetThreadTEB();
     133    frame->Prev = (PWINEXCEPTION_FRAME)teb->except;
     134    teb->except = frame;
     135    return frame->Prev;
     136}
     137
     138static inline WINEXCEPTION_FRAME * EXC_pop_frame( WINEXCEPTION_FRAME *frame )
     139{
     140    // TODO: rewrite in assembly
     141    TEB *teb = GetThreadTEB();
     142    teb->except = frame->Prev;
     143    return frame->Prev;
    120144}
    121145
     
    215239}
    216240
     241/*******************************************************************
     242 *         EXC_RaiseHandler
     243 *
     244 * Handler for exceptions happening inside a handler.
     245 */
     246static DWORD WIN32API EXC_RaiseHandler( WINEXCEPTION_RECORD *rec, WINEXCEPTION_FRAME *frame,
     247//                             WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher )
     248                               WINCONTEXT *context, LPVOID dispatcher )
     249{
     250    if (rec->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
     251        return ExceptionContinueSearch;
     252    /* We shouldn't get here so we store faulty frame in dispatcher */
     253    *(PWINEXCEPTION_FRAME*)dispatcher = ((EXC_NESTED_FRAME*)frame)->prevFrame;
     254    return ExceptionNestedException;
     255}
     256
     257/*******************************************************************
     258 *         EXC_CallHandler
     259 *
     260 * Call an exception handler, setting up an exception frame to catch exceptions
     261 * happening during the handler execution.
     262 * WARNING:
     263 * Please do not change the first 4 parameters order in any way - some exceptions handlers
     264 * rely on Base Pointer (EBP) to have a fixed position related to the exception frame
     265 */
     266static DWORD EXC_CallHandler( WINEXCEPTION_RECORD *record, WINEXCEPTION_FRAME *frame,
     267                              WINCONTEXT *context, WINEXCEPTION_FRAME **dispatcher,
     268                              PEXCEPTION_HANDLER handler, PEXCEPTION_HANDLER nested_handler)
     269{
     270    EXC_NESTED_FRAME newframe;
     271    DWORD ret;
     272
     273    newframe.frame.Handler = nested_handler;
     274    newframe.prevFrame     = frame;
     275    EXC_push_frame( &newframe.frame );
     276    dprintf(("KERNEL32: Calling handler at %p code=%lx flags=%lx\n",
     277           handler, record->ExceptionCode, record->ExceptionFlags));
     278    ret = handler( record, frame, context, dispatcher );
     279    dprintf(("KERNEL32: Handler returned %lx\n", ret));
     280    EXC_pop_frame( &newframe.frame );
     281    return ret;
     282}
    217283
    218284//******************************************************************************
     
    220286DWORD RtlDispatchException(WINEXCEPTION_RECORD *pRecord, WINCONTEXT *pContext)
    221287{
    222   PWINEXCEPTION_FRAME   pframe, dispatch, nested_frame;
     288  PWINEXCEPTION_FRAME   pFrame, dispatch, nested_frame;
    223289  int                   rc;
    224290
     
    228294  nested_frame = NULL;
    229295  TEB *winteb = GetThreadTEB();
    230   pframe      = (PWINEXCEPTION_FRAME)winteb->except;
     296  pFrame      = (PWINEXCEPTION_FRAME)winteb->except;
    231297
    232298  dprintf(("KERNEL32: RtlDispatchException entered"));
    233299
    234   PrintWin32ExceptionChain(pframe);
     300  PrintWin32ExceptionChain(pFrame);
    235301
    236302  // walk the exception chain
    237   while( (pframe != NULL) && (pframe != ((void *)0xFFFFFFFF)) )
     303  while( (pFrame != NULL) && (pFrame != ((void *)0xFFFFFFFF)) )
    238304  {
    239         dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", pframe, pframe->Prev));
    240         if (pframe == pframe->Prev) {
     305        dprintf(("KERNEL32: RtlDispatchException - pframe=%08X, pframe->Prev=%08X", pFrame, pFrame->Prev));
     306        if (pFrame == pFrame->Prev) {
    241307            dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
    242308            return 0;
     
    246312
    247313        /* Check frame address */
    248         if (((void*)pframe < winteb->stack_low) ||
    249             ((void*)(pframe+1) > winteb->stack_top) ||
    250             (int)pframe & 3)
     314        if (((void*)pFrame < winteb->stack_low) ||
     315            ((void*)(pFrame+1) > winteb->stack_top) ||
     316            (int)pFrame & 3)
    251317        {
    252318            dprintf(("Invalid stack! low=%08X, top=%08X, pframe = %08X",
    253                     winteb->stack_low, winteb->stack_top, pframe));
     319                    winteb->stack_low, winteb->stack_top, pFrame));
    254320
    255321            pRecord->ExceptionFlags |= EH_STACK_INVALID;
     
    257323        }
    258324
    259         dprintf(("KERNEL32: RtlDispatchException - calling exception handler %08X", pframe->Handler));
    260 
    261         rc = pframe->Handler(pRecord,
    262                              pframe,
    263                              pContext,
    264                              dispatch);
    265 
    266         dprintf(("KERNEL32: RtlDispatchException - exception handler returned %#x", rc));
    267         PrintWin32ExceptionChain(pframe);
    268 
    269         if (pframe == nested_frame)
     325
     326        /* call handler */
     327        rc = EXC_CallHandler(pRecord, pFrame, pContext, &dispatch, pFrame->Handler, EXC_RaiseHandler );
     328
     329        PrintWin32ExceptionChain(pFrame);
     330
     331        if (pFrame == nested_frame)
    270332        {
    271333            /* no longer nested */
     
    293355        }
    294356
    295         dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", pframe, pframe->Prev));
    296         if (pframe == pframe->Prev) {
     357        dprintf(("KERNEL32: RtlDispatchException - going from frame %08X to previous frame %08X", pFrame, pFrame->Prev));
     358        if (pFrame == pFrame->Prev) {
    297359            dprintf(("KERNEL32: RtlDispatchException - Invalid exception frame!!"));
    298360            break;
    299361        }
    300         pframe = pframe->Prev;
     362        pFrame = pFrame->Prev;
    301363  }
    302364  dprintf(("KERNEL32: RtlDispatchException returns %#x", rc));
    303   PrintWin32ExceptionChain(pframe);
     365  PrintWin32ExceptionChain(pFrame);
    304366  return rc;
    305367}
     
    375437  while ((frame != (PWINEXCEPTION_FRAME)0xffffffff) && (frame != pEndFrame))
    376438  {
    377         /* Check frame address */
    378         if (pEndFrame && (frame > pEndFrame))
    379         {
    380             newrec.ExceptionCode    = STATUS_INVALID_UNWIND_TARGET;
    381             newrec.ExceptionFlags   = EH_NONCONTINUABLE;
    382             newrec.ExceptionRecord  = pRecord;
    383             newrec.NumberParameters = 0;
    384             dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
    385             DosExit(EXIT_THREAD, 0);
    386         }
    387         if (((void*)frame < winteb->stack_low) ||
    388             ((void*)(frame+1) > winteb->stack_top) ||
    389             (int)frame & 3)
    390         {
    391             newrec.ExceptionCode    = STATUS_BAD_STACK;
    392             newrec.ExceptionFlags   = EH_NONCONTINUABLE;
    393             newrec.ExceptionRecord  = pRecord;
    394             newrec.NumberParameters = 0;
    395             dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
    396             DosExit(EXIT_THREAD, 0);
    397         }
    398 
    399         /* Call handler */
    400         dprintf(("KERNEL32: RtlUnwind - calling exception handler %08X", frame->Handler));
    401         rc = frame->Handler(pRecord, frame, &context, &dispatch);
    402         dprintf(("KERNEL32: RtlUnwind - handler returned %#x", rc));
    403         switch (rc)
    404         {
    405         case ExceptionContinueSearch:
    406             break;
    407         case ExceptionCollidedUnwind:
    408             frame = dispatch;
    409             break;
    410         default:
    411             newrec.ExceptionCode    = STATUS_INVALID_DISPOSITION;
    412             newrec.ExceptionFlags   = EH_NONCONTINUABLE;
    413             newrec.ExceptionRecord  = pRecord;
    414             newrec.NumberParameters = 0;
    415             dprintf(("KERNEL32: RtlUnwind terminating thread.\n"));
    416             DosExit(EXIT_THREAD, 0);
    417             break;
    418         }
    419         dprintf(("KERNEL32: RtlUnwind (before)- frame=%08X, frame->Prev=%08X", frame, frame->Prev));
    420         SetExceptionChain((DWORD)frame->Prev);
    421         frame = frame->Prev;
    422         dprintf(("KERNEL32: RtlUnwind (after) - frame=%08X, frame->Prev=%08X", frame, frame->Prev));
    423   }
    424 
    425 
    426   /* Note: I _think_ that on Win32, RtlUnwind unwinds exception handlers up  */
    427   /*  and _including_ the handler in pEndFrame argument. My reasons are:     */
    428   /*   - MSVCRT sometimes calls RtlUnwind with the address of the very first */
    429   /*     exception handler - could be just inefficient code                  */
    430   /*   - after a call to RtlUnwind, MSVCRT in some cases tries to restore    */
    431   /*     the original exception handler. If RtlUnwind didn't remove it,      */
    432   /*     the exception chain gets looped, spelling very bad mojo!            */
    433   if (frame == pEndFrame)
    434   {
    435         /* Just repeat what we did in the while loop above */
    436439        /* Check frame address */
    437440        if (pEndFrame && (frame > pEndFrame))
     
    11741177        //    recurse infinitely until we run out of stack space!!
    11751178        if (pERepRec->fHandlerFlags & EH_NESTED_CALL)
    1176                 return XCPT_CONTINUE_SEARCH;
     1179                return XCPT_CONTINUE_SEARCH;
    11771180
    11781181#ifdef DEBUG
Note: See TracChangeset for help on using the changeset viewer.