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