23 #include <freerdp/config.h>
25 #include <winpr/crt.h>
26 #include <winpr/print.h>
27 #include <winpr/stream.h>
29 #include "rdpei_main.h"
30 #include "../rdpei_common.h"
31 #include <freerdp/channels/rdpei.h>
32 #include <freerdp/server/rdpei.h>
37 STATE_WAITING_CLIENT_READY,
42 struct s_rdpei_server_private
52 UINT16 currentMsgType;
57 enum RdpEiState automataState;
60 RdpeiServerContext* rdpei_server_context_new(HANDLE vcm)
62 RdpeiServerContext* ret = calloc(1,
sizeof(*ret));
63 RdpeiServerPrivate* priv = NULL;
68 ret->priv = priv = calloc(1,
sizeof(*ret->priv));
72 priv->inputStream = Stream_New(NULL, 256);
73 if (!priv->inputStream)
76 priv->outputStream = Stream_New(NULL, 200);
77 if (!priv->inputStream)
81 rdpei_server_context_reset(ret);
85 WINPR_PRAGMA_DIAG_PUSH
86 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
87 rdpei_server_context_free(ret);
97 UINT rdpei_server_init(RdpeiServerContext* context)
100 DWORD bytesReturned = 0;
101 RdpeiServerPrivate* priv = context->priv;
102 UINT32 channelId = 0;
105 priv->channelHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, RDPEI_DVC_CHANNEL_NAME,
106 WTS_CHANNEL_OPTION_DYNAMIC);
107 if (!priv->channelHandle)
109 WLog_ERR(TAG,
"WTSVirtualChannelOpenEx failed!");
110 return CHANNEL_RC_INITIALIZATION_ERROR;
113 channelId = WTSChannelGetIdByHandle(priv->channelHandle);
115 IFCALLRET(context->onChannelIdAssigned, status, context, channelId);
118 WLog_ERR(TAG,
"context->onChannelIdAssigned failed!");
122 if (!WTSVirtualChannelQuery(priv->channelHandle, WTSVirtualEventHandle, &buffer,
124 (bytesReturned !=
sizeof(HANDLE)))
127 "WTSVirtualChannelQuery failed or invalid invalid returned size(%" PRIu32
")!",
130 WTSFreeMemory(buffer);
133 CopyMemory(&priv->eventHandle, buffer,
sizeof(HANDLE));
134 WTSFreeMemory(buffer);
136 return CHANNEL_RC_OK;
139 (void)WTSVirtualChannelClose(priv->channelHandle);
140 return CHANNEL_RC_INITIALIZATION_ERROR;
143 void rdpei_server_context_reset(RdpeiServerContext* context)
145 RdpeiServerPrivate* priv = context->priv;
147 priv->channelHandle = INVALID_HANDLE_VALUE;
148 priv->expectedBytes = RDPINPUT_HEADER_LENGTH;
149 priv->waitingHeaders = TRUE;
150 priv->automataState = STATE_INITIAL;
151 Stream_SetPosition(priv->inputStream, 0);
154 void rdpei_server_context_free(RdpeiServerContext* context)
156 RdpeiServerPrivate* priv = NULL;
160 priv = context->priv;
163 if (priv->channelHandle != INVALID_HANDLE_VALUE)
164 (void)WTSVirtualChannelClose(priv->channelHandle);
165 Stream_Free(priv->inputStream, TRUE);
171 HANDLE rdpei_server_get_event_handle(RdpeiServerContext* context)
173 return context->priv->eventHandle;
181 static UINT read_cs_ready_message(RdpeiServerContext* context,
wStream* s)
183 UINT error = CHANNEL_RC_OK;
184 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
185 return ERROR_INVALID_DATA;
187 Stream_Read_UINT32(s, context->protocolFlags);
188 Stream_Read_UINT32(s, context->clientVersion);
189 Stream_Read_UINT16(s, context->maxTouchPoints);
191 switch (context->clientVersion)
193 case RDPINPUT_PROTOCOL_V10:
194 case RDPINPUT_PROTOCOL_V101:
195 case RDPINPUT_PROTOCOL_V200:
196 case RDPINPUT_PROTOCOL_V300:
199 WLog_ERR(TAG,
"unhandled RPDEI protocol version 0x%" PRIx32
"", context->clientVersion);
203 IFCALLRET(context->onClientReady, error, context);
205 WLog_ERR(TAG,
"context->onClientReady failed with error %" PRIu32
"", error);
215 static UINT read_touch_contact_data(RdpeiServerContext* context,
wStream* s,
218 WINPR_UNUSED(context);
219 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
220 return ERROR_INVALID_DATA;
222 Stream_Read_UINT8(s, contactData->contactId);
223 if (!rdpei_read_2byte_unsigned(s, &contactData->fieldsPresent) ||
224 !rdpei_read_4byte_signed(s, &contactData->x) ||
225 !rdpei_read_4byte_signed(s, &contactData->y) ||
226 !rdpei_read_4byte_unsigned(s, &contactData->contactFlags))
228 WLog_ERR(TAG,
"rdpei_read_ failed!");
229 return ERROR_INTERNAL_ERROR;
232 if (contactData->fieldsPresent & CONTACT_DATA_CONTACTRECT_PRESENT)
234 if (!rdpei_read_2byte_signed(s, &contactData->contactRectLeft) ||
235 !rdpei_read_2byte_signed(s, &contactData->contactRectTop) ||
236 !rdpei_read_2byte_signed(s, &contactData->contactRectRight) ||
237 !rdpei_read_2byte_signed(s, &contactData->contactRectBottom))
239 WLog_ERR(TAG,
"rdpei_read_ failed!");
240 return ERROR_INTERNAL_ERROR;
244 if ((contactData->fieldsPresent & CONTACT_DATA_ORIENTATION_PRESENT) &&
245 !rdpei_read_4byte_unsigned(s, &contactData->orientation))
247 WLog_ERR(TAG,
"rdpei_read_ failed!");
248 return ERROR_INTERNAL_ERROR;
251 if ((contactData->fieldsPresent & CONTACT_DATA_PRESSURE_PRESENT) &&
252 !rdpei_read_4byte_unsigned(s, &contactData->pressure))
254 WLog_ERR(TAG,
"rdpei_read_ failed!");
255 return ERROR_INTERNAL_ERROR;
258 return CHANNEL_RC_OK;
261 static UINT read_pen_contact(RdpeiServerContext* context,
wStream* s,
264 WINPR_UNUSED(context);
265 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
266 return ERROR_INVALID_DATA;
268 Stream_Read_UINT8(s, contactData->deviceId);
269 if (!rdpei_read_2byte_unsigned(s, &contactData->fieldsPresent) ||
270 !rdpei_read_4byte_signed(s, &contactData->x) ||
271 !rdpei_read_4byte_signed(s, &contactData->y) ||
272 !rdpei_read_4byte_unsigned(s, &contactData->contactFlags))
274 WLog_ERR(TAG,
"rdpei_read_ failed!");
275 return ERROR_INTERNAL_ERROR;
278 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_PENFLAGS_PRESENT)
280 if (!rdpei_read_4byte_unsigned(s, &contactData->penFlags))
281 return ERROR_INVALID_DATA;
283 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_PRESSURE_PRESENT)
285 if (!rdpei_read_4byte_unsigned(s, &contactData->pressure))
286 return ERROR_INVALID_DATA;
288 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_ROTATION_PRESENT)
290 if (!rdpei_read_2byte_unsigned(s, &contactData->rotation))
291 return ERROR_INVALID_DATA;
293 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_TILTX_PRESENT)
295 if (!rdpei_read_2byte_signed(s, &contactData->tiltX))
296 return ERROR_INVALID_DATA;
298 if (contactData->fieldsPresent & RDPINPUT_PEN_CONTACT_TILTY_PRESENT)
300 if (!rdpei_read_2byte_signed(s, &contactData->tiltY))
301 return ERROR_INVALID_DATA;
304 return CHANNEL_RC_OK;
317 if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) ||
318 !rdpei_read_8byte_unsigned(s, &frame->frameOffset))
320 WLog_ERR(TAG,
"rdpei_read_ failed!");
321 return ERROR_INTERNAL_ERROR;
325 if (!frame->contacts)
327 WLog_ERR(TAG,
"calloc failed!");
328 return CHANNEL_RC_NO_MEMORY;
331 for (UINT32 i = 0; i < frame->contactCount; i++, contact++)
333 if ((error = read_touch_contact_data(context, s, contact)))
335 WLog_ERR(TAG,
"read_touch_contact_data failed with error %" PRIu32
"!", error);
336 frame->contactCount = i;
337 touch_frame_reset(frame);
341 return CHANNEL_RC_OK;
349 if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) ||
350 !rdpei_read_8byte_unsigned(s, &frame->frameOffset))
352 WLog_ERR(TAG,
"rdpei_read_ failed!");
353 return ERROR_INTERNAL_ERROR;
357 if (!frame->contacts)
359 WLog_ERR(TAG,
"calloc failed!");
360 return CHANNEL_RC_NO_MEMORY;
363 for (UINT32 i = 0; i < frame->contactCount; i++, contact++)
365 if ((error = read_pen_contact(context, s, contact)))
367 WLog_ERR(TAG,
"read_touch_contact_data failed with error %" PRIu32
"!", error);
368 frame->contactCount = i;
369 pen_frame_reset(frame);
373 return CHANNEL_RC_OK;
381 static UINT read_touch_event(RdpeiServerContext* context,
wStream* s)
383 UINT16 frameCount = 0;
386 UINT error = CHANNEL_RC_OK;
388 if (!rdpei_read_4byte_unsigned(s, &event->encodeTime) ||
389 !rdpei_read_2byte_unsigned(s, &frameCount))
391 WLog_ERR(TAG,
"rdpei_read_ failed!");
392 return ERROR_INTERNAL_ERROR;
395 event->frameCount = frameCount;
399 WLog_ERR(TAG,
"calloc failed!");
400 return CHANNEL_RC_NO_MEMORY;
403 for (UINT32 i = 0; i < frameCount; i++, frame++)
405 if ((error = read_touch_frame(context, s, frame)))
407 WLog_ERR(TAG,
"read_touch_contact_data failed with error %" PRIu32
"!", error);
408 event->frameCount = i;
413 IFCALLRET(context->onTouchEvent, error, context, event);
415 WLog_ERR(TAG,
"context->onTouchEvent failed with error %" PRIu32
"", error);
418 touch_event_reset(event);
422 static UINT read_pen_event(RdpeiServerContext* context,
wStream* s)
424 UINT16 frameCount = 0;
427 UINT error = CHANNEL_RC_OK;
429 if (!rdpei_read_4byte_unsigned(s, &event->encodeTime) ||
430 !rdpei_read_2byte_unsigned(s, &frameCount))
432 WLog_ERR(TAG,
"rdpei_read_ failed!");
433 return ERROR_INTERNAL_ERROR;
436 event->frameCount = frameCount;
440 WLog_ERR(TAG,
"calloc failed!");
441 return CHANNEL_RC_NO_MEMORY;
444 for (UINT32 i = 0; i < frameCount; i++, frame++)
446 if ((error = read_pen_frame(context, s, frame)))
448 WLog_ERR(TAG,
"read_pen_frame failed with error %" PRIu32
"!", error);
449 event->frameCount = i;
454 IFCALLRET(context->onPenEvent, error, context, event);
456 WLog_ERR(TAG,
"context->onPenEvent failed with error %" PRIu32
"", error);
459 pen_event_reset(event);
468 static UINT read_dismiss_hovering_contact(RdpeiServerContext* context,
wStream* s)
471 UINT error = CHANNEL_RC_OK;
473 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
474 return ERROR_INVALID_DATA;
476 Stream_Read_UINT8(s, contactId);
478 IFCALLRET(context->onTouchReleased, error, context, contactId);
480 WLog_ERR(TAG,
"context->onTouchReleased failed with error %" PRIu32
"", error);
490 UINT rdpei_server_handle_messages(RdpeiServerContext* context)
492 DWORD bytesReturned = 0;
493 RdpeiServerPrivate* priv = context->priv;
494 wStream* s = priv->inputStream;
495 UINT error = CHANNEL_RC_OK;
497 if (!WTSVirtualChannelRead(priv->channelHandle, 0, Stream_Pointer(s), priv->expectedBytes,
500 if (GetLastError() == ERROR_NO_DATA)
501 return ERROR_READ_FAULT;
503 WLog_DBG(TAG,
"channel connection closed");
504 return CHANNEL_RC_OK;
506 priv->expectedBytes -= bytesReturned;
507 Stream_Seek(s, bytesReturned);
509 if (priv->expectedBytes)
510 return CHANNEL_RC_OK;
512 Stream_SealLength(s);
513 Stream_SetPosition(s, 0);
515 if (priv->waitingHeaders)
520 Stream_Read_UINT16(s, priv->currentMsgType);
521 Stream_Read_UINT16(s, pduLen);
523 if (pduLen < RDPINPUT_HEADER_LENGTH)
525 WLog_ERR(TAG,
"invalid pduLength %" PRIu32
"", pduLen);
526 return ERROR_INVALID_DATA;
528 priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH;
529 priv->waitingHeaders = FALSE;
530 Stream_SetPosition(s, 0);
531 if (priv->expectedBytes)
533 if (!Stream_EnsureCapacity(s, priv->expectedBytes))
535 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
536 return CHANNEL_RC_NO_MEMORY;
538 return CHANNEL_RC_OK;
543 switch (priv->currentMsgType)
545 case EVENTID_CS_READY:
546 if (priv->automataState != STATE_WAITING_CLIENT_READY)
548 WLog_ERR(TAG,
"not expecting a CS_READY packet in this state(%d)",
549 priv->automataState);
550 return ERROR_INVALID_STATE;
553 if ((error = read_cs_ready_message(context, s)))
555 WLog_ERR(TAG,
"read_cs_ready_message failed with error %" PRIu32
"", error);
561 if ((error = read_touch_event(context, s)))
563 WLog_ERR(TAG,
"read_touch_event failed with error %" PRIu32
"", error);
567 case EVENTID_DISMISS_HOVERING_CONTACT:
568 if ((error = read_dismiss_hovering_contact(context, s)))
570 WLog_ERR(TAG,
"read_dismiss_hovering_contact failed with error %" PRIu32
"", error);
575 if ((error = read_pen_event(context, s)))
577 WLog_ERR(TAG,
"read_pen_event failed with error %" PRIu32
"", error);
582 WLog_ERR(TAG,
"unexpected message type 0x%" PRIx16
"", priv->currentMsgType);
585 Stream_SetPosition(s, 0);
586 priv->waitingHeaders = TRUE;
587 priv->expectedBytes = RDPINPUT_HEADER_LENGTH;
596 UINT rdpei_server_send_sc_ready(RdpeiServerContext* context, UINT32 version, UINT32 features)
599 RdpeiServerPrivate* priv = context->priv;
602 if (priv->automataState != STATE_INITIAL)
604 WLog_ERR(TAG,
"called from unexpected state %d", priv->automataState);
605 return ERROR_INVALID_STATE;
608 Stream_SetPosition(priv->outputStream, 0);
610 if (version >= RDPINPUT_PROTOCOL_V300)
613 if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH + pduLen))
615 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
616 return CHANNEL_RC_NO_MEMORY;
619 Stream_Write_UINT16(priv->outputStream, EVENTID_SC_READY);
620 Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH + pduLen);
621 Stream_Write_UINT32(priv->outputStream, version);
622 if (version >= RDPINPUT_PROTOCOL_V300)
623 Stream_Write_UINT32(priv->outputStream, features);
625 const size_t pos = Stream_GetPosition(priv->outputStream);
627 WINPR_ASSERT(pos <= UINT32_MAX);
628 if (!WTSVirtualChannelWrite(priv->channelHandle, Stream_BufferAs(priv->outputStream,
char),
629 (ULONG)pos, &written))
631 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
632 return ERROR_INTERNAL_ERROR;
635 priv->automataState = STATE_WAITING_CLIENT_READY;
636 return CHANNEL_RC_OK;
644 UINT rdpei_server_suspend(RdpeiServerContext* context)
647 RdpeiServerPrivate* priv = context->priv;
649 switch (priv->automataState)
651 case STATE_SUSPENDED:
652 WLog_ERR(TAG,
"already suspended");
653 return CHANNEL_RC_OK;
654 case STATE_WAITING_FRAME:
657 WLog_ERR(TAG,
"called from unexpected state %d", priv->automataState);
658 return ERROR_INVALID_STATE;
661 Stream_SetPosition(priv->outputStream, 0);
662 if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH))
664 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
665 return CHANNEL_RC_NO_MEMORY;
668 Stream_Write_UINT16(priv->outputStream, EVENTID_SUSPEND_TOUCH);
669 Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH);
671 const size_t pos = Stream_GetPosition(priv->outputStream);
673 WINPR_ASSERT(pos <= UINT32_MAX);
674 if (!WTSVirtualChannelWrite(priv->channelHandle, Stream_BufferAs(priv->outputStream,
char),
675 (ULONG)pos, &written))
677 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
678 return ERROR_INTERNAL_ERROR;
681 priv->automataState = STATE_SUSPENDED;
682 return CHANNEL_RC_OK;
690 UINT rdpei_server_resume(RdpeiServerContext* context)
693 RdpeiServerPrivate* priv = context->priv;
695 switch (priv->automataState)
697 case STATE_WAITING_FRAME:
698 WLog_ERR(TAG,
"not suspended");
699 return CHANNEL_RC_OK;
700 case STATE_SUSPENDED:
703 WLog_ERR(TAG,
"called from unexpected state %d", priv->automataState);
704 return ERROR_INVALID_STATE;
707 Stream_SetPosition(priv->outputStream, 0);
708 if (!Stream_EnsureCapacity(priv->outputStream, RDPINPUT_HEADER_LENGTH))
710 WLog_ERR(TAG,
"Stream_EnsureCapacity failed!");
711 return CHANNEL_RC_NO_MEMORY;
714 Stream_Write_UINT16(priv->outputStream, EVENTID_RESUME_TOUCH);
715 Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH);
717 const size_t pos = Stream_GetPosition(priv->outputStream);
719 WINPR_ASSERT(pos <= UINT32_MAX);
720 if (!WTSVirtualChannelWrite(priv->channelHandle, Stream_BufferAs(priv->outputStream,
char),
721 (ULONG)pos, &written))
723 WLog_ERR(TAG,
"WTSVirtualChannelWrite failed!");
724 return ERROR_INTERNAL_ERROR;
727 priv->automataState = STATE_WAITING_FRAME;
728 return CHANNEL_RC_OK;