FreeRDP
Loading...
Searching...
No Matches
server/rdpei_main.c
1
23#include <freerdp/config.h>
24
25#include <winpr/cast.h>
26#include <winpr/crt.h>
27#include <winpr/print.h>
28#include <winpr/stream.h>
29
30#include "rdpei_main.h"
31#include "../rdpei_common.h"
32#include <freerdp/channels/rdpei.h>
33#include <freerdp/server/rdpei.h>
34
35typedef enum
36{
37 RDPEI_INITIAL,
38 RDPEI_OPENED,
39} eRdpEiChannelState;
40
41enum RdpEiState
42{
43 STATE_INITIAL,
44 STATE_WAITING_CLIENT_READY,
45 STATE_WAITING_FRAME,
46 STATE_SUSPENDED,
47};
48
49struct s_rdpei_server_private
50{
51 HANDLE channelHandle;
52 HANDLE eventHandle;
53
54 HANDLE stopEvent;
55 HANDLE thread;
56
57 /* Channel state */
58 eRdpEiChannelState channelState;
59
60 UINT32 expectedBytes;
61 BOOL waitingHeaders;
62 wStream* inputStream;
63 wStream* outputStream;
64
65 UINT16 currentMsgType;
66
67 RDPINPUT_TOUCH_EVENT touchEvent;
68 RDPINPUT_PEN_EVENT penEvent;
69
70 enum RdpEiState automataState;
71};
72
73static UINT rdpei_server_open_channel(RdpeiServerContext* context)
74{
75 DWORD error = ERROR_SUCCESS;
76 DWORD bytesReturned = 0;
77 PULONG pSessionId = NULL;
78 BOOL status = TRUE;
79
80 WINPR_ASSERT(context);
81
82 RdpeiServerPrivate* priv = context->priv;
83 WINPR_ASSERT(priv);
84
85 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId,
86 (LPSTR*)&pSessionId, &bytesReturned) == FALSE)
87 {
88 WLog_ERR(TAG, "WTSQuerySessionInformationA failed!");
89 return ERROR_INTERNAL_ERROR;
90 }
91
92 DWORD sessionId = (DWORD)*pSessionId;
93 WTSFreeMemory(pSessionId);
94
95 priv->channelHandle =
96 WTSVirtualChannelOpenEx(sessionId, RDPEI_DVC_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC);
97 if (!priv->channelHandle)
98 {
99 error = GetLastError();
100 WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed with error %" PRIu32 "!", error);
101 return error;
102 }
103
104 const UINT32 channelId = WTSChannelGetIdByHandle(priv->channelHandle);
105
106 IFCALLRET(context->onChannelIdAssigned, status, context, channelId);
107 if (!status)
108 {
109 WLog_ERR(TAG, "context->onChannelIdAssigned failed!");
110 return ERROR_INTERNAL_ERROR;
111 }
112
113 return error;
114}
115
116static UINT rdpei_server_context_poll_int(RdpeiServerContext* context)
117{
118 RdpeiServerPrivate* priv = NULL;
119 UINT error = ERROR_INTERNAL_ERROR;
120
121 WINPR_ASSERT(context);
122 priv = context->priv;
123 WINPR_ASSERT(priv);
124
125 switch (priv->channelState)
126 {
127 case RDPEI_INITIAL:
128 error = rdpei_server_open_channel(context);
129 if (error)
130 WLog_ERR(TAG, "rdpei_server_open_channel failed with error %" PRIu32 "!", error);
131 else
132 priv->channelState = RDPEI_OPENED;
133 break;
134 case RDPEI_OPENED:
135 error = rdpei_server_handle_messages(context);
136 break;
137 default:
138 break;
139 }
140
141 return error;
142}
143
144static HANDLE rdpei_server_get_channel_handle(RdpeiServerContext* context)
145{
146 RdpeiServerPrivate* priv = NULL;
147 void* buffer = NULL;
148 DWORD bytesReturned = 0;
149 HANDLE channelEvent = NULL;
150
151 WINPR_ASSERT(context);
152 priv = context->priv;
153 WINPR_ASSERT(priv);
154
155 if (WTSVirtualChannelQuery(priv->channelHandle, WTSVirtualEventHandle, &buffer,
156 &bytesReturned) == TRUE)
157 {
158 if (bytesReturned == sizeof(HANDLE))
159 channelEvent = *(HANDLE*)buffer;
160
161 WTSFreeMemory(buffer);
162 }
163
164 return channelEvent;
165}
166
167static DWORD WINAPI rdpei_server_thread_func(LPVOID arg)
168{
169 RdpeiServerContext* context = (RdpeiServerContext*)arg;
170 RdpeiServerPrivate* priv = NULL;
171 HANDLE events[2] = { 0 };
172 DWORD nCount = 0;
173 UINT error = CHANNEL_RC_OK;
174 DWORD status = 0;
175
176 WINPR_ASSERT(context);
177 priv = context->priv;
178 WINPR_ASSERT(priv);
179
180 events[nCount++] = priv->stopEvent;
181
182 while ((error == CHANNEL_RC_OK) && (WaitForSingleObject(events[0], 0) != WAIT_OBJECT_0))
183 {
184 switch (priv->channelState)
185 {
186 case RDPEI_INITIAL:
187 error = rdpei_server_context_poll_int(context);
188 if (error == CHANNEL_RC_OK)
189 {
190 events[1] = rdpei_server_get_channel_handle(context);
191 nCount = 2;
192 }
193 break;
194 case RDPEI_OPENED:
195 status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
196 switch (status)
197 {
198 case WAIT_OBJECT_0:
199 break;
200 case WAIT_OBJECT_0 + 1:
201 case WAIT_TIMEOUT:
202 error = rdpei_server_context_poll_int(context);
203 break;
204
205 case WAIT_FAILED:
206 default:
207 error = ERROR_INTERNAL_ERROR;
208 break;
209 }
210 break;
211 default:
212 break;
213 }
214 }
215
216 (void)WTSVirtualChannelClose(priv->channelHandle);
217 priv->channelHandle = NULL;
218
219 ExitThread(error);
220 return error;
221}
222
223static UINT rdpei_server_open(RdpeiServerContext* context)
224{
225 RdpeiServerPrivate* priv = NULL;
226
227 priv = context->priv;
228 WINPR_ASSERT(priv);
229
230 if (!priv->thread)
231 {
232 priv->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
233 if (!priv->stopEvent)
234 {
235 WLog_ERR(TAG, "CreateEvent failed!");
236 return ERROR_INTERNAL_ERROR;
237 }
238
239 priv->thread = CreateThread(NULL, 0, rdpei_server_thread_func, context, 0, NULL);
240 if (!priv->thread)
241 {
242 WLog_ERR(TAG, "CreateThread failed!");
243 (void)CloseHandle(priv->stopEvent);
244 priv->stopEvent = NULL;
245 return ERROR_INTERNAL_ERROR;
246 }
247 }
248
249 return CHANNEL_RC_OK;
250}
251
252static UINT rdpei_server_close(RdpeiServerContext* context)
253{
254 RdpeiServerPrivate* priv = NULL;
255 UINT error = CHANNEL_RC_OK;
256
257 priv = context->priv;
258 WINPR_ASSERT(priv);
259
260 if (priv->thread)
261 {
262 (void)SetEvent(priv->stopEvent);
263
264 if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
265 {
266 error = GetLastError();
267 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error);
268 return error;
269 }
270
271 (void)CloseHandle(priv->thread);
272 (void)CloseHandle(priv->stopEvent);
273 priv->thread = NULL;
274 priv->stopEvent = NULL;
275 }
276
277 return error;
278}
279
280RdpeiServerContext* rdpei_server_context_new(HANDLE vcm)
281{
282 RdpeiServerContext* ret = calloc(1, sizeof(*ret));
283
284 if (!ret)
285 return NULL;
286
287 ret->Open = rdpei_server_open;
288 ret->Close = rdpei_server_close;
289
290 ret->priv = calloc(1, sizeof(*ret->priv));
291 if (!ret->priv)
292 goto fail;
293
294 ret->priv->inputStream = Stream_New(NULL, 256);
295 if (!ret->priv->inputStream)
296 goto fail;
297
298 ret->priv->outputStream = Stream_New(NULL, 200);
299 if (!ret->priv->inputStream)
300 goto fail;
301
302 ret->vcm = vcm;
303 rdpei_server_context_reset(ret);
304 return ret;
305
306fail:
307 WINPR_PRAGMA_DIAG_PUSH
308 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
309 rdpei_server_context_free(ret);
310 WINPR_PRAGMA_DIAG_POP
311 return NULL;
312}
313
319UINT rdpei_server_init(RdpeiServerContext* context)
320{
321 RdpeiServerPrivate* priv = context->priv;
322 UINT error = rdpei_server_open_channel(context);
323 if (error)
324 return error;
325
326 priv->eventHandle = rdpei_server_get_channel_handle(context);
327 if (!priv->eventHandle)
328 {
329 WLog_ERR(TAG, "Failed to get channel handle!");
330 goto out_close;
331 }
332
333 return CHANNEL_RC_OK;
334
335out_close:
336 (void)WTSVirtualChannelClose(priv->channelHandle);
337 return CHANNEL_RC_INITIALIZATION_ERROR;
338}
339
340void rdpei_server_context_reset(RdpeiServerContext* context)
341{
342 RdpeiServerPrivate* priv = context->priv;
343
344 priv->channelHandle = INVALID_HANDLE_VALUE;
345 priv->expectedBytes = RDPINPUT_HEADER_LENGTH;
346 priv->waitingHeaders = TRUE;
347 priv->automataState = STATE_INITIAL;
348 Stream_SetPosition(priv->inputStream, 0);
349}
350
351void rdpei_server_context_free(RdpeiServerContext* context)
352{
353 RdpeiServerPrivate* priv = NULL;
354
355 if (!context)
356 return;
357 priv = context->priv;
358 if (priv)
359 {
360 if (priv->channelHandle && priv->channelHandle != INVALID_HANDLE_VALUE)
361 (void)WTSVirtualChannelClose(priv->channelHandle);
362 Stream_Free(priv->inputStream, TRUE);
363 }
364 free(priv);
365 free(context);
366}
367
368HANDLE rdpei_server_get_event_handle(RdpeiServerContext* context)
369{
370 return context->priv->eventHandle;
371}
372
378static UINT read_cs_ready_message(RdpeiServerContext* context, wStream* s)
379{
380 UINT error = CHANNEL_RC_OK;
381 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
382 return ERROR_INVALID_DATA;
383
384 Stream_Read_UINT32(s, context->protocolFlags);
385 Stream_Read_UINT32(s, context->clientVersion);
386 Stream_Read_UINT16(s, context->maxTouchPoints);
387
388 switch (context->clientVersion)
389 {
390 case RDPINPUT_PROTOCOL_V10:
391 case RDPINPUT_PROTOCOL_V101:
392 case RDPINPUT_PROTOCOL_V200:
393 case RDPINPUT_PROTOCOL_V300:
394 break;
395 default:
396 WLog_ERR(TAG, "unhandled RPDEI protocol version 0x%" PRIx32 "", context->clientVersion);
397 break;
398 }
399
400 IFCALLRET(context->onClientReady, error, context);
401 if (error)
402 WLog_ERR(TAG, "context->onClientReady failed with error %" PRIu32 "", error);
403
404 return error;
405}
406
412static UINT read_touch_contact_data(RdpeiServerContext* context, wStream* s,
413 RDPINPUT_CONTACT_DATA* contactData)
414{
415 WINPR_UNUSED(context);
416 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
417 return ERROR_INVALID_DATA;
418
419 Stream_Read_UINT8(s, contactData->contactId);
420 if (!rdpei_read_2byte_unsigned(s, &contactData->fieldsPresent) ||
421 !rdpei_read_4byte_signed(s, &contactData->x) ||
422 !rdpei_read_4byte_signed(s, &contactData->y) ||
423 !rdpei_read_4byte_unsigned(s, &contactData->contactFlags))
424 {
425 WLog_ERR(TAG, "rdpei_read_ failed!");
426 return ERROR_INTERNAL_ERROR;
427 }
428
429 if (contactData->fieldsPresent & CONTACT_DATA_CONTACTRECT_PRESENT)
430 {
431 if (!rdpei_read_2byte_signed(s, &contactData->contactRectLeft) ||
432 !rdpei_read_2byte_signed(s, &contactData->contactRectTop) ||
433 !rdpei_read_2byte_signed(s, &contactData->contactRectRight) ||
434 !rdpei_read_2byte_signed(s, &contactData->contactRectBottom))
435 {
436 WLog_ERR(TAG, "rdpei_read_ failed!");
437 return ERROR_INTERNAL_ERROR;
438 }
439 }
440
441 if ((contactData->fieldsPresent & CONTACT_DATA_ORIENTATION_PRESENT) &&
442 !rdpei_read_4byte_unsigned(s, &contactData->orientation))
443 {
444 WLog_ERR(TAG, "rdpei_read_ failed!");
445 return ERROR_INTERNAL_ERROR;
446 }
447
448 if ((contactData->fieldsPresent & CONTACT_DATA_PRESSURE_PRESENT) &&
449 !rdpei_read_4byte_unsigned(s, &contactData->pressure))
450 {
451 WLog_ERR(TAG, "rdpei_read_ failed!");
452 return ERROR_INTERNAL_ERROR;
453 }
454
455 return CHANNEL_RC_OK;
456}
457
458static UINT read_pen_contact(RdpeiServerContext* context, wStream* s,
459 RDPINPUT_PEN_CONTACT* contactData)
460{
461 WINPR_UNUSED(context);
462 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
463 return ERROR_INVALID_DATA;
464
465 Stream_Read_UINT8(s, contactData->deviceId);
466 if (!rdpei_read_2byte_unsigned(s, &contactData->fieldsPresent) ||
467 !rdpei_read_4byte_signed(s, &contactData->x) ||
468 !rdpei_read_4byte_signed(s, &contactData->y) ||
469 !rdpei_read_4byte_unsigned(s, &contactData->contactFlags))
470 {
471 WLog_ERR(TAG, "rdpei_read_ failed!");
472 return ERROR_INTERNAL_ERROR;
473 }
474
475 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_PENFLAGS_PRESENT)
476 {
477 if (!rdpei_read_4byte_unsigned(s, &contactData->penFlags))
478 return ERROR_INVALID_DATA;
479 }
480 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_PRESSURE_PRESENT)
481 {
482 if (!rdpei_read_4byte_unsigned(s, &contactData->pressure))
483 return ERROR_INVALID_DATA;
484 }
485 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_ROTATION_PRESENT)
486 {
487 if (!rdpei_read_2byte_unsigned(s, &contactData->rotation))
488 return ERROR_INVALID_DATA;
489 }
490 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_TILTX_PRESENT)
491 {
492 if (!rdpei_read_2byte_signed(s, &contactData->tiltX))
493 return ERROR_INVALID_DATA;
494 }
495 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_TILTY_PRESENT)
496 {
497 if (!rdpei_read_2byte_signed(s, &contactData->tiltY))
498 return ERROR_INVALID_DATA;
499 }
500
501 return CHANNEL_RC_OK;
502}
503
509static UINT read_touch_frame(RdpeiServerContext* context, wStream* s, RDPINPUT_TOUCH_FRAME* frame)
510{
511 RDPINPUT_CONTACT_DATA* contact = NULL;
512 UINT error = 0;
513
514 if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) ||
515 !rdpei_read_8byte_unsigned(s, &frame->frameOffset))
516 {
517 WLog_ERR(TAG, "rdpei_read_ failed!");
518 return ERROR_INTERNAL_ERROR;
519 }
520
521 frame->contacts = contact = calloc(frame->contactCount, sizeof(RDPINPUT_CONTACT_DATA));
522 if (!frame->contacts)
523 {
524 WLog_ERR(TAG, "calloc failed!");
525 return CHANNEL_RC_NO_MEMORY;
526 }
527
528 for (UINT32 i = 0; i < frame->contactCount; i++, contact++)
529 {
530 if ((error = read_touch_contact_data(context, s, contact)))
531 {
532 WLog_ERR(TAG, "read_touch_contact_data failed with error %" PRIu32 "!", error);
533 frame->contactCount = WINPR_ASSERTING_INT_CAST(UINT16, i);
534 touch_frame_reset(frame);
535 return error;
536 }
537 }
538 return CHANNEL_RC_OK;
539}
540
541static UINT read_pen_frame(RdpeiServerContext* context, wStream* s, RDPINPUT_PEN_FRAME* frame)
542{
543 RDPINPUT_PEN_CONTACT* contact = NULL;
544 UINT error = 0;
545
546 if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) ||
547 !rdpei_read_8byte_unsigned(s, &frame->frameOffset))
548 {
549 WLog_ERR(TAG, "rdpei_read_ failed!");
550 return ERROR_INTERNAL_ERROR;
551 }
552
553 frame->contacts = contact = calloc(frame->contactCount, sizeof(RDPINPUT_PEN_CONTACT));
554 if (!frame->contacts)
555 {
556 WLog_ERR(TAG, "calloc failed!");
557 return CHANNEL_RC_NO_MEMORY;
558 }
559
560 for (UINT32 i = 0; i < frame->contactCount; i++, contact++)
561 {
562 if ((error = read_pen_contact(context, s, contact)))
563 {
564 WLog_ERR(TAG, "read_touch_contact_data failed with error %" PRIu32 "!", error);
565 frame->contactCount = WINPR_ASSERTING_INT_CAST(UINT16, i);
566
567 pen_frame_reset(frame);
568 return error;
569 }
570 }
571 return CHANNEL_RC_OK;
572}
573
579static UINT read_touch_event(RdpeiServerContext* context, wStream* s)
580{
581 UINT16 frameCount = 0;
582 RDPINPUT_TOUCH_EVENT* event = &context->priv->touchEvent;
583 RDPINPUT_TOUCH_FRAME* frame = NULL;
584 UINT error = CHANNEL_RC_OK;
585
586 if (!rdpei_read_4byte_unsigned(s, &event->encodeTime) ||
587 !rdpei_read_2byte_unsigned(s, &frameCount))
588 {
589 WLog_ERR(TAG, "rdpei_read_ failed!");
590 return ERROR_INTERNAL_ERROR;
591 }
592
593 event->frameCount = frameCount;
594 event->frames = frame = calloc(event->frameCount, sizeof(RDPINPUT_TOUCH_FRAME));
595 if (!event->frames)
596 {
597 WLog_ERR(TAG, "calloc failed!");
598 return CHANNEL_RC_NO_MEMORY;
599 }
600
601 for (UINT32 i = 0; i < frameCount; i++, frame++)
602 {
603 if ((error = read_touch_frame(context, s, frame)))
604 {
605 WLog_ERR(TAG, "read_touch_contact_data failed with error %" PRIu32 "!", error);
606 event->frameCount = WINPR_ASSERTING_INT_CAST(UINT16, i);
607
608 goto out_cleanup;
609 }
610 }
611
612 IFCALLRET(context->onTouchEvent, error, context, event);
613 if (error)
614 WLog_ERR(TAG, "context->onTouchEvent failed with error %" PRIu32 "", error);
615
616out_cleanup:
617 touch_event_reset(event);
618 return error;
619}
620
621static UINT read_pen_event(RdpeiServerContext* context, wStream* s)
622{
623 UINT16 frameCount = 0;
624 RDPINPUT_PEN_EVENT* event = &context->priv->penEvent;
625 RDPINPUT_PEN_FRAME* frame = NULL;
626 UINT error = CHANNEL_RC_OK;
627
628 if (!rdpei_read_4byte_unsigned(s, &event->encodeTime) ||
629 !rdpei_read_2byte_unsigned(s, &frameCount))
630 {
631 WLog_ERR(TAG, "rdpei_read_ failed!");
632 return ERROR_INTERNAL_ERROR;
633 }
634
635 event->frameCount = frameCount;
636 event->frames = frame = calloc(event->frameCount, sizeof(RDPINPUT_PEN_FRAME));
637 if (!event->frames)
638 {
639 WLog_ERR(TAG, "calloc failed!");
640 return CHANNEL_RC_NO_MEMORY;
641 }
642
643 for (UINT32 i = 0; i < frameCount; i++, frame++)
644 {
645 if ((error = read_pen_frame(context, s, frame)))
646 {
647 WLog_ERR(TAG, "read_pen_frame failed with error %" PRIu32 "!", error);
648 event->frameCount = WINPR_ASSERTING_INT_CAST(UINT16, i);
649
650 goto out_cleanup;
651 }
652 }
653
654 IFCALLRET(context->onPenEvent, error, context, event);
655 if (error)
656 WLog_ERR(TAG, "context->onPenEvent failed with error %" PRIu32 "", error);
657
658out_cleanup:
659 pen_event_reset(event);
660 return error;
661}
662
668static UINT read_dismiss_hovering_contact(RdpeiServerContext* context, wStream* s)
669{
670 BYTE contactId = 0;
671 UINT error = CHANNEL_RC_OK;
672
673 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
674 return ERROR_INVALID_DATA;
675
676 Stream_Read_UINT8(s, contactId);
677
678 IFCALLRET(context->onTouchReleased, error, context, contactId);
679 if (error)
680 WLog_ERR(TAG, "context->onTouchReleased failed with error %" PRIu32 "", error);
681
682 return error;
683}
684
690UINT rdpei_server_handle_messages(RdpeiServerContext* context)
691{
692 DWORD bytesReturned = 0;
693 RdpeiServerPrivate* priv = context->priv;
694 wStream* s = priv->inputStream;
695 UINT error = CHANNEL_RC_OK;
696
697 if (!WTSVirtualChannelRead(priv->channelHandle, 0, Stream_Pointer(s), priv->expectedBytes,
698 &bytesReturned))
699 {
700 if (GetLastError() == ERROR_NO_DATA)
701 return ERROR_READ_FAULT;
702
703 WLog_DBG(TAG, "channel connection closed");
704 return CHANNEL_RC_OK;
705 }
706 priv->expectedBytes -= bytesReturned;
707 Stream_Seek(s, bytesReturned);
708
709 if (priv->expectedBytes)
710 return CHANNEL_RC_OK;
711
712 Stream_SealLength(s);
713 Stream_SetPosition(s, 0);
714
715 if (priv->waitingHeaders)
716 {
717 UINT32 pduLen = 0;
718
719 /* header case */
720 Stream_Read_UINT16(s, priv->currentMsgType);
721 Stream_Read_UINT32(s, pduLen);
722
723 if (pduLen < RDPINPUT_HEADER_LENGTH)
724 {
725 WLog_ERR(TAG, "invalid pduLength %" PRIu32 "", pduLen);
726 return ERROR_INVALID_DATA;
727 }
728 priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH;
729 priv->waitingHeaders = FALSE;
730 Stream_SetPosition(s, 0);
731 if (priv->expectedBytes)
732 {
733 if (!Stream_EnsureCapacity(s, priv->expectedBytes))
734 {
735 WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
736 return CHANNEL_RC_NO_MEMORY;
737 }
738 return CHANNEL_RC_OK;
739 }
740 }
741
742 /* when here we have the header + the body */
743 switch (priv->currentMsgType)
744 {
745 case EVENTID_CS_READY:
746 if (priv->automataState != STATE_WAITING_CLIENT_READY)
747 {
748 WLog_ERR(TAG, "not expecting a CS_READY packet in this state(%d)",
749 priv->automataState);
750 return ERROR_INVALID_STATE;
751 }
752
753 if ((error = read_cs_ready_message(context, s)))
754 {
755 WLog_ERR(TAG, "read_cs_ready_message failed with error %" PRIu32 "", error);
756 return error;
757 }
758 break;
759
760 case EVENTID_TOUCH:
761 if ((error = read_touch_event(context, s)))
762 {
763 WLog_ERR(TAG, "read_touch_event failed with error %" PRIu32 "", error);
764 return error;
765 }
766 break;
767 case EVENTID_DISMISS_HOVERING_CONTACT:
768 if ((error = read_dismiss_hovering_contact(context, s)))
769 {
770 WLog_ERR(TAG, "read_dismiss_hovering_contact failed with error %" PRIu32 "", error);
771 return error;
772 }
773 break;
774 case EVENTID_PEN:
775 if ((error = read_pen_event(context, s)))
776 {
777 WLog_ERR(TAG, "read_pen_event failed with error %" PRIu32 "", error);
778 return error;
779 }
780 break;
781 default:
782 WLog_ERR(TAG, "unexpected message type 0x%" PRIx16 "", priv->currentMsgType);
783 }
784
785 Stream_SetPosition(s, 0);
786 priv->waitingHeaders = TRUE;
787 priv->expectedBytes = RDPINPUT_HEADER_LENGTH;
788 return error;
789}
790
796UINT rdpei_server_send_sc_ready(RdpeiServerContext* context, UINT32 version, UINT32 features)
797{
798 ULONG written = 0;
799 RdpeiServerPrivate* priv = context->priv;
800 UINT32 pduLen = 4;
801
802 if (priv->automataState != STATE_INITIAL)
803 {
804 WLog_ERR(TAG, "called from unexpected state %d", priv->automataState);
805 return ERROR_INVALID_STATE;
806 }
807
808 Stream_SetPosition(priv->outputStream, 0);
809
810 if (version >= RDPINPUT_PROTOCOL_V300)
811 pduLen += 4;
812
813 if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + pduLen))
814 {
815 WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
816 return CHANNEL_RC_NO_MEMORY;
817 }
818
819 Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY);
820 Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + pduLen);
821 Stream_Write_UINT32(priv->outputStream, version);
822 if (version >= RDPINPUT_PROTOCOL_V300)
823 Stream_Write_UINT32(priv->outputStream, features);
824
825 const size_t pos = Stream_GetPosition(priv->outputStream);
826
827 WINPR_ASSERT(pos <= UINT32_MAX);
828 if (!WTSVirtualChannelWrite(priv->channelHandle, Stream_BufferAs(priv->outputStream, char),
829 (ULONG)pos, &written))
830 {
831 WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
832 return ERROR_INTERNAL_ERROR;
833 }
834
835 priv->automataState = STATE_WAITING_CLIENT_READY;
836 return CHANNEL_RC_OK;
837}
838
844UINT rdpei_server_suspend(RdpeiServerContext* context)
845{
846 ULONG written = 0;
847 RdpeiServerPrivate* priv = context->priv;
848
849 switch (priv->automataState)
850 {
851 case STATE_SUSPENDED:
852 WLog_ERR(TAG, "already suspended");
853 return CHANNEL_RC_OK;
854 case STATE_WAITING_FRAME:
855 break;
856 default:
857 WLog_ERR(TAG, "called from unexpected state %d", priv->automataState);
858 return ERROR_INVALID_STATE;
859 }
860
861 Stream_SetPosition(priv->outputStream, 0);
862 if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH))
863 {
864 WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
865 return CHANNEL_RC_NO_MEMORY;
866 }
867
868 Stream_Write_UINT16(priv->outputStream, EVENTID_SUSPEND_TOUCH);
869 Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH);
870
871 const size_t pos = Stream_GetPosition(priv->outputStream);
872
873 WINPR_ASSERT(pos <= UINT32_MAX);
874 if (!WTSVirtualChannelWrite(priv->channelHandle, Stream_BufferAs(priv->outputStream, char),
875 (ULONG)pos, &written))
876 {
877 WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
878 return ERROR_INTERNAL_ERROR;
879 }
880
881 priv->automataState = STATE_SUSPENDED;
882 return CHANNEL_RC_OK;
883}
884
890UINT rdpei_server_resume(RdpeiServerContext* context)
891{
892 ULONG written = 0;
893 RdpeiServerPrivate* priv = context->priv;
894
895 switch (priv->automataState)
896 {
897 case STATE_WAITING_FRAME:
898 WLog_ERR(TAG, "not suspended");
899 return CHANNEL_RC_OK;
900 case STATE_SUSPENDED:
901 break;
902 default:
903 WLog_ERR(TAG, "called from unexpected state %d", priv->automataState);
904 return ERROR_INVALID_STATE;
905 }
906
907 Stream_SetPosition(priv->outputStream, 0);
908 if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH))
909 {
910 WLog_ERR(TAG, "Stream_EnsureCapacity failed!");
911 return CHANNEL_RC_NO_MEMORY;
912 }
913
914 Stream_Write_UINT16(priv->outputStream, EVENTID_RESUME_TOUCH);
915 Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH);
916
917 const size_t pos = Stream_GetPosition(priv->outputStream);
918
919 WINPR_ASSERT(pos <= UINT32_MAX);
920 if (!WTSVirtualChannelWrite(priv->channelHandle, Stream_BufferAs(priv->outputStream, char),
921 (ULONG)pos, &written))
922 {
923 WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
924 return ERROR_INTERNAL_ERROR;
925 }
926
927 priv->automataState = STATE_WAITING_FRAME;
928 return CHANNEL_RC_OK;
929}
a touch event with some frames
a touch event with some frames
a frame containing contact points