diff --git a/windows/syscall_windows.go b/windows/syscall_windows.go
index 4a32543868..eb7696e6d9 100644
--- a/windows/syscall_windows.go
+++ b/windows/syscall_windows.go
@@ -321,6 +321,10 @@ func NewCallbackCDecl(fn interface{}) uintptr {
 //sys	SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP
 //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	ReadConsoleInput(console Handle, buf *InputRecord, toread uint32, read *uint32) (err error) = kernel32.ReadConsoleInputW
+//sys	PeekConsoleInput(console Handle, buf *InputRecord, toread uint32, read *uint32) (err error) = kernel32.PeekConsoleInputW
+//sys	GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) = kernel32.GetNumberOfConsoleInputEvents
+//sys	FlushConsoleInputBuffer(console Handle) (err error) = kernel32.FlushConsoleInputBuffer
 //sys	resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole
 //sys	CreateToolhelp32Snapshot(flags uint32, processId uint32) (handle Handle, err error) [failretval==InvalidHandle] = kernel32.CreateToolhelp32Snapshot
 //sys	Module32First(snapshot Handle, moduleEntry *ModuleEntry32) (err error) = kernel32.Module32FirstW
diff --git a/windows/types_windows.go b/windows/types_windows.go
index 9d138de5fe..e567c09021 100644
--- a/windows/types_windows.go
+++ b/windows/types_windows.go
@@ -3601,3 +3601,90 @@ const (
 	KLF_NOTELLSHELL   = 0x00000080
 	KLF_SETFORPROCESS = 0x00000100
 )
+
+// FocusEventRecord corresponds to the FocusEventRecord structure from the
+// Windows console API.
+// https://docs.microsoft.com/en-us/windows/console/focus-event-record-str
+type FocusEventRecord struct {
+	// SetFocus is reserved and should not be used.
+	SetFocus bool
+}
+
+// KeyEventRecord corresponds to the KeyEventRecord structure from the Windows
+// console API.
+// https://docs.microsoft.com/en-us/windows/console/key-event-record-str
+type KeyEventRecord struct {
+	// KeyDown specified whether the key is pressed or released.
+	KeyDown bool
+
+	//  RepeatCount indicates that a key is being held down. For example, when a
+	//  key is held down, five events with RepeatCount equal to 1 may be
+	//  generated, one event with RepeatCount equal to 5, or multiple events
+	//  with RepeatCount greater than or equal to 1.
+	RepeatCount uint16
+
+	// VirtualKeyCode identifies the given key in a device-independent manner
+	// (see
+	// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes).
+	VirtualKeyCode uint16
+
+	//  VirtualScanCode represents the device-dependent value generated by the
+	//  keyboard hardware.
+	VirtualScanCode uint16
+
+	// Char is the character that corresponds to the pressed key. Char can be
+	// zero for some keys.
+	Char rune
+
+	//ControlKeyState holds the state of the control keys.
+	ControlKeyState uint32
+}
+
+// MenuEventRecord corresponds to the MenuEventRecord structure from the
+// Windows console API.
+// https://docs.microsoft.com/en-us/windows/console/menu-event-record-str
+type MenuEventRecord struct {
+	CommandID uint32
+}
+
+// MouseEventRecord corresponds to the MouseEventRecord structure from the
+// Windows console API.
+// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str
+type MouseEventRecord struct {
+	// MousePosition contains the location of the cursor, in terms of the
+	// console screen buffer's character-cell coordinates.
+	MousePositon Coord
+
+	// ButtonState holds the status of the mouse buttons.
+	ButtonState uint32
+
+	// ControlKeyState holds the state of the control keys.
+	ControlKeyState uint32
+
+	// EventFlags specify the type of mouse event.
+	EventFlags uint32
+}
+
+// WindowBufferSizeRecord corresponds to the WindowBufferSizeRecord structure
+// from the Windows console API.
+// https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str
+type WindowBufferSizeRecord struct {
+	// Size contains the size of the console screen buffer, in character cell
+	// columns and rows.
+	Size Coord
+}
+
+// InputRecord corresponds to the INPUT_RECORD structure from the Windows
+// console API.
+//
+// https://docs.microsoft.com/en-us/windows/console/input-record-str
+type InputRecord struct {
+	// EventType specifies the type of event that helt in Event.
+	EventType uint16
+
+	// Padding of the 16-bit EventType to a whole 32-bit dword.
+	_ [2]byte
+
+	// Event holds the actual event data.
+	Event [16]byte
+}
diff --git a/windows/zsyscall_windows.go b/windows/zsyscall_windows.go
index 01c0716c2c..2282dc89ff 100644
--- a/windows/zsyscall_windows.go
+++ b/windows/zsyscall_windows.go
@@ -238,6 +238,7 @@ var (
 	procFindResourceW                                        = modkernel32.NewProc("FindResourceW")
 	procFindVolumeClose                                      = modkernel32.NewProc("FindVolumeClose")
 	procFindVolumeMountPointClose                            = modkernel32.NewProc("FindVolumeMountPointClose")
+	procFlushConsoleInputBuffer                              = modkernel32.NewProc("FlushConsoleInputBuffer")
 	procFlushFileBuffers                                     = modkernel32.NewProc("FlushFileBuffers")
 	procFlushViewOfFile                                      = modkernel32.NewProc("FlushViewOfFile")
 	procFormatMessageW                                       = modkernel32.NewProc("FormatMessageW")
@@ -283,6 +284,7 @@ var (
 	procGetNamedPipeClientProcessId                          = modkernel32.NewProc("GetNamedPipeClientProcessId")
 	procGetNamedPipeHandleStateW                             = modkernel32.NewProc("GetNamedPipeHandleStateW")
 	procGetNamedPipeInfo                                     = modkernel32.NewProc("GetNamedPipeInfo")
+	procGetNumberOfConsoleInputEvents                        = modkernel32.NewProc("GetNumberOfConsoleInputEvents")
 	procGetNamedPipeServerProcessId                          = modkernel32.NewProc("GetNamedPipeServerProcessId")
 	procGetOverlappedResult                                  = modkernel32.NewProc("GetOverlappedResult")
 	procGetPriorityClass                                     = modkernel32.NewProc("GetPriorityClass")
@@ -333,6 +335,7 @@ var (
 	procOpenMutexW                                           = modkernel32.NewProc("OpenMutexW")
 	procOpenProcess                                          = modkernel32.NewProc("OpenProcess")
 	procOpenThread                                           = modkernel32.NewProc("OpenThread")
+	procPeekConsoleInputW                                    = modkernel32.NewProc("PeekConsoleInputW")
 	procPostQueuedCompletionStatus                           = modkernel32.NewProc("PostQueuedCompletionStatus")
 	procProcess32FirstW                                      = modkernel32.NewProc("Process32FirstW")
 	procProcess32NextW                                       = modkernel32.NewProc("Process32NextW")
@@ -342,6 +345,7 @@ var (
 	procQueryDosDeviceW                                      = modkernel32.NewProc("QueryDosDeviceW")
 	procQueryFullProcessImageNameW                           = modkernel32.NewProc("QueryFullProcessImageNameW")
 	procQueryInformationJobObject                            = modkernel32.NewProc("QueryInformationJobObject")
+	procReadConsoleInputW                                    = modkernel32.NewProc("ReadConsoleInputW")
 	procReadConsoleW                                         = modkernel32.NewProc("ReadConsoleW")
 	procReadDirectoryChangesW                                = modkernel32.NewProc("ReadDirectoryChangesW")
 	procReadFile                                             = modkernel32.NewProc("ReadFile")
@@ -2110,6 +2114,14 @@ func FindVolumeMountPointClose(findVolumeMountPoint Handle) (err error) {
 	return
 }
 
+func FlushConsoleInputBuffer(console Handle) (err error) {
+	r1, _, e1 := syscall.SyscallN(procFlushConsoleInputBuffer.Addr(), uintptr(console))
+	if r1 == 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
 func FlushFileBuffers(handle Handle) (err error) {
 	r1, _, e1 := syscall.Syscall(procFlushFileBuffers.Addr(), 1, uintptr(handle), 0, 0)
 	if r1 == 0 {
@@ -2480,6 +2492,14 @@ func GetNamedPipeServerProcessId(pipe Handle, serverProcessID *uint32) (err erro
 	return
 }
 
+func GetNumberOfConsoleInputEvents(console Handle, numevents *uint32) (err error) {
+	r1, _, e1 := syscall.SyscallN(procGetNumberOfConsoleInputEvents.Addr(), uintptr(console), uintptr(unsafe.Pointer(numevents)))
+	if r1 == 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
 func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) {
 	var _p0 uint32
 	if wait {
@@ -2937,6 +2957,14 @@ func OpenThread(desiredAccess uint32, inheritHandle bool, threadId uint32) (hand
 	return
 }
 
+func PeekConsoleInput(console Handle, buf *InputRecord, toread uint32, read *uint32) (err error) {
+	r1, _, e1 := syscall.SyscallN(procPeekConsoleInputW.Addr(), uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)))
+	if r1 == 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
 func PostQueuedCompletionStatus(cphandle Handle, qty uint32, key uintptr, overlapped *Overlapped) (err error) {
 	r1, _, e1 := syscall.Syscall6(procPostQueuedCompletionStatus.Addr(), 4, uintptr(cphandle), uintptr(qty), uintptr(key), uintptr(unsafe.Pointer(overlapped)), 0, 0)
 	if r1 == 0 {
@@ -3010,6 +3038,14 @@ func QueryInformationJobObject(job Handle, JobObjectInformationClass int32, JobO
 	return
 }
 
+func ReadConsoleInput(console Handle, buf *InputRecord, toread uint32, read *uint32) (err error) {
+	r1, _, e1 := syscall.SyscallN(procReadConsoleInputW.Addr(), uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)))
+	if r1 == 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
 func ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) {
 	r1, _, e1 := syscall.Syscall6(procReadConsoleW.Addr(), 5, uintptr(console), uintptr(unsafe.Pointer(buf)), uintptr(toread), uintptr(unsafe.Pointer(read)), uintptr(unsafe.Pointer(inputControl)), 0)
 	if r1 == 0 {