📄 objdisp.c
字号:
// 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); 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); return (phd && phd->pci && phd->pci->type==type) ? phd->pvObj : 0;}PVOID GetObjectPtrByTypePermissioned(HANDLE h, int type){ PHDATA phd; h2p(h, phd); 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 inHANDLESC_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; if (pCurProc->bTrustLevel != KERN_TRUST_FULL) { ERRORMSG(1,(L"SC_CreateAPISet failed due to insufficient trust\r\n")); KSetLastError(pCurThread, ERROR_ACCESS_DENIED); return 0; } 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 = ppfnMethods; pas->cinfo.pdwSig = 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;}voidSC_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 tableBOOLSC_RegisterAPISet(HANDLE hSet, DWORD dwSetID){ PAPISET pas; BOOL typeOnly, bKPSL; int err = ERROR_INVALID_PARAMETER; if (pCurProc->bTrustLevel != KERN_TRUST_FULL) { ERRORMSG(1,(L"SC_RegisterAPISet failed due to insufficient trust\r\n")); KSetLastError(pCurThread,ERROR_ACCESS_DENIED); return 0; } 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) { if (pCurThread->pcstkTop) { if ((DWORD)pCurThread->pcstkTop->pprcLast >= 0x10000) return pCurThread->pcstkTop->pprcLast; if ((pCurThread->pcstkTop->pcstkNext) && ((DWORD)pCurThread->pcstkTop->pcstkNext->pprcLast >= 0x10000)) return pCurThread->pcstkTop->pcstkNext->pprcLast; } return pCurProc;}HANDLESC_CreateAPIHandle(HANDLE hSet, LPVOID pvData){ PAPISET pas; HANDLE hRet; if ((pas = (bAllKMode ? HandleToAPISetPerm(hSet) : HandleToAPISet(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;}LPVOIDSC_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.intSC_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: 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 = 1; // Make sure that ServerCallReturn frees the CALLSTACK return ret;}#ifdef NKPROFextern BOOL bProfileObjCall;extern void ProfilerHit(RETADDR ra);#endifBOOL TryCloseMappedHandle(HANDLE h);RETADDR ObjectCall(int *pMode, RETADDR ra, void *args, long iMethod){ const HDATA *phd; const CINFO *pci; int inx; HANDLE h; PPROCESS pprc; PCALLSTACK pcstk; PTHREAD pth; LPVOID lpvVal; register DWORD dwSig; DWORD dwVal, dwBase; ACCESSKEY akyCur; PCALLBACKINFO pcbi; PFNVOID pfn; 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 = ra; akyCur = pcstk->akyLast = pth->aky; pcstk->extra = pMode[1];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -