github.com/zaquestion/lab@v0.25.1/cmd/util_windows.go (about)

     1  // This file contains Windows specific calls.
     2  
     3  package cmd
     4  
     5  // Even though Windows has a POSIX layer, it's implemented in userspace and,
     6  // consequently, the "syscall" lib doesn't export it.
     7  // Because of it, we need to use specific Windows calls to handle some of the
     8  // syscall we're using the `lab`.
     9  
    10  import "syscall"
    11  
    12  // SetStdHandle is not exported by golang syscall lib, we need to get it
    13  // ourselves from kernel32.dll.
    14  var (
    15  	kernel32             = syscall.MustLoadDLL("kernel32.dll")
    16  	procSetStdHandleAddr = kernel32.MustFindProc("SetStdHandle").Addr()
    17  )
    18  
    19  // Windows has the concept of "Handles", which in Unix can be directly
    20  // converted to integers.
    21  var (
    22  	sysStdout = int(syscall.Stdout)
    23  	sysStderr = int(syscall.Stderr)
    24  )
    25  
    26  // closeFD behaves the as POSIX close()
    27  func closeFD(fd int) error {
    28  	return syscall.Close(syscall.Handle(fd))
    29  }
    30  
    31  // dupFD behaves the same as POSIX dup()
    32  func dupFD(fd int) (int, error) {
    33  	proc, err := syscall.GetCurrentProcess()
    34  	if err != nil {
    35  		return 0, err
    36  	}
    37  
    38  	var hndl syscall.Handle
    39  	err = syscall.DuplicateHandle(proc, syscall.Handle(fd), proc, &hndl, 0, true, syscall.DUPLICATE_SAME_ACCESS)
    40  	return int(hndl), err
    41  }
    42  
    43  // dupFD2 behaves the same as POSIX dup2()
    44  func dupFD2(oldFD, newFD int) error {
    45  	ret, _, err := syscall.Syscall(procSetStdHandleAddr, 2, uintptr(oldFD), uintptr(newFD), 0)
    46  	if err != 0 {
    47  		return error(err)
    48  	}
    49  
    50  	if ret == 0 {
    51  		return syscall.EINVAL
    52  	}
    53  
    54  	return nil
    55  }