windows: add SetConsoleCursorPosition

Relates to https://github.com/gotestyourself/gotestsum/pull/115#issuecomment-629785089

For details see: https://docs.microsoft.com/en-us/windows/console/SetConsoleCursorPosition

Change-Id: I512428b64af253916c81187cb644e40a6ba418b5
GitHub-Last-Rev: c6c7ba0ad0a79ff6afcfb837836008bab246b85d
GitHub-Pull-Request: golang/sys#87
Reviewed-on: https://go-review.googlesource.com/c/sys/+/258038
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Trust: Alex Brainman <alex.brainman@gmail.com>
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
diff --git a/windows/mkwinsyscall/mkwinsyscall.go b/windows/mkwinsyscall/mkwinsyscall.go
index 392ce1b..ff2048b 100644
--- a/windows/mkwinsyscall/mkwinsyscall.go
+++ b/windows/mkwinsyscall/mkwinsyscall.go
@@ -202,6 +202,11 @@
 		s = fmt.Sprintf("unsafe.Pointer(%s)", p.Name)
 	case t == "bool":
 		s = p.tmpVar()
+	case t == "Coord":
+		// Convert a COORD into a uintptr (by fooling the type system). This code
+		// assumes the two SHORTs are correctly laid out; the "cast" to uint32 is
+		// just to get a pointer to pass.
+		s = fmt.Sprintf("*((*uint32)(unsafe.Pointer(&%s)))", p.Name)
 	case strings.HasPrefix(t, "[]"):
 		return []string{
 			fmt.Sprintf("uintptr(unsafe.Pointer(%s))", p.tmpVar()),
diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go
index 2aa29e8..30ef641 100644
--- a/windows/syscall_windows.go
+++ b/windows/syscall_windows.go
@@ -273,6 +273,7 @@
 //sys	GetConsoleMode(console Handle, mode *uint32) (err error) = kernel32.GetConsoleMode
 //sys	SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode
 //sys	GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo
+//sys	SetConsoleCursorPosition(console Handle, position Coord) (err error) = kernel32.SetConsoleCursorPosition
 //sys	WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
 //sys	ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
 //sys	CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go
index 347f13d..f1ae76b 100644
--- a/windows/zsyscall_windows.go
+++ b/windows/zsyscall_windows.go
@@ -183,6 +183,7 @@
 	procGetConsoleMode                                       = modkernel32.NewProc("GetConsoleMode")
 	procSetConsoleMode                                       = modkernel32.NewProc("SetConsoleMode")
 	procGetConsoleScreenBufferInfo                           = modkernel32.NewProc("GetConsoleScreenBufferInfo")
+	procSetConsoleCursorPosition                             = modkernel32.NewProc("SetConsoleCursorPosition")
 	procWriteConsoleW                                        = modkernel32.NewProc("WriteConsoleW")
 	procReadConsoleW                                         = modkernel32.NewProc("ReadConsoleW")
 	procCreateToolhelp32Snapshot                             = modkernel32.NewProc("CreateToolhelp32Snapshot")
@@ -1978,6 +1979,18 @@
 	return
 }
 
+func SetConsoleCursorPosition(console Handle, position Coord) (err error) {
+	r1, _, e1 := syscall.Syscall(procSetConsoleCursorPosition.Addr(), 2, uintptr(console), uintptr(*((*uint32)(unsafe.Pointer(&position)))), 0)
+	if r1 == 0 {
+		if e1 != 0 {
+			err = errnoErr(e1)
+		} else {
+			err = syscall.EINVAL
+		}
+	}
+	return
+}
+
 func WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) {
 	r1, _, e1 := syscall.Syscall6(procWriteConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(towrite), uintptr(unsafe.Pointer(written)), uintptr(unsafe.Pointer(reserved)), 0)
 	if r1 == 0 {