📄 objdisp.c
字号:
/* 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 //XTIMEvoid SyscallTime(DWORD); //XTIME record exception elapsed time#endif //XTIMEvoid 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 listvoid 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 listvoid 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 + -