github.com/sagernet/sing@v0.4.0-beta.19.0.20240518125136-f67a0988a636/common/winpowrprof/event_windows.go (about) 1 package winpowrprof 2 3 // modify from https://github.com/golang/go/blob/b634f6fdcbebee23b7da709a243f3db217b64776/src/runtime/os_windows.go#L257 4 5 import ( 6 "syscall" 7 "unsafe" 8 9 "golang.org/x/sys/windows" 10 ) 11 12 var ( 13 modpowerprof = windows.NewLazySystemDLL("powrprof.dll") 14 procPowerRegisterSuspendResumeNotification = modpowerprof.NewProc("PowerRegisterSuspendResumeNotification") 15 procPowerUnregisterSuspendResumeNotification = modpowerprof.NewProc("PowerUnregisterSuspendResumeNotification") 16 ) 17 18 const ( 19 PBT_APMSUSPEND uint32 = 4 20 PBT_APMRESUMESUSPEND uint32 = 7 21 PBT_APMRESUMEAUTOMATIC uint32 = 18 22 ) 23 24 const ( 25 _DEVICE_NOTIFY_CALLBACK = 2 26 ) 27 28 type _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct { 29 callback uintptr 30 context uintptr 31 } 32 33 type eventListener struct { 34 params _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS 35 handle uintptr 36 } 37 38 func NewEventListener(callback func(event int)) (EventListener, error) { 39 if err := procPowerRegisterSuspendResumeNotification.Find(); err != nil { 40 return nil, err // Running on Windows 7, where we don't need it anyway. 41 } 42 if err := procPowerUnregisterSuspendResumeNotification.Find(); err != nil { 43 return nil, err // Running on Windows 7, where we don't need it anyway. 44 } 45 46 var fn interface{} = func(context uintptr, changeType uint32, setting uintptr) uintptr { 47 switch changeType { 48 case PBT_APMSUSPEND: 49 callback(EVENT_SUSPEND) 50 case PBT_APMRESUMESUSPEND: 51 callback(EVENT_RESUME) 52 case PBT_APMRESUMEAUTOMATIC: 53 callback(EVENT_RESUME_AUTOMATIC) 54 } 55 return 0 56 } 57 return &eventListener{ 58 params: _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS{ 59 callback: windows.NewCallback(fn), 60 }, 61 }, nil 62 } 63 64 func (l *eventListener) Start() error { 65 _, _, errno := syscall.SyscallN( 66 procPowerRegisterSuspendResumeNotification.Addr(), 67 _DEVICE_NOTIFY_CALLBACK, 68 uintptr(unsafe.Pointer(&l.params)), 69 uintptr(unsafe.Pointer(&l.handle)), 70 ) 71 if errno != 0 { 72 return errno 73 } 74 return nil 75 } 76 77 func (l *eventListener) Close() error { 78 _, _, errno := syscall.SyscallN(procPowerUnregisterSuspendResumeNotification.Addr(), uintptr(unsafe.Pointer(&l.handle))) 79 if errno != 0 { 80 return errno 81 } 82 return nil 83 }