⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exdsptch.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++


Module Name:

    exdsptch.c

Abstract:

    This module implements the dispatching of exception and the unwinding of
    procedure call frames.

--*/

#include "kernel.h"
#include "excpt.h"


// Obtain current stack limits
//  if we're on original stack, or if there is a secure stack (pth->tlsSecure != pth->tlsNonSecure)
//  and we're on the secure stack (pth->tlsPtr == pth->tlsSecure), then *LL == KSTKBASE(pth), 
//  *HL = pth->tlsPtr. Otherwise we're on FIBER stack.
//
static void GetStackLimitsFromTLS (PTHREAD pth, LPDWORD tlsPtr, LPDWORD pLL, LPDWORD pHL)
{
    if (((*pLL = tlsPtr[PRETLS_STACKBASE]) == pth->dwOrigBase)         // on original stack?
        || ((pth->tlsNonSecure != pth->tlsSecure) && (tlsPtr == pth->tlsSecure))) { // on secure stack?
        *pHL = (DWORD) pth->tlsPtr;
    } else {
        *pHL = tlsPtr[PRETLS_PROCSTKSIZE] + *pLL        // fibers have fix size stack
                - cbMDStkAlign;                         // back off a bit or SEH would go across the boundary
    }
}


void NKGetStackLimits (PTHREAD pth, LPDWORD pLL, LPDWORD pHL)
{
    GetStackLimitsFromTLS (pth, pth->tlsPtr, pLL, pHL);
}

void SetupCSTK (PCALLSTACK pcstk)
{
    pcstk->dwPrcInfo = CST_CALLBACK | CST_MODE_TO_USER;
    pcstk->akyLast 
        = pcstk->dwPrevSP
        = pcstk->extra = 0;
    pcstk->retAddr = 0; // RA to be fill by assembly
    pcstk->pcstkNext = pCurThread->pcstkTop;
    pcstk->pprcLast = pCurProc;
}



//
// Define local macros.
//
// Raise noncontinuable exception with associated exception record.
//

#define RAISE_EXCEPTION(Status, ExceptionRecordt) DEBUGCHK(0)

extern CRITICAL_SECTION ModListcs;


#ifdef x86

#define EXCEPTION_CHAIN_END ((PEXCEPTION_REGISTRATION_RECORD)-1)

//
// Define private function prototypes.
//

EXCEPTION_DISPOSITION RtlpExecuteHandlerForException(
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN PVOID EstablisherFrame,
    IN OUT PCONTEXT ContextRecord,
    IN OUT PDISPATCHER_CONTEXT DispatcherContext,
    IN PEXCEPTION_ROUTINE ExceptionRoutine,
    IN OUT PCALLSTACK pcstk,
    IN ULONG ExceptionMode);

EXCEPTION_DISPOSITION RtlpExecuteHandlerForUnwind(
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN PVOID EstablisherFrame,
    IN OUT PCONTEXT ContextRecord,
    IN OUT PDISPATCHER_CONTEXT DispatcherContext,
    IN PEXCEPTION_ROUTINE ExceptionRoutine,
    IN OUT PCALLSTACK pcstk,
    IN ULONG ExceptionMode);

BOOLEAN NKUnwind(
    IN PTHREAD pth,
    IN PCALLSTACK TargetCStk OPTIONAL,
    IN PEXCEPTION_REGISTRATION_RECORD TargetFrame OPTIONAL,
    IN ULONG TargetIp OPTIONAL,
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN ULONG ReturnValue,
    IN PCONTEXT ContextRecord);

void UpdateASID(IN PTHREAD pth, IN PPROCESS pProc, IN ACCESSKEY aky);

extern EXCEPTION_ROUTINE KPSLExceptionRoutine;



#pragma warning(disable:4733)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void __inline 
StoreRegistrationPointer(
    void *RegistrationPointer
    )
{
    __asm {
        mov eax, [RegistrationPointer]
        mov dword ptr fs:[0], eax
    }
}
#pragma warning(default:4733)

#pragma warning(disable:4035)



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PVOID __inline 
GetRegistrationHead(void)
{
    __asm mov eax, dword ptr fs:[0];
}
        
#pragma warning(default:4035)





//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOLEAN
NKDispatchException(
    IN PTHREAD pth,
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN PCONTEXT ContextRecord
    )
{
    EXCEPTION_DISPOSITION Disposition;
    PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
    PEXCEPTION_REGISTRATION_RECORD NestedRegistration;
    DISPATCHER_CONTEXT DispatcherContext;
    UINT HighAddress;
    UINT HighLimit;
    UINT LowLimit;
    PCALLSTACK pcstk;
    PCALLSTACK TargetCStk;
    PPROCESS pProc;
    PPROCESS pprcSave;
    ACCESSKEY akySave;
    EXCEPTION_REGISTRATION_RECORD TempRegistration;
    CONTEXT ContextRecord1;
    LPDWORD tlsSave;

    // Get current stack limits
    NKGetStackLimits(pth, &LowLimit, &HighLimit);

    DEBUGMSG(ZONE_SEH, (TEXT("X86 DispatchException(%x %x) pc %x code %x address %x\r\n"),
        ExceptionRecord, ContextRecord, ContextRecord->Eip,
        ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress));
    pcstk = pth->pcstkTop;
    akySave = pth->aky;
    pprcSave = pCurProc;
    tlsSave = pth->tlsPtr;

    memcpy(&ContextRecord1, ContextRecord, sizeof(CONTEXT));

    /*
       Start with the frame specified by the context record and search
       backwards through the call frame hierarchy attempting to find an
       exception handler that will handler the exception.
     */
    RegistrationPointer = GetRegistrationHead();

    if (!RegistrationPointer || (RegistrationPointer == EXCEPTION_CHAIN_END)) {
        // in case there is no exception handler, just return unhandled
        return FALSE;
    }
    NestedRegistration = 0;
    TargetCStk = 0;
    do {
        // Check for PSL call boundary.
        DEBUGMSG(ZONE_SEH, (TEXT("NKDispatchException: Proc=%8.8lx RP=%8.8lx\r\n"),
                pCurProc, RegistrationPointer));
        while (RegistrationPointer == (PEXCEPTION_REGISTRATION_RECORD)-2) {
            PEXCEPTION_ROUTINE pEH = KPSLExceptionRoutine;

            if (!pcstk) {
                RETAILMSG(1, (TEXT("NKDispatchException: no CALLSTACK with RP=%d\r\n"),
                        RegistrationPointer));
                KPlpvTls = pth->tlsPtr = tlsSave;
                UpdateASID(pth, pprcSave, akySave);
                return FALSE;
            }

            // in a PSL call.
            pProc = pcstk->pprcLast;
            if (!TargetCStk 
                && pcstk->akyLast 
                && ((pcstk->dwPrcInfo & CST_IN_KERNEL) || (pCurProc == pProc) || (pEH = pCurProc->pfnEH) != 0)) {
                DEBUGMSG(ZONE_SEH, (TEXT("NKDispatchException: Found PSL Global Handler\r\n")));
                TargetCStk = pcstk;
                RegistrationPointer = &TempRegistration;
                RegistrationPointer->Next = (PEXCEPTION_REGISTRATION_RECORD)-2;
                RegistrationPointer->Handler = pEH;
                break;
            } else {
                TargetCStk = 0;
                RegistrationPointer = (PEXCEPTION_REGISTRATION_RECORD)pcstk->extra;
                DEBUGCHK (pcstk->dwPrcInfo & CST_CALLBACK);
                
                DEBUGMSG(ZONE_SEH, (TEXT("NKDispatchException: Walking across CallBack\r\n")));
                if (pcstk->dwPrevSP) {
                    ContextRecord1.Esp = pcstk->dwPrevSP;
                    KPlpvTls = pth->tlsPtr = pth->tlsSecure;
                    NKGetStackLimits(pth, &LowLimit, &HighLimit);
                }
                
                SetContextMode(&ContextRecord1, (pcstk->dwPrcInfo & CST_MODE_FROM_USER)? USER_MODE : KERNEL_MODE);
                UpdateASID(pth, pProc, pcstk->akyLast ? pcstk->akyLast : pth->aky);
                pcstk = pcstk->pcstkNext;
                DEBUGMSG(ZONE_SEH, (TEXT("NKDispatchException: PSL return Proc=%8.8lx RP=%8.8lx pcstk=%8.8lx\r\n"),
                        pProc, RegistrationPointer, pcstk));
            }
        }

        DEBUGCHK (RegistrationPointer != (PEXCEPTION_REGISTRATION_RECORD)-2);
        /*
           If the call frame is not within the specified stack limits or the
           call frame is unaligned, then set the stack invalid flag in the
           exception record and return FALSE. Else check to determine if the
           frame has an exception handler.
         */
        HighAddress = (UINT)RegistrationPointer + sizeof(EXCEPTION_REGISTRATION_RECORD);
        if ((UINT)RegistrationPointer < LowLimit
                || HighAddress > HighLimit
                || ((UINT)RegistrationPointer & 0x3) != 0) { /* Not aligned */
            ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
            break;
        } else {
            /* The handler must be executed by calling another routine
             that is written in assembler. This is required because
             up level addressing of the handler information is required
             when a nested exception is encountered.
             */
            PCALLSTACK pcstkForHandler = 0;
            DWORD ctxMode = GetContextMode(&ContextRecord1);
            
            DispatcherContext.ControlPc = 0;
            DispatcherContext.RegistrationPointer = RegistrationPointer;
            DEBUGMSG(ZONE_SEH, (TEXT("Calling exception handler @%8.8lx RP=%8.8lx\r\n"),
                    RegistrationPointer->Handler, RegistrationPointer));

            if (KERNEL_MODE != ctxMode) {
                if (!(pcstkForHandler = (PCALLSTACK) AllocMem (HEAP_CALLSTACK))) {
                    // we're completely out of memory, can't do much about it
                    ExceptionRecord->ExceptionFlags |= EXCEPTION_STACK_INVALID;
                    break;
                }
                SetupCSTK (pcstkForHandler);
            }

            Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
                    RegistrationPointer, ContextRecord, &DispatcherContext,
                    RegistrationPointer->Handler, pcstkForHandler, ctxMode);

            // don't need to free pcstkForHandler since it'll be freed at callback return
            
            DEBUGMSG(ZONE_SEH, (TEXT("exception dispostion = %d\r\n"), Disposition));

            /* If the current scan is within a nested context and the frame
               just examined is the end of the context region, then clear
               the nested context frame and the nested exception in the
               exception flags.
             */
            if (NestedRegistration == RegistrationPointer) {
                ExceptionRecord->ExceptionFlags &= (~EXCEPTION_NESTED_CALL);
                NestedRegistration = 0;
            }

            // Case on the handler disposition.
            switch (Disposition) {
                    // The disposition is to execute a frame based handler. The
                    // target handler address is in DispatcherContext.ControlPc.
                    // Reset to the original context and switch to unwind mode.
                case ExceptionExecuteHandler:
                    DEBUGMSG(ZONE_SEH && DispatcherContext.ControlPc,
                            (TEXT("Unwinding to %8.8lx RegistrationPointer=%8.8lx\r\n"),
                            DispatcherContext.ControlPc, RegistrationPointer));
                    DEBUGMSG(ZONE_SEH && !DispatcherContext.ControlPc,
                            (TEXT("Unwinding to %8.8lx RegistrationPointer=%8.8lx Ebx=%8.8lx Esi=%d\r\n"),
                            ContextRecord->Eip, RegistrationPointer,
                            ContextRecord->Ebx, ContextRecord->Esi));

                    if (tlsSave != pth->tlsPtr) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -