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 Stream_SetPosition(s, body);
182 IFCALLRET(context->FilterUpdated, error, context, &pdu);
185 WLog_ERR(TAG,
"context->FilterUpdated failed with error %" PRIu32
"", error);
195static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp,
wStream* s,
199 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
202 return ERROR_INVALID_HANDLE;
204 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
205 return ERROR_INVALID_DATA;
207 const size_t pos = Stream_GetPosition(s);
208 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
209 return ERROR_INVALID_DATA;
210 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
212 WINPR_ASSERT(header);
213 pdu.Length = header->Length;
214 pdu.Type = header->Type;
216 Stream_Read_UINT16(s, pdu.Flags);
217 Stream_Read_UINT32(s, pdu.AppId);
219 UINT error = encomsp_read_unicode_string(s, &(pdu.Name));
220 if (error != CHANNEL_RC_OK)
222 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
226 const size_t end = Stream_GetPosition(s);
227 const size_t body = beg + header->Length;
231 WLog_ERR(TAG,
"Not enough data!");
232 return ERROR_INVALID_DATA;
237 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
238 return ERROR_INVALID_DATA;
240 Stream_SetPosition(s, body);
243 IFCALLRET(context->ApplicationCreated, error, context, &pdu);
246 WLog_ERR(TAG,
"context->ApplicationCreated failed with error %" PRIu32
"", error);
256static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp,
wStream* s,
260 UINT error = CHANNEL_RC_OK;
261 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
264 return ERROR_INVALID_HANDLE;
266 const size_t pos = Stream_GetPosition(s);
267 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
268 return ERROR_INVALID_DATA;
269 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
271 WINPR_ASSERT(header);
272 pdu.Length = header->Length;
273 pdu.Type = header->Type;
275 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
276 return ERROR_INVALID_DATA;
278 Stream_Read_UINT32(s, pdu.AppId);
279 const size_t end = Stream_GetPosition(s);
280 const size_t body = beg + header->Length;
284 WLog_ERR(TAG,
"Not enough data!");
285 return ERROR_INVALID_DATA;
290 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
291 return ERROR_INVALID_DATA;
293 Stream_SetPosition(s, body);
296 IFCALLRET(context->ApplicationRemoved, error, context, &pdu);
299 WLog_ERR(TAG,
"context->ApplicationRemoved failed with error %" PRIu32
"", error);
309static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp,
wStream* s,
313 UINT error = CHANNEL_RC_OK;
314 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
317 return ERROR_INVALID_HANDLE;
319 const size_t pos = Stream_GetPosition(s);
320 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
321 return ERROR_INVALID_DATA;
322 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
324 WINPR_ASSERT(header);
325 pdu.Length = header->Length;
326 pdu.Type = header->Type;
328 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
329 return ERROR_INVALID_DATA;
331 Stream_Read_UINT16(s, pdu.Flags);
332 Stream_Read_UINT32(s, pdu.AppId);
333 Stream_Read_UINT32(s, pdu.WndId);
335 if ((error = encomsp_read_unicode_string(s, &(pdu.Name))))
337 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
341 const size_t end = Stream_GetPosition(s);
342 const size_t body = beg + header->Length;
346 WLog_ERR(TAG,
"Not enough data!");
347 return ERROR_INVALID_DATA;
352 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
353 return ERROR_INVALID_DATA;
355 Stream_SetPosition(s, body);
358 IFCALLRET(context->WindowCreated, error, context, &pdu);
361 WLog_ERR(TAG,
"context->WindowCreated failed with error %" PRIu32
"", error);
371static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp,
wStream* s,
375 UINT error = CHANNEL_RC_OK;
376 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
379 return ERROR_INVALID_HANDLE;
381 const size_t pos = Stream_GetPosition(s);
382 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
383 return ERROR_INVALID_DATA;
384 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
386 WINPR_ASSERT(header);
387 pdu.Length = header->Length;
388 pdu.Type = header->Type;
390 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
391 return ERROR_INVALID_DATA;
393 Stream_Read_UINT32(s, pdu.WndId);
394 const size_t end = Stream_GetPosition(s);
395 const size_t body = beg + header->Length;
399 WLog_ERR(TAG,
"Not enough data!");
400 return ERROR_INVALID_DATA;
405 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
406 return ERROR_INVALID_DATA;
408 Stream_SetPosition(s, body);
411 IFCALLRET(context->WindowRemoved, error, context, &pdu);
414 WLog_ERR(TAG,
"context->WindowRemoved failed with error %" PRIu32
"", error);
424static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp,
wStream* s,
428 UINT error = CHANNEL_RC_OK;
429 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
432 return ERROR_INVALID_HANDLE;
434 const size_t pos = Stream_GetPosition(s);
435 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
436 return ERROR_INVALID_DATA;
437 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
439 WINPR_ASSERT(header);
440 pdu.Length = header->Length;
441 pdu.Type = header->Type;
443 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
444 return ERROR_INVALID_DATA;
446 Stream_Read_UINT32(s, pdu.WndId);
447 const size_t end = Stream_GetPosition(s);
448 const size_t body = beg + header->Length;
452 WLog_ERR(TAG,
"Not enough data!");
453 return ERROR_INVALID_DATA;
458 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
459 return ERROR_INVALID_DATA;
461 Stream_SetPosition(s, body);
464 IFCALLRET(context->ShowWindow, error, context, &pdu);
467 WLog_ERR(TAG,
"context->ShowWindow failed with error %" PRIu32
"", error);
477static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp,
wStream* s,
481 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
484 return ERROR_INVALID_HANDLE;
486 const size_t pos = Stream_GetPosition(s);
487 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
488 return ERROR_INVALID_DATA;
489 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
491 WINPR_ASSERT(header);
492 pdu.Length = header->Length;
493 pdu.Type = header->Type;
495 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
496 return ERROR_INVALID_DATA;
498 Stream_Read_UINT32(s, pdu.ParticipantId);
499 Stream_Read_UINT32(s, pdu.GroupId);
500 Stream_Read_UINT16(s, pdu.Flags);
502 UINT error = encomsp_read_unicode_string(s, &(pdu.FriendlyName));
503 if (error != CHANNEL_RC_OK)
505 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
509 const size_t end = Stream_GetPosition(s);
510 const size_t body = beg + header->Length;
514 WLog_ERR(TAG,
"Not enough data!");
515 return ERROR_INVALID_DATA;
520 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
521 return ERROR_INVALID_DATA;
523 Stream_SetPosition(s, body);
526 IFCALLRET(context->ParticipantCreated, error, context, &pdu);
529 WLog_ERR(TAG,
"context->ParticipantCreated failed with error %" PRIu32
"", error);
539static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp,
wStream* s,
543 UINT error = CHANNEL_RC_OK;
544 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
547 return ERROR_INVALID_HANDLE;
549 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
550 return ERROR_INVALID_DATA;
552 const size_t beg = (Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
554 WINPR_ASSERT(header);
555 pdu.Length = header->Length;
556 pdu.Type = header->Type;
558 Stream_Read_UINT32(s, pdu.ParticipantId);
559 Stream_Read_UINT32(s, pdu.DiscType);
560 Stream_Read_UINT32(s, pdu.DiscCode);
561 const size_t end = Stream_GetPosition(s);
562 const size_t body = beg + header->Length;
566 WLog_ERR(TAG,
"Not enough data!");
567 return ERROR_INVALID_DATA;
572 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
573 return ERROR_INVALID_DATA;
575 Stream_SetPosition(s, body);
578 IFCALLRET(context->ParticipantRemoved, error, context, &pdu);
581 WLog_ERR(TAG,
"context->ParticipantRemoved failed with error %" PRIu32
"", error);
591static UINT encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp,
wStream* s,
595 UINT error = CHANNEL_RC_OK;
596 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
599 return ERROR_INVALID_HANDLE;
601 const size_t pos = Stream_GetPosition(s);
602 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
603 return ERROR_INVALID_DATA;
604 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
606 WINPR_ASSERT(header);
607 pdu.Length = header->Length;
608 pdu.Type = header->Type;
610 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
611 return ERROR_INVALID_DATA;
613 Stream_Read_UINT16(s, pdu.Flags);
614 Stream_Read_UINT32(s, pdu.ParticipantId);
615 const size_t end = Stream_GetPosition(s);
616 const size_t body = beg + header->Length;
620 WLog_ERR(TAG,
"Not enough data!");
621 return ERROR_INVALID_DATA;
626 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
627 return ERROR_INVALID_DATA;
629 Stream_SetPosition(s, body);
632 IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu);
635 WLog_ERR(TAG,
"context->ChangeParticipantControlLevel failed with error %" PRIu32
"",
646static UINT encomsp_send_change_participant_control_level_pdu(
651 WINPR_ASSERT(context);
652 encomspPlugin* encomsp = (encomspPlugin*)context->handle;
654 header.Type = ODTYPE_PARTICIPANT_CTRL_CHANGED;
655 header.Length = ENCOMSP_ORDER_HEADER_SIZE + 6;
657 wStream* s = Stream_New(NULL, header.Length);
661 WLog_ERR(TAG,
"Stream_New failed!");
662 return CHANNEL_RC_NO_MEMORY;
665 const UINT error = encomsp_write_header(s, &header);
666 if (error != CHANNEL_RC_OK)
668 WLog_ERR(TAG,
"encomsp_write_header failed with error %" PRIu32
"!", error);
672 Stream_Write_UINT16(s, pdu->Flags);
673 Stream_Write_UINT32(s, pdu->ParticipantId);
674 Stream_SealLength(s);
675 return encomsp_virtual_channel_write(encomsp, s);
683static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp,
wStream* s,
687 UINT error = CHANNEL_RC_OK;
688 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
691 return ERROR_INVALID_HANDLE;
693 const size_t pos = Stream_GetPosition(s);
694 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
695 return ERROR_INVALID_DATA;
696 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
698 WINPR_ASSERT(header);
699 pdu.Length = header->Length;
700 pdu.Type = header->Type;
702 const size_t end = Stream_GetPosition(s);
703 const size_t body = beg + header->Length;
707 WLog_ERR(TAG,
"Not enough data!");
708 return ERROR_INVALID_DATA;
713 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
714 return ERROR_INVALID_DATA;
716 Stream_SetPosition(s, body);
719 IFCALLRET(context->GraphicsStreamPaused, error, context, &pdu);
722 WLog_ERR(TAG,
"context->GraphicsStreamPaused failed with error %" PRIu32
"", error);
732static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp,
wStream* s,
736 UINT error = CHANNEL_RC_OK;
737 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
740 return ERROR_INVALID_HANDLE;
742 const size_t pos = Stream_GetPosition(s);
743 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
744 return ERROR_INVALID_DATA;
745 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
747 WINPR_ASSERT(header);
748 pdu.Length = header->Length;
749 pdu.Type = header->Type;
751 const size_t end = Stream_GetPosition(s);
752 const size_t body = beg + header->Length;
756 WLog_ERR(TAG,
"Not enough data!");
757 return ERROR_INVALID_DATA;
762 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
763 return ERROR_INVALID_DATA;
765 Stream_SetPosition(s, body);
768 IFCALLRET(context->GraphicsStreamResumed, error, context, &pdu);
771 WLog_ERR(TAG,
"context->GraphicsStreamResumed failed with error %" PRIu32
"", error);
781static UINT encomsp_process_receive(encomspPlugin* encomsp,
wStream* s)
783 UINT error = CHANNEL_RC_OK;
786 WINPR_ASSERT(encomsp);
787 while (Stream_GetRemainingLength(s) > 0)
789 if ((error = encomsp_read_header(s, &header)))
791 WLog_ERR(TAG,
"encomsp_read_header failed with error %" PRIu32
"!", error);
800 case ODTYPE_FILTER_STATE_UPDATED:
801 if ((error = encomsp_recv_filter_updated_pdu(encomsp, s, &header)))
803 WLog_ERR(TAG,
"encomsp_recv_filter_updated_pdu failed with error %" PRIu32
"!",
810 case ODTYPE_APP_REMOVED:
811 if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header)))
814 "encomsp_recv_application_removed_pdu failed with error %" PRIu32
"!",
821 case ODTYPE_APP_CREATED:
822 if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header)))
825 "encomsp_recv_application_removed_pdu failed with error %" PRIu32
"!",
832 case ODTYPE_WND_REMOVED:
833 if ((error = encomsp_recv_window_removed_pdu(encomsp, s, &header)))
835 WLog_ERR(TAG,
"encomsp_recv_window_removed_pdu failed with error %" PRIu32
"!",
842 case ODTYPE_WND_CREATED:
843 if ((error = encomsp_recv_window_created_pdu(encomsp, s, &header)))
845 WLog_ERR(TAG,
"encomsp_recv_window_created_pdu failed with error %" PRIu32
"!",
852 case ODTYPE_WND_SHOW:
853 if ((error = encomsp_recv_show_window_pdu(encomsp, s, &header)))
855 WLog_ERR(TAG,
"encomsp_recv_show_window_pdu failed with error %" PRIu32
"!",
862 case ODTYPE_PARTICIPANT_REMOVED:
863 if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header)))
866 "encomsp_recv_participant_removed_pdu failed with error %" PRIu32
"!",
873 case ODTYPE_PARTICIPANT_CREATED:
874 if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header)))
877 "encomsp_recv_participant_created_pdu failed with error %" PRIu32
"!",
884 case ODTYPE_PARTICIPANT_CTRL_CHANGED:
886 encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header)))
889 "encomsp_recv_change_participant_control_level_pdu failed with error "
897 case ODTYPE_GRAPHICS_STREAM_PAUSED:
898 if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header)))
901 "encomsp_recv_graphics_stream_paused_pdu failed with error %" PRIu32
909 case ODTYPE_GRAPHICS_STREAM_RESUMED:
910 if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header)))
913 "encomsp_recv_graphics_stream_resumed_pdu failed with error %" PRIu32
922 WLog_ERR(TAG,
"header.Type %" PRIu16
" not found", header.Type);
923 return ERROR_INVALID_DATA;
935static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
const void* pData,
936 UINT32 dataLength, UINT32 totalLength,
939 WINPR_ASSERT(encomsp);
941 if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
942 return CHANNEL_RC_OK;
944 if (dataFlags & CHANNEL_FLAG_FIRST)
946 if (encomsp->data_in)
947 Stream_Free(encomsp->data_in, TRUE);
949 encomsp->data_in = Stream_New(NULL, totalLength);
951 if (!encomsp->data_in)
953 WLog_ERR(TAG,
"Stream_New failed!");
954 return CHANNEL_RC_NO_MEMORY;
958 wStream* data_in = encomsp->data_in;
960 if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
962 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
963 return ERROR_INTERNAL_ERROR;
966 Stream_Write(data_in, pData, dataLength);
968 if (dataFlags & CHANNEL_FLAG_LAST)
970 if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
972 WLog_ERR(TAG,
"encomsp_plugin_process_received: read error");
973 return ERROR_INVALID_DATA;
976 encomsp->data_in = NULL;
977 Stream_SealLength(data_in);
978 Stream_SetPosition(data_in, 0);
980 if (!MessageQueue_Post(encomsp->queue, NULL, 0, (
void*)data_in, NULL))
982 WLog_ERR(TAG,
"MessageQueue_Post failed!");
983 return ERROR_INTERNAL_ERROR;
987 return CHANNEL_RC_OK;
990static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
991 UINT event, LPVOID pData,
992 UINT32 dataLength, UINT32 totalLength,
995 UINT error = CHANNEL_RC_OK;
996 encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1000 case CHANNEL_EVENT_DATA_RECEIVED:
1001 if (!encomsp || (encomsp->OpenHandle != openHandle))
1003 WLog_ERR(TAG,
"error no match");
1006 if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength,
1007 totalLength, dataFlags)))
1009 "encomsp_virtual_channel_event_data_received failed with error %" PRIu32
1015 case CHANNEL_EVENT_WRITE_CANCELLED:
1016 case CHANNEL_EVENT_WRITE_COMPLETE:
1019 Stream_Free(s, TRUE);
1023 case CHANNEL_EVENT_USER:
1029 if (error && encomsp && encomsp->rdpcontext)
1030 setChannelError(encomsp->rdpcontext, error,
1031 "encomsp_virtual_channel_open_event reported an error");
1034static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg)
1037 wMessage message = { 0 };
1038 encomspPlugin* encomsp = (encomspPlugin*)arg;
1039 UINT error = CHANNEL_RC_OK;
1041 WINPR_ASSERT(encomsp);
1044 if (!MessageQueue_Wait(encomsp->queue))
1046 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
1047 error = ERROR_INTERNAL_ERROR;
1051 if (!MessageQueue_Peek(encomsp->queue, &message, TRUE))
1053 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
1054 error = ERROR_INTERNAL_ERROR;
1058 if (message.id == WMQ_QUIT)
1061 if (message.id == 0)
1063 data = (
wStream*)message.wParam;
1065 if ((error = encomsp_process_receive(encomsp, data)))
1067 WLog_ERR(TAG,
"encomsp_process_receive failed with error %" PRIu32
"!", error);
1068 Stream_Free(data, TRUE);
1072 Stream_Free(data, TRUE);
1076 if (error && encomsp->rdpcontext)
1077 setChannelError(encomsp->rdpcontext, error,
1078 "encomsp_virtual_channel_client_thread reported an error");
1089static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
1090 WINPR_ATTR_UNUSED LPVOID pData,
1091 WINPR_ATTR_UNUSED UINT32 dataLength)
1093 WINPR_ASSERT(encomsp);
1095 encomsp->queue = MessageQueue_New(NULL);
1097 if (!encomsp->queue)
1099 WLog_ERR(TAG,
"MessageQueue_New failed!");
1100 return CHANNEL_RC_NO_MEMORY;
1103 if (!(encomsp->thread = CreateThread(NULL, 0, encomsp_virtual_channel_client_thread,
1104 (
void*)encomsp, 0, NULL)))
1106 WLog_ERR(TAG,
"CreateThread failed!");
1107 MessageQueue_Free(encomsp->queue);
1108 return ERROR_INTERNAL_ERROR;
1111 return encomsp->channelEntryPoints.pVirtualChannelOpenEx(
1112 encomsp->InitHandle, &encomsp->OpenHandle, encomsp->channelDef.name,
1113 encomsp_virtual_channel_open_event_ex);
1121static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
1123 WINPR_ASSERT(encomsp);
1124 if (encomsp->OpenHandle == 0)
1125 return CHANNEL_RC_OK;
1127 if (encomsp->queue && encomsp->thread)
1129 if (MessageQueue_PostQuit(encomsp->queue, 0) &&
1130 (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED))
1132 const UINT rc = GetLastError();
1133 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", rc);
1138 MessageQueue_Free(encomsp->queue);
1139 (void)CloseHandle(encomsp->thread);
1140 encomsp->queue = NULL;
1141 encomsp->thread = NULL;
1143 WINPR_ASSERT(encomsp->channelEntryPoints.pVirtualChannelCloseEx);
1144 const UINT rc = encomsp->channelEntryPoints.pVirtualChannelCloseEx(encomsp->InitHandle,
1145 encomsp->OpenHandle);
1147 if (CHANNEL_RC_OK != rc)
1149 WLog_ERR(TAG,
"pVirtualChannelClose failed with %s [%08" PRIX32
"]", WTSErrorToString(rc),
1154 encomsp->OpenHandle = 0;
1156 if (encomsp->data_in)
1158 Stream_Free(encomsp->data_in, TRUE);
1159 encomsp->data_in = NULL;
1162 return CHANNEL_RC_OK;
1170static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
1172 WINPR_ASSERT(encomsp);
1174 encomsp->InitHandle = 0;
1175 free(encomsp->context);
1177 return CHANNEL_RC_OK;
1180static VOID VCAPITYPE encomsp_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
1181 UINT event, LPVOID pData,
1184 UINT error = CHANNEL_RC_OK;
1185 encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1187 if (!encomsp || (encomsp->InitHandle != pInitHandle))
1189 WLog_ERR(TAG,
"error no match");
1195 case CHANNEL_EVENT_INITIALIZED:
1198 case CHANNEL_EVENT_CONNECTED:
1199 if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength)))
1201 "encomsp_virtual_channel_event_connected failed with error %" PRIu32
"",
1206 case CHANNEL_EVENT_DISCONNECTED:
1207 if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
1209 "encomsp_virtual_channel_event_disconnected failed with error %" PRIu32
"",
1214 case CHANNEL_EVENT_TERMINATED:
1215 encomsp_virtual_channel_event_terminated(encomsp);
1222 if (error && encomsp->rdpcontext)
1223 setChannelError(encomsp->rdpcontext, error,
1224 "encomsp_virtual_channel_init_event reported an error");
1228#define VirtualChannelEntryEx encomsp_VirtualChannelEntryEx
1230FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints,
1233 BOOL isFreerdp = FALSE;
1234 encomspPlugin* encomsp = (encomspPlugin*)calloc(1,
sizeof(encomspPlugin));
1238 WLog_ERR(TAG,
"calloc failed!");
1242 encomsp->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
1243 CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
1244 (void)sprintf_s(encomsp->channelDef.name, ARRAYSIZE(encomsp->channelDef.name),
1245 ENCOMSP_SVC_CHANNEL_NAME);
1248 WINPR_ASSERT(pEntryPointsEx);
1250 EncomspClientContext* context = NULL;
1252 (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
1254 context = (EncomspClientContext*)calloc(1,
sizeof(EncomspClientContext));
1258 WLog_ERR(TAG,
"calloc failed!");
1262 context->handle = (
void*)encomsp;
1263 context->FilterUpdated = NULL;
1264 context->ApplicationCreated = NULL;
1265 context->ApplicationRemoved = NULL;
1266 context->WindowCreated = NULL;
1267 context->WindowRemoved = NULL;
1268 context->ShowWindow = NULL;
1269 context->ParticipantCreated = NULL;
1270 context->ParticipantRemoved = NULL;
1271 context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu;
1272 context->GraphicsStreamPaused = NULL;
1273 context->GraphicsStreamResumed = NULL;
1274 encomsp->context = context;
1275 encomsp->rdpcontext = pEntryPointsEx->context;
1279 CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints,
1281 encomsp->InitHandle = pInitHandle;
1282 const UINT rc = encomsp->channelEntryPoints.pVirtualChannelInitEx(
1283 encomsp, context, pInitHandle, &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
1284 encomsp_virtual_channel_init_event_ex);
1286 if (CHANNEL_RC_OK != rc)
1288 WLog_ERR(TAG,
"failed with %s [%08" PRIX32
"]", WTSErrorToString(rc), rc);
1292 encomsp->channelEntryPoints.pInterface = context;
1297 free(encomsp->context);