BOOL CreateAPnpMsgQueue(PHANDLE phQueue, PHANDLE phNoti, GUID inGUID ) { if(phQueue == NULL || phNoti == NULL){ return FALSE; } MSGQUEUEOPTIONS msgqopts = {0}; msgqopts.dwSize = sizeof(MSGQUEUEOPTIONS); msgqopts.dwFlags = 0; msgqopts.cbMaxMessage = QUEUE_ITEM_SIZE; msgqopts.bReadAccess = TRUE; *phQueue = NULL; *phQueue = CreateMsgQueue(NULL, &msgqopts); if(*phQueue == NULL){ return FALSE; } *phNoti = RequestDeviceNotifications(&inGUID, *phQueue, FALSE); if(*phNoti == NULL){ CloseMsgQueue(hPnpQueue); return FALSE; } return TRUE; }
static void destroyDeviceNotificationQueue(HANDLE& queue, HANDLE& notif) { StopDeviceNotifications(notif); CloseMsgQueue(queue); }
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) { RetailPrint (_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 RetailPrint (_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(); RetailPrint (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(); RetailPrint (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(); RetailPrint (_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); RetailPrint (_T("%s: exiting\r\n"), pszFname); return 0; }
void PowerMonitorThread() { MSGQUEUEOPTIONS PowerMsgQOptions = {0,}; HANDLE hPowerMsgQ = NULL; HANDLE hPowerNotifications = NULL; HANDLE rgHandles[2] = {0}; PowerMsgQOptions.dwSize = sizeof(MSGQUEUEOPTIONS); PowerMsgQOptions.dwFlags = MSGQUEUE_NOPRECOMMIT ; PowerMsgQOptions.dwMaxMessages = 0; PowerMsgQOptions.cbMaxMessage = sizeof(POWER_BROADCAST) + sizeof(POWER_BROADCAST_POWER_INFO); PowerMsgQOptions.bReadAccess = TRUE; hPowerMsgQ = CreateMsgQueue(NULL, &PowerMsgQOptions); if( hPowerMsgQ == NULL ) { RETAILMSG(1,(L"[WSM] CreateMsgQueue Failed(%d) \r\n", GetLastError() )); goto Exit; } // Request power notifications hPowerNotifications = RequestPowerNotifications(hPowerMsgQ, PBT_TRANSITION | PBT_RESUME | PBT_POWERINFOCHANGE); if( hPowerNotifications == NULL ) { RETAILMSG(1,(L"[WSM] RequestPowerNotifications Failed(%d) \r\n", GetLastError() )); goto Exit; } rgHandles[0] = hPowerMsgQ; rgHandles[1] = g_hEventClosePwrMonThread; // 1번째 핸들이 아닌경우에는 이 스레드는 Close 된다. (g_hEventClosePwrMonThread 이벤트 인경우 Close) while( WaitForMultipleObjects(2, rgHandles, FALSE, INFINITE) == WAIT_OBJECT_0 ) { DWORD cbRead; DWORD dwFlags; POWER_BROADCAST *ppb = (POWER_BROADCAST*) new BYTE[sizeof(POWER_BROADCAST) + sizeof(POWER_BROADCAST_POWER_INFO)]; // loop through in case there is more than 1 msg. while(ReadMsgQueue(hPowerMsgQ, ppb, sizeof(POWER_BROADCAST) + sizeof(POWER_BROADCAST_POWER_INFO), &cbRead, 0, &dwFlags)) { if( ppb->Message == PBT_TRANSITION ) { if( ppb->Length && wcscmp(ppb->SystemPowerState, L"unattended") == 0 ) { if ( g_bCheckedUnattendedMode == TRUE ) { // Create RepeatSysIdleTimerResetThread g_bRunningRepeatSysIdleTimerResetThread = TRUE; g_hRepeatSysIdleTimerResetThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RepeatSysIdleTimerResetThread, NULL, 0, NULL); if( g_hRepeatSysIdleTimerResetThread == INVALID_HANDLE_VALUE ) { RETAILMSG(1, (TEXT("[ERR] Can't create g_hRepeatSysIdleTimerResetThread \r\n") )); g_hRepeatSysIdleTimerResetThread = NULL; } } } else { // Close RepeatSysIdleTimerResetThread g_bRunningRepeatSysIdleTimerResetThread = FALSE; if( g_hRepeatSysIdleTimerResetThread ) { if( WaitForSingleObject(g_hRepeatSysIdleTimerResetThread, 1000) == WAIT_TIMEOUT ) { DWORD dwCode = 0; GetExitCodeThread(g_hRepeatSysIdleTimerResetThread, &dwCode); if( dwCode == STILL_ACTIVE ) { RETAILMSG(1, (TEXT("[WSM] g_hRepeatSysIdleTimerResetThread Terminate \r\n") )); TerminateThread(g_hRepeatSysIdleTimerResetThread, 0); } } CloseHandle(g_hRepeatSysIdleTimerResetThread); g_hRepeatSysIdleTimerResetThread = NULL; } } } } delete[] ppb; } RETAILMSG(1,(L"[WSM] PowerMonitorThread End \r\n")); Exit: if (hPowerNotifications) { StopPowerNotifications(hPowerNotifications); hPowerNotifications = NULL; } if (hPowerMsgQ) { CloseMsgQueue(hPowerMsgQ); hPowerMsgQ = NULL; } return; }
//*************************************************************************** // Function Name: PowerNotificationThread // // Purpose: listens for power change notifications // DWORD PowerNotificationThread(LPVOID pVoid) { // size of a POWER_BROADCAST message DWORD cbPowerMsgSize = sizeof POWER_BROADCAST + (MAX_PATH * sizeof TCHAR); // Initialize our MSGQUEUEOPTIONS structure MSGQUEUEOPTIONS mqo; mqo.dwSize = sizeof(MSGQUEUEOPTIONS); mqo.dwFlags = MSGQUEUE_NOPRECOMMIT; mqo.dwMaxMessages = 4; mqo.cbMaxMessage = cbPowerMsgSize; mqo.bReadAccess = TRUE; // Create a message queue to receive power notifications HANDLE hPowerMsgQ = CreateMsgQueue(NULL, &mqo); if (NULL == hPowerMsgQ) { RETAILMSG(1, (L"CreateMsgQueue failed: %x\n", GetLastError())); goto Error; } // Request power notifications HANDLE hPowerNotifications = RequestPowerNotifications(hPowerMsgQ, PBT_TRANSITION | PBT_RESUME | PBT_POWERINFOCHANGE); if (NULL == hPowerNotifications) { RETAILMSG(1, (L"RequestPowerNotifications failed: %x\n", GetLastError())); goto Error; } HANDLE rgHandles[2] = {0}; rgHandles[0] = hPowerMsgQ; rgHandles[1] = g_hEventShutDown; // Wait for a power notification or for the app to exit while(WaitForMultipleObjects(2, rgHandles, FALSE, INFINITE) == WAIT_OBJECT_0) { DWORD cbRead; DWORD dwFlags; POWER_BROADCAST *ppb = (POWER_BROADCAST*) new BYTE[cbPowerMsgSize]; // loop through in case there is more than 1 msg while(ReadMsgQueue(hPowerMsgQ, ppb, cbPowerMsgSize, &cbRead, 0, &dwFlags)) { switch (ppb->Message) { case PBT_TRANSITION: RETAILMSG(1,(L"Power Notification Message: PBT_TRANSITION\n")); RETAILMSG(1,(L"Flags: %lx", ppb->Flags)); RETAILMSG(1,(L"Length: %d", ppb->Length)); if (ppb->Length) { RETAILMSG(1,(L"SystemPowerState: %s\n", ppb->SystemPowerState)); } break; case PBT_RESUME: RETAILMSG(1,(L"Power Notification Message: PBT_RESUME\n")); break; case PBT_POWERINFOCHANGE: { RETAILMSG(1,(L"Power Notification Message: PBT_POWERINFOCHANGE\n")); // PBT_POWERINFOCHANGE message embeds a // POWER_BROADCAST_POWER_INFO structure into the // SystemPowerState field PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) ppb->SystemPowerState; if (ppbpi) { RETAILMSG(1,(L"Length: %d", ppb->Length)); RETAILMSG(1,(L"BatteryLifeTime = %d\n",ppbpi->dwBatteryLifeTime)); RETAILMSG(1,(L"BatterFullLifeTime = %d\n", ppbpi->dwBatteryFullLifeTime)); RETAILMSG(1,(L"BackupBatteryLifeTime = %d\n", ppbpi->dwBackupBatteryLifeTime)); RETAILMSG(1,(L"BackupBatteryFullLifeTime = %d\n", ppbpi->dwBackupBatteryFullLifeTime)); RETAILMSG(1,(L"ACLineStatus = %d\n",ppbpi->bACLineStatus)); RETAILMSG(1,(L"BatteryFlag = %d\n",ppbpi->bBatteryFlag)); RETAILMSG(1,(L"BatteryLifePercent = %d\n", ppbpi->bBatteryLifePercent)); RETAILMSG(1,(L"BackupBatteryFlag = %d\n", ppbpi->bBackupBatteryFlag)); RETAILMSG(1,(L"BackupBatteryLifePercent = %d\n", ppbpi->bBackupBatteryLifePercent)); } break; } default: break; } UpdatePowerState(); } delete[] ppb; } Error: if (hPowerNotifications) StopPowerNotifications(hPowerNotifications); if (hPowerMsgQ) CloseMsgQueue(hPowerMsgQ); return NULL; }