📄 pmtimer.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
// This module contains code to handle activity timers. Activity timers are
// unsignaled until they count down to 0 (expire), at which point they become
// signaled. The PM implements activity timers by providing named auto-reset
// events that reset the timers. Each timer has a pair of named manual-reset
// events that indicates activity or inactivity. Both of these timers are reset
// during suspend.
//
#include <pmimpl.h>
#include <nkintr.h>
// This routine initializes the list of activity timers. It returns ERROR_SUCCESS
// if successful or a Win32 error code otherwise.
DWORD
ActivityTimerInitList(VOID)
{
DWORD dwStatus;
HKEY hk = NULL;
TCHAR szSources[1024];
DWORD dwNumTimers = 0;
PPACTIVITY_TIMER ppatList = NULL;
SETFNAME(_T("ActivityTimerInitList"));
wsprintf(szSources, _T("%s\\ActivityTimers"), PWRMGR_REG_KEY);
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSources, 0, 0, &hk);
if(dwStatus == ERROR_SUCCESS) {
// figure out how many values are associated with the key
dwStatus = RegQueryInfoKey(hk, NULL, NULL, NULL, &dwNumTimers, NULL, NULL, NULL,
NULL, NULL, NULL, NULL);
} else {
// no timers configured in the registry
dwNumTimers = 0;
dwStatus = ERROR_SUCCESS;
}
// if there are any values, allocate an array to hold them
if(dwStatus == ERROR_SUCCESS) {
ppatList = (PPACTIVITY_TIMER) PmAlloc((dwNumTimers + 1) * sizeof(PACTIVITY_TIMER));
if(ppatList == NULL) {
PMLOGMSG(ZONE_WARN, (_T("%s: couldn't allocate %d timers\r\n"), pszFname,
dwNumTimers));
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
} else {
memset(ppatList, 0, (dwNumTimers + 1) * sizeof(PACTIVITY_TIMER));
ppatList[dwNumTimers] = NULL;
}
}
// read list of timers
if(dwStatus == ERROR_SUCCESS && dwNumTimers != 0) {
DWORD dwIndex = 0;
do {
TCHAR szName[256];
DWORD cbValueName = dim(szName);
dwStatus = RegEnumKeyEx(hk, dwIndex, szName, &cbValueName, NULL,
NULL, NULL, NULL);
if(dwStatus == ERROR_SUCCESS) {
HKEY hkSubKey = NULL;
// open the subkey
dwStatus = RegOpenKeyEx(hk, szName, 0, 0, &hkSubKey);
if(dwStatus == ERROR_SUCCESS) {
DWORD dwSize, dwType, dwTimeout;
LPTSTR pszValueName;
// read the timeout, expressed in seconds
dwSize = sizeof(dwTimeout);
pszValueName = _T("Timeout");
dwStatus = RegQueryValueEx(hkSubKey, pszValueName, NULL, &dwType, (LPBYTE) &dwTimeout,
&dwSize);
if(dwStatus == ERROR_SUCCESS) {
if(dwType != REG_DWORD || dwTimeout > MAXTIMERINTERVAL) {
PMLOGMSG(ZONE_WARN,
(_T("%s: RegQueryValueEx('%s'\'%s') or returned invalid type %d or invalid value %d\r\n"),
pszFname, szName, pszValueName, dwType, dwTimeout));
dwStatus = ERROR_INVALID_DATA;
}
// convert timeout to milliseconds
dwTimeout *= 1000;
} else {
// no timeout in seconds, try milliseconds
dwSize = sizeof(dwTimeout);
pszValueName = _T("TimeoutMs");
dwStatus = RegQueryValueEx(hkSubKey, pszValueName, NULL, &dwType, (LPBYTE) &dwTimeout,
&dwSize);
if(dwStatus != ERROR_SUCCESS || dwType != REG_DWORD || dwTimeout > (MAXTIMERINTERVAL * 1000)) {
PMLOGMSG(ZONE_WARN,
(_T("%s: RegQueryValueEx('%s'\'%s') failed %d (or returned invalid type %d or invalid value %d)\r\n"),
pszFname, szName, pszValueName, dwStatus, dwType, dwTimeout));
dwStatus = ERROR_INVALID_DATA;
}
}
if(dwStatus == ERROR_SUCCESS) {
// get wake sources
dwSize = sizeof(szSources);
pszValueName = _T("WakeSources");
dwStatus = RegQueryValueEx(hkSubKey, pszValueName, NULL, &dwType, (LPBYTE) szSources,
&dwSize);
if(dwStatus != ERROR_SUCCESS) {
// no wake sources
szSources[0] = 0;
szSources[1] = 0;
dwStatus = ERROR_SUCCESS;
} else if(dwType != REG_MULTI_SZ) {
PMLOGMSG(ZONE_WARN, (_T("%s: invalid type %d for '%s'\'%s'\r\n"), pszFname, dwType,
szName, pszValueName));
dwStatus = ERROR_INVALID_DATATYPE;
} else {
szSources[dim(szSources) -1] = szSources[dim(szSources) -2] = 0; // Terminate MultiSZ
}
}
// did we get the parameters?
if(dwStatus == ERROR_SUCCESS) {
ppatList[dwIndex] = ActivityTimerCreate(szName, dwTimeout, szSources);
if(ppatList[dwIndex] == NULL) {
dwStatus = ERROR_NOT_ENOUGH_MEMORY;
}
}
}
// release the registry key
RegCloseKey(hkSubKey);
}
// update the index
dwIndex++;
} while(dwStatus == ERROR_SUCCESS && dwIndex < dwNumTimers);
// did we read all items ok?
if(dwStatus == ERROR_NO_MORE_ITEMS) {
dwStatus = ERROR_SUCCESS;
}
// terminate the list with a NULL
ppatList[dwIndex] = NULL;
}
// did we succeed?
if(dwStatus == ERROR_SUCCESS) {
PMLOCK();
gppActivityTimers = ppatList;
PMUNLOCK();
} else {
DWORD dwIndex;
if(ppatList != NULL) {
for(dwIndex = 0; dwIndex < dwNumTimers; dwIndex++) {
if(ppatList[dwIndex] != NULL) {
ActivityTimerDestroy(ppatList[dwIndex]);
}
}
PmFree(ppatList);
}
}
// release resources
if(hk != NULL) RegCloseKey(hk);
PMLOGMSG(dwStatus != ERROR_SUCCESS && ZONE_WARN,
(_T("%s: returning %d\r\n"), pszFname, dwStatus));
return dwStatus;
}
// This routine calculates the next timeout interval for the various
// activity timers. This routine doesn't sort timers, on the assumption
// that a given system will have relatively few inactivity timers.
DWORD
GetNextInactivityTimeout(DWORD dwElapsed)
{
DWORD dwTimeout = INFINITE;
DWORD dwIndex;
PACTIVITY_TIMER pat;
PMLOCK();
for(dwIndex = 0; (pat = gppActivityTimers[dwIndex]) != NULL; dwIndex++) {
DWORD dwTimeLeft = pat->dwTimeLeft;
if(dwTimeLeft != INFINITE) {
// subtract elapsed time
if(dwTimeLeft < dwElapsed) {
dwTimeLeft = 0;
} else {
dwTimeLeft -= dwElapsed;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -