📄 kwin32.c
字号:
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
SC_SetHardwareWatch(
LPVOID vAddr,
DWORD flags
)
{
LPVOID pAddr = 0;
extern SetCPUHardwareWatch(LPVOID,DWORD);
TRUSTED_API ("SC_SetHardwareWatch", FALSE);
#ifdef MIPS
vAddr = MapPtrProc(vAddr, pCurProc);
pAddr = VerifyAccess(vAddr, VERIFY_KERNEL_OK|VERIFY_READ_FLAG, 0xffffffff);
SetCPUHardwareWatch(pAddr, flags);
return TRUE;
#elif x86
// Make sure this runs without preemption
vAddr = MapPtrProc(vAddr, pCurProc);
SetCPUHardwareWatch(vAddr, flags);
return TRUE;
#else
return FALSE;
#endif
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
SC_SetKMode(
BOOL newMode
)
{
PCALLSTACK pcstk;
BOOL bRet;
// Retrive the previous mode from the callstack structure because the thread is now
// in kernel mode because it is running here. Then update the callstack to switch to
// the desired mode when we return.
if (bAllKMode)
bRet = 1;
else {
TRUSTED_API (L"SC_SetKMode", FALSE);
pcstk = pCurThread->pcstkTop;
bRet = !((DWORD)pcstk->dwPrcInfo & CST_MODE_FROM_USER);
// can't set kmode to false if our base mode is kmode
if (!pcstk->pcstkNext || (pcstk->pcstkNext->dwPrcInfo & CST_MODE_TO_USER)) {
if (newMode)
pcstk->dwPrcInfo &= ~CST_MODE_FROM_USER; // to KMode --> clear the bit
else
pcstk->dwPrcInfo |= CST_MODE_FROM_USER; // to UMode --> set the bit
} else {
DEBUGCHK (bRet); // we must be in KMode here
}
}
return bRet;
}
void UpdateCallerInfo (PTHREAD pth, BOOL fInKMode);
void SwitchBack();
void InitClock(void);
PPROCESS SwitchToProcPtr(
CALLSTACK* pcstk,
PPROCESS pprc
)
{
pcstk->pprcLast = pCurProc;
pcstk->akyLast = CurAKey;
pcstk->retAddr = 0;
pcstk->dwPrevSP = 0;
pcstk->pcstkNext = pCurThread->pcstkTop;
pcstk->dwPrcInfo = 0;
pCurThread->pcstkTop = pcstk;
pCurThread->pProc = pprc;
AddAccess(&pCurThread->aky, pprc->aky);
SetCPUASID(pCurThread);
UpdateCallerInfo (pCurThread, TRUE);
return pcstk->pprcLast;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
SC_SetPowerOffHandler(
FARPROC pfn
)
{
TRUSTED_API (L"SC_SetPowerOffHandler", FALSE);
PowerKey = GETCURKEY();
PowerFunc = pfn;
PowerProc = pCurProc;
return TRUE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
SC_SetGwesPowerHandler(
FARPROC pfn
)
{
TRUSTED_API (L"SC_SetGwesPowerHandler", FALSE);
GwesPowerKey = GETCURKEY();
GwesPowerFunc = pfn;
GwesPowerProc = pCurProc;
return TRUE;
}
//------------------------------------------------------------------------------
//
// Invoke power on/off handler in the registered process space. Note that the
// current thread is used to set the access key and process address space information
// but that the thread is not actually scheduled in this state. Since a reschedule
// will always occur after a power off, it is not necessary to call SetCPUASID to
// restore the address space information when we are done.
//
//------------------------------------------------------------------------------
void CallPowerProc(
PPROCESS pprc,
FARPROC pfn,
BOOL bOff,
LPCWSTR pszMsg
)
{
if (pfn) {
CALLSTACK cstk;
RETAILMSG(1, (pszMsg));
SwitchToProcPtr (&cstk, pprc);
(*pfn)(bOff); /* set power off state */
SwitchBack ();
}
}
void CallOEMPowerOff (void)
{
INTERRUPTS_OFF ();
#if SHx
OEMCacheRangeFlush (0, 0, CACHE_SYNC_DISCARD | CACHE_SYNC_INSTRUCTIONS);
#endif
OEMPowerOff ();
#if SHx
OEMCacheRangeFlush (0, 0, CACHE_SYNC_DISCARD | CACHE_SYNC_INSTRUCTIONS);
#endif
InitClock ();
INTERRUPTS_ON ();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void SC_PowerOffSystem(void)
{
extern DWORD bLastIdle;
extern HANDLE hEvtPwrHndlr;
DWORD bPrio = GET_BPRIO(pCurThread);
DWORD dwQuantum = pCurThread->dwQuantum;
TRUSTED_API_VOID (L"SC_PowerOffSystem");
bLastIdle = 0;
SC_CeSetThreadPriority (hCurThread, 0);
SC_CeSetThreadQuantum (hCurThread, 0);
// this retail message is required to make sure no other thread holds the
// CS for debug transport.
// NOTE: must be done after we change the priority and before setting
// PowerOffFlag
RETAILMSG(1, (TEXT("Powering Off system:\r\n")));
PowerOffFlag = TRUE;
SetEvent (hEvtPwrHndlr);
/* Tell GWES and FileSys that we are turning power off */
CallPowerProc (GwesPowerProc, GwesPowerFunc, TRUE, TEXT(" Calling GWES power proc.\r\n"));
CallPowerProc (PowerProc, PowerFunc, TRUE, TEXT(" Calling device manager power proc.\r\n"));
RETAILMSG(1, (TEXT(" Calling OEMPowerOff...\r\n")));
KCall ((FARPROC) CallOEMPowerOff);
KInfoTable[KINX_TIMECHANGECOUNT] ++; // indicate time changed since tick won't run while powered off
RETAILMSG(1, (TEXT("Back from OEMPowerOff\r\n")));
/* Tell GWES and Device manager that we are turning power back on */
CallPowerProc (PowerProc, PowerFunc, FALSE, TEXT(" Calling device manager power proc.\r\n"));
CallPowerProc (GwesPowerProc, GwesPowerFunc, FALSE, TEXT(" Calling GWES power proc.\r\n"));
RETAILMSG(1, (TEXT(" Returning to normally scheduled programming.\r\n")));
// If platform supports debug Ethernet, turn interrupts back on
if (pKITLInitializeInterrupt)
pKITLInitializeInterrupt();
PowerOffFlag = FALSE;
SC_CeSetThreadQuantum (hCurThread, dwQuantum);
SC_CeSetThreadPriority (hCurThread, bPrio);
}
VOID (*pWriteDebugLED)(WORD wIndex, DWORD dwPattern);
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
VOID
SC_WriteDebugLED(
WORD wIndex,
DWORD dwPattern
)
{
if( pWriteDebugLED )
pWriteDebugLED( wIndex, dwPattern );
}
//------------------------------------------------------------------------------
// Print debug message using debug Ethernet card
//------------------------------------------------------------------------------
void
KITLWriteDebugString(
unsigned short *str
)
{
UCHAR FmtBuf[256+sizeof(KITL_DBGMSG_INFO)];
KITL_DBGMSG_INFO *pDbgInfo = (KITL_DBGMSG_INFO *)FmtBuf;
// Prepend a header so that application on the other side can get timing
// and thread info.
pDbgInfo->dwLen = sizeof(KITL_DBGMSG_INFO);
pDbgInfo->dwThreadId = (DWORD)hCurThread;
pDbgInfo->dwProcId = (DWORD)hCurProc;
pDbgInfo->dwTimeStamp = CurMSec;
KUnicodeToAscii(FmtBuf+sizeof(KITL_DBGMSG_INFO),str,256);
pKITLSend(KITL_SVC_DBGMSG, FmtBuf, sizeof(KITL_DBGMSG_INFO)+strlen(FmtBuf+sizeof(KITL_DBGMSG_INFO))+1);
}
// kernelIoctl: route it through KITL before calling OEMIoControl
BOOL KernelIoctl (DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned)
{
DWORD dwRet = ERROR_NOT_SUPPORTED;
BOOL fRet;
switch (dwIoControlCode) {
// allow non-trusted apps to get device id/info
case IOCTL_HAL_GET_CACHE_INFO:
if (sizeof (CacheInfo) != nOutBufSize) {
KSetLastError (pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
// fall through
case IOCTL_HAL_GET_DEVICE_INFO:
case IOCTL_HAL_GET_DEVICEID:
// validate parameters if caller is not fully trusted
if ((KERN_TRUST_FULL != pCurProc->bTrustLevel)
&& ((lpInBuf && !SC_MapPtrWithSize (lpInBuf, nInBufSize, hCurProc))
|| !lpOutBuf
|| !SC_MapPtrWithSize (lpOutBuf, nOutBufSize, hCurProc)
|| (lpBytesReturned && !SC_MapPtrWithSize (lpBytesReturned, sizeof (DWORD), hCurProc)))) {
KSetLastError (pCurThread, ERROR_INVALID_PARAMETER);
return FALSE;
}
break;
default:
TRUSTED_API (L"KernelIoctl", FALSE);
if (pKITLIoCtl) {
dwRet = pKITLIoCtl (dwIoControlCode, lpInBuf, nInBufSize, lpOutBuf, nOutBufSize, lpBytesReturned);
}
break;
}
if (ERROR_NOT_SUPPORTED == dwRet){
if (IOCTL_HAL_REBOOT == dwIoControlCode){
KDReboot(TRUE); // Inform kdstub we are about to reboot
}
fRet = OEMIoControl (dwIoControlCode, lpInBuf, nInBufSize, lpOutBuf, nOutBufSize, lpBytesReturned);
if (IOCTL_HAL_REBOOT == dwIoControlCode){
Sleep(1000); // Allow time for hardware to reset
KDReboot(FALSE); // Inform kdstub reboot failed
}
}
else {
fRet = (BOOL) dwRet;
}
return fRet;
}
//------------------------------------------------------------------------------
//
// Routine to start DBGMSG and PPSH KITL service.
//
//------------------------------------------------------------------------------
BOOL
SetKernelCommDev (
UCHAR Service,
UCHAR CommDevice
)
{
UCHAR *PpfsEthBuf;
// only support KERNEL_COMM_ETHER
if (KERNEL_COMM_ETHER != CommDevice) {
return FALSE;
}
switch (Service) {
case KERNEL_SVC_DBGMSG:
if (pKITLRegisterDfltClient &&
pKITLRegisterDfltClient(KITL_SVC_DBGMSG,0,NULL,NULL)) {
lpWriteDebugStringFunc = KITLWriteDebugString;
return TRUE;
}
break;
case KERNEL_SVC_PPSH:
if (pKITLRegisterDfltClient &&
pKITLRegisterDfltClient(KITL_SVC_PPSH,0,&PpfsEthBuf,&PpfsEthBuf)) {
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
void UnloadExe(PPROCESS pProc);
void UnloadMod(PMODULE pMod);
static DWORD UnloadDepends (PPROCESS pprc, DWORD dwFlags)
{
PMODULE pMod;
DWORD dwErr = 0;
EnterCriticalSection (&ModListcs);
__try {
for (pMod = pModList; pMod; pMod = pMod->pMod) {
if ((pMod->inuse & pprc->aky) // the module is loaded by the process
&& PageAble (&pMod->oe) // the module is pageable
&& ((PAGE_OUT_ALL_DEPENDENT_DLL == dwFlags) // either the flags say to page out all
|| !(pMod->inuse & ~pprc->aky))) { // or we're the only only process using this moudle
UnloadMod (pMod);
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErr = ERROR_INVALID_PARAMETER;
}
LeaveCriticalSection (&ModListcs);
return dwErr;
}
//------------------------------------------------------------------------------
// Page out a particular module
//------------------------------------------------------------------------------
static BOOL SC_PageOutModule (HANDLE hModule, DWORD dwFlags)
{
PPROCESS pprc = NULL;
PMODULE pMod = NULL;
DWORD dwErr = 0;
ACCESSKEY oldaky;
TRUSTED_API (L"SC_PageOutModule", FALSE);
EnterCriticalSection (&PageOutCS); // criticalsection ordering require pageoutCS to
EnterCriticalSection (&LLcs); // be held before Loader CS
switch (dwFlags) {
case PAGE_OUT_PROCESS_ONLY:
case PAGE_OUT_DLL_USED_ONLY_BY_THISPROC:
case PAGE_OUT_ALL_DEPENDENT_DLL:
if (!hModule
|| (hModule == ProcArray[0].hProc) // cannot page out NK
|| (GetCurrentProcess() == hModule) // page out current process - not a good idea
|| (hCurProc == hModule)
|| (!(pprc = HandleToProc (hModule)) // has to be valid process
&& !IsValidModule (pMod = (PMODULE) hModule))) { // or a valid module
dwErr = ERROR_INVALID_HANDLE;
break;
}
SWITCHKEY (oldaky, 0xFFFFFFFF);
__try {
if (pprc) {
// paging out a process
UnloadExe (pprc);
// pageout dependent modules based on flags
if (PAGE_OUT_PROCESS_ONLY != dwFlags)
dwErr = UnloadDepends (pprc, dwFlags);
} else if (PageAble (&pMod->oe)) {
UnloadMod (pMod);
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
dwErr = ERROR_INVALID_PARAMETER;
}
SETCURKEY (oldaky);
break;
default:
dwErr = ERROR_INVALID_PARAMETER;
}
LeaveCriticalSection (&LLcs);
LeaveCriticalSection (&PageOutCS);
if (dwErr)
KSetLastError (pCurThread, dwErr);
return !dwErr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -