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

📄 objdisp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
HANDLE
SC_CreateAPIHandle(
    HANDLE hSet,
    LPVOID pvData
    )
{
    PAPISET pas;
    HANDLE hRet;

    DEBUGMSG (!pvData, (L"SC_CreateAPIHandle: pvData == NULL\r\n"));
    if ((pas = HandleToAPISetPerm(hSet)) && (pas->cinfo.disp == DISPATCH_PSL)) {
        if ((hRet = AllocHandle(&pas->cinfo, pvData, CalcHandleOwner())) != 0)
            return hRet;
        KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
    } else
        KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
    return 0;
}




//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID
SC_VerifyAPIHandle(
    HANDLE hSet,
    HANDLE h
    )
{
    PAPISET pas;
    PHDATA phd;

    if ((pas = HandleToAPISet(hSet)) != 0) {
        if ((phd = HandleToPointer(h)) != 0
                && TestAccess(&phd->lock, &pCurThread->aky)
                && phd->pci == &pas->cinfo)
            return phd->pvObj;
        KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
    } else
        KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
    return 0;
}



//------------------------------------------------------------------------------
//
//  @func int | QueryAPISetID | Lookup an API Set index
//  @rdesc Returns the index of the requested API set (-1 if not found)
//  @parm PCHAR | pName | the name of the API Set (4 characters or less)
//  @comm Looks in the table of registered API Sets to find an API set with
//        the requested name. If one is found, the index of that set is returned.
//        If no matching set is found, then -1 is returned.
//
//------------------------------------------------------------------------------
int
SC_QueryAPISetID(
    char *pName
    )
{
    const CINFO *pci;
    char acName[4];
    int inx;

    for (inx = 0 ; inx < sizeof(acName) ; ++inx) {
        if ((acName[inx] = *pName) != 0)
            pName++;
    }
    if (*pName == 0) {
        for (inx = 0 ; inx < NUM_SYS_HANDLES ; ++inx) {
            if ((pci = SystemAPISets[inx]) != 0
                    && *(PDWORD)pci->acName == *(PDWORD)acName)
                return inx;
        }
    }
    return -1;
}



//------------------------------------------------------------------------------
//
//  @func DWORD | PerformCallback | Performs a call into another address space
//  @rdesc Returns the return value from the called function
//  @parm PCALLBACKINFO | pcbi | the callback to perform
//  @parmvar Zero or more parameters to pass to the function
//  @comm Switches into the address space of the process specified in the callback,
//        and then calls the specified function
//
//  NOTE: PerformCallBack() is implemented directly by ObjectCall().
//
//  SetBadHandleError - set error code based upon handle type
//
//  SetBadHandleError uses the handle type from the API call and the method
//  index to determine what value to return from an API call on an invalid handle.
//  If there is not default behavior, then an exception is raised.
//
//------------------------------------------------------------------------------
uint 
SetBadHandleError(
    int type,
    long iMethod
    ) 
{
    RETAILMSG(1, (TEXT("Invalid handle: Set=%d Method=%d\r\n"), type, iMethod));
    KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
    switch (type) {
    case HT_SOCKET:
        return WSAENOTSOCK;

    case HT_WNETENUM:
        return ERROR_INVALID_HANDLE;
        
    case HT_FILE:
        if (iMethod == 4 || iMethod == 5)
            return 0xFFFFFFFF;
        return 0;

    case SH_CURTHREAD:
        switch (iMethod) {
        case ID_THREAD_SUSPEND:
        case ID_THREAD_RESUME:
            return 0xFFFFFFFF;

        case ID_THREAD_GETTHREADPRIO:
        case ID_THREAD_CEGETPRIO:
            return THREAD_PRIORITY_ERROR_RETURN;
        }
        return 0;

    case SH_CURPROC:
    case SH_CURTOKEN:
        return FALSE;

    case HT_DBFILE:
    case HT_DBFIND:
    case HT_FIND:
    case HT_EVENT:
    case HT_APISET:
    case HT_MUTEX:
    case HT_FSMAP:
    case HT_SEMAPHORE:
        return FALSE;   // just return FALSE
    }

    // Fault the thread.
    RaiseException(STATUS_INVALID_SYSTEM_SERVICE, EXCEPTION_NONCONTINUABLE, 1, &iMethod);
    DEBUGCHK(0);    /* shouldn't get here */
    return 0;
}



//------------------------------------------------------------------------------
// ErrorReturn - return a error value from an invalid API call
//
//  This function is invoked via ObjectCall as a kernel PSL. It extracts a
// return value from the CALLSTACK's access key.
//------------------------------------------------------------------------------
uint 
ErrorReturn(void) 
{
    uint ret;
    ret = pCurThread->pcstkTop->akyLast;
    pCurThread->pcstkTop->akyLast = pCurThread->aky;     // Make sure that ServerCallReturn frees the CALLSTACK
    return ret;
}

#ifdef NKPROF
extern DWORD g_dwProfilerFlags;
extern void ProfilerHit(RETADDR ra);
#endif

BOOL TryCloseMappedHandle(HANDLE h);

void UpdateCallerInfo (PTHREAD pth, BOOL fInKMode)
{
    PCALLSTACK pcstk = pth->pcstkTop;
    PPROCESS pProc;

    // skip the faked callstacks for exception dispatch
    while (pcstk && ((DWORD) pcstk->pcstkNext & 1)) {
        pcstk = (PCALLSTACK) ((DWORD) pcstk->pcstkNext & ~1);
    }

    pProc = pcstk? pcstk->pprcLast : pth->pOwnerProc;

    KCALLERTRUST(pth) = pProc? pProc->bTrustLevel : KERN_TRUST_FULL;
    KCALLERVMBASE(pth) = pProc? pProc->dwVMBase : SECURE_VMBASE;
    if (fInKMode)
        KTHRDINFO(pth) |= UTLS_INKMODE;
    else
        KTHRDINFO(pth) &= ~UTLS_INKMODE;

    // tlsNonSecure can be 0 in NKTerminateThread
    if ((pth->tlsNonSecure != pth->tlsSecure) && pth->tlsNonSecure){
        pth->tlsNonSecure[PRETLS_THRDINFO] = 0;
    }
}

BOOL DoCloseAPIHandle (HANDLE h)
{
    BOOL fRet = FALSE, fFree;
    PHDATA phd;
    DEBUGMSG (ZONE_OBJDISP, (TEXT("DoCloseAPIHandle: closing=%8.8lx\r\n"), h));

    // decrement the reference count first to avoid RACE condition
    if (phd = (PHDATA) KCall ((FARPROC) TryDecRef, h, pCurThread->pcstkTop->pprcLast, &fFree)) {
        DEBUGCHK (phd->pci);
        DEBUGMSG (!phd->pvObj, (L"DoCloseAPIHandle: phd->pvObj == NULL\r\n"));

        // invoke the Close function
         __try {
            fRet = ((BOOL (*) (HANDLE)) (phd->pci->ppfnMethods[0])) (phd->pvObj);
        } __except (EXCEPTION_EXECUTE_HANDLER) {
            KSetLastError(pCurThread, ERROR_INVALID_PARAMETER);
        }
        DEBUGMSG (!fRet, (TEXT("DoCloseAPIHandle: CloseHandle failed, h = %8.8lx, proc = %8.8lx, pvObj = %8.8lx\r\n"), 
            h, pCurThread->pcstkTop->pprcLast, phd->pvObj));

        if (!fRet) {
            // close handle failed, increment the ref count back,
            // last error should've been set by the real CloseHandle function
            KCall (DoIncRef, h, pCurThread->pcstkTop->pprcLast, TRUE);
        } else if (fFree) {
            // succeed, free the handle if we're the last one referencing it
            FreeHandle (h);
        }
    } else {
        KSetLastError (pCurThread, ERROR_INVALID_PARAMETER);
    }

    return fRet;
}

PFNVOID GetPSLPfnAndValidateArgs (const CINFO *pci, long iMethod, LPBYTE args)
{

    if (!iMethod && (DISPATCH_I_PSL == pci->disp)) {
        // PSLNotify, either 0 or hCurProc/hCurThread
        HANDLE hProc, hThrd;
        PHDATA phd = NULL;

        NextArg (args, DWORD);      // skip arg 0
        hProc = Arg (args, HANDLE); // arg 1 == hProc
        h2p (hProc, phd);
        NextArg (args, DWORD);
        hThrd = Arg (args, HANDLE); // arg 2 == hThrd

        if ((hProc && (!phd || !TestAccess (&phd->lock, &pCurThread->aky)))
            || (hThrd && (hThrd != hCurThread))) {
            DEBUGMSG(1, (TEXT("PSLNotify : invalid argument hProc=%8.8x, hThrd = %8.8lx\r\n"), hProc, hThrd));
            KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
            return (PFNVOID)ErrorReturn; // void function, don't need to worry about return value
        }
        
    } else {
    
        DWORD dwSig, dwVal;
        DWORD dwBase = pCurProc->dwVMBase;
        BOOL  bTrusted = (KERN_TRUST_FULL == pCurProc->bTrustLevel);

        for (dwSig = pci->pdwSig[iMethod] ; dwSig ; dwSig >>= ARG_TYPE_BITS) {
            if ((dwSig & ARG_TYPE_MASK) == ARG_PTR) {
                dwVal = Arg(args, DWORD);
                if (!(dwVal>>VA_SECTION)) {
                    if (dwVal >= 0x10000)
                        WriteArg(args, DWORD, dwVal += dwBase);
                } else if (!bTrusted && (SC_MapPtrWithSize ((LPVOID) dwVal, 1, hCurProc) != (LPVOID)dwVal)) {
                    CurAKey = pCurThread->aky = pCurThread->pcstkTop->akyLast;
                    // invalid argument for non-trusted app. Raise exception
                    DEBUGMSG(1, (TEXT("Invalid Pointer Arguement for PSL (1): %lx\r\n"), dwVal));
                    RaiseException(STATUS_INVALID_PARAMETER_MIX, EXCEPTION_NONCONTINUABLE,
                            1, &dwVal);
                    DEBUGCHK(0);    /* shouldn't get here */
                    
                }
            }
            NextArg(args, DWORD);
        }
    }
    return pci->ppfnMethods[iMethod];
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
#pragma prefast(disable: 11, "Exceptio would have been raised if pci is NULL")
RETADDR ObjectCall (POBJCALLSTRUCT pobs)
{
    const HDATA *phd = NULL;
    const CINFO *pci;
    int inx;
    HANDLE h;
    PPROCESS pprc;
    PCALLSTACK pcstk;
    PTHREAD pth;
    LPVOID lpvVal;
    PFNVOID pfn;
    long iMethod = pobs->method;
    LPBYTE args = (LPBYTE) pobs->args;

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


    //DEBUGMSG(1, (TEXT("ObjectCall: ra=%8.8lx pMode=%8.8lx iMethod=%lx args=%8.8lx dwPrevSP=%8.8lx, *pMode = %8.8lx\r\n"),
    //        ra, pMode, iMethod, args, dwPrevSP, *pMode));
    randdw1 = ((randdw1<<5) | (randdw1>>27)) ^ (CurMSec & 0x1f);

    pth = pCurThread;
    /** Setup a kernel PSL CALLSTACK structure. This is done here so that
     * any exceptions are handled correctly.
     */
    // If this fails, we'll fault on setting the retAddr - but we'd only raise an exception if we
    // were checking, anyway.
    pcstk = AllocMem(HEAP_CALLSTACK);
    /* Save return address, previous access key, and extra CPU dependent info */
    pcstk->retAddr = pobs->ra;
    pcstk->dwPrevSP = pobs->prevSP;
    pcstk->akyLast = pth->aky;
    pcstk->extra = pobs->linkage;
    /* Save previous kernel/user mode info */
    pcstk->pprcLast = pth->pProc;
    pcstk->dwPrcInfo = (KERNEL_MODE == pobs->mode)? 0 : CST_MODE_FROM_USER;
    /* Link the CALLSTACK struct at the head of the thread's list */
    pcstk->pcstkNext = pth->pcstkTop;
    pth->pcstkTop = pcstk;

    DEBUGMSG(ZONE_OBJDISP, (TEXT("ObjectCall: obs = %8.8lx, ra=%8.8lx h=%8.8lx iMethod=%lx mode=%x extra=%8.8lx, prevSP = %8.8lx\r\n"),
            pobs, pobs->ra, Arg(args, HANDLE), iMethod, pobs->mode, pobs->linkage, pobs->prevSP));

    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) {
            DEBUGMSG(1, (TEXT("ObjectCall: Failed(1): %lx\r\n"), inx));
            RaiseException(STATUS_INVALID_SYSTEM_SERVICE, EXCEPTION_NONCONTINUABLE,
                    1, &iMethod);
            DEBUGCHK(0);    /* shouldn't get here */
        }
        iMethod &= METHOD_MASK;
        DEBUGCHK(pci->type == 0 || pci->type == inx);
        inx = pci->type;
    }

    /* For handle based api calls, validate the handle argument. */
    if (inx) {
        /* validate handle argument and turn into HDATA pointer. */
        h = Arg(args, HANDLE);
        h2p(h, phd);
        if (!phd || !TestAccess(&phd->lock, &pth->aky)) {
            if (iMethod <= 1) {
                DEBUGMSG(ZONE_OBJDISP, (TEXT("CloseHandle/WaitForSingleObject: invalid handle h=%x\r\n"),
                        Arg(args, HANDLE)));
                KSetLastError(pth, ERROR_INVALID_HANDLE);
                pcstk->akyLast = (ACCESSKEY)(iMethod==0 ? 0 : WAIT_FAILED);
                return (PFNVOID)ErrorReturn;
            }
            DEBUGMSG(ZONE_OBJDISP, (TEXT("ObjectCall: Failed (2): h=%x\r\n"), Arg(args, HANDLE)));
            pcstk->akyLast = (ACCESSKEY)SetBadHandleError(inx, iMethod);
            return (PFNVOID)ErrorReturn;
        }
        pci = phd->pci;
        if (pci->type != inx && (inx != NUM_SYS_HANDLES || iMethod > 1)) {
            // The handle is valid but the type is wrong.
            DEBUGMSG(ZONE_OBJDISP, (TEXT("ObjectCall: Failed(2a): h=%x t=%d shdb %d\r\n"),
                    Arg(args, HANDLE), pci->type, inx));
            pcstk->akyLast = (ACCESSKEY)SetBadHandleError(inx, iMethod);
            return (PFNVOID)ErrorReturn;
        }
    }

    /* validate interface and method indicies. */
    DEBUGMSG(ZONE_OBJDISP,
            (TEXT("ObjectCall: %8.8lx '%.4a' API call #%d. disp=%d.\r\n"),
            pci, pci->acName, iMethod, pci->disp));
    if (iMethod >= pci->cMethods) {
        DEBUGMSG(1,(TEXT("ObjectCall: Failed (3): %d %d\r\n"),
                iMethod, pci->cMethods));
        RaiseException(STATUS_INVALID_SYSTEM_SERVICE, EXCEPTION_NONCONTINUABLE, 1, &iMethod);
        DEBUGCHK(0);    /* shouldn't get here */
    }

    pfn = 0;
    
    /* Dispatch api call based upon the dispatch type in the cinfo struct. */
    switch (pci->disp) {
    case DISPATCH_KERNEL_PSL:
    case DISPATCH_I_KPSL:
        pfn = pci->ppfnMethods[iMethod];
        if ((pfn == (PFNVOID)-1) || (pfn == (PFNVOID)-2)) {
            //pobs->ra = (RETADDR) SYSCALL_RETURN;
            // If you hit the following exception, you're doing a PerformCall"Forward", which is 
            // no longer supported since it violates security rule.
            RaiseException(STATUS_INVALID_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, 0);
            DEBUGCHK (0);   // should never get here
        } else {
            /* Continue the thread in kernel mode */
            pcstk->dwPrcInfo |= CST_IN_KERNEL;
//            GoToKernTime();
        }

        DEBUGMSG(ZONE_OBJDISP, (TEXT("KPSLDispatch: pci %8.8lx, fnptr %8.8lx\r\n"),
                pci, pfn));
#ifdef NKPROF
    if (g_dwProfilerFlags & PROFILE_OBJCALL)
        ProfilerHit(pfn);
#endif
        return pfn;

    case DISPATCH_PSL:
        lpvVal = phd->pvObj;
        if (iMethod == 0) {
            /* Closing this handle, decrement the reference count */
            if (!TestAccess(&phd->lock, &pCurProc->aky)) {
                if ((phd->lock == 1) && (phd->ref.count == 1)) {
                    pcstk->akyLast = TryCloseMappedHandle(h);
                    return (PFNVOID)ErrorReturn;
                }
                KSetLastError(pth, ERROR_INVALID_HANDLE);
                pcstk->akyLast = 0;
                return (PFNVOID)ErrorReturn;
            }

            pfn = DoCloseAPIHandle;
        } else {
            WriteArg(args, LPVOID, lpvVal);
            DEBUGMSG(ZONE_OBJDISP,(TEXT("PSLDispatch: info=%8.8lx\r\n"), phd->pvObj));
        }
        // fall through
    case DISPATCH_I_PSL:
        pprc = pci->pServer;
        AddAccess(&pth->aky, pprc->aky);
        if (!pfn) {

⌨️ 快捷键说明

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