📄 mon.c
字号:
HANDLE hEvents[3];
LPTSTR pszFname = _T("PMMON!MonThreadProc");
UNREFERENCED_PARAMETER(pvParam);
ASSERT(ghPowerNotifications != NULL);
ASSERT(ghDeviceNotifications != NULL);
ASSERT(ghevTerminate != NULL);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
hEvents[0] = ghPowerNotifications;
hEvents[1] = ghDeviceNotifications;
hEvents[2] = ghevTerminate;
while (1)
{
DWORD dwStatus;
// Block on our message queue.
// This thread runs when the power manager writes a notification into the queue.
dwStatus = WaitForMultipleObjects(3, hEvents, FALSE, INFINITE);
if(dwStatus == WAIT_OBJECT_0) {
ProcessPowerNotification(ghPowerNotifications);
} else if(dwStatus == (WAIT_OBJECT_0 + 1)) {
ProcessDeviceNotification(ghDeviceNotifications);
} else if(dwStatus == (WAIT_OBJECT_0 + 2)) {
RETAILMSG(1, (TEXT("%s: termination event signaled\r\n"), pszFname));
} else {
RETAILMSG(1, (TEXT("%s: WaitForMultipleObjects returned %d (error %d)\r\n"), pszFname,
dwStatus, GetLastError()));
break;
}
}
return 0;
}
// this routine converts a string into a GUID and returns TRUE if the
// conversion was successful.
BOOL
ConvertStringToGuid (LPCTSTR pszGuid, GUID *pGuid)
{
UINT Data4[8];
int Count;
BOOL fOk = FALSE;
TCHAR *pszGuidFormat = _T("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}");
ASSERT(pGuid != NULL && pszGuid != NULL);
__try
{
if (_stscanf(pszGuid, pszGuidFormat, &pGuid->Data1,
&pGuid->Data2, &pGuid->Data3, &Data4[0], &Data4[1], &Data4[2], &Data4[3],
&Data4[4], &Data4[5], &Data4[6], &Data4[7]) == 11)
{
for(Count = 0; Count < (sizeof(Data4) / sizeof(Data4[0])); Count++)
{
pGuid->Data4[Count] = (UCHAR) Data4[Count];
}
}
fOk = TRUE;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
}
return fOk;
}
BOOL
RequestPMDeviceNotifications(DWORD cNotifications, HANDLE *phNotifications)
{
BOOL fOk = TRUE;
DWORD dwStatus;
HKEY hk;
TCHAR szBuf[MAX_PATH];
LPTSTR pszFname = _T("PMMON!RequestPMDeviceNotifications");
// 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;
DWORD dwNotificationIndex = 0;
do {
DWORD cbValueName = MAX_PATH, dwType;
GUID idInterface;
dwStatus = RegEnumValue(hk, dwIndex, szBuf, &cbValueName, NULL,
&dwType, NULL, NULL);
if(dwStatus == ERROR_SUCCESS) {
if(dwType != REG_SZ) {
RETAILMSG(TRUE, (_T("%s: invalid type for value '%s'\r\n"),
pszFname, szBuf));
} else if(!ConvertStringToGuid(szBuf, &idInterface)) {
RETAILMSG(TRUE, (_T("%s: can't convert '%s' to GUID\r\n"),
pszFname, szBuf));
} else if((phNotifications[dwNotificationIndex] = RequestDeviceNotifications(&idInterface, ghDeviceNotifications, TRUE)) == NULL) {
RETAILMSG(TRUE, (_T("%s: RequestDeviceNotifications('%s') failed\r\n"),
pszFname, szBuf));
} else {
dwNotificationIndex++;
}
// update the index
dwIndex++;
}
} while(dwStatus == ERROR_SUCCESS && dwNotificationIndex < cNotifications);
// check for abnormal termination of the loop
if(dwStatus != ERROR_NO_MORE_ITEMS) {
fOk = FALSE;
}
// close the registry handle
RegCloseKey(hk);
}
return fOk;
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nCmShow)
{
HANDLE hNotifications = NULL;
HANDLE hDeviceNotifications[64];
HANDLE ht;
int i;
LPTSTR pszFname = _T("PMMON:WinMain");
MSGQUEUEOPTIONS msgOptions = {0};
UNREFERENCED_PARAMETER(hInst);
UNREFERENCED_PARAMETER(hPrevInst);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmShow);
// clear globals
memset(hDeviceNotifications, 0, sizeof(hDeviceNotifications));
// create a termination event
ghevTerminate = CreateEvent(NULL, FALSE, FALSE, _T("SOFTWARE/PMTestPrograms/PMMON/Terminate"));
if(ghevTerminate == NULL) {
RETAILMSG(TRUE, (_T("%s: CreateEvent() failed %d for termination event\r\n"),
pszFname, GetLastError()));
goto _Exit;
}
// did the event already exist?
if(GetLastError() == ERROR_ALREADY_EXISTS) {
// yes, kill the existing process
RETAILMSG(TRUE, (_T("%s: Signaling termination event\r\n"), pszFname));
SetEvent(ghevTerminate);
goto _Exit;
}
// create a message queue for Power Manager notifications
msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
msgOptions.dwFlags = 0;
msgOptions.dwMaxMessages = QUEUE_ENTRIES;
msgOptions.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
msgOptions.bReadAccess = TRUE;
ghPowerNotifications= CreateMsgQueue(NULL, &msgOptions);
if (!ghPowerNotifications) {
DWORD dwErr = GetLastError();
RETAILMSG(1, (TEXT("%s:CreateMessageQueue ERROR:%d\n"), pszFname, dwErr));
goto _Exit;
}
// request Power notifications
hNotifications = RequestPowerNotifications(ghPowerNotifications, POWER_NOTIFY_ALL); // Flags
if (!hNotifications) {
DWORD dwErr = GetLastError();
RETAILMSG(TRUE, (TEXT("%s:RequestPowerNotifications ERROR:%d\n"), pszFname, dwErr));
goto _Exit;
}
// create message queues
memset(&msgOptions, 0, sizeof(msgOptions));
msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
msgOptions.dwFlags = 0;
msgOptions.cbMaxMessage = PNP_QUEUE_SIZE;
msgOptions.bReadAccess = TRUE;
ghDeviceNotifications = CreateMsgQueue(NULL, &msgOptions);
if(ghDeviceNotifications == NULL) {
DWORD dwStatus = GetLastError();
RETAILMSG(TRUE, (_T("%s:CreateMsgQueue() failed %d\r\n"), pszFname, dwStatus));
goto _Exit;
}
// create the monitoring thread
ht = CreateThread(NULL, 0, MonThreadProc, NULL, 0, NULL);
if(ht) {
// request device notifications (do this after the thread is
// created so we don't drop any notifications)
RequestPMDeviceNotifications(64, hDeviceNotifications);
// wait for the thread to exit
WaitForSingleObject(ht, INFINITE);
CloseHandle(ht);
}
_Exit:
if(hNotifications) StopPowerNotifications(hNotifications);
if(ghPowerNotifications) CloseMsgQueue(ghPowerNotifications);
for(i = 0; i < 64 && hDeviceNotifications[i] != NULL; i++) {
StopDeviceNotifications(hDeviceNotifications[i]);
}
if(ghDeviceNotifications) CloseMsgQueue(ghDeviceNotifications);
if(ghevTerminate) CloseHandle(ghevTerminate);
RETAILMSG(TRUE, (_T("%s: exiting\r\n"), pszFname));
return 0;
}
// EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -