diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-06-07 11:23:10 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-06-09 10:25:59 +0200 |
commit | 581ad18db14c673e7c074e2505b81c3398b176e6 (patch) | |
tree | bffa62fae3a126eb67ca15e7877c93d25f2f2f3d /tunnel/service.go | |
parent | manager: set sidtype using upstream method (diff) | |
download | wireguard-windows-581ad18db14c673e7c074e2505b81c3398b176e6.tar.xz wireguard-windows-581ad18db14c673e7c074e2505b81c3398b176e6.zip |
tunnel: SCM lock status is upstream now
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to '')
-rw-r--r-- | tunnel/service.go | 43 |
1 files changed, 11 insertions, 32 deletions
diff --git a/tunnel/service.go b/tunnel/service.go index ffb71db5..8a045aab 100644 --- a/tunnel/service.go +++ b/tunnel/service.go @@ -16,9 +16,7 @@ import ( "runtime/debug" "strings" "time" - "unsafe" - "golang.org/x/sys/windows" "golang.org/x/sys/windows/svc" "golang.org/x/sys/windows/svc/mgr" "golang.zx2c4.com/wireguard/device" @@ -36,29 +34,6 @@ type Service struct { Path string } -// TODO: integrate into x/sys/windows/svc/mgr -func scmIsLocked() bool { - type lockStatus struct { - isLocked uint32 - owner *uint16 - duration uint32 - ownerData [1024]uint16 - } - status := &lockStatus{} - s, err := mgr.Connect() - if err == nil { - var needed uint32 - windows.NewLazySystemDLL("advapi32.dll").NewProc("QueryServiceLockStatusW").Call( - uintptr(s.Handle), - uintptr(unsafe.Pointer(status)), - uintptr(unsafe.Sizeof(lockStatus{})), - uintptr(unsafe.Pointer(&needed)), - ) - s.Disconnect() - } - return status.isLocked != 0 -} - func (service *Service) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (svcSpecificEC bool, exitCode uint32) { changes <- svc.Status{State: svc.StartPending} @@ -152,13 +127,17 @@ func (service *Service) Execute(args []string, r <-chan svc.ChangeRequest, chang log.Println("Starting", version.UserAgent()) - if scmIsLocked() { - /* If we don't do this, then the Wintun installation will block forever, because - * Windows doesn't like starting a service from a service that hasn't started, but - * only when it's in the phase of autostarting services at boot, and even then, - * seemingly only on Windows 8.1. - */ - changes <- svc.Status{State: svc.Running} + if m, err := mgr.Connect(); err == nil { + if lockStatus, err := m.LockStatus(); err == nil && lockStatus.IsLocked { + /* If we don't do this, then the Wintun installation will block forever, because + * installing a Wintun device starts a service too. Apparently at boot time, Windows + * 8.1 locks the SCM for each service start, creating a deadlock if we don't announce + * that we're running before starting additional services. + */ + log.Printf("SCM locked for %v by %s, marking service as started", lockStatus.Age, lockStatus.Owner) + changes <- svc.Status{State: svc.Running} + } + m.Disconnect() } log.Println("Resolving DNS names") |