2.02.2010

Get Powe Notification : AP

AP 要收到 suspend/wakeup 的通知,可以用 RequestPowerNotifications
Sample Code 在 google groupe 上: PowerChange Notifications : Resume

很好心的把 code 都貼出來,但是我用起來有一點問題,就是 Notification Thread 沒有辦法terminate 掉,

/ John Baik: Sample code for Power Notification

#include <windows.h>
#include <PM.h>
// from pmimpl.h file.
#ifndef QUEUE_ENTRIES
#define QUEUE_ENTRIES 3
#endif
#ifndef MAX_NAMELEN
#define MAX_NAMELEN 128
#endif

#ifndef QUEUE_SIZE
#define QUEUE_SIZE (QUEUE_ENTRIES * (sizeof(POWER_BROADCAST) + \\
(MAX_NAMELEN * sizeof(TCHAR))))
#endif

int WINAPI PMNotifyThread(LPVOID pvParam);
void PMNotification(HANDLE hMsgQ);

HANDLE ghPMNotifyQ = NULL;


int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSGQUEUEOPTIONS msgQpm = {0};
HANDLE hPwrNotify=NULL; // Power manager handle
HANDLE hPMThread=NULL;

// create a message queue for Power Manager notifications
msgQpm.dwSize = sizeof(MSGQUEUEOPTIONS);
msgQpm.dwFlags = 0;
msgQpm.dwMaxMessages = QUEUE_ENTRIES;
msgQpm.cbMaxMessage = sizeof(POWER_BROADCAST) + MAX_NAMELEN;
msgQpm.bReadAccess = TRUE;

ghPMNotifyQ= CreateMsgQueue(NULL, &msgQpm);

if (ghPMNotifyQ == NULL)
{
DWORD dwErr = GetLastError();
RETAILMSG(1, (TEXT(" PMNotify:CreateMessageQueue ERROR:%d \r\n"), dwErr));
return 1;
}

// request Power notifications
hPwrNotify = RequestPowerNotifications(ghPMNotifyQ, PBT_TRANSITION |
PBT_RESUME);

if (hPwrNotify == NULL)
{
DWORD dwErr = GetLastError();
RETAILMSG(1, (TEXT(" PMNotify:RequestPowerNotifications ERROR:%d\r\n"), dwErr));
return 2;
}

// Create PMNotifyThread
hPMThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE )PMNotifyThread, NULL, 0, NULL);

if(hPMThread)
{
// wait for PMNotifyThread done
WaitForSingleObject(hPMThread, INFINITE);
CloseHandle(hPMThread);

if(hPwrNotify)
{
StopPowerNotifications(hPwrNotify);
}
}

return 0;

}

// PMNotifyThread: Wait for Message from PM Driver.
//
int WINAPI PMNotifyThread(LPVOID pvParam)
{
DWORD dwStatus;

while (TRUE)
{
dwStatus = WaitForSingleObject(ghPMNotifyQ, INFINITE);

if(dwStatus == WAIT_OBJECT_0)
{
PMNotification(ghPMNotifyQ);
}
else
{
RETAILMSG(1,
(TEXT(" PMNotify: WaitForSingleObject returned %d (error %d)\r\n"),
dwStatus, GetLastError()));
break;
}
}

return 0;

}

void PMNotification(HANDLE hMsgQ)
{
UCHAR pmbuf[QUEUE_SIZE];
int nBytesRead=0;
DWORD dwFlags = 0;
int dwCount = 0;

memset(pmbuf, 0, sizeof(pmbuf));

if ( !ReadMsgQueue(hMsgQ,
pmbuf,
QUEUE_SIZE,
(LPDWORD)&nBytesRead,
INFINITE, // Timeout
&dwFlags))
{
DWORD dwErr = GetLastError();
RETAILMSG(1,
(TEXT(" ProcessPowerNotification: ReadMsgQueue:ERROR:%d\n"), dwErr));
}
else if(nBytesRead >= sizeof(POWER_BROADCAST))
{
// process power notifications
//-----------------------------
PPOWER_BROADCAST pPB = (PPOWER_BROADCAST) pmbuf;

switch (pPB->Message)
{
case PBT_RESUME:
RETAILMSG(1, (TEXT(" PMNotify:PBT_RESUME \r\n")));
break;

case PBT_POWERSTATUSCHANGE:
RETAILMSG(1, (TEXT(" PMNotify:PBT_POWERSTATUSCHANGE: \r\n")));
break;

case PBT_POWERINFOCHANGE:
RETAILMSG(1, (TEXT(" PMNotify:PBT_POWERSTATUSCHANGE: \r\n")));
break;

case PBT_TRANSITION:
{
switch (POWER_STATE(pPB->Flags))
{
case POWER_STATE_ON:
break;
case POWER_STATE_OFF:
break;
case POWER_STATE_CRITICAL:
break;
case POWER_STATE_BOOT:
break;
case POWER_STATE_IDLE:
break;
case POWER_STATE_SUSPEND:
break;
case POWER_STATE_RESET:
break;
default:
break;
}
break;
}

default:
break;
}
}

}


實際上用要稍微修改一下..
  • PMThread 要有 Exit 的機制 - 在 WaitForSingleObject 加 Timeout check flag 或是用 WaitForMultipleObject 代替
  • WinMain 的 code 其實要分兩部份: InitPowerHandler, ClosePowerHandler. 放在 Dialog Proc 的 WM_INITDIALOG 和 WM_CLOSE

沒有留言: