Skip to content

Commit 02535f6

Browse files
wwqgtxxnekohasekai
authored andcommitted
Add winpowrprof package
1 parent c48c8e7 commit 02535f6

File tree

4 files changed

+125
-0
lines changed

4 files changed

+125
-0
lines changed

common/winpowrprof/event.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package winpowrprof
2+
3+
const (
4+
EVENT_SUSPEND = iota
5+
EVENT_RESUME
6+
EVENT_RESUME_AUTOMATIC // Because the user is not present, most applications should do nothing.
7+
)
8+
9+
type EventListener interface {
10+
Start() error
11+
Close() error
12+
}

common/winpowrprof/event_stub.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//go:build !windows
2+
3+
package winpowrprof
4+
5+
import (
6+
"os"
7+
)
8+
9+
func NewEventListener(callback func(event int)) (EventListener, error) {
10+
return nil, os.ErrInvalid
11+
}

common/winpowrprof/event_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package winpowrprof
2+
3+
import (
4+
"runtime"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
func TestPowerEvents(t *testing.T) {
11+
if runtime.GOOS != "windows" {
12+
t.SkipNow()
13+
}
14+
listener, err := NewEventListener(func(event int) {})
15+
require.NoError(t, err)
16+
require.NotNil(t, listener)
17+
require.NoError(t, listener.Start())
18+
require.NoError(t, listener.Close())
19+
}

common/winpowrprof/event_windows.go

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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+
}

0 commit comments

Comments
 (0)