github.com/angdraug/packer@v1.3.2/common/terminal_windows.go (about)

     1  // +build windows
     2  
     3  package common
     4  
     5  import (
     6  	"syscall"
     7  	"unsafe"
     8  )
     9  
    10  // windows constants and structures pulled from msdn
    11  const (
    12  	_STD_INPUT_HANDLE  = -10
    13  	_STD_OUTPUT_HANDLE = -11
    14  	_STD_ERROR_HANDLE  = -12
    15  )
    16  
    17  type (
    18  	_SHORT int16
    19  	_WORD  uint16
    20  
    21  	_SMALL_RECT struct {
    22  		Left, Top, Right, Bottom _SHORT
    23  	}
    24  	_COORD struct {
    25  		X, Y _SHORT
    26  	}
    27  	_CONSOLE_SCREEN_BUFFER_INFO struct {
    28  		dwSize, dwCursorPosition _COORD
    29  		wAttributes              _WORD
    30  		srWindow                 _SMALL_RECT
    31  		dwMaximumWindowSize      _COORD
    32  	}
    33  )
    34  
    35  // Low-level functions that call into Windows API for getting console info
    36  var kernel32 = syscall.NewLazyDLL("kernel32.dll")
    37  var kernel32_GetStdHandleProc = kernel32.NewProc("GetStdHandle")
    38  var kernel32_GetConsoleScreenBufferInfoProc = kernel32.NewProc("GetConsoleScreenBufferInfo")
    39  
    40  func kernel32_GetStdHandle(nStdHandle int32) (syscall.Handle, error) {
    41  	res, _, err := kernel32_GetStdHandleProc.Call(uintptr(nStdHandle))
    42  	if res == uintptr(syscall.InvalidHandle) {
    43  		return syscall.InvalidHandle, error(err)
    44  	}
    45  	return syscall.Handle(res), nil
    46  }
    47  
    48  func kernel32_GetConsoleScreenBufferInfo(hConsoleOutput syscall.Handle, info *_CONSOLE_SCREEN_BUFFER_INFO) error {
    49  	ok, _, err := kernel32_GetConsoleScreenBufferInfoProc.Call(uintptr(hConsoleOutput), uintptr(unsafe.Pointer(info)))
    50  	if int(ok) == 0 {
    51  		return error(err)
    52  	}
    53  	return nil
    54  }
    55  
    56  // windows api to get the console screen buffer info
    57  func getConsoleScreenBufferInfo(csbi *_CONSOLE_SCREEN_BUFFER_INFO) (err error) {
    58  	var (
    59  		bi _CONSOLE_SCREEN_BUFFER_INFO
    60  		fd syscall.Handle
    61  	)
    62  
    63  	// Re-open CONOUT$ as in some instances, stdout may be closed and guaranteed an stdout
    64  	if fd, err = syscall.Open("CONOUT$", syscall.O_RDWR, 0); err != nil {
    65  		return err
    66  	}
    67  	defer syscall.Close(fd)
    68  
    69  	// grab the dimensions for the console
    70  	if err = kernel32_GetConsoleScreenBufferInfo(fd, &bi); err != nil {
    71  		return err
    72  	}
    73  
    74  	*csbi = bi
    75  	return nil
    76  }
    77  
    78  func platformGetTerminalDimensions() (width, height int, err error) {
    79  	var csbi _CONSOLE_SCREEN_BUFFER_INFO
    80  
    81  	if err = getConsoleScreenBufferInfo(&csbi); err != nil {
    82  		return 0, 0, err
    83  	}
    84  
    85  	return int(csbi.dwSize.X), int(csbi.dwSize.Y), nil
    86  }