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

📄 objdisp.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// 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.
//

/*+
    objdisp.c - object call dispatch routines.

    This file contains the routines for dispatching method calls to objects
    implemented by protected system libraries, direct kernel functions,
    and kernel mode threads.
*/

#include "kernel.h"
#include "winsock.h"

#ifndef _PREFAST_
#pragma warning(disable: 4068) // Disable pragma warnings
#endif


void SC_CloseAPISet(HANDLE hSet);
BOOL SC_RegisterAPISet(HANDLE hSet, DWORD dwSetID);
LPVOID SC_VerifyAPIHandle(HANDLE hSet, HANDLE h);
//void GoToUserTime(void);
//void GoToKernTime(void);

extern CRITICAL_SECTION LLcs;

const PFNVOID APISetMethods[] = {
    (PFNVOID)SC_CloseAPISet,
    (PFNVOID)SC_NotSupported,
    (PFNVOID)SC_RegisterAPISet,
    (PFNVOID)SC_CreateAPIHandle,
    (PFNVOID)SC_VerifyAPIHandle,
};

const CINFO cinfAPISet = {
    "APIS",
    DISPATCH_KERNEL_PSL,
    HT_APISET,
    sizeof(APISetMethods)/sizeof(APISetMethods[0]),
    APISetMethods,
};

// Head of double linked list of active handles in the system.
DList HandleList = { &HandleList, &HandleList };

// Serial # for handle values.
unsigned int HandleSerial;

// Array of pointers to system api sets.
const CINFO *SystemAPISets[NUM_SYSTEM_SETS];

extern const CINFO cinfThread;


//------------------------------------------------------------------------------
// Find a process index from an access lock.
//------------------------------------------------------------------------------
int 
IndexFromLock(
    ulong lock
    )
{
    ulong mask;
    int inxRet;
    int inx;

    mask = 0x0000FFFFul;
    for (inxRet = 0, inx = 16 ; inx ; inx >>= 1, mask >>= inx) {
        if ((lock & mask) == 0) {
            inxRet += inx;
            lock >>= inx;
        }
    }
    return inxRet;
}



//------------------------------------------------------------------------------
// Insert an item into a double linked list
//------------------------------------------------------------------------------
void 
AddToDList(
    DList *head,
    DList *item
    )
{
    item->back = head;
    item->fwd = head->fwd;
    head->fwd->back = item;
    head->fwd = item;
}



//------------------------------------------------------------------------------
// Remove an item from a double linked list
//------------------------------------------------------------------------------
void 
RemoveDList(
    DList *item
    )
{
    item->fwd->back = item->back;
    item->back->fwd = item->fwd;
}



//------------------------------------------------------------------------------
// Convert a HANDLE to an HDATA pointer.
//
// HandleToPointer() is a function which can be used by other kernel modules.
//
//  h2p() is an private macro used to speed up the internal processing of
// ObjectCall() and the various GetXXX/SetXXX functions.
//------------------------------------------------------------------------------
#define h2p(h, phdRet) \
    do { \
        if ((ulong)h < NUM_SYS_HANDLES+SYS_HANDLE_BASE && (ulong)h >= SYS_HANDLE_BASE) \
             h = KData.ahSys[(uint)h-SYS_HANDLE_BASE]; \
        if (h) {            \
            phdRet = (PHDATA)(((ulong)h & HANDLE_ADDRESS_MASK) + KData.handleBase); \
            if (!IsValidKPtr(phdRet) || phdRet->hValue != h) \
                phdRet = 0; \
        } else              \
            phdRet = 0;     \
    } while (0)



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PHDATA 
HandleToPointer(
    HANDLE h
    )
{
    PHDATA phdRet;

    h2p(h, phdRet);
    return phdRet;
}


PHDATA PhdPrevReturn, PhdNext;

//------------------------------------------------------------------------------
// Return the next handle to close.
//
// The active handle list is scanned for a handle which is referenced by the process
// whose procnum is (id). (hLast) is the previous return value from this
// routine.  If a handle is found, its reference count for the process is forced
// to 1 so that it will be closed by a single call to CloseHandle(). To speed up the
// iterative process of scanning the entire table, a pointer to the next handle in
// the list is retained. The next call will use that value if the list is unchanged,
// except for the possible freeing of the handle previously returned. If the list
// has changed, the scan will restart at the beginning of the list.
//
//NOTE: This function is called via KCall().
//------------------------------------------------------------------------------
PHDATA 
NextCloseHandle(
    PHDATA *phdLast,
    int ixProc
    ) 
{
    PHDATA phd;
    KCALLPROFON(7);
    if (!PhdPrevReturn || !PhdNext || (*phdLast != PhdNext))
        phd = (PHDATA)HandleList.fwd;
    else
        phd = (PHDATA)PhdNext->linkage.fwd;
    DEBUGCHK(phd != 0);
    if (&phd->linkage == &HandleList) {
        PhdPrevReturn = 0;
        KCALLPROFOFF(7);
        return 0;
    }
    PhdPrevReturn = phd;
    if ((phd->lock & (1<<ixProc)) && (phd->hValue != hCurThread) && (phd->hValue != hCurProc)) {
        // Force handle reference count for this process to one.
        if (phd->ref.count < 0x10000)
            phd->ref.count = 1;
        else
            phd->ref.pFr->usRefs[ixProc] = 1;
    } else {
        PhdNext = *phdLast = phd;
        phd = (PHDATA)((ulong)phd | 1);
    }
    KCALLPROFOFF(7);
    return phd;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
SC_CloseAllHandles(void) 
{
    PHDATA phd, next;
    int ixProc;

    
    next = 0;
    ixProc = pCurProc->procnum;
    while (phd = (PHDATA)KCall((PKFN)NextCloseHandle, &next, ixProc))
        if (!((DWORD)phd & 1)) {
            if (!CloseHandle(phd->hValue)) {
                DEBUGMSG (1, (L"SC_CloseAllHandles: CloseHandle(0x%8.8lx) Failed on Process exit, zapping the handle\r\n", phd->hValue));
                // we're exiting, remove the access to the handle from the process
                RemoveAccess (&phd->lock, pCurProc->aky);
                
                // process exiting and CloseHandle returned FALSE; we'll just
                // zap the handle if we're the last one referencing it.
                if (!phd->lock) {
                    FreeHandle (phd->hValue);
                } else {
                    // if we're not the last one referencing the handle, just revoke the
                    // access and set the per-proc refcnt to 0
                    // ASSUMPTION : NextCloseHandle can not get us to this point
                    // unless there is a full ref count structure.
                    DEBUGCHK ((phd->ref.count >= 0x10000) && (1 == phd->ref.pFr->usRefs[ixProc]));
                    phd->ref.pFr->usRefs[ixProc] = 0;
                }
            }
        }
}



//------------------------------------------------------------------------------
// Non-preemtible handle setup for AllocHandle().
//------------------------------------------------------------------------------
BOOL 
SetupHandle(
    PHDATA phdNew,
    PPROCESS pprc
    ) 
{
    KCALLPROFON(8);
    phdNew->hValue = (HANDLE)(((ulong)phdNew & HANDLE_ADDRESS_MASK) | 2 | (randdw1 & 0xE0000000));
    LockFromKey(&phdNew->lock, &pprc->aky);
    // Zap PhdPrevReturn so to force a restart the next time
    // NextCloseHandle() is called.
    PhdPrevReturn = 0; 
    AddToDList(&HandleList, &phdNew->linkage);
    KCALLPROFOFF(8);
    return TRUE;
}



//------------------------------------------------------------------------------
// Non-preemtible handle cleanup for FreeHandle().
//------------------------------------------------------------------------------
PHDATA 
ZapHandle(
    HANDLE h
    ) 
{
    PHDATA phd;
    KCALLPROFON(9);
    h2p(h, phd);
    if (phd) {
        phd->lock = 0;
        // make it so that the handle no longer matches existing handles given out
        DEBUGCHK(((DWORD)phd->hValue & 0x1fffffff) == (((ulong)phd & HANDLE_ADDRESS_MASK) | 2));
        phd->hValue = (HANDLE)((DWORD)phd->hValue+0x20000000);
        // If freeing a handle other than the last one returned by
        // NextCloseHandle(), then zap PhdPrevReturn so to force
        // a restart the next time NextCloseHandle() is called.
        if (phd != PhdPrevReturn)
            PhdPrevReturn = 0; 
        if (phd == PhdNext)
            PhdNext = 0;
        RemoveDList(&phd->linkage);
    }
    KCALLPROFOFF(9);
    return phd;
}



//------------------------------------------------------------------------------
// Create a new handle.
//------------------------------------------------------------------------------
HANDLE 
AllocHandle(
    const CINFO *pci,
    PVOID pvObj,
    PPROCESS pprc
    )
{
    PHDATA phdNew;

    DEBUGMSG(ZONE_MEMORY, (TEXT("AllocHandle: pci=%8.8lx pvObj=%8.8lx pprc=%8.8lx\r\n"),
            pci, pvObj, pprc));
    if ((phdNew = AllocMem(HEAP_HDATA)) != 0) {
        phdNew->pci = pci;
        phdNew->pvObj = pvObj;
        phdNew->dwInfo = 0;
        phdNew->ref.count = 1;
        if (KCall((PKFN)SetupHandle, phdNew, pprc)) {
            DEBUGMSG(ZONE_MEMORY, (TEXT("AllocHandle: phd=%8.8lx hValue=%8.8lx\r\n"),
                    phdNew, phdNew->hValue));
            return phdNew->hValue;
        }
        DEBUGMSG(ZONE_MEMORY, (TEXT("AllocHandle: SetupHandle Failed!\r\n")));
        FreeMem(phdNew, HEAP_HDATA);
    } else
        DEBUGMSG(ZONE_MEMORY, (TEXT("AllocHandle: AllocMem Failed!\r\n")));
    return 0;
}




//------------------------------------------------------------------------------
// Destroy a handle.
//------------------------------------------------------------------------------
BOOL 
FreeHandle(
    HANDLE h
    )
{
    PHDATA phd;

    if ((phd = (PHDATA)KCall((PKFN)ZapHandle, h)) != 0) {
        if (phd->ref.count >= 0x10000)
            FreeMem(phd->ref.pFr, HEAP_FULLREF);
        FreeMem(phd, HEAP_HDATA);
        return TRUE;
    }
    return FALSE;
}



//------------------------------------------------------------------------------
// Non-preemtible: copies single refcount to FULLREF.
//------------------------------------------------------------------------------
BOOL 
CopyRefs(
    HANDLE h,
    FULLREF *pFr
    ) 
{
    PHDATA phd;
    int inx;
    KCALLPROFON(12);
    h2p(h, phd);
    if (phd && phd->ref.count < 0x10000) {
        inx = IndexFromLock(phd->lock);
        pFr->usRefs[inx] = (ushort)phd->ref.count;
        phd->ref.pFr = pFr;
        KCALLPROFOFF(12);
        return FALSE;
    }
    KCALLPROFOFF(12);
    return TRUE;
}



//------------------------------------------------------------------------------
// Non-preemtible worker for IncRef().
//------------------------------------------------------------------------------
int 
DoIncRef(
    HANDLE h,
    PPROCESS pprc,
    BOOL fAddAccess
    ) 
{
    PHDATA phd;
    ACCESSKEY aky;
    int inx;
    KCALLPROFON(11);
    aky = pprc->aky;
    inx = pprc->procnum;
    h2p(h, phd);
    if (phd) {
        if (fAddAccess) {
            AddAccess(&phd->lock, aky);
        }
        if (phd->lock != 0) {
            if (phd->ref.count < 0x10000) {               
                if (TestAccess(&phd->lock, &aky)) {
                    ++phd->ref.count;
                    KCALLPROFOFF(11);
                    return 1;
                }
                KCALLPROFOFF(11);
                return 2;   // Tell IncRef to allocate a FULLREF.
            }
            // There is a FULLREF structure. Increment the entry for this
            // process and add it to the access key.
            AddAccess(&phd->lock, aky);
            ++phd->ref.pFr->usRefs[inx];
            KCALLPROFOFF(11);
            return 1;
        }
    }
    KCALLPROFOFF(11);
    return 0;
}



//------------------------------------------------------------------------------
// Returns FALSE if handle not valid or refcnt==0.
//------------------------------------------------------------------------------
BOOL 
IncRef(
    HANDLE h,
    PPROCESS pprc
    )
{
    FULLREF *pFr;
    int ret;

    while ((ret = KCall(DoIncRef, h, pprc, FALSE)) == 2) {
        // Second process referencing handle. Must allocate
        // a FULLREF structure to track references from
        // multiple processes.
        if ((pFr = AllocMem(HEAP_FULLREF)) == 0)
            return FALSE;
        memset(pFr,0,sizeof(FULLREF));
        if (KCall(CopyRefs, h, pFr)) {
            // Another thread already allocated a FULLREF for this handle.
            FreeMem(pFr, HEAP_FULLREF);
        }
    }

⌨️ 快捷键说明

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