Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

284 lines
8.5 KiB

/***
*trnsctrl.cpp - Routines for doing control transfers
*
* Copyright (c) 1993-1995, Microsoft Corporation. All rights reserved.
*
*Purpose:
* Routines for doing control transfers; written using inline
* assembly in naked functions. Contains the public routine
* _CxxFrameHandler, the entry point for the frame handler
*
*Revision History:
* 05-24-93 BES Module created
* 08-07-95 RKP Support for VC++ V4.0 Non-Local Goto
*
****/
#if defined(_NTSUBSET_)
extern "C" {
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <ntstatus.h> // STATUS_UNHANDLED_EXCEPTION
#include <ntos.h>
#include <ex.h> // ExRaiseException
}
#endif
#include <windows.h>
#include <mtdll.h>
#include <ehdata.h>
#include <trnsctrl.h>
#include <eh.h>
#include <ehhooks.h>
#pragma hdrstop
#include <setjmp.h>
#include <ehassert.h>
#include "ehunwind.h"
#include "bridge.h"
/////////////////////////////////////////////////////////////////////////////
//
// _CxxFrameHandler - Real entry point to the runtime; this thunk fixes up
// the parameters, and then calls the workhorse.
//
extern "C" EXCEPTION_DISPOSITION __cdecl __InternalCxxFrameHandler(
EHExceptionRecord *pExcept, // Information for this exception
EHRegistrationNode *pRN, // Dynamic information for this frame
void *pContext, // Context info
DispatcherContext *pDC, // More dynamic info for this frame
FuncInfo *pFuncInfo, // Static information for this frame
int CatchDepth, // Unused on Alpha
EHRegistrationNode *pMarkerRN, // Unused on Alpha
BOOL recursive); // True if this is a translation exception
extern "C" _CRTIMP EXCEPTION_DISPOSITION __cdecl _CxxFrameHandler(
EHExceptionRecord *pExcept, // Information for this exception
EHRegistrationNode *pRN, // Dynamic information for this frame
void *pContext, // Context info
DispatcherContext *pDC // More dynamic info for this frame
) {
return __InternalCxxFrameHandler
( pExcept, pRN, pContext, pDC, 0, 0, NULL, FALSE );
}
/////////////////////////////////////////////////////////////////////////////
//
// Call RtlUnwind in a returning fassion (hack required)
//
extern "C" VOID _UnwindNestedFrames (
IN EHRegistrationNode *TargetFrame,
IN EHExceptionRecord *ExceptionRecord
) {
RtlUnwindActions(
(PVOID)TargetFrame,
(PEXCEPTION_RECORD)ExceptionRecord
);
}
/////////////////////////////////////////////////////////////////////////////
//
// _JumpToContinuation - unwind the stack to the specified frame and jump
// to the specified address.
//
// Does not return.
//
void _JumpToContinuation(
void *TargetIp, // The target address
EHRegistrationNode *TargetFrame // The target virtual frame ptr
) {
//
// MIPS does not call NLG_Notify in _JumpToContinuation
// so ALPHA doesn't either
//
RtlUnwind (
(void *)TargetFrame,
(void *)TargetIp,
NULL,
NULL
);
}
/////////////////////////////////////////////////////////////////////////////
//
// __CxxInternalEHGoto - unwind the stack to the specified frame AND STATE
// then jump to the specified address. Only Called from __CxxEHGoto
//
// Does not return.
//
extern "C" _CRTIMP
void __CxxInternalEHGoto(
void * target_address,
LONG target_state,
void * target_real_fp
) {
void * target_virtual_fp;
EXCEPTION_RECORD GotoException;
GotoException.ExceptionCode = STATUS_UNWIND;
GotoException.ExceptionFlags = EXCEPTION_UNWINDING;
GotoException.ExceptionRecord = NULL;
GotoException.ExceptionAddress = 0;
GotoException.NumberParameters = 1;
GotoException.ExceptionInformation[0] = target_state;
//
// NLG_Notify uses Real FP + 1 instead of Virtual FP
// This maintains the debugger invariant of Actual SP < Target FP
//
target_virtual_fp = (char *)target_real_fp + 1;
_NLG_Notify ( target_address, target_virtual_fp, 0x2 /*NLG_CATCH_LEAVE*/ );
RtlUnwindRfp( target_real_fp, target_address, &GotoException, 0 );
//
// Control should not return to this point
//
DASSERT(0);
}
/////////////////////////////////////////////////////////////////////////////
//
// CallSEHTranslator - calls the SEH translator, and handles the translation
// exception.
//
// Assumes that a valid translator exists.
//
// Method:
// The user written translator function is called through a "bridge" routine
// which is written in assembly so that it may specify a custom frame handler.
// This frame handler will capture the translated exception thrown by the
// translator (if any) and pass it back into the C++ EH run-time.
//
// If the exception is not fully handled, the handler returns control to here,
// so that this function can return to resume the normal search for a handler
// for the original exception.
//
// Returns: TRUE if translator had a translation (handled or not)
// FALSE if there was no translation
// Does not return if translation was fully handled
//
BOOL _CallSETranslator(
EHExceptionRecord *pExcept, // The exception to be translated
EHRegistrationNode *pRN, // Dynamic info of function with catch
void *pContext, // Context info (we don't care what's in it)
DispatcherContext *pDC, // More dynamic info of function with catch (ignored)
FuncInfo *pFuncInfo, // Static info of function with catch
int CatchDepth, // How deeply nested in catch blocks are we?
EHRegistrationNode *pMarkerRN // Marker for parent context
) {
//
// Call the translator; assume it will NOT give a translation
//
_EXCEPTION_POINTERS pointers = {
(PEXCEPTION_RECORD)pExcept,
(PCONTEXT)pContext };
BOOL DidTranslate = FALSE;
__CxxSETranslatorBridge(
__pSETranslator, // _se_translator_function
PER_CODE(pExcept), // DWORD
&pointers, // _EXCEPTION_POINTERS *
pDC, // DispatcherContext *
&DidTranslate); // BOOL *
//
// If control returned here the exception was either not translated or
// was re-thrown.
//
return DidTranslate;
}
/////////////////////////////////////////////////////////////////////////////
//
// TranslatorGuardHandler - frame handler for the SEH translator bridge
// function __CxxSETranslatorBridge (see bridge.s).
//
// On search:
// This frame handler will check if there is a catch at the current level
// for the translated exception. If there is no handler or the handler
// did a re-throw, control is transfered back into CallSEHTranslator.
//
// Note that this handler must reference several values in the bridge
// function's frame. Always use the offset macros defined in bridge.h to
// ensure that both this routine and the bridge function are in sync.
//
// Does not return.
//
// On unwind:
// Sets the DidUnwind flag in the bridge function's frame, and returns.
//
extern "C"
EXCEPTION_DISPOSITION __CxxTranslatorGuardHandler(
EHExceptionRecord *pExcept, // Information for this exception
EHRegistrationNode *pRN, // not sure what on Alpha
CONTEXT *pContext, // Translated Exception Context
DispatcherContext *pDC // Bridge Frame Dispatcher Context
) {
//
// Virtual Frame Pointer to the __CxxSETranslatorBridge frame
// for which this frame handler was established.
//
char * BridgeVfp = (char *)(pDC -> EstablisherFrame);
if (IS_UNWINDING(PER_FLAGS(pExcept)))
{
//
// Indicate that translation occured.
//
BOOL *pDidTranslate =
*((BOOL **)(BridgeVfp+BrTrpDidTrans_vfp));
*pDidTranslate = TRUE;
return ExceptionContinueSearch;
}
else {
//
// Check for a handler:
//
DispatcherContext *EHpDC =
*((DispatcherContext **)(BridgeVfp+BrTrEHpDC_vfp));
__InternalCxxFrameHandler
( pExcept, 0, pContext, EHpDC, 0, 0, 0, TRUE );
//
// Transfer control back to establisher (i.e. the bridge).
//
void *BrTrContinue =
*((void **)(BridgeVfp+BrTrpContinue_vfp));
//
// No debugger notification needed for unwinding back to the bridge
//
RtlUnwind( (void *)BridgeVfp, BrTrContinue, NULL, NULL );
// Unreached.
return ExceptionContinueSearch;
}
}