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