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; }
static void destroyDeviceNotificationQueue(HANDLE& queue, HANDLE& notif) { StopDeviceNotifications(notif); CloseMsgQueue(queue); }
DWORD WINAPI PnpThreadProc(LPVOID lpvParam) { DWORD dwStatus; HANDLE hnGeneric = NULL; HANDLE hevReady = (HANDLE) lpvParam; HANDLE hEvents[MAXIMUM_WAIT_OBJECTS]; DWORD dwNumEvents = 0; BOOL fDone = FALSE; BOOL fOk; INT iPriority; PDEVICE_LIST pdl; SETFNAME(_T("PnpThreadProc")); PMLOGMSG(ZONE_INIT, (_T("+%s: thread 0x%08x\r\n"), pszFname, GetCurrentThreadId())); // set the thread priority if(!GetPMThreadPriority(_T("PnPPriority256"), &iPriority)) { iPriority = DEF_PNP_THREAD_PRIORITY; } CeSetThreadPriority(GetCurrentThread(), iPriority); // first list entry is the exit event hEvents[dwNumEvents++] = ghevPmShutdown; // set up device notifications for(pdl = gpDeviceLists; pdl != NULL && dwNumEvents < dim(hEvents); pdl = pdl->pNext) { hEvents[dwNumEvents++] = pdl->hMsgQ; pdl->hnClass = RequestDeviceNotifications(pdl->pGuid, pdl->hMsgQ, TRUE); if(pdl->hnClass == NULL) { PMLOGMSG(ZONE_WARN, (_T("%s: RequestDeviceNotifications() failed %d\r\n"), pszFname, GetLastError())); } } DEBUGCHK(dwNumEvents > 1); // we're up and running SetEvent(hevReady); // Wait for Initalization complete. HANDLE hInit[2] = {ghevPowerManagerReady, ghevPmShutdown}; fDone = (WaitForMultipleObjects(_countof(hInit), hInit, FALSE, INFINITE)!= WAIT_OBJECT_0); // wait for new devices to arrive while(!fDone) { dwStatus = WaitForMultipleObjects(dwNumEvents, hEvents, FALSE, INFINITE); if(dwStatus == (WAIT_OBJECT_0 + 0)) { PMLOGMSG(ZONE_WARN, (_T("%s: shutdown event set\r\n"), pszFname)); fDone = TRUE; } else if(dwStatus > WAIT_OBJECT_0 && dwStatus <= (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS)) { dwStatus -= WAIT_OBJECT_0; fOk = ProcessPnPMsgQueue(hEvents[dwStatus]); if(!fOk) { PMLOGMSG(ZONE_WARN, (_T("%s: ProcessPnPMsgQueue(0x%08x) failed\r\n"), pszFname, hEvents[dwStatus])); } } else { PMLOGMSG(ZONE_WARN, (_T("%s: WaitForMultipleObjects() returned %d, status is %d\r\n"), pszFname, dwStatus, GetLastError())); fDone = TRUE; break; } } // release resources for(pdl = gpDeviceLists; pdl != NULL; pdl = pdl->pNext) { if(pdl->hnClass != NULL) StopDeviceNotifications(pdl->hnClass); } // all done PMLOGMSG(ZONE_INIT | ZONE_WARN, (_T("-%s: exiting\r\n"), pszFname)); return 0; }