diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-04-27 09:30:50 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-04-27 11:49:50 +0200 |
commit | ed3b2d2812eaec765b4c348081a6e471c7b1aaab (patch) | |
tree | afddee66dc01e3925938e4d53a280a372c87e830 /service | |
parent | ui: simplify everything (diff) | |
download | wireguard-windows-ed3b2d2812eaec765b4c348081a6e471c7b1aaab.tar.xz wireguard-windows-ed3b2d2812eaec765b4c348081a6e471c7b1aaab.zip |
service: create environment for user
Diffstat (limited to 'service')
-rw-r--r-- | service/service_manager.go | 36 | ||||
-rw-r--r-- | service/zsyscall_windows.go | 33 |
2 files changed, 69 insertions, 0 deletions
diff --git a/service/service_manager.go b/service/service_manager.go index 3d7449bd..b3752d31 100644 --- a/service/service_manager.go +++ b/service/service_manager.go @@ -15,6 +15,7 @@ import ( "runtime/debug" "sync" "syscall" + "unicode/utf16" "unsafe" ) @@ -55,6 +56,34 @@ type wellKnownSidType uint32 //sys wtsEnumerateSessions(handle windows.Handle, reserved uint32, version uint32, sessions **wtsSessionInfo, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW //sys wtsFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory +//sys createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock +//sys destroyEnvironmentBlock(block uintptr) (err error) = userenv.DestroyEnvironmentBlock + +func userEnviron(token windows.Token) (env []string, err error) { + var block uintptr + err = createEnvironmentBlock(&block, token, false) + if err != nil { + return + } + offset := uintptr(0) + for { + entry := (*[1<<30 - 1]uint16)(unsafe.Pointer(block + offset))[:] + for i, v := range entry { + if v == 0 { + entry = entry[:i] + break + } + } + if len(entry) == 0 { + break + } + env = append(env, string(utf16.Decode(entry))) + offset += 2 * (uintptr(len(entry)) + 1) + } + destroyEnvironmentBlock(block) + return +} + type managerService struct{} func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (svcSpecificEC bool, exitCode uint32) { @@ -175,12 +204,19 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest return } + env, err := userEnviron(userToken) + if err != nil { + log.Printf("Unable to determine user environment: %v", err) + return + } + log.Printf("Starting UI process for user: '%s@%s'", username, domain) attr := &os.ProcAttr{ Sys: &syscall.SysProcAttr{ Token: syscall.Token(userToken), }, Files: []*os.File{devNull, devNull, devNull}, + Env: env, } proc, err := os.StartProcess(path, []string{path, "/ui", theirReaderStr, theirWriterStr, theirEventStr, theirLogMapping}, attr) theirReader.Close() diff --git a/service/zsyscall_windows.go b/service/zsyscall_windows.go index d3ca8ddd..40bac8ff 100644 --- a/service/zsyscall_windows.go +++ b/service/zsyscall_windows.go @@ -38,12 +38,15 @@ func errnoErr(e syscall.Errno) error { var ( modwtsapi32 = windows.NewLazySystemDLL("wtsapi32.dll") + moduserenv = windows.NewLazySystemDLL("userenv.dll") modadvapi32 = windows.NewLazySystemDLL("advapi32.dll") modkernel32 = windows.NewLazySystemDLL("kernel32.dll") procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken") procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW") procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory") + procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") + procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") procSleepEx = modkernel32.NewProc("SleepEx") ) @@ -77,6 +80,36 @@ func wtsFreeMemory(ptr uintptr) { return } +func createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) { + var _p0 uint32 + if inheritExisting { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func destroyEnvironmentBlock(block uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(block), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func notifyServiceStatusChange(service windows.Handle, notifyMask uint32, notifyBuffer uintptr) (status uint32) { r0, _, _ := syscall.Syscall(procNotifyServiceStatusChangeW.Addr(), 3, uintptr(service), uintptr(notifyMask), uintptr(notifyBuffer)) status = uint32(r0) |