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

📄 objdisp.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved. */

/*+
    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 "xtime.h"
#include "winsock.h"

#ifdef XTIME							//XTIME
void SyscallTime(DWORD);				//XTIME record exception elapsed time
#endif									//XTIME

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];

// 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;
}

// 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 PhdPrevReturn, PhdNext;

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))
    		CloseHandle(phd->hValue);
}

// Non-preemtible handle setup for AllocHandle().
BOOL SetupHandle(PHDATA phdNew, PPROCESS pprc) {
	KCALLPROFON(8);
	phdNew->hValue = (HANDLE)(((ulong)phdNew & HANDLE_ADDRESS_MASK) | 2 | ((ulong)phdNew->hValue & 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) {
    PHDATA phd;
    ACCESSKEY aky;
    int inx;
    KCALLPROFON(11);
    aky = pprc->aky;
    inx = pprc->procnum;
    h2p(h, phd);
    if (phd && 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)) == 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);
        }
    }
    return ret;
}

// Non-preemtible worker for DecRef().
BOOL DoDecRef(HANDLE h, PPROCESS pprc, BOOL fAll) {
    PHDATA phd;
    ACCESSKEY aky;
    int inx;
    KCALLPROFON(30);
    aky = pprc->aky;
    inx = pprc->procnum;
    h2p(h, phd);
    if (phd && TestAccess(&phd->lock, &aky)) {
        if (phd->ref.count < 0x10000) {               
            if (fAll || phd->ref.count == 1) {
                phd->lock = 0;
                phd->ref.count = 0;
			    KCALLPROFOFF(30);
                return TRUE;
            }
            --phd->ref.count;
        } else {
            // There is a FULLREF structure. Decrement the entry for this
            // process. If the last reference for this process is removed,
            // remove its permission to access the handle.
            if (fAll || phd->ref.pFr->usRefs[inx] == 1) {
                phd->ref.pFr->usRefs[inx] = 0;
                if (RemoveAccess(&phd->lock, aky) == 0) {
				    KCALLPROFOFF(30);
                    return TRUE;
				}
            } else
                --phd->ref.pFr->usRefs[inx];
        }
    }
    KCALLPROFOFF(30);
    return FALSE;
}

// Returns TRUE if all references removed.
BOOL DecRef(HANDLE h, PPROCESS pprc, BOOL fAll)
{
    return KCall(DoDecRef, h, pprc, fAll);
}

BOOL CheckLastRef(HANDLE hTh) {
	PHDATA phd;
	BOOL bRet;
	KCALLPROFON(49);
	bRet = TRUE;
	h2p(hTh,phd);
	if (phd && phd->pvObj && (phd->pci->type==SH_CURTHREAD) && ((THREAD *)(phd->pvObj))->pOwnerProc == pCurProc) {
		if (phd->ref.count < 0x10000) {
			if (phd->ref.count == 1)
				bRet = FALSE;
		} else {
        	if (phd->ref.pFr->usRefs[pCurProc->procnum] == 1)
        		bRet = FALSE;
        }
    }
	KCALLPROFOFF(49);
	return bRet;
}

// Returns 0 if handle is not valid.
DWORD GetUserInfo(HANDLE h)
{
    PHDATA phd;

    h2p(h, phd);
    return phd ? phd->dwInfo : 0;
}

⌨️ 快捷键说明

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