📄 objdisp.c
字号:
CurAKey = pth->aky; // MIPS: CurAkey is used in TLB miss handler instead of pCurThread->aky
pfn = GetPSLPfnAndValidateArgs (pci, iMethod, args);
}
/* Save previous process */
pcstk->pprcLast = pth->pProc;
/* setup thread structure for method call */
pth->pProc = pprc;
SetCPUASID(pth); /* switch to server's address space */
UpdateCallerInfo(pth, TRUE);
DEBUGMSG(ZONE_OBJDISP, (TEXT("PSLDispatch: pci %8.8lx, fnptr %8.8lx\r\n"),
pci, pci->ppfnMethods[iMethod]));
#ifdef NKPROF
if (g_dwProfilerFlags & PROFILE_OBJCALL)
ProfilerHit(pci->ppfnMethods[iMethod]);
#endif
return pfn;
default:
DEBUGMSG(ZONE_OBJDISP, (TEXT("ObjectCall: invalid dispatch type\r\n")));
DEBUGCHK(0);
break;
}
RaiseException(STATUS_INVALID_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, 0);
DEBUGCHK (0);
return 0; // keep compiler happy
}
#pragma prefast(pop)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
SC_CeMapArgumentArray(
HANDLE hProc,
LPVOID *pArgList,
DWORD dwSig
)
{
DWORD dwVal;
PPROCESS pproc;
TRUSTED_API (L"SC_CeMapArgumentArray", FALSE);
pproc = HandleToProc(hProc);
if (!pproc) {
KSetLastError(pCurThread, ERROR_INVALID_HANDLE);
return 0;
}
while (dwSig) {
if ((dwSig & ARG_TYPE_MASK) == ARG_PTR) {
dwVal = (DWORD)*pArgList;
if (!(dwVal>>VA_SECTION) && (dwVal >= 0x10000)) {
*pArgList = (LPVOID)(dwVal + pproc->dwVMBase);
}
}
pArgList++;
dwSig >>= ARG_TYPE_BITS;
}
return 1;
}
void SuspendSelf (void)
{
KCALLPROFON (64);
DEBUGCHK (!pCurThread->bSuspendCnt);
// we need to check the bit again because it might be
// cleared before we enter KCall
if (pCurThread->bPendSusp) {
pCurThread->bSuspendCnt = pCurThread->bPendSusp;
pCurThread->bPendSusp = 0;
SET_RUNSTATE (pCurThread, RUNSTATE_BLOCKED);
SET_USERBLOCK (pCurThread); // okay to terminate the thread
RunList.pth = 0;
SetReschedule ();
}
KCALLPROFOFF (64);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SC_KillThreadIfNeeded()
{
/* The check for bPendSusp is kind of redundent here. However, we don't want to
make a KCall unless it's remotely needed. Thus the check */
if ((LLcs.OwnerThread != hCurThread) && (pCurProc == pCurThread->pOwnerProc)) {
if (pCurThread->bPendSusp && (!GET_DYING(pCurThread) || GET_DEAD(pCurThread))) {
// suspend ourself
DEBUGCHK (LLcs.OwnerThread != hCurThread);
KCall ((FARPROC) SuspendSelf);
CLEAR_USERBLOCK (pCurThread);
}
// check if we are being terminated.
if (GET_DYING(pCurThread) && !GET_DEAD(pCurThread)) {
SET_DEAD(pCurThread);
CLEAR_USERBLOCK(pCurThread);
CLEAR_DEBUGWAIT(pCurThread);
(*(void (*)(int))pExitThread)(0);
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
RETADDR ServerCallReturn (PSVRRTNSTRUCT psrs)
{
PPROCESS pprc;
PCALLSTACK pcstk;
RETADDR ra;
BOOL fWasInKernel;
extern LPVOID pExitThread;
DEBUGMSG (ZONE_OBJDISP, (L"SCR: psrs = %8.8lx\n", psrs));
pcstk = pCurThread->pcstkTop;
pprc = pcstk->pprcLast;
psrs->prevSP = pcstk->dwPrevSP;
ra = pcstk->retAddr;
psrs->linkage = pcstk->extra;
psrs->mode = (pcstk->dwPrcInfo & CST_MODE_FROM_USER)? USER_MODE : KERNEL_MODE;
pCurThread->aky = pcstk->akyLast;
pCurThread->pProc = pprc;
fWasInKernel = pcstk->dwPrcInfo & CST_IN_KERNEL;
if (pcstk == &pCurThread->IntrStk) {
pCurThread->pcstkTop = pcstk->pcstkNext;
} else {
/* unlink CALLSTACK structure from list */
pCurThread->pcstkTop = pcstk->pcstkNext;
if (IsValidKPtr(pcstk))
FreeMem(pcstk,HEAP_CALLSTACK);
/* The check for bPendSusp is kind of redundent here. However, we don't want to
make a KCall unless it's remotely needed. Thus the check */
if (pCurThread->bPendSusp
&& !((DWORD)ra & 0x80000000)
&& (!pCurThread->pcstkTop
|| (pprc == pCurThread->pOwnerProc)
|| (fWasInKernel && (pCurThread->pOwnerProc == pCurThread->pProc)))) {
// suspend ourself
DEBUGCHK (LLcs.OwnerThread != hCurThread);
KCall ((FARPROC) SuspendSelf);
CLEAR_USERBLOCK (pCurThread);
}
if (GET_DYING(pCurThread) && !GET_DEAD(pCurThread)
&& (LLcs.OwnerThread != hCurThread)
&& !((DWORD)ra & 0x80000000)
&& (!pCurThread->pcstkTop
|| (pprc == pCurThread->pOwnerProc)
|| (fWasInKernel && (pCurThread->pOwnerProc == pCurThread->pProc)))) {
SET_DEAD(pCurThread);
CLEAR_USERBLOCK(pCurThread);
CLEAR_DEBUGWAIT(pCurThread);
ra = (RETADDR)pExitThread;
}
DEBUGMSG(ZONE_OBJDISP, (TEXT("SCRet: return to %8.8lx Proc=%lx aky=%lx, mode = %8.8lx\r\n"),
ra, pprc, pCurThread->aky, psrs->mode));
if (!fWasInKernel) {
/* Returning from a user mode server, restore the previous
* address space information and return.
*/
SetCPUASID(pCurThread);
} else {
/*
* must do this or SetProcPermissions won't work on MIPS
*/
CurAKey = pCurThread->aky;
}
}
if (fWasInKernel) {
// GoToUserTime();
}
UpdateCallerInfo(pCurThread, KERNEL_MODE == psrs->mode);
DEBUGMSG(ZONE_OBJDISP, (TEXT("SCRet: Before return psrs->mode = %x, psrs->prevSP = %8.8lx\n"),
psrs->mode, psrs->prevSP));
return ra;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
RETADDR PerformCallBackExt (POBJCALLSTRUCT pobs)
{
CALLSTACK *pcstk;
PPROCESS pProc;
PTHREAD pth = pCurThread;
DWORD currSP = pobs->prevSP;
DWORD akyLast = pth->aky;
PCALLBACKINFO pcbi = Arg(pobs->args, PCALLBACKINFO);
#ifdef MIPS
DEBUGCHK (!((DWORD) pobs->args & (sizeof (REG_TYPE) -1)));
#endif
DEBUGMSG(ZONE_OBJDISP, (TEXT("PerformCallBackExt: obs = %8.8lx, ra=%8.8lx mode=%x extra=%8.8lx, prevSP = %8.8lx\r\n"),
pobs, pobs->ra, pobs->mode, pobs->linkage, pobs->prevSP));
if (!(pProc = HandleToProc(pcbi->hProc))
|| (!((DWORD) pobs->ra & 0x80000000) && (KERN_TRUST_FULL != pth->pProc->bTrustLevel))) {
RaiseException(STATUS_INVALID_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, 0);
DEBUGCHK (0);
}
pobs->mode = KERNEL_MODE; // default is kernel mode
pobs->prevSP = 0; // default no stack switch
if (pProc != &ProcArray[0]) {
for (pcstk = pCurThread->pcstkTop; pcstk && (pcstk->pprcLast != pProc); pcstk = (PCALLSTACK)((ulong)pcstk->pcstkNext&~1))
;
if (pcstk) {
pth->aky = pcstk->akyLast;
// only switch stack when calling back to user mode process
if (pcstk->dwPrcInfo & CST_MODE_FROM_USER) {
pobs->mode = USER_MODE;
pobs->prevSP = pcstk->dwPrevSP;
}
} else if (bAllKMode || ((DWORD) pcbi->pfn & 0x80000000)) {
DEBUGCHK (KERN_TRUST_FULL == pProc->bTrustLevel);
pth->aky = pth->pOwnerProc->aky;
AddAccess(&pth->aky, ProcArray[0].aky);
AddAccess(&pth->aky, pProc->aky);
} else {
#define SECURE_WORKAROUND
#ifdef SECURE_WORKAROUND
RETAILMSG (1, (L"!!!! Work around Security violation (call forward), pth = %8.8lx, proc = '%s' !!!!\n",
pth, pCurProc->lpszProcName));
pth->aky = pth->pOwnerProc->aky;
AddAccess(&pth->aky, ProcArray[0].aky);
AddAccess(&pth->aky, pProc->aky);
#else
// SECURITY VIOLATION: callback originalted from PSL, into a non-trusted process
RaiseException(STATUS_INVALID_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, 0);
DEBUGCHK (0);
#endif
}
}
// allocate new callstack
// If this fails, we'll fault on setting the pprcLast - but we'd only raise an exception if we
// were checking, anyway.
pcstk = AllocMem(HEAP_CALLSTACK);
pcstk->pprcLast = pth->pProc;
pth->pProc = pProc;
pcstk->akyLast = akyLast;
pcstk->retAddr = pobs->ra;
pcstk->extra = pobs->linkage;
pcstk->pcstkNext = pth->pcstkTop;
pcstk->dwPrevSP = pobs->prevSP? (currSP-CALLEE_SAVED_REGS) : 0;
pcstk->dwPrcInfo = CST_CALLBACK | ((USER_MODE == pobs->mode)? CST_MODE_TO_USER : 0);
pth->pcstkTop = pcstk;
SetCPUASID (pth);
UpdateCallerInfo(pCurThread, KERNEL_MODE == pobs->mode);
DEBUGMSG (ZONE_OBJDISP, (L"Calling callback function %8.8lx tls = %8.8lx, tlsNonSec = %8.8lx, tlsSec = %8.8lx, dwPrevSP = %8.8lx\n",
ZeroPtr (pcbi->pfn), pth->tlsPtr, pth->tlsNonSecure, pth->tlsSecure, pobs->prevSP));
randdw1 = ((randdw1<<5) | (randdw1>>27)) ^ (CurMSec & 0x1f);
// mark return address as syscall_retrun
pobs->ra = (RETADDR) SYSCALL_RETURN;
// replace arg0 with real arg0
WriteArg(pobs->args, DWORD, (DWORD) pcbi->pvArg0);
return (RETADDR) ZeroPtr (pcbi->pfn);
}
RETADDR CallbackReturn (LPDWORD pLinkage)
{
PCALLSTACK pcstk;
RETADDR ra;
PPROCESS pProc;
ACCESSKEY aky;
DEBUGMSG (ZONE_OBJDISP, (L"CallbackReturn: pLinkage = %8.8lx\n", pLinkage));
pcstk = pCurThread->pcstkTop;
DEBUGCHK (pcstk);
pCurThread->pcstkTop = pcstk->pcstkNext;
pProc = pcstk->pprcLast;
// if pcstk->akyLast is 0, it's an exception handler's record
if (aky = pcstk->akyLast) {
pCurThread->aky = aky;
} else {
// we'll only setup the callstak if calling into user-mode handler
// update the TLS record
KTHRDINFO (pCurThread) &= ~UTLS_INKMODE;
}
*pLinkage = pcstk->extra;
ra = pcstk->retAddr;
DEBUGCHK ((pcstk->dwPrcInfo & CST_CALLBACK) && !(pcstk->dwPrcInfo & CST_MODE_FROM_USER));
pCurThread->pProc = pProc;
if (IsValidKPtr(pcstk))
FreeMem (pcstk,HEAP_CALLSTACK);
if (aky) {
if (pProc != &ProcArray[0]) {
SetCPUASID(pCurThread);
}
UpdateCallerInfo (pCurThread, TRUE);
}
DEBUGMSG(ZONE_OBJDISP,
(TEXT("CBRet: return to %8.8lx Proc=%lx aky=%lx, *pLinkage = %d\n"),
ra, pCurThread->pProc, pCurThread->aky, *pLinkage));
return ra;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
PFNVOID
DBG_CallCheck(
PTHREAD pth,
DWORD dwJumpAddress,
PCONTEXT pCtx
)
{
register const HDATA *phd;
register const CINFO *pci;
register int inx;
register long iMethod;
HANDLE h;
#if defined (MIPS)
h = (HANDLE)pCtx->IntA0;
if ((dwJumpAddress & 3) != 2 || dwJumpAddress
< IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
return 0;
iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 2;
#elif defined (SHx)
h = (HANDLE)pCtx->R4;
if (!(dwJumpAddress & 1) || dwJumpAddress
< IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
return 0;
iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 1;
#elif defined (x86)
h = *(HANDLE*)(pCtx->Esp);
if ((dwJumpAddress & 1) || dwJumpAddress
< IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
return 0;
iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 1;
#elif defined (ARM)
h = (HANDLE)pCtx->R0;
if ((dwJumpAddress & 3) || dwJumpAddress
< IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
return 0;
iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 2;
#else
#error("Unknown CPU")
#endif
DEBUGMSG(ZONE_OBJDISP, (TEXT("CallCheck: pth %8.8lx, h %8.8lx, iMethod %lx\r\n"),
pth, h, iMethod));
inx = NUM_SYS_HANDLES;
if (iMethod < 0) {
/* API call to an implicit handle. In this case, bits 30-16 of the
* method index indicate which entry in the system handle table.
*/
iMethod = -iMethod;
if ((inx = iMethod>>HANDLE_SHIFT & HANDLE_MASK) >= NUM_SYS_HANDLES
|| (pci = SystemAPISets[inx]) == 0)
return 0;
iMethod &= METHOD_MASK;
#ifdef SECURE_WORKAROUND
// special case for PerformCallBack(113) and PerformCallForward(149)
if (!inx && ((iMethod == 113) || (iMethod == 149))) {
// Lookup the function being called from the PCALLBACKINFO parameter in
// arg0, a.k.a. "h" from above. Set a breakpoint on the target of the
// callback instead of SC_CallForward
PCALLBACKINFO pcbInfo;
PPROCESS pproc;
if ((pcbInfo = (PCALLBACKINFO)DbgVerify (h, FALSE, NULL)) &&
(pproc = HandleToProc(pcbInfo->hProc))) {
return MapPtrProc(pcbInfo->pfn, pproc);
}
}
#endif
inx = pci->type;
}
if (inx) {
/* validate handle argument and turn into HDATA pointer. */
h2p (h, phd);
if (!phd)
return 0;
pci = phd->pci;
}
/* validate interface and method indicies. */
if (iMethod >= pci->cMethods)
return 0;
/* Dispatch api call based upon the dispatch type in the cinfo struct. */
switch (pci->disp) {
case DISPATCH_KERNEL:
case DISPATCH_I_KERNEL:
case DISPATCH_KERNEL_PSL:
case DISPATCH_I_KPSL:
DEBUGMSG(ZONE_OBJDISP,
(TEXT("CallCheck: %8.8lx '%.4a' API call #%d. pfn=%8.8lx.\r\n"),
pci, pci->acName, iMethod, pci->ppfnMethods[iMethod]));
return pci->ppfnMethods[iMethod];
case DISPATCH_PSL:
case DISPATCH_I_PSL:
{
PFNVOID *ppfn;
PFNVOID pfn;
ppfn = (PFNVOID*)MapPtrProc(pci->ppfnMethods, pci->pServer);
pfn = (PFNVOID)MapPtrProc(ppfn[iMethod], pci->pServer);
DEBUGMSG(ZONE_OBJDISP,
(TEXT("CallCheck: %8.8lx '%.4a' API call #%d. pfn=%8.8lx.\r\n"),
pci, pci->acName, iMethod, pfn));
return pfn;
}
default:
break;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -