📄 pminit.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 file contains the entry points for the Power Manager. These entry
// points are called from device.exe, which implicitly links with the PM dll.
// PM global variables are defined in this module.
//
#define _DEFINE_PM_VARS // global variables defined in this module
#include <pmimpl.h>
#include "PmSysReg.h"
// force C linkage to match external variable declarations
extern "C" {
// define guids
GUID idGenericPMDeviceClass = { 0xA32942B7, 0x920C, 0x486b, { 0xB0, 0xE6, 0x92, 0xA7, 0x02, 0xA9, 0x9B, 0x35 } };
GUID idPMDisplayDeviceClass = { 0xEB91C7C9, 0x8BF6, 0x4A2D, { 0x9A, 0xB8, 0x69, 0x72, 0x4E, 0xED, 0x97, 0xD1 } };
// define list pointers
PDEVICE_POWER_RESTRICTION gpFloorDx;
PDEVICE_POWER_RESTRICTION gpCeilingDx;
PPOWER_NOTIFICATION gpPowerNotifications;
PSYSTEM_POWER_STATE gpSystemPowerState;
PDEVICE_LIST gpDeviceLists;
PPACTIVITY_TIMER gppActivityTimers;
// thread control variables
HANDLE ghevPmShutdown; // set this event to close threads
HANDLE ghtPnP; // handle to the PnP thread
HANDLE ghtResume; // handle to the resume thread
HANDLE ghtSystem; // handle to the system thread
HANDLE ghtActivityTimers; // handle to the activity timers thread
// other globals
CRITICAL_SECTION gcsPowerManager; // serialize access to PM data
CRITICAL_SECTION gcsDeviceUpdateAPIs; // serialize application calls that cause device updates
HINSTANCE ghInst; // handle to the PM DLL
HANDLE ghevPowerManagerReady; // when set, this event means that the PM api is enabled
HANDLE ghevResume; // power handler sets this to signal system resume
HANDLE ghevTimerResume; // power handler sets this to re-enable activity timers
HANDLE ghPmHeap; // power manager's memory allocation heap
#if defined(DEBUG) || !defined(_PM_NOCELOGMSG)
// message zone configuration
#define DBG_ERROR (1 << 0)
#define DBG_WARN (1 << 1)
#define DBG_INIT (1 << 2)
#define DBG_RESUME (1 << 3)
#define DBG_DEVICE (1 << 4)
#define DBG_IOCTL (1 << 5)
#define DBG_REFCNT (1 << 6)
#define DBG_REQUIRE (1 << 7)
#define DBG_NOTIFY (1 << 8)
#define DBG_REGISTRY (1 << 9)
#define DBG_PLATFORM (1 << 10)
#define DBG_API (1 << 11)
#define DBG_ALLOC (1 << 12)
#define DBG_TIMERS (1 << 13)
DBGPARAM dpCurSettings = {
_T("PM"),
{
TEXT("Errors"), TEXT("Warnings"), TEXT("Init"), TEXT("Resume"),
TEXT("Device"), TEXT("Ioctl"), TEXT("Refcnt"), TEXT("Require"),
TEXT("Notify"),TEXT("Registry"),TEXT("Platform"),TEXT("API"),
TEXT("Alloc"),TEXT("Timers"),TEXT(""),TEXT("")
},
DBG_ERROR | DBG_WARN // ulZoneMask
};
#endif // defined(DEBUG) || !defined(_PM_NOCELOGMSG)
}; // extern "C"
// C++ Global for PM registry.
SystemNotifyRegKey * g_pSysRegistryAccess = NULL;
// This routine reads the registry to determine what type of device interfaces
// we will be monitoring. The default PM GUID is ignored if present in the
// registry and is always added last (so it's first in the list).
BOOL
DeviceListsInit(VOID)
{
BOOL fOk = TRUE;
PDEVICE_LIST pdl;
DWORD dwStatus;
HKEY hk;
TCHAR szBuf[MAX_PATH];
SETFNAME(_T("DeviceListsInit"));
// enumerate all the device classes
wsprintf(szBuf, _T("%s\\Interfaces"), PWRMGR_REG_KEY);
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuf, 0, 0, &hk);
if(dwStatus == ERROR_SUCCESS) {
DWORD dwIndex = 0;
do {
DWORD cbValueName = dim(szBuf), dwType;
GUID idInterface;
dwStatus = RegEnumValue(hk, dwIndex, szBuf, &cbValueName, NULL,
&dwType, NULL, NULL);
if(dwStatus == ERROR_SUCCESS) {
if(dwType != REG_SZ) {
PMLOGMSG(ZONE_WARN, (_T("%s: invalid type for value '%s'\r\n"),
pszFname, szBuf));
} else if(!ConvertStringToGuid(szBuf, &idInterface)) {
PMLOGMSG(ZONE_WARN, (_T("%s: can't convert '%s' to GUID\r\n"),
pszFname, szBuf));
} else if(idInterface == idGenericPMDeviceClass) {
PMLOGMSG(ZONE_INIT, (_T("%s: default GUID found in registry as expected\r\n"),
pszFname));
} else if((pdl = DeviceListCreate(&idInterface)) == NULL) {
PMLOGMSG(ZONE_WARN, (_T("%s: DeviceListCreate() failed\r\n"),
pszFname));
} else if(PlatformDeviceListInit(pdl) == FALSE) {
PMLOGMSG(ZONE_WARN, (_T("%s: PlatformDeviceListInit() failed\r\n"),
pszFname));
DeviceListDestroy(pdl);
} else {
// add the new entry to the list
pdl->pNext = gpDeviceLists;
gpDeviceLists = pdl;
}
// update the index
dwIndex++;
}
} while(dwStatus == ERROR_SUCCESS);
// check for abnormal termination of the loop
if(dwStatus != ERROR_NO_MORE_ITEMS) {
fOk = FALSE;
}
// close the registry handle
RegCloseKey(hk);
}
// add the default list last
if(fOk) {
fOk = FALSE;
pdl = DeviceListCreate(&idGenericPMDeviceClass);
if(pdl != NULL) {
if(PlatformDeviceListInit(pdl) == FALSE) {
PMLOGMSG(ZONE_INIT || ZONE_WARN,
(_T("%s: PlatformDeviceListInit() failed for default class\r\n"),
pszFname));
DeviceListDestroy(pdl);
} else {
pdl->pNext = gpDeviceLists;
gpDeviceLists = pdl;
fOk = TRUE;
}
}
}
// clean up if necessary
if(!fOk) {
PMLOGMSG(ZONE_WARN, (_T("%s: error during list initialization\r\n"),
pszFname));
while(gpDeviceLists != NULL) {
pdl = gpDeviceLists;
gpDeviceLists = pdl->pNext;
pdl->pNext = NULL;
DeviceListDestroy(pdl);
}
}
return fOk;
}
// This routine initializes the power manager and notifies the system that
// its api set is ready to be used. It returns TRUE if successful and FALSE
// if there's a problem.
EXTERN_C BOOL WINAPI
PmInit(VOID)
{
BOOL fOk = TRUE;
HANDLE hevPnPReady = NULL, hevResumeReady = NULL, hevSystemReady = NULL;
HANDLE hevActivityTimersReady = NULL, hevDummy = NULL;
SETFNAME(_T("PmInit"));
PMLOGMSG(ZONE_INIT || ZONE_API, (_T("+%s\r\n"), pszFname));
// set up globals
InitializeCriticalSection(&gcsPowerManager);
InitializeCriticalSection(&gcsDeviceUpdateAPIs);
gpFloorDx = NULL;
gpCeilingDx = NULL;
gpPowerNotifications = NULL;
gpSystemPowerState = NULL;
ghPmHeap = GetProcessHeap();
gpDeviceLists = NULL;
gppActivityTimers = NULL;
ghevPowerManagerReady = NULL;
ghevResume = NULL;
ghevTimerResume = NULL;
ghtPnP = NULL;
ghtResume = NULL;
ghtActivityTimers = NULL;
ghtSystem = NULL;
// cleanup event (hopefully never used)
ghevPmShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
if(ghevPmShutdown == NULL) {
PMLOGMSG(ZONE_ERROR, (_T("%s: CreateEvent() failed for shutdown event\r\n"), pszFname));
fOk = FALSE;
}
// validate the power management registry settings. OEM code should use this
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -