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;
57 if (!Stream_CheckAndLogRequiredLength(TAG, s, ENCOMSP_ORDER_HEADER_SIZE))
58 return ERROR_INVALID_DATA;
60 Stream_Read_UINT16(s, header->Type);
61 Stream_Read_UINT16(s, header->Length);
73 Stream_Write_UINT16(s, header->Type);
74 Stream_Write_UINT16(s, header->Length);
89 if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
90 return ERROR_INVALID_DATA;
92 Stream_Read_UINT16(s, str->cchString);
94 if (str->cchString > 1024)
96 WLog_ERR(TAG,
"cchString was %" PRIu16
" but has to be < 1025!", str->cchString);
97 return ERROR_INVALID_DATA;
100 if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, str->cchString,
sizeof(WCHAR)))
101 return ERROR_INVALID_DATA;
103 Stream_Read(s, &(str->wString), (
sizeof(WCHAR) * str->cchString));
104 return CHANNEL_RC_OK;
107static EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp)
109 WINPR_ASSERT(encomsp);
110 return (EncomspClientContext*)encomsp->channelEntryPoints.pInterface;
118static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp,
wStream* s)
122 Stream_Free(s, TRUE);
123 return ERROR_INVALID_HANDLE;
126 const UINT status = encomsp->channelEntryPoints.pVirtualChannelWriteEx(
127 encomsp->InitHandle, encomsp->OpenHandle, Stream_Buffer(s), (UINT32)Stream_Length(s), s);
129 if (status != CHANNEL_RC_OK)
131 Stream_Free(s, TRUE);
132 WLog_ERR(TAG,
"VirtualChannelWriteEx failed with %s [%08" PRIX32
"]",
133 WTSErrorToString(status), status);
143static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp,
wStream* s,
147 UINT error = CHANNEL_RC_OK;
148 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
151 return ERROR_INVALID_HANDLE;
153 WINPR_ASSERT(header);
154 const size_t pos = Stream_GetPosition(s);
155 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
156 return ERROR_INVALID_DATA;
157 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
158 pdu.Length = header->Length;
159 pdu.Type = header->Type;
161 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
162 return ERROR_INVALID_DATA;
164 Stream_Read_UINT8(s, pdu.Flags);
165 const size_t end = Stream_GetPosition(s);
166 const size_t body = beg + header->Length;
170 WLog_ERR(TAG,
"Not enough data!");
171 return ERROR_INVALID_DATA;
176 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
177 return ERROR_INVALID_DATA;
179 if (!Stream_SetPosition(s, body))
180 return ERROR_INVALID_DATA;
183 IFCALLRET(context->FilterUpdated, error, context, &pdu);
186 WLog_ERR(TAG,
"context->FilterUpdated failed with error %" PRIu32
"", error);
196static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp,
wStream* s,
200 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
203 return ERROR_INVALID_HANDLE;
205 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
206 return ERROR_INVALID_DATA;
208 const size_t pos = Stream_GetPosition(s);
209 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
210 return ERROR_INVALID_DATA;
211 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
213 WINPR_ASSERT(header);
214 pdu.Length = header->Length;
215 pdu.Type = header->Type;
217 Stream_Read_UINT16(s, pdu.Flags);
218 Stream_Read_UINT32(s, pdu.AppId);
220 UINT error = encomsp_read_unicode_string(s, &(pdu.Name));
221 if (error != CHANNEL_RC_OK)
223 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
227 const size_t end = Stream_GetPosition(s);
228 const size_t body = beg + header->Length;
232 WLog_ERR(TAG,
"Not enough data!");
233 return ERROR_INVALID_DATA;
238 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
239 return ERROR_INVALID_DATA;
241 if (!Stream_SetPosition(s, body))
242 return ERROR_INVALID_DATA;
245 IFCALLRET(context->ApplicationCreated, error, context, &pdu);
248 WLog_ERR(TAG,
"context->ApplicationCreated failed with error %" PRIu32
"", error);
258static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp,
wStream* s,
262 UINT error = CHANNEL_RC_OK;
263 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
266 return ERROR_INVALID_HANDLE;
268 const size_t pos = Stream_GetPosition(s);
269 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
270 return ERROR_INVALID_DATA;
271 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
273 WINPR_ASSERT(header);
274 pdu.Length = header->Length;
275 pdu.Type = header->Type;
277 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
278 return ERROR_INVALID_DATA;
280 Stream_Read_UINT32(s, pdu.AppId);
281 const size_t end = Stream_GetPosition(s);
282 const size_t body = beg + header->Length;
286 WLog_ERR(TAG,
"Not enough data!");
287 return ERROR_INVALID_DATA;
292 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
293 return ERROR_INVALID_DATA;
295 if (!Stream_SetPosition(s, body))
296 return ERROR_INVALID_DATA;
299 IFCALLRET(context->ApplicationRemoved, error, context, &pdu);
302 WLog_ERR(TAG,
"context->ApplicationRemoved failed with error %" PRIu32
"", error);
312static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp,
wStream* s,
316 UINT error = CHANNEL_RC_OK;
317 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
320 return ERROR_INVALID_HANDLE;
322 const size_t pos = Stream_GetPosition(s);
323 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
324 return ERROR_INVALID_DATA;
325 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
327 WINPR_ASSERT(header);
328 pdu.Length = header->Length;
329 pdu.Type = header->Type;
331 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
332 return ERROR_INVALID_DATA;
334 Stream_Read_UINT16(s, pdu.Flags);
335 Stream_Read_UINT32(s, pdu.AppId);
336 Stream_Read_UINT32(s, pdu.WndId);
338 if ((error = encomsp_read_unicode_string(s, &(pdu.Name))))
340 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
344 const size_t end = Stream_GetPosition(s);
345 const size_t body = beg + header->Length;
349 WLog_ERR(TAG,
"Not enough data!");
350 return ERROR_INVALID_DATA;
355 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
356 return ERROR_INVALID_DATA;
358 if (!Stream_SetPosition(s, body))
359 return ERROR_INVALID_DATA;
362 IFCALLRET(context->WindowCreated, error, context, &pdu);
365 WLog_ERR(TAG,
"context->WindowCreated failed with error %" PRIu32
"", error);
375static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp,
wStream* s,
379 UINT error = CHANNEL_RC_OK;
380 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
383 return ERROR_INVALID_HANDLE;
385 const size_t pos = Stream_GetPosition(s);
386 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
387 return ERROR_INVALID_DATA;
388 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
390 WINPR_ASSERT(header);
391 pdu.Length = header->Length;
392 pdu.Type = header->Type;
394 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
395 return ERROR_INVALID_DATA;
397 Stream_Read_UINT32(s, pdu.WndId);
398 const size_t end = Stream_GetPosition(s);
399 const size_t body = beg + header->Length;
403 WLog_ERR(TAG,
"Not enough data!");
404 return ERROR_INVALID_DATA;
409 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
410 return ERROR_INVALID_DATA;
412 if (!Stream_SetPosition(s, body))
413 return ERROR_INVALID_DATA;
416 IFCALLRET(context->WindowRemoved, error, context, &pdu);
419 WLog_ERR(TAG,
"context->WindowRemoved failed with error %" PRIu32
"", error);
429static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp,
wStream* s,
433 UINT error = CHANNEL_RC_OK;
434 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
437 return ERROR_INVALID_HANDLE;
439 const size_t pos = Stream_GetPosition(s);
440 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
441 return ERROR_INVALID_DATA;
442 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
444 WINPR_ASSERT(header);
445 pdu.Length = header->Length;
446 pdu.Type = header->Type;
448 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
449 return ERROR_INVALID_DATA;
451 Stream_Read_UINT32(s, pdu.WndId);
452 const size_t end = Stream_GetPosition(s);
453 const size_t body = beg + header->Length;
457 WLog_ERR(TAG,
"Not enough data!");
458 return ERROR_INVALID_DATA;
463 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
464 return ERROR_INVALID_DATA;
466 if (!Stream_SetPosition(s, body))
467 return ERROR_INVALID_DATA;
470 IFCALLRET(context->ShowWindow, error, context, &pdu);
473 WLog_ERR(TAG,
"context->ShowWindow failed with error %" PRIu32
"", error);
483static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp,
wStream* s,
487 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
490 return ERROR_INVALID_HANDLE;
492 const size_t pos = Stream_GetPosition(s);
493 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
494 return ERROR_INVALID_DATA;
495 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
497 WINPR_ASSERT(header);
498 pdu.Length = header->Length;
499 pdu.Type = header->Type;
501 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
502 return ERROR_INVALID_DATA;
504 Stream_Read_UINT32(s, pdu.ParticipantId);
505 Stream_Read_UINT32(s, pdu.GroupId);
506 Stream_Read_UINT16(s, pdu.Flags);
508 UINT error = encomsp_read_unicode_string(s, &(pdu.FriendlyName));
509 if (error != CHANNEL_RC_OK)
511 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
515 const size_t end = Stream_GetPosition(s);
516 const size_t body = beg + header->Length;
520 WLog_ERR(TAG,
"Not enough data!");
521 return ERROR_INVALID_DATA;
526 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
527 return ERROR_INVALID_DATA;
529 if (!Stream_SetPosition(s, body))
530 return ERROR_INVALID_DATA;
533 IFCALLRET(context->ParticipantCreated, error, context, &pdu);
536 WLog_ERR(TAG,
"context->ParticipantCreated failed with error %" PRIu32
"", error);
546static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp,
wStream* s,
550 UINT error = CHANNEL_RC_OK;
551 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
554 return ERROR_INVALID_HANDLE;
556 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
557 return ERROR_INVALID_DATA;
559 const size_t beg = (Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
561 WINPR_ASSERT(header);
562 pdu.Length = header->Length;
563 pdu.Type = header->Type;
565 Stream_Read_UINT32(s, pdu.ParticipantId);
566 Stream_Read_UINT32(s, pdu.DiscType);
567 Stream_Read_UINT32(s, pdu.DiscCode);
568 const size_t end = Stream_GetPosition(s);
569 const size_t body = beg + header->Length;
573 WLog_ERR(TAG,
"Not enough data!");
574 return ERROR_INVALID_DATA;
579 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
580 return ERROR_INVALID_DATA;
582 if (!Stream_SetPosition(s, body))
583 return ERROR_INVALID_DATA;
586 IFCALLRET(context->ParticipantRemoved, error, context, &pdu);
589 WLog_ERR(TAG,
"context->ParticipantRemoved failed with error %" PRIu32
"", error);
599static UINT encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp,
wStream* s,
603 UINT error = CHANNEL_RC_OK;
604 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
607 return ERROR_INVALID_HANDLE;
609 const size_t pos = Stream_GetPosition(s);
610 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
611 return ERROR_INVALID_DATA;
612 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
614 WINPR_ASSERT(header);
615 pdu.Length = header->Length;
616 pdu.Type = header->Type;
618 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
619 return ERROR_INVALID_DATA;
621 Stream_Read_UINT16(s, pdu.Flags);
622 Stream_Read_UINT32(s, pdu.ParticipantId);
623 const size_t end = Stream_GetPosition(s);
624 const size_t body = beg + header->Length;
628 WLog_ERR(TAG,
"Not enough data!");
629 return ERROR_INVALID_DATA;
634 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
635 return ERROR_INVALID_DATA;
637 if (!Stream_SetPosition(s, body))
638 return ERROR_INVALID_DATA;
641 IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu);
644 WLog_ERR(TAG,
"context->ChangeParticipantControlLevel failed with error %" PRIu32
"",
655static UINT encomsp_send_change_participant_control_level_pdu(
660 WINPR_ASSERT(context);
661 encomspPlugin* encomsp = (encomspPlugin*)context->handle;
663 header.Type = ODTYPE_PARTICIPANT_CTRL_CHANGED;
664 header.Length = ENCOMSP_ORDER_HEADER_SIZE + 6;
666 wStream* s = Stream_New(
nullptr, header.Length);
670 WLog_ERR(TAG,
"Stream_New failed!");
671 return CHANNEL_RC_NO_MEMORY;
674 const UINT error = encomsp_write_header(s, &header);
675 if (error != CHANNEL_RC_OK)
677 WLog_ERR(TAG,
"encomsp_write_header failed with error %" PRIu32
"!", error);
681 Stream_Write_UINT16(s, pdu->Flags);
682 Stream_Write_UINT32(s, pdu->ParticipantId);
683 Stream_SealLength(s);
684 return encomsp_virtual_channel_write(encomsp, s);
692static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp,
wStream* s,
696 UINT error = CHANNEL_RC_OK;
697 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
700 return ERROR_INVALID_HANDLE;
702 const size_t pos = Stream_GetPosition(s);
703 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
704 return ERROR_INVALID_DATA;
705 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
707 WINPR_ASSERT(header);
708 pdu.Length = header->Length;
709 pdu.Type = header->Type;
711 const size_t end = Stream_GetPosition(s);
712 const size_t body = beg + header->Length;
716 WLog_ERR(TAG,
"Not enough data!");
717 return ERROR_INVALID_DATA;
722 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
723 return ERROR_INVALID_DATA;
725 if (!Stream_SetPosition(s, body))
726 return ERROR_INVALID_DATA;
729 IFCALLRET(context->GraphicsStreamPaused, error, context, &pdu);
732 WLog_ERR(TAG,
"context->GraphicsStreamPaused failed with error %" PRIu32
"", error);
742static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp,
wStream* s,
746 UINT error = CHANNEL_RC_OK;
747 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
750 return ERROR_INVALID_HANDLE;
752 const size_t pos = Stream_GetPosition(s);
753 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
754 return ERROR_INVALID_DATA;
755 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
757 WINPR_ASSERT(header);
758 pdu.Length = header->Length;
759 pdu.Type = header->Type;
761 const size_t end = Stream_GetPosition(s);
762 const size_t body = beg + header->Length;
766 WLog_ERR(TAG,
"Not enough data!");
767 return ERROR_INVALID_DATA;
772 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
773 return ERROR_INVALID_DATA;
775 if (!Stream_SetPosition(s, body))
776 return ERROR_INVALID_DATA;
779 IFCALLRET(context->GraphicsStreamResumed, error, context, &pdu);
782 WLog_ERR(TAG,
"context->GraphicsStreamResumed failed with error %" PRIu32
"", error);
792static UINT encomsp_process_receive(encomspPlugin* encomsp,
wStream* s)
794 UINT error = CHANNEL_RC_OK;
797 WINPR_ASSERT(encomsp);
798 while (Stream_GetRemainingLength(s) > 0)
800 if ((error = encomsp_read_header(s, &header)))
802 WLog_ERR(TAG,
"encomsp_read_header failed with error %" PRIu32
"!", error);
811 case ODTYPE_FILTER_STATE_UPDATED:
812 if ((error = encomsp_recv_filter_updated_pdu(encomsp, s, &header)))
814 WLog_ERR(TAG,
"encomsp_recv_filter_updated_pdu failed with error %" PRIu32
"!",
821 case ODTYPE_APP_REMOVED:
822 if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header)))
825 "encomsp_recv_application_removed_pdu failed with error %" PRIu32
"!",
832 case ODTYPE_APP_CREATED:
833 if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header)))
836 "encomsp_recv_application_removed_pdu failed with error %" PRIu32
"!",
843 case ODTYPE_WND_REMOVED:
844 if ((error = encomsp_recv_window_removed_pdu(encomsp, s, &header)))
846 WLog_ERR(TAG,
"encomsp_recv_window_removed_pdu failed with error %" PRIu32
"!",
853 case ODTYPE_WND_CREATED:
854 if ((error = encomsp_recv_window_created_pdu(encomsp, s, &header)))
856 WLog_ERR(TAG,
"encomsp_recv_window_created_pdu failed with error %" PRIu32
"!",
863 case ODTYPE_WND_SHOW:
864 if ((error = encomsp_recv_show_window_pdu(encomsp, s, &header)))
866 WLog_ERR(TAG,
"encomsp_recv_show_window_pdu failed with error %" PRIu32
"!",
873 case ODTYPE_PARTICIPANT_REMOVED:
874 if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header)))
877 "encomsp_recv_participant_removed_pdu failed with error %" PRIu32
"!",
884 case ODTYPE_PARTICIPANT_CREATED:
885 if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header)))
888 "encomsp_recv_participant_created_pdu failed with error %" PRIu32
"!",
895 case ODTYPE_PARTICIPANT_CTRL_CHANGED:
897 encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header)))
900 "encomsp_recv_change_participant_control_level_pdu failed with error "
908 case ODTYPE_GRAPHICS_STREAM_PAUSED:
909 if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header)))
912 "encomsp_recv_graphics_stream_paused_pdu failed with error %" PRIu32
920 case ODTYPE_GRAPHICS_STREAM_RESUMED:
921 if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header)))
924 "encomsp_recv_graphics_stream_resumed_pdu failed with error %" PRIu32
933 WLog_ERR(TAG,
"header.Type %" PRIu16
" not found", header.Type);
934 return ERROR_INVALID_DATA;
946static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
const void* pData,
947 UINT32 dataLength, UINT32 totalLength,
950 WINPR_ASSERT(encomsp);
952 if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
953 return CHANNEL_RC_OK;
955 if (dataFlags & CHANNEL_FLAG_FIRST)
957 if (encomsp->data_in)
958 Stream_Free(encomsp->data_in, TRUE);
960 encomsp->data_in = Stream_New(
nullptr, totalLength);
962 if (!encomsp->data_in)
964 WLog_ERR(TAG,
"Stream_New failed!");
965 return CHANNEL_RC_NO_MEMORY;
969 wStream* data_in = encomsp->data_in;
971 if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
973 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
974 return ERROR_INTERNAL_ERROR;
977 Stream_Write(data_in, pData, dataLength);
979 if (dataFlags & CHANNEL_FLAG_LAST)
981 if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
983 WLog_ERR(TAG,
"encomsp_plugin_process_received: read error");
984 return ERROR_INVALID_DATA;
987 encomsp->data_in =
nullptr;
988 Stream_SealLength(data_in);
989 Stream_ResetPosition(data_in);
991 if (!MessageQueue_Post(encomsp->queue,
nullptr, 0, (
void*)data_in,
nullptr))
993 WLog_ERR(TAG,
"MessageQueue_Post failed!");
994 return ERROR_INTERNAL_ERROR;
998 return CHANNEL_RC_OK;
1001static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
1002 UINT event, LPVOID pData,
1003 UINT32 dataLength, UINT32 totalLength,
1006 UINT error = CHANNEL_RC_OK;
1007 encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1011 case CHANNEL_EVENT_DATA_RECEIVED:
1012 if (!encomsp || (encomsp->OpenHandle != openHandle))
1014 WLog_ERR(TAG,
"error no match");
1017 if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength,
1018 totalLength, dataFlags)))
1020 "encomsp_virtual_channel_event_data_received failed with error %" PRIu32
1026 case CHANNEL_EVENT_WRITE_CANCELLED:
1027 case CHANNEL_EVENT_WRITE_COMPLETE:
1030 Stream_Free(s, TRUE);
1034 case CHANNEL_EVENT_USER:
1040 if (error && encomsp && encomsp->rdpcontext)
1041 setChannelError(encomsp->rdpcontext, error,
1042 "encomsp_virtual_channel_open_event reported an error");
1045static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg)
1048 wMessage message = WINPR_C_ARRAY_INIT;
1049 encomspPlugin* encomsp = (encomspPlugin*)arg;
1050 UINT error = CHANNEL_RC_OK;
1052 WINPR_ASSERT(encomsp);
1055 if (!MessageQueue_Wait(encomsp->queue))
1057 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
1058 error = ERROR_INTERNAL_ERROR;
1062 if (!MessageQueue_Peek(encomsp->queue, &message, TRUE))
1064 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
1065 error = ERROR_INTERNAL_ERROR;
1069 if (message.id == WMQ_QUIT)
1072 if (message.id == 0)
1074 data = (
wStream*)message.wParam;
1076 if ((error = encomsp_process_receive(encomsp, data)))
1078 WLog_ERR(TAG,
"encomsp_process_receive failed with error %" PRIu32
"!", error);
1079 Stream_Free(data, TRUE);
1083 Stream_Free(data, TRUE);
1087 if (error && encomsp->rdpcontext)
1088 setChannelError(encomsp->rdpcontext, error,
1089 "encomsp_virtual_channel_client_thread reported an error");
1100static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
1101 WINPR_ATTR_UNUSED LPVOID pData,
1102 WINPR_ATTR_UNUSED UINT32 dataLength)
1104 WINPR_ASSERT(encomsp);
1106 encomsp->queue = MessageQueue_New(
nullptr);
1108 if (!encomsp->queue)
1110 WLog_ERR(TAG,
"MessageQueue_New failed!");
1111 return CHANNEL_RC_NO_MEMORY;
1114 if (!(encomsp->thread = CreateThread(
nullptr, 0, encomsp_virtual_channel_client_thread,
1115 (
void*)encomsp, 0,
nullptr)))
1117 WLog_ERR(TAG,
"CreateThread failed!");
1118 MessageQueue_Free(encomsp->queue);
1119 return ERROR_INTERNAL_ERROR;
1122 return encomsp->channelEntryPoints.pVirtualChannelOpenEx(
1123 encomsp->InitHandle, &encomsp->OpenHandle, encomsp->channelDef.name,
1124 encomsp_virtual_channel_open_event_ex);
1132static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
1134 WINPR_ASSERT(encomsp);
1135 if (encomsp->OpenHandle == 0)
1136 return CHANNEL_RC_OK;
1138 if (encomsp->queue && encomsp->thread)
1140 if (MessageQueue_PostQuit(encomsp->queue, 0) &&
1141 (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED))
1143 const UINT rc = GetLastError();
1144 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", rc);
1149 MessageQueue_Free(encomsp->queue);
1150 (void)CloseHandle(encomsp->thread);
1151 encomsp->queue =
nullptr;
1152 encomsp->thread =
nullptr;
1154 WINPR_ASSERT(encomsp->channelEntryPoints.pVirtualChannelCloseEx);
1155 const UINT rc = encomsp->channelEntryPoints.pVirtualChannelCloseEx(encomsp->InitHandle,
1156 encomsp->OpenHandle);
1158 if (CHANNEL_RC_OK != rc)
1160 WLog_ERR(TAG,
"pVirtualChannelClose failed with %s [%08" PRIX32
"]", WTSErrorToString(rc),
1165 encomsp->OpenHandle = 0;
1167 if (encomsp->data_in)
1169 Stream_Free(encomsp->data_in, TRUE);
1170 encomsp->data_in =
nullptr;
1173 return CHANNEL_RC_OK;
1181static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
1183 WINPR_ASSERT(encomsp);
1185 encomsp->InitHandle =
nullptr;
1186 free(encomsp->context);
1188 return CHANNEL_RC_OK;
1191static VOID VCAPITYPE encomsp_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
1192 UINT event, LPVOID pData,
1195 UINT error = CHANNEL_RC_OK;
1196 encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1198 if (!encomsp || (encomsp->InitHandle != pInitHandle))
1200 WLog_ERR(TAG,
"error no match");
1206 case CHANNEL_EVENT_INITIALIZED:
1209 case CHANNEL_EVENT_CONNECTED:
1210 if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength)))
1212 "encomsp_virtual_channel_event_connected failed with error %" PRIu32
"",
1217 case CHANNEL_EVENT_DISCONNECTED:
1218 if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
1220 "encomsp_virtual_channel_event_disconnected failed with error %" PRIu32
"",
1225 case CHANNEL_EVENT_TERMINATED:
1226 encomsp_virtual_channel_event_terminated(encomsp);
1233 if (error && encomsp->rdpcontext)
1234 setChannelError(encomsp->rdpcontext, error,
1235 "encomsp_virtual_channel_init_event reported an error");
1239#define VirtualChannelEntryEx encomsp_VirtualChannelEntryEx
1241FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints,
1244 BOOL isFreerdp = FALSE;
1245 encomspPlugin* encomsp = (encomspPlugin*)calloc(1,
sizeof(encomspPlugin));
1249 WLog_ERR(TAG,
"calloc failed!");
1253 encomsp->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
1254 CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
1255 (void)sprintf_s(encomsp->channelDef.name, ARRAYSIZE(encomsp->channelDef.name),
1256 ENCOMSP_SVC_CHANNEL_NAME);
1259 WINPR_ASSERT(pEntryPointsEx);
1261 EncomspClientContext* context =
nullptr;
1263 (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
1265 context = (EncomspClientContext*)calloc(1,
sizeof(EncomspClientContext));
1269 WLog_ERR(TAG,
"calloc failed!");
1273 context->handle = (
void*)encomsp;
1274 context->FilterUpdated =
nullptr;
1275 context->ApplicationCreated =
nullptr;
1276 context->ApplicationRemoved =
nullptr;
1277 context->WindowCreated =
nullptr;
1278 context->WindowRemoved =
nullptr;
1279 context->ShowWindow =
nullptr;
1280 context->ParticipantCreated =
nullptr;
1281 context->ParticipantRemoved =
nullptr;
1282 context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu;
1283 context->GraphicsStreamPaused =
nullptr;
1284 context->GraphicsStreamResumed =
nullptr;
1285 encomsp->context = context;
1286 encomsp->rdpcontext = pEntryPointsEx->context;
1290 CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints,
1292 encomsp->InitHandle = pInitHandle;
1295 const UINT rc = encomsp->channelEntryPoints.pVirtualChannelInitEx(
1296 encomsp, context, pInitHandle, &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
1297 encomsp_virtual_channel_init_event_ex);
1299 if (CHANNEL_RC_OK != rc)
1301 WLog_ERR(TAG,
"failed with %s [%08" PRIX32
"]", WTSErrorToString(rc), rc);
1306 encomsp->channelEntryPoints.pInterface = context;
1311 free(encomsp->context);