FreeRDP
Loading...
Searching...
No Matches
libfreerdp/core/client.c
1
22#include <freerdp/config.h>
23
24#include "settings.h"
25
26#include <winpr/assert.h>
27
28#include <freerdp/log.h>
29#include <freerdp/channels/drdynvc.h>
30
31#include "rdp.h"
32#include "client.h"
33
34#define TAG FREERDP_TAG("core.client")
35
36typedef struct
37{
38 freerdp_channel_handle_fkt_t fkt;
39 void* userdata;
40} ChannelEventEntry;
41
42/* Use this instance to get access to channels in VirtualChannelInit. It is set during
43 * freerdp_connect so channels that use VirtualChannelInit must be initialized from the same thread
44 * as freerdp_connect was called */
45static WINPR_TLS freerdp* g_Instance = nullptr;
46
47/* use global counter to ensure uniqueness across channel manager instances */
48static volatile LONG g_OpenHandleSeq = 1;
49
50/* HashTable mapping channel handles to CHANNEL_OPEN_DATA */
51static INIT_ONCE g_ChannelHandlesOnce = INIT_ONCE_STATIC_INIT;
52static wHashTable* g_ChannelHandles = nullptr;
53
54static BOOL freerdp_channels_process_message_free(wMessage* message, DWORD type);
55
56static CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* channels,
57 const char* name)
58{
59 for (int index = 0; index < channels->openDataCount; index++)
60 {
61 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[index];
62
63 if (strncmp(name, pChannelOpenData->name, CHANNEL_NAME_LEN + 1) == 0)
64 return pChannelOpenData;
65 }
66
67 return nullptr;
68}
69
70/* returns rdpChannel for the channel name passed in */
71static rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp, const char* name)
72{
73 rdpMcs* mcs = nullptr;
74
75 if (!rdp)
76 return nullptr;
77
78 mcs = rdp->mcs;
79
80 for (UINT32 index = 0; index < mcs->channelCount; index++)
81 {
82 rdpMcsChannel* channel = &mcs->channels[index];
83
84 if (strncmp(name, channel->Name, CHANNEL_NAME_LEN + 1) == 0)
85 {
86 return channel;
87 }
88 }
89
90 return nullptr;
91}
92
93static rdpMcsChannel* freerdp_channels_find_channel_by_id(rdpRdp* rdp, UINT16 channel_id)
94{
95 rdpMcsChannel* channel = nullptr;
96 rdpMcs* mcs = nullptr;
97
98 if (!rdp)
99 return nullptr;
100
101 mcs = rdp->mcs;
102
103 for (UINT32 index = 0; index < mcs->channelCount; index++)
104 {
105 channel = &mcs->channels[index];
106
107 if (channel->ChannelId == channel_id)
108 {
109 return channel;
110 }
111 }
112
113 return nullptr;
114}
115
116static void channel_queue_message_free(wMessage* msg)
117{
118 CHANNEL_OPEN_EVENT* ev = nullptr;
119
120 if (!msg || (msg->id != 0))
121 return;
122
123 ev = (CHANNEL_OPEN_EVENT*)msg->wParam;
124 free(ev);
125}
126
127static void channel_queue_free(void* obj)
128{
129 wMessage* msg = (wMessage*)obj;
130 freerdp_channels_process_message_free(msg, CHANNEL_EVENT_WRITE_CANCELLED);
131 channel_queue_message_free(msg);
132}
133
134static BOOL CALLBACK init_channel_handles_table(WINPR_ATTR_UNUSED PINIT_ONCE once,
135 WINPR_ATTR_UNUSED PVOID param,
136 WINPR_ATTR_UNUSED PVOID* context)
137{
138 g_ChannelHandles = HashTable_New(TRUE);
139 return TRUE;
140}
141
142static void* channel_event_entry_clone(const void* data)
143{
144 const ChannelEventEntry* entry = data;
145 if (!entry)
146 return nullptr;
147
148 ChannelEventEntry* copy = calloc(1, sizeof(ChannelEventEntry));
149 if (!copy)
150 return nullptr;
151 *copy = *entry;
152 return copy;
153}
154
155rdpChannels* freerdp_channels_new(freerdp* instance)
156{
157 if (!InitOnceExecuteOnce(&g_ChannelHandlesOnce, init_channel_handles_table, nullptr, nullptr))
158 return nullptr;
159
160 wObject* obj = nullptr;
161 rdpChannels* channels = nullptr;
162 channels = (rdpChannels*)calloc(1, sizeof(rdpChannels));
163
164 if (!channels)
165 return nullptr;
166
167 if (!g_ChannelHandles)
168 goto error;
169 if (!InitializeCriticalSectionAndSpinCount(&channels->channelsLock, 4000))
170 goto error;
171
172 channels->instance = instance;
173 channels->queue = MessageQueue_New(nullptr);
174
175 if (!channels->queue)
176 goto error;
177
178 obj = MessageQueue_Object(channels->queue);
179 obj->fnObjectFree = channel_queue_free;
180
181 channels->channelEvents = HashTable_New(FALSE);
182 if (!channels->channelEvents)
183 goto error;
184
185 obj = HashTable_ValueObject(channels->channelEvents);
186 WINPR_ASSERT(obj);
187 obj->fnObjectFree = free;
188 obj->fnObjectNew = channel_event_entry_clone;
189 return channels;
190error:
191 WINPR_PRAGMA_DIAG_PUSH
192 WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
193 freerdp_channels_free(channels);
194 WINPR_PRAGMA_DIAG_POP
195 return nullptr;
196}
197
198void freerdp_channels_free(rdpChannels* channels)
199{
200 if (!channels)
201 return;
202
203 HashTable_Free(channels->channelEvents);
204
205 DeleteCriticalSection(&channels->channelsLock);
206
207 if (channels->queue)
208 {
209 MessageQueue_Free(channels->queue);
210 channels->queue = nullptr;
211 }
212
213 free(channels);
214}
215
221static UINT freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const char* name,
222 void* pInterface)
223{
224 UINT status = CHANNEL_RC_OK;
225 ChannelConnectedEventArgs e = WINPR_C_ARRAY_INIT;
226
227 WINPR_ASSERT(context);
228
229 rdpChannels* channels = (rdpChannels*)context->custom;
230 WINPR_ASSERT(channels);
231
232 freerdp* instance = channels->instance;
233 WINPR_ASSERT(instance);
234 WINPR_ASSERT(instance->context);
235
236 EventArgsInit(&e, "freerdp");
237 e.name = name;
238 e.pInterface = pInterface;
239 if (PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e) < 0)
240 return ERROR_INTERNAL_ERROR;
241 return status;
242}
243
249static UINT freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext* context, const char* name,
250 void* pInterface)
251{
252 UINT status = CHANNEL_RC_OK;
253 ChannelDisconnectedEventArgs e = WINPR_C_ARRAY_INIT;
254
255 WINPR_ASSERT(context);
256 rdpChannels* channels = (rdpChannels*)context->custom;
257 WINPR_ASSERT(channels);
258
259 freerdp* instance = channels->instance;
260 WINPR_ASSERT(instance);
261 WINPR_ASSERT(instance->context);
262
263 EventArgsInit(&e, "freerdp");
264 e.name = name;
265 e.pInterface = pInterface;
266 if (PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e) < 0)
267 return ERROR_INTERNAL_ERROR;
268 return status;
269}
270
271static UINT freerdp_drdynvc_on_channel_attached(DrdynvcClientContext* context, const char* name,
272 void* pInterface)
273{
274 UINT status = CHANNEL_RC_OK;
275 ChannelAttachedEventArgs e = WINPR_C_ARRAY_INIT;
276
277 WINPR_ASSERT(context);
278 rdpChannels* channels = (rdpChannels*)context->custom;
279 WINPR_ASSERT(channels);
280
281 freerdp* instance = channels->instance;
282 WINPR_ASSERT(instance);
283 WINPR_ASSERT(instance->context);
284
285 EventArgsInit(&e, "freerdp");
286 e.name = name;
287 e.pInterface = pInterface;
288 if (PubSub_OnChannelAttached(instance->context->pubSub, instance->context, &e) < 0)
289 return ERROR_INTERNAL_ERROR;
290 return status;
291}
292
293static UINT freerdp_drdynvc_on_channel_detached(DrdynvcClientContext* context, const char* name,
294 void* pInterface)
295{
296 UINT status = CHANNEL_RC_OK;
297 ChannelDetachedEventArgs e = WINPR_C_ARRAY_INIT;
298
299 WINPR_ASSERT(context);
300 rdpChannels* channels = (rdpChannels*)context->custom;
301 WINPR_ASSERT(channels);
302
303 freerdp* instance = channels->instance;
304 WINPR_ASSERT(instance);
305 WINPR_ASSERT(instance->context);
306
307 EventArgsInit(&e, "freerdp");
308 e.name = name;
309 e.pInterface = pInterface;
310 if (PubSub_OnChannelDetached(instance->context->pubSub, instance->context, &e) < 0)
311 return ERROR_INTERNAL_ERROR;
312 return status;
313}
314
315void freerdp_channels_register_instance(WINPR_ATTR_UNUSED rdpChannels* channels, freerdp* instance)
316{
317 /* store instance in TLS so future VirtualChannelInit calls can use it */
318 g_Instance = instance;
319}
320
325UINT freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance)
326{
327 UINT error = CHANNEL_RC_OK;
328
329 MessageQueue_Clear(channels->queue);
330
331 for (int index = 0; index < channels->clientDataCount; index++)
332 {
333 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[index];
334
335 if (pChannelClientData->pChannelInitEventProc)
336 {
337 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
338 CHANNEL_EVENT_INITIALIZED, nullptr, 0);
339 }
340 else if (pChannelClientData->pChannelInitEventProcEx)
341 {
342 pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
343 pChannelClientData->pInitHandle,
344 CHANNEL_EVENT_INITIALIZED, nullptr, 0);
345 }
346
347 error = getChannelError(instance->context);
348 if (CHANNEL_RC_OK != error)
349 break;
350
351 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[index];
352 CHANNEL_INIT_DATA* pChannelInitData = &channels->initDataList[index];
353 ChannelInitializedEventArgs e = WINPR_C_ARRAY_INIT;
354 EventArgsInit(&e, "freerdp");
355 e.name = pChannelOpenData->name;
356 e.pInterface = pChannelInitData->pInterface;
357 if (PubSub_OnChannelInitialized(instance->context->pubSub, instance->context, &e) < 0)
358 {
359 error = ERROR_INTERNAL_ERROR;
360 break;
361 }
362 }
363
364 return error;
365}
366
367UINT freerdp_channels_attach(freerdp* instance)
368{
369 UINT error = CHANNEL_RC_OK;
370 const char* hostname = nullptr;
371 size_t hostnameLength = 0;
372 rdpChannels* channels = nullptr;
373 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
374
375 WINPR_ASSERT(instance);
376 WINPR_ASSERT(instance->context);
377 WINPR_ASSERT(instance->context->settings);
378
379 channels = instance->context->channels;
380 hostname = freerdp_settings_get_string(instance->context->settings, FreeRDP_ServerHostname);
381 WINPR_ASSERT(hostname);
382 hostnameLength = strnlen(hostname, MAX_PATH);
383
384 for (int index = 0; index < channels->clientDataCount; index++)
385 {
386 union
387 {
388 const void* cpv;
389 void* pv;
390 } cnv;
391 ChannelAttachedEventArgs e = WINPR_C_ARRAY_INIT;
392
393 cnv.cpv = hostname;
394 pChannelClientData = &channels->clientDataList[index];
395
396 if (pChannelClientData->pChannelInitEventProc)
397 {
398
399 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
400 CHANNEL_EVENT_ATTACHED, cnv.pv,
401 (UINT)hostnameLength);
402 }
403 else if (pChannelClientData->pChannelInitEventProcEx)
404 {
405 pChannelClientData->pChannelInitEventProcEx(
406 pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
407 CHANNEL_EVENT_ATTACHED, cnv.pv, (UINT)hostnameLength);
408 }
409
410 error = getChannelError(instance->context);
411 if (error != CHANNEL_RC_OK)
412 goto fail;
413
414 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[index];
415 EventArgsInit(&e, "freerdp");
416 e.name = pChannelOpenData->name;
417 e.pInterface = pChannelOpenData->pInterface;
418 if (PubSub_OnChannelAttached(instance->context->pubSub, instance->context, &e) < 0)
419 {
420 error = ERROR_INTERNAL_ERROR;
421 goto fail;
422 }
423 }
424
425fail:
426 return error;
427}
428
429UINT freerdp_channels_detach(freerdp* instance)
430{
431 UINT error = CHANNEL_RC_OK;
432 const char* hostname = nullptr;
433 size_t hostnameLength = 0;
434 rdpChannels* channels = nullptr;
435 rdpContext* context = nullptr;
436 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
437
438 WINPR_ASSERT(instance);
439
440 context = instance->context;
441 WINPR_ASSERT(context);
442
443 channels = context->channels;
444 WINPR_ASSERT(channels);
445
446 WINPR_ASSERT(context->settings);
447 hostname = freerdp_settings_get_string(context->settings, FreeRDP_ServerHostname);
448 WINPR_ASSERT(hostname);
449 hostnameLength = strnlen(hostname, MAX_PATH);
450
451 for (int index = 0; index < channels->clientDataCount; index++)
452 {
453 union
454 {
455 const void* cpv;
456 void* pv;
457 } cnv;
458
459 ChannelDetachedEventArgs e = WINPR_C_ARRAY_INIT;
460
461 cnv.cpv = hostname;
462 pChannelClientData = &channels->clientDataList[index];
463
464 if (pChannelClientData->pChannelInitEventProc)
465 {
466 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
467 CHANNEL_EVENT_DETACHED, cnv.pv,
468 (UINT)hostnameLength);
469 }
470 else if (pChannelClientData->pChannelInitEventProcEx)
471 {
472 pChannelClientData->pChannelInitEventProcEx(
473 pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
474 CHANNEL_EVENT_DETACHED, cnv.pv, (UINT)hostnameLength);
475 }
476
477 error = getChannelError(context);
478 if (error != CHANNEL_RC_OK)
479 goto fail;
480
481 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[index];
482 EventArgsInit(&e, "freerdp");
483 e.name = pChannelOpenData->name;
484 e.pInterface = pChannelOpenData->pInterface;
485 if (PubSub_OnChannelDetached(context->pubSub, context, &e) < 0)
486 {
487 error = ERROR_INTERNAL_ERROR;
488 goto fail;
489 }
490 }
491
492fail:
493 return error;
494}
495
501UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
502{
503 UINT error = CHANNEL_RC_OK;
504
505 WINPR_ASSERT(channels);
506 WINPR_ASSERT(instance);
507 WINPR_ASSERT(instance->context);
508 WINPR_ASSERT(instance->context->settings);
509
510 channels->connected = TRUE;
511 const char* hostname =
512 freerdp_settings_get_string(instance->context->settings, FreeRDP_ServerHostname);
513 WINPR_ASSERT(hostname);
514 const size_t hostnameLength = strnlen(hostname, MAX_PATH);
515
516 for (int index = 0; index < channels->clientDataCount; index++)
517 {
518 union
519 {
520 const void* pcb;
521 void* pb;
522 } cnv;
523
524 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[index];
525 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[index];
526
527 cnv.pcb = hostname;
528 if (pChannelClientData->pChannelInitEventProc)
529 {
530 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
531 CHANNEL_EVENT_CONNECTED, cnv.pb,
532 (UINT)hostnameLength);
533 }
534 else if (pChannelClientData->pChannelInitEventProcEx)
535 {
536 pChannelClientData->pChannelInitEventProcEx(
537 pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
538 CHANNEL_EVENT_CONNECTED, cnv.pb, (UINT)hostnameLength);
539 }
540
541 error = getChannelError(instance->context);
542 if (error != CHANNEL_RC_OK)
543 goto fail;
544
545 ChannelConnectedEventArgs e = WINPR_C_ARRAY_INIT;
546 EventArgsInit(&e, "freerdp");
547 e.name = pChannelOpenData->name;
548 e.pInterface = pChannelOpenData->pInterface;
549 if (PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e) < 0)
550 {
551 error = ERROR_INTERNAL_ERROR;
552 goto fail;
553 }
554 }
555
556 channels->drdynvc = (DrdynvcClientContext*)freerdp_channels_get_static_channel_interface(
557 channels, DRDYNVC_SVC_CHANNEL_NAME);
558
559 if (channels->drdynvc)
560 {
561 channels->drdynvc->custom = (void*)channels;
562 channels->drdynvc->OnChannelConnected = freerdp_drdynvc_on_channel_connected;
563 channels->drdynvc->OnChannelDisconnected = freerdp_drdynvc_on_channel_disconnected;
564 channels->drdynvc->OnChannelAttached = freerdp_drdynvc_on_channel_attached;
565 channels->drdynvc->OnChannelDetached = freerdp_drdynvc_on_channel_detached;
566 }
567
568fail:
569 return error;
570}
571
572BOOL freerdp_channels_data(freerdp* instance, UINT16 channelId, const BYTE* cdata, size_t dataSize,
573 UINT32 flags, size_t totalSize)
574{
575 rdpMcs* mcs = nullptr;
576 rdpChannels* channels = nullptr;
577 rdpMcsChannel* channel = nullptr;
578 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
579 union
580 {
581 const BYTE* pcb;
582 BYTE* pb;
583 } data;
584
585 data.pcb = cdata;
586 if (!instance || !data.pcb)
587 {
588 WLog_ERR(TAG, "(%p, %" PRIu16 ", %p, 0x%08x): Invalid arguments",
589 WINPR_CXX_COMPAT_CAST(const void*, instance), channelId,
590 WINPR_CXX_COMPAT_CAST(const void*, data.pcb), flags);
591 return FALSE;
592 }
593
594 mcs = instance->context->rdp->mcs;
595 channels = instance->context->channels;
596
597 if (!channels || !mcs)
598 {
599 return FALSE;
600 }
601
602 for (UINT32 index = 0; index < mcs->channelCount; index++)
603 {
604 rdpMcsChannel* cur = &mcs->channels[index];
605
606 if (cur->ChannelId == channelId)
607 {
608 channel = cur;
609 break;
610 }
611 }
612
613 if (!channel)
614 {
615 return FALSE;
616 }
617
618 pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, channel->Name);
619
620 if (!pChannelOpenData)
621 {
622 return FALSE;
623 }
624
625 if (pChannelOpenData->pChannelOpenEventProc)
626 {
627 pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle,
628 CHANNEL_EVENT_DATA_RECEIVED, data.pb,
629 (UINT32)dataSize, (UINT32)totalSize, flags);
630 }
631 else if (pChannelOpenData->pChannelOpenEventProcEx)
632 {
633 pChannelOpenData->pChannelOpenEventProcEx(
634 pChannelOpenData->lpUserParam, pChannelOpenData->OpenHandle,
635 CHANNEL_EVENT_DATA_RECEIVED, data.pb, (UINT32)dataSize, (UINT32)totalSize, flags);
636 }
637
638 return TRUE;
639}
640
641UINT16 freerdp_channels_get_id_by_name(freerdp* instance, const char* channel_name)
642{
643 if (!instance || !channel_name)
644 return 0;
645
646 rdpMcsChannel* mcsChannel =
647 freerdp_channels_find_channel_by_name(instance->context->rdp, channel_name);
648 if (!mcsChannel)
649 return 0;
650
651 return mcsChannel->ChannelId;
652}
653
654const char* freerdp_channels_get_name_by_id(freerdp* instance, UINT16 channelId)
655{
656 rdpMcsChannel* mcsChannel = nullptr;
657 if (!instance)
658 return nullptr;
659
660 mcsChannel = freerdp_channels_find_channel_by_id(instance->context->rdp, channelId);
661 if (!mcsChannel)
662 return nullptr;
663
664 return mcsChannel->Name;
665}
666
667BOOL freerdp_channels_process_message_free(wMessage* message, DWORD type)
668{
669 if (message->id == WMQ_QUIT)
670 {
671 return FALSE;
672 }
673
674 if (message->id == 0)
675 {
676 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
677 CHANNEL_OPEN_EVENT* item = (CHANNEL_OPEN_EVENT*)message->wParam;
678
679 if (!item)
680 return FALSE;
681
682 pChannelOpenData = item->pChannelOpenData;
683
684 if (pChannelOpenData->pChannelOpenEventProc)
685 {
686 pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, type,
687 item->UserData, item->DataLength,
688 item->DataLength, 0);
689 }
690 else if (pChannelOpenData->pChannelOpenEventProcEx)
691 {
692 pChannelOpenData->pChannelOpenEventProcEx(
693 pChannelOpenData->lpUserParam, pChannelOpenData->OpenHandle, type, item->UserData,
694 item->DataLength, item->DataLength, 0);
695 }
696 }
697
698 return TRUE;
699}
700
701static BOOL freerdp_channels_process_message(freerdp* instance, wMessage* message)
702{
703 BOOL ret = TRUE;
704 BOOL rc = FALSE;
705
706 WINPR_ASSERT(instance);
707 WINPR_ASSERT(message);
708
709 if (message->id == WMQ_QUIT)
710 goto fail;
711 else if (message->id == 0)
712 {
713 rdpMcsChannel* channel = nullptr;
714 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
715 CHANNEL_OPEN_EVENT* item = (CHANNEL_OPEN_EVENT*)message->wParam;
716
717 if (!item)
718 goto fail;
719
720 pChannelOpenData = item->pChannelOpenData;
721 if (pChannelOpenData->flags != 2)
722 {
723 freerdp_channels_process_message_free(message, CHANNEL_EVENT_WRITE_CANCELLED);
724 goto fail;
725 }
726 channel =
727 freerdp_channels_find_channel_by_name(instance->context->rdp, pChannelOpenData->name);
728
729 if (channel)
730 ret = instance->SendChannelData(instance, channel->ChannelId, item->Data,
731 item->DataLength);
732 }
733
734 if (!freerdp_channels_process_message_free(message, CHANNEL_EVENT_WRITE_COMPLETE))
735 goto fail;
736
737 rc = ret;
738
739fail:
740 IFCALL(message->Free, message);
741 return rc;
742}
743
747static BOOL freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance)
748{
749 BOOL status = TRUE;
750 wMessage message = WINPR_C_ARRAY_INIT;
751
752 WINPR_ASSERT(channels);
753
754 while (MessageQueue_Peek(channels->queue, &message, TRUE))
755 {
756 if (!freerdp_channels_process_message(instance, &message))
757 status = FALSE;
758 }
759
760 return status;
761}
762
766#if defined(WITH_FREERDP_DEPRECATED)
767BOOL freerdp_channels_get_fds(rdpChannels* channels, WINPR_ATTR_UNUSED freerdp* instance,
768 void** read_fds, int* read_count, WINPR_ATTR_UNUSED void** write_fds,
769 WINPR_ATTR_UNUSED int* write_count)
770{
771 void* pfd = nullptr;
772 pfd = GetEventWaitObject(MessageQueue_Event(channels->queue));
773
774 if (pfd)
775 {
776 read_fds[*read_count] = pfd;
777 (*read_count)++;
778 }
779
780 return TRUE;
781}
782#endif
783
784void* freerdp_channels_get_static_channel_interface(rdpChannels* channels, const char* name)
785{
786 void* pInterface = nullptr;
787 CHANNEL_OPEN_DATA* pChannelOpenData =
788 freerdp_channels_find_channel_open_data_by_name(channels, name);
789
790 if (pChannelOpenData)
791 pInterface = pChannelOpenData->pInterface;
792
793 return pInterface;
794}
795
796HANDLE freerdp_channels_get_event_handle(freerdp* instance)
797{
798 if (!instance)
799 return INVALID_HANDLE_VALUE;
800
801 WINPR_ASSERT(instance->context);
802
803 rdpChannels* channels = instance->context->channels;
804 WINPR_ASSERT(channels);
805
806 return MessageQueue_Event(channels->queue);
807}
808
809static BOOL channels_process(const void* key, void* value, void* arg)
810{
811 ChannelEventEntry* entry = value;
812 rdpContext* context = arg;
813
814 WINPR_UNUSED(key);
815
816 if (!entry->fkt)
817 return FALSE;
818 return entry->fkt(context, entry->userdata);
819}
820
821int freerdp_channels_process_pending_messages(freerdp* instance)
822{
823 if (!instance)
824 return -1;
825
826 WINPR_ASSERT(instance->context);
827
828 rdpChannels* channels = instance->context->channels;
829 WINPR_ASSERT(channels);
830
831 const DWORD status = WaitForSingleObject(MessageQueue_Event(channels->queue), 0);
832 if (status == WAIT_OBJECT_0)
833 {
834 if (!freerdp_channels_process_sync(channels, instance))
835 return -1;
836 }
837
838 if (!HashTable_Foreach(channels->channelEvents, channels_process, instance->context))
839 return -1;
840
841 return 1;
842}
843
847BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance)
848{
849 WINPR_ASSERT(channels);
850 WINPR_UNUSED(channels);
851
852 const int rc = freerdp_channels_process_pending_messages(instance);
853 return rc == 1;
854}
855
856BOOL freerdp_client_channel_register(rdpChannels* channels, HANDLE handle,
857 freerdp_channel_handle_fkt_t fkt, void* userdata)
858{
859 if (!channels || (handle == INVALID_HANDLE_VALUE) || !fkt)
860 {
861 WLog_ERR(TAG, "Invalid function arguments (channels=%p, handle=%p, fkt=%p, userdata=%p",
862 WINPR_FUNC_PTR_CAST(channels, const void*), handle,
863 WINPR_FUNC_PTR_CAST(fkt, const void*), userdata);
864 return FALSE;
865 }
866
867 ChannelEventEntry entry = { .fkt = fkt, .userdata = userdata };
868 return HashTable_Insert(channels->channelEvents, handle, &entry);
869}
870
871BOOL freerdp_client_channel_unregister(rdpChannels* channels, HANDLE handle)
872{
873 if (!channels || (handle == INVALID_HANDLE_VALUE))
874 {
875 WLog_ERR(TAG, "Invalid function arguments (channels=%p, handle=%p",
876 WINPR_CXX_COMPAT_CAST(const void*, channels), handle);
877 return FALSE;
878 }
879
880 return HashTable_Remove(channels->channelEvents, handle);
881}
882
883SSIZE_T freerdp_client_channel_get_registered_event_handles(rdpChannels* channels, HANDLE* events,
884 DWORD count)
885{
886 SSIZE_T rc = -1;
887
888 WINPR_ASSERT(channels);
889 WINPR_ASSERT(events || (count == 0));
890
891 HashTable_Lock(channels->channelEvents);
892 size_t len = HashTable_Count(channels->channelEvents);
893 if (len <= count)
894 {
895 ULONG_PTR* keys = nullptr;
896 const size_t nrKeys = HashTable_GetKeys(channels->channelEvents, &keys);
897 if ((nrKeys <= SSIZE_MAX) && (nrKeys == len))
898 {
899 for (size_t x = 0; x < nrKeys; x++)
900 {
901 HANDLE cur = (HANDLE)keys[x];
902 events[x] = cur;
903 }
904 rc = (SSIZE_T)nrKeys;
905 }
906 free(keys);
907 }
908 HashTable_Unlock(channels->channelEvents);
909 return rc;
910}
911
912UINT freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
913{
914 UINT error = CHANNEL_RC_OK;
915 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
916
917 WINPR_ASSERT(channels);
918
919 if (!channels->connected)
920 return 0;
921
922 freerdp_channels_check_fds(channels, instance);
923
924 /* tell all libraries we are shutting down */
925 for (int index = 0; index < channels->clientDataCount; index++)
926 {
927 ChannelDisconnectedEventArgs e = WINPR_C_ARRAY_INIT;
928 pChannelClientData = &channels->clientDataList[index];
929
930 if (pChannelClientData->pChannelInitEventProc)
931 {
932 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
933 CHANNEL_EVENT_DISCONNECTED, nullptr, 0);
934 }
935 else if (pChannelClientData->pChannelInitEventProcEx)
936 {
937 pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
938 pChannelClientData->pInitHandle,
939 CHANNEL_EVENT_DISCONNECTED, nullptr, 0);
940 }
941
942 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[index];
943 EventArgsInit(&e, "freerdp");
944 e.name = pChannelOpenData->name;
945 e.pInterface = pChannelOpenData->pInterface;
946 if (PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e) < 0)
947 error = ERROR_INTERNAL_ERROR;
948 }
949
950 channels->connected = FALSE;
951
952 /* Flush pending messages */
953 freerdp_channels_check_fds(channels, instance);
954 return error;
955}
956
957void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
958{
959 WINPR_ASSERT(channels);
960 WINPR_ASSERT(instance);
961
962 MessageQueue_PostQuit(channels->queue, 0);
963 freerdp_channels_check_fds(channels, instance);
964
965 /* tell all libraries we are shutting down */
966 for (int index = 0; index < channels->clientDataCount; index++)
967 {
968 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[index];
969
970 if (pChannelClientData->pChannelInitEventProc)
971 {
972 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
973 CHANNEL_EVENT_TERMINATED, nullptr, 0);
974 }
975 else if (pChannelClientData->pChannelInitEventProcEx)
976 {
977 pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
978 pChannelClientData->pInitHandle,
979 CHANNEL_EVENT_TERMINATED, nullptr, 0);
980 }
981
982 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[index];
983 CHANNEL_INIT_DATA* pChannelInitData = &channels->initDataList[index];
984 ChannelTerminatedEventArgs e = WINPR_C_ARRAY_INIT;
985 EventArgsInit(&e, "freerdp");
986 e.name = pChannelOpenData->name;
987 e.pInterface = pChannelInitData->pInterface;
988 if (PubSub_OnChannelTerminated(instance->context->pubSub, instance->context, &e) < 0)
989 {
990 WLog_WARN(TAG, "PubSub_OnChannelTerminated(%s) failed", pChannelOpenData->name);
991 }
992 }
993
994 for (int index = 0; index < channels->openDataCount; index++)
995 {
996 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[index];
997 HashTable_Remove(g_ChannelHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle);
998 }
999
1000 channels->openDataCount = 0;
1001 channels->initDataCount = 0;
1002 channels->clientDataCount = 0;
1003
1004 WINPR_ASSERT(instance->context);
1005 WINPR_ASSERT(instance->context->settings);
1006 instance->context->settings->ChannelCount = 0;
1007 g_Instance = nullptr;
1008}
1009
1010static UINT VCAPITYPE FreeRDP_VirtualChannelInitEx(
1011 LPVOID lpUserParam, LPVOID clientContext, LPVOID pInitHandle, PCHANNEL_DEF pChannel,
1012 INT channelCount, ULONG versionRequested, PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx)
1013{
1014 rdpSettings* settings = nullptr;
1015 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
1016
1017 if (!pInitHandle)
1018 return CHANNEL_RC_BAD_INIT_HANDLE;
1019
1020 if (!pChannel)
1021 return CHANNEL_RC_BAD_CHANNEL;
1022
1023 if ((channelCount <= 0) || !pChannelInitEventProcEx)
1024 return CHANNEL_RC_INITIALIZATION_ERROR;
1025
1026 CHANNEL_INIT_DATA* pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1027 WINPR_ASSERT(pChannelInitData);
1028
1029 rdpChannels* channels = pChannelInitData->channels;
1030 WINPR_ASSERT(channels);
1031
1032 if (!channels->can_call_init)
1033 return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
1034
1035 if ((channels->openDataCount + channelCount) > CHANNEL_MAX_COUNT)
1036 return CHANNEL_RC_TOO_MANY_CHANNELS;
1037
1038 if (channels->connected)
1039 return CHANNEL_RC_ALREADY_CONNECTED;
1040
1041 if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
1042 {
1043 }
1044
1045 for (int index = 0; index < channelCount; index++)
1046 {
1047 const PCHANNEL_DEF pChannelDef = &pChannel[index];
1048
1049 if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != nullptr)
1050 {
1051 return CHANNEL_RC_BAD_CHANNEL;
1052 }
1053 }
1054
1055 pChannelInitData->pInterface = clientContext;
1056 pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1057 pChannelClientData->pChannelInitEventProcEx = pChannelInitEventProcEx;
1058 pChannelClientData->pInitHandle = pInitHandle;
1059 pChannelClientData->lpUserParam = lpUserParam;
1060 channels->clientDataCount++;
1061
1062 WINPR_ASSERT(channels->instance);
1063 WINPR_ASSERT(channels->instance->context);
1064 settings = channels->instance->context->settings;
1065 WINPR_ASSERT(settings);
1066
1067 for (int index = 0; index < channelCount; index++)
1068 {
1069 const PCHANNEL_DEF pChannelDef = &pChannel[index];
1070 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[channels->openDataCount];
1071
1072 WINPR_ASSERT(pChannelOpenData);
1073
1074 const LONG hdl = InterlockedIncrement(&g_OpenHandleSeq);
1075 pChannelOpenData->OpenHandle = WINPR_ASSERTING_INT_CAST(uint32_t, hdl);
1076 pChannelOpenData->channels = channels;
1077 pChannelOpenData->lpUserParam = lpUserParam;
1078 if (!HashTable_Insert(g_ChannelHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle,
1079 (void*)pChannelOpenData))
1080 {
1081 pChannelInitData->pInterface = nullptr;
1082 return CHANNEL_RC_INITIALIZATION_ERROR;
1083 }
1084 pChannelOpenData->flags = 1; /* init */
1085 strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
1086 pChannelOpenData->options = pChannelDef->options;
1087
1088 const UINT32 max = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1089 WINPR_ASSERT(max >= CHANNEL_MAX_COUNT);
1090 if (settings->ChannelCount < max)
1091 {
1092 CHANNEL_DEF* channel = freerdp_settings_get_pointer_array_writable(
1093 settings, FreeRDP_ChannelDefArray, settings->ChannelCount);
1094 if (!channel)
1095 continue;
1096 strncpy(channel->name, pChannelDef->name, CHANNEL_NAME_LEN);
1097 channel->options = pChannelDef->options;
1098 settings->ChannelCount++;
1099 }
1100
1101 channels->openDataCount++;
1102 }
1103
1104 return CHANNEL_RC_OK;
1105}
1106
1107static UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, PCHANNEL_DEF pChannel,
1108 INT channelCount, ULONG versionRequested,
1109 PCHANNEL_INIT_EVENT_FN pChannelInitEventProc)
1110{
1111 CHANNEL_DEF* channel = nullptr;
1112 rdpSettings* settings = nullptr;
1113 PCHANNEL_DEF pChannelDef = nullptr;
1114 CHANNEL_INIT_DATA* pChannelInitData = nullptr;
1115 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
1116 rdpChannels* channels = nullptr;
1117
1118 /* g_Instance should have been set during freerdp_connect - otherwise VirtualChannelInit was
1119 * called from a different thread */
1120 if (!g_Instance || !g_Instance->context)
1121 return CHANNEL_RC_NOT_INITIALIZED;
1122
1123 channels = g_Instance->context->channels;
1124
1125 if (!ppInitHandle || !channels)
1126 return CHANNEL_RC_BAD_INIT_HANDLE;
1127
1128 if (!pChannel)
1129 return CHANNEL_RC_BAD_CHANNEL;
1130
1131 if ((channelCount <= 0) || !pChannelInitEventProc)
1132 return CHANNEL_RC_INITIALIZATION_ERROR;
1133
1134 pChannelInitData = &(channels->initDataList[channels->initDataCount]);
1135 *ppInitHandle = pChannelInitData;
1136 channels->initDataCount++;
1137 pChannelInitData->channels = channels;
1138 pChannelInitData->pInterface = nullptr;
1139
1140 if (!channels->can_call_init)
1141 return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
1142
1143 if (channels->openDataCount + channelCount > CHANNEL_MAX_COUNT)
1144 return CHANNEL_RC_TOO_MANY_CHANNELS;
1145
1146 if (channels->connected)
1147 return CHANNEL_RC_ALREADY_CONNECTED;
1148
1149 if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
1150 {
1151 }
1152
1153 for (int index = 0; index < channelCount; index++)
1154 {
1155 pChannelDef = &pChannel[index];
1156
1157 if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != nullptr)
1158 {
1159 return CHANNEL_RC_BAD_CHANNEL;
1160 }
1161 }
1162
1163 pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1164 pChannelClientData->pChannelInitEventProc = pChannelInitEventProc;
1165 pChannelClientData->pInitHandle = *ppInitHandle;
1166 channels->clientDataCount++;
1167 settings = channels->instance->context->settings;
1168
1169 for (int index = 0; index < channelCount; index++)
1170 {
1171 UINT32 ChannelCount = freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount);
1172
1173 pChannelDef = &pChannel[index];
1174
1175 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[channels->openDataCount];
1176
1177 const LONG hdl = InterlockedIncrement(&g_OpenHandleSeq);
1178 pChannelOpenData->OpenHandle = WINPR_ASSERTING_INT_CAST(uint32_t, hdl);
1179 pChannelOpenData->channels = channels;
1180 if (!HashTable_Insert(g_ChannelHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle,
1181 (void*)pChannelOpenData))
1182 return CHANNEL_RC_INITIALIZATION_ERROR;
1183 pChannelOpenData->flags = 1; /* init */
1184 strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
1185 pChannelOpenData->options = pChannelDef->options;
1186
1187 if (ChannelCount < CHANNEL_MAX_COUNT)
1188 {
1189 channel = freerdp_settings_get_pointer_array_writable(settings, FreeRDP_ChannelDefArray,
1190 ChannelCount++);
1191 strncpy(channel->name, pChannelDef->name, CHANNEL_NAME_LEN);
1192 channel->options = pChannelDef->options;
1193 if (!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, ChannelCount))
1194 return ERROR_INTERNAL_ERROR;
1195 }
1196
1197 channels->openDataCount++;
1198 }
1199
1200 return CHANNEL_RC_OK;
1201}
1202
1203static UINT VCAPITYPE
1204FreeRDP_VirtualChannelOpenEx(LPVOID pInitHandle, LPDWORD pOpenHandle, PCHAR pChannelName,
1205 PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx)
1206{
1207 CHANNEL_INIT_DATA* pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1208 rdpChannels* channels = pChannelInitData->channels;
1209 void* pInterface = pChannelInitData->pInterface;
1210
1211 if (!pOpenHandle)
1212 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1213
1214 if (!pChannelOpenEventProcEx)
1215 return CHANNEL_RC_BAD_PROC;
1216
1217 if (!channels->connected)
1218 return CHANNEL_RC_NOT_CONNECTED;
1219
1220 CHANNEL_OPEN_DATA* pChannelOpenData =
1221 freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
1222
1223 if (!pChannelOpenData)
1224 return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
1225
1226 if (pChannelOpenData->flags == 2)
1227 return CHANNEL_RC_ALREADY_OPEN;
1228
1229 pChannelOpenData->flags = 2; /* open */
1230 pChannelOpenData->pInterface = pInterface;
1231 pChannelOpenData->pChannelOpenEventProcEx = pChannelOpenEventProcEx;
1232 *pOpenHandle = pChannelOpenData->OpenHandle;
1233 return CHANNEL_RC_OK;
1234}
1235
1236static UINT VCAPITYPE FreeRDP_VirtualChannelOpen(LPVOID pInitHandle, LPDWORD pOpenHandle,
1237 PCHAR pChannelName,
1238 PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc)
1239{
1240 void* pInterface = nullptr;
1241 rdpChannels* channels = nullptr;
1242 CHANNEL_INIT_DATA* pChannelInitData = nullptr;
1243 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1244 pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1245 channels = pChannelInitData->channels;
1246 pInterface = pChannelInitData->pInterface;
1247
1248 if (!pOpenHandle)
1249 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1250
1251 if (!pChannelOpenEventProc)
1252 return CHANNEL_RC_BAD_PROC;
1253
1254 if (!channels->connected)
1255 return CHANNEL_RC_NOT_CONNECTED;
1256
1257 pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
1258
1259 if (!pChannelOpenData)
1260 return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
1261
1262 if (pChannelOpenData->flags == 2)
1263 return CHANNEL_RC_ALREADY_OPEN;
1264
1265 pChannelOpenData->flags = 2; /* open */
1266 pChannelOpenData->pInterface = pInterface;
1267 pChannelOpenData->pChannelOpenEventProc = pChannelOpenEventProc;
1268 *pOpenHandle = pChannelOpenData->OpenHandle;
1269 return CHANNEL_RC_OK;
1270}
1271
1272static UINT VCAPITYPE FreeRDP_VirtualChannelCloseEx(LPVOID pInitHandle, DWORD openHandle)
1273{
1274 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1275
1276 if (!pInitHandle)
1277 return CHANNEL_RC_BAD_INIT_HANDLE;
1278
1279 pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1280
1281 if (!pChannelOpenData)
1282 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1283
1284 if (pChannelOpenData->flags != 2)
1285 return CHANNEL_RC_NOT_OPEN;
1286
1287 pChannelOpenData->flags = 0;
1288 return CHANNEL_RC_OK;
1289}
1290
1291static UINT VCAPITYPE FreeRDP_VirtualChannelClose(DWORD openHandle)
1292{
1293 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1294
1295 pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1296
1297 if (!pChannelOpenData)
1298 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1299
1300 if (pChannelOpenData->flags != 2)
1301 return CHANNEL_RC_NOT_OPEN;
1302
1303 pChannelOpenData->flags = 0;
1304 return CHANNEL_RC_OK;
1305}
1306
1307static UINT VCAPITYPE FreeRDP_VirtualChannelWriteEx(LPVOID pInitHandle, DWORD openHandle,
1308 LPVOID pData, ULONG dataLength,
1309 LPVOID pUserData)
1310{
1311 rdpChannels* channels = nullptr;
1312 CHANNEL_INIT_DATA* pChannelInitData = nullptr;
1313 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1314 CHANNEL_OPEN_EVENT* pChannelOpenEvent = nullptr;
1315 wMessage message = WINPR_C_ARRAY_INIT;
1316
1317 if (!pInitHandle)
1318 return CHANNEL_RC_BAD_INIT_HANDLE;
1319
1320 pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1321 channels = pChannelInitData->channels;
1322
1323 if (!channels)
1324 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1325
1326 pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1327
1328 if (!pChannelOpenData)
1329 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1330
1331 if (!channels->connected)
1332 return CHANNEL_RC_NOT_CONNECTED;
1333
1334 if (!pData)
1335 return CHANNEL_RC_NULL_DATA;
1336
1337 if (!dataLength)
1338 return CHANNEL_RC_ZERO_LENGTH;
1339
1340 if (pChannelOpenData->flags != 2)
1341 return CHANNEL_RC_NOT_OPEN;
1342
1343 pChannelOpenEvent = (CHANNEL_OPEN_EVENT*)malloc(sizeof(CHANNEL_OPEN_EVENT));
1344
1345 if (!pChannelOpenEvent)
1346 return CHANNEL_RC_NO_MEMORY;
1347
1348 pChannelOpenEvent->Data = pData;
1349 pChannelOpenEvent->DataLength = dataLength;
1350 pChannelOpenEvent->UserData = pUserData;
1351 pChannelOpenEvent->pChannelOpenData = pChannelOpenData;
1352 message.context = channels;
1353 message.id = 0;
1354 message.wParam = pChannelOpenEvent;
1355 message.lParam = nullptr;
1356 message.Free = channel_queue_message_free;
1357
1358 if (!MessageQueue_Dispatch(channels->queue, &message))
1359 {
1360 free(pChannelOpenEvent);
1361 return CHANNEL_RC_NO_MEMORY;
1362 }
1363
1364 return CHANNEL_RC_OK;
1365}
1366
1367static UINT VCAPITYPE FreeRDP_VirtualChannelWrite(DWORD openHandle, LPVOID pData, ULONG dataLength,
1368 LPVOID pUserData)
1369{
1370 wMessage message = WINPR_C_ARRAY_INIT;
1371 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1372 CHANNEL_OPEN_EVENT* pChannelOpenEvent = nullptr;
1373 rdpChannels* channels = nullptr;
1374
1375 pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1376
1377 if (!pChannelOpenData)
1378 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1379
1380 channels = pChannelOpenData->channels;
1381 if (!channels)
1382 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1383
1384 if (!channels->connected)
1385 return CHANNEL_RC_NOT_CONNECTED;
1386
1387 if (!pData)
1388 return CHANNEL_RC_NULL_DATA;
1389
1390 if (!dataLength)
1391 return CHANNEL_RC_ZERO_LENGTH;
1392
1393 if (pChannelOpenData->flags != 2)
1394 return CHANNEL_RC_NOT_OPEN;
1395
1396 pChannelOpenEvent = (CHANNEL_OPEN_EVENT*)malloc(sizeof(CHANNEL_OPEN_EVENT));
1397
1398 if (!pChannelOpenEvent)
1399 return CHANNEL_RC_NO_MEMORY;
1400
1401 pChannelOpenEvent->Data = pData;
1402 pChannelOpenEvent->DataLength = dataLength;
1403 pChannelOpenEvent->UserData = pUserData;
1404 pChannelOpenEvent->pChannelOpenData = pChannelOpenData;
1405 message.context = channels;
1406 message.id = 0;
1407 message.wParam = pChannelOpenEvent;
1408 message.lParam = nullptr;
1409 message.Free = channel_queue_message_free;
1410
1411 if (!MessageQueue_Dispatch(channels->queue, &message))
1412 {
1413 free(pChannelOpenEvent);
1414 return CHANNEL_RC_NO_MEMORY;
1415 }
1416
1417 return CHANNEL_RC_OK;
1418}
1419
1420static BOOL freerdp_channels_is_loaded(rdpChannels* channels, PVIRTUALCHANNELENTRY entry)
1421{
1422 for (int i = 0; i < channels->clientDataCount; i++)
1423 {
1424 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[i];
1425
1426 if (pChannelClientData->entry == entry)
1427 return TRUE;
1428 }
1429
1430 return FALSE;
1431}
1432
1433static BOOL freerdp_channels_is_loaded_ex(rdpChannels* channels, PVIRTUALCHANNELENTRYEX entryEx)
1434{
1435 for (int i = 0; i < channels->clientDataCount; i++)
1436 {
1437 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[i];
1438
1439 if (pChannelClientData->entryEx == entryEx)
1440 return TRUE;
1441 }
1442
1443 return FALSE;
1444}
1445
1446int freerdp_channels_client_load(rdpChannels* channels, WINPR_ATTR_UNUSED rdpSettings* settings,
1447 PVIRTUALCHANNELENTRY entry, void* data)
1448{
1449 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
1450
1451 WINPR_ASSERT(channels);
1452 WINPR_ASSERT(channels->instance);
1453 WINPR_ASSERT(channels->instance->context);
1454 WINPR_ASSERT(entry);
1455
1456 if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT)
1457 {
1458 WLog_ERR(TAG, "error: too many channels");
1459 return 1;
1460 }
1461
1462 if (freerdp_channels_is_loaded(channels, entry))
1463 {
1464 WLog_WARN(TAG, "Skipping, channel already loaded");
1465 return 0;
1466 }
1467
1468 pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1469 pChannelClientData->entry = entry;
1470
1471 CHANNEL_ENTRY_POINTS_FREERDP EntryPoints = { .cbSize = sizeof(EntryPoints),
1472 .protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000,
1473 .pVirtualChannelInit = FreeRDP_VirtualChannelInit,
1474 .pVirtualChannelOpen = FreeRDP_VirtualChannelOpen,
1475 .pVirtualChannelClose =
1476 FreeRDP_VirtualChannelClose,
1477 .pVirtualChannelWrite =
1478 FreeRDP_VirtualChannelWrite,
1479 .MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER,
1480 .pExtendedData = data,
1481 .context = channels->instance->context };
1482 /* enable VirtualChannelInit */
1483 union
1484 {
1486 PCHANNEL_ENTRY_POINTS px;
1487 } ptr;
1488
1489 ptr.pfx = &EntryPoints;
1490
1491 channels->can_call_init = TRUE;
1492 EnterCriticalSection(&channels->channelsLock);
1493 const BOOL status = pChannelClientData->entry(ptr.px);
1494 LeaveCriticalSection(&channels->channelsLock);
1495 /* disable MyVirtualChannelInit */
1496 channels->can_call_init = FALSE;
1497
1498 if (!status)
1499 {
1500 WLog_ERR(TAG, "error: channel export function call failed");
1501 return 1;
1502 }
1503
1504 return 0;
1505}
1506
1507int freerdp_channels_client_load_ex(rdpChannels* channels, WINPR_ATTR_UNUSED rdpSettings* settings,
1508 PVIRTUALCHANNELENTRYEX entryEx, void* data)
1509{
1510 WINPR_ASSERT(channels);
1511 WINPR_ASSERT(channels->instance);
1512 WINPR_ASSERT(channels->instance->context);
1513 WINPR_ASSERT(entryEx);
1514
1515 if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT)
1516 {
1517 WLog_ERR(TAG, "error: too many channels");
1518 return 1;
1519 }
1520
1521 if (freerdp_channels_is_loaded_ex(channels, entryEx))
1522 {
1523 WLog_WARN(TAG, "Skipping, channel already loaded");
1524 return 0;
1525 }
1526
1527 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1528 pChannelClientData->entryEx = entryEx;
1529
1530 CHANNEL_INIT_DATA* pChannelInitData = &(channels->initDataList[channels->initDataCount++]);
1531 void* pInitHandle = pChannelInitData;
1532 pChannelInitData->channels = channels;
1533
1534 CHANNEL_ENTRY_POINTS_FREERDP_EX EntryPointsEx = {
1535 .cbSize = sizeof(EntryPointsEx),
1536 .protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000,
1537 .pVirtualChannelInitEx = FreeRDP_VirtualChannelInitEx,
1538 .pVirtualChannelOpenEx = FreeRDP_VirtualChannelOpenEx,
1539 .pVirtualChannelCloseEx = FreeRDP_VirtualChannelCloseEx,
1540 .pVirtualChannelWriteEx = FreeRDP_VirtualChannelWriteEx,
1541 .MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER,
1542 .pExtendedData = data,
1543 .context = channels->instance->context
1544 };
1545
1546 union
1547 {
1549 PCHANNEL_ENTRY_POINTS_EX px;
1550 } ptr;
1551
1552 ptr.pfx = &EntryPointsEx;
1553
1554 /* enable VirtualChannelInit */
1555 channels->can_call_init = TRUE;
1556 EnterCriticalSection(&channels->channelsLock);
1557 const BOOL status = pChannelClientData->entryEx(ptr.px, pInitHandle);
1558 LeaveCriticalSection(&channels->channelsLock);
1559 /* disable MyVirtualChannelInit */
1560 channels->can_call_init = FALSE;
1561
1562 if (!status)
1563 {
1564 WLog_ERR(TAG, "error: channel export function call failed");
1565 return 1;
1566 }
1567
1568 return 0;
1569}
1570
1575int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name,
1576 void* data)
1577{
1578 PVIRTUALCHANNELENTRY entry =
1579 freerdp_load_channel_addin_entry(name, nullptr, nullptr, FREERDP_ADDIN_CHANNEL_STATIC);
1580
1581 if (!entry)
1582 return 1;
1583
1584 return freerdp_channels_client_load(channels, settings, entry, data);
1585}
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
Definition svc.h:60
Definition svc.h:43
This struct contains function pointer to initialize/free objects.
Definition collections.h:52
OBJECT_FREE_FN fnObjectFree
Definition collections.h:59
WINPR_ATTR_NODISCARD OBJECT_NEW_FN fnObjectNew
Definition collections.h:54