summaryrefslogtreecommitdiff
path: root/src/rdp/rdp_user_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/rdp/rdp_user_input.c')
-rw-r--r--src/rdp/rdp_user_input.c458
1 files changed, 458 insertions, 0 deletions
diff --git a/src/rdp/rdp_user_input.c b/src/rdp/rdp_user_input.c
new file mode 100644
index 0000000..c79e5b1
--- /dev/null
+++ b/src/rdp/rdp_user_input.c
@@ -0,0 +1,458 @@
+/* BSD-2-Clause license
+ *
+ * Copyright (c) 2018-2023 NST <www.newinfosec.ru>, sss <sss at dark-alexandr dot net>.
+ *
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "webrdp_core_api.h"
+#include "webrdp_module_api.h"
+
+#include "rdp_backend_api.h"
+#include "rdp_impl.h"
+
+const UINT32 ASCII_TO_SCANCODE[256] = {
+ 0, /* 0 */
+ 0, /* 1 */
+ 0, /* 2 */
+ 0, /* 3 */
+ 0, /* 4 */
+ 0, /* 5 */
+ 0, /* 6 */
+ 0, /* 7 */
+ RDP_SCANCODE_BACKSPACE, /* 8 */
+ RDP_SCANCODE_TAB, /* 9 */
+ VK_KEY_D, /* 10 */
+ VK_KEY_F, /* 11 */
+ VK_KEY_H, /* 12 */
+ RDP_SCANCODE_RETURN, /* 13 */
+ RDP_SCANCODE_BACKSPACE, /* 14 */
+ VK_KEY_X, /* 15 */
+ RDP_SCANCODE_LSHIFT, /* 16 */
+ RDP_SCANCODE_LCONTROL, /* 17 */
+ RDP_SCANCODE_LMENU, /* 18 */
+ RDP_SCANCODE_PAUSE, /* 19 */
+ RDP_SCANCODE_CAPSLOCK, /* 20 */
+ VK_KEY_W, /* 21 */
+ VK_KEY_E, /* 22 */
+ VK_KEY_R, /* 23 */
+ VK_KEY_Y, /* 24 */
+ VK_KEY_A, /* 25 */
+ VK_KEY_1, /* 26 */
+ RDP_SCANCODE_ESCAPE, /* 27 */
+ VK_KEY_3, /* 28 */
+ VK_KEY_4, /* 29 */
+ VK_KEY_6, /* 30 */
+ VK_KEY_5, /* 31 */
+ RDP_SCANCODE_SPACE, /* 32 */
+ RDP_SCANCODE_PRIOR, /* 33 */
+ RDP_SCANCODE_NEXT, /* 34 */
+ RDP_SCANCODE_END, /* 35 */
+ RDP_SCANCODE_HOME, /* 36 */
+ RDP_SCANCODE_LEFT, /* 37 */
+ RDP_SCANCODE_UP, /* 38 */
+ RDP_SCANCODE_RIGHT, /* 39 */
+ RDP_SCANCODE_DOWN, /* 40 */
+ RDP_SCANCODE_KEY_0, /* 41 */
+ RDP_SCANCODE_MULTIPLY, /* 42 */
+ RDP_SCANCODE_ADD, /* 43 */
+ RDP_SCANCODE_PRINTSCREEN, /* 44 */
+ RDP_SCANCODE_INSERT, /* 45 */
+ RDP_SCANCODE_DELETE, /* 46 */
+ RDP_SCANCODE_DIVIDE, /* 47 */
+ RDP_SCANCODE_KEY_0, /* 48 */
+ RDP_SCANCODE_KEY_1, /* 49 */
+ RDP_SCANCODE_KEY_2, /* 50 */
+ RDP_SCANCODE_KEY_3, /* 51 */
+ RDP_SCANCODE_KEY_4, /* 52 */
+ RDP_SCANCODE_KEY_5, /* 53 */
+ RDP_SCANCODE_KEY_6, /* 54 */
+ RDP_SCANCODE_KEY_7, /* 55 */
+ RDP_SCANCODE_KEY_8, /* 56 */
+ RDP_SCANCODE_KEY_9, /* 57 */
+ RDP_SCANCODE_OEM_1, /* 58 */
+ RDP_SCANCODE_OEM_1, /* 59 */
+ RDP_SCANCODE_OEM_COMMA, /* 60 */
+ RDP_SCANCODE_OEM_PLUS, /* 61 */
+ RDP_SCANCODE_OEM_PERIOD, /* 62 */
+ RDP_SCANCODE_DIVIDE, /* 63 */
+ RDP_SCANCODE_KEY_2, /* 64 */
+ RDP_SCANCODE_KEY_A, /* 65 */
+ RDP_SCANCODE_KEY_B, /* 66 */
+ RDP_SCANCODE_KEY_C, /* 67 */
+ RDP_SCANCODE_KEY_D, /* 68 */
+ RDP_SCANCODE_KEY_E, /* 69 */
+ RDP_SCANCODE_KEY_F, /* 70 */
+ RDP_SCANCODE_KEY_G, /* 71 */
+ RDP_SCANCODE_KEY_H, /* 72 */
+ RDP_SCANCODE_KEY_I, /* 73 */
+ RDP_SCANCODE_KEY_J, /* 74 */
+ RDP_SCANCODE_KEY_K, /* 75 */
+ RDP_SCANCODE_KEY_L, /* 76 */
+ RDP_SCANCODE_KEY_M, /* 77 */
+ RDP_SCANCODE_KEY_N, /* 78 */
+ RDP_SCANCODE_KEY_O, /* 79 */
+ RDP_SCANCODE_KEY_P, /* 80 */
+ RDP_SCANCODE_KEY_Q, /* 81 */
+ RDP_SCANCODE_KEY_R, /* 82 */
+ RDP_SCANCODE_KEY_S, /* 83 */
+ RDP_SCANCODE_KEY_T, /* 84 */
+ RDP_SCANCODE_KEY_U, /* 85 */
+ RDP_SCANCODE_KEY_V, /* 86 */
+ RDP_SCANCODE_KEY_W, /* 87 */
+ RDP_SCANCODE_KEY_X, /* 88 */
+ RDP_SCANCODE_KEY_Y, /* 89 */
+ RDP_SCANCODE_KEY_Z, /* 90 */
+ RDP_SCANCODE_LWIN, /* 91 */
+ RDP_SCANCODE_RWIN, /* 92 */
+ RDP_SCANCODE_APPS, /* 93 */
+ RDP_SCANCODE_KEY_6, /* 94 */
+ RDP_SCANCODE_OEM_MINUS, /* 95 */
+ RDP_SCANCODE_NUMPAD0, /* 96 */
+ RDP_SCANCODE_NUMPAD1, /* 97 */
+ RDP_SCANCODE_NUMPAD2, /* 98 */
+ RDP_SCANCODE_NUMPAD3, /* 99 */
+ RDP_SCANCODE_NUMPAD4, /* 100 */
+ RDP_SCANCODE_NUMPAD5, /* 101 */
+ RDP_SCANCODE_NUMPAD6, /* 102 */
+ RDP_SCANCODE_NUMPAD7, /* 103 */
+ RDP_SCANCODE_NUMPAD8, /* 104 */
+ RDP_SCANCODE_NUMPAD9, /* 105 */
+ RDP_SCANCODE_MULTIPLY, /* 106 */
+ RDP_SCANCODE_ADD, /* 107 */
+ 0, /* 108 */
+ RDP_SCANCODE_SUBTRACT, /* 109 */
+ RDP_SCANCODE_DELETE, /* 110 */
+ RDP_SCANCODE_DIVIDE, /* 111 */
+ RDP_SCANCODE_F1, /* 112 */
+ RDP_SCANCODE_F2, /* 113 */
+ RDP_SCANCODE_F3, /* 114 */
+ RDP_SCANCODE_F4, /* 115 */
+ RDP_SCANCODE_F5, /* 116 */
+ RDP_SCANCODE_F6, /* 117 */
+ RDP_SCANCODE_F7, /* 118 */
+ RDP_SCANCODE_F8, /* 119 */
+ RDP_SCANCODE_F9, /* 120 */
+ RDP_SCANCODE_F10, /* 121 */
+ RDP_SCANCODE_F11, /* 122 */
+ RDP_SCANCODE_F12, /* 123 */
+ RDP_SCANCODE_OEM_5, /* 124 */
+ RDP_SCANCODE_OEM_6, /* 125 */
+ VK_F4, /* 126 */
+ VK_END, /* 127 */
+ VK_F2, /* 128 */
+ VK_NEXT, /* 129 */
+ VK_F1, /* 130 */
+ VK_LEFT, /* 131 */
+ VK_RIGHT, /* 132 */
+ VK_DOWN, /* 133 */
+ VK_UP, /* 134 */
+ 0, /* 135 */
+ 0, /* 136 */
+ 0, /* 137 */
+ 0, /* 138 */
+ 0, /* 139 */
+ 0, /* 140 */
+ 0, /* 141 */
+ 0, /* 142 */
+ 0, /* 143 */
+ RDP_SCANCODE_NUMLOCK, /* 144 */
+ RDP_SCANCODE_SCROLLLOCK, /* 145 */
+ 0, /* 146 */
+ 0, /* 147 */
+ 0, /* 148 */
+ 0, /* 149 */
+ 0, /* 150 */
+ 0, /* 151 */
+ 0, /* 152 */
+ 0, /* 153 */
+ 0, /* 154 */
+ 0, /* 155 */
+ 0, /* 156 */
+ 0, /* 157 */
+ 0, /* 158 */
+ 0, /* 159 */
+ 0, /* 160 */
+ 0, /* 161 */
+ 0, /* 162 */
+ 0, /* 163 */
+ 0, /* 164 */
+ 0, /* 165 */
+ 0, /* 166 */
+ 0, /* 167 */
+ 0, /* 168 */
+ 0, /* 169 */
+ 0, /* 170 */
+ 0, /* 171 */
+ 0, /* 172 */
+ RDP_SCANCODE_OEM_MINUS, /* 173 */
+ 0, /* 174 */
+ 0, /* 175 */
+ 0, /* 176 */
+ 0, /* 177 */
+ 0, /* 178 */
+ 0, /* 179 */
+ 0, /* 180 */
+ 0, /* 181 */
+ 0, /* 182 */
+ 0, /* 183 */
+ 0, /* 184 */
+ 0, /* 185 */
+ RDP_SCANCODE_OEM_1, /* 186 */
+ RDP_SCANCODE_OEM_PLUS, /* 187 */
+ RDP_SCANCODE_OEM_COMMA, /* 188 */
+ RDP_SCANCODE_OEM_MINUS, /* 189 */
+ RDP_SCANCODE_OEM_PERIOD, /* 190 */
+ RDP_SCANCODE_OEM_2, /* 191 */
+ RDP_SCANCODE_OEM_3, /* 192 */
+ 0, /* 193 */
+ 0, /* 194 */
+ 0, /* 195 */
+ 0, /* 196 */
+ 0, /* 197 */
+ 0, /* 198 */
+ 0, /* 199 */
+ 0, /* 200 */
+ 0, /* 201 */
+ 0, /* 202 */
+ 0, /* 203 */
+ 0, /* 204 */
+ 0, /* 205 */
+ 0, /* 206 */
+ 0, /* 207 */
+ 0, /* 208 */
+ 0, /* 209 */
+ 0, /* 210 */
+ 0, /* 211 */
+ 0, /* 212 */
+ 0, /* 213 */
+ 0, /* 214 */
+ 0, /* 215 */
+ 0, /* 216 */
+ 0, /* 217 */
+ 0, /* 218 */
+ RDP_SCANCODE_OEM_4, /* 219 */
+ RDP_SCANCODE_OEM_5, /* 220 */
+ RDP_SCANCODE_OEM_6, /* 221 */
+ RDP_SCANCODE_OEM_7, /* 222 */
+ 0, /* 223 */
+ 0, /* 224 */
+ 0, /* 225 */
+ 0, /* 226 */
+ 0, /* 227 */
+ 0, /* 228 */
+ 0, /* 229 */
+ 0, /* 230 */
+ 0, /* 231 */
+ 0, /* 232 */
+ 0, /* 233 */
+ 0, /* 234 */
+ 0, /* 235 */
+ 0, /* 236 */
+ 0, /* 237 */
+ 0, /* 238 */
+ 0, /* 239 */
+ 0, /* 240 */
+ 0, /* 241 */
+ 0, /* 242 */
+ 0, /* 243 */
+ 0, /* 244 */
+ 0, /* 245 */
+ 0, /* 246 */
+ 0, /* 247 */
+ 0, /* 248 */
+ 0, /* 249 */
+ 0, /* 250 */
+ 0, /* 251 */
+ 0, /* 252 */
+ 0, /* 253 */
+ 0, /* 254 */
+ 0 /* 255 */
+};
+
+static bool
+rdp_backend_handle_input_mouse(ws_input_mouse input, void *internals)
+{
+ rdp_internals *_i = internals;
+ rdpInput *inp = _i->instance->context->input;
+ _i->core->api_core->reset_idle(_i->task_info);
+ inp->MouseEvent(inp, input.flags, input.x, input.y);
+ return true;
+}
+
+static bool
+rdp_backend_handle_input_kupdown(ws_input_kupdown input, void *internals)
+{
+ rdp_internals *_i = internals;
+ rdpInput *inp = _i->instance->context->input;
+ if (0 < input.code)
+ {
+ _i->core->api_core->reset_idle(_i->task_info);
+ /* make byte */
+ input.code = RDP_SCANCODE_CODE(input.code);
+ /* apply extended */
+ input.code = ASCII_TO_SCANCODE[input.code];
+ /* extract extended sepparatelly in tflag */
+ uint32_t tflag = RDP_SCANCODE_EXTENDED(input.code) ?
+ KBD_FLAGS_EXTENDED :
+ 0;
+ freerdp_input_send_keyboard_event(inp,
+ (input.down ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE) | tflag,
+ input.code);
+ }
+ return true;
+}
+
+static bool
+rdp_backend_handle_input_kpress(ws_input_kpress input, void *internals)
+{
+ rdp_internals *_i = internals;
+ rdpInput *inp = _i->instance->context->input;
+ _i->core->api_core->reset_idle(_i->task_info);
+ if (0x20 < input.code)
+ {
+ if (input.shiftstate & 6)
+ {
+ //Control and or Alt: Must use scan-codes since
+ //unicode-event can't handle these
+ if (((64 < input.code) && (91 > input.code))
+ || ((96 < input.code) && (123 > input.code)))
+ {
+ input.code -= (input.shiftstate & 1) ? 0 : 32;
+ input.code
+ = GetVirtualScanCodeFromVirtualKeyCode(
+ input.code, 4);
+ if (0 < input.code)
+ {
+ freerdp_input_send_unicode_keyboard_event(
+ inp, KBD_FLAGS_DOWN,
+ ASCII_TO_SCANCODE[input.code]);
+ freerdp_input_send_unicode_keyboard_event(
+ inp, KBD_FLAGS_RELEASE,
+ ASCII_TO_SCANCODE[input.code]);
+ }
+ }
+ }
+ else
+ {
+ if (0 < input.code)
+ {
+ if (input.code == 96)
+ {
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_DOWN,
+ RDP_SCANCODE_LCONTROL);
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU);
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_DOWN,
+ (UINT8)RDP_SCANCODE_DELETE);
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_RELEASE,
+ RDP_SCANCODE_LCONTROL);
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_RELEASE,
+ RDP_SCANCODE_LMENU);
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_RELEASE,
+ (UINT8)RDP_SCANCODE_DELETE);
+ }
+
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_DOWN,
+ ASCII_TO_SCANCODE[input.code]);
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_RELEASE,
+ ASCII_TO_SCANCODE[input.code]);
+ }
+ }
+ }
+ else
+ {
+ if (0 < input.code)
+ {
+ input.code = RDP_SCANCODE_CODE(input.code);
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_DOWN, ASCII_TO_SCANCODE[input.code]);
+ freerdp_input_send_keyboard_event(inp,
+ KBD_FLAGS_RELEASE, ASCII_TO_SCANCODE[input.code]);
+ }
+ }
+ return true;
+}
+
+static bool
+rdp_backend_handle_input_kcomb(ws_input_keycomb input, void *internals)
+{
+ rdp_internals *_i = internals;
+ rdpInput *inp = _i->instance->context->input;
+ _i->core->api_core->reset_idle(_i->task_info);
+ switch (input)
+ {
+ case ws_keycomb_ctrlaltdel_press:
+ {
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_DOWN, RDP_SCANCODE_LCONTROL);
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU);
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_DOWN, (UINT8)RDP_SCANCODE_DELETE);
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_LCONTROL);
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_LMENU);
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_RELEASE, (UINT8)RDP_SCANCODE_DELETE);
+ }
+ break;
+ case ws_keycomb_alttab_press:
+ {
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_DOWN, RDP_SCANCODE_LMENU);
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_DOWN, RDP_SCANCODE_TAB);
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_TAB);
+ }
+ break;
+ case ws_keycomb_alttab_release:
+ {
+ freerdp_input_send_keyboard_event(
+ inp, KBD_FLAGS_RELEASE, RDP_SCANCODE_LMENU);
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+static bool
+rdp_backend_handle_input_unicode(ws_input_unicode input, void *internals)
+{
+ rdp_internals *_i = internals;
+ rdpInput *inp = _i->instance->context->input;
+ int i;
+ _i->core->api_core->reset_idle(_i->task_info);
+ for (i = 0; i < input.length; ++i)
+ {
+ freerdp_input_send_unicode_keyboard_event(
+ inp, KBD_FLAGS_DOWN, (UINT16)input.input[i]);
+ freerdp_input_send_unicode_keyboard_event(
+ inp, KBD_FLAGS_RELEASE, (UINT16)input.input[i]);
+ }
+ return true;
+}
+
+void
+register_input(wrdp_backend_module *backend)
+{
+ backend->callbacks_input->kcomb = rdp_backend_handle_input_kcomb;
+ backend->callbacks_input->kupdown = rdp_backend_handle_input_kupdown;
+ backend->callbacks_input->kpress = rdp_backend_handle_input_kpress;
+ backend->callbacks_input->mouse = rdp_backend_handle_input_mouse;
+ backend->callbacks_input->unicode = rdp_backend_handle_input_unicode;
+}