@@ -3,134 +3,89 @@ package winpowrprof
33// modify from https://github.com/golang/go/blob/b634f6fdcbebee23b7da709a243f3db217b64776/src/runtime/os_windows.go#L257
44
55import (
6- "sync"
76 "syscall"
87 "unsafe"
98
10- "github.com/sagernet/sing/common/x/list "
9+ "github.com/sagernet/sing/common"
1110
1211 "golang.org/x/sys/windows"
1312)
1413
15- type powerEventListener struct {
16- element * list.Element [EventCallback ]
17- }
18-
19- func NewEventListener (callback EventCallback ) (EventListener , error ) {
20- err := initCallback ()
21- if err != nil {
22- return nil , err
23- }
24- access .Lock ()
25- defer access .Unlock ()
26- return & powerEventListener {
27- element : callbackList .PushBack (callback ),
28- }, nil
29- }
30-
31- func (l * powerEventListener ) Start () error {
32- access .Lock ()
33- defer access .Unlock ()
34- if handle != 0 {
35- return nil
36- }
37- return startListener ()
38- }
39-
40- func (l * powerEventListener ) Close () error {
41- access .Lock ()
42- defer access .Unlock ()
43- if l .element != nil {
44- callbackList .Remove (l .element )
45- }
46- if callbackList .Len () > 0 {
47- return nil
48- }
49- return closeListener ()
50- }
51-
5214var (
5315 modpowerprof = windows .NewLazySystemDLL ("powrprof.dll" )
5416 procPowerRegisterSuspendResumeNotification = modpowerprof .NewProc ("PowerRegisterSuspendResumeNotification" )
5517 procPowerUnregisterSuspendResumeNotification = modpowerprof .NewProc ("PowerUnregisterSuspendResumeNotification" )
5618)
5719
58- var (
59- access sync.Mutex
60- callbackList list.List [EventCallback ]
61- initCallbackOnce sync.Once
62- rawCallback uintptr
63- handle uintptr
64- )
20+ var suspendResumeNotificationCallback = common .OnceValue (func () uintptr {
21+ return windows .NewCallback (func (context * EventCallback , changeType uint32 , setting uintptr ) uintptr {
22+ callback := * context
23+ const (
24+ PBT_APMSUSPEND uint32 = 4
25+ PBT_APMRESUMESUSPEND uint32 = 7
26+ PBT_APMRESUMEAUTOMATIC uint32 = 18
27+ )
28+ var event int
29+ switch changeType {
30+ case PBT_APMSUSPEND :
31+ event = EVENT_SUSPEND
32+ case PBT_APMRESUMESUSPEND :
33+ event = EVENT_RESUME
34+ case PBT_APMRESUMEAUTOMATIC :
35+ event = EVENT_RESUME_AUTOMATIC
36+ default :
37+ return 0
38+ }
39+ callback (event )
40+ return 0
41+ })
42+ })
6543
66- func initCallback () error {
44+ type powerEventListener struct {
45+ callback EventCallback
46+ handle uintptr
47+ }
48+
49+ func NewEventListener (callback EventCallback ) (EventListener , error ) {
6750 err := procPowerRegisterSuspendResumeNotification .Find ()
6851 if err != nil {
69- return err // Running on Windows 7, where we don't need it anyway.
52+ return nil , err // Running on Windows 7, where we don't need it anyway.
7053 }
7154 err = procPowerUnregisterSuspendResumeNotification .Find ()
7255 if err != nil {
73- return err // Running on Windows 7, where we don't need it anyway.
56+ return nil , err // Running on Windows 7, where we don't need it anyway.
7457 }
75- initCallbackOnce .Do (func () {
76- rawCallback = windows .NewCallback (func (context uintptr , changeType uint32 , setting uintptr ) uintptr {
77- const (
78- PBT_APMSUSPEND uint32 = 4
79- PBT_APMRESUMESUSPEND uint32 = 7
80- PBT_APMRESUMEAUTOMATIC uint32 = 18
81- )
82- var event int
83- switch changeType {
84- case PBT_APMSUSPEND :
85- event = EVENT_SUSPEND
86- case PBT_APMRESUMESUSPEND :
87- event = EVENT_RESUME
88- case PBT_APMRESUMEAUTOMATIC :
89- event = EVENT_RESUME_AUTOMATIC
90- default :
91- return 0
92- }
93- access .Lock ()
94- callbacks := callbackList .Array ()
95- access .Unlock ()
96- for _ , callback := range callbacks {
97- callback (event )
98- }
99- return 0
100- })
101- })
102- return nil
58+ return & powerEventListener {
59+ callback : callback ,
60+ }, nil
10361}
10462
105- func startListener () error {
63+ func ( l * powerEventListener ) Start () error {
10664 type DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct {
10765 callback uintptr
108- context uintptr
66+ context unsafe. Pointer
10967 }
11068 const DEVICE_NOTIFY_CALLBACK = 2
11169 params := DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS {
112- callback : rawCallback ,
70+ callback : suspendResumeNotificationCallback (),
71+ context : unsafe .Pointer (& l .callback ),
11372 }
11473 _ , _ , errno := syscall .SyscallN (
11574 procPowerRegisterSuspendResumeNotification .Addr (),
11675 DEVICE_NOTIFY_CALLBACK ,
11776 uintptr (unsafe .Pointer (& params )),
118- uintptr (unsafe .Pointer (& handle )),
77+ uintptr (unsafe .Pointer (& l . handle )),
11978 )
12079 if errno != 0 {
12180 return errno
12281 }
12382 return nil
12483}
12584
126- func closeListener () error {
127- if handle == 0 {
128- return nil
129- }
130- _ , _ , errno := syscall .SyscallN (procPowerUnregisterSuspendResumeNotification .Addr (), uintptr (unsafe .Pointer (& handle )))
85+ func (l * powerEventListener ) Close () error {
86+ _ , _ , errno := syscall .SyscallN (procPowerUnregisterSuspendResumeNotification .Addr (), uintptr (unsafe .Pointer (& l .handle )))
13187 if errno != 0 {
13288 return errno
13389 }
134- handle = 0
13590 return nil
13691}
0 commit comments