22#include <freerdp/config.h>
25#include <winpr/assert.h>
26#include <winpr/print.h>
28#include <freerdp/freerdp.h>
29#include <freerdp/channels/log.h>
30#include <freerdp/client/encomsp.h>
32#include "encomsp_main.h"
39 EncomspClientContext* context;
46 rdpContext* rdpcontext;
47 BOOL firstFlagReceived;
59 if (!Stream_CheckAndLogRequiredLength(TAG, s, ENCOMSP_ORDER_HEADER_SIZE))
60 return ERROR_INVALID_DATA;
62 Stream_Read_UINT16(s, header->Type);
63 Stream_Read_UINT16(s, header->Length);
75 Stream_Write_UINT16(s, header->Type);
76 Stream_Write_UINT16(s, header->Length);
91 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
92 return ERROR_INVALID_DATA;
94 Stream_Read_UINT16(s, str->cchString);
96 if (str->cchString > 1024)
98 WLog_ERR(TAG,
"cchString was %" PRIu16
" but has to be < 1025!", str->cchString);
99 return ERROR_INVALID_DATA;
102 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, str->cchString,
sizeof(WCHAR)))
103 return ERROR_INVALID_DATA;
105 Stream_Read(s, &(str->wString), (
sizeof(WCHAR) * str->cchString));
106 return CHANNEL_RC_OK;
109static EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp)
111 WINPR_ASSERT(encomsp);
112 return (EncomspClientContext*)encomsp->channelEntryPoints.pInterface;
120static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp,
wStream* s)
124 Stream_Free(s, TRUE);
125 return ERROR_INVALID_HANDLE;
128 const UINT status = encomsp->channelEntryPoints.pVirtualChannelWriteEx(
129 encomsp->InitHandle, encomsp->OpenHandle, Stream_Buffer(s), (UINT32)Stream_Length(s), s);
131 if (status != CHANNEL_RC_OK)
133 Stream_Free(s, TRUE);
134 WLog_ERR(TAG,
"VirtualChannelWriteEx failed with %s [%08" PRIX32
"]",
135 WTSErrorToString(status), status);
145static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp,
wStream* s,
149 UINT error = CHANNEL_RC_OK;
150 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
153 return ERROR_INVALID_HANDLE;
155 WINPR_ASSERT(header);
156 const size_t pos = Stream_GetPosition(s);
157 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
158 return ERROR_INVALID_DATA;
159 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
160 pdu.Length = header->Length;
161 pdu.Type = header->Type;
163 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
164 return ERROR_INVALID_DATA;
166 Stream_Read_UINT8(s, pdu.Flags);
167 const size_t end = Stream_GetPosition(s);
168 const size_t body = beg + header->Length;
172 WLog_ERR(TAG,
"Not enough data!");
173 return ERROR_INVALID_DATA;
178 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
179 return ERROR_INVALID_DATA;
181 if (!Stream_SetPosition(s, body))
182 return ERROR_INVALID_DATA;
185 IFCALLRET(context->FilterUpdated, error, context, &pdu);
188 WLog_ERR(TAG,
"context->FilterUpdated failed with error %" PRIu32
"", error);
198static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp,
wStream* s,
202 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
205 return ERROR_INVALID_HANDLE;
207 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
208 return ERROR_INVALID_DATA;
210 const size_t pos = Stream_GetPosition(s);
211 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
212 return ERROR_INVALID_DATA;
213 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
215 WINPR_ASSERT(header);
216 pdu.Length = header->Length;
217 pdu.Type = header->Type;
219 Stream_Read_UINT16(s, pdu.Flags);
220 Stream_Read_UINT32(s, pdu.AppId);
222 UINT error = encomsp_read_unicode_string(s, &(pdu.Name));
223 if (error != CHANNEL_RC_OK)
225 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
229 const size_t end = Stream_GetPosition(s);
230 const size_t body = beg + header->Length;
234 WLog_ERR(TAG,
"Not enough data!");
235 return ERROR_INVALID_DATA;
240 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
241 return ERROR_INVALID_DATA;
243 if (!Stream_SetPosition(s, body))
244 return ERROR_INVALID_DATA;
247 IFCALLRET(context->ApplicationCreated, error, context, &pdu);
250 WLog_ERR(TAG,
"context->ApplicationCreated failed with error %" PRIu32
"", error);
260static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp,
wStream* s,
264 UINT error = CHANNEL_RC_OK;
265 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
268 return ERROR_INVALID_HANDLE;
270 const size_t pos = Stream_GetPosition(s);
271 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
272 return ERROR_INVALID_DATA;
273 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
275 WINPR_ASSERT(header);
276 pdu.Length = header->Length;
277 pdu.Type = header->Type;
279 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
280 return ERROR_INVALID_DATA;
282 Stream_Read_UINT32(s, pdu.AppId);
283 const size_t end = Stream_GetPosition(s);
284 const size_t body = beg + header->Length;
288 WLog_ERR(TAG,
"Not enough data!");
289 return ERROR_INVALID_DATA;
294 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
295 return ERROR_INVALID_DATA;
297 if (!Stream_SetPosition(s, body))
298 return ERROR_INVALID_DATA;
301 IFCALLRET(context->ApplicationRemoved, error, context, &pdu);
304 WLog_ERR(TAG,
"context->ApplicationRemoved failed with error %" PRIu32
"", error);
314static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp,
wStream* s,
318 UINT error = CHANNEL_RC_OK;
319 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
322 return ERROR_INVALID_HANDLE;
324 const size_t pos = Stream_GetPosition(s);
325 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
326 return ERROR_INVALID_DATA;
327 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
329 WINPR_ASSERT(header);
330 pdu.Length = header->Length;
331 pdu.Type = header->Type;
333 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
334 return ERROR_INVALID_DATA;
336 Stream_Read_UINT16(s, pdu.Flags);
337 Stream_Read_UINT32(s, pdu.AppId);
338 Stream_Read_UINT32(s, pdu.WndId);
340 if ((error = encomsp_read_unicode_string(s, &(pdu.Name))))
342 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
346 const size_t end = Stream_GetPosition(s);
347 const size_t body = beg + header->Length;
351 WLog_ERR(TAG,
"Not enough data!");
352 return ERROR_INVALID_DATA;
357 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
358 return ERROR_INVALID_DATA;
360 if (!Stream_SetPosition(s, body))
361 return ERROR_INVALID_DATA;
364 IFCALLRET(context->WindowCreated, error, context, &pdu);
367 WLog_ERR(TAG,
"context->WindowCreated failed with error %" PRIu32
"", error);
377static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp,
wStream* s,
381 UINT error = CHANNEL_RC_OK;
382 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
385 return ERROR_INVALID_HANDLE;
387 const size_t pos = Stream_GetPosition(s);
388 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
389 return ERROR_INVALID_DATA;
390 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
392 WINPR_ASSERT(header);
393 pdu.Length = header->Length;
394 pdu.Type = header->Type;
396 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
397 return ERROR_INVALID_DATA;
399 Stream_Read_UINT32(s, pdu.WndId);
400 const size_t end = Stream_GetPosition(s);
401 const size_t body = beg + header->Length;
405 WLog_ERR(TAG,
"Not enough data!");
406 return ERROR_INVALID_DATA;
411 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
412 return ERROR_INVALID_DATA;
414 if (!Stream_SetPosition(s, body))
415 return ERROR_INVALID_DATA;
418 IFCALLRET(context->WindowRemoved, error, context, &pdu);
421 WLog_ERR(TAG,
"context->WindowRemoved failed with error %" PRIu32
"", error);
431static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp,
wStream* s,
435 UINT error = CHANNEL_RC_OK;
436 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
439 return ERROR_INVALID_HANDLE;
441 const size_t pos = Stream_GetPosition(s);
442 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
443 return ERROR_INVALID_DATA;
444 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
446 WINPR_ASSERT(header);
447 pdu.Length = header->Length;
448 pdu.Type = header->Type;
450 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
451 return ERROR_INVALID_DATA;
453 Stream_Read_UINT32(s, pdu.WndId);
454 const size_t end = Stream_GetPosition(s);
455 const size_t body = beg + header->Length;
459 WLog_ERR(TAG,
"Not enough data!");
460 return ERROR_INVALID_DATA;
465 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
466 return ERROR_INVALID_DATA;
468 if (!Stream_SetPosition(s, body))
469 return ERROR_INVALID_DATA;
472 IFCALLRET(context->ShowWindow, error, context, &pdu);
475 WLog_ERR(TAG,
"context->ShowWindow failed with error %" PRIu32
"", error);
485static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp,
wStream* s,
489 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
492 return ERROR_INVALID_HANDLE;
494 const size_t pos = Stream_GetPosition(s);
495 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
496 return ERROR_INVALID_DATA;
497 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
499 WINPR_ASSERT(header);
500 pdu.Length = header->Length;
501 pdu.Type = header->Type;
503 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
504 return ERROR_INVALID_DATA;
506 Stream_Read_UINT32(s, pdu.ParticipantId);
507 Stream_Read_UINT32(s, pdu.GroupId);
508 Stream_Read_UINT16(s, pdu.Flags);
510 UINT error = encomsp_read_unicode_string(s, &(pdu.FriendlyName));
511 if (error != CHANNEL_RC_OK)
513 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
517 const size_t end = Stream_GetPosition(s);
518 const size_t body = beg + header->Length;
522 WLog_ERR(TAG,
"Not enough data!");
523 return ERROR_INVALID_DATA;
528 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
529 return ERROR_INVALID_DATA;
531 if (!Stream_SetPosition(s, body))
532 return ERROR_INVALID_DATA;
535 IFCALLRET(context->ParticipantCreated, error, context, &pdu);
538 WLog_ERR(TAG,
"context->ParticipantCreated failed with error %" PRIu32
"", error);
548static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp,
wStream* s,
552 UINT error = CHANNEL_RC_OK;
553 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
556 return ERROR_INVALID_HANDLE;
558 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
559 return ERROR_INVALID_DATA;
561 const size_t beg = (Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
563 WINPR_ASSERT(header);
564 pdu.Length = header->Length;
565 pdu.Type = header->Type;
567 Stream_Read_UINT32(s, pdu.ParticipantId);
568 Stream_Read_UINT32(s, pdu.DiscType);
569 Stream_Read_UINT32(s, pdu.DiscCode);
570 const size_t end = Stream_GetPosition(s);
571 const size_t body = beg + header->Length;
575 WLog_ERR(TAG,
"Not enough data!");
576 return ERROR_INVALID_DATA;
581 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
582 return ERROR_INVALID_DATA;
584 if (!Stream_SetPosition(s, body))
585 return ERROR_INVALID_DATA;
588 IFCALLRET(context->ParticipantRemoved, error, context, &pdu);
591 WLog_ERR(TAG,
"context->ParticipantRemoved failed with error %" PRIu32
"", error);
601static UINT encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp,
wStream* s,
605 UINT error = CHANNEL_RC_OK;
606 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
609 return ERROR_INVALID_HANDLE;
611 const size_t pos = Stream_GetPosition(s);
612 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
613 return ERROR_INVALID_DATA;
614 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
616 WINPR_ASSERT(header);
617 pdu.Length = header->Length;
618 pdu.Type = header->Type;
620 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
621 return ERROR_INVALID_DATA;
623 Stream_Read_UINT16(s, pdu.Flags);
624 Stream_Read_UINT32(s, pdu.ParticipantId);
625 const size_t end = Stream_GetPosition(s);
626 const size_t body = beg + header->Length;
630 WLog_ERR(TAG,
"Not enough data!");
631 return ERROR_INVALID_DATA;
636 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
637 return ERROR_INVALID_DATA;
639 if (!Stream_SetPosition(s, body))
640 return ERROR_INVALID_DATA;
643 IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu);
646 WLog_ERR(TAG,
"context->ChangeParticipantControlLevel failed with error %" PRIu32
"",
657static UINT encomsp_send_change_participant_control_level_pdu(
662 WINPR_ASSERT(context);
663 encomspPlugin* encomsp = (encomspPlugin*)context->handle;
665 header.Type = ODTYPE_PARTICIPANT_CTRL_CHANGED;
666 header.Length = ENCOMSP_ORDER_HEADER_SIZE + 6;
668 wStream* s = Stream_New(
nullptr, header.Length);
672 WLog_ERR(TAG,
"Stream_New failed!");
673 return CHANNEL_RC_NO_MEMORY;
676 const UINT error = encomsp_write_header(s, &header);
677 if (error != CHANNEL_RC_OK)
679 WLog_ERR(TAG,
"encomsp_write_header failed with error %" PRIu32
"!", error);
683 Stream_Write_UINT16(s, pdu->Flags);
684 Stream_Write_UINT32(s, pdu->ParticipantId);
685 Stream_SealLength(s);
686 return encomsp_virtual_channel_write(encomsp, s);
694static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp,
wStream* s,
698 UINT error = CHANNEL_RC_OK;
699 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
702 return ERROR_INVALID_HANDLE;
704 const size_t pos = Stream_GetPosition(s);
705 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
706 return ERROR_INVALID_DATA;
707 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
709 WINPR_ASSERT(header);
710 pdu.Length = header->Length;
711 pdu.Type = header->Type;
713 const size_t end = Stream_GetPosition(s);
714 const size_t body = beg + header->Length;
718 WLog_ERR(TAG,
"Not enough data!");
719 return ERROR_INVALID_DATA;
724 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
725 return ERROR_INVALID_DATA;
727 if (!Stream_SetPosition(s, body))
728 return ERROR_INVALID_DATA;
731 IFCALLRET(context->GraphicsStreamPaused, error, context, &pdu);
734 WLog_ERR(TAG,
"context->GraphicsStreamPaused failed with error %" PRIu32
"", error);
744static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp,
wStream* s,
748 UINT error = CHANNEL_RC_OK;
749 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
752 return ERROR_INVALID_HANDLE;
754 const size_t pos = Stream_GetPosition(s);
755 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
756 return ERROR_INVALID_DATA;
757 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
759 WINPR_ASSERT(header);
760 pdu.Length = header->Length;
761 pdu.Type = header->Type;
763 const size_t end = Stream_GetPosition(s);
764 const size_t body = beg + header->Length;
768 WLog_ERR(TAG,
"Not enough data!");
769 return ERROR_INVALID_DATA;
774 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
775 return ERROR_INVALID_DATA;
777 if (!Stream_SetPosition(s, body))
778 return ERROR_INVALID_DATA;
781 IFCALLRET(context->GraphicsStreamResumed, error, context, &pdu);
784 WLog_ERR(TAG,
"context->GraphicsStreamResumed failed with error %" PRIu32
"", error);
794static UINT encomsp_process_receive(encomspPlugin* encomsp,
wStream* s)
796 UINT error = CHANNEL_RC_OK;
799 WINPR_ASSERT(encomsp);
800 while (Stream_GetRemainingLength(s) > 0)
802 if ((error = encomsp_read_header(s, &header)))
804 WLog_ERR(TAG,
"encomsp_read_header failed with error %" PRIu32
"!", error);
813 case ODTYPE_FILTER_STATE_UPDATED:
814 if ((error = encomsp_recv_filter_updated_pdu(encomsp, s, &header)))
816 WLog_ERR(TAG,
"encomsp_recv_filter_updated_pdu failed with error %" PRIu32
"!",
823 case ODTYPE_APP_REMOVED:
824 if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header)))
827 "encomsp_recv_application_removed_pdu failed with error %" PRIu32
"!",
834 case ODTYPE_APP_CREATED:
835 if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header)))
838 "encomsp_recv_application_removed_pdu failed with error %" PRIu32
"!",
845 case ODTYPE_WND_REMOVED:
846 if ((error = encomsp_recv_window_removed_pdu(encomsp, s, &header)))
848 WLog_ERR(TAG,
"encomsp_recv_window_removed_pdu failed with error %" PRIu32
"!",
855 case ODTYPE_WND_CREATED:
856 if ((error = encomsp_recv_window_created_pdu(encomsp, s, &header)))
858 WLog_ERR(TAG,
"encomsp_recv_window_created_pdu failed with error %" PRIu32
"!",
865 case ODTYPE_WND_SHOW:
866 if ((error = encomsp_recv_show_window_pdu(encomsp, s, &header)))
868 WLog_ERR(TAG,
"encomsp_recv_show_window_pdu failed with error %" PRIu32
"!",
875 case ODTYPE_PARTICIPANT_REMOVED:
876 if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header)))
879 "encomsp_recv_participant_removed_pdu failed with error %" PRIu32
"!",
886 case ODTYPE_PARTICIPANT_CREATED:
887 if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header)))
890 "encomsp_recv_participant_created_pdu failed with error %" PRIu32
"!",
897 case ODTYPE_PARTICIPANT_CTRL_CHANGED:
899 encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header)))
902 "encomsp_recv_change_participant_control_level_pdu failed with error "
910 case ODTYPE_GRAPHICS_STREAM_PAUSED:
911 if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header)))
914 "encomsp_recv_graphics_stream_paused_pdu failed with error %" PRIu32
922 case ODTYPE_GRAPHICS_STREAM_RESUMED:
923 if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header)))
926 "encomsp_recv_graphics_stream_resumed_pdu failed with error %" PRIu32
935 WLog_ERR(TAG,
"header.Type %" PRIu16
" not found", header.Type);
936 return ERROR_INVALID_DATA;
948static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
const void* pData,
949 UINT32 dataLength, UINT32 totalLength,
952 WINPR_ASSERT(encomsp);
954 if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
955 return CHANNEL_RC_OK;
957 if (dataFlags & CHANNEL_FLAG_FIRST)
959 if (encomsp->firstFlagReceived)
960 return ERROR_INVALID_DATA;
961 encomsp->firstFlagReceived = TRUE;
962 if (encomsp->data_in)
963 Stream_Free(encomsp->data_in, TRUE);
965 encomsp->data_in = Stream_New(
nullptr, dataLength);
967 if (!encomsp->data_in)
969 WLog_ERR(TAG,
"Stream_New failed!");
970 return CHANNEL_RC_NO_MEMORY;
972 encomsp->totalLength = totalLength;
975 wStream* data_in = encomsp->data_in;
977 return ERROR_INVALID_DATA;
979 if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
981 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
982 return ERROR_INTERNAL_ERROR;
985 Stream_Write(data_in, pData, dataLength);
987 if ((Stream_GetPosition(data_in) > totalLength) || (encomsp->totalLength != totalLength))
988 return ERROR_INVALID_DATA;
990 if (dataFlags & CHANNEL_FLAG_LAST)
992 if (!encomsp->firstFlagReceived)
993 return ERROR_INVALID_DATA;
994 encomsp->firstFlagReceived = FALSE;
996 if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
998 WLog_ERR(TAG,
"encomsp_plugin_process_received: read error");
999 return ERROR_INVALID_DATA;
1002 encomsp->totalLength = 0;
1003 encomsp->data_in =
nullptr;
1004 Stream_SealLength(data_in);
1005 Stream_ResetPosition(data_in);
1007 if (!MessageQueue_Post(encomsp->queue,
nullptr, 0, (
void*)data_in,
nullptr))
1009 WLog_ERR(TAG,
"MessageQueue_Post failed!");
1010 return ERROR_INTERNAL_ERROR;
1014 return CHANNEL_RC_OK;
1017static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
1018 UINT event, LPVOID pData,
1019 UINT32 dataLength, UINT32 totalLength,
1022 UINT error = CHANNEL_RC_OK;
1023 encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1027 case CHANNEL_EVENT_DATA_RECEIVED:
1028 if (!encomsp || (encomsp->OpenHandle != openHandle))
1030 WLog_ERR(TAG,
"error no match");
1033 if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength,
1034 totalLength, dataFlags)))
1036 "encomsp_virtual_channel_event_data_received failed with error %" PRIu32
1042 case CHANNEL_EVENT_WRITE_CANCELLED:
1043 case CHANNEL_EVENT_WRITE_COMPLETE:
1046 Stream_Free(s, TRUE);
1050 case CHANNEL_EVENT_USER:
1056 if (error && encomsp && encomsp->rdpcontext)
1057 setChannelError(encomsp->rdpcontext, error,
1058 "encomsp_virtual_channel_open_event reported an error");
1061static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg)
1064 wMessage message = WINPR_C_ARRAY_INIT;
1065 encomspPlugin* encomsp = (encomspPlugin*)arg;
1066 UINT error = CHANNEL_RC_OK;
1068 WINPR_ASSERT(encomsp);
1071 if (!MessageQueue_Wait(encomsp->queue))
1073 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
1074 error = ERROR_INTERNAL_ERROR;
1078 if (!MessageQueue_Peek(encomsp->queue, &message, TRUE))
1080 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
1081 error = ERROR_INTERNAL_ERROR;
1085 if (message.id == WMQ_QUIT)
1088 if (message.id == 0)
1090 data = (
wStream*)message.wParam;
1092 if ((error = encomsp_process_receive(encomsp, data)))
1094 WLog_ERR(TAG,
"encomsp_process_receive failed with error %" PRIu32
"!", error);
1095 Stream_Free(data, TRUE);
1099 Stream_Free(data, TRUE);
1103 if (error && encomsp->rdpcontext)
1104 setChannelError(encomsp->rdpcontext, error,
1105 "encomsp_virtual_channel_client_thread reported an error");
1116static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
1117 WINPR_ATTR_UNUSED LPVOID pData,
1118 WINPR_ATTR_UNUSED UINT32 dataLength)
1120 WINPR_ASSERT(encomsp);
1122 encomsp->queue = MessageQueue_New(
nullptr);
1124 if (!encomsp->queue)
1126 WLog_ERR(TAG,
"MessageQueue_New failed!");
1127 return CHANNEL_RC_NO_MEMORY;
1130 if (!(encomsp->thread = CreateThread(
nullptr, 0, encomsp_virtual_channel_client_thread,
1131 (
void*)encomsp, 0,
nullptr)))
1133 WLog_ERR(TAG,
"CreateThread failed!");
1134 MessageQueue_Free(encomsp->queue);
1135 return ERROR_INTERNAL_ERROR;
1138 return encomsp->channelEntryPoints.pVirtualChannelOpenEx(
1139 encomsp->InitHandle, &encomsp->OpenHandle, encomsp->channelDef.name,
1140 encomsp_virtual_channel_open_event_ex);
1148static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
1150 WINPR_ASSERT(encomsp);
1151 if (encomsp->OpenHandle == 0)
1152 return CHANNEL_RC_OK;
1154 if (encomsp->queue && encomsp->thread)
1156 if (MessageQueue_PostQuit(encomsp->queue, 0) &&
1157 (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED))
1159 const UINT rc = GetLastError();
1160 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", rc);
1165 MessageQueue_Free(encomsp->queue);
1166 (void)CloseHandle(encomsp->thread);
1167 encomsp->queue =
nullptr;
1168 encomsp->thread =
nullptr;
1170 WINPR_ASSERT(encomsp->channelEntryPoints.pVirtualChannelCloseEx);
1171 const UINT rc = encomsp->channelEntryPoints.pVirtualChannelCloseEx(encomsp->InitHandle,
1172 encomsp->OpenHandle);
1174 if (CHANNEL_RC_OK != rc)
1176 WLog_ERR(TAG,
"pVirtualChannelClose failed with %s [%08" PRIX32
"]", WTSErrorToString(rc),
1181 encomsp->OpenHandle = 0;
1183 if (encomsp->data_in)
1185 Stream_Free(encomsp->data_in, TRUE);
1186 encomsp->data_in =
nullptr;
1189 return CHANNEL_RC_OK;
1197static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
1199 WINPR_ASSERT(encomsp);
1201 encomsp->InitHandle =
nullptr;
1202 free(encomsp->context);
1204 return CHANNEL_RC_OK;
1207static VOID VCAPITYPE encomsp_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
1208 UINT event, LPVOID pData,
1211 UINT error = CHANNEL_RC_OK;
1212 encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1214 if (!encomsp || (encomsp->InitHandle != pInitHandle))
1216 WLog_ERR(TAG,
"error no match");
1222 case CHANNEL_EVENT_INITIALIZED:
1225 case CHANNEL_EVENT_CONNECTED:
1226 if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength)))
1228 "encomsp_virtual_channel_event_connected failed with error %" PRIu32
"",
1233 case CHANNEL_EVENT_DISCONNECTED:
1234 if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
1236 "encomsp_virtual_channel_event_disconnected failed with error %" PRIu32
"",
1241 case CHANNEL_EVENT_TERMINATED:
1242 encomsp_virtual_channel_event_terminated(encomsp);
1249 if (error && encomsp->rdpcontext)
1250 setChannelError(encomsp->rdpcontext, error,
1251 "encomsp_virtual_channel_init_event reported an error");
1255#define VirtualChannelEntryEx encomsp_VirtualChannelEntryEx
1257FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints,
1260 BOOL isFreerdp = FALSE;
1261 encomspPlugin* encomsp = (encomspPlugin*)calloc(1,
sizeof(encomspPlugin));
1265 WLog_ERR(TAG,
"calloc failed!");
1269 encomsp->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
1270 CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
1271 (void)sprintf_s(encomsp->channelDef.name, ARRAYSIZE(encomsp->channelDef.name),
1272 ENCOMSP_SVC_CHANNEL_NAME);
1275 WINPR_ASSERT(pEntryPointsEx);
1277 EncomspClientContext* context =
nullptr;
1279 (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
1281 context = (EncomspClientContext*)calloc(1,
sizeof(EncomspClientContext));
1285 WLog_ERR(TAG,
"calloc failed!");
1289 context->handle = (
void*)encomsp;
1290 context->FilterUpdated =
nullptr;
1291 context->ApplicationCreated =
nullptr;
1292 context->ApplicationRemoved =
nullptr;
1293 context->WindowCreated =
nullptr;
1294 context->WindowRemoved =
nullptr;
1295 context->ShowWindow =
nullptr;
1296 context->ParticipantCreated =
nullptr;
1297 context->ParticipantRemoved =
nullptr;
1298 context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu;
1299 context->GraphicsStreamPaused =
nullptr;
1300 context->GraphicsStreamResumed =
nullptr;
1301 encomsp->context = context;
1302 encomsp->rdpcontext = pEntryPointsEx->context;
1306 CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints,
1308 encomsp->InitHandle = pInitHandle;
1311 const UINT rc = encomsp->channelEntryPoints.pVirtualChannelInitEx(
1312 encomsp, context, pInitHandle, &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
1313 encomsp_virtual_channel_init_event_ex);
1315 if (CHANNEL_RC_OK != rc)
1317 WLog_ERR(TAG,
"failed with %s [%08" PRIX32
"]", WTSErrorToString(rc), rc);
1322 encomsp->channelEntryPoints.pInterface = context;
1327 free(encomsp->context);