📄 mon.c
字号:
//
// 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:
mon.c
Abstract:
Power Manager Monitor.
Run in the background to display power state changes in debugger.
Notes:
Revision History:
--*/
#include <windows.h>
#include <msgqueue.h>
#include <pnp.h>
#include <guiddef.h>
#include <pm.h>
#define QUEUE_ENTRIES 3
#define MAX_NAMELEN 200
#define QUEUE_SIZE (QUEUE_ENTRIES * (sizeof(POWER_BROADCAST) + MAX_NAMELEN))
// device notification queue parameters
#define PNP_QUEUE_ENTRIES 3
#define PNP_MAX_NAMELEN 128
#define PNP_QUEUE_SIZE (PNP_QUEUE_ENTRIES * (sizeof(DEVDETAIL) + (PNP_MAX_NAMELEN * sizeof(TCHAR))))
#define PWRMGR_REG_KEY TEXT("SYSTEM\\CurrentControlSet\\Control\\Power")
// global variables
HANDLE ghPowerNotifications = NULL;
HANDLE ghDeviceNotifications = NULL;
HANDLE ghevTerminate = NULL;
void ProcessPowerNotification(HANDLE hMsgQ)
{
UCHAR buf[QUEUE_SIZE];
int iBytesInQueue;
DWORD dwFlags = 0;
int dwCount = 0;
LPTSTR pszFname = _T("PMMON!ProcessPowerNotification");
iBytesInQueue = 0;
memset(buf, 0, QUEUE_SIZE);
if ( !ReadMsgQueue(hMsgQ,
buf,
QUEUE_SIZE,
&iBytesInQueue,
INFINITE, // Timeout
&dwFlags))
{
DWORD dwErr = GetLastError();
RETAILMSG(1, (TEXT("%s: ReadMsgQueue: ERROR:%d\n"), pszFname, dwErr));
ASSERT(0);
} else if(iBytesInQueue >= sizeof(POWER_BROADCAST)) {
//
// process power notifications
//
PPOWER_BROADCAST pB = (PPOWER_BROADCAST) buf;
RETAILMSG(1, (TEXT("%s: *** Power Notification @ Tick:%u, Count:%d***\n"), pszFname,
GetTickCount(), dwCount++));
switch (pB->Message)
{
case PBT_TRANSITION:
RETAILMSG(1, (TEXT("%s:\tPBT_TRANSITION to system power state: '%s'\n"), pszFname, pB->SystemPowerState));
switch (POWER_STATE(pB->Flags)) {
case POWER_STATE_ON:
RETAILMSG(1, (TEXT("%s:\tPOWER_STATE_ON\n"), pszFname));
break;
case POWER_STATE_OFF:
RETAILMSG(1, (TEXT("%s:\tPOWER_STATE_OFF\n"), pszFname));
break;
case POWER_STATE_CRITICAL:
RETAILMSG(1, (TEXT("%s:\tPOWER_STATE_CRITICAL\n"), pszFname));
break;
case POWER_STATE_BOOT:
RETAILMSG(1, (TEXT("%s:\tPOWER_STATE_BOOT\n"), pszFname));
break;
case POWER_STATE_IDLE:
RETAILMSG(1, (TEXT("%s:\tPOWER_STATE_IDLE\n"), pszFname));
break;
case POWER_STATE_SUSPEND:
RETAILMSG(1, (TEXT("%s:\tPOWER_STATE_SUSPEND\n"), pszFname));
break;
case POWER_STATE_RESET:
RETAILMSG(1, (TEXT("%s:\tPOWER_STATE_RESET\n"), pszFname));
break;
case 0:
break;
default:
RETAILMSG(1,(TEXT("%s:\tUnknown Power State Flags:0x%x\n"), pszFname, pB->Flags));
ASSERT(0);
break;
}
break;
case PBT_RESUME:
RETAILMSG(1, (TEXT("%s:\tPBT_RESUME\n"), pszFname));
break;
case PBT_POWERSTATUSCHANGE:
RETAILMSG(1, (TEXT("%s:\tPBT_POWERSTATUSCHANGE\n"), pszFname));
break;
case PBT_POWERINFOCHANGE:
{
PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pB->SystemPowerState;
RETAILMSG(1, (TEXT("%s:\tPBT_POWERINFOCHANGE\n"), pszFname));
RETAILMSG(1, (TEXT("%s:\t\tAC line status %u, battery flag %u, backup flag %u, %d levels\n"), pszFname,
ppbpi->bACLineStatus, ppbpi->bBatteryFlag, ppbpi->bBackupBatteryFlag, ppbpi->dwNumLevels));
RETAILMSG(1, (TEXT("%s:\t\tbattery life %d, backup life %d\n"), pszFname,
ppbpi->bBatteryLifePercent, ppbpi->bBackupBatteryLifePercent));
RETAILMSG(1, (TEXT("%s:\t\tlifetime 0x%08x, full lifetime 0x%08x\n"), pszFname,
ppbpi->dwBatteryLifeTime, ppbpi->dwBatteryFullLifeTime));
RETAILMSG(1, (TEXT("%s:\t\tbackup lifetime 0x%08x, backup full lifetime 0x%08x\n"), pszFname,
ppbpi->dwBackupBatteryLifeTime, ppbpi->dwBackupBatteryFullLifeTime));
}
break;
default:
RETAILMSG(1, (TEXT("%s:\tUnknown Message:%d\n"), pszFname, pB->Message));
ASSERT(0);
break;
}
RETAILMSG(1, (TEXT("%s:\tMessage: 0x%x\n"), pszFname, pB->Message));
RETAILMSG(1, (TEXT("%s:\tFlags: 0x%x\n"), pszFname, pB->Flags));
RETAILMSG(1, (TEXT("%s:\tdwLen: %d\n"), pszFname, pB->Length));
RETAILMSG(1, (TEXT("%s:***********************\n"), pszFname));
} else {
RETAILMSG(1, (TEXT("%s:\tReceived short message: %d bytes\n"), pszFname, iBytesInQueue));
ASSERT(0);
}
}
void
ProcessDeviceNotification(HANDLE hMsgQ)
{
UCHAR deviceBuf[PNP_QUEUE_SIZE];
DWORD iBytesInQueue = 0;
DWORD dwFlags = 0;
LPTSTR pszFname = _T("PMMON!ProcessDeviceNotification");
// read a message from the message queue -- it should be a device advertisement
memset(deviceBuf, 0, PNP_QUEUE_SIZE);
if ( !ReadMsgQueue(hMsgQ, deviceBuf, PNP_QUEUE_SIZE, &iBytesInQueue, 0, &dwFlags)) {
// nothing in the queue
RETAILMSG(TRUE, (_T("%s: ReadMsgQueue() failed %d\r\n"), pszFname,
GetLastError()));
} else if(iBytesInQueue >= sizeof(DEVDETAIL)) {
// process the message
PDEVDETAIL pDevDetail = (PDEVDETAIL) deviceBuf;
DWORD dwMessageSize = sizeof(DEVDETAIL) + pDevDetail->cbName;
// check for overlarge names
if(pDevDetail->cbName > ((PNP_MAX_NAMELEN - 1) * sizeof(pDevDetail->szName[0]))) {
RETAILMSG(TRUE, (_T("%s: device name longer than %d characters\r\n"),
pszFname, PNP_MAX_NAMELEN - 1));
} else {
LPCTSTR pszName = pDevDetail->szName;
LPCGUID guidDevClass = &pDevDetail->guidDevClass;
TCHAR szClassDescription[MAX_PATH];
TCHAR szClassName[MAX_PATH];
HKEY hk;
DWORD dwStatus;
// format the class name
_stprintf(szClassName, _T("{%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x}"),
guidDevClass->Data1, guidDevClass->Data2, guidDevClass->Data3,
(guidDevClass->Data4[0] << 8) + guidDevClass->Data4[1], guidDevClass->Data4[2], guidDevClass->Data4[3],
guidDevClass->Data4[4], guidDevClass->Data4[5], guidDevClass->Data4[6], guidDevClass->Data4[7]);
// (inefficiently) look up the class description whenever a device registers
wsprintf(szClassDescription, _T("%s\\Interfaces"), PWRMGR_REG_KEY);
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szClassDescription, 0, 0, &hk);
if(dwStatus == ERROR_SUCCESS) {
DWORD dwSize = sizeof(szClassDescription);
dwStatus = RegQueryValueEx(hk, szClassName, NULL, NULL, (LPBYTE) szClassDescription, &dwSize);
RegCloseKey(hk);
}
if(dwStatus != ERROR_SUCCESS) {
_tcscpy(szClassDescription, (_T("<unknown class>")));
}
RETAILMSG(TRUE,
(_T("%s: device '%s' %s class %s ('%s')\r\n"), pszFname,
pszName, pDevDetail->fAttached ? _T("joining") : _T("leaving"),
szClassName, szClassDescription));
}
} else {
// not enough bytes for a message
RETAILMSG(TRUE, (_T("%s: got runt message (%d bytes)\r\n"), pszFname,
iBytesInQueue));
}
}
int WINAPI MonThreadProc(LPVOID pvParam)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -