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