⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 objdisp.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* 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 + -