diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..09b9286 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/yuk7/wsllib-go + +go 1.16 + +require golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b9ce074 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/mksyscall.go b/mksyscall.go new file mode 100644 index 0000000..159ab18 --- /dev/null +++ b/mksyscall.go @@ -0,0 +1,3 @@ +package wsllib + +//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go wsllib.go diff --git a/wsllib.go b/wsllib.go new file mode 100644 index 0000000..8e82c14 --- /dev/null +++ b/wsllib.go @@ -0,0 +1,93 @@ +package wsllib + +import ( + "os" + "syscall" +) + +const ( + //FlagEnableInterop is flag of interop feature + FlagEnableInterop = 1 + //FlagAppendNTPath is flag of appending windows path + FlagAppendNTPath = 2 + //FlagEnableDriveMounting is flag of mounting windows drive + FlagEnableDriveMounting = 4 + //FlagEnableWsl2 is flag of enabled wsl2, read only + FlagEnableWsl2 = 8 +) + +//sys _WslGetDistributionConfiguration(distributionName *uint16, distributionVersion *uint32, defaultUID *uint64, wslDistributionFlags *uint32, defaultEnv ***uint16, defaultEnvCnt *uint64) (res error) = wslapi.WslGetDistributionConfiguration + +// WslGetDistributionConfiguration gets distribution configuration +func WslGetDistributionConfiguration(distributionName string) (distributionVersion uint32, defaultUID uint64, flags uint32, err error) { + pDistributionName, _ := syscall.UTF16PtrFromString(distributionName) + + var pEnv **uint16 + var envCnt uint64 + + err = _WslGetDistributionConfiguration(pDistributionName, &distributionVersion, &defaultUID, &flags, &pEnv, &envCnt) + + return +} + +//sys _WslConfigureDistribution(distributionName *uint16, defaultUID uint64, wslDistributionFlags uint32) (res error) = wslapi.WslConfigureDistribution + +// WslConfigureDistribution configures distribution configuration +func WslConfigureDistribution(distributionName string, defaultUID uint64, wslDistributionFlags uint32) (err error) { + pDistributionName, _ := syscall.UTF16PtrFromString(distributionName) + + return _WslConfigureDistribution(pDistributionName, defaultUID, wslDistributionFlags) +} + +//sys _WslIsDistributionRegistered(distributionName *uint16) (res bool) = wslapi.WslIsDistributionRegistered + +// WslIsDistributionRegistered determines if a distribution is already registered +func WslIsDistributionRegistered(distributionName string) bool { + pDistributionName, _ := syscall.UTF16PtrFromString(distributionName) + return _WslIsDistributionRegistered(pDistributionName) +} + +//sys _WslRegisterDistribution(distributionName *uint16, tarGzFilename *uint16) (res error) = wslapi.WslRegisterDistribution + +// WslRegisterDistribution registers a new distribution +func WslRegisterDistribution(distributionName, tarGzFilename string) error { + pDistributionName, _ := syscall.UTF16PtrFromString(distributionName) + pTarGzFilename, _ := syscall.UTF16PtrFromString(tarGzFilename) + return _WslRegisterDistribution(pDistributionName, pTarGzFilename) +} + +//sys _WslLaunch(distributionName *uint16, command *uint16, useCurrentWorkingDirectory bool, stdIn syscall.Handle, stdOut syscall.Handle, stdErr syscall.Handle, process *syscall.Handle) (err error) = wslapi.WslLaunch + +// WslLaunch launches the distribution with handle +func WslLaunch(distributionName string, command string, useCurrentWorkingDirectory bool, stdIn syscall.Handle, stdOut syscall.Handle, stdErr syscall.Handle) (process syscall.Handle, err error) { + pDistributionName, _ := syscall.UTF16PtrFromString(distributionName) + pCommand, _ := syscall.UTF16PtrFromString(command) + + _WslLaunch(pDistributionName, pCommand, useCurrentWorkingDirectory, stdIn, stdOut, stdErr, &process) + return +} + +// WslLaunchInteractive launches the distribution with interactive shell +func WslLaunchInteractive(distributionName string, command string, useCurrentWorkingDirectory bool) (exitCode uint32, err error) { + p, _ := syscall.GetCurrentProcess() + stdin := syscall.Handle(0) + stdout := syscall.Handle(0) + stderr := syscall.Handle(0) + + syscall.DuplicateHandle(p, syscall.Handle(os.Stdin.Fd()), p, &stdin, 0, true, syscall.DUPLICATE_SAME_ACCESS) + syscall.DuplicateHandle(p, syscall.Handle(os.Stdout.Fd()), p, &stdout, 0, true, syscall.DUPLICATE_SAME_ACCESS) + syscall.DuplicateHandle(p, syscall.Handle(os.Stderr.Fd()), p, &stderr, 0, true, syscall.DUPLICATE_SAME_ACCESS) + + handle, err := WslLaunch(distributionName, command, useCurrentWorkingDirectory, stdin, stdout, stderr) + syscall.WaitForSingleObject(handle, syscall.INFINITE) + syscall.GetExitCodeProcess(handle, &exitCode) + return +} + +//sys _WslUnregisterDistribution(distributionName *uint16) (res error) = wslapi.WslUnregisterDistribution + +// WslUnregisterDistribution unregisters the specified distribution +func WslUnregisterDistribution(distributionName string) error { + pDistributionName, _ := syscall.UTF16PtrFromString(distributionName) + return _WslUnregisterDistribution(pDistributionName) +} \ No newline at end of file diff --git a/zsyscall_windows.go b/zsyscall_windows.go new file mode 100644 index 0000000..f1427ba --- /dev/null +++ b/zsyscall_windows.go @@ -0,0 +1,99 @@ +// Code generated by 'go generate'; DO NOT EDIT. + +package wsllib + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) + errERROR_EINVAL error = syscall.EINVAL +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return errERROR_EINVAL + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modwslapi = windows.NewLazySystemDLL("wslapi.dll") + + procWslConfigureDistribution = modwslapi.NewProc("WslConfigureDistribution") + procWslGetDistributionConfiguration = modwslapi.NewProc("WslGetDistributionConfiguration") + procWslIsDistributionRegistered = modwslapi.NewProc("WslIsDistributionRegistered") + procWslLaunch = modwslapi.NewProc("WslLaunch") + procWslRegisterDistribution = modwslapi.NewProc("WslRegisterDistribution") + procWslUnregisterDistribution = modwslapi.NewProc("WslUnregisterDistribution") +) + +func _WslConfigureDistribution(distributionName *uint16, defaultUID uint64, wslDistributionFlags uint32) (res error) { + r0, _, _ := syscall.Syscall(procWslConfigureDistribution.Addr(), 3, uintptr(unsafe.Pointer(distributionName)), uintptr(defaultUID), uintptr(wslDistributionFlags)) + if r0 != 0 { + res = syscall.Errno(r0) + } + return +} + +func _WslGetDistributionConfiguration(distributionName *uint16, distributionVersion *uint32, defaultUID *uint64, wslDistributionFlags *uint32, defaultEnv ***uint16, defaultEnvCnt *uint64) (res error) { + r0, _, _ := syscall.Syscall6(procWslGetDistributionConfiguration.Addr(), 6, uintptr(unsafe.Pointer(distributionName)), uintptr(unsafe.Pointer(distributionVersion)), uintptr(unsafe.Pointer(defaultUID)), uintptr(unsafe.Pointer(wslDistributionFlags)), uintptr(unsafe.Pointer(defaultEnv)), uintptr(unsafe.Pointer(defaultEnvCnt))) + if r0 != 0 { + res = syscall.Errno(r0) + } + return +} + +func _WslIsDistributionRegistered(distributionName *uint16) (res bool) { + r0, _, _ := syscall.Syscall(procWslIsDistributionRegistered.Addr(), 1, uintptr(unsafe.Pointer(distributionName)), 0, 0) + res = r0 != 0 + return +} + +func _WslLaunch(distributionName *uint16, command *uint16, useCurrentWorkingDirectory bool, stdIn syscall.Handle, stdOut syscall.Handle, stdErr syscall.Handle, process *syscall.Handle) (err error) { + var _p0 uint32 + if useCurrentWorkingDirectory { + _p0 = 1 + } + r1, _, e1 := syscall.Syscall9(procWslLaunch.Addr(), 7, uintptr(unsafe.Pointer(distributionName)), uintptr(unsafe.Pointer(command)), uintptr(_p0), uintptr(stdIn), uintptr(stdOut), uintptr(stdErr), uintptr(unsafe.Pointer(process)), 0, 0) + if r1 == 0 { + err = errnoErr(e1) + } + return +} + +func _WslRegisterDistribution(distributionName *uint16, tarGzFilename *uint16) (res error) { + r0, _, _ := syscall.Syscall(procWslRegisterDistribution.Addr(), 2, uintptr(unsafe.Pointer(distributionName)), uintptr(unsafe.Pointer(tarGzFilename)), 0) + if r0 != 0 { + res = syscall.Errno(r0) + } + return +} + +func _WslUnregisterDistribution(distributionName *uint16) (res error) { + r0, _, _ := syscall.Syscall(procWslUnregisterDistribution.Addr(), 1, uintptr(unsafe.Pointer(distributionName)), 0, 0) + if r0 != 0 { + res = syscall.Errno(r0) + } + return +}