📄 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 + -