1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Input PDUs
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 
24 #include <winpr/crt.h>
25 
26 #include <freerdp/input.h>
27 #include <freerdp/log.h>
28 
29 #include "message.h"
30 
31 #include "input.h"
32 
33 #define TAG FREERDP_TAG("core")
34 
35 /* Input Events */
36 #define INPUT_EVENT_SYNC 0x0000
37 #define INPUT_EVENT_SCANCODE 0x0004
38 #define INPUT_EVENT_UNICODE 0x0005
39 #define INPUT_EVENT_MOUSE 0x8001
40 #define INPUT_EVENT_MOUSEX 0x8002
41 
42 #define RDP_CLIENT_INPUT_PDU_HEADER_LENGTH 4
43 
rdp_write_client_input_pdu_header(wStream * s,UINT16 number)44 static void rdp_write_client_input_pdu_header(wStream* s, UINT16 number)
45 {
46 	Stream_Write_UINT16(s, 1); /* numberEvents (2 bytes) */
47 	Stream_Write_UINT16(s, 0); /* pad2Octets (2 bytes) */
48 }
49 
rdp_write_input_event_header(wStream * s,UINT32 time,UINT16 type)50 static void rdp_write_input_event_header(wStream* s, UINT32 time, UINT16 type)
51 {
52 	Stream_Write_UINT32(s, time); /* eventTime (4 bytes) */
53 	Stream_Write_UINT16(s, type); /* messageType (2 bytes) */
54 }
55 
rdp_client_input_pdu_init(rdpRdp * rdp,UINT16 type)56 static wStream* rdp_client_input_pdu_init(rdpRdp* rdp, UINT16 type)
57 {
58 	wStream* s;
59 	s = rdp_data_pdu_init(rdp);
60 
61 	if (!s)
62 		return NULL;
63 
64 	rdp_write_client_input_pdu_header(s, 1);
65 	rdp_write_input_event_header(s, 0, type);
66 	return s;
67 }
68 
rdp_send_client_input_pdu(rdpRdp * rdp,wStream * s)69 static BOOL rdp_send_client_input_pdu(rdpRdp* rdp, wStream* s)
70 {
71 	return rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_INPUT, rdp->mcs->userId);
72 }
73 
input_write_synchronize_event(wStream * s,UINT32 flags)74 static void input_write_synchronize_event(wStream* s, UINT32 flags)
75 {
76 	Stream_Write_UINT16(s, 0);     /* pad2Octets (2 bytes) */
77 	Stream_Write_UINT32(s, flags); /* toggleFlags (4 bytes) */
78 }
79 
input_send_synchronize_event(rdpInput * input,UINT32 flags)80 static BOOL input_send_synchronize_event(rdpInput* input, UINT32 flags)
81 {
82 	wStream* s;
83 	rdpRdp* rdp;
84 
85 	if (!input || !input->context)
86 		return FALSE;
87 
88 	rdp = input->context->rdp;
89 	s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_SYNC);
90 
91 	if (!s)
92 		return FALSE;
93 
94 	input_write_synchronize_event(s, flags);
95 	return rdp_send_client_input_pdu(rdp, s);
96 }
97 
input_write_keyboard_event(wStream * s,UINT16 flags,UINT16 code)98 static void input_write_keyboard_event(wStream* s, UINT16 flags, UINT16 code)
99 {
100 	Stream_Write_UINT16(s, flags); /* keyboardFlags (2 bytes) */
101 	Stream_Write_UINT16(s, code);  /* keyCode (2 bytes) */
102 	Stream_Write_UINT16(s, 0);     /* pad2Octets (2 bytes) */
103 }
104 
input_send_keyboard_event(rdpInput * input,UINT16 flags,UINT16 code)105 static BOOL input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
106 {
107 	wStream* s;
108 	rdpRdp* rdp;
109 
110 	if (!input || !input->context)
111 		return FALSE;
112 
113 	rdp = input->context->rdp;
114 	s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_SCANCODE);
115 
116 	if (!s)
117 		return FALSE;
118 
119 	input_write_keyboard_event(s, flags, code);
120 	return rdp_send_client_input_pdu(rdp, s);
121 }
122 
input_write_unicode_keyboard_event(wStream * s,UINT16 flags,UINT16 code)123 static void input_write_unicode_keyboard_event(wStream* s, UINT16 flags, UINT16 code)
124 {
125 	Stream_Write_UINT16(s, flags); /* keyboardFlags (2 bytes) */
126 	Stream_Write_UINT16(s, code);  /* unicodeCode (2 bytes) */
127 	Stream_Write_UINT16(s, 0);     /* pad2Octets (2 bytes) */
128 }
129 
input_send_unicode_keyboard_event(rdpInput * input,UINT16 flags,UINT16 code)130 static BOOL input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
131 {
132 	wStream* s;
133 	rdpRdp* rdp;
134 
135 	if (!input || !input->context)
136 		return FALSE;
137 
138 	if (!input->context->settings->UnicodeInput)
139 	{
140 		WLog_WARN(TAG, "Unicode input not supported by server.");
141 		return FALSE;
142 	}
143 
144 	rdp = input->context->rdp;
145 	s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_UNICODE);
146 
147 	if (!s)
148 		return FALSE;
149 
150 	input_write_unicode_keyboard_event(s, flags, code);
151 	return rdp_send_client_input_pdu(rdp, s);
152 }
153 
input_write_mouse_event(wStream * s,UINT16 flags,UINT16 x,UINT16 y)154 static void input_write_mouse_event(wStream* s, UINT16 flags, UINT16 x, UINT16 y)
155 {
156 	Stream_Write_UINT16(s, flags); /* pointerFlags (2 bytes) */
157 	Stream_Write_UINT16(s, x);     /* xPos (2 bytes) */
158 	Stream_Write_UINT16(s, y);     /* yPos (2 bytes) */
159 }
160 
input_send_mouse_event(rdpInput * input,UINT16 flags,UINT16 x,UINT16 y)161 static BOOL input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
162 {
163 	wStream* s;
164 	rdpRdp* rdp;
165 
166 	if (!input || !input->context || !input->context->settings)
167 		return FALSE;
168 
169 	rdp = input->context->rdp;
170 
171 	if (!input->context->settings->HasHorizontalWheel)
172 	{
173 		if (flags & PTR_FLAGS_HWHEEL)
174 		{
175 			WLog_WARN(TAG,
176 			          "skip mouse event %" PRIu16 "x%" PRIu16 " flags=0x%04" PRIX16
177 			          ", no horizontal mouse wheel supported",
178 			          x, y, flags);
179 			return TRUE;
180 		}
181 	}
182 
183 	s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSE);
184 
185 	if (!s)
186 		return FALSE;
187 
188 	input_write_mouse_event(s, flags, x, y);
189 	return rdp_send_client_input_pdu(rdp, s);
190 }
191 
input_write_extended_mouse_event(wStream * s,UINT16 flags,UINT16 x,UINT16 y)192 static void input_write_extended_mouse_event(wStream* s, UINT16 flags, UINT16 x, UINT16 y)
193 {
194 	Stream_Write_UINT16(s, flags); /* pointerFlags (2 bytes) */
195 	Stream_Write_UINT16(s, x);     /* xPos (2 bytes) */
196 	Stream_Write_UINT16(s, y);     /* yPos (2 bytes) */
197 }
198 
input_send_extended_mouse_event(rdpInput * input,UINT16 flags,UINT16 x,UINT16 y)199 static BOOL input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
200 {
201 	wStream* s;
202 	rdpRdp* rdp;
203 
204 	if (!input || !input->context)
205 		return FALSE;
206 
207 	if (!input->context->settings->HasExtendedMouseEvent)
208 	{
209 		WLog_WARN(TAG,
210 		          "skip extended mouse event %" PRIu16 "x%" PRIu16 " flags=0x%04" PRIX16
211 		          ", no extended mouse events supported",
212 		          x, y, flags);
213 		return TRUE;
214 	}
215 
216 	rdp = input->context->rdp;
217 	s = rdp_client_input_pdu_init(rdp, INPUT_EVENT_MOUSEX);
218 
219 	if (!s)
220 		return FALSE;
221 
222 	input_write_extended_mouse_event(s, flags, x, y);
223 	return rdp_send_client_input_pdu(rdp, s);
224 }
225 
input_send_focus_in_event(rdpInput * input,UINT16 toggleStates)226 static BOOL input_send_focus_in_event(rdpInput* input, UINT16 toggleStates)
227 {
228 	/* send a tab up like mstsc.exe */
229 	if (!input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f))
230 		return FALSE;
231 
232 	/* send the toggle key states */
233 	if (!input_send_synchronize_event(input, (toggleStates & 0x1F)))
234 		return FALSE;
235 
236 	/* send another tab up like mstsc.exe */
237 	return input_send_keyboard_event(input, KBD_FLAGS_RELEASE, 0x0f);
238 }
239 
input_send_keyboard_pause_event(rdpInput * input)240 static BOOL input_send_keyboard_pause_event(rdpInput* input)
241 {
242 	/* In ancient days, pause-down without control sent E1 1D 45 E1 9D C5,
243 	 * and pause-up sent nothing.  However, reverse engineering mstsc shows
244 	 * it sending the following sequence:
245 	 */
246 
247 	/* Control down (0x1D) */
248 	if (!input_send_keyboard_event(input, KBD_FLAGS_EXTENDED1,
249 	                               RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL)))
250 		return FALSE;
251 
252 	/* Numlock down (0x45) */
253 	if (!input_send_keyboard_event(input, 0, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK)))
254 		return FALSE;
255 
256 	/* Control up (0x1D) */
257 	if (!input_send_keyboard_event(input, KBD_FLAGS_RELEASE | KBD_FLAGS_EXTENDED1,
258 	                               RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL)))
259 		return FALSE;
260 
261 	/* Numlock up (0x45) */
262 	return input_send_keyboard_event(input, KBD_FLAGS_RELEASE,
263 	                                 RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
264 }
265 
input_send_fastpath_synchronize_event(rdpInput * input,UINT32 flags)266 static BOOL input_send_fastpath_synchronize_event(rdpInput* input, UINT32 flags)
267 {
268 	wStream* s;
269 	rdpRdp* rdp;
270 
271 	if (!input || !input->context)
272 		return FALSE;
273 
274 	rdp = input->context->rdp;
275 	/* The FastPath Synchronization eventFlags has identical values as SlowPath */
276 	s = fastpath_input_pdu_init(rdp->fastpath, (BYTE)flags, FASTPATH_INPUT_EVENT_SYNC);
277 
278 	if (!s)
279 		return FALSE;
280 
281 	return fastpath_send_input_pdu(rdp->fastpath, s);
282 }
283 
input_send_fastpath_keyboard_event(rdpInput * input,UINT16 flags,UINT16 code)284 static BOOL input_send_fastpath_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
285 {
286 	wStream* s;
287 	BYTE eventFlags = 0;
288 	rdpRdp* rdp;
289 
290 	if (!input || !input->context)
291 		return FALSE;
292 
293 	rdp = input->context->rdp;
294 	eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0;
295 	eventFlags |= (flags & KBD_FLAGS_EXTENDED) ? FASTPATH_INPUT_KBDFLAGS_EXTENDED : 0;
296 	eventFlags |= (flags & KBD_FLAGS_EXTENDED1) ? FASTPATH_INPUT_KBDFLAGS_PREFIX_E1 : 0;
297 	s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_SCANCODE);
298 
299 	if (!s)
300 		return FALSE;
301 
302 	Stream_Write_UINT8(s, code); /* keyCode (1 byte) */
303 	return fastpath_send_input_pdu(rdp->fastpath, s);
304 }
305 
input_send_fastpath_unicode_keyboard_event(rdpInput * input,UINT16 flags,UINT16 code)306 static BOOL input_send_fastpath_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
307 {
308 	wStream* s;
309 	BYTE eventFlags = 0;
310 	rdpRdp* rdp;
311 
312 	if (!input || !input->context)
313 		return FALSE;
314 
315 	if (!input->context->settings->UnicodeInput)
316 	{
317 		WLog_WARN(TAG, "Unicode input not supported by server.");
318 		return FALSE;
319 	}
320 
321 	rdp = input->context->rdp;
322 	eventFlags |= (flags & KBD_FLAGS_RELEASE) ? FASTPATH_INPUT_KBDFLAGS_RELEASE : 0;
323 	s = fastpath_input_pdu_init(rdp->fastpath, eventFlags, FASTPATH_INPUT_EVENT_UNICODE);
324 
325 	if (!s)
326 		return FALSE;
327 
328 	Stream_Write_UINT16(s, code); /* unicodeCode (2 bytes) */
329 	return fastpath_send_input_pdu(rdp->fastpath, s);
330 }
331 
input_send_fastpath_mouse_event(rdpInput * input,UINT16 flags,UINT16 x,UINT16 y)332 static BOOL input_send_fastpath_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
333 {
334 	wStream* s;
335 	rdpRdp* rdp;
336 
337 	if (!input || !input->context || !input->context->settings)
338 		return FALSE;
339 
340 	rdp = input->context->rdp;
341 
342 	if (!input->context->settings->HasHorizontalWheel)
343 	{
344 		if (flags & PTR_FLAGS_HWHEEL)
345 		{
346 			WLog_WARN(TAG,
347 			          "skip mouse event %" PRIu16 "x%" PRIu16 " flags=0x%04" PRIX16
348 			          ", no horizontal mouse wheel supported",
349 			          x, y, flags);
350 			return TRUE;
351 		}
352 	}
353 
354 	s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSE);
355 
356 	if (!s)
357 		return FALSE;
358 
359 	input_write_mouse_event(s, flags, x, y);
360 	return fastpath_send_input_pdu(rdp->fastpath, s);
361 }
362 
input_send_fastpath_extended_mouse_event(rdpInput * input,UINT16 flags,UINT16 x,UINT16 y)363 static BOOL input_send_fastpath_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x,
364                                                      UINT16 y)
365 {
366 	wStream* s;
367 	rdpRdp* rdp;
368 
369 	if (!input || !input->context)
370 		return FALSE;
371 
372 	if (!input->context->settings->HasExtendedMouseEvent)
373 	{
374 		WLog_WARN(TAG,
375 		          "skip extended mouse event %" PRIu16 "x%" PRIu16 " flags=0x%04" PRIX16
376 		          ", no extended mouse events supported",
377 		          x, y, flags);
378 		return TRUE;
379 	}
380 
381 	rdp = input->context->rdp;
382 	s = fastpath_input_pdu_init(rdp->fastpath, 0, FASTPATH_INPUT_EVENT_MOUSEX);
383 
384 	if (!s)
385 		return FALSE;
386 
387 	input_write_extended_mouse_event(s, flags, x, y);
388 	return fastpath_send_input_pdu(rdp->fastpath, s);
389 }
390 
input_send_fastpath_focus_in_event(rdpInput * input,UINT16 toggleStates)391 static BOOL input_send_fastpath_focus_in_event(rdpInput* input, UINT16 toggleStates)
392 {
393 	wStream* s;
394 	BYTE eventFlags = 0;
395 	rdpRdp* rdp;
396 
397 	if (!input || !input->context)
398 		return FALSE;
399 
400 	rdp = input->context->rdp;
401 	s = fastpath_input_pdu_init_header(rdp->fastpath);
402 
403 	if (!s)
404 		return FALSE;
405 
406 	/* send a tab up like mstsc.exe */
407 	eventFlags = FASTPATH_INPUT_KBDFLAGS_RELEASE | FASTPATH_INPUT_EVENT_SCANCODE << 5;
408 	Stream_Write_UINT8(s, eventFlags); /* Key Release event (1 byte) */
409 	Stream_Write_UINT8(s, 0x0f);       /* keyCode (1 byte) */
410 	/* send the toggle key states */
411 	eventFlags = (toggleStates & 0x1F) | FASTPATH_INPUT_EVENT_SYNC << 5;
412 	Stream_Write_UINT8(s, eventFlags); /* toggle state (1 byte) */
413 	/* send another tab up like mstsc.exe */
414 	eventFlags = FASTPATH_INPUT_KBDFLAGS_RELEASE | FASTPATH_INPUT_EVENT_SCANCODE << 5;
415 	Stream_Write_UINT8(s, eventFlags); /* Key Release event (1 byte) */
416 	Stream_Write_UINT8(s, 0x0f);       /* keyCode (1 byte) */
417 	return fastpath_send_multiple_input_pdu(rdp->fastpath, s, 3);
418 }
419 
input_send_fastpath_keyboard_pause_event(rdpInput * input)420 static BOOL input_send_fastpath_keyboard_pause_event(rdpInput* input)
421 {
422 	/* In ancient days, pause-down without control sent E1 1D 45 E1 9D C5,
423 	 * and pause-up sent nothing.  However, reverse engineering mstsc shows
424 	 * it sending the following sequence:
425 	 */
426 	wStream* s;
427 	const BYTE keyDownEvent = FASTPATH_INPUT_EVENT_SCANCODE << 5;
428 	const BYTE keyUpEvent = (FASTPATH_INPUT_EVENT_SCANCODE << 5) | FASTPATH_INPUT_KBDFLAGS_RELEASE;
429 	rdpRdp* rdp;
430 
431 	if (!input || !input->context)
432 		return FALSE;
433 
434 	rdp = input->context->rdp;
435 	s = fastpath_input_pdu_init_header(rdp->fastpath);
436 
437 	if (!s)
438 		return FALSE;
439 
440 	/* Control down (0x1D) */
441 	Stream_Write_UINT8(s, keyDownEvent | FASTPATH_INPUT_KBDFLAGS_PREFIX_E1);
442 	Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL));
443 	/* Numlock down (0x45) */
444 	Stream_Write_UINT8(s, keyDownEvent);
445 	Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
446 	/* Control up (0x1D) */
447 	Stream_Write_UINT8(s, keyUpEvent | FASTPATH_INPUT_KBDFLAGS_PREFIX_E1);
448 	Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_LCONTROL));
449 	/* Numlock down (0x45) */
450 	Stream_Write_UINT8(s, keyUpEvent);
451 	Stream_Write_UINT8(s, RDP_SCANCODE_CODE(RDP_SCANCODE_NUMLOCK));
452 	return fastpath_send_multiple_input_pdu(rdp->fastpath, s, 4);
453 }
454 
input_recv_sync_event(rdpInput * input,wStream * s)455 static BOOL input_recv_sync_event(rdpInput* input, wStream* s)
456 {
457 	UINT32 toggleFlags;
458 
459 	if (Stream_GetRemainingLength(s) < 6)
460 		return FALSE;
461 
462 	Stream_Seek(s, 2);                  /* pad2Octets (2 bytes) */
463 	Stream_Read_UINT32(s, toggleFlags); /* toggleFlags (4 bytes) */
464 	return IFCALLRESULT(TRUE, input->SynchronizeEvent, input, toggleFlags);
465 }
466 
input_recv_keyboard_event(rdpInput * input,wStream * s)467 static BOOL input_recv_keyboard_event(rdpInput* input, wStream* s)
468 {
469 	UINT16 keyboardFlags, keyCode;
470 
471 	if (Stream_GetRemainingLength(s) < 6)
472 		return FALSE;
473 
474 	Stream_Read_UINT16(s, keyboardFlags); /* keyboardFlags (2 bytes) */
475 	Stream_Read_UINT16(s, keyCode);       /* keyCode (2 bytes) */
476 	Stream_Seek(s, 2);                    /* pad2Octets (2 bytes) */
477 
478 	/**
479 	 * Note: A lot of code in FreeRDP and in dependent projects checks the
480 	 * KBDFLAGS_DOWN flag in order to detect a key press.
481 	 * According to the specs only the absence of the slow-path
482 	 * KBDFLAGS_RELEASE flag indicates a key-down event.
483 	 * The slow-path KBDFLAGS_DOWN flag merely indicates that the key was
484 	 * down prior to this event.
485 	 * The checks for KBDFLAGS_DOWN only work successfully because the code
486 	 * handling the fast-path keyboard input sets the KBDFLAGS_DOWN flag if
487 	 * the FASTPATH_INPUT_KBDFLAGS_RELEASE flag is missing.
488 	 * Since the same input callback is used for slow- and fast-path events
489 	 * we have to follow that "convention" here.
490 	 */
491 
492 	if (keyboardFlags & KBD_FLAGS_RELEASE)
493 		keyboardFlags &= ~KBD_FLAGS_DOWN;
494 	else
495 		keyboardFlags |= KBD_FLAGS_DOWN;
496 
497 	return IFCALLRESULT(TRUE, input->KeyboardEvent, input, keyboardFlags, keyCode);
498 }
499 
input_recv_unicode_keyboard_event(rdpInput * input,wStream * s)500 static BOOL input_recv_unicode_keyboard_event(rdpInput* input, wStream* s)
501 {
502 	UINT16 keyboardFlags, unicodeCode;
503 
504 	if (Stream_GetRemainingLength(s) < 6)
505 		return FALSE;
506 
507 	Stream_Read_UINT16(s, keyboardFlags); /* keyboardFlags (2 bytes) */
508 	Stream_Read_UINT16(s, unicodeCode);   /* unicodeCode (2 bytes) */
509 	Stream_Seek(s, 2);                    /* pad2Octets (2 bytes) */
510 
511 	/* "fix" keyboardFlags - see comment in input_recv_keyboard_event() */
512 
513 	if (keyboardFlags & KBD_FLAGS_RELEASE)
514 		keyboardFlags &= ~KBD_FLAGS_DOWN;
515 	else
516 		keyboardFlags |= KBD_FLAGS_DOWN;
517 
518 	return IFCALLRESULT(TRUE, input->UnicodeKeyboardEvent, input, keyboardFlags, unicodeCode);
519 }
520 
input_recv_mouse_event(rdpInput * input,wStream * s)521 static BOOL input_recv_mouse_event(rdpInput* input, wStream* s)
522 {
523 	UINT16 pointerFlags, xPos, yPos;
524 
525 	if (Stream_GetRemainingLength(s) < 6)
526 		return FALSE;
527 
528 	Stream_Read_UINT16(s, pointerFlags); /* pointerFlags (2 bytes) */
529 	Stream_Read_UINT16(s, xPos);         /* xPos (2 bytes) */
530 	Stream_Read_UINT16(s, yPos);         /* yPos (2 bytes) */
531 	return IFCALLRESULT(TRUE, input->MouseEvent, input, pointerFlags, xPos, yPos);
532 }
533 
input_recv_extended_mouse_event(rdpInput * input,wStream * s)534 static BOOL input_recv_extended_mouse_event(rdpInput* input, wStream* s)
535 {
536 	UINT16 pointerFlags, xPos, yPos;
537 
538 	if (Stream_GetRemainingLength(s) < 6)
539 		return FALSE;
540 
541 	Stream_Read_UINT16(s, pointerFlags); /* pointerFlags (2 bytes) */
542 	Stream_Read_UINT16(s, xPos);         /* xPos (2 bytes) */
543 	Stream_Read_UINT16(s, yPos);         /* yPos (2 bytes) */
544 	return IFCALLRESULT(TRUE, input->ExtendedMouseEvent, input, pointerFlags, xPos, yPos);
545 }
546 
input_recv_event(rdpInput * input,wStream * s)547 static BOOL input_recv_event(rdpInput* input, wStream* s)
548 {
549 	UINT16 messageType;
550 
551 	if (Stream_GetRemainingLength(s) < 6)
552 		return FALSE;
553 
554 	Stream_Seek(s, 4);                  /* eventTime (4 bytes), ignored by the server */
555 	Stream_Read_UINT16(s, messageType); /* messageType (2 bytes) */
556 
557 	switch (messageType)
558 	{
559 		case INPUT_EVENT_SYNC:
560 			if (!input_recv_sync_event(input, s))
561 				return FALSE;
562 
563 			break;
564 
565 		case INPUT_EVENT_SCANCODE:
566 			if (!input_recv_keyboard_event(input, s))
567 				return FALSE;
568 
569 			break;
570 
571 		case INPUT_EVENT_UNICODE:
572 			if (!input_recv_unicode_keyboard_event(input, s))
573 				return FALSE;
574 
575 			break;
576 
577 		case INPUT_EVENT_MOUSE:
578 			if (!input_recv_mouse_event(input, s))
579 				return FALSE;
580 
581 			break;
582 
583 		case INPUT_EVENT_MOUSEX:
584 			if (!input_recv_extended_mouse_event(input, s))
585 				return FALSE;
586 
587 			break;
588 
589 		default:
590 			WLog_ERR(TAG, "Unknown messageType %" PRIu16 "", messageType);
591 			/* Each input event uses 6 bytes. */
592 			Stream_Seek(s, 6);
593 			break;
594 	}
595 
596 	return TRUE;
597 }
598 
input_recv(rdpInput * input,wStream * s)599 BOOL input_recv(rdpInput* input, wStream* s)
600 {
601 	UINT16 i, numberEvents;
602 
603 	if (!input || !s)
604 		return FALSE;
605 
606 	if (Stream_GetRemainingLength(s) < 4)
607 		return FALSE;
608 
609 	Stream_Read_UINT16(s, numberEvents); /* numberEvents (2 bytes) */
610 	Stream_Seek(s, 2);                   /* pad2Octets (2 bytes) */
611 
612 	/* Each input event uses 6 exactly bytes. */
613 	if (Stream_GetRemainingLength(s) < (size_t)(6 * numberEvents))
614 		return FALSE;
615 
616 	for (i = 0; i < numberEvents; i++)
617 	{
618 		if (!input_recv_event(input, s))
619 			return FALSE;
620 	}
621 
622 	return TRUE;
623 }
624 
input_register_client_callbacks(rdpInput * input)625 BOOL input_register_client_callbacks(rdpInput* input)
626 {
627 	rdpSettings* settings;
628 
629 	if (!input || !input->context)
630 		return FALSE;
631 
632 	settings = input->context->settings;
633 
634 	if (!settings)
635 		return FALSE;
636 
637 	if (settings->FastPathInput)
638 	{
639 		input->SynchronizeEvent = input_send_fastpath_synchronize_event;
640 		input->KeyboardEvent = input_send_fastpath_keyboard_event;
641 		input->KeyboardPauseEvent = input_send_fastpath_keyboard_pause_event;
642 		input->UnicodeKeyboardEvent = input_send_fastpath_unicode_keyboard_event;
643 		input->MouseEvent = input_send_fastpath_mouse_event;
644 		input->ExtendedMouseEvent = input_send_fastpath_extended_mouse_event;
645 		input->FocusInEvent = input_send_fastpath_focus_in_event;
646 	}
647 	else
648 	{
649 		input->SynchronizeEvent = input_send_synchronize_event;
650 		input->KeyboardEvent = input_send_keyboard_event;
651 		input->KeyboardPauseEvent = input_send_keyboard_pause_event;
652 		input->UnicodeKeyboardEvent = input_send_unicode_keyboard_event;
653 		input->MouseEvent = input_send_mouse_event;
654 		input->ExtendedMouseEvent = input_send_extended_mouse_event;
655 		input->FocusInEvent = input_send_focus_in_event;
656 	}
657 
658 	input->asynchronous = settings->AsyncInput;
659 
660 	if (input->asynchronous)
661 	{
662 		input->proxy = input_message_proxy_new(input);
663 
664 		if (!input->proxy)
665 			return FALSE;
666 	}
667 
668 	return TRUE;
669 }
670 
freerdp_input_send_synchronize_event(rdpInput * input,UINT32 flags)671 BOOL freerdp_input_send_synchronize_event(rdpInput* input, UINT32 flags)
672 {
673 	if (!input)
674 		return FALSE;
675 
676 	return IFCALLRESULT(TRUE, input->SynchronizeEvent, input, flags);
677 }
678 
freerdp_input_send_keyboard_event(rdpInput * input,UINT16 flags,UINT16 code)679 BOOL freerdp_input_send_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
680 {
681 	if (!input)
682 		return FALSE;
683 
684 	return IFCALLRESULT(TRUE, input->KeyboardEvent, input, flags, code);
685 }
686 
freerdp_input_send_keyboard_event_ex(rdpInput * input,BOOL down,UINT32 rdp_scancode)687 BOOL freerdp_input_send_keyboard_event_ex(rdpInput* input, BOOL down, UINT32 rdp_scancode)
688 {
689 	return freerdp_input_send_keyboard_event(
690 	    input,
691 	    (RDP_SCANCODE_EXTENDED(rdp_scancode) ? KBD_FLAGS_EXTENDED : 0) |
692 	        ((down) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE),
693 	    RDP_SCANCODE_CODE(rdp_scancode));
694 }
695 
freerdp_input_send_unicode_keyboard_event(rdpInput * input,UINT16 flags,UINT16 code)696 BOOL freerdp_input_send_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
697 {
698 	if (!input)
699 		return FALSE;
700 
701 	return IFCALLRESULT(TRUE, input->UnicodeKeyboardEvent, input, flags, code);
702 }
703 
freerdp_input_send_mouse_event(rdpInput * input,UINT16 flags,UINT16 x,UINT16 y)704 BOOL freerdp_input_send_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
705 {
706 	if (!input)
707 		return FALSE;
708 
709 	return IFCALLRESULT(TRUE, input->MouseEvent, input, flags, x, y);
710 }
711 
freerdp_input_send_extended_mouse_event(rdpInput * input,UINT16 flags,UINT16 x,UINT16 y)712 BOOL freerdp_input_send_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
713 {
714 	if (!input)
715 		return FALSE;
716 
717 	return IFCALLRESULT(TRUE, input->ExtendedMouseEvent, input, flags, x, y);
718 }
719 
freerdp_input_send_focus_in_event(rdpInput * input,UINT16 toggleStates)720 BOOL freerdp_input_send_focus_in_event(rdpInput* input, UINT16 toggleStates)
721 {
722 	if (!input)
723 		return FALSE;
724 
725 	return IFCALLRESULT(TRUE, input->FocusInEvent, input, toggleStates);
726 }
727 
freerdp_input_send_keyboard_pause_event(rdpInput * input)728 BOOL freerdp_input_send_keyboard_pause_event(rdpInput* input)
729 {
730 	if (!input)
731 		return FALSE;
732 
733 	return IFCALLRESULT(TRUE, input->KeyboardPauseEvent, input);
734 }
735 
input_process_events(rdpInput * input)736 int input_process_events(rdpInput* input)
737 {
738 	if (!input)
739 		return FALSE;
740 
741 	return input_message_queue_process_pending_messages(input);
742 }
743 
input_free_queued_message(void * obj)744 static void input_free_queued_message(void* obj)
745 {
746 	wMessage* msg = (wMessage*)obj;
747 	input_message_queue_free_message(msg);
748 }
749 
input_new(rdpRdp * rdp)750 rdpInput* input_new(rdpRdp* rdp)
751 {
752 	const wObject cb = { NULL, NULL, NULL, input_free_queued_message, NULL };
753 	rdpInput* input;
754 	input = (rdpInput*)calloc(1, sizeof(rdpInput));
755 
756 	if (!input)
757 		return NULL;
758 
759 	input->queue = MessageQueue_New(&cb);
760 
761 	if (!input->queue)
762 	{
763 		free(input);
764 		return NULL;
765 	}
766 
767 	return input;
768 }
769 
input_free(rdpInput * input)770 void input_free(rdpInput* input)
771 {
772 	if (input != NULL)
773 	{
774 		if (input->asynchronous)
775 			input_message_proxy_free(input->proxy);
776 
777 		MessageQueue_Free(input->queue);
778 		free(input);
779 	}
780 }
781