Esempio n. 1
0
std::size_t PipeIODevice::onRead(char* buffer, std::size_t count, bool& eof)
{
    if( Read != _mode )
        throw IOError( PT_ERROR_MSG("Could not read from write only pipe") );

    DWORD readBytes = 0;
    DWORD flags     = 0;
    eof = false;

    DWORD timeout = _timeout == EventLoop::WaitInfinite ? INFINITE 
                                                        : static_cast<std::size_t>(_timeout);

    if(_bufferSize) 
    {
        readBytes = _bufferSize;
    }
    else if ( FALSE == ReadMsgQueue(handle(), &_buffer[0], _msgSize, &readBytes, timeout, &flags) ) 
    {
        throw IOError("ReadMsgQueue failed");
    }

    memcpy(buffer, &_buffer[0], count);
    _bufferSize = 0;

    if (count >= readBytes)
        return readBytes;

    std::vector<char>::iterator beginData = (_buffer.begin() + count);
    std::vector<char>::iterator endData   = (_buffer.begin() + readBytes);
    std::copy(beginData, endData, _buffer.begin());
    _bufferSize = (readBytes - count);

    return count;
}
Esempio n. 2
0
std::size_t PipeIODevice::onEndRead(EventLoop& loop, char* buffer, std::size_t n, bool& eof)
{
    loop.selector().disable(_ioh);

    DWORD readBytes = 0;
    DWORD flags     = 0;
    eof = false;

    // TODO: can we receive EOF?

    if (_bufferSize)
    {
        readBytes = _bufferSize;
    }
    else if ( FALSE == ReadMsgQueue(handle(), &_buffer[0], _msgSize, &readBytes, INFINITE, &flags) )
    {
        throw IOError( PT_ERROR_MSG("Could not read from message queue handle") );
    }

    DWORD bytesToCopy = std::min<DWORD>(_rbuflen, readBytes);

    memcpy(_rbuf, &_buffer[0], bytesToCopy);
    _bufferSize = 0;

    if (_rbuflen >= readBytes)
        return readBytes;

    std::vector<char>::iterator beginData = (_buffer.begin() + bytesToCopy);
    std::vector<char>::iterator endData   = (_buffer.begin() + readBytes);
    std::copy(beginData, endData, _buffer.begin());

    _bufferSize = (readBytes - bytesToCopy);
    return bytesToCopy;
}
Esempio n. 3
0
// --------------------------------------------------------------------
BOOL ReadPnpMsgQueue(HANDLE hQueue, PDEVDETAIL pDevDetail, DWORD dwTimeout)
// --------------------------------------------------------------------
{
    DWORD dwRead = 0;
    DWORD dwFlags =0;
    return ReadMsgQueue(hQueue, pDevDetail, QUEUE_ITEM_SIZE, &dwRead, 
        dwTimeout, &dwFlags);
}
Esempio n. 4
0
// this routine reads device notifications from a message queue and updates
// the PM's internal tables appropriately.
BOOL
ProcessPnPMsgQueue(HANDLE hMsgQ)
{
    BOOL fOk = FALSE;
    UCHAR deviceBuf[PNP_QUEUE_SIZE];
    DWORD iBytesInQueue = 0;
    DWORD dwFlags = 0;
    SETFNAME(_T("ProcessPnPMsgQueue"));

    // 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
        PMLOGMSG(ZONE_WARN, (_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]))) {
            PMLOGMSG(ZONE_WARN, (_T("%s: device name longer than %d characters\r\n"), 
                pszFname, PNP_MAX_NAMELEN - 1));
        } else {
            // convert the device name to lower case
            int i;
            for(i = 0; i < (PNP_MAX_NAMELEN - 1) && pDevDetail->szName[i] != 0; i++) {
                pDevDetail->szName[i] = _totlower(pDevDetail->szName[i]);
            }
            pDevDetail->szName[i] = 0;
            
            // add or remove the device -- note that a particular interface may be
            // advertised more than once, so these routines must handle that possibility.
            if(pDevDetail->fAttached) {
                AddDevice(&pDevDetail->guidDevClass, pDevDetail->szName, NULL, NULL);
            } else {
                RemoveDevice(&pDevDetail->guidDevClass, pDevDetail->szName);
            }
            fOk = TRUE;
        }
    } else {
        // not enough bytes for a message
        PMLOGMSG(ZONE_WARN, (_T("%s: got runt message (%d bytes)\r\n"), pszFname, 
            iBytesInQueue));
    }

    return fOk;
}
static void checkDeviceNotificationQueue(HANDLE& queue)
{
    const DWORD maxBufLen = sizeof(DEVDETAIL) + MAX_DEVCLASS_NAMELEN;
    char buf[maxBufLen];
    DWORD bytesRead;
    DWORD flags;

    while (ReadMsgQueue(queue, &buf, maxBufLen, &bytesRead, 0, &flags)) {
        DEVDETAIL* detail = reinterpret_cast<DEVDETAIL*>(buf);
        if (detail->fAttached) {
            wprintf(L"\nDevice attached: %s\n", detail->szName);
        } else {
            wprintf(L"\nDevice detached: %s\n", detail->szName);
        }
    }
}
Esempio n. 6
0
DWORD msgThread(LPVOID lpParam){
	HWND hWnd = (HWND)lpParam;
	hwndMsg=hWnd;

	DEBUGMSG(1,(L"Waiting for Bluetooth notifications with hwnd=%i...\n", hWnd));
	nclog(L"%s: Waiting for Bluetooth notifications...\n", logDateTime());
	
	TCHAR szMsg[MAX_PATH];
	wsprintf(szMsg, L"\r\n%s: Waiting for Bluetooth notifications...", logDateTime());
	printMsg(szMsg, hWnd);

	BTEVENT btEvent;
	DWORD dwBytesRead;
	DWORD dwFlags;
	BOOL fRet;

	while (FALSE == bStop) {
		DWORD dwWait = WaitForSingleObject (hMsgQ, 5000);//wait up to 5 seconds INFINITE);
		switch (dwWait){
			case WAIT_OBJECT_0:
				// We have got a Bluetooth event!
				dwFlags = 0;
				dwBytesRead = 0;

				fRet = ReadMsgQueue (hMsgQ, &btEvent, sizeof(BTEVENT), &dwBytesRead, 10, &dwFlags);
				if (! fRet) {
					DEBUGMSG(1,(L"Error - Failed to read message from queue!\n"));
					//bStop=TRUE;
				} 
				else {
					dumpBTevent(btEvent, hWnd);
				}
				break;
			case WAIT_TIMEOUT:
				break;
			case WAIT_ABANDONED:
				DEBUGMSG(1,(L"Error - Unexpected return value from WaitForSingleObject!\n"));
				//bStop=TRUE;
				break;
			case WAIT_FAILED:
				DEBUGMSG(1,(L"Error - Unexpected return value from WaitForSingleObject!\n"));
				//bStop=TRUE;
				break;
		}//switch
	}//while
	return 0;
}
Esempio n. 7
0
void ProcessPowerNotification(HANDLE hMsgQ)
{
    union {
        UCHAR buf[QUEUE_SIZE];
        POWER_BROADCAST powerBroadcast;
    } u;
    int iBytesInQueue;
    DWORD dwFlags = 0;
    int dwCount = 0;
    LPTSTR pszFname = _T("PMMON!ProcessPowerNotification");

    iBytesInQueue = 0;
    memset(u.buf, 0, QUEUE_SIZE);

    if ( !ReadMsgQueue(hMsgQ,
                       u.buf,
                       QUEUE_SIZE,
                       &iBytesInQueue,
                       INFINITE,    // Timeout
                       &dwFlags))
    {
        DWORD dwErr = GetLastError();
        RetailPrint  (TEXT("%s: ReadMsgQueue: ERROR:%d\n"), pszFname, dwErr);
        ASSERT(0);
    } else if(iBytesInQueue >= sizeof(POWER_BROADCAST)) {
        //
        // process power notifications
        //
        PPOWER_BROADCAST pB = &u.powerBroadcast;
        dwFlags = pB->Flags;

        RetailPrint  (TEXT("%s: *** Power Notification @ Tick:%u, Count:%d***\n"), pszFname,
                      GetTickCount(), dwCount++);
        switch (pB->Message)
        {
        case PBT_TRANSITION:
            RetailPrint  (TEXT("%s:\tPBT_TRANSITION to system power state: '%s'\n"), pszFname, pB->SystemPowerState);
            RetailPrint  (TEXT("%s:\t0x%08x "), pszFname, dwFlags);
            {
                struct {
                    DWORD dwFlag;
                    LPCTSTR pszFlagName;
                } sFlagInfo[] = {
                    FLAGINFO(POWER_STATE_ON),
                    FLAGINFO(POWER_STATE_OFF),
                    FLAGINFO(POWER_STATE_CRITICAL),
                    FLAGINFO(POWER_STATE_BOOT),
                    FLAGINFO(POWER_STATE_IDLE),
                    FLAGINFO(POWER_STATE_SUSPEND),
                    FLAGINFO(POWER_STATE_RESET),
                    FLAGINFO(POWER_STATE_PASSWORD),
                };
                int i;

                // display each bit that's in the mask
                for(i = 0; i < dim(sFlagInfo); i++) {
                    if((dwFlags & sFlagInfo[i].dwFlag) != 0) {
                        RetailPrint  (TEXT("%s "), sFlagInfo[i].pszFlagName);
                        dwFlags &= ~sFlagInfo[i].dwFlag;        // mask off the bit
                    }
                }
                if(dwFlags != 0) {
                    RetailPrint  (TEXT("***UNKNOWN***"));
                }
            }
            RetailPrint  (TEXT("\r\n"));
            break;

        case PBT_RESUME:
            RetailPrint  (TEXT("%s:\tPBT_RESUME\n"), pszFname);
            break;

        case PBT_POWERSTATUSCHANGE:
            RetailPrint  (TEXT("%s:\tPBT_POWERSTATUSCHANGE\n"), pszFname);
            break;

        case PBT_POWERINFOCHANGE:
        {
            PPOWER_BROADCAST_POWER_INFO ppbpi = (PPOWER_BROADCAST_POWER_INFO) pB->SystemPowerState;

            RetailPrint  (TEXT("%s:\tPBT_POWERINFOCHANGE\n"), pszFname);
            RetailPrint  (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);
            RetailPrint  (TEXT("%s:\t\tbattery life %d, backup life %d\n"), pszFname,
                          ppbpi->bBatteryLifePercent, ppbpi->bBackupBatteryLifePercent);
            RetailPrint  (TEXT("%s:\t\tlifetime 0x%08x, full lifetime 0x%08x\n"), pszFname,
                          ppbpi->dwBatteryLifeTime, ppbpi->dwBatteryFullLifeTime);
            RetailPrint  (TEXT("%s:\t\tbackup lifetime 0x%08x, backup full lifetime 0x%08x\n"), pszFname,
                          ppbpi->dwBackupBatteryLifeTime, ppbpi->dwBackupBatteryFullLifeTime);
        }
        break;

        default:
            RetailPrint  (TEXT("%s:\tUnknown Message:%d\n"), pszFname, pB->Message);
            break;
        }

        RetailPrint  (TEXT("%s:\tMessage: 0x%x\n"), pszFname, pB->Message);
        RetailPrint  (TEXT("%s:\tFlags: 0x%x\n"), pszFname, pB->Flags);
        RetailPrint  (TEXT("%s:\tdwLen: %d\n"), pszFname, pB->Length);

        RetailPrint  (TEXT("%s:***********************\n"), pszFname);
    } else {
        RetailPrint  (TEXT("%s:\tReceived short message: %d bytes\n"), pszFname, iBytesInQueue);
        ASSERT(0);
    }
}
Esempio n. 8
0
void
ProcessDeviceNotification(HANDLE hMsgQ)
{
    union {
        UCHAR deviceBuf[PNP_QUEUE_SIZE];
        DEVDETAIL devDetail;
    } u;
    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(u.deviceBuf, 0, PNP_QUEUE_SIZE);
    if ( !ReadMsgQueue(hMsgQ, u.deviceBuf, PNP_QUEUE_SIZE, &iBytesInQueue, 0, &dwFlags)) {
        // nothing in the queue
        RetailPrint  (_T("%s: ReadMsgQueue() failed %d\r\n"), pszFname,
                      GetLastError());
    } else if(iBytesInQueue >= sizeof(DEVDETAIL)) {
        // process the message
        PDEVDETAIL pDevDetail = &u.devDetail;
        //DWORD dwMessageSize = sizeof(DEVDETAIL) + pDevDetail->cbName;

        // check for overlarge names
        if(pDevDetail->cbName > ((PNP_MAX_NAMELEN - 1) * sizeof(pDevDetail->szName[0]))) {
            RetailPrint  (_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>")));
            }

            RetailPrint
            (_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
        RetailPrint  (_T("%s: got runt message (%d bytes)\r\n"), pszFname,
                      iBytesInQueue);
    }
}
Esempio n. 9
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;

}
Esempio n. 10
0
//***************************************************************************
// 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;
}