📄 objdisp.c
字号:
/* Save previous kernel/user mode info */
pcstk->pprcLast = (HANDLE)*pMode;
/* Link the CALLSTACK struct at the head of the thread's list */
pcstk->pcstkNext = pth->pcstkTop;
pth->pcstkTop = pcstk;
DEBUGMSG(ZONE_OBJDISP, (TEXT("ObjectCall: ra=%8.8lx h=%8.8lx iMethod=%lx mode=%x extra=%8.8lx\r\n"),
ra, Arg(args, HANDLE), iMethod, pMode[0], pMode[1]));
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) {
DEBUGMSG(1, (TEXT("ObjectCall: Failed(1): %lx\r\n"), inx));
RaiseException(STATUS_INVALID_SYSTEM_SERVICE, EXCEPTION_NONCONTINUABLE,
1, &iMethod);
DEBUGCHK(0); /* shouldn't get here */
}
iMethod &= METHOD_MASK;
DEBUGCHK(pci->type == 0 || pci->type == inx);
inx = pci->type;
}
/* For handle based api calls, validate the handle argument. */
if (inx) {
/* validate handle argument and turn into HDATA pointer. */
h = Arg(args, HANDLE);
h2p(h, phd);
if (!phd || !TestAccess(&phd->lock, &pth->aky)) {
if (iMethod <= 1) {
DEBUGMSG(1, (TEXT("CloseHandle/WaitForSingleObject: invalid handle h=%x\r\n"),
Arg(args, HANDLE)));
KSetLastError(pth, ERROR_INVALID_HANDLE);
pcstk->akyLast = (ACCESSKEY)(iMethod==0 ? 0 : WAIT_FAILED);
/* Continue the thread in kernel mode */
*pMode = KERNEL_MODE;
return (PFNVOID)ErrorReturn;
}
DEBUGMSG(1, (TEXT("ObjectCall: Failed (2): h=%x\r\n"), Arg(args, HANDLE)));
pcstk->akyLast = (ACCESSKEY)SetBadHandleError(inx, iMethod);
/* Continue the thread in kernel mode */
*pMode = KERNEL_MODE;
return (PFNVOID)ErrorReturn;
}
pci = phd->pci;
if (pci->type != inx && (inx != NUM_SYS_HANDLES || iMethod > 1)) {
// The handle is valid but the type is wrong.
DEBUGMSG(1, (TEXT("ObjectCall: Failed(2a): h=%x t=%d shdb %d\r\n"),
Arg(args, HANDLE), pci->type, inx));
pcstk->akyLast = (ACCESSKEY)SetBadHandleError(inx, iMethod);
/* Continue the thread in kernel mode */
*pMode = KERNEL_MODE;
return (PFNVOID)ErrorReturn;
}
}
/* validate interface and method indicies. */
DEBUGMSG(ZONE_OBJDISP,
(TEXT("ObjectCall: %8.8lx '%.4a' API call #%d. disp=%d.\r\n"),
pci, pci->acName, iMethod, pci->disp));
if (iMethod >= pci->cMethods) {
DEBUGMSG(1,(TEXT("ObjectCall: Failed (3): %d %d\r\n"),
iMethod, pci->cMethods));
RaiseException(STATUS_INVALID_SYSTEM_SERVICE, EXCEPTION_NONCONTINUABLE, 1, &iMethod);
DEBUGCHK(0); /* shouldn't get here */
}
/* Dispatch api call based upon the dispatch type in the cinfo struct. */
switch (pci->disp) {
case DISPATCH_KERNEL_PSL:
case DISPATCH_I_KPSL:
pfn = pci->ppfnMethods[iMethod];
if ((pfn == (PFNVOID)-1) || (pfn == (PFNVOID)-2)) {
/* PerformCallBack() or PerformCallForward() kernel API call.
* Save the previous process and scan the CALLSTACKs to find
* the new access key to use.
*/
pcbi = Arg(args, PCALLBACKINFO);
DEBUGMSG(ZONE_OBJDISP,(TEXT("CallBack: info=%8.8lx, pfn=%8.8lx\r\n"), pcbi, pcbi->pfn));
Arg(args, LPVOID) = pcbi->pvArg0;
pfn = (PFNVOID)pcbi->pfn;
pfn = (PFNVOID)ZeroPtr(pfn);
h = pcbi->hProc;
h2p(h, phd);
if (!phd || !phd->pci || (phd->pci->type != SH_CURPROC) || !(pprc = phd->pvObj) ||
((pCurProc->bTrustLevel != KERN_TRUST_FULL) && !((DWORD)pcstk->retAddr & 0x80000000))) {
/* Bogus process handle. Raise an "invalid parameter" exception. */
ERRORMSG(phd && phd->pci && (phd->pci->type == SH_CURPROC) && phd->pvObj,(L"PerformCallback failed due to insufficient trust\r\n"));
RaiseException(STATUS_INVALID_PARAMETER, EXCEPTION_NONCONTINUABLE, 0, 0);
DEBUGCHK(0); /* shouldn't get here */
}
/* Save previous process */
pcstk->pprcLast = pth->pProc;
/* Scan the CALLSTACKs to find the new access key to use. */
if ((pci->ppfnMethods[iMethod] == (PFNVOID)-1) && (pcbi->hProc != ProcArray[0].hProc)) {
while (((pcstk = (PCALLSTACK)((ulong)pcstk->pcstkNext&~1)) != 0) && (pcstk->pprcLast != pprc))
;
if (pcstk)
pth->aky = pcstk->akyLast;
else {
/* The thread must always have the permissions of its owner process
* so that it can access its stack, as well as the kernel and the
* destination process. */
pth->aky = pth->pOwnerProc->aky;
AddAccess(&pth->aky, ProcArray[0].aky);
AddAccess(&pth->aky, pprc->aky);
}
}
/* Switch to the new process */
pth->pProc = pprc;
SetCPUASID(pth); /* switch to callback process's address space */
} else {
/* Continue the thread in kernel mode */
GoToKernTime();
*pMode = KERNEL_MODE;
}
DEBUGMSG(ZONE_OBJDISP, (TEXT("KPSLDispatch: pci %8.8lx, fnptr %8.8lx\r\n"),
pci, pfn));
#ifdef XTIME
if (iMethod >= 2 && iMethod <= XT_NUM_PSL+2)
SyscallTime(iMethod+XT_FIRST_PSL-2);
#endif
#ifdef NKPROF
if (bProfileObjCall)
ProfilerHit(pfn);
#endif
return pfn;
case DISPATCH_PSL:
lpvVal = phd->pvObj;
if (iMethod == 0) {
/* Closing this handle, decrement the reference count */
if (!TestAccess(&phd->lock, &pCurProc->aky)) {
if ((phd->lock == 1) && (phd->ref.count == 1)) {
pcstk->akyLast = TryCloseMappedHandle(h);
*pMode = KERNEL_MODE;
return (PFNVOID)ErrorReturn;
}
KSetLastError(pth, ERROR_INVALID_HANDLE);
pcstk->akyLast = 0;
*pMode = KERNEL_MODE;
return (PFNVOID)ErrorReturn;
}
DEBUGMSG(ZONE_OBJDISP, (TEXT("PSLDispatch: closing=%8.8lx\r\n"),
Arg(args, HANDLE)));
if (DecRef(Arg(args, HANDLE), pCurProc, FALSE))
FreeHandle(Arg(args,HANDLE));
}
Arg(args, LPVOID) = lpvVal;
DEBUGMSG(ZONE_OBJDISP,(TEXT("PSLDispatch: info=%8.8lx\r\n"), phd->pvObj));
case DISPATCH_I_PSL:
/* Save previous process */
pcstk->pprcLast = pth->pProc;
dwBase = pth->pProc->dwVMBase;
/* setup thread structure for method call */
pth->pProc = pprc = pci->pServer;
AddAccess(&pth->aky, pprc->aky);
SetCPUASID(pth); /* switch to server's address space */
for (dwSig = pci->pdwSig[iMethod] ; dwSig ; dwSig >>= ARG_TYPE_BITS) {
if ((dwSig & ARG_TYPE_MASK) == ARG_PTR) {
dwVal = Arg(args, DWORD);
if (!(dwVal>>VA_SECTION) && (dwVal >= 0x10000))
Arg(args, DWORD) = dwVal + dwBase;
}
NextArg(args, DWORD);
}
DEBUGMSG(ZONE_OBJDISP, (TEXT("PSLDispatch: pci %8.8lx, fnptr %8.8lx\r\n"),
pci, pci->ppfnMethods[iMethod]));
#ifdef NKPROF
if (bProfileObjCall)
ProfilerHit(pci->ppfnMethods[iMethod]);
#endif
return pci->ppfnMethods[iMethod];
default:
DEBUGMSG(ZONE_OBJDISP, (TEXT("ObjectCall: invalid dispatch type\r\n")));
DEBUGCHK(0);
break;
}
#ifdef NKPROF
if (bProfileObjCall)
ProfilerHit(ra);
#endif
return ra;
}
BOOL SC_CeMapArgumentArray(HANDLE hProc, LPVOID *pArgList, DWORD dwSig) {
DWORD dwVal;
PPROCESS pproc;
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 SC_KillThreadIfNeeded() {
if (GET_DYING(pCurThread) && !GET_DEAD(pCurThread) && (LLcs.OwnerThread != hCurThread) && (pCurProc == pCurThread->pOwnerProc)) {
SET_DEAD(pCurThread);
CLEAR_USERBLOCK(pCurThread);
CLEAR_DEBUGWAIT(pCurThread);
(*(void (*)(int))pExitThread)(0);
}
}
RETADDR ServerCallReturn(int *pMode) {
PPROCESS pprc;
PCALLSTACK pcstk;
RETADDR ra;
ACCESSKEY aky;
extern LPVOID pExitThread;
pcstk = pCurThread->pcstkTop;
pprc = pcstk->pprcLast;
ra = pcstk->retAddr;
pMode[1] = pcstk->extra;
if (pcstk == &pCurThread->IntrStk) {
pCurThread->pcstkTop = pcstk->pcstkNext;
*pMode = (int)pprc;
GoToUserTime();
} else {
aky = pcstk->akyLast;
/* unlink CALLSTACK structure from list */
pCurThread->pcstkTop = pcstk->pcstkNext;
if (IsValidKPtr(pcstk))
FreeMem(pcstk,HEAP_CALLSTACK);
if (GET_DYING(pCurThread) && !GET_DEAD(pCurThread) && (LLcs.OwnerThread != hCurThread) &&
!((DWORD)ra & 0x80000000) &&
(!pCurThread->pcstkTop || (pprc == pCurThread->pOwnerProc) ||
(((DWORD)pprc < 0x10000) && (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\r\n"),ra, pprc, pCurThread->aky));
if ((ulong)pprc < 0x10000) {
/* This call is returning from kernel mode server. Restore
* the thread's previous operating mode and return.
*/
*pMode = (int)pprc;
GoToUserTime();
} else {
/* Returning from a user mode server, restore the previous
* address space information and return.
*/
pCurThread->aky = aky;
pCurThread->pProc = pprc;
SetCPUASID(pCurThread);
}
}
return ra;
}
PFNVOID DBG_CallCheck(PTHREAD pth, DWORD dwJumpAddress) {
register const HDATA *phd;
register const CINFO *pci;
register int inx;
register long iMethod;
HANDLE h;
#if R3000 || R4000
h = (HANDLE)pth->ARG0;
if ((dwJumpAddress & 3) == 2 || dwJumpAddress
< IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
return 0;
iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 2;
#elif SHx
h = (HANDLE)pth->ARG0;
if (!(dwJumpAddress & 1) || dwJumpAddress
< IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
return 0;
iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 1;
#elif x86
h = *(HANDLE*)(pth->ctx.TcxEsp+4);
if ((dwJumpAddress & 1) || dwJumpAddress
< IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
return 0;
iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 1;
#elif PPC
h = (HANDLE)pth->ARG0;
if ((dwJumpAddress & 3) || dwJumpAddress
< IMPLICIT_CALL(HANDLE_MASK, METHOD_MASK))
return 0;
iMethod = (long)(dwJumpAddress - FIRST_METHOD) >> 2;
#elif ARM
h = (HANDLE)pth->ARG0;
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));
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;
} else {
/* validate handle argument and turn into HDATA pointer. */
if ((phd = HandleToPointer(h)) == 0)
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:
{
DWORD vmBase;
PFNVOID *ppfn;
PFNVOID pfn;
vmBase = pci->pServer->dwVMBase;
ppfn = (PFNVOID*)((DWORD)pci->ppfnMethods | vmBase);
pfn = (PFNVOID)((DWORD)ppfn[iMethod] | vmBase);
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 + -