/* BSD-2-Clause license * * Copyright (c) 2018-2023 NST , sss . * */ #include #include #include #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; }