-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsend.go
152 lines (140 loc) · 4.32 KB
/
send.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
package user32util
import (
"fmt"
"unsafe"
)
const (
InputMouse = iota
InputKeyboard
InputHardware
)
// Various MouseInput dwFlags.
//
// Refer to the following Windows API document for more information:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-mouseinput
const (
MouseEventFAbsolute uint32 = 0x8000
MouseEventFHWheel uint32 = 0x01000
MouseEventFMove uint32 = 0x0001
MouseEventFMoveNoCoalesce uint32 = 0x2000
MouseEventFLeftDown uint32 = 0x0002
MouseEventFLeftUp uint32 = 0x0004
MouseEventFRightDown uint32 = 0x0008
MouseEventFRightUp uint32 = 0x0010
MouseEventFMiddleDown uint32 = 0x0020
MouseEventFMiddleUp uint32 = 0x0040
MouseEventFVirtualDesk uint32 = 0x4000
MouseEventFWheel uint32 = 0x0800
MouseEventFXDown uint32 = 0x0080
MouseEventFXUp uint32 = 0x0100
)
// Various KeybdInput dwFlags.
//
// Refer to the following Windows API document for more information:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-keybdinput
const (
KeyEventFExtendedKey uint32 = 0x0001
KeyEventFKeyUp uint32 = 0x0002
KeyEventFScanCode uint32 = 0x0008
KeyEventFUnicode uint32 = 0x0004
)
// From the Windows API documentation:
// Contains information about a simulated mouse event.
//
// Refer to the following Windows API document for more information:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-mouseinput
type MouseInput struct {
Dx int32
Dy int32
MouseData uint32
DwFlags uint32
Time uint32
DwExtraInfo uintptr
}
// Wrapper for SendInput() that sends a single MouseInput.
func SendMouseInput(input MouseInput, user32 *User32DLL) error {
// Apparently, no byte padding is needed.
s := struct {
Type uint32
Val MouseInput
}{
Type: InputMouse,
Val: input,
}
return SendInput(1, unsafe.Pointer(&s), unsafe.Sizeof(s), user32)
}
// From the Windows API documentation:
// Contains information about a simulated keyboard event.
//
// Refer to the following Windows API document for more information:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-keybdinput
type KeybdInput struct {
WVK uint16
WScan uint16
DwFlags uint32
Time uint32
DwExtraInfo uintptr
}
// Wrapper for SendInput() that sends a single KeybdInput.
func SendKeydbInput(input KeybdInput, user32 *User32DLL) error {
// uint64's worth of padding needed to make Windows happy.
// This is so we can omit the other structs, thereby making go
// AND Windows happy.
s := struct {
Type uint32
Val KeybdInput
Padd uint64
}{
Type: InputKeyboard,
Val: input,
Padd: 0,
}
return SendInput(1, unsafe.Pointer(&s), unsafe.Sizeof(s), user32)
}
// From the Windows API documentation:
// Contains information about a simulated message generated by
// an input device other than a keyboard or mouse.
//
// Refer to the following Windows API document for more information:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-hardwareinput
type HardwareInput struct {
UMsg uint32
WParamL uint16
WParamH uint16
}
// No idea if this works. Untested.
func SendHardwareInput(input HardwareInput, user32 *User32DLL) error {
s := struct {
Type uint32
Val HardwareInput
Padd uint64
}{
Type: InputHardware,
Val: input,
Padd: 0,
}
return SendInput(1, unsafe.Pointer(&s), unsafe.Sizeof(s), user32)
}
// SendInput is a hacky implementation of SendInput that works around the
// lack of union support.
//
// https://github.com/JamesHovious/w32/blob/master/user32.go works around this
// by using cgo. I have no desire to make cgo a dependency of the project.
//
// From the Windows API documentation:
// Synthesizes keystrokes, mouse motions, and button clicks.
//
// Refer to the following Windows API document for more information:
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendinput
func SendInput(numInputs uint, unsafePointerToVal unsafe.Pointer, inputStructSizeBytes uintptr, user32 *User32DLL) error {
numSent, _, err := user32.sendInput.Call(
uintptr(numInputs),
uintptr(unsafePointerToVal),
uintptr(inputStructSizeBytes))
if uint(numSent) == numInputs {
return nil
} else if err != nil {
return err
}
return fmt.Errorf("failed to send input, unknown errror")
}