aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-06-07 11:23:10 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-06-09 10:25:59 +0200
commit581ad18db14c673e7c074e2505b81c3398b176e6 (patch)
treebffa62fae3a126eb67ca15e7877c93d25f2f2f3d
parentmanager: set sidtype using upstream method (diff)
downloadwireguard-windows-581ad18db14c673e7c074e2505b81c3398b176e6.tar.xz
wireguard-windows-581ad18db14c673e7c074e2505b81c3398b176e6.zip
tunnel: SCM lock status is upstream now
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--tunnel/service.go43
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")