From 581ad18db14c673e7c074e2505b81c3398b176e6 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 7 Jun 2019 11:23:10 +0200 Subject: tunnel: SCM lock status is upstream now Signed-off-by: Jason A. Donenfeld --- tunnel/service.go | 43 +++++++++++-------------------------------- 1 file 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") -- cgit v1.2.3-59-g8ed1b