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

📄 objdisp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
            CurAKey = pth->aky;     // MIPS: CurAkey is used in TLB miss handler instead of pCurThread->aky
            pfn = GetPSLPfnAndValidateArgs (pci, iMethod, args);
        }
        
        /* Save previous process */
        pcstk->pprcLast = pth->pProc;
        /* setup thread structure for method call */
        pth->pProc = pprc;
        SetCPUASID(pth);        /* switch to server's address space */
        UpdateCallerInfo(pth, TRUE);
        DEBUGMSG(ZONE_OBJDISP, (TEXT("PSLDispatch: pci %8.8lx, fnptr %8.8lx\r\n"),
                pci, pci->ppfnMethods[iMethod]));
#ifdef NKPROF
    if (g_dwProfilerFlags & PROFILE_OBJCALL)
        ProfilerHit(pci->ppfnMethods[iMethod]);
#endif
        return pfn;

    default:
        DEBUGMSG(ZONE_OBJDISP, (TEXT("ObjectCall: invalid dispatch type\r\n")));
        DEBUGCHK(0);
        break;
    }

    RaiseException(STATUS_INVALID_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, 0);
    DEBUGCHK (0);
    return 0;    // keep compiler happy
}
#pragma prefast(pop)


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL 
SC_CeMapArgumentArray(
    HANDLE hProc,
    LPVOID *pArgList,
    DWORD dwSig
    ) 
{
    DWORD dwVal;
    PPROCESS pproc;
    TRUSTED_API (L"SC_CeMapArgumentArray", FALSE);
    pproc = HandleToProc(hProc);
    if (!pproc) {
        KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
        return 0;
    }
    while (dwSig) {
        if ((dwSig & ARG_TYPE_MASK) == ARG_PTR) {
            dwVal = (DWORD)*pArgList;
            if (!(dwVal>>VA_SECTION) && (dwVal >= 0x10000)) {
                *pArgList = (LPVOID)(dwVal + pproc->dwVMBase);
            }
        }
        pArgList++;    
        dwSig >>= ARG_TYPE_BITS;
    }
    return 1;
}

void SuspendSelf (void)
{
    KCALLPROFON (64);
    DEBUGCHK (!pCurThread->bSuspendCnt);
    // we need to check the bit again because it might be
    // cleared before we enter KCall
    if (pCurThread->bPendSusp) {
        pCurThread->bSuspendCnt = pCurThread->bPendSusp;
        pCurThread->bPendSusp = 0;
        SET_RUNSTATE (pCurThread, RUNSTATE_BLOCKED);
        SET_USERBLOCK (pCurThread);     // okay to terminate the thread
        RunList.pth = 0;
        SetReschedule ();
    }
    KCALLPROFOFF (64);
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
SC_KillThreadIfNeeded() 
{
    /* The check for bPendSusp is kind of redundent here. However, we don't want to
       make a KCall unless it's remotely needed. Thus the check */
    if ((LLcs.OwnerThread != hCurThread) && (pCurProc == pCurThread->pOwnerProc)) {
        if (pCurThread->bPendSusp && (!GET_DYING(pCurThread) || GET_DEAD(pCurThread))) {
            // suspend ourself
            DEBUGCHK (LLcs.OwnerThread != hCurThread);
            KCall ((FARPROC) SuspendSelf);
            CLEAR_USERBLOCK (pCurThread);
        }
        // check if we are being terminated.
        if (GET_DYING(pCurThread) && !GET_DEAD(pCurThread)) {
            SET_DEAD(pCurThread);
            CLEAR_USERBLOCK(pCurThread);
            CLEAR_DEBUGWAIT(pCurThread);
            (*(void (*)(int))pExitThread)(0);
        }
    }
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
RETADDR ServerCallReturn (PSVRRTNSTRUCT psrs)
{
    PPROCESS pprc;
    PCALLSTACK pcstk;
    RETADDR ra;
    BOOL    fWasInKernel;
    extern LPVOID pExitThread;

    DEBUGMSG (ZONE_OBJDISP, (L"SCR: psrs = %8.8lx\n", psrs));

    pcstk = pCurThread->pcstkTop;
    pprc = pcstk->pprcLast;
    psrs->prevSP = pcstk->dwPrevSP;
    ra = pcstk->retAddr;
    psrs->linkage = pcstk->extra;
    psrs->mode = (pcstk->dwPrcInfo & CST_MODE_FROM_USER)? USER_MODE : KERNEL_MODE;
    pCurThread->aky = pcstk->akyLast;
    pCurThread->pProc = pprc;
    fWasInKernel = pcstk->dwPrcInfo & CST_IN_KERNEL;
    if (pcstk == &pCurThread->IntrStk) {
        pCurThread->pcstkTop = pcstk->pcstkNext;
    } else {

        /* unlink CALLSTACK structure from list */
        pCurThread->pcstkTop = pcstk->pcstkNext;
        if (IsValidKPtr(pcstk))
            FreeMem(pcstk,HEAP_CALLSTACK);

        /* The check for bPendSusp is kind of redundent here. However, we don't want to
           make a KCall unless it's remotely needed. Thus the check */
        if (pCurThread->bPendSusp
            && !((DWORD)ra & 0x80000000) 
            && (!pCurThread->pcstkTop 
                || (pprc == pCurThread->pOwnerProc)
                || (fWasInKernel && (pCurThread->pOwnerProc == pCurThread->pProc)))) {
            // suspend ourself
            DEBUGCHK (LLcs.OwnerThread != hCurThread);
            KCall ((FARPROC) SuspendSelf);
            CLEAR_USERBLOCK (pCurThread);
        }

        if (GET_DYING(pCurThread) && !GET_DEAD(pCurThread)
            && (LLcs.OwnerThread != hCurThread)
            && !((DWORD)ra & 0x80000000) 
            && (!pCurThread->pcstkTop 
                || (pprc == pCurThread->pOwnerProc)
                || (fWasInKernel && (pCurThread->pOwnerProc == pCurThread->pProc)))) {

            SET_DEAD(pCurThread);
            CLEAR_USERBLOCK(pCurThread);
            CLEAR_DEBUGWAIT(pCurThread);
            ra = (RETADDR)pExitThread;
        }
        DEBUGMSG(ZONE_OBJDISP, (TEXT("SCRet: return to %8.8lx Proc=%lx aky=%lx, mode = %8.8lx\r\n"),
            ra, pprc, pCurThread->aky, psrs->mode));
        if (!fWasInKernel) {
            /* Returning from a user mode server, restore the previous
             * address space information and return.
             */
            SetCPUASID(pCurThread);
        } else {
            /*
             * must do this or SetProcPermissions won't work on MIPS
             */
            CurAKey = pCurThread->aky;
        }
    }
    if (fWasInKernel) {
//        GoToUserTime();
    }
    UpdateCallerInfo(pCurThread, KERNEL_MODE == psrs->mode);
    DEBUGMSG(ZONE_OBJDISP, (TEXT("SCRet: Before return psrs->mode = %x, psrs->prevSP = %8.8lx\n"), 
        psrs->mode, psrs->prevSP));
    return ra;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
RETADDR PerformCallBackExt (POBJCALLSTRUCT pobs)
{
    CALLSTACK *pcstk;
    PPROCESS pProc;
    PTHREAD pth = pCurThread;
    DWORD currSP = pobs->prevSP;
    DWORD akyLast = pth->aky;
    PCALLBACKINFO pcbi = Arg(pobs->args, PCALLBACKINFO);

#ifdef MIPS
    DEBUGCHK (!((DWORD) pobs->args & (sizeof (REG_TYPE) -1)));
#endif

    DEBUGMSG(ZONE_OBJDISP, (TEXT("PerformCallBackExt: obs = %8.8lx, ra=%8.8lx mode=%x extra=%8.8lx, prevSP = %8.8lx\r\n"),
            pobs, pobs->ra,  pobs->mode, pobs->linkage, pobs->prevSP));

    if (!(pProc = HandleToProc(pcbi->hProc)) 
        || (!((DWORD) pobs->ra & 0x80000000) && (KERN_TRUST_FULL != pth->pProc->bTrustLevel))) {
        RaiseException(STATUS_INVALID_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, 0);
        DEBUGCHK (0);
    }
    pobs->mode = KERNEL_MODE;   // default is kernel mode
    pobs->prevSP = 0;           // default no stack switch
    if (pProc != &ProcArray[0]) {
        for (pcstk = pCurThread->pcstkTop; pcstk && (pcstk->pprcLast != pProc); pcstk = (PCALLSTACK)((ulong)pcstk->pcstkNext&~1))
            ;

        if (pcstk) {
            pth->aky = pcstk->akyLast;
            // only switch stack when calling back to user mode process
            if (pcstk->dwPrcInfo & CST_MODE_FROM_USER) {
                pobs->mode = USER_MODE;
                pobs->prevSP = pcstk->dwPrevSP;
            }
        } else if (bAllKMode || ((DWORD) pcbi->pfn & 0x80000000)) {

            DEBUGCHK (KERN_TRUST_FULL == pProc->bTrustLevel);

            pth->aky = pth->pOwnerProc->aky;
            AddAccess(&pth->aky, ProcArray[0].aky);
            AddAccess(&pth->aky, pProc->aky);

        } else {
#define SECURE_WORKAROUND
#ifdef SECURE_WORKAROUND
            RETAILMSG (1, (L"!!!! Work around Security violation (call forward), pth = %8.8lx, proc = '%s' !!!!\n", 
                pth, pCurProc->lpszProcName));
            pth->aky = pth->pOwnerProc->aky;
            AddAccess(&pth->aky, ProcArray[0].aky);
            AddAccess(&pth->aky, pProc->aky);
#else
            // SECURITY VIOLATION: callback originalted from PSL, into a non-trusted process
            RaiseException(STATUS_INVALID_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, 0);
            DEBUGCHK (0);
#endif
        }
    }
    // allocate new callstack

    // If this fails, we'll fault on setting the pprcLast - but we'd only raise an exception if we
    // were checking, anyway.
    pcstk = AllocMem(HEAP_CALLSTACK);

    pcstk->pprcLast = pth->pProc;
    pth->pProc = pProc;

    pcstk->akyLast = akyLast;
    pcstk->retAddr = pobs->ra;
    pcstk->extra = pobs->linkage;
    pcstk->pcstkNext = pth->pcstkTop;
    pcstk->dwPrevSP = pobs->prevSP? (currSP-CALLEE_SAVED_REGS) : 0;
    pcstk->dwPrcInfo = CST_CALLBACK | ((USER_MODE == pobs->mode)? CST_MODE_TO_USER : 0);
    pth->pcstkTop = pcstk;

    SetCPUASID (pth);
    UpdateCallerInfo(pCurThread, KERNEL_MODE == pobs->mode);
    DEBUGMSG (ZONE_OBJDISP, (L"Calling  callback function %8.8lx tls = %8.8lx, tlsNonSec = %8.8lx, tlsSec = %8.8lx, dwPrevSP = %8.8lx\n",
                ZeroPtr (pcbi->pfn), pth->tlsPtr, pth->tlsNonSecure, pth->tlsSecure, pobs->prevSP));

    randdw1 = ((randdw1<<5) | (randdw1>>27)) ^ (CurMSec & 0x1f);

    // mark return address as syscall_retrun
    pobs->ra = (RETADDR) SYSCALL_RETURN;
    // replace arg0 with real arg0
    WriteArg(pobs->args, DWORD, (DWORD) pcbi->pvArg0);
    return (RETADDR) ZeroPtr (pcbi->pfn);
}


RETADDR CallbackReturn (LPDWORD pLinkage) 
{
    PCALLSTACK pcstk;
    RETADDR ra;
    PPROCESS pProc;
    ACCESSKEY aky;

    DEBUGMSG (ZONE_OBJDISP, (L"CallbackReturn: pLinkage = %8.8lx\n", pLinkage));
    pcstk = pCurThread->pcstkTop;
    DEBUGCHK (pcstk);
    pCurThread->pcstkTop = pcstk->pcstkNext;
    pProc = pcstk->pprcLast;

    // if pcstk->akyLast is 0, it's an exception handler's record
    if (aky = pcstk->akyLast) {
        pCurThread->aky = aky;
    } else {
        // we'll only setup the callstak if calling into user-mode handler
        // update the TLS record
        KTHRDINFO (pCurThread) &= ~UTLS_INKMODE;
    }
    *pLinkage = pcstk->extra;
    ra = pcstk->retAddr;

    DEBUGCHK ((pcstk->dwPrcInfo & CST_CALLBACK) && !(pcstk->dwPrcInfo & CST_MODE_FROM_USER));

    pCurThread->pProc = pProc;

    if (IsValidKPtr(pcstk))
        FreeMem (pcstk,HEAP_CALLSTACK);

    if (aky) {
        if (pProc != &ProcArray[0]) {
            SetCPUASID(pCurThread);
        }
        UpdateCallerInfo (pCurThread, TRUE);
    }
    
    DEBUGMSG(ZONE_OBJDISP, 
            (TEXT("CBRet: return to %8.8lx Proc=%lx aky=%lx, *pLinkage = %d\n"),
            ra, pCurThread->pProc, pCurThread->aky, *pLinkage));

    return ra;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PFNVOID 
DBG_CallCheck(
    PTHREAD pth,
    DWORD dwJumpAddress,
    PCONTEXT pCtx
    ) 
{
    register const HDATA *phd;
    register const CINFO *pci;
    register int inx;
    register long iMethod;
    HANDLE h;

#if defined (MIPS)
    h = (HANDLE)pCtx->IntA0;
    if ((dwJumpAddress & 3) != 2 || dwJumpAddress
            < IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
        return 0;
    iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 2;
#elif defined (SHx)
    h = (HANDLE)pCtx->R4;
    if (!(dwJumpAddress & 1) || dwJumpAddress
            < IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
        return 0;
    iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 1;
#elif defined (x86)
    h = *(HANDLE*)(pCtx->Esp);
    if ((dwJumpAddress & 1) || dwJumpAddress
            < IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
        return 0;
    iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 1;
#elif defined (ARM)
    h = (HANDLE)pCtx->R0;
    if ((dwJumpAddress & 3) || dwJumpAddress
            < IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
        return 0;
    iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 2;
#else
    #error("Unknown CPU")
#endif

    DEBUGMSG(ZONE_OBJDISP, (TEXT("CallCheck: pth %8.8lx, h %8.8lx, iMethod %lx\r\n"),
            pth, h, iMethod));
    inx = NUM_SYS_HANDLES;
    if (iMethod < 0) {
        /* API call to an implicit handle. In this case, bits 30-16 of the
         * method index indicate which entry in the system handle table.
         */
        iMethod = -iMethod;
        if ((inx = iMethod>>HANDLE_SHIFT & HANDLE_MASK) >= NUM_SYS_HANDLES
                || (pci = SystemAPISets[inx]) == 0)
            return 0;
        iMethod &= METHOD_MASK;
#ifdef SECURE_WORKAROUND
        // special case for PerformCallBack(113) and PerformCallForward(149)
        if (!inx && ((iMethod == 113) || (iMethod == 149))) {
            // Lookup the function being called from the PCALLBACKINFO parameter in
            // arg0, a.k.a. "h" from above.  Set a breakpoint on the target of the
            // callback instead of SC_CallForward
            PCALLBACKINFO pcbInfo;
            PPROCESS pproc;
            if ((pcbInfo = (PCALLBACKINFO)DbgVerify (h, FALSE, NULL)) &&
                (pproc = HandleToProc(pcbInfo->hProc))) {
                return MapPtrProc(pcbInfo->pfn, pproc);
            }
        }   
#endif
        inx = pci->type;
    }

    if (inx) {
        /* validate handle argument and turn into HDATA pointer. */
        h2p (h, phd);
        if (!phd)
            return 0;
        pci = phd->pci;
    }
    
    /* validate interface and method indicies. */
    if (iMethod >= pci->cMethods)
        return 0;

    /* Dispatch api call based upon the dispatch type in the cinfo struct. */
    switch (pci->disp) {
    case DISPATCH_KERNEL:
    case DISPATCH_I_KERNEL:
    case DISPATCH_KERNEL_PSL:
    case DISPATCH_I_KPSL:
        DEBUGMSG(ZONE_OBJDISP,
                (TEXT("CallCheck: %8.8lx '%.4a' API call #%d. pfn=%8.8lx.\r\n"),
                pci, pci->acName, iMethod, pci->ppfnMethods[iMethod]));
        return pci->ppfnMethods[iMethod];

    case DISPATCH_PSL:
    case DISPATCH_I_PSL:
    {
        PFNVOID *ppfn;
        PFNVOID pfn;

        ppfn = (PFNVOID*)MapPtrProc(pci->ppfnMethods, pci->pServer);
        pfn = (PFNVOID)MapPtrProc(ppfn[iMethod], pci->pServer);
        DEBUGMSG(ZONE_OBJDISP,
                (TEXT("CallCheck: %8.8lx '%.4a' API call #%d. pfn=%8.8lx.\r\n"),
                pci, pci->acName, iMethod, pfn));
        return pfn;
    }

    default:
        break;
    }
    return 0;
}

⌨️ 快捷键说明

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