Figure 14: KiUserExceptionDispatcher Pseudocode

KiUserExceptionDispatcher( PEXCEPTION_RECORD pExcptRec, CONTEXT * pContext )
{
    DWORD retValue;

    // Note: If the exception is handled, RtlDispatchException() never returns
    if ( RtlDispatchException( pExceptRec, pContext ) )
	retValue = NtContinue( pContext, 0 );
    else
	retValue = NtRaiseException( pExceptRec, pContext, 0 );

    EXCEPTION_RECORD excptRec2;

    excptRec2.ExceptionCode = retValue;
    excptRec2.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
    excptRec2.ExceptionRecord = pExcptRec;
    excptRec2.NumberParameters = 0;

    RtlRaiseException( &excptRec2 );
}

int RtlDispatchException( PEXCEPTION_RECORD pExcptRec, CONTEXT * pContext )
{
    DWORD   stackUserBase;
    DWORD   stackUserTop;
    PEXCEPTION_REGISTRATION pRegistrationFrame;
    DWORD hLog;

    // Get stack boundaries from FS:[4] and FS:[8]
    RtlpGetStackLimits( &stackUserBase, &stackUserTop );

    pRegistrationFrame = RtlpGetRegistrationHead();

    while ( -1 != pRegistrationFrame )
    {
	PVOID justPastRegistrationFrame = &pRegistrationFrame + 8;
	if ( stackUserBase > justPastRegistrationFrame )
	{
	    pExcptRec->ExceptionFlags |= EH_STACK_INVALID;
	    return DISPOSITION_DISMISS; // 0
	}

	if ( stackUsertop < justPastRegistrationFrame )
	{
	    pExcptRec->ExceptionFlags |= EH_STACK_INVALID;
	    return DISPOSITION_DISMISS; // 0
	}

	if ( pRegistrationFrame & 3 )   // Make sure stack is DWORD aligned
	{
	    pExcptRec->ExceptionFlags |= EH_STACK_INVALID;
	    return DISPOSITION_DISMISS; // 0
	}

	if ( someProcessFlag )
	{
	    // Doesn't seem to do a whole heck of a lot.
	    hLog = RtlpLogExceptionHandler( pExcptRec, pContext, 0,
					    pRegistrationFrame, 0x10 );
	}

	DWORD retValue, dispatcherContext;

	retValue= RtlpExecuteHandlerForException(pExcptRec, pRegistrationFrame,
						 pContext, &dispatcherContext,
						 pRegistrationFrame->handler );

	// Doesn't seem to do a whole heck of a lot.
	if ( someProcessFlag )
	    RtlpLogLastExceptionDisposition( hLog, retValue );

	if ( 0 == pRegistrationFrame )
	{
	    pExcptRec->ExceptionFlags &= ~EH_NESTED_CALL;   // Turn off flag
	}

	EXCEPTION_RECORD excptRec2;

	DWORD yetAnotherValue = 0;

	if ( DISPOSITION_DISMISS == retValue )
	{
	    if ( pExcptRec->ExceptionFlags & EH_NONCONTINUABLE )
	    {
		excptRec2.ExceptionRecord = pExcptRec;
		excptRec2.ExceptionNumber = STATUS_NONCONTINUABLE_EXCEPTION;
		excptRec2.ExceptionFlags = EH_NONCONTINUABLE;
		excptRec2.NumberParameters = 0
		RtlRaiseException( &excptRec2 );
	    }
	    else
		return DISPOSITION_CONTINUE_SEARCH;
	}
	else if ( DISPOSITION_CONTINUE_SEARCH == retValue )
	{
	}
	else if ( DISPOSITION_NESTED_EXCEPTION == retValue )
	{
	    pExcptRec->ExceptionFlags |= EH_EXIT_UNWIND;
	    if ( dispatcherContext > yetAnotherValue )
		yetAnotherValue = dispatcherContext;
	}
	else    // DISPOSITION_COLLIDED_UNWIND
	{
	    excptRec2.ExceptionRecord = pExcptRec;
	    excptRec2.ExceptionNumber = STATUS_INVALID_DISPOSITION;
	    excptRec2.ExceptionFlags = EH_NONCONTINUABLE;
	    excptRec2.NumberParameters = 0
	    RtlRaiseException( &excptRec2 );
	}

	pRegistrationFrame = pRegistrationFrame->prev;  // Go to previous frame
    }

    return DISPOSITION_DISMISS;
}


_RtlpExecuteHandlerForException:    // Handles exception (first time through)
    MOV     EDX,XXXXXXXX
    JMP     ExecuteHandler


RtlpExecutehandlerForUnwind:	// Handles unwind (second time through)
    MOV     EDX,XXXXXXXX



int ExecuteHandler( PEXCEPTION_RECORD pExcptRec
		    PEXCEPTION_REGISTRATION pExcptReg
		    CONTEXT * pContext
		    PVOID pDispatcherContext,
		    FARPROC handler ) // Really a ptr to an _except_handler()

    // Set up an EXCEPTION_REGISTRATION, where EDX points to the
    // appropriate handler code shown below
    PUSH    EDX
    PUSH    FS:[0]
    MOV     FS:[0],ESP

    // Invoke the exception callback function
    EAX = handler( pExcptRec, pExcptReg, pContext, pDispatcherContext );

    // Remove the minimal EXCEPTION_REGISTRATION frame
    MOV     ESP,DWORD PTR FS:[00000000]
    POP     DWORD PTR FS:[00000000]

    return EAX;
}

Exception handler used for _RtlpExecuteHandlerForException:
{
    // If unwind flag set, return DISPOSITION_CONTINUE_SEARCH, else
    // assign pDispatcher context and return DISPOSITION_NESTED_EXCEPTION

    return pExcptRec->ExceptionFlags & EXCEPTION_UNWIND_CONTEXT
		? DISPOSITION_CONTINUE_SEARCH 
		: *pDispatcherContext = pRegistrationFrame->scopetable,
		  DISPOSITION_NESTED_EXCEPTION;
}

Exception handler used for _RtlpExecuteHandlerForUnwind:
{
    // If unwind flag set, return DISPOSITION_CONTINUE_SEARCH, else
    // assign pDispatcher context and return DISPOSITION_COLLIDED_UNWIND

    return pExcptRec->ExceptionFlags & EXCEPTION_UNWIND_CONTEXT
		? DISPOSITION_CONTINUE_SEARCH 
		: *pDispatcherContext = pRegistrationFrame->scopetable,
		  DISPOSITION_COLLIDED_UNWIND;
}