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  rdpMcsChannel* mcsChannel = NULL;
585  if (!instance || !channel_name)
586  return -1;
587 
588  mcsChannel = freerdp_channels_find_channel_by_name(instance->context->rdp, channel_name);
589  if (!mcsChannel)
590  return -1;
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  pChannelOpenData->OpenHandle = InterlockedIncrement(&g_OpenHandleSeq);
1010  pChannelOpenData->channels = channels;
1011  pChannelOpenData->lpUserParam = lpUserParam;
1012  if (!HashTable_Insert(g_ChannelHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle,
1013  (void*)pChannelOpenData))
1014  {
1015  pChannelInitData->pInterface = NULL;
1016  return CHANNEL_RC_INITIALIZATION_ERROR;
1017  }
1018  pChannelOpenData->flags = 1; /* init */
1019  strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
1020  pChannelOpenData->options = pChannelDef->options;
1021 
1022  const UINT32 max = freerdp_settings_get_uint32(settings, FreeRDP_ChannelDefArraySize);
1023  WINPR_ASSERT(max >= CHANNEL_MAX_COUNT);
1024  if (settings->ChannelCount < max)
1025  {
1026  CHANNEL_DEF* channel = freerdp_settings_get_pointer_array_writable(
1027  settings, FreeRDP_ChannelDefArray, settings->ChannelCount);
1028  if (!channel)
1029  continue;
1030  strncpy(channel->name, pChannelDef->name, CHANNEL_NAME_LEN);
1031  channel->options = pChannelDef->options;
1032  settings->ChannelCount++;
1033  }
1034 
1035  channels->openDataCount++;
1036  }
1037 
1038  return CHANNEL_RC_OK;
1039 }
1040 
1041 static UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, PCHANNEL_DEF pChannel,
1042  INT channelCount, ULONG versionRequested,
1043  PCHANNEL_INIT_EVENT_FN pChannelInitEventProc)
1044 {
1045  CHANNEL_DEF* channel = NULL;
1046  rdpSettings* settings = NULL;
1047  PCHANNEL_DEF pChannelDef = NULL;
1048  CHANNEL_INIT_DATA* pChannelInitData = NULL;
1049  CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
1050  CHANNEL_CLIENT_DATA* pChannelClientData = NULL;
1051  rdpChannels* channels = NULL;
1052 
1053  /* g_Instance should have been set during freerdp_connect - otherwise VirtualChannelInit was
1054  * called from a different thread */
1055  if (!g_Instance || !g_Instance->context)
1056  return CHANNEL_RC_NOT_INITIALIZED;
1057 
1058  channels = g_Instance->context->channels;
1059 
1060  if (!ppInitHandle || !channels)
1061  return CHANNEL_RC_BAD_INIT_HANDLE;
1062 
1063  if (!pChannel)
1064  return CHANNEL_RC_BAD_CHANNEL;
1065 
1066  if ((channelCount <= 0) || !pChannelInitEventProc)
1067  return CHANNEL_RC_INITIALIZATION_ERROR;
1068 
1069  pChannelInitData = &(channels->initDataList[channels->initDataCount]);
1070  *ppInitHandle = pChannelInitData;
1071  channels->initDataCount++;
1072  pChannelInitData->channels = channels;
1073  pChannelInitData->pInterface = NULL;
1074 
1075  if (!channels->can_call_init)
1076  return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
1077 
1078  if (channels->openDataCount + channelCount > CHANNEL_MAX_COUNT)
1079  return CHANNEL_RC_TOO_MANY_CHANNELS;
1080 
1081  if (channels->connected)
1082  return CHANNEL_RC_ALREADY_CONNECTED;
1083 
1084  if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
1085  {
1086  }
1087 
1088  for (int index = 0; index < channelCount; index++)
1089  {
1090  pChannelDef = &pChannel[index];
1091 
1092  if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != 0)
1093  {
1094  return CHANNEL_RC_BAD_CHANNEL;
1095  }
1096  }
1097 
1098  pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1099  pChannelClientData->pChannelInitEventProc = pChannelInitEventProc;
1100  pChannelClientData->pInitHandle = *ppInitHandle;
1101  channels->clientDataCount++;
1102  settings = channels->instance->context->settings;
1103 
1104  for (int index = 0; index < channelCount; index++)
1105  {
1106  UINT32 ChannelCount = freerdp_settings_get_uint32(settings, FreeRDP_ChannelCount);
1107 
1108  pChannelDef = &pChannel[index];
1109  pChannelOpenData = &channels->openDataList[channels->openDataCount];
1110  pChannelOpenData->OpenHandle = InterlockedIncrement(&g_OpenHandleSeq);
1111  pChannelOpenData->channels = channels;
1112  if (!HashTable_Insert(g_ChannelHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle,
1113  (void*)pChannelOpenData))
1114  return CHANNEL_RC_INITIALIZATION_ERROR;
1115  pChannelOpenData->flags = 1; /* init */
1116  strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
1117  pChannelOpenData->options = pChannelDef->options;
1118 
1119  if (ChannelCount < CHANNEL_MAX_COUNT)
1120  {
1121  channel = freerdp_settings_get_pointer_array_writable(settings, FreeRDP_ChannelDefArray,
1122  ChannelCount++);
1123  strncpy(channel->name, pChannelDef->name, CHANNEL_NAME_LEN);
1124  channel->options = pChannelDef->options;
1125  if (!freerdp_settings_set_uint32(settings, FreeRDP_ChannelCount, ChannelCount))
1126  return ERROR_INTERNAL_ERROR;
1127  }
1128 
1129  channels->openDataCount++;
1130  }
1131 
1132  return CHANNEL_RC_OK;
1133 }
1134 
1135 static UINT VCAPITYPE
1136 FreeRDP_VirtualChannelOpenEx(LPVOID pInitHandle, LPDWORD pOpenHandle, PCHAR pChannelName,
1137  PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx)
1138 {
1139  void* pInterface = NULL;
1140  rdpChannels* channels = NULL;
1141  CHANNEL_INIT_DATA* pChannelInitData = NULL;
1142  CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
1143  pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1144  channels = pChannelInitData->channels;
1145  pInterface = pChannelInitData->pInterface;
1146 
1147  if (!pOpenHandle)
1148  return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1149 
1150  if (!pChannelOpenEventProcEx)
1151  return CHANNEL_RC_BAD_PROC;
1152 
1153  if (!channels->connected)
1154  return CHANNEL_RC_NOT_CONNECTED;
1155 
1156  pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
1157 
1158  if (!pChannelOpenData)
1159  return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
1160 
1161  if (pChannelOpenData->flags == 2)
1162  return CHANNEL_RC_ALREADY_OPEN;
1163 
1164  pChannelOpenData->flags = 2; /* open */
1165  pChannelOpenData->pInterface = pInterface;
1166  pChannelOpenData->pChannelOpenEventProcEx = pChannelOpenEventProcEx;
1167  *pOpenHandle = pChannelOpenData->OpenHandle;
1168  return CHANNEL_RC_OK;
1169 }
1170 
1171 static UINT VCAPITYPE FreeRDP_VirtualChannelOpen(LPVOID pInitHandle, LPDWORD pOpenHandle,
1172  PCHAR pChannelName,
1173  PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc)
1174 {
1175  void* pInterface = NULL;
1176  rdpChannels* channels = NULL;
1177  CHANNEL_INIT_DATA* pChannelInitData = NULL;
1178  CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
1179  pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1180  channels = pChannelInitData->channels;
1181  pInterface = pChannelInitData->pInterface;
1182 
1183  if (!pOpenHandle)
1184  return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1185 
1186  if (!pChannelOpenEventProc)
1187  return CHANNEL_RC_BAD_PROC;
1188 
1189  if (!channels->connected)
1190  return CHANNEL_RC_NOT_CONNECTED;
1191 
1192  pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
1193 
1194  if (!pChannelOpenData)
1195  return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
1196 
1197  if (pChannelOpenData->flags == 2)
1198  return CHANNEL_RC_ALREADY_OPEN;
1199 
1200  pChannelOpenData->flags = 2; /* open */
1201  pChannelOpenData->pInterface = pInterface;
1202  pChannelOpenData->pChannelOpenEventProc = pChannelOpenEventProc;
1203  *pOpenHandle = pChannelOpenData->OpenHandle;
1204  return CHANNEL_RC_OK;
1205 }
1206 
1207 static UINT VCAPITYPE FreeRDP_VirtualChannelCloseEx(LPVOID pInitHandle, DWORD openHandle)
1208 {
1209  CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
1210 
1211  if (!pInitHandle)
1212  return CHANNEL_RC_BAD_INIT_HANDLE;
1213 
1214  pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1215 
1216  if (!pChannelOpenData)
1217  return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1218 
1219  if (pChannelOpenData->flags != 2)
1220  return CHANNEL_RC_NOT_OPEN;
1221 
1222  pChannelOpenData->flags = 0;
1223  return CHANNEL_RC_OK;
1224 }
1225 
1226 static UINT VCAPITYPE FreeRDP_VirtualChannelClose(DWORD openHandle)
1227 {
1228  CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
1229 
1230  pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1231 
1232  if (!pChannelOpenData)
1233  return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1234 
1235  if (pChannelOpenData->flags != 2)
1236  return CHANNEL_RC_NOT_OPEN;
1237 
1238  pChannelOpenData->flags = 0;
1239  return CHANNEL_RC_OK;
1240 }
1241 
1242 static UINT VCAPITYPE FreeRDP_VirtualChannelWriteEx(LPVOID pInitHandle, DWORD openHandle,
1243  LPVOID pData, ULONG dataLength,
1244  LPVOID pUserData)
1245 {
1246  rdpChannels* channels = NULL;
1247  CHANNEL_INIT_DATA* pChannelInitData = NULL;
1248  CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
1249  CHANNEL_OPEN_EVENT* pChannelOpenEvent = NULL;
1250  wMessage message = { 0 };
1251 
1252  if (!pInitHandle)
1253  return CHANNEL_RC_BAD_INIT_HANDLE;
1254 
1255  pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1256  channels = pChannelInitData->channels;
1257 
1258  if (!channels)
1259  return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1260 
1261  pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1262 
1263  if (!pChannelOpenData)
1264  return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1265 
1266  if (!channels->connected)
1267  return CHANNEL_RC_NOT_CONNECTED;
1268 
1269  if (!pData)
1270  return CHANNEL_RC_NULL_DATA;
1271 
1272  if (!dataLength)
1273  return CHANNEL_RC_ZERO_LENGTH;
1274 
1275  if (pChannelOpenData->flags != 2)
1276  return CHANNEL_RC_NOT_OPEN;
1277 
1278  pChannelOpenEvent = (CHANNEL_OPEN_EVENT*)malloc(sizeof(CHANNEL_OPEN_EVENT));
1279 
1280  if (!pChannelOpenEvent)
1281  return CHANNEL_RC_NO_MEMORY;
1282 
1283  pChannelOpenEvent->Data = pData;
1284  pChannelOpenEvent->DataLength = dataLength;
1285  pChannelOpenEvent->UserData = pUserData;
1286  pChannelOpenEvent->pChannelOpenData = pChannelOpenData;
1287  message.context = channels;
1288  message.id = 0;
1289  message.wParam = pChannelOpenEvent;
1290  message.lParam = NULL;
1291  message.Free = channel_queue_message_free;
1292 
1293  if (!MessageQueue_Dispatch(channels->queue, &message))
1294  {
1295  free(pChannelOpenEvent);
1296  return CHANNEL_RC_NO_MEMORY;
1297  }
1298 
1299  return CHANNEL_RC_OK;
1300 }
1301 
1302 static UINT VCAPITYPE FreeRDP_VirtualChannelWrite(DWORD openHandle, LPVOID pData, ULONG dataLength,
1303  LPVOID pUserData)
1304 {
1305  wMessage message = { 0 };
1306  CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
1307  CHANNEL_OPEN_EVENT* pChannelOpenEvent = NULL;
1308  rdpChannels* channels = NULL;
1309 
1310  pChannelOpenData = HashTable_GetItemValue(g_ChannelHandles, (void*)(UINT_PTR)openHandle);
1311 
1312  if (!pChannelOpenData)
1313  return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1314 
1315  channels = pChannelOpenData->channels;
1316  if (!channels)
1317  return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1318 
1319  if (!channels->connected)
1320  return CHANNEL_RC_NOT_CONNECTED;
1321 
1322  if (!pData)
1323  return CHANNEL_RC_NULL_DATA;
1324 
1325  if (!dataLength)
1326  return CHANNEL_RC_ZERO_LENGTH;
1327 
1328  if (pChannelOpenData->flags != 2)
1329  return CHANNEL_RC_NOT_OPEN;
1330 
1331  pChannelOpenEvent = (CHANNEL_OPEN_EVENT*)malloc(sizeof(CHANNEL_OPEN_EVENT));
1332 
1333  if (!pChannelOpenEvent)
1334  return CHANNEL_RC_NO_MEMORY;
1335 
1336  pChannelOpenEvent->Data = pData;
1337  pChannelOpenEvent->DataLength = dataLength;
1338  pChannelOpenEvent->UserData = pUserData;
1339  pChannelOpenEvent->pChannelOpenData = pChannelOpenData;
1340  message.context = channels;
1341  message.id = 0;
1342  message.wParam = pChannelOpenEvent;
1343  message.lParam = NULL;
1344  message.Free = channel_queue_message_free;
1345 
1346  if (!MessageQueue_Dispatch(channels->queue, &message))
1347  {
1348  free(pChannelOpenEvent);
1349  return CHANNEL_RC_NO_MEMORY;
1350  }
1351 
1352  return CHANNEL_RC_OK;
1353 }
1354 
1355 static BOOL freerdp_channels_is_loaded(rdpChannels* channels, PVIRTUALCHANNELENTRY entry)
1356 {
1357  for (int i = 0; i < channels->clientDataCount; i++)
1358  {
1359  CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[i];
1360 
1361  if (pChannelClientData->entry == entry)
1362  return TRUE;
1363  }
1364 
1365  return FALSE;
1366 }
1367 
1368 static BOOL freerdp_channels_is_loaded_ex(rdpChannels* channels, PVIRTUALCHANNELENTRYEX entryEx)
1369 {
1370  for (int i = 0; i < channels->clientDataCount; i++)
1371  {
1372  CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[i];
1373 
1374  if (pChannelClientData->entryEx == entryEx)
1375  return TRUE;
1376  }
1377 
1378  return FALSE;
1379 }
1380 
1381 int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings,
1382  PVIRTUALCHANNELENTRY entry, void* data)
1383 {
1384  int status = 0;
1385  CHANNEL_ENTRY_POINTS_FREERDP EntryPoints = { 0 };
1386  CHANNEL_CLIENT_DATA* pChannelClientData = NULL;
1387 
1388  WINPR_ASSERT(channels);
1389  WINPR_ASSERT(channels->instance);
1390  WINPR_ASSERT(channels->instance->context);
1391  WINPR_ASSERT(entry);
1392 
1393  if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT)
1394  {
1395  WLog_ERR(TAG, "error: too many channels");
1396  return 1;
1397  }
1398 
1399  if (freerdp_channels_is_loaded(channels, entry))
1400  {
1401  WLog_WARN(TAG, "Skipping, channel already loaded");
1402  return 0;
1403  }
1404 
1405  pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1406  pChannelClientData->entry = entry;
1407 
1408  EntryPoints.cbSize = sizeof(EntryPoints);
1409  EntryPoints.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
1410  EntryPoints.pVirtualChannelInit = FreeRDP_VirtualChannelInit;
1411  EntryPoints.pVirtualChannelOpen = FreeRDP_VirtualChannelOpen;
1412  EntryPoints.pVirtualChannelClose = FreeRDP_VirtualChannelClose;
1413  EntryPoints.pVirtualChannelWrite = FreeRDP_VirtualChannelWrite;
1414  EntryPoints.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER;
1415  EntryPoints.pExtendedData = data;
1416  EntryPoints.context = channels->instance->context;
1417  /* enable VirtualChannelInit */
1418  channels->can_call_init = TRUE;
1419  EnterCriticalSection(&channels->channelsLock);
1420  status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS)&EntryPoints);
1421  LeaveCriticalSection(&channels->channelsLock);
1422  /* disable MyVirtualChannelInit */
1423  channels->can_call_init = FALSE;
1424 
1425  if (!status)
1426  {
1427  WLog_ERR(TAG, "error: channel export function call failed");
1428  return 1;
1429  }
1430 
1431  return 0;
1432 }
1433 
1434 int freerdp_channels_client_load_ex(rdpChannels* channels, rdpSettings* settings,
1435  PVIRTUALCHANNELENTRYEX entryEx, void* data)
1436 {
1437  int status = 0;
1438  void* pInitHandle = NULL;
1439  CHANNEL_ENTRY_POINTS_FREERDP_EX EntryPointsEx = { 0 };
1440  CHANNEL_INIT_DATA* pChannelInitData = NULL;
1441  CHANNEL_CLIENT_DATA* pChannelClientData = NULL;
1442 
1443  WINPR_ASSERT(channels);
1444  WINPR_ASSERT(channels->instance);
1445  WINPR_ASSERT(channels->instance->context);
1446  WINPR_ASSERT(entryEx);
1447 
1448  if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT)
1449  {
1450  WLog_ERR(TAG, "error: too many channels");
1451  return 1;
1452  }
1453 
1454  if (freerdp_channels_is_loaded_ex(channels, entryEx))
1455  {
1456  WLog_WARN(TAG, "Skipping, channel already loaded");
1457  return 0;
1458  }
1459 
1460  pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1461  pChannelClientData->entryEx = entryEx;
1462  pChannelInitData = &(channels->initDataList[channels->initDataCount++]);
1463  pInitHandle = pChannelInitData;
1464  pChannelInitData->channels = channels;
1465  EntryPointsEx.cbSize = sizeof(EntryPointsEx);
1466  EntryPointsEx.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
1467  EntryPointsEx.pVirtualChannelInitEx = FreeRDP_VirtualChannelInitEx;
1468  EntryPointsEx.pVirtualChannelOpenEx = FreeRDP_VirtualChannelOpenEx;
1469  EntryPointsEx.pVirtualChannelCloseEx = FreeRDP_VirtualChannelCloseEx;
1470  EntryPointsEx.pVirtualChannelWriteEx = FreeRDP_VirtualChannelWriteEx;
1471  EntryPointsEx.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER;
1472  EntryPointsEx.pExtendedData = data;
1473  EntryPointsEx.context = channels->instance->context;
1474  /* enable VirtualChannelInit */
1475  channels->can_call_init = TRUE;
1476  EnterCriticalSection(&channels->channelsLock);
1477  status = pChannelClientData->entryEx((PCHANNEL_ENTRY_POINTS_EX)&EntryPointsEx, pInitHandle);
1478  LeaveCriticalSection(&channels->channelsLock);
1479  /* disable MyVirtualChannelInit */
1480  channels->can_call_init = FALSE;
1481 
1482  if (!status)
1483  {
1484  WLog_ERR(TAG, "error: channel export function call failed");
1485  return 1;
1486  }
1487 
1488  return 0;
1489 }
1490 
1495 int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name,
1496  void* data)
1497 {
1498  PVIRTUALCHANNELENTRY entry =
1499  freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
1500 
1501  if (!entry)
1502  return 1;
1503 
1504  return freerdp_channels_client_load(channels, settings, entry, data);
1505 }
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