Skip to content

Commit 886a9a5

Browse files
wwqgtxxnekohasekai
authored andcommitted
Add winpowrprof package
1 parent b9ca6f2 commit 886a9a5

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

common/winpowrprof/event.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package winpowrprof
2+
3+
import "io"
4+
5+
const (
6+
EVENT_SUSPEND = iota
7+
EVENT_RESUME
8+
EVENT_RESUME_AUTOMATIC // Because the user is not present, most applications should do nothing.
9+
)
10+
11+
type EventListener interface {
12+
io.Closer
13+
}

common/winpowrprof/event_stub.go

Lines changed: 11 additions & 0 deletions
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_windows.go

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

0 commit comments

Comments
 (0)