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

📄 platform.cpp

📁 此代码为WCE5.0下电源管理的源代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            } else {
                gdwStateTimeLeft = gdwBattTimeoutToUserIdle;
            }
        }
        break;
    case UserIdle:
        pszNewState = _T("useridle");
        if(fChangingActivityStates) {
            if(fOnACPower) {
                gdwStateTimeLeft = gdwACTimeoutToSystemIdle;
            } else {
                gdwStateTimeLeft = gdwBattTimeoutToSystemIdle;
            }
        }
        break;
    case SystemActive:
        pszNewState = _T("systemidle");
        gdwStateTimeLeft = INFINITE;
        break;
    case SystemInactive:
        pszNewState = _T("systemidle");
        if(fOnACPower) {
            gdwStateTimeLeft = gdwACTimeoutToSuspend;
        } else {
            gdwStateTimeLeft = gdwBattTimeoutToSuspend;
        }
        break;
    case Suspend:
        pszNewState = _T("suspend");
        gdwStateTimeLeft = INFINITE;
        break;
    }

    // update elapsed time
    if(!fChangingActivityStates && gdwStateTimeLeft != INFINITE) {
        if(gdwStateTimeLeft > dwElapsedTime) {
            gdwStateTimeLeft -= dwElapsedTime;
        } else {
            gdwStateTimeLeft = 0;
        }
    }
    
    // are we changing states or forcing an update?
    PMLOGMSG(ZONE_PLATFORM && fChangingActivityStates,
        (_T("%s: entering activity state '%s', state time left %d\r\n"), pszFname,
        gActivityState == UserActive ? _T("UserActive") :
        gActivityState == UserInactive ? _T("UserInactive") :
        gActivityState == UserIdle ? _T("UserIdle") :
        gActivityState == SystemActive ? _T("SystemActive") :
        gActivityState == SystemInactive ? _T("SystemInactive") :
        gActivityState == Suspend ? _T("Suspend") : _T("<UNKNOWN>"), gdwStateTimeLeft));
    if(dwElapsedTime == INFINITE 
    || gpSystemPowerState == NULL
    || _tcscmp(pszNewState, gpSystemPowerState->pszName) != 0) {
        PMLOGMSG(ZONE_PLATFORM, (_T("%s: %supdate from activity state %d to activity state %d\r\n"),
            pszFname, dwElapsedTime == INFINITE ? _T("forced ") : _T(""),
            gActivityState, asNew));
    } else {
        // no update necessary
        pszNewState = NULL;
    }

    PMUNLOCK();

    // update the system power state if necessary
    if(pszNewState != NULL) {
        PmSetSystemPowerState_I(pszNewState, 0, 0, TRUE);
    }

    return gdwStateTimeLeft;
}

// This routine reads and verifies system power state information from
// the registry, then updates all devices appropriately.  The caller of this
// routine should hold the system power state critical section.  The fInternal
// flag indicates whether the call originated within the PM or outside it.
EXTERN_C DWORD WINAPI
PlatformSetSystemPowerState(LPCTSTR pszName, BOOL fForce, BOOL fInternal)
{
    DWORD dwStatus = ERROR_SUCCESS;
    PSYSTEM_POWER_STATE pNewSystemPowerState = NULL;
    PDEVICE_POWER_RESTRICTION pNewCeilingDx = NULL;
    BOOL fDoTransition = FALSE;
    INT iPreSuspendPriority = 0;
    static BOOL fFirstCall = TRUE;
    SETFNAME(_T("PlatformSetSystemPowerState"));
    
    // read system power state variables and construct new lists
    if (gfFileSystemsAvailable)
        PmUpdateSystemPowerStatesIfChanged();
    dwStatus = RegReadSystemPowerState(pszName, &pNewSystemPowerState, &pNewCeilingDx);
    
    // did we get registry information about the new power state?			
    if(dwStatus == ERROR_SUCCESS) {
        BOOL fSuspendSystem = FALSE;
        BOOL fWantStartupScreen = FALSE;
        DWORD dwNewStateFlags = pNewSystemPowerState->dwFlags;
        BOOL  fPasswordOn = ((dwNewStateFlags & POWER_STATE_PASSWORD)!=0) ;
        
        // assume we will update the system power state
        fDoTransition = TRUE;
        
        // Are we going to suspend the system as a whole?
        if((dwNewStateFlags & (POWER_STATE_SUSPEND | POWER_STATE_OFF | POWER_STATE_CRITICAL | POWER_STATE_RESET)) != 0) {
            fSuspendSystem = TRUE;
        }
        
        // A "critical" suspend might mean we have totally lost battery power and need
        // to suspend really quickly.  Depending on the platform, OEMs may be able
        // to bypass driver notification entirely and rely on xxx_PowerDown() notifications
        // to suspend gracefully.  Or they may be able to implement a critical suspend
        // kernel ioctl.  This sample implementation is very generic and simply sets the 
        // POWER_FORCE flag, which is not used.
        if(dwNewStateFlags & (POWER_STATE_CRITICAL | POWER_STATE_OFF | POWER_STATE_RESET)) {
            fForce = TRUE;
        }
        
        // should we allow the transition?
        if(gfActiveManagement && !fInternal && !fSuspendSystem) {
            // We are actively managing system power, the request update request came
            // from outside the PM, and the request is not to suspend the system.  
            // Only permit this update if it is to set the system power state to its
            // current value (for example, to refresh its settings from the registry).
            PMLOCK();
            if(gpSystemPowerState != NULL
                && _tcscmp(gpSystemPowerState->pszName, pNewSystemPowerState->pszName) != 0) {
                fDoTransition = FALSE;
                dwStatus = ERROR_ACCESS_DENIED;
            }
            PMUNLOCK();
        }
        
        // if everything seems ok, do the set operation
        if(fDoTransition) {
            POWER_BROADCAST_BUFFER pbb;
            PDEVICE_LIST pdl;
            BOOL fResumeSystem = FALSE;
            
            // send out system power state change notifications
            pbb.Message = PBT_TRANSITION;
            pbb.Flags = pNewSystemPowerState->dwFlags;
            pbb.Length = _tcslen(pNewSystemPowerState->pszName) + 1; // char count not byte count for now
            if(pbb.Length > MAX_PATH) {
                // truncate the system power state name -- note, we actually have MAX_PATH + 1
                // characters available.
                pbb.Length = MAX_PATH;
            }
            _tcsncpy(pbb.SystemPowerState, pNewSystemPowerState->pszName, pbb.Length);
            pbb.Length *= sizeof(pbb.SystemPowerState[0]);      // convert to byte count
            GenerateNotifications((PPOWER_BROADCAST) &pbb);
            
            // are we suspending?
            if(fSuspendSystem && gpfnGwesPowerDown != NULL) {
                // is GWES ready?
                if(!gfGwesReady) {
                    DEBUGCHK(ghevGwesReady != NULL);
                    if(WaitForSingleObject(ghevGwesReady, 0) == WAIT_OBJECT_0) {
                        gfGwesReady = TRUE;
                        CloseHandle(ghevGwesReady);
                        ghevGwesReady = NULL;
                    }
                }
                
                // Start the process of suspending GWES
                if(gfGwesReady) {
                    fWantStartupScreen = gpfnGwesPowerDown();
                }
            }
            
            // update global system state variables
            PMLOCK();
            PSYSTEM_POWER_STATE pOldSystemPowerState = gpSystemPowerState;
            PDEVICE_POWER_RESTRICTION pOldCeilingDx = gpCeilingDx;
            if(gpSystemPowerState != NULL
                && (gpSystemPowerState->dwFlags & (POWER_STATE_SUSPEND | POWER_STATE_OFF | POWER_STATE_CRITICAL)) != 0) {
                // we are exiting a suspended state
                fResumeSystem = TRUE;
            }
            gpSystemPowerState = pNewSystemPowerState;
            gpCeilingDx = pNewCeilingDx;
            PMUNLOCK();
            
            // are we suspending, resuming, or neither?
            if(fSuspendSystem) {
                INT iCurrentPriority;
                
                // we're suspending; update all devices other than block devices,
                // in case any of them need to access the registry or write files.
                PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, 
                    (_T("%s: suspending - notifying non-block drivers\r\n"), pszFname));
                for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) {
                    if(*pdl->pGuid != idBlockDevices) {
                        UpdateClassDeviceStates(pdl);
                    }
                }
                
                // Notify the kernel that we are about to suspend.  This gives the
                // kernel an opportunity to clear wake source flags before we initiate
                // the suspend process.  If we don't do this and a wake source interrupt
                // occurs between the time we call PowerOffSystem() and the time 
                // OEMPowerOff() is invoked it is hard for the kernel to know whether or
                // not to suspend.
                PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, 
                    (_T("%s: calling KernelIoControl(IOCTL_HAL_PRESUSPEND)\r\n"), pszFname));
                KernelIoControl(IOCTL_HAL_PRESUSPEND, NULL, 0, NULL, 0, NULL);
                iCurrentPriority = CeGetThreadPriority(GetCurrentThread());
                DEBUGCHK(iCurrentPriority != THREAD_PRIORITY_ERROR_RETURN);
                if(iCurrentPriority != THREAD_PRIORITY_ERROR_RETURN) {
                    CeSetThreadPriority(GetCurrentThread(), giPreSuspendPriority);
                    Sleep(0);
                    CeSetThreadPriority(GetCurrentThread(), iCurrentPriority);
                }
                
                // Notify file systems that their block drivers will soon go away.  After making
                // this call, this thread is the only one that can access the file system
                // (including registry and device drivers) without blocking.  Unfortunately,
                // this API takes and holds the file system critical section, so other threads
                // attempting to access the registry or files may cause priority inversions.
                // To avoid priority problem that may starve the PM, we can raise our own priority
                // to a high level.  Do this if giSuspendPriority is non-zero.
                if(giSuspendPriority != 0) {
                    iPreSuspendPriority = CeGetThreadPriority(GetCurrentThread());
                    DEBUGCHK(iPreSuspendPriority != THREAD_PRIORITY_ERROR_RETURN);
                    PMLOGMSG(ZONE_PLATFORM, 
                        (_T("%s: suspending: raising thread priority for 0x%08x from %d to %d\r\n"),
                        pszFname, GetCurrentThreadId(), iPreSuspendPriority, giSuspendPriority));
                    CeSetThreadPriority(GetCurrentThread(), giSuspendPriority);
                }
                FileSystemPowerFunction(FSNOTIFY_POWER_OFF);
                gfFileSystemsAvailable = FALSE;
                
                // update block device power states
                PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, 
                    (_T("%s: suspending - notifying block drivers\r\n"), pszFname));
                pdl = GetDeviceListFromClass(&idBlockDevices);
                if(pdl != NULL) {
                    UpdateClassDeviceStates(pdl);
                }
                
                // Handle resets and shutdowns here, after flushing files.  Since Windows CE does
                // not define a standard mechanism for handling shutdown (via POWER_STATE_OFF),
                // OEMs will need to fill in the appropriate code here.  Similarly, if an OEM does
                // not support IOCTL_HAL_REBOOT, they should not support POWER_STATE_RESET.
                if((dwNewStateFlags & POWER_STATE_RESET) != 0) {
                    // is this to be a cold boot?
                    if(_tcscmp(pszName, _T("coldreboot")) == 0) {
                        SetCleanRebootFlag();
                    }

                    // should not return from this call, but if we do just suspend the system
                    KernelIoControl(IOCTL_HAL_REBOOT, NULL, 0, NULL, 0, NULL);
                    RETAILMSG(TRUE, (_T("PM: PlatformSetSystemPowerState: KernelIoControl(IOCTL_HAL_REBOOT) returned!\r\n")));
                    DEBUGCHK(FALSE);        // break into the debugger
                } 
            } else if(fResumeSystem) {
                // we're waking up from a resume -- update block device power states
                // so we can access the registry and/or files.
                PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, 
                    (_T("%s: resuming - notifying block drivers\r\n"), pszFname));
                pdl = GetDeviceListFromClass(&idBlockDevices);
                if(pdl != NULL) {
                    UpdateClassDeviceStates(pdl);
                }
                
                // Notify file systems that their block drivers are back.
                FileSystemPowerFunction(FSNOTIFY_POWER_ON);
                gfFileSystemsAvailable = TRUE;
                
                // update all devices other than block devices
                PMLOGMSG(ZONE_PLATFORM || ZONE_RESUME, 
                    (_T("%s: resuming - notifying block drivers\r\n"), pszFname));
                for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) {
                    if(*pdl->pGuid != idBlockDevices) {
                        UpdateClassDeviceStates(pdl);
                    }
                }
            } else {
                // update all devices without any particular ordering
                UpdateAllDeviceStates();
            }
            
            // release the old state information
            SystemPowerStateDestroy(pOldSystemPowerState);
            while(pOldCeilingDx != NULL) {
                PDEVICE_POWER_RESTRICTION pdpr = pOldCeilingDx->pNext;
                PowerRestrictionDestroy(pOldCeilingDx);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -