aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-06-06 15:24:18 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-06-07 11:31:53 +0200
commit66b2b9eacff6e824f75afd9453e3dbf6ed9bcf8a (patch)
tree982acc6852813f8fdfefa71943b8b039e1256054
parentfirewall: GUID generation is now upstream (diff)
downloadwireguard-windows-66b2b9eacff6e824f75afd9453e3dbf6ed9bcf8a.tar.xz
wireguard-windows-66b2b9eacff6e824f75afd9453e3dbf6ed9bcf8a.zip
tunnel: release SCM locks by faking an early start before wintun init
Otherwise creating the wintun service deadlocks the entire SCM on Windows 8.1. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to '')
-rw-r--r--tunnel/service.go35
1 files changed, 35 insertions, 0 deletions
diff --git a/tunnel/service.go b/tunnel/service.go
index 97ffb551..ffb71db5 100644
--- a/tunnel/service.go
+++ b/tunnel/service.go
@@ -16,8 +16,11 @@ 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"
"golang.zx2c4.com/wireguard/ipc"
"golang.zx2c4.com/wireguard/tun"
@@ -33,6 +36,29 @@ 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}
@@ -126,6 +152,15 @@ 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}
+ }
+
log.Println("Resolving DNS names")
uapiConf, err := conf.ToUAPI()
if err != nil {