winapi - Hook system power button in Windows -


i have headless computer running custom service want enable/disable using power button, rather having remotely connect every time. computer other things well, turning off not option.

is possible hook system power button under windows xp & up, such program event before windows initiates powerdown/sleep event (before pbt_apmquerysuspend event sent out)?

this indeed possible, it's bit hackish , requires 2 different implementations depending on windows version. both methods, need set power button put computer sleep in power options.

windows xp , below:

you need overwrite program's main window's wndproc function. on ides don't support natively, can done using setwindowlong in user32 api. in custom wndproc function, listen wm_powerbroadcast (0x218) message. if receive message wparam of pbt_apmquerysuspend (0x0), call wanted function , return broadcast_query_deny (0x424d5144) instead of calling base wndproc function. example code:

//at program start //gwl_wndproc = -4 oldwndproc = setwindowlong(this.hwnd, gwl_wndproc, &mywndproc)  //in mywndproc(hwnd, wmsg, wparam, lparam) //wm_powerbroadcast = 0x218 //pbt_apmquerysuspend = 0x0 //broadcast_query_deny = 0x424d5144 if wmsg = wm_powerbroadcast && wparam = pbt_apmquerysuspend (     //call function here!     return broadcast_query_deny ) return callwindowproc(oldwndproc, hwnd, wmsg, wparam, lparam)  //before exiting setwindowlong(me.hwnd, gwl_wndproc, oldwndproc) 

windows vista & up: (thanks remy lebeau setting me on right track)

you need override wndproc xp, call setthreadexecutionstate in kernel32 api disable sleep mode , registerpowersettingnotification in user32 api listen advanced power notifications. listening, in particular, guid_system_awaymode notification, gets sent out when system asked go sleep unable so. convert string formed lpcguid can use uuidfromstringa in rpcrt4.dll api. example code:

typedef struct uuid{     int d1, d2, d3, d4 } lpcguid;  //at program start //gwl_wndproc = -4 //es_continuous = 0x80000000 //es_system_required = 0x1 //es_awaymode_required = 0x40 //guid_system_awaymode = "98a7f580-01f7-48aa-9c0f-44352c29e5c0" lpcguid uid; oldwndproc = setwindowlong(this.hwnd, gwl_wndproc, &mywndproc) setthreadexecutionstate(es_continuous | es_system_required | es_awaymode_required) uuidfromstringa(*(guid_system_awaymode), uid) ps = registerpowersettingnotification(this.hwnd, uid, 0)  //in mywndproc(hwnd, wmsg, wparam, lparam) //wm_powerbroadcast = 0x218 //pbt_powersettingchange = 0x8013 if wmsg = wm_powerbroadcast && wparam = pbt_powersettingchange (     //call function here!     //you can additionally extract data lparam verify     //this notification you're waiting (see below) ) return callwindowproc(oldwndproc, hwnd, wmsg, wparam, lparam)  //before exiting setwindowlong(me.hwnd, gwl_wndproc, oldwndproc) unregisterpowersettingnotification(ps) 

this method has side effect of turning off physical screen (not problem on headless machine), , possibly locking session. make sure disable prompting password after sleeping avoid this. there's additional useful information on registerpowersettingnotification available here shows how extract information lparam in wndproc function in case want additional info on notification. have fun ;)