Skip to content

Commit

Permalink
Add winpowrprof package
Browse files Browse the repository at this point in the history
  • Loading branch information
wwqgtxx authored and nekohasekai committed Feb 22, 2024
1 parent b9ca6f2 commit 886a9a5
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 0 deletions.
13 changes: 13 additions & 0 deletions common/winpowrprof/event.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package winpowrprof

import "io"

const (
EVENT_SUSPEND = iota
EVENT_RESUME
EVENT_RESUME_AUTOMATIC // Because the user is not present, most applications should do nothing.
)

type EventListener interface {
io.Closer
}
11 changes: 11 additions & 0 deletions common/winpowrprof/event_stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//go:build !windows

package winpowrprof

import (
"os"
)

func NewEventListener(callback func(event int)) (EventListener, error) {
return nil, os.ErrInvalid
}
74 changes: 74 additions & 0 deletions common/winpowrprof/event_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package winpowrprof

// modify from https://github.com/golang/go/blob/b634f6fdcbebee23b7da709a243f3db217b64776/src/runtime/os_windows.go#L257

import (
"unsafe"

"golang.org/x/sys/windows"
)

var (
modpowerprof = windows.NewLazySystemDLL("powrprof.dll")
procPowerRegisterSuspendResumeNotification = modpowerprof.NewProc("PowerRegisterSuspendResumeNotification")
procPowerUnregisterSuspendResumeNotification = modpowerprof.NewProc("PowerUnregisterSuspendResumeNotification")
)

type eventListener struct {
callback uintptr
handle uintptr
}

func NewEventListener(callback func(event int)) (EventListener, error) {
if err := procPowerRegisterSuspendResumeNotification.Find(); err != nil {
return nil, err // Running on Windows 7, where we don't need it anyway.
}
if err := procPowerUnregisterSuspendResumeNotification.Find(); err != nil {
return nil, err // Running on Windows 7, where we don't need it anyway.
}

const (
PBT_APMSUSPEND uint32 = 4
PBT_APMRESUMESUSPEND uint32 = 7
PBT_APMRESUMEAUTOMATIC uint32 = 18
)

const (
_DEVICE_NOTIFY_CALLBACK = 2
)
type _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS struct {
callback uintptr
context uintptr
}

var fn interface{} = func(context uintptr, changeType uint32, setting uintptr) uintptr {
switch changeType {
case PBT_APMSUSPEND:
callback(EVENT_SUSPEND)
case PBT_APMRESUMESUSPEND:
callback(EVENT_RESUME)
case PBT_APMRESUMEAUTOMATIC:
callback(EVENT_RESUME_AUTOMATIC)
}
return 0
}
var listener eventListener
listener.callback = windows.NewCallback(fn)
params := _DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS{
callback: listener.callback,
}
_, _, err := procPowerRegisterSuspendResumeNotification.Call(
_DEVICE_NOTIFY_CALLBACK,
uintptr(unsafe.Pointer(&params)),
uintptr(unsafe.Pointer(&listener.handle)),
)
if err != nil {
return nil, err
}
return &listener, nil
}

func (l *eventListener) Close() error {
_, _, err := procPowerUnregisterSuspendResumeNotification.Call(uintptr(unsafe.Pointer(&l.handle)))
return err
}

0 comments on commit 886a9a5

Please sign in to comment.