📄 objdisp.c
字号:
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];
}
}
// fAll is TRUE only for closing a process handle while process is exiting. We need to set
// pvobj to 0 if we don't free the handle. The reason is that other processes still
// have a handle the the exited process, and we need to make sure that they don't have
// access to the object anymore.
if (fAll && phd) {
DEBUGCHK (phd->pci && (phd->pci->type==SH_CURPROC));
#ifdef DEBUG
phd->pvObj = (PVOID) 0xabababef;
#else
phd->pvObj = NULL;
#endif
}
KCALLPROFOFF(30);
return FALSE;
}
//------------------------------------------------------------------------------
// This function MUST BE CALLED Within KCall
// it decrements the ref count of a handle and return the pointer to the HDATA
// *pfFree will be set to TRUE if the handle can be freed, FALSE otherwise
//------------------------------------------------------------------------------
PHDATA TryDecRef (HANDLE h, PPROCESS pprc, BOOL *pfFree)
{
PHDATA phd;
h2p (h, phd);
if (!phd || !TestAccess (&phd->lock, &pprc->aky))
return NULL;
*pfFree = DoDecRef (h, pprc, FALSE);
return phd;
}
//------------------------------------------------------------------------------
// Returns TRUE if all references removed.
//------------------------------------------------------------------------------
BOOL
DecRef(
HANDLE h,
PPROCESS pprc,
BOOL fAll
)
{
return KCall(DoDecRef, h, pprc, fAll);
}
//
// Decrement ref count of a thread
//
BOOL DecThreadRef (HANDLE hTh, PPROCESS pprc)
{
PHDATA phd;
BOOL bRet = FALSE;
ACCESSKEY aky = pprc->aky;
ushort minref; // minimum ref count
KCALLPROFON (49);
h2p (hTh, phd);
if (phd && TestAccess(&phd->lock, &aky) && (&cinfThread == phd->pci)) {
PTHREAD pth = phd->pvObj;
// min ref count for owner proc is 1 if the thread is still alive
minref = (pth
#ifdef DEBUG
&& ((PVOID) 0xabababcd != pth)
#endif
&& (pth->pOwnerProc == pprc))? 1 : 0;
if (phd->ref.count < 0x10000) { // fullref structure?
// no fullref structure
if ((phd->ref.count > minref) // greater than min ref count?
&& (bRet = !(-- phd->ref.count))) { // decrement to 0?
phd->lock = 0; // set lock to 0 if true
}
} else {
// fullref structure
int inx = pprc->procnum;
bRet = (phd->ref.pFr->usRefs[inx] > minref) // greater than min ref count?
&& !(-- phd->ref.pFr->usRefs[inx]) // decrement to 0?
&& !RemoveAccess(&phd->lock, aky); // last process accessing it?
}
}
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;
}
//------------------------------------------------------------------------------
// Returns FALSE if handle is not valid.
//------------------------------------------------------------------------------
BOOL
SetUserInfo(
HANDLE h,
DWORD info
)
{
PHDATA phd;
h2p(h, phd);
if (phd) {
phd->dwInfo = info;
return TRUE;
}
return FALSE;
}
//------------------------------------------------------------------------------
// Returns NULL if handle is not valid.
//------------------------------------------------------------------------------
PVOID
GetObjectPtr(
HANDLE h
)
{
PHDATA phd;
h2p(h, phd);
#ifdef DEBUG
if (phd && (((PVOID) 0xabababcd == phd->pvObj) || ((PVOID) 0xabababef == phd->pvObj)))
return 0;
#endif
return phd ? phd->pvObj : 0;
}
//------------------------------------------------------------------------------
// Returns NULL if handle is not valid or not correct type.
//------------------------------------------------------------------------------
PVOID
GetObjectPtrByType(
HANDLE h,
int type
)
{
PHDATA phd;
h2p(h, phd);
#ifdef DEBUG
if (phd && (((PVOID) 0xabababcd == phd->pvObj) || ((PVOID) 0xabababef == phd->pvObj)))
return 0;
#endif
return (phd && phd->pci && phd->pci->type==type) ? phd->pvObj : 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PVOID
GetObjectPtrByTypePermissioned(
HANDLE h,
int type
)
{
PHDATA phd;
h2p(h, phd);
#ifdef DEBUG
if (phd && (((PVOID) 0xabababcd == phd->pvObj) || ((PVOID) 0xabababef == phd->pvObj)))
return 0;
#endif
return (phd && phd->pci && phd->pci->type==type && TestAccess(&phd->lock, &pCurThread->aky)) ? phd->pvObj : 0;
}
//------------------------------------------------------------------------------
// Returns FALSE if handle is not valid.
//------------------------------------------------------------------------------
BOOL
SetObjectPtr(
HANDLE h,
PVOID pvObj
)
{
PHDATA phd;
h2p(h, phd);
if (phd) {
phd->pvObj = pvObj;
return TRUE;
}
return FALSE;
}
//------------------------------------------------------------------------------
// Returns 0 if handle is not valid.
//------------------------------------------------------------------------------
int
GetHandleType(
HANDLE h
)
{
PHDATA phd;
h2p(h, phd);
return (phd && phd->pci != 0) ? phd->pci->type : 0;
}
//------------------------------------------------------------------------------
// SetHandleOwner - switch ownership of a handle
//
// SetHandleOwner will take a handle that the current process has exclusive
// permission to access and give exclusive access to another process. This is used
// by the file system to switch ownership of handles which are returned by forwarded
// api calls.
//
// NOTE: The handle reference count must be 1.
//------------------------------------------------------------------------------
BOOL
SC_SetHandleOwner(
HANDLE h,
HANDLE hProc
)
{
PPROCESS pprc;
PHDATA phd;
if ((phd = HandleToPointer(h)) != 0 && phd->ref.count == 1
&& TestAccess(&phd->lock, &CurAKey)
&& (pprc = HandleToProc(hProc)) != 0) {
// Zap the old lock with the key from the new owner.
LockFromKey(&phd->lock, &pprc->aky);
return TRUE;
}
return FALSE;
}
//------------------------------------------------------------------------------
//
// @func HANDLE | CreateAPISet | Creates an API set
// @rdesc Returns the handle to the API set
// @parm char[4] | acName | class name (for debugging)
// @parm USHORT | cFunctions | # of functions in set
// @parm PFNVOID* | ppfnMethods | array of API functions
// @parm LPDWORD | pdwSig | array of signatures for API functions
// @comm Creates an API set from the list of functions passed in
//
//------------------------------------------------------------------------------
HANDLE
SC_CreateAPISet(
char acName[4], /* 'class name' for debugging & QueryAPISetID() */
USHORT cFunctions, /* # of functions in set */
const PFNVOID *ppfnMethods, /* array of API functions */
const DWORD *pdwSig /* array of signatures for API functions */
)
{
PAPISET pas;
HANDLE hSet;
TRUSTED_API (L"SC_CreateAPISet", NULL);
if ((pas = AllocMem(HEAP_APISET)) != 0
&& (hSet = AllocHandle(&cinfAPISet, pas, pCurProc)) != 0) {
*(PDWORD)pas->cinfo.acName = *(PDWORD)acName;
pas->cinfo.disp = DISPATCH_PSL;
pas->cinfo.type = NUM_SYS_HANDLES;
pas->cinfo.cMethods = cFunctions;
pas->cinfo.ppfnMethods = (const PFNVOID *) MapPtr (ppfnMethods);
pas->cinfo.pdwSig = (const DWORD *) MapPtr (pdwSig);
pas->cinfo.pServer = pCurProc;
pas->iReg = -1; /* not a registered handle */
return hSet;
} else if (pas != 0)
FreeMem(pas, HEAP_APISET);
KSetLastError(pCurThread, ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SC_CloseAPISet(
HANDLE hSet
)
{
PAPISET pas;
if (DecRef(hSet, pCurProc, FALSE) && (pas = HandleToAPISet(hSet)) != 0) {
if (pas->iReg != -1 && pas->cinfo.type == 0) {
SystemAPISets[pas->iReg] = 0;
KInfoTable[KINX_API_MASK] &= ~(1ul << pas->iReg);
}
FreeMem(pas, HEAP_APISET);
FreeHandle(hSet);
}
return;
}
//------------------------------------------------------------------------------
//
// @func BOOL | RegisterAPISet | Registers a global APIset
// @rdesc Returns TRUE on success, else FALSE
// @parm HANDLE | hASet | handle to API set
// @parm DWORD | dwSetID | constant identifying which API set to register as
// @comm Associates the APIset with a slot in the global APIset table
//
//------------------------------------------------------------------------------
BOOL
SC_RegisterAPISet(
HANDLE hSet,
DWORD dwSetID
)
{
PAPISET pas;
BOOL typeOnly, bKPSL;
int err = ERROR_INVALID_PARAMETER;
TRUSTED_API (L"SC_RegisterAPISet", FALSE);
typeOnly = dwSetID >> 31;
bKPSL = (dwSetID >> 30) & 1;
dwSetID = dwSetID & 0x3fffffff;
if (dwSetID == 0) {
err = ERROR_NO_PROC_SLOTS;
dwSetID = NUM_SYS_HANDLES;
while ((dwSetID - 1) > SH_LASTRESERVED)
if (!SystemAPISets[--dwSetID])
break;
} else
dwSetID &= 0x7fffffff;
if ((pas = HandleToAPISet(hSet)) && (pas->iReg == -1) &&
(typeOnly ? (dwSetID < SH_LAST_NOTIFY && SystemAPISets[dwSetID] &&
SystemAPISets[dwSetID]->type == dwSetID) :
((dwSetID >= SH_LAST_NOTIFY) && (dwSetID < NUM_SYS_HANDLES) &&
!SystemAPISets[dwSetID]))) {
if (typeOnly) {
pas->iReg = dwSetID;
pas->cinfo.type = (uchar)dwSetID;
} else {
pas->iReg = dwSetID;
pas->cinfo.disp = bKPSL ? DISPATCH_I_KPSL : DISPATCH_I_PSL;
pas->cinfo.type = 0;
SystemAPISets[dwSetID] = &pas->cinfo;
KInfoTable[KINX_API_MASK] |= 1ul << dwSetID;
}
return TRUE;
} else {
RETAILMSG(1, (TEXT("RegisterAPISet failed for api set id %d.\r\n"),dwSetID));
KSetLastError(pCurThread, err);
}
return FALSE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PPROCESS
CalcHandleOwner(void)
{
PCALLSTACK pcstk = pCurThread->pcstkTop;
while (pcstk && (pcstk->dwPrcInfo & CST_IN_KERNEL) && (pcstk->pprcLast != ProcArray)) {
pcstk = pcstk->pcstkNext;
}
return pcstk? pcstk->pprcLast : pCurProc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -