mirror of
https://git.zx2c4.com/wireguard-windows
synced 2024-11-10 16:59:18 +00:00
6ed37f30f5
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
104 lines
2.8 KiB
Go
104 lines
2.8 KiB
Go
/* SPDX-License-Identifier: MIT
|
|
*
|
|
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
|
|
*/
|
|
|
|
package manager
|
|
|
|
import (
|
|
"errors"
|
|
"runtime"
|
|
"sync/atomic"
|
|
"syscall"
|
|
"unsafe"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
type uiProcess struct {
|
|
handle uintptr
|
|
}
|
|
|
|
func launchUIProcess(executable string, args []string, workingDirectory string, handles []windows.Handle, token windows.Token) (*uiProcess, error) {
|
|
executable16, err := windows.UTF16PtrFromString(executable)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
args16, err := windows.UTF16PtrFromString(windows.ComposeCommandLine(args))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
workingDirectory16, err := windows.UTF16PtrFromString(workingDirectory)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var environmentBlock *uint16
|
|
err = windows.CreateEnvironmentBlock(&environmentBlock, token, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer windows.DestroyEnvironmentBlock(environmentBlock)
|
|
attributeList, err := windows.NewProcThreadAttributeList(1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer attributeList.Delete()
|
|
si := &windows.StartupInfoEx{
|
|
StartupInfo: windows.StartupInfo{Cb: uint32(unsafe.Sizeof(windows.StartupInfoEx{}))},
|
|
ProcThreadAttributeList: attributeList.List(),
|
|
}
|
|
if len(handles) == 0 {
|
|
handles = []windows.Handle{0}
|
|
}
|
|
attributeList.Update(windows.PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&handles[0]), uintptr(len(handles))*unsafe.Sizeof(handles[0]))
|
|
pi := new(windows.ProcessInformation)
|
|
err = windows.CreateProcessAsUser(token, executable16, args16, nil, nil, true, windows.CREATE_DEFAULT_ERROR_MODE|windows.CREATE_UNICODE_ENVIRONMENT|windows.EXTENDED_STARTUPINFO_PRESENT, environmentBlock, workingDirectory16, &si.StartupInfo, pi)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
windows.CloseHandle(pi.Thread)
|
|
uiProc := &uiProcess{handle: uintptr(pi.Process)}
|
|
runtime.SetFinalizer(uiProc, (*uiProcess).release)
|
|
return uiProc, nil
|
|
}
|
|
|
|
func (p *uiProcess) release() error {
|
|
handle := windows.Handle(atomic.SwapUintptr(&p.handle, uintptr(windows.InvalidHandle)))
|
|
if handle == windows.InvalidHandle {
|
|
return nil
|
|
}
|
|
err := windows.CloseHandle(handle)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
runtime.SetFinalizer(p, nil)
|
|
return nil
|
|
}
|
|
|
|
func (p *uiProcess) Wait() (uint32, error) {
|
|
handle := windows.Handle(atomic.LoadUintptr(&p.handle))
|
|
s, err := windows.WaitForSingleObject(handle, syscall.INFINITE)
|
|
switch s {
|
|
case windows.WAIT_OBJECT_0:
|
|
case windows.WAIT_FAILED:
|
|
return 0, err
|
|
default:
|
|
return 0, errors.New("unexpected result from WaitForSingleObject")
|
|
}
|
|
var exitCode uint32
|
|
err = windows.GetExitCodeProcess(handle, &exitCode)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
p.release()
|
|
return exitCode, nil
|
|
}
|
|
|
|
func (p *uiProcess) Kill() error {
|
|
handle := windows.Handle(atomic.LoadUintptr(&p.handle))
|
|
if handle == windows.InvalidHandle {
|
|
return nil
|
|
}
|
|
return windows.TerminateProcess(handle, 1)
|
|
}
|