📄 pmstubs.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.
//
/*++
Module Name:
pmstubs.cpp
Abstract:
Empty PM APIs, solely to satisfy the linker.
Revision History:
--*/
#include <windows.h>
#include <pm.h>
#include <extfile.h>
#define _DEFINE_PM_VARS // global variables defined in this module
#include <pmimpl.h>
typedef BOOL (WINAPI * PFN_GwesPowerDown)(void);
typedef void (WINAPI * PFN_GwesPowerUp)(BOOL);
// force C linkage to match external variable declarations
extern "C" {
// define list pointers
PPOWER_NOTIFICATION gpPowerNotifications;
// 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 ghPmHeap; // power manager's memory allocation heap
HANDLE ghevPmShutdown; // signal to cause PM threads to exit
HANDLE ghevGwesReady;
BOOL gfGwesReady;
PFN_GwesPowerDown gpfnGwesPowerDown;
PFN_GwesPowerUp gpfnGwesPowerUp;
POWER_BROADCAST_POWER_INFO gSystemPowerStatus;
#if defined(DEBUG) || !defined(_PM_NOCELOGMSG)
#define DBG_ERROR (1 << 0)
#define DBG_WARN (1 << 1)
#define DBG_INIT (1 << 2)
#define DBG_REGISTRY (1 << 9)
#define DBG_PLATFORM (1 << 10)
#define DBG_API (1 << 11)
#define DBG_ALLOC (1 << 12)
DBGPARAM dpCurSettings = {
_T("PM"),
{
TEXT("Errors"), TEXT("Warnings"), TEXT("Init"), TEXT(""),
TEXT(""), TEXT(""), TEXT(""), TEXT(""),
TEXT("Notify"),TEXT("Registry"),TEXT("Platform"),TEXT("API"),
TEXT("Alloc"),TEXT(""),TEXT(""),TEXT("")
},
DBG_ERROR | DBG_WARN | DBG_INIT
};
#endif
}; // extern "C"
EXTERN_C BOOL WINAPI
PmInit(VOID)
{
BOOL fOk = TRUE;
HMODULE hmCoreDll = NULL;
SETFNAME(_T("PmInit"));
DEBUGMSG(ZONE_INIT || ZONE_API, (_T("+%s\r\n"), pszFname));
// set up globals
InitializeCriticalSection(&gcsPowerManager);
InitializeCriticalSection(&gcsDeviceUpdateAPIs);
gpPowerNotifications = NULL;
ghPmHeap = GetProcessHeap();
ghevPowerManagerReady = NULL;
gpfnGwesPowerDown = NULL;
gpfnGwesPowerUp = NULL;
// cleanup event (hopefully never used)
ghevPmShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
if(ghevPmShutdown == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: CreateEvent() failed for shutdown event\r\n"), pszFname));
fOk = FALSE;
}
// create events
if(fOk) {
ghevPowerManagerReady = CreateEvent(NULL, TRUE, FALSE, _T("SYSTEM/PowerManagerReady"));
// check everything
if(ghevPowerManagerReady == NULL) {
DEBUGMSG(ZONE_ERROR, (_T("%s: event creation failure\r\n"), pszFname));
fOk = FALSE;
}
}
// Get pointers to GWES's suspend/routine APIs. These require GWES, so the OEM may
// not have them on this platform.
if(fOk) {
hmCoreDll = (HMODULE) LoadLibrary(_T("coredll.dll"));
gfGwesReady = FALSE;
if(hmCoreDll != NULL) {
gpfnGwesPowerDown = (PFN_GwesPowerDown) GetProcAddress(hmCoreDll, _T("GwesPowerDown"));
gpfnGwesPowerUp = (PFN_GwesPowerUp) GetProcAddress(hmCoreDll, _T("GwesPowerUp"));
// do we have both of them?
if(gpfnGwesPowerDown == NULL || gpfnGwesPowerUp == NULL) {
// no, ignore GWES
gpfnGwesPowerDown = NULL;
gpfnGwesPowerUp = NULL;
} else {
// monitor GWES apis
ghevGwesReady = OpenEvent(EVENT_ALL_ACCESS, FALSE, _T("SYSTEM/GweApiSetReady"));
DEBUGCHK(ghevGwesReady != NULL);
if(ghevGwesReady == NULL) {
fOk = FALSE;
}
}
}
}
// if everything is initialized, we're ready start the power monitor thread
if(fOk) {
BOOL fGotBatteryAPIs = PmInitPowerStatus(hmCoreDll);
if(fGotBatteryAPIs) {
DWORD WINAPI PowerMonitorThreadProc(LPVOID lpvParam);
HANDLE htMonitor = CreateThread(NULL, 0, PowerMonitorThreadProc, NULL, 0, NULL);
if(htMonitor == NULL) {
DEBUGMSG(ZONE_WARN, (_T("%s: CreateThread() failed %d for power monitor thread\r\n"),
pszFname, GetLastError()));
} else {
CloseHandle(htMonitor);
}
}
}
// should we signal that our API is ready?
if(fOk) {
// yes, the PM is initialized
SetEvent(ghevPowerManagerReady);
} else {
// no, clean up
DEBUGMSG(ZONE_ERROR, (_T("%s: closing handles\r\n"), pszFname));
if(ghevPowerManagerReady != NULL) CloseHandle(ghevPowerManagerReady);
if(ghevGwesReady != NULL) CloseHandle(ghevGwesReady);
if(hmCoreDll != NULL) FreeLibrary(hmCoreDll);
if(ghevPmShutdown != NULL) CloseHandle(ghevPmShutdown);
}
DEBUGMSG((!fOk && ZONE_ERROR) || ZONE_INIT || ZONE_API,
(_T("-%s: returning %d\r\n"), pszFname, fOk));
DEBUGCHK(fOk); // make sure we raise a red flag if the init fails
return fOk;
}
// This routine receives notifications from the system about various system
// events, including processes exiting. Some of the messages have the same
// names as DllEntry() messages, but the resemblance is superficial. Note
// that unlike DLL entry point message handlers, these notifications allow
// the message handler to use synchronization objects without deadlocking
// the system.
EXTERN_C VOID WINAPI
PmNotify(DWORD dwFlags, HPROCESS hProcess, HTHREAD hThread)
{
SETFNAME(_T("PmNotify"));
UnusedParameter(hThread);
switch(dwFlags) {
case DLL_PROCESS_DETACH:
// release any resources held by this process
DEBUGMSG(ZONE_API, (_T("+%s: hProcess 0x%08x exiting\r\n"), pszFname, hProcess));
DeleteProcessNotifications(hProcess);
DEBUGMSG(ZONE_API, (_T("-%s\r\n"), pszFname));
break;
default:
break;
}
}
DWORD WINAPI
PmSetDevicePower(
PVOID pvDevice,
DWORD dwDeviceFlags,
CEDEVICE_POWER_STATE DeviceState
)
{
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return ERROR_SERVICE_DOES_NOT_EXIST;
}
DWORD WINAPI
PmGetDevicePower(
PVOID pvDevice,
DWORD dwDeviceFlags,
PCEDEVICE_POWER_STATE pDeviceState
)
{
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return ERROR_SERVICE_DOES_NOT_EXIST;
}
DWORD WINAPI
PmDevicePowerNotify(
PVOID pvDevice,
CEDEVICE_POWER_STATE DeviceState,
DWORD Flags
)
{
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return ERROR_SERVICE_DOES_NOT_EXIST;
}
DWORD WINAPI
PmGetSystemPowerState(
LPWSTR pBuffer,
DWORD Length,
PDWORD pFlags
)
{
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return ERROR_SERVICE_DOES_NOT_EXIST;
}
DWORD WINAPI
PmReleasePowerRequirement(
HANDLE h,
DWORD Flags
)
{
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return ERROR_SERVICE_DOES_NOT_EXIST;
}
HANDLE WINAPI
PmRegisterPowerRelationship(
PVOID pvParent, // e.g. 'NDS0:'
PVOID pvChild, // e.g. 'NE20001', 'NE20002', ...
PPOWER_CAPABILITIES pCaps, // OPTIONAL Child's capabilities
DWORD Flags
)
{
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return INVALID_HANDLE_VALUE;
}
DWORD WINAPI
PmReleasePowerRelationship(
HANDLE h
)
{
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return ERROR_SERVICE_DOES_NOT_EXIST;
}
HANDLE WINAPI
PmSetPowerRequirement(
PVOID pvDevice,
CEDEVICE_POWER_STATE DeviceState,
ULONG DeviceFlags,
PVOID pvSystemState, // OPTIONAL
ULONG StateFlags // OPTIONAL
)
{
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
return INVALID_HANDLE_VALUE;
}
EXTERN_C DWORD WINAPI
PmSetSystemPowerState(LPCWSTR pwsState, DWORD dwStateHint, DWORD dwOptions)
{
DWORD dwStatus = ERROR_SUCCESS;
SETFNAME(_T("PmSetSystemPowerState"));
DEBUGMSG(ZONE_API, (_T("+%s: name %s, hint 0x%08x, options 0x%08x\r\n"),
pszFname, pwsState != NULL ? pwsState : _T("<NULL>"), dwStateHint, dwOptions));
PMENTERUPDATE();
// are we being asked to suspend the system?
if(pwsState != NULL
|| (dwStateHint & (POWER_STATE_SUSPEND | POWER_STATE_OFF | POWER_STATE_CRITICAL)) == 0) {
// no, return an error
SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
dwStatus = ERROR_SERVICE_DOES_NOT_EXIST;
} else {
// are the GWES suspend APIs present and ready?
if(!gfGwesReady && gpfnGwesPowerDown != NULL) {
// APIs present, but not ready -- check for readiness
if(WaitForSingleObject(ghevGwesReady, 0) == WAIT_OBJECT_0) {
gfGwesReady = TRUE;
CloseHandle(ghevGwesReady);
ghevGwesReady = NULL;
}
}
// suspend the system
BOOL fWantStartupScreen = FALSE;
if(gfGwesReady && gpfnGwesPowerDown != NULL) {
fWantStartupScreen = gpfnGwesPowerDown();
}
KernelIoControl(IOCTL_HAL_PRESUSPEND, NULL, 0, NULL, 0, NULL);
FileSystemPowerFunction(FSNOTIFY_POWER_OFF);
PowerOffSystem();
Sleep(0);
FileSystemPowerFunction(FSNOTIFY_POWER_ON);
if(gfGwesReady && gpfnGwesPowerUp != NULL) {
gpfnGwesPowerUp(fWantStartupScreen);
}
}
PMLEAVEUPDATE();
DEBUGMSG(ZONE_API, (_T("-%s: returning dwStatus %d\r\n"), pszFname, dwStatus));
return dwStatus;
}
VOID WINAPI PmPowerHandler(BOOL bOff)
{
UnusedParameter(bOff);
}
// dll entry point
BOOL WINAPI
DllEntry(HANDLE hInst, DWORD dwReason, LPVOID lpvReserved)
{
BOOL bRc = TRUE;
SETFNAME(_T("Power Manager"));
UnusedParameter(hInst);
UnusedParameter(lpvReserved);
switch (dwReason) {
case DLL_PROCESS_ATTACH:
ghInst = (HINSTANCE) hInst;
DEBUGREGISTER(ghInst);
DEBUGMSG(ZONE_INIT,(TEXT("*** %s: DLL_PROCESS_ATTACH - Current Process: 0x%x, ID: 0x%x ***\r\n"),
pszFname, GetCurrentProcess(), GetCurrentProcessId()));
DisableThreadLibraryCalls((HMODULE) hInst);
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT,(TEXT("*** %s: DLL_PROCESS_DETACH - Current Process: 0x%x, ID: 0x%x ***\r\n"),
pszFname, GetCurrentProcess(), GetCurrentProcessId()));
break;
default:
break;
}
return bRc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -