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 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
329
330 MessageQueue_Clear(channels->queue);
331
332 for (int index = 0; index < channels->clientDataCount; index++)
333 {
334 pChannelClientData = &channels->clientDataList[index];
335
336 if (pChannelClientData->pChannelInitEventProc)
337 {
338 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
339 CHANNEL_EVENT_INITIALIZED, nullptr, 0);
340 }
341 else if (pChannelClientData->pChannelInitEventProcEx)
342 {
343 pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
344 pChannelClientData->pInitHandle,
345 CHANNEL_EVENT_INITIALIZED, nullptr, 0);
346 }
347
348 if (CHANNEL_RC_OK != getChannelError(instance->context))
349 break;
350 }
351
352 return error;
353}
354
355UINT freerdp_channels_attach(freerdp* instance)
356{
357 UINT error = CHANNEL_RC_OK;
358 const char* hostname = nullptr;
359 size_t hostnameLength = 0;
360 rdpChannels* channels = nullptr;
361 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
362
363 WINPR_ASSERT(instance);
364 WINPR_ASSERT(instance->context);
365 WINPR_ASSERT(instance->context->settings);
366
367 channels = instance->context->channels;
368 hostname = freerdp_settings_get_string(instance->context->settings, FreeRDP_ServerHostname);
369 WINPR_ASSERT(hostname);
370 hostnameLength = strnlen(hostname, MAX_PATH);
371
372 for (int index = 0; index < channels->clientDataCount; index++)
373 {
374 union
375 {
376 const void* cpv;
377 void* pv;
378 } cnv;
379 ChannelAttachedEventArgs e = WINPR_C_ARRAY_INIT;
380 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
381
382 cnv.cpv = hostname;
383 pChannelClientData = &channels->clientDataList[index];
384
385 if (pChannelClientData->pChannelInitEventProc)
386 {
387
388 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
389 CHANNEL_EVENT_ATTACHED, cnv.pv,
390 (UINT)hostnameLength);
391 }
392 else if (pChannelClientData->pChannelInitEventProcEx)
393 {
394 pChannelClientData->pChannelInitEventProcEx(
395 pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
396 CHANNEL_EVENT_ATTACHED, cnv.pv, (UINT)hostnameLength);
397 }
398
399 error = getChannelError(instance->context);
400 if (error != CHANNEL_RC_OK)
401 goto fail;
402
403 pChannelOpenData = &channels->openDataList[index];
404 EventArgsInit(&e, "freerdp");
405 e.name = pChannelOpenData->name;
406 e.pInterface = pChannelOpenData->pInterface;
407 if (PubSub_OnChannelAttached(instance->context->pubSub, instance->context, &e) < 0)
408 {
409 error = ERROR_INTERNAL_ERROR;
410 goto fail;
411 }
412 }
413
414fail:
415 return error;
416}
417
418UINT freerdp_channels_detach(freerdp* instance)
419{
420 UINT error = CHANNEL_RC_OK;
421 const char* hostname = nullptr;
422 size_t hostnameLength = 0;
423 rdpChannels* channels = nullptr;
424 rdpContext* context = nullptr;
425 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
426
427 WINPR_ASSERT(instance);
428
429 context = instance->context;
430 WINPR_ASSERT(context);
431
432 channels = context->channels;
433 WINPR_ASSERT(channels);
434
435 WINPR_ASSERT(context->settings);
436 hostname = freerdp_settings_get_string(context->settings, FreeRDP_ServerHostname);
437 WINPR_ASSERT(hostname);
438 hostnameLength = strnlen(hostname, MAX_PATH);
439
440 for (int index = 0; index < channels->clientDataCount; index++)
441 {
442 union
443 {
444 const void* cpv;
445 void* pv;
446 } cnv;
447
448 ChannelDetachedEventArgs e = WINPR_C_ARRAY_INIT;
449 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
450
451 cnv.cpv = hostname;
452 pChannelClientData = &channels->clientDataList[index];
453
454 if (pChannelClientData->pChannelInitEventProc)
455 {
456 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
457 CHANNEL_EVENT_DETACHED, cnv.pv,
458 (UINT)hostnameLength);
459 }
460 else if (pChannelClientData->pChannelInitEventProcEx)
461 {
462 pChannelClientData->pChannelInitEventProcEx(
463 pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
464 CHANNEL_EVENT_DETACHED, cnv.pv, (UINT)hostnameLength);
465 }
466
467 error = getChannelError(context);
468 if (error != CHANNEL_RC_OK)
469 goto fail;
470
471 pChannelOpenData = &channels->openDataList[index];
472 EventArgsInit(&e, "freerdp");
473 e.name = pChannelOpenData->name;
474 e.pInterface = pChannelOpenData->pInterface;
475 if (PubSub_OnChannelDetached(context->pubSub, context, &e) < 0)
476 {
477 error = ERROR_INTERNAL_ERROR;
478 goto fail;
479 }
480 }
481
482fail:
483 return error;
484}
485
491UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
492{
493 UINT error = CHANNEL_RC_OK;
494 const char* hostname = nullptr;
495 size_t hostnameLength = 0;
496 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
497
498 WINPR_ASSERT(channels);
499 WINPR_ASSERT(instance);
500 WINPR_ASSERT(instance->context);
501 WINPR_ASSERT(instance->context->settings);
502
503 channels->connected = TRUE;
504 hostname = freerdp_settings_get_string(instance->context->settings, FreeRDP_ServerHostname);
505 WINPR_ASSERT(hostname);
506 hostnameLength = strnlen(hostname, MAX_PATH);
507
508 for (int index = 0; index < channels->clientDataCount; index++)
509 {
510 union
511 {
512 const void* pcb;
513 void* pb;
514 } cnv;
515 ChannelConnectedEventArgs e = WINPR_C_ARRAY_INIT;
516 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
517 pChannelClientData = &channels->clientDataList[index];
518
519 cnv.pcb = hostname;
520 if (pChannelClientData->pChannelInitEventProc)
521 {
522 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
523 CHANNEL_EVENT_CONNECTED, cnv.pb,
524 (UINT)hostnameLength);
525 }
526 else if (pChannelClientData->pChannelInitEventProcEx)
527 {
528 pChannelClientData->pChannelInitEventProcEx(
529 pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
530 CHANNEL_EVENT_CONNECTED, cnv.pb, (UINT)hostnameLength);
531 }
532
533 error = getChannelError(instance->context);
534 if (error != CHANNEL_RC_OK)
535 goto fail;
536
537 pChannelOpenData = &channels->openDataList[index];
538 EventArgsInit(&e, "freerdp");
539 e.name = pChannelOpenData->name;
540 e.pInterface = pChannelOpenData->pInterface;
541 if (PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e) < 0)
542 {
543 error = ERROR_INTERNAL_ERROR;
544 goto fail;
545 }
546 }
547
548 channels->drdynvc = (DrdynvcClientContext*)freerdp_channels_get_static_channel_interface(
549 channels, DRDYNVC_SVC_CHANNEL_NAME);
550
551 if (channels->drdynvc)
552 {
553 channels->drdynvc->custom = (void*)channels;
554 channels->drdynvc->OnChannelConnected = freerdp_drdynvc_on_channel_connected;
555 channels->drdynvc->OnChannelDisconnected = freerdp_drdynvc_on_channel_disconnected;
556 channels->drdynvc->OnChannelAttached = freerdp_drdynvc_on_channel_attached;
557 channels->drdynvc->OnChannelDetached = freerdp_drdynvc_on_channel_detached;
558 }
559
560fail:
561 return error;
562}
563
564BOOL freerdp_channels_data(freerdp* instance, UINT16 channelId, const BYTE* cdata, size_t dataSize,
565 UINT32 flags, size_t totalSize)
566{
567 rdpMcs* mcs = nullptr;
568 rdpChannels* channels = nullptr;
569 rdpMcsChannel* channel = nullptr;
570 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
571 union
572 {
573 const BYTE* pcb;
574 BYTE* pb;
575 } data;
576
577 data.pcb = cdata;
578 if (!instance || !data.pcb)
579 {
580 WLog_ERR(TAG, "(%p, %" PRIu16 ", %p, 0x%08x): Invalid arguments",
581 WINPR_CXX_COMPAT_CAST(const void*, instance), channelId,
582 WINPR_CXX_COMPAT_CAST(const void*, data.pcb), flags);
583 return FALSE;
584 }
585
586 mcs = instance->context->rdp->mcs;
587 channels = instance->context->channels;
588
589 if (!channels || !mcs)
590 {
591 return FALSE;
592 }
593
594 for (UINT32 index = 0; index < mcs->channelCount; index++)
595 {
596 rdpMcsChannel* cur = &mcs->channels[index];
597
598 if (cur->ChannelId == channelId)
599 {
600 channel = cur;
601 break;
602 }
603 }
604
605 if (!channel)
606 {
607 return FALSE;
608 }
609
610 pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, channel->Name);
611
612 if (!pChannelOpenData)
613 {
614 return FALSE;
615 }
616
617 if (pChannelOpenData->pChannelOpenEventProc)
618 {
619 pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle,
620 CHANNEL_EVENT_DATA_RECEIVED, data.pb,
621 (UINT32)dataSize, (UINT32)totalSize, flags);
622 }
623 else if (pChannelOpenData->pChannelOpenEventProcEx)
624 {
625 pChannelOpenData->pChannelOpenEventProcEx(
626 pChannelOpenData->lpUserParam, pChannelOpenData->OpenHandle,
627 CHANNEL_EVENT_DATA_RECEIVED, data.pb, (UINT32)dataSize, (UINT32)totalSize, flags);
628 }
629
630 return TRUE;
631}
632
633UINT16 freerdp_channels_get_id_by_name(freerdp* instance, const char* channel_name)
634{
635 if (!instance || !channel_name)
636 return 0;
637
638 rdpMcsChannel* mcsChannel =
639 freerdp_channels_find_channel_by_name(instance->context->rdp, channel_name);
640 if (!mcsChannel)
641 return 0;
642
643 return mcsChannel->ChannelId;
644}
645
646const char* freerdp_channels_get_name_by_id(freerdp* instance, UINT16 channelId)
647{
648 rdpMcsChannel* mcsChannel = nullptr;
649 if (!instance)
650 return nullptr;
651
652 mcsChannel = freerdp_channels_find_channel_by_id(instance->context->rdp, channelId);
653 if (!mcsChannel)
654 return nullptr;
655
656 return mcsChannel->Name;
657}
658
659BOOL freerdp_channels_process_message_free(wMessage* message, DWORD type)
660{
661 if (message->id == WMQ_QUIT)
662 {
663 return FALSE;
664 }
665
666 if (message->id == 0)
667 {
668 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
669 CHANNEL_OPEN_EVENT* item = (CHANNEL_OPEN_EVENT*)message->wParam;
670
671 if (!item)
672 return FALSE;
673
674 pChannelOpenData = item->pChannelOpenData;
675
676 if (pChannelOpenData->pChannelOpenEventProc)
677 {
678 pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, type,
679 item->UserData, item->DataLength,
680 item->DataLength, 0);
681 }
682 else if (pChannelOpenData->pChannelOpenEventProcEx)
683 {
684 pChannelOpenData->pChannelOpenEventProcEx(
685 pChannelOpenData->lpUserParam, pChannelOpenData->OpenHandle, type, item->UserData,
686 item->DataLength, item->DataLength, 0);
687 }
688 }
689
690 return TRUE;
691}
692
693static BOOL freerdp_channels_process_message(freerdp* instance, wMessage* message)
694{
695 BOOL ret = TRUE;
696 BOOL rc = FALSE;
697
698 WINPR_ASSERT(instance);
699 WINPR_ASSERT(message);
700
701 if (message->id == WMQ_QUIT)
702 goto fail;
703 else if (message->id == 0)
704 {
705 rdpMcsChannel* channel = nullptr;
706 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
707 CHANNEL_OPEN_EVENT* item = (CHANNEL_OPEN_EVENT*)message->wParam;
708
709 if (!item)
710 goto fail;
711
712 pChannelOpenData = item->pChannelOpenData;
713 if (pChannelOpenData->flags != 2)
714 {
715 freerdp_channels_process_message_free(message, CHANNEL_EVENT_WRITE_CANCELLED);
716 goto fail;
717 }
718 channel =
719 freerdp_channels_find_channel_by_name(instance->context->rdp, pChannelOpenData->name);
720
721 if (channel)
722 ret = instance->SendChannelData(instance, channel->ChannelId, item->Data,
723 item->DataLength);
724 }
725
726 if (!freerdp_channels_process_message_free(message, CHANNEL_EVENT_WRITE_COMPLETE))
727 goto fail;
728
729 rc = ret;
730
731fail:
732 IFCALL(message->Free, message);
733 return rc;
734}
735
739static BOOL freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance)
740{
741 BOOL status = TRUE;
742 wMessage message = WINPR_C_ARRAY_INIT;
743
744 WINPR_ASSERT(channels);
745
746 while (MessageQueue_Peek(channels->queue, &message, TRUE))
747 {
748 if (!freerdp_channels_process_message(instance, &message))
749 status = FALSE;
750 }
751
752 return status;
753}
754
758#if defined(WITH_FREERDP_DEPRECATED)
759BOOL freerdp_channels_get_fds(rdpChannels* channels, WINPR_ATTR_UNUSED freerdp* instance,
760 void** read_fds, int* read_count, WINPR_ATTR_UNUSED void** write_fds,
761 WINPR_ATTR_UNUSED int* write_count)
762{
763 void* pfd = nullptr;
764 pfd = GetEventWaitObject(MessageQueue_Event(channels->queue));
765
766 if (pfd)
767 {
768 read_fds[*read_count] = pfd;
769 (*read_count)++;
770 }
771
772 return TRUE;
773}
774#endif
775
776void* freerdp_channels_get_static_channel_interface(rdpChannels* channels, const char* name)
777{
778 void* pInterface = nullptr;
779 CHANNEL_OPEN_DATA* pChannelOpenData =
780 freerdp_channels_find_channel_open_data_by_name(channels, name);
781
782 if (pChannelOpenData)
783 pInterface = pChannelOpenData->pInterface;
784
785 return pInterface;
786}
787
788HANDLE freerdp_channels_get_event_handle(freerdp* instance)
789{
790 if (!instance)
791 return INVALID_HANDLE_VALUE;
792
793 WINPR_ASSERT(instance->context);
794
795 rdpChannels* channels = instance->context->channels;
796 WINPR_ASSERT(channels);
797
798 return MessageQueue_Event(channels->queue);
799}
800
801static BOOL channels_process(const void* key, void* value, void* arg)
802{
803 ChannelEventEntry* entry = value;
804 rdpContext* context = arg;
805
806 WINPR_UNUSED(key);
807
808 if (!entry->fkt)
809 return FALSE;
810 return entry->fkt(context, entry->userdata);
811}
812
813int freerdp_channels_process_pending_messages(freerdp* instance)
814{
815 if (!instance)
816 return -1;
817
818 WINPR_ASSERT(instance->context);
819
820 rdpChannels* channels = instance->context->channels;
821 WINPR_ASSERT(channels);
822
823 const DWORD status = WaitForSingleObject(MessageQueue_Event(channels->queue), 0);
824 if (status == WAIT_OBJECT_0)
825 {
826 if (!freerdp_channels_process_sync(channels, instance))
827 return -1;
828 }
829
830 if (!HashTable_Foreach(channels->channelEvents, channels_process, instance->context))
831 return -1;
832
833 return 1;
834}
835
839BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance)
840{
841 WINPR_ASSERT(channels);
842 WINPR_UNUSED(channels);
843
844 const int rc = freerdp_channels_process_pending_messages(instance);
845 return rc == 1;
846}
847
848BOOL freerdp_client_channel_register(rdpChannels* channels, HANDLE handle,
849 freerdp_channel_handle_fkt_t fkt, void* userdata)
850{
851 if (!channels || (handle == INVALID_HANDLE_VALUE) || !fkt)
852 {
853 WLog_ERR(TAG, "Invalid function arguments (channels=%p, handle=%p, fkt=%p, userdata=%p",
854 WINPR_FUNC_PTR_CAST(channels, const void*), handle,
855 WINPR_FUNC_PTR_CAST(fkt, const void*), userdata);
856 return FALSE;
857 }
858
859 ChannelEventEntry entry = { .fkt = fkt, .userdata = userdata };
860 return HashTable_Insert(channels->channelEvents, handle, &entry);
861}
862
863BOOL freerdp_client_channel_unregister(rdpChannels* channels, HANDLE handle)
864{
865 if (!channels || (handle == INVALID_HANDLE_VALUE))
866 {
867 WLog_ERR(TAG, "Invalid function arguments (channels=%p, handle=%p",
868 WINPR_CXX_COMPAT_CAST(const void*, channels), handle);
869 return FALSE;
870 }
871
872 return HashTable_Remove(channels->channelEvents, handle);
873}
874
875SSIZE_T freerdp_client_channel_get_registered_event_handles(rdpChannels* channels, HANDLE* events,
876 DWORD count)
877{
878 SSIZE_T rc = -1;
879
880 WINPR_ASSERT(channels);
881 WINPR_ASSERT(events || (count == 0));
882
883 HashTable_Lock(channels->channelEvents);
884 size_t len = HashTable_Count(channels->channelEvents);
885 if (len <= count)
886 {
887 ULONG_PTR* keys = nullptr;
888 const size_t nrKeys = HashTable_GetKeys(channels->channelEvents, &keys);
889 if ((nrKeys <= SSIZE_MAX) && (nrKeys == len))
890 {
891 for (size_t x = 0; x < nrKeys; x++)
892 {
893 HANDLE cur = (HANDLE)keys[x];
894 events[x] = cur;
895 }
896 rc = (SSIZE_T)nrKeys;
897 }
898 free(keys);
899 }
900 HashTable_Unlock(channels->channelEvents);
901 return rc;
902}
903
904UINT freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
905{
906 UINT error = CHANNEL_RC_OK;
907 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
908 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
909
910 WINPR_ASSERT(channels);
911
912 if (!channels->connected)
913 return 0;
914
915 freerdp_channels_check_fds(channels, instance);
916
917 /* tell all libraries we are shutting down */
918 for (int index = 0; index < channels->clientDataCount; index++)
919 {
920 ChannelDisconnectedEventArgs e = WINPR_C_ARRAY_INIT;
921 pChannelClientData = &channels->clientDataList[index];
922
923 if (pChannelClientData->pChannelInitEventProc)
924 {
925 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
926 CHANNEL_EVENT_DISCONNECTED, nullptr, 0);
927 }
928 else if (pChannelClientData->pChannelInitEventProcEx)
929 {
930 pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
931 pChannelClientData->pInitHandle,
932 CHANNEL_EVENT_DISCONNECTED, nullptr, 0);
933 }
934
935 pChannelOpenData = &channels->openDataList[index];
936 EventArgsInit(&e, "freerdp");
937 e.name = pChannelOpenData->name;
938 e.pInterface = pChannelOpenData->pInterface;
939 if (PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e) < 0)
940 error = ERROR_INTERNAL_ERROR;
941 }
942
943 channels->connected = FALSE;
944
945 /* Flush pending messages */
946 freerdp_channels_check_fds(channels, instance);
947 return error;
948}
949
950void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
951{
952 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
953 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
954
955 WINPR_ASSERT(channels);
956 WINPR_ASSERT(instance);
957
958 MessageQueue_PostQuit(channels->queue, 0);
959 freerdp_channels_check_fds(channels, instance);
960
961 /* tell all libraries we are shutting down */
962 for (int index = 0; index < channels->clientDataCount; index++)
963 {
964 pChannelClientData = &channels->clientDataList[index];
965
966 if (pChannelClientData->pChannelInitEventProc)
967 {
968 pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
969 CHANNEL_EVENT_TERMINATED, nullptr, 0);
970 }
971 else if (pChannelClientData->pChannelInitEventProcEx)
972 {
973 pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
974 pChannelClientData->pInitHandle,
975 CHANNEL_EVENT_TERMINATED, nullptr, 0);
976 }
977 }
978
979 for (int index = 0; index < channels->openDataCount; index++)
980 {
981 pChannelOpenData = &channels->openDataList[index];
982 HashTable_Remove(g_ChannelHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle);
983 }
984
985 channels->openDataCount = 0;
986 channels->initDataCount = 0;
987 channels->clientDataCount = 0;
988
989 WINPR_ASSERT(instance->context);
990 WINPR_ASSERT(instance->context->settings);
991 instance->context->settings->ChannelCount = 0;
992 g_Instance = nullptr;
993}
994
995static UINT VCAPITYPE FreeRDP_VirtualChannelInitEx(
996 LPVOID lpUserParam, LPVOID clientContext, LPVOID pInitHandle, PCHANNEL_DEF pChannel,
997 INT channelCount, ULONG versionRequested, PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx)
998{
999 rdpSettings* settings = nullptr;
1000 CHANNEL_INIT_DATA* pChannelInitData = nullptr;
1001 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
1002 rdpChannels* channels = nullptr;
1003
1004 if (!pInitHandle)
1005 return CHANNEL_RC_BAD_INIT_HANDLE;
1006
1007 if (!pChannel)
1008 return CHANNEL_RC_BAD_CHANNEL;
1009
1010 if ((channelCount <= 0) || !pChannelInitEventProcEx)
1011 return CHANNEL_RC_INITIALIZATION_ERROR;
1012
1013 pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1014 WINPR_ASSERT(pChannelInitData);
1015
1016 channels = pChannelInitData->channels;
1017 WINPR_ASSERT(channels);
1018
1019 if (!channels->can_call_init)
1020 return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
1021
1022 if ((channels->openDataCount + channelCount) > CHANNEL_MAX_COUNT)
1023 return CHANNEL_RC_TOO_MANY_CHANNELS;
1024
1025 if (channels->connected)
1026 return CHANNEL_RC_ALREADY_CONNECTED;
1027
1028 if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
1029 {
1030 }
1031
1032 for (int index = 0; index < channelCount; index++)
1033 {
1034 const PCHANNEL_DEF pChannelDef = &pChannel[index];
1035
1036 if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != nullptr)
1037 {
1038 return CHANNEL_RC_BAD_CHANNEL;
1039 }
1040 }
1041
1042 pChannelInitData->pInterface = clientContext;
1043 pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1044 pChannelClientData->pChannelInitEventProcEx = pChannelInitEventProcEx;
1045 pChannelClientData->pInitHandle = pInitHandle;
1046 pChannelClientData->lpUserParam = lpUserParam;
1047 channels->clientDataCount++;
1048
1049 WINPR_ASSERT(channels->instance);
1050 WINPR_ASSERT(channels->instance->context);
1051 settings = channels->instance->context->settings;
1052 WINPR_ASSERT(settings);
1053
1054 for (int index = 0; index < channelCount; index++)
1055 {
1056 const PCHANNEL_DEF pChannelDef = &pChannel[index];
1057 CHANNEL_OPEN_DATA* pChannelOpenData = &channels->openDataList[channels->openDataCount];
1058
1059 WINPR_ASSERT(pChannelOpenData);
1060
1061 const LONG hdl = InterlockedIncrement(&g_OpenHandleSeq);
1062 pChannelOpenData->OpenHandle = WINPR_ASSERTING_INT_CAST(uint32_t, hdl);
1063 pChannelOpenData->channels = channels;
1064 pChannelOpenData->lpUserParam = lpUserParam;
1065 if (!HashTable_Insert(g_ChannelHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle,
1066 (void*)pChannelOpenData))
1067 {
1068 pChannelInitData->pInterface = nullptr;
1069 return CHANNEL_RC_INITIALIZATION_ERROR;
1070 }
1071 pChannelOpenData->flags = 1; /* init */
1072 strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
1073 pChannelOpenData->options = pChannelDef->options;
1074
1075 const UINT32 max = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1076 WINPR_ASSERT(max >= CHANNEL_MAX_COUNT);
1077 if (settings->ChannelCount < max)
1078 {
1079 CHANNEL_DEF* channel = freerdp_settings_get_pointer_array_writable(
1080 settings, FreeRDP_ChannelDefArray, settings->ChannelCount);
1081 if (!channel)
1082 continue;
1083 strncpy(channel->name, pChannelDef->name, CHANNEL_NAME_LEN);
1084 channel->options = pChannelDef->options;
1085 settings->ChannelCount++;
1086 }
1087
1088 channels->openDataCount++;
1089 }
1090
1091 return CHANNEL_RC_OK;
1092}
1093
1094static UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, PCHANNEL_DEF pChannel,
1095 INT channelCount, ULONG versionRequested,
1096 PCHANNEL_INIT_EVENT_FN pChannelInitEventProc)
1097{
1098 CHANNEL_DEF* channel = nullptr;
1099 rdpSettings* settings = nullptr;
1100 PCHANNEL_DEF pChannelDef = nullptr;
1101 CHANNEL_INIT_DATA* pChannelInitData = nullptr;
1102 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1103 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
1104 rdpChannels* channels = nullptr;
1105
1106 /* g_Instance should have been set during freerdp_connect - otherwise VirtualChannelInit was
1107 * called from a different thread */
1108 if (!g_Instance || !g_Instance->context)
1109 return CHANNEL_RC_NOT_INITIALIZED;
1110
1111 channels = g_Instance->context->channels;
1112
1113 if (!ppInitHandle || !channels)
1114 return CHANNEL_RC_BAD_INIT_HANDLE;
1115
1116 if (!pChannel)
1117 return CHANNEL_RC_BAD_CHANNEL;
1118
1119 if ((channelCount <= 0) || !pChannelInitEventProc)
1120 return CHANNEL_RC_INITIALIZATION_ERROR;
1121
1122 pChannelInitData = &(channels->initDataList[channels->initDataCount]);
1123 *ppInitHandle = pChannelInitData;
1124 channels->initDataCount++;
1125 pChannelInitData->channels = channels;
1126 pChannelInitData->pInterface = nullptr;
1127
1128 if (!channels->can_call_init)
1129 return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
1130
1131 if (channels->openDataCount + channelCount > CHANNEL_MAX_COUNT)
1132 return CHANNEL_RC_TOO_MANY_CHANNELS;
1133
1134 if (channels->connected)
1135 return CHANNEL_RC_ALREADY_CONNECTED;
1136
1137 if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
1138 {
1139 }
1140
1141 for (int index = 0; index < channelCount; index++)
1142 {
1143 pChannelDef = &pChannel[index];
1144
1145 if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != nullptr)
1146 {
1147 return CHANNEL_RC_BAD_CHANNEL;
1148 }
1149 }
1150
1151 pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1152 pChannelClientData->pChannelInitEventProc = pChannelInitEventProc;
1153 pChannelClientData->pInitHandle = *ppInitHandle;
1154 channels->clientDataCount++;
1155 settings = channels->instance->context->settings;
1156
1157 for (int index = 0; index < channelCount; index++)
1158 {
1159 UINT32 ChannelCount = freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount);
1160
1161 pChannelDef = &pChannel[index];
1162
1163 pChannelOpenData = &channels->openDataList[channels->openDataCount];
1164
1165 const LONG hdl = InterlockedIncrement(&g_OpenHandleSeq);
1166 pChannelOpenData->OpenHandle = WINPR_ASSERTING_INT_CAST(uint32_t, hdl);
1167 pChannelOpenData->channels = channels;
1168 if (!HashTable_Insert(g_ChannelHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle,
1169 (void*)pChannelOpenData))
1170 return CHANNEL_RC_INITIALIZATION_ERROR;
1171 pChannelOpenData->flags = 1; /* init */
1172 strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
1173 pChannelOpenData->options = pChannelDef->options;
1174
1175 if (ChannelCount < CHANNEL_MAX_COUNT)
1176 {
1177 channel = freerdp_settings_get_pointer_array_writable(settings, FreeRDP_ChannelDefArray,
1178 ChannelCount++);
1179 strncpy(channel->name, pChannelDef->name, CHANNEL_NAME_LEN);
1180 channel->options = pChannelDef->options;
1181 if (!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, ChannelCount))
1182 return ERROR_INTERNAL_ERROR;
1183 }
1184
1185 channels->openDataCount++;
1186 }
1187
1188 return CHANNEL_RC_OK;
1189}
1190
1191static UINT VCAPITYPE
1192FreeRDP_VirtualChannelOpenEx(LPVOID pInitHandle, LPDWORD pOpenHandle, PCHAR pChannelName,
1193 PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx)
1194{
1195 void* pInterface = nullptr;
1196 rdpChannels* channels = nullptr;
1197 CHANNEL_INIT_DATA* pChannelInitData = nullptr;
1198 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1199 pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1200 channels = pChannelInitData->channels;
1201 pInterface = pChannelInitData->pInterface;
1202
1203 if (!pOpenHandle)
1204 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1205
1206 if (!pChannelOpenEventProcEx)
1207 return CHANNEL_RC_BAD_PROC;
1208
1209 if (!channels->connected)
1210 return CHANNEL_RC_NOT_CONNECTED;
1211
1212 pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
1213
1214 if (!pChannelOpenData)
1215 return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
1216
1217 if (pChannelOpenData->flags == 2)
1218 return CHANNEL_RC_ALREADY_OPEN;
1219
1220 pChannelOpenData->flags = 2; /* open */
1221 pChannelOpenData->pInterface = pInterface;
1222 pChannelOpenData->pChannelOpenEventProcEx = pChannelOpenEventProcEx;
1223 *pOpenHandle = pChannelOpenData->OpenHandle;
1224 return CHANNEL_RC_OK;
1225}
1226
1227static UINT VCAPITYPE FreeRDP_VirtualChannelOpen(LPVOID pInitHandle, LPDWORD pOpenHandle,
1228 PCHAR pChannelName,
1229 PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc)
1230{
1231 void* pInterface = nullptr;
1232 rdpChannels* channels = nullptr;
1233 CHANNEL_INIT_DATA* pChannelInitData = nullptr;
1234 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1235 pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1236 channels = pChannelInitData->channels;
1237 pInterface = pChannelInitData->pInterface;
1238
1239 if (!pOpenHandle)
1240 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1241
1242 if (!pChannelOpenEventProc)
1243 return CHANNEL_RC_BAD_PROC;
1244
1245 if (!channels->connected)
1246 return CHANNEL_RC_NOT_CONNECTED;
1247
1248 pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
1249
1250 if (!pChannelOpenData)
1251 return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
1252
1253 if (pChannelOpenData->flags == 2)
1254 return CHANNEL_RC_ALREADY_OPEN;
1255
1256 pChannelOpenData->flags = 2; /* open */
1257 pChannelOpenData->pInterface = pInterface;
1258 pChannelOpenData->pChannelOpenEventProc = pChannelOpenEventProc;
1259 *pOpenHandle = pChannelOpenData->OpenHandle;
1260 return CHANNEL_RC_OK;
1261}
1262
1263static UINT VCAPITYPE FreeRDP_VirtualChannelCloseEx(LPVOID pInitHandle, DWORD openHandle)
1264{
1265 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1266
1267 if (!pInitHandle)
1268 return CHANNEL_RC_BAD_INIT_HANDLE;
1269
1270 pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1271
1272 if (!pChannelOpenData)
1273 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1274
1275 if (pChannelOpenData->flags != 2)
1276 return CHANNEL_RC_NOT_OPEN;
1277
1278 pChannelOpenData->flags = 0;
1279 return CHANNEL_RC_OK;
1280}
1281
1282static UINT VCAPITYPE FreeRDP_VirtualChannelClose(DWORD openHandle)
1283{
1284 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1285
1286 pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1287
1288 if (!pChannelOpenData)
1289 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1290
1291 if (pChannelOpenData->flags != 2)
1292 return CHANNEL_RC_NOT_OPEN;
1293
1294 pChannelOpenData->flags = 0;
1295 return CHANNEL_RC_OK;
1296}
1297
1298static UINT VCAPITYPE FreeRDP_VirtualChannelWriteEx(LPVOID pInitHandle, DWORD openHandle,
1299 LPVOID pData, ULONG dataLength,
1300 LPVOID pUserData)
1301{
1302 rdpChannels* channels = nullptr;
1303 CHANNEL_INIT_DATA* pChannelInitData = nullptr;
1304 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1305 CHANNEL_OPEN_EVENT* pChannelOpenEvent = nullptr;
1306 wMessage message = WINPR_C_ARRAY_INIT;
1307
1308 if (!pInitHandle)
1309 return CHANNEL_RC_BAD_INIT_HANDLE;
1310
1311 pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1312 channels = pChannelInitData->channels;
1313
1314 if (!channels)
1315 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1316
1317 pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1318
1319 if (!pChannelOpenData)
1320 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1321
1322 if (!channels->connected)
1323 return CHANNEL_RC_NOT_CONNECTED;
1324
1325 if (!pData)
1326 return CHANNEL_RC_NULL_DATA;
1327
1328 if (!dataLength)
1329 return CHANNEL_RC_ZERO_LENGTH;
1330
1331 if (pChannelOpenData->flags != 2)
1332 return CHANNEL_RC_NOT_OPEN;
1333
1334 pChannelOpenEvent = (CHANNEL_OPEN_EVENT*)malloc(sizeof(CHANNEL_OPEN_EVENT));
1335
1336 if (!pChannelOpenEvent)
1337 return CHANNEL_RC_NO_MEMORY;
1338
1339 pChannelOpenEvent->Data = pData;
1340 pChannelOpenEvent->DataLength = dataLength;
1341 pChannelOpenEvent->UserData = pUserData;
1342 pChannelOpenEvent->pChannelOpenData = pChannelOpenData;
1343 message.context = channels;
1344 message.id = 0;
1345 message.wParam = pChannelOpenEvent;
1346 message.lParam = nullptr;
1347 message.Free = channel_queue_message_free;
1348
1349 if (!MessageQueue_Dispatch(channels->queue, &message))
1350 {
1351 free(pChannelOpenEvent);
1352 return CHANNEL_RC_NO_MEMORY;
1353 }
1354
1355 return CHANNEL_RC_OK;
1356}
1357
1358static UINT VCAPITYPE FreeRDP_VirtualChannelWrite(DWORD openHandle, LPVOID pData, ULONG dataLength,
1359 LPVOID pUserData)
1360{
1361 wMessage message = WINPR_C_ARRAY_INIT;
1362 CHANNEL_OPEN_DATA* pChannelOpenData = nullptr;
1363 CHANNEL_OPEN_EVENT* pChannelOpenEvent = nullptr;
1364 rdpChannels* channels = nullptr;
1365
1366 pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1367
1368 if (!pChannelOpenData)
1369 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1370
1371 channels = pChannelOpenData->channels;
1372 if (!channels)
1373 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1374
1375 if (!channels->connected)
1376 return CHANNEL_RC_NOT_CONNECTED;
1377
1378 if (!pData)
1379 return CHANNEL_RC_NULL_DATA;
1380
1381 if (!dataLength)
1382 return CHANNEL_RC_ZERO_LENGTH;
1383
1384 if (pChannelOpenData->flags != 2)
1385 return CHANNEL_RC_NOT_OPEN;
1386
1387 pChannelOpenEvent = (CHANNEL_OPEN_EVENT*)malloc(sizeof(CHANNEL_OPEN_EVENT));
1388
1389 if (!pChannelOpenEvent)
1390 return CHANNEL_RC_NO_MEMORY;
1391
1392 pChannelOpenEvent->Data = pData;
1393 pChannelOpenEvent->DataLength = dataLength;
1394 pChannelOpenEvent->UserData = pUserData;
1395 pChannelOpenEvent->pChannelOpenData = pChannelOpenData;
1396 message.context = channels;
1397 message.id = 0;
1398 message.wParam = pChannelOpenEvent;
1399 message.lParam = nullptr;
1400 message.Free = channel_queue_message_free;
1401
1402 if (!MessageQueue_Dispatch(channels->queue, &message))
1403 {
1404 free(pChannelOpenEvent);
1405 return CHANNEL_RC_NO_MEMORY;
1406 }
1407
1408 return CHANNEL_RC_OK;
1409}
1410
1411static BOOL freerdp_channels_is_loaded(rdpChannels* channels, PVIRTUALCHANNELENTRY entry)
1412{
1413 for (int i = 0; i < channels->clientDataCount; i++)
1414 {
1415 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[i];
1416
1417 if (pChannelClientData->entry == entry)
1418 return TRUE;
1419 }
1420
1421 return FALSE;
1422}
1423
1424static BOOL freerdp_channels_is_loaded_ex(rdpChannels* channels, PVIRTUALCHANNELENTRYEX entryEx)
1425{
1426 for (int i = 0; i < channels->clientDataCount; i++)
1427 {
1428 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[i];
1429
1430 if (pChannelClientData->entryEx == entryEx)
1431 return TRUE;
1432 }
1433
1434 return FALSE;
1435}
1436
1437int freerdp_channels_client_load(rdpChannels* channels, WINPR_ATTR_UNUSED rdpSettings* settings,
1438 PVIRTUALCHANNELENTRY entry, void* data)
1439{
1440 CHANNEL_CLIENT_DATA* pChannelClientData = nullptr;
1441
1442 WINPR_ASSERT(channels);
1443 WINPR_ASSERT(channels->instance);
1444 WINPR_ASSERT(channels->instance->context);
1445 WINPR_ASSERT(entry);
1446
1447 if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT)
1448 {
1449 WLog_ERR(TAG, "error: too many channels");
1450 return 1;
1451 }
1452
1453 if (freerdp_channels_is_loaded(channels, entry))
1454 {
1455 WLog_WARN(TAG, "Skipping, channel already loaded");
1456 return 0;
1457 }
1458
1459 pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1460 pChannelClientData->entry = entry;
1461
1462 CHANNEL_ENTRY_POINTS_FREERDP EntryPoints = { .cbSize = sizeof(EntryPoints),
1463 .protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000,
1464 .pVirtualChannelInit = FreeRDP_VirtualChannelInit,
1465 .pVirtualChannelOpen = FreeRDP_VirtualChannelOpen,
1466 .pVirtualChannelClose =
1467 FreeRDP_VirtualChannelClose,
1468 .pVirtualChannelWrite =
1469 FreeRDP_VirtualChannelWrite,
1470 .MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER,
1471 .pExtendedData = data,
1472 .context = channels->instance->context };
1473 /* enable VirtualChannelInit */
1474 union
1475 {
1477 PCHANNEL_ENTRY_POINTS px;
1478 } ptr;
1479
1480 ptr.pfx = &EntryPoints;
1481
1482 channels->can_call_init = TRUE;
1483 EnterCriticalSection(&channels->channelsLock);
1484 const BOOL status = pChannelClientData->entry(ptr.px);
1485 LeaveCriticalSection(&channels->channelsLock);
1486 /* disable MyVirtualChannelInit */
1487 channels->can_call_init = FALSE;
1488
1489 if (!status)
1490 {
1491 WLog_ERR(TAG, "error: channel export function call failed");
1492 return 1;
1493 }
1494
1495 return 0;
1496}
1497
1498int freerdp_channels_client_load_ex(rdpChannels* channels, WINPR_ATTR_UNUSED rdpSettings* settings,
1499 PVIRTUALCHANNELENTRYEX entryEx, void* data)
1500{
1501 WINPR_ASSERT(channels);
1502 WINPR_ASSERT(channels->instance);
1503 WINPR_ASSERT(channels->instance->context);
1504 WINPR_ASSERT(entryEx);
1505
1506 if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT)
1507 {
1508 WLog_ERR(TAG, "error: too many channels");
1509 return 1;
1510 }
1511
1512 if (freerdp_channels_is_loaded_ex(channels, entryEx))
1513 {
1514 WLog_WARN(TAG, "Skipping, channel already loaded");
1515 return 0;
1516 }
1517
1518 CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1519 pChannelClientData->entryEx = entryEx;
1520
1521 CHANNEL_INIT_DATA* pChannelInitData = &(channels->initDataList[channels->initDataCount++]);
1522 void* pInitHandle = pChannelInitData;
1523 pChannelInitData->channels = channels;
1524
1525 CHANNEL_ENTRY_POINTS_FREERDP_EX EntryPointsEx = {
1526 .cbSize = sizeof(EntryPointsEx),
1527 .protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000,
1528 .pVirtualChannelInitEx = FreeRDP_VirtualChannelInitEx,
1529 .pVirtualChannelOpenEx = FreeRDP_VirtualChannelOpenEx,
1530 .pVirtualChannelCloseEx = FreeRDP_VirtualChannelCloseEx,
1531 .pVirtualChannelWriteEx = FreeRDP_VirtualChannelWriteEx,
1532 .MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER,
1533 .pExtendedData = data,
1534 .context = channels->instance->context
1535 };
1536
1537 union
1538 {
1540 PCHANNEL_ENTRY_POINTS_EX px;
1541 } ptr;
1542
1543 ptr.pfx = &EntryPointsEx;
1544
1545 /* enable VirtualChannelInit */
1546 channels->can_call_init = TRUE;
1547 EnterCriticalSection(&channels->channelsLock);
1548 const BOOL status = pChannelClientData->entryEx(ptr.px, pInitHandle);
1549 LeaveCriticalSection(&channels->channelsLock);
1550 /* disable MyVirtualChannelInit */
1551 channels->can_call_init = FALSE;
1552
1553 if (!status)
1554 {
1555 WLog_ERR(TAG, "error: channel export function call failed");
1556 return 1;
1557 }
1558
1559 return 0;
1560}
1561
1566int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name,
1567 void* data)
1568{
1569 PVIRTUALCHANNELENTRY entry =
1570 freerdp_load_channel_addin_entry(name, nullptr, nullptr, FREERDP_ADDIN_CHANNEL_STATIC);
1571
1572 if (!entry)
1573 return 1;
1574
1575 return freerdp_channels_client_load(channels, settings, entry, data);
1576}
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 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 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:58
OBJECT_NEW_FN fnObjectNew
Definition collections.h:53