-
Notifications
You must be signed in to change notification settings - Fork 0
/
read.go
154 lines (125 loc) · 5.29 KB
/
read.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//go:build windows
// +build windows
package coninput
import (
"fmt"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var (
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procReadConsoleInputW = modkernel32.NewProc("ReadConsoleInputW")
procPeekConsoleInputW = modkernel32.NewProc("PeekConsoleInputW")
procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents")
procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer")
)
// NewStdinHandle is a shortcut for windows.GetStdHandle(windows.STD_INPUT_HANDLE).
func NewStdinHandle() (windows.Handle, error) {
return windows.GetStdHandle(windows.STD_INPUT_HANDLE)
}
// WinReadConsoleInput is a thin wrapper around the Windows console API function
// ReadConsoleInput (see
// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). In most
// cases it is more practical to either use ReadConsoleInput or
// ReadNConsoleInputs.
func WinReadConsoleInput(consoleInput windows.Handle, buffer *InputRecord,
length uint32, numberOfEventsRead *uint32) error {
r, _, e := syscall.Syscall6(procReadConsoleInputW.Addr(), 4,
uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length),
uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0)
if r == 0 {
return error(e)
}
return nil
}
// ReadNConsoleInputs is a wrapper around ReadConsoleInput (see
// https://docs.microsoft.com/en-us/windows/console/readconsoleinput) that
// automates the event buffer allocation in oder to provide io.Reader-like
// sematics. maxEvents must be greater than zero.
func ReadNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) {
if maxEvents == 0 {
return nil, fmt.Errorf("maxEvents cannot be zero")
}
var inputRecords = make([]InputRecord, maxEvents)
n, err := ReadConsoleInput(console, inputRecords)
return inputRecords[:n], err
}
// ReadConsoleInput provides an ideomatic interface to the Windows console API
// function ReadConsoleInput (see
// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). The size
// of inputRecords must be greater than zero.
func ReadConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) {
if len(inputRecords) == 0 {
return 0, fmt.Errorf("size of input record buffer cannot be zero")
}
var read uint32
err := WinReadConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read)
return read, err
}
// WinPeekConsoleInput is a thin wrapper around the Windows console API function
// PeekConsoleInput (see
// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). In most
// cases it is more practical to either use PeekConsoleInput or
// PeekNConsoleInputs.
func WinPeekConsoleInput(consoleInput windows.Handle, buffer *InputRecord,
length uint32, numberOfEventsRead *uint32) error {
r, _, e := syscall.Syscall6(procPeekConsoleInputW.Addr(), 4,
uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length),
uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0)
if r == 0 {
return error(e)
}
return nil
}
// PeekNConsoleInputs is a wrapper around PeekConsoleInput (see
// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput) that
// automates the event buffer allocation in oder to provide io.Reader-like
// sematics. maxEvents must be greater than zero.
func PeekNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) {
if maxEvents == 0 {
return nil, fmt.Errorf("maxEvents cannot be zero")
}
var inputRecords = make([]InputRecord, maxEvents)
n, err := PeekConsoleInput(console, inputRecords)
return inputRecords[:n], err
}
// PeekConsoleInput provides an ideomatic interface to the Windows console API
// function PeekConsoleInput (see
// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). The size
// of inputRecords must be greater than zero.
func PeekConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) {
if len(inputRecords) == 0 {
return 0, fmt.Errorf("size of input record buffer cannot be zero")
}
var read uint32
err := WinPeekConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read)
return read, err
}
// WinGetNumberOfConsoleInputEvents provides an ideomatic interface to the
// Windows console API function GetNumberOfConsoleInputEvents (see
// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents).
func WinGetNumberOfConsoleInputEvents(consoleInput windows.Handle, numberOfEvents *uint32) error {
r, _, e := syscall.Syscall6(procGetNumberOfConsoleInputEvents.Addr(), 2,
uintptr(consoleInput), uintptr(unsafe.Pointer(numberOfEvents)), 0,
0, 0, 0)
if r == 0 {
return error(e)
}
return nil
}
// GetNumberOfConsoleInputEvents provides an ideomatic interface to the Windows
// console API function GetNumberOfConsoleInputEvents (see
// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents).
func GetNumberOfConsoleInputEvents(console windows.Handle) (uint32, error) {
var nEvents uint32
err := WinGetNumberOfConsoleInputEvents(console, &nEvents)
return nEvents, err
}
func FlushConsoleInputBuffer(consoleInput windows.Handle) error {
r, _, e := syscall.Syscall(procFlushConsoleInputBuffer.Addr(), 1, uintptr(consoleInput), 0, 0)
if r == 0 {
return error(e)
}
return nil
}