22 #include <freerdp/config.h>
24 #include <winpr/crt.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;
107 static EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp)
109 WINPR_ASSERT(encomsp);
110 return (EncomspClientContext*)encomsp->channelEntryPoints.pInterface;
118 static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp,
wStream* s)
122 Stream_Free(s, TRUE);
123 return ERROR_INVALID_HANDLE;
127 WLog_INFO(TAG,
"EncomspWrite (%"PRIuz
")", Stream_Length(s));
128 winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
130 const UINT status = encomsp->channelEntryPoints.pVirtualChannelWriteEx(
131 encomsp->InitHandle, encomsp->OpenHandle, Stream_Buffer(s), (UINT32)Stream_Length(s), s);
133 if (status != CHANNEL_RC_OK)
135 Stream_Free(s, TRUE);
136 WLog_ERR(TAG,
"VirtualChannelWriteEx failed with %s [%08" PRIX32
"]",
137 WTSErrorToString(status), status);
147 static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp,
wStream* s,
151 UINT error = CHANNEL_RC_OK;
152 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
155 return ERROR_INVALID_HANDLE;
157 WINPR_ASSERT(header);
158 const size_t pos = Stream_GetPosition(s);
159 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
160 return ERROR_INVALID_DATA;
161 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
162 pdu.Length = header->Length;
163 pdu.Type = header->Type;
165 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
166 return ERROR_INVALID_DATA;
168 Stream_Read_UINT8(s, pdu.Flags);
169 const size_t end = Stream_GetPosition(s);
170 const size_t body = beg + header->Length;
174 WLog_ERR(TAG,
"Not enough data!");
175 return ERROR_INVALID_DATA;
180 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
181 return ERROR_INVALID_DATA;
183 Stream_SetPosition(s, body);
186 IFCALLRET(context->FilterUpdated, error, context, &pdu);
189 WLog_ERR(TAG,
"context->FilterUpdated failed with error %" PRIu32
"", error);
199 static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp,
wStream* s,
203 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
206 return ERROR_INVALID_HANDLE;
208 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
209 return ERROR_INVALID_DATA;
211 const size_t pos = Stream_GetPosition(s);
212 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
213 return ERROR_INVALID_DATA;
214 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
216 WINPR_ASSERT(header);
217 pdu.Length = header->Length;
218 pdu.Type = header->Type;
220 Stream_Read_UINT16(s, pdu.Flags);
221 Stream_Read_UINT32(s, pdu.AppId);
223 UINT error = encomsp_read_unicode_string(s, &(pdu.Name));
224 if (error != CHANNEL_RC_OK)
226 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
230 const size_t end = Stream_GetPosition(s);
231 const size_t body = beg + header->Length;
235 WLog_ERR(TAG,
"Not enough data!");
236 return ERROR_INVALID_DATA;
241 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
242 return ERROR_INVALID_DATA;
244 Stream_SetPosition(s, body);
247 IFCALLRET(context->ApplicationCreated, error, context, &pdu);
250 WLog_ERR(TAG,
"context->ApplicationCreated failed with error %" PRIu32
"", error);
260 static 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 Stream_SetPosition(s, body);
300 IFCALLRET(context->ApplicationRemoved, error, context, &pdu);
303 WLog_ERR(TAG,
"context->ApplicationRemoved failed with error %" PRIu32
"", error);
313 static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp,
wStream* s,
317 UINT error = CHANNEL_RC_OK;
318 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
321 return ERROR_INVALID_HANDLE;
323 const size_t pos = Stream_GetPosition(s);
324 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
325 return ERROR_INVALID_DATA;
326 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
328 WINPR_ASSERT(header);
329 pdu.Length = header->Length;
330 pdu.Type = header->Type;
332 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
333 return ERROR_INVALID_DATA;
335 Stream_Read_UINT16(s, pdu.Flags);
336 Stream_Read_UINT32(s, pdu.AppId);
337 Stream_Read_UINT32(s, pdu.WndId);
339 if ((error = encomsp_read_unicode_string(s, &(pdu.Name))))
341 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
345 const size_t end = Stream_GetPosition(s);
346 const size_t body = beg + header->Length;
350 WLog_ERR(TAG,
"Not enough data!");
351 return ERROR_INVALID_DATA;
356 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
357 return ERROR_INVALID_DATA;
359 Stream_SetPosition(s, body);
362 IFCALLRET(context->WindowCreated, error, context, &pdu);
365 WLog_ERR(TAG,
"context->WindowCreated failed with error %" PRIu32
"", error);
375 static 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 Stream_SetPosition(s, body);
415 IFCALLRET(context->WindowRemoved, error, context, &pdu);
418 WLog_ERR(TAG,
"context->WindowRemoved failed with error %" PRIu32
"", error);
428 static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp,
wStream* s,
432 UINT error = CHANNEL_RC_OK;
433 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
436 return ERROR_INVALID_HANDLE;
438 const size_t pos = Stream_GetPosition(s);
439 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
440 return ERROR_INVALID_DATA;
441 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
443 WINPR_ASSERT(header);
444 pdu.Length = header->Length;
445 pdu.Type = header->Type;
447 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
448 return ERROR_INVALID_DATA;
450 Stream_Read_UINT32(s, pdu.WndId);
451 const size_t end = Stream_GetPosition(s);
452 const size_t body = beg + header->Length;
456 WLog_ERR(TAG,
"Not enough data!");
457 return ERROR_INVALID_DATA;
462 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
463 return ERROR_INVALID_DATA;
465 Stream_SetPosition(s, body);
468 IFCALLRET(context->ShowWindow, error, context, &pdu);
471 WLog_ERR(TAG,
"context->ShowWindow failed with error %" PRIu32
"", error);
481 static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp,
wStream* s,
485 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
488 return ERROR_INVALID_HANDLE;
490 const size_t pos = Stream_GetPosition(s);
491 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
492 return ERROR_INVALID_DATA;
493 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
495 WINPR_ASSERT(header);
496 pdu.Length = header->Length;
497 pdu.Type = header->Type;
499 if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
500 return ERROR_INVALID_DATA;
502 Stream_Read_UINT32(s, pdu.ParticipantId);
503 Stream_Read_UINT32(s, pdu.GroupId);
504 Stream_Read_UINT16(s, pdu.Flags);
506 UINT error = encomsp_read_unicode_string(s, &(pdu.FriendlyName));
507 if (error != CHANNEL_RC_OK)
509 WLog_ERR(TAG,
"encomsp_read_unicode_string failed with error %" PRIu32
"", error);
513 const size_t end = Stream_GetPosition(s);
514 const size_t body = beg + header->Length;
518 WLog_ERR(TAG,
"Not enough data!");
519 return ERROR_INVALID_DATA;
524 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
525 return ERROR_INVALID_DATA;
527 Stream_SetPosition(s, body);
530 IFCALLRET(context->ParticipantCreated, error, context, &pdu);
533 WLog_ERR(TAG,
"context->ParticipantCreated failed with error %" PRIu32
"", error);
543 static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp,
wStream* s,
547 UINT error = CHANNEL_RC_OK;
548 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
551 return ERROR_INVALID_HANDLE;
553 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
554 return ERROR_INVALID_DATA;
556 const size_t beg = (Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
558 WINPR_ASSERT(header);
559 pdu.Length = header->Length;
560 pdu.Type = header->Type;
562 Stream_Read_UINT32(s, pdu.ParticipantId);
563 Stream_Read_UINT32(s, pdu.DiscType);
564 Stream_Read_UINT32(s, pdu.DiscCode);
565 const size_t end = Stream_GetPosition(s);
566 const size_t body = beg + header->Length;
570 WLog_ERR(TAG,
"Not enough data!");
571 return ERROR_INVALID_DATA;
576 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
577 return ERROR_INVALID_DATA;
579 Stream_SetPosition(s, body);
582 IFCALLRET(context->ParticipantRemoved, error, context, &pdu);
585 WLog_ERR(TAG,
"context->ParticipantRemoved failed with error %" PRIu32
"", error);
595 static UINT encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp,
wStream* s,
599 UINT error = CHANNEL_RC_OK;
600 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
603 return ERROR_INVALID_HANDLE;
605 const size_t pos = Stream_GetPosition(s);
606 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
607 return ERROR_INVALID_DATA;
608 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
610 WINPR_ASSERT(header);
611 pdu.Length = header->Length;
612 pdu.Type = header->Type;
614 if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
615 return ERROR_INVALID_DATA;
617 Stream_Read_UINT16(s, pdu.Flags);
618 Stream_Read_UINT32(s, pdu.ParticipantId);
619 const size_t end = Stream_GetPosition(s);
620 const size_t body = beg + header->Length;
624 WLog_ERR(TAG,
"Not enough data!");
625 return ERROR_INVALID_DATA;
630 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
631 return ERROR_INVALID_DATA;
633 Stream_SetPosition(s, body);
636 IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu);
639 WLog_ERR(TAG,
"context->ChangeParticipantControlLevel failed with error %" PRIu32
"",
650 static UINT encomsp_send_change_participant_control_level_pdu(
655 WINPR_ASSERT(context);
656 encomspPlugin* encomsp = (encomspPlugin*)context->handle;
658 header.Type = ODTYPE_PARTICIPANT_CTRL_CHANGED;
659 header.Length = ENCOMSP_ORDER_HEADER_SIZE + 6;
661 wStream* s = Stream_New(NULL, header.Length);
665 WLog_ERR(TAG,
"Stream_New failed!");
666 return CHANNEL_RC_NO_MEMORY;
669 const UINT error = encomsp_write_header(s, &header);
670 if (error != CHANNEL_RC_OK)
672 WLog_ERR(TAG,
"encomsp_write_header failed with error %" PRIu32
"!", error);
676 Stream_Write_UINT16(s, pdu->Flags);
677 Stream_Write_UINT32(s, pdu->ParticipantId);
678 Stream_SealLength(s);
679 return encomsp_virtual_channel_write(encomsp, s);
687 static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp,
wStream* s,
691 UINT error = CHANNEL_RC_OK;
692 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
695 return ERROR_INVALID_HANDLE;
697 const size_t pos = Stream_GetPosition(s);
698 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
699 return ERROR_INVALID_DATA;
700 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
702 WINPR_ASSERT(header);
703 pdu.Length = header->Length;
704 pdu.Type = header->Type;
706 const size_t end = Stream_GetPosition(s);
707 const size_t body = beg + header->Length;
711 WLog_ERR(TAG,
"Not enough data!");
712 return ERROR_INVALID_DATA;
717 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
718 return ERROR_INVALID_DATA;
720 Stream_SetPosition(s, body);
723 IFCALLRET(context->GraphicsStreamPaused, error, context, &pdu);
726 WLog_ERR(TAG,
"context->GraphicsStreamPaused failed with error %" PRIu32
"", error);
736 static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp,
wStream* s,
740 UINT error = CHANNEL_RC_OK;
741 EncomspClientContext* context = encomsp_get_client_interface(encomsp);
744 return ERROR_INVALID_HANDLE;
746 const size_t pos = Stream_GetPosition(s);
747 if (pos < ENCOMSP_ORDER_HEADER_SIZE)
748 return ERROR_INVALID_DATA;
749 const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
751 WINPR_ASSERT(header);
752 pdu.Length = header->Length;
753 pdu.Type = header->Type;
755 const size_t end = Stream_GetPosition(s);
756 const size_t body = beg + header->Length;
760 WLog_ERR(TAG,
"Not enough data!");
761 return ERROR_INVALID_DATA;
766 if (!Stream_CheckAndLogRequiredLength(TAG, s, (
size_t)(body - end)))
767 return ERROR_INVALID_DATA;
769 Stream_SetPosition(s, body);
772 IFCALLRET(context->GraphicsStreamResumed, error, context, &pdu);
775 WLog_ERR(TAG,
"context->GraphicsStreamResumed failed with error %" PRIu32
"", error);
785 static UINT encomsp_process_receive(encomspPlugin* encomsp,
wStream* s)
787 UINT error = CHANNEL_RC_OK;
790 WINPR_ASSERT(encomsp);
791 while (Stream_GetRemainingLength(s) > 0)
793 if ((error = encomsp_read_header(s, &header)))
795 WLog_ERR(TAG,
"encomsp_read_header failed with error %" PRIu32
"!", error);
804 case ODTYPE_FILTER_STATE_UPDATED:
805 if ((error = encomsp_recv_filter_updated_pdu(encomsp, s, &header)))
807 WLog_ERR(TAG,
"encomsp_recv_filter_updated_pdu failed with error %" PRIu32
"!",
814 case ODTYPE_APP_REMOVED:
815 if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header)))
818 "encomsp_recv_application_removed_pdu failed with error %" PRIu32
"!",
825 case ODTYPE_APP_CREATED:
826 if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header)))
829 "encomsp_recv_application_removed_pdu failed with error %" PRIu32
"!",
836 case ODTYPE_WND_REMOVED:
837 if ((error = encomsp_recv_window_removed_pdu(encomsp, s, &header)))
839 WLog_ERR(TAG,
"encomsp_recv_window_removed_pdu failed with error %" PRIu32
"!",
846 case ODTYPE_WND_CREATED:
847 if ((error = encomsp_recv_window_created_pdu(encomsp, s, &header)))
849 WLog_ERR(TAG,
"encomsp_recv_window_created_pdu failed with error %" PRIu32
"!",
856 case ODTYPE_WND_SHOW:
857 if ((error = encomsp_recv_show_window_pdu(encomsp, s, &header)))
859 WLog_ERR(TAG,
"encomsp_recv_show_window_pdu failed with error %" PRIu32
"!",
866 case ODTYPE_PARTICIPANT_REMOVED:
867 if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header)))
870 "encomsp_recv_participant_removed_pdu failed with error %" PRIu32
"!",
877 case ODTYPE_PARTICIPANT_CREATED:
878 if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header)))
881 "encomsp_recv_participant_created_pdu failed with error %" PRIu32
"!",
888 case ODTYPE_PARTICIPANT_CTRL_CHANGED:
890 encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header)))
893 "encomsp_recv_change_participant_control_level_pdu failed with error "
901 case ODTYPE_GRAPHICS_STREAM_PAUSED:
902 if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header)))
905 "encomsp_recv_graphics_stream_paused_pdu failed with error %" PRIu32
913 case ODTYPE_GRAPHICS_STREAM_RESUMED:
914 if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header)))
917 "encomsp_recv_graphics_stream_resumed_pdu failed with error %" PRIu32
926 WLog_ERR(TAG,
"header.Type %" PRIu16
" not found", header.Type);
927 return ERROR_INVALID_DATA;
939 static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
const void* pData,
940 UINT32 dataLength, UINT32 totalLength,
943 WINPR_ASSERT(encomsp);
945 if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
946 return CHANNEL_RC_OK;
948 if (dataFlags & CHANNEL_FLAG_FIRST)
950 if (encomsp->data_in)
951 Stream_Free(encomsp->data_in, TRUE);
953 encomsp->data_in = Stream_New(NULL, totalLength);
955 if (!encomsp->data_in)
957 WLog_ERR(TAG,
"Stream_New failed!");
958 return CHANNEL_RC_NO_MEMORY;
962 wStream* data_in = encomsp->data_in;
964 if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
966 WLog_ERR(TAG,
"Stream_EnsureRemainingCapacity failed!");
967 return ERROR_INTERNAL_ERROR;
970 Stream_Write(data_in, pData, dataLength);
972 if (dataFlags & CHANNEL_FLAG_LAST)
974 if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
976 WLog_ERR(TAG,
"encomsp_plugin_process_received: read error");
977 return ERROR_INVALID_DATA;
980 encomsp->data_in = NULL;
981 Stream_SealLength(data_in);
982 Stream_SetPosition(data_in, 0);
984 if (!MessageQueue_Post(encomsp->queue, NULL, 0, (
void*)data_in, NULL))
986 WLog_ERR(TAG,
"MessageQueue_Post failed!");
987 return ERROR_INTERNAL_ERROR;
991 return CHANNEL_RC_OK;
994 static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
995 UINT event, LPVOID pData,
996 UINT32 dataLength, UINT32 totalLength,
999 UINT error = CHANNEL_RC_OK;
1000 encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1004 case CHANNEL_EVENT_DATA_RECEIVED:
1005 if (!encomsp || (encomsp->OpenHandle != openHandle))
1007 WLog_ERR(TAG,
"error no match");
1010 if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength,
1011 totalLength, dataFlags)))
1013 "encomsp_virtual_channel_event_data_received failed with error %" PRIu32
1019 case CHANNEL_EVENT_WRITE_CANCELLED:
1020 case CHANNEL_EVENT_WRITE_COMPLETE:
1023 Stream_Free(s, TRUE);
1027 case CHANNEL_EVENT_USER:
1033 if (error && encomsp && encomsp->rdpcontext)
1034 setChannelError(encomsp->rdpcontext, error,
1035 "encomsp_virtual_channel_open_event reported an error");
1038 static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg)
1041 wMessage message = { 0 };
1042 encomspPlugin* encomsp = (encomspPlugin*)arg;
1043 UINT error = CHANNEL_RC_OK;
1045 WINPR_ASSERT(encomsp);
1048 if (!MessageQueue_Wait(encomsp->queue))
1050 WLog_ERR(TAG,
"MessageQueue_Wait failed!");
1051 error = ERROR_INTERNAL_ERROR;
1055 if (!MessageQueue_Peek(encomsp->queue, &message, TRUE))
1057 WLog_ERR(TAG,
"MessageQueue_Peek failed!");
1058 error = ERROR_INTERNAL_ERROR;
1062 if (message.id == WMQ_QUIT)
1065 if (message.id == 0)
1067 data = (
wStream*)message.wParam;
1069 if ((error = encomsp_process_receive(encomsp, data)))
1071 WLog_ERR(TAG,
"encomsp_process_receive failed with error %" PRIu32
"!", error);
1072 Stream_Free(data, TRUE);
1076 Stream_Free(data, TRUE);
1080 if (error && encomsp->rdpcontext)
1081 setChannelError(encomsp->rdpcontext, error,
1082 "encomsp_virtual_channel_client_thread reported an error");
1093 static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, LPVOID pData,
1096 WINPR_ASSERT(encomsp);
1098 encomsp->queue = MessageQueue_New(NULL);
1100 if (!encomsp->queue)
1102 WLog_ERR(TAG,
"MessageQueue_New failed!");
1103 return CHANNEL_RC_NO_MEMORY;
1106 if (!(encomsp->thread = CreateThread(NULL, 0, encomsp_virtual_channel_client_thread,
1107 (
void*)encomsp, 0, NULL)))
1109 WLog_ERR(TAG,
"CreateThread failed!");
1110 MessageQueue_Free(encomsp->queue);
1111 return ERROR_INTERNAL_ERROR;
1114 return encomsp->channelEntryPoints.pVirtualChannelOpenEx(
1115 encomsp->InitHandle, &encomsp->OpenHandle, encomsp->channelDef.name,
1116 encomsp_virtual_channel_open_event_ex);
1124 static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
1126 WINPR_ASSERT(encomsp);
1127 if (encomsp->OpenHandle == 0)
1128 return CHANNEL_RC_OK;
1130 if (encomsp->queue && encomsp->thread)
1132 if (MessageQueue_PostQuit(encomsp->queue, 0) &&
1133 (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED))
1135 const UINT rc = GetLastError();
1136 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"", rc);
1141 MessageQueue_Free(encomsp->queue);
1142 (void)CloseHandle(encomsp->thread);
1143 encomsp->queue = NULL;
1144 encomsp->thread = NULL;
1146 WINPR_ASSERT(encomsp->channelEntryPoints.pVirtualChannelCloseEx);
1147 const UINT rc = encomsp->channelEntryPoints.pVirtualChannelCloseEx(encomsp->InitHandle,
1148 encomsp->OpenHandle);
1150 if (CHANNEL_RC_OK != rc)
1152 WLog_ERR(TAG,
"pVirtualChannelClose failed with %s [%08" PRIX32
"]", WTSErrorToString(rc),
1157 encomsp->OpenHandle = 0;
1159 if (encomsp->data_in)
1161 Stream_Free(encomsp->data_in, TRUE);
1162 encomsp->data_in = NULL;
1165 return CHANNEL_RC_OK;
1173 static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
1175 WINPR_ASSERT(encomsp);
1177 encomsp->InitHandle = 0;
1178 free(encomsp->context);
1180 return CHANNEL_RC_OK;
1183 static VOID VCAPITYPE encomsp_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
1184 UINT event, LPVOID pData,
1187 UINT error = CHANNEL_RC_OK;
1188 encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1190 if (!encomsp || (encomsp->InitHandle != pInitHandle))
1192 WLog_ERR(TAG,
"error no match");
1198 case CHANNEL_EVENT_INITIALIZED:
1201 case CHANNEL_EVENT_CONNECTED:
1202 if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength)))
1204 "encomsp_virtual_channel_event_connected failed with error %" PRIu32
"",
1209 case CHANNEL_EVENT_DISCONNECTED:
1210 if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
1212 "encomsp_virtual_channel_event_disconnected failed with error %" PRIu32
"",
1217 case CHANNEL_EVENT_TERMINATED:
1218 encomsp_virtual_channel_event_terminated(encomsp);
1225 if (error && encomsp->rdpcontext)
1226 setChannelError(encomsp->rdpcontext, error,
1227 "encomsp_virtual_channel_init_event reported an error");
1231 #define VirtualChannelEntryEx encomsp_VirtualChannelEntryEx
1233 FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints,
1236 BOOL isFreerdp = FALSE;
1237 encomspPlugin* encomsp = (encomspPlugin*)calloc(1,
sizeof(encomspPlugin));
1241 WLog_ERR(TAG,
"calloc failed!");
1245 encomsp->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
1246 CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
1247 (void)sprintf_s(encomsp->channelDef.name, ARRAYSIZE(encomsp->channelDef.name),
1248 ENCOMSP_SVC_CHANNEL_NAME);
1251 WINPR_ASSERT(pEntryPointsEx);
1253 EncomspClientContext* context = NULL;
1255 (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
1257 context = (EncomspClientContext*)calloc(1,
sizeof(EncomspClientContext));
1261 WLog_ERR(TAG,
"calloc failed!");
1265 context->handle = (
void*)encomsp;
1266 context->FilterUpdated = NULL;
1267 context->ApplicationCreated = NULL;
1268 context->ApplicationRemoved = NULL;
1269 context->WindowCreated = NULL;
1270 context->WindowRemoved = NULL;
1271 context->ShowWindow = NULL;
1272 context->ParticipantCreated = NULL;
1273 context->ParticipantRemoved = NULL;
1274 context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu;
1275 context->GraphicsStreamPaused = NULL;
1276 context->GraphicsStreamResumed = NULL;
1277 encomsp->context = context;
1278 encomsp->rdpcontext = pEntryPointsEx->context;
1282 CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints,
1284 encomsp->InitHandle = pInitHandle;
1285 const UINT rc = encomsp->channelEntryPoints.pVirtualChannelInitEx(
1286 encomsp, context, pInitHandle, &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
1287 encomsp_virtual_channel_init_event_ex);
1289 if (CHANNEL_RC_OK != rc)
1291 WLog_ERR(TAG,
"failed with %s [%08" PRIX32
"]", WTSErrorToString(rc), rc);
1295 encomsp->channelEntryPoints.pInterface = context;
1300 free(encomsp->context);