FreeRDP
libfreerdp/core/server.c
1 
22 #include <freerdp/config.h>
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdint.h>
28 
29 #include <winpr/wtypes.h>
30 #include <winpr/crt.h>
31 #include <winpr/synch.h>
32 #include <winpr/stream.h>
33 #include <winpr/assert.h>
34 #include <winpr/cast.h>
35 
36 #include <freerdp/log.h>
37 #include <freerdp/constants.h>
38 #include <freerdp/server/channels.h>
39 #include <freerdp/channels/drdynvc.h>
40 #include <freerdp/utils/drdynvc.h>
41 
42 #include "rdp.h"
43 
44 #include "server.h"
45 
46 #define TAG FREERDP_TAG("core.server")
47 #ifdef WITH_DEBUG_DVC
48 #define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__)
49 #else
50 #define DEBUG_DVC(...) \
51  do \
52  { \
53  } while (0)
54 #endif
55 
56 #define DVC_MAX_DATA_PDU_SIZE 1600
57 
58 typedef struct
59 {
60  UINT16 channelId;
61  UINT16 reserved;
62  UINT32 length;
63  UINT32 offset;
64 } wtsChannelMessage;
65 
66 static DWORD g_SessionId = 1;
67 static wHashTable* g_ServerHandles = NULL;
68 
69 static rdpPeerChannel* wts_get_dvc_channel_by_id(WTSVirtualChannelManager* vcm, UINT32 ChannelId)
70 {
71  WINPR_ASSERT(vcm);
72  return HashTable_GetItemValue(vcm->dynamicVirtualChannels, &ChannelId);
73 }
74 
75 static BOOL wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* Buffer, UINT32 Length)
76 {
77  BYTE* buffer = NULL;
78  wtsChannelMessage* messageCtx = NULL;
79 
80  WINPR_ASSERT(channel);
81  messageCtx = (wtsChannelMessage*)malloc(sizeof(wtsChannelMessage) + Length);
82 
83  if (!messageCtx)
84  return FALSE;
85 
86  WINPR_ASSERT(channel->channelId <= UINT16_MAX);
87  messageCtx->channelId = (UINT16)channel->channelId;
88  messageCtx->length = Length;
89  messageCtx->offset = 0;
90  buffer = (BYTE*)(messageCtx + 1);
91  CopyMemory(buffer, Buffer, Length);
92  return MessageQueue_Post(channel->queue, messageCtx, 0, NULL, NULL);
93 }
94 
95 static BOOL wts_queue_send_item(rdpPeerChannel* channel, BYTE* Buffer, UINT32 Length)
96 {
97  BYTE* buffer = NULL;
98  UINT32 length = 0;
99 
100  WINPR_ASSERT(channel);
101  WINPR_ASSERT(channel->vcm);
102  buffer = Buffer;
103  length = Length;
104 
105  WINPR_ASSERT(channel->channelId <= UINT16_MAX);
106  const UINT16 channelId = (UINT16)channel->channelId;
107  return MessageQueue_Post(channel->vcm->queue, (void*)(UINT_PTR)channelId, 0, (void*)buffer,
108  (void*)(UINT_PTR)length);
109 }
110 
111 static unsigned wts_read_variable_uint(wStream* s, int cbLen, UINT32* val)
112 {
113  WINPR_ASSERT(s);
114  WINPR_ASSERT(val);
115  switch (cbLen)
116  {
117  case 0:
118  if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
119  return 0;
120 
121  Stream_Read_UINT8(s, *val);
122  return 1;
123 
124  case 1:
125  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
126  return 0;
127 
128  Stream_Read_UINT16(s, *val);
129  return 2;
130 
131  case 2:
132  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
133  return 0;
134 
135  Stream_Read_UINT32(s, *val);
136  return 4;
137 
138  default:
139  WLog_ERR(TAG, "invalid wts variable uint len %d", cbLen);
140  return 0;
141  }
142 }
143 
144 static BOOL wts_read_drdynvc_capabilities_response(rdpPeerChannel* channel, UINT32 length)
145 {
146  UINT16 Version = 0;
147 
148  WINPR_ASSERT(channel);
149  WINPR_ASSERT(channel->vcm);
150  if (length < 3)
151  return FALSE;
152 
153  Stream_Seek_UINT8(channel->receiveData); /* Pad (1 byte) */
154  Stream_Read_UINT16(channel->receiveData, Version);
155  DEBUG_DVC("Version: %" PRIu16 "", Version);
156 
157  if (Version < 1)
158  {
159  WLog_ERR(TAG, "invalid version %" PRIu16 " for DRDYNVC", Version);
160  return FALSE;
161  }
162 
163  WTSVirtualChannelManager* vcm = channel->vcm;
164  vcm->drdynvc_state = DRDYNVC_STATE_READY;
165 
166  /* we only support version 1 for now (no compression yet) */
167  vcm->dvc_spoken_version = MAX(Version, 1);
168 
169  return SetEvent(MessageQueue_Event(vcm->queue));
170 }
171 
172 static BOOL wts_read_drdynvc_create_response(rdpPeerChannel* channel, wStream* s, UINT32 length)
173 {
174  UINT32 CreationStatus = 0;
175  BOOL status = TRUE;
176 
177  WINPR_ASSERT(channel);
178  WINPR_ASSERT(s);
179  if (length < 4)
180  return FALSE;
181 
182  Stream_Read_UINT32(s, CreationStatus);
183 
184  if ((INT32)CreationStatus < 0)
185  {
186  DEBUG_DVC("ChannelId %" PRIu32 " creation failed (%" PRId32 ")", channel->channelId,
187  (INT32)CreationStatus);
188  channel->dvc_open_state = DVC_OPEN_STATE_FAILED;
189  }
190  else
191  {
192  DEBUG_DVC("ChannelId %" PRIu32 " creation succeeded", channel->channelId);
193  channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED;
194  }
195 
196  channel->creationStatus = (INT32)CreationStatus;
197  IFCALLRET(channel->vcm->dvc_creation_status, status, channel->vcm->dvc_creation_status_userdata,
198  channel->channelId, (INT32)CreationStatus);
199  if (!status)
200  WLog_ERR(TAG, "vcm->dvc_creation_status failed!");
201 
202  return status;
203 }
204 
205 static BOOL wts_read_drdynvc_data_first(rdpPeerChannel* channel, wStream* s, int cbLen,
206  UINT32 length)
207 {
208  WINPR_ASSERT(channel);
209  WINPR_ASSERT(s);
210  const UINT32 value = wts_read_variable_uint(s, cbLen, &channel->dvc_total_length);
211 
212  if (value == 0)
213  return FALSE;
214  if (value > length)
215  length = 0;
216  else
217  length -= value;
218 
219  if (length > channel->dvc_total_length)
220  return FALSE;
221 
222  Stream_SetPosition(channel->receiveData, 0);
223 
224  if (!Stream_EnsureRemainingCapacity(channel->receiveData, channel->dvc_total_length))
225  return FALSE;
226 
227  Stream_Write(channel->receiveData, Stream_ConstPointer(s), length);
228  return TRUE;
229 }
230 
231 static BOOL wts_read_drdynvc_data(rdpPeerChannel* channel, wStream* s, UINT32 length)
232 {
233  BOOL ret = FALSE;
234 
235  WINPR_ASSERT(channel);
236  WINPR_ASSERT(s);
237  if (channel->dvc_total_length > 0)
238  {
239  if (Stream_GetPosition(channel->receiveData) + length > channel->dvc_total_length)
240  {
241  channel->dvc_total_length = 0;
242  WLog_ERR(TAG, "incorrect fragment data, discarded.");
243  return FALSE;
244  }
245 
246  Stream_Write(channel->receiveData, Stream_ConstPointer(s), length);
247 
248  if (Stream_GetPosition(channel->receiveData) >= channel->dvc_total_length)
249  {
250  ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData),
251  channel->dvc_total_length);
252  channel->dvc_total_length = 0;
253  }
254  else
255  ret = TRUE;
256  }
257  else
258  {
259  ret = wts_queue_receive_data(channel, Stream_ConstPointer(s), length);
260  }
261 
262  return ret;
263 }
264 
265 static void wts_read_drdynvc_close_response(rdpPeerChannel* channel)
266 {
267  WINPR_ASSERT(channel);
268  DEBUG_DVC("ChannelId %" PRIu32 " close response", channel->channelId);
269  channel->dvc_open_state = DVC_OPEN_STATE_CLOSED;
270  MessageQueue_PostQuit(channel->queue, 0);
271 }
272 
273 static BOOL wts_read_drdynvc_pdu(rdpPeerChannel* channel)
274 {
275  UINT8 Cmd = 0;
276  UINT8 Sp = 0;
277  UINT8 cbChId = 0;
278  UINT32 ChannelId = 0;
279  rdpPeerChannel* dvc = NULL;
280 
281  WINPR_ASSERT(channel);
282  WINPR_ASSERT(channel->vcm);
283 
284  size_t length = Stream_GetPosition(channel->receiveData);
285 
286  if ((length < 1) || (length > UINT32_MAX))
287  return FALSE;
288 
289  Stream_SetPosition(channel->receiveData, 0);
290  const UINT8 value = Stream_Get_UINT8(channel->receiveData);
291  length--;
292  Cmd = (value & 0xf0) >> 4;
293  Sp = (value & 0x0c) >> 2;
294  cbChId = (value & 0x03) >> 0;
295 
296  if (Cmd == CAPABILITY_REQUEST_PDU)
297  return wts_read_drdynvc_capabilities_response(channel, (UINT32)length);
298 
299  if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY)
300  {
301  BOOL haveChannelId = 0;
302  switch (Cmd)
303  {
304  case SOFT_SYNC_REQUEST_PDU:
305  case SOFT_SYNC_RESPONSE_PDU:
306  haveChannelId = FALSE;
307  break;
308  default:
309  haveChannelId = TRUE;
310  break;
311  }
312 
313  if (haveChannelId)
314  {
315  const unsigned val = wts_read_variable_uint(channel->receiveData, cbChId, &ChannelId);
316  if (val == 0)
317  return FALSE;
318 
319  length -= val;
320 
321  DEBUG_DVC("Cmd %s ChannelId %" PRIu32 " length %" PRIuz "",
322  drdynvc_get_packet_type(Cmd), ChannelId, length);
323  dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId);
324  if (!dvc)
325  {
326  DEBUG_DVC("ChannelId %" PRIu32 " does not exist.", ChannelId);
327  return TRUE;
328  }
329  }
330 
331  switch (Cmd)
332  {
333  case CREATE_REQUEST_PDU:
334  return wts_read_drdynvc_create_response(dvc, channel->receiveData, (UINT32)length);
335 
336  case DATA_FIRST_PDU:
337  if (dvc->dvc_open_state != DVC_OPEN_STATE_SUCCEEDED)
338  {
339  WLog_ERR(TAG,
340  "ChannelId %" PRIu32 " did not open successfully. "
341  "Ignoring DYNVC_DATA_FIRST PDU",
342  ChannelId);
343  return TRUE;
344  }
345 
346  return wts_read_drdynvc_data_first(dvc, channel->receiveData, Sp, (UINT32)length);
347 
348  case DATA_PDU:
349  if (dvc->dvc_open_state != DVC_OPEN_STATE_SUCCEEDED)
350  {
351  WLog_ERR(TAG,
352  "ChannelId %" PRIu32 " did not open successfully. "
353  "Ignoring DYNVC_DATA PDU",
354  ChannelId);
355  return TRUE;
356  }
357 
358  return wts_read_drdynvc_data(dvc, channel->receiveData, (UINT32)length);
359 
360  case CLOSE_REQUEST_PDU:
361  wts_read_drdynvc_close_response(dvc);
362  break;
363 
364  case DATA_FIRST_COMPRESSED_PDU:
365  case DATA_COMPRESSED_PDU:
366  WLog_ERR(TAG, "Compressed data not handled");
367  break;
368 
369  case SOFT_SYNC_RESPONSE_PDU:
370  WLog_ERR(TAG, "SoftSync response not handled yet(and rather strange to receive "
371  "that packet as our code doesn't send SoftSync requests");
372  break;
373 
374  case SOFT_SYNC_REQUEST_PDU:
375  WLog_ERR(TAG, "Not expecting a SoftSyncRequest on the server");
376  return FALSE;
377 
378  default:
379  WLog_ERR(TAG, "Cmd %d not recognized.", Cmd);
380  break;
381  }
382  }
383  else
384  {
385  WLog_ERR(TAG, "received Cmd %d but channel is not ready.", Cmd);
386  }
387 
388  return TRUE;
389 }
390 
391 static int wts_write_variable_uint(wStream* s, UINT32 val)
392 {
393  int cb = 0;
394 
395  WINPR_ASSERT(s);
396  if (val <= 0xFF)
397  {
398  cb = 0;
399  Stream_Write_UINT8(s, WINPR_ASSERTING_INT_CAST(uint8_t, val));
400  }
401  else if (val <= 0xFFFF)
402  {
403  cb = 1;
404  Stream_Write_UINT16(s, WINPR_ASSERTING_INT_CAST(uint16_t, val));
405  }
406  else
407  {
408  cb = 2;
409  Stream_Write_UINT32(s, val);
410  }
411 
412  return cb;
413 }
414 
415 static void wts_write_drdynvc_header(wStream* s, BYTE Cmd, UINT32 ChannelId)
416 {
417  BYTE* bm = NULL;
418  int cbChId = 0;
419 
420  WINPR_ASSERT(s);
421 
422  Stream_GetPointer(s, bm);
423  Stream_Seek_UINT8(s);
424  cbChId = wts_write_variable_uint(s, ChannelId);
425  *bm = (((Cmd & 0x0F) << 4) | cbChId) & 0xFF;
426 }
427 
428 static BOOL wts_write_drdynvc_create_request(wStream* s, UINT32 ChannelId, const char* ChannelName)
429 {
430  size_t len = 0;
431 
432  WINPR_ASSERT(s);
433  WINPR_ASSERT(ChannelName);
434 
435  wts_write_drdynvc_header(s, CREATE_REQUEST_PDU, ChannelId);
436  len = strlen(ChannelName) + 1;
437 
438  if (!Stream_EnsureRemainingCapacity(s, len))
439  return FALSE;
440 
441  Stream_Write(s, ChannelName, len);
442  return TRUE;
443 }
444 
445 static BOOL WTSProcessChannelData(rdpPeerChannel* channel, UINT16 channelId, const BYTE* data,
446  size_t s, UINT32 flags, size_t t)
447 {
448  BOOL ret = TRUE;
449  const size_t size = s;
450  const size_t totalSize = t;
451 
452  WINPR_ASSERT(channel);
453  WINPR_ASSERT(channel->vcm);
454  WINPR_UNUSED(channelId);
455 
456  if (flags & CHANNEL_FLAG_FIRST)
457  {
458  Stream_SetPosition(channel->receiveData, 0);
459  }
460 
461  if (!Stream_EnsureRemainingCapacity(channel->receiveData, size))
462  return FALSE;
463 
464  Stream_Write(channel->receiveData, data, size);
465 
466  if (flags & CHANNEL_FLAG_LAST)
467  {
468  if (Stream_GetPosition(channel->receiveData) != totalSize)
469  {
470  WLog_ERR(TAG, "read error");
471  }
472 
473  if (channel == channel->vcm->drdynvc_channel)
474  {
475  ret = wts_read_drdynvc_pdu(channel);
476  }
477  else
478  {
479  const size_t pos = Stream_GetPosition(channel->receiveData);
480  if (pos > UINT32_MAX)
481  ret = FALSE;
482  else
483  ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData),
484  (UINT32)pos);
485  }
486 
487  Stream_SetPosition(channel->receiveData, 0);
488  }
489 
490  return ret;
491 }
492 
493 static BOOL WTSReceiveChannelData(freerdp_peer* client, UINT16 channelId, const BYTE* data,
494  size_t size, UINT32 flags, size_t totalSize)
495 {
496  rdpMcs* mcs = NULL;
497 
498  WINPR_ASSERT(client);
499  WINPR_ASSERT(client->context);
500  WINPR_ASSERT(client->context->rdp);
501 
502  mcs = client->context->rdp->mcs;
503  WINPR_ASSERT(mcs);
504 
505  for (UINT32 i = 0; i < mcs->channelCount; i++)
506  {
507  rdpMcsChannel* cur = &mcs->channels[i];
508  if (cur->ChannelId == channelId)
509  {
510  rdpPeerChannel* channel = (rdpPeerChannel*)cur->handle;
511 
512  if (channel)
513  return WTSProcessChannelData(channel, channelId, data, size, flags, totalSize);
514  }
515  }
516 
517  WLog_WARN(TAG, "unknown channelId %" PRIu16 " ignored", channelId);
518 
519  return TRUE;
520 }
521 
522 #if defined(WITH_FREERDP_DEPRECATED)
523 void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer, void** fds, int* fds_count)
524 {
525  void* fd = NULL;
527  WINPR_ASSERT(vcm);
528  WINPR_ASSERT(fds);
529  WINPR_ASSERT(fds_count);
530 
531  fd = GetEventWaitObject(MessageQueue_Event(vcm->queue));
532 
533  if (fd)
534  {
535  fds[*fds_count] = fd;
536  (*fds_count)++;
537  }
538 
539 #if 0
540 
541  if (vcm->drdynvc_channel)
542  {
543  fd = GetEventWaitObject(vcm->drdynvc_channel->receiveEvent);
544 
545  if (fd)
546  {
547  fds[*fds_count] = fd;
548  (*fds_count)++;
549  }
550  }
551 
552 #endif
553 }
554 #endif
555 
556 BOOL WTSVirtualChannelManagerOpen(HANDLE hServer)
557 {
559 
560  if (!vcm)
561  return FALSE;
562 
563  if (vcm->drdynvc_state == DRDYNVC_STATE_NONE)
564  {
565  rdpPeerChannel* channel = NULL;
566 
567  /* Initialize drdynvc channel once and only once. */
568  vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
569  channel = (rdpPeerChannel*)WTSVirtualChannelOpen((HANDLE)vcm, WTS_CURRENT_SESSION,
570  DRDYNVC_SVC_CHANNEL_NAME);
571 
572  if (channel)
573  {
574  BYTE capaBuffer[12] = { 0 };
575  wStream staticS = { 0 };
576  wStream* s = Stream_StaticInit(&staticS, capaBuffer, sizeof(capaBuffer));
577 
578  vcm->drdynvc_channel = channel;
579  vcm->dvc_spoken_version = 1;
580  Stream_Write_UINT8(s, 0x50); /* Cmd=5 sp=0 cbId=0 */
581  Stream_Write_UINT8(s, 0x00); /* Pad */
582  Stream_Write_UINT16(s, 0x0001); /* Version */
583 
584  /* TODO: shall implement version 2 and 3 */
585 
586  const size_t pos = Stream_GetPosition(s);
587  WINPR_ASSERT(pos <= UINT32_MAX);
588  ULONG written = 0;
589  if (!WTSVirtualChannelWrite(channel, (PCHAR)capaBuffer, (UINT32)pos, &written))
590  return FALSE;
591  }
592  }
593 
594  return TRUE;
595 }
596 
597 BOOL WTSVirtualChannelManagerCheckFileDescriptorEx(HANDLE hServer, BOOL autoOpen)
598 {
599  wMessage message = { 0 };
600  BOOL status = TRUE;
601  WTSVirtualChannelManager* vcm = NULL;
602 
603  if (!hServer || hServer == INVALID_HANDLE_VALUE)
604  return FALSE;
605 
606  vcm = (WTSVirtualChannelManager*)hServer;
607 
608  if (autoOpen)
609  {
610  if (!WTSVirtualChannelManagerOpen(hServer))
611  return FALSE;
612  }
613 
614  while (MessageQueue_Peek(vcm->queue, &message, TRUE))
615  {
616  BYTE* buffer = NULL;
617  UINT32 length = 0;
618  UINT16 channelId = 0;
619  channelId = (UINT16)(UINT_PTR)message.context;
620  buffer = (BYTE*)message.wParam;
621  length = (UINT32)(UINT_PTR)message.lParam;
622 
623  WINPR_ASSERT(vcm->client);
624  WINPR_ASSERT(vcm->client->SendChannelData);
625  if (!vcm->client->SendChannelData(vcm->client, channelId, buffer, length))
626  {
627  status = FALSE;
628  }
629 
630  free(buffer);
631 
632  if (!status)
633  break;
634  }
635 
636  return status;
637 }
638 
639 BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)
640 {
641  return WTSVirtualChannelManagerCheckFileDescriptorEx(hServer, TRUE);
642 }
643 
644 HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer)
645 {
647  WINPR_ASSERT(vcm);
648  return MessageQueue_Event(vcm->queue);
649 }
650 
651 static rdpMcsChannel* wts_get_joined_channel_by_name(rdpMcs* mcs, const char* channel_name)
652 {
653  if (!mcs || !channel_name || !strnlen(channel_name, CHANNEL_NAME_LEN + 1))
654  return NULL;
655 
656  for (UINT32 index = 0; index < mcs->channelCount; index++)
657  {
658  rdpMcsChannel* mchannel = &mcs->channels[index];
659  if (mchannel->joined)
660  {
661  if (_strnicmp(mchannel->Name, channel_name, CHANNEL_NAME_LEN + 1) == 0)
662  return mchannel;
663  }
664  }
665 
666  return NULL;
667 }
668 
669 static rdpMcsChannel* wts_get_joined_channel_by_id(rdpMcs* mcs, const UINT16 channel_id)
670 {
671  if (!mcs || !channel_id)
672  return NULL;
673 
674  WINPR_ASSERT(mcs->channels);
675  for (UINT32 index = 0; index < mcs->channelCount; index++)
676  {
677  rdpMcsChannel* mchannel = &mcs->channels[index];
678  if (mchannel->joined)
679  {
680  if (mchannel->ChannelId == channel_id)
681  return &mcs->channels[index];
682  }
683  }
684 
685  return NULL;
686 }
687 
688 BOOL WTSIsChannelJoinedByName(freerdp_peer* client, const char* channel_name)
689 {
690  if (!client || !client->context || !client->context->rdp)
691  return FALSE;
692 
693  return wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name) == NULL ? FALSE
694  : TRUE;
695 }
696 
697 BOOL WTSIsChannelJoinedById(freerdp_peer* client, const UINT16 channel_id)
698 {
699  if (!client || !client->context || !client->context->rdp)
700  return FALSE;
701 
702  return wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id) == NULL ? FALSE
703  : TRUE;
704 }
705 
706 BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer, const char* name)
707 {
709 
710  if (!vcm || !vcm->rdp)
711  return FALSE;
712 
713  return wts_get_joined_channel_by_name(vcm->rdp->mcs, name) == NULL ? FALSE : TRUE;
714 }
715 
716 BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)
717 {
719  WINPR_ASSERT(vcm);
720  return vcm->drdynvc_state;
721 }
722 
723 void WTSVirtualChannelManagerSetDVCCreationCallback(HANDLE hServer, psDVCCreationStatusCallback cb,
724  void* userdata)
725 {
726  WTSVirtualChannelManager* vcm = hServer;
727 
728  WINPR_ASSERT(vcm);
729 
730  vcm->dvc_creation_status = cb;
731  vcm->dvc_creation_status_userdata = userdata;
732 }
733 
734 UINT16 WTSChannelGetId(freerdp_peer* client, const char* channel_name)
735 {
736  rdpMcsChannel* channel = NULL;
737 
738  WINPR_ASSERT(channel_name);
739  if (!client || !client->context || !client->context->rdp)
740  return 0;
741 
742  channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
743 
744  if (!channel)
745  return 0;
746 
747  return channel->ChannelId;
748 }
749 
750 UINT32 WTSChannelGetIdByHandle(HANDLE hChannelHandle)
751 {
752  rdpPeerChannel* channel = hChannelHandle;
753 
754  WINPR_ASSERT(channel);
755 
756  return channel->channelId;
757 }
758 
759 BOOL WTSChannelSetHandleByName(freerdp_peer* client, const char* channel_name, void* handle)
760 {
761  rdpMcsChannel* channel = NULL;
762 
763  WINPR_ASSERT(channel_name);
764  if (!client || !client->context || !client->context->rdp)
765  return FALSE;
766 
767  channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
768 
769  if (!channel)
770  return FALSE;
771 
772  channel->handle = handle;
773  return TRUE;
774 }
775 
776 BOOL WTSChannelSetHandleById(freerdp_peer* client, const UINT16 channel_id, void* handle)
777 {
778  rdpMcsChannel* channel = NULL;
779 
780  if (!client || !client->context || !client->context->rdp)
781  return FALSE;
782 
783  channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
784 
785  if (!channel)
786  return FALSE;
787 
788  channel->handle = handle;
789  return TRUE;
790 }
791 
792 void* WTSChannelGetHandleByName(freerdp_peer* client, const char* channel_name)
793 {
794  rdpMcsChannel* channel = NULL;
795 
796  WINPR_ASSERT(channel_name);
797  if (!client || !client->context || !client->context->rdp)
798  return NULL;
799 
800  channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
801 
802  if (!channel)
803  return NULL;
804 
805  return channel->handle;
806 }
807 
808 void* WTSChannelGetHandleById(freerdp_peer* client, const UINT16 channel_id)
809 {
810  rdpMcsChannel* channel = NULL;
811 
812  if (!client || !client->context || !client->context->rdp)
813  return NULL;
814 
815  channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
816 
817  if (!channel)
818  return NULL;
819 
820  return channel->handle;
821 }
822 
823 const char* WTSChannelGetName(freerdp_peer* client, UINT16 channel_id)
824 {
825  rdpMcsChannel* channel = NULL;
826 
827  if (!client || !client->context || !client->context->rdp)
828  return NULL;
829 
830  channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
831 
832  if (!channel)
833  return NULL;
834 
835  return (const char*)channel->Name;
836 }
837 
838 char** WTSGetAcceptedChannelNames(freerdp_peer* client, size_t* count)
839 {
840  rdpMcs* mcs = NULL;
841  char** names = NULL;
842 
843  if (!client || !client->context || !count)
844  return NULL;
845 
846  WINPR_ASSERT(client->context->rdp);
847  mcs = client->context->rdp->mcs;
848  WINPR_ASSERT(mcs);
849  *count = mcs->channelCount;
850 
851  names = (char**)calloc(mcs->channelCount, sizeof(char*));
852  if (!names)
853  return NULL;
854 
855  for (UINT32 index = 0; index < mcs->channelCount; index++)
856  {
857  rdpMcsChannel* mchannel = &mcs->channels[index];
858  names[index] = mchannel->Name;
859  }
860 
861  return names;
862 }
863 
864 INT64 WTSChannelGetOptions(freerdp_peer* client, UINT16 channel_id)
865 {
866  rdpMcsChannel* channel = NULL;
867 
868  if (!client || !client->context || !client->context->rdp)
869  return -1;
870 
871  channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
872 
873  if (!channel)
874  return -1;
875 
876  return (INT64)channel->options;
877 }
878 
879 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId,
880  BYTE HotkeyVk, USHORT HotkeyModifiers)
881 {
882  return FALSE;
883 }
884 
885 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId,
886  BYTE HotkeyVk, USHORT HotkeyModifiers)
887 {
888  return FALSE;
889 }
890 
891 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExW(LPWSTR pTargetServerName, ULONG TargetLogonId,
892  BYTE HotkeyVk, USHORT HotkeyModifiers,
893  DWORD flags)
894 {
895  return FALSE;
896 }
897 
898 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExA(LPSTR pTargetServerName, ULONG TargetLogonId,
899  BYTE HotkeyVk, USHORT HotkeyModifiers,
900  DWORD flags)
901 {
902  return FALSE;
903 }
904 
905 BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(ULONG LogonId)
906 {
907  return FALSE;
908 }
909 
910 BOOL WINAPI FreeRDP_WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword,
911  BOOL bWait)
912 {
913  return FALSE;
914 }
915 
916 BOOL WINAPI FreeRDP_WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword,
917  BOOL bWait)
918 {
919  return FALSE;
920 }
921 
922 BOOL WINAPI FreeRDP_WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version,
923  PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount)
924 {
925  return FALSE;
926 }
927 
928 BOOL WINAPI FreeRDP_WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version,
929  PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount)
930 {
931  return FALSE;
932 }
933 
934 HANDLE WINAPI FreeRDP_WTSOpenServerW(LPWSTR pServerName)
935 {
936  return INVALID_HANDLE_VALUE;
937 }
938 
939 static void wts_virtual_channel_manager_free_message(void* obj)
940 {
941  wMessage* msg = (wMessage*)obj;
942 
943  if (msg)
944  {
945  BYTE* buffer = (BYTE*)msg->wParam;
946 
947  if (buffer)
948  free(buffer);
949  }
950 }
951 
952 static void channel_free(rdpPeerChannel* channel)
953 {
954  server_channel_common_free(channel);
955 }
956 
957 static void array_channel_free(void* ptr)
958 {
959  rdpPeerChannel* channel = ptr;
960  channel_free(channel);
961 }
962 
963 static BOOL dynChannelMatch(const void* v1, const void* v2)
964 {
965  const UINT32* p1 = (const UINT32*)v1;
966  const UINT32* p2 = (const UINT32*)v2;
967  return *p1 == *p2;
968 }
969 
970 static UINT32 channelId_Hash(const void* key)
971 {
972  const UINT32* v = (const UINT32*)key;
973  return *v;
974 }
975 
976 HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName)
977 {
978  rdpContext* context = NULL;
979  freerdp_peer* client = NULL;
980  WTSVirtualChannelManager* vcm = NULL;
981  HANDLE hServer = INVALID_HANDLE_VALUE;
982  wObject queueCallbacks = { 0 };
983 
984  context = (rdpContext*)pServerName;
985 
986  if (!context)
987  return INVALID_HANDLE_VALUE;
988 
989  client = context->peer;
990 
991  if (!client)
992  {
993  SetLastError(ERROR_INVALID_DATA);
994  return INVALID_HANDLE_VALUE;
995  }
996 
997  vcm = (WTSVirtualChannelManager*)calloc(1, sizeof(WTSVirtualChannelManager));
998 
999  if (!vcm)
1000  goto error_vcm_alloc;
1001 
1002  vcm->client = client;
1003  vcm->rdp = context->rdp;
1004  vcm->SessionId = g_SessionId++;
1005 
1006  if (!g_ServerHandles)
1007  {
1008  g_ServerHandles = HashTable_New(TRUE);
1009 
1010  if (!g_ServerHandles)
1011  goto error_free;
1012  }
1013 
1014  if (!HashTable_Insert(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId, (void*)vcm))
1015  goto error_free;
1016 
1017  queueCallbacks.fnObjectFree = wts_virtual_channel_manager_free_message;
1018  vcm->queue = MessageQueue_New(&queueCallbacks);
1019 
1020  if (!vcm->queue)
1021  goto error_queue;
1022 
1023  vcm->dvc_channel_id_seq = 0;
1024  vcm->dynamicVirtualChannels = HashTable_New(TRUE);
1025 
1026  if (!vcm->dynamicVirtualChannels)
1027  goto error_dynamicVirtualChannels;
1028 
1029  if (!HashTable_SetHashFunction(vcm->dynamicVirtualChannels, channelId_Hash))
1030  goto error_hashFunction;
1031 
1032  {
1033  wObject* obj = HashTable_ValueObject(vcm->dynamicVirtualChannels);
1034  WINPR_ASSERT(obj);
1035  obj->fnObjectFree = array_channel_free;
1036 
1037  obj = HashTable_KeyObject(vcm->dynamicVirtualChannels);
1038  obj->fnObjectEquals = dynChannelMatch;
1039  }
1040  client->ReceiveChannelData = WTSReceiveChannelData;
1041  hServer = (HANDLE)vcm;
1042  return hServer;
1043 
1044 error_hashFunction:
1045  HashTable_Free(vcm->dynamicVirtualChannels);
1046 error_dynamicVirtualChannels:
1047  MessageQueue_Free(vcm->queue);
1048 error_queue:
1049  HashTable_Remove(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId);
1050 error_free:
1051  free(vcm);
1052 error_vcm_alloc:
1053  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1054  return INVALID_HANDLE_VALUE;
1055 }
1056 
1057 HANDLE WINAPI FreeRDP_WTSOpenServerExW(LPWSTR pServerName)
1058 {
1059  return INVALID_HANDLE_VALUE;
1060 }
1061 
1062 HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName)
1063 {
1064  return FreeRDP_WTSOpenServerA(pServerName);
1065 }
1066 
1067 VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer)
1068 {
1069  WTSVirtualChannelManager* vcm = NULL;
1070  vcm = (WTSVirtualChannelManager*)hServer;
1071 
1072  if (vcm && (vcm != INVALID_HANDLE_VALUE))
1073  {
1074  HashTable_Remove(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId);
1075 
1076  HashTable_Free(vcm->dynamicVirtualChannels);
1077 
1078  if (vcm->drdynvc_channel)
1079  {
1080  (void)WTSVirtualChannelClose(vcm->drdynvc_channel);
1081  vcm->drdynvc_channel = NULL;
1082  }
1083 
1084  MessageQueue_Free(vcm->queue);
1085  free(vcm);
1086  }
1087 }
1088 
1089 BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version,
1090  PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount)
1091 {
1092  return FALSE;
1093 }
1094 
1095 BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version,
1096  PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount)
1097 {
1098  return FALSE;
1099 }
1100 
1101 BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter,
1102  PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount)
1103 {
1104  return FALSE;
1105 }
1106 
1107 BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter,
1108  PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount)
1109 {
1110  return FALSE;
1111 }
1112 
1113 BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version,
1114  PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount)
1115 {
1116  return FALSE;
1117 }
1118 
1119 BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version,
1120  PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount)
1121 {
1122  return FALSE;
1123 }
1124 
1125 BOOL WINAPI FreeRDP_WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode)
1126 {
1127  return FALSE;
1128 }
1129 
1130 BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId,
1131  WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer,
1132  DWORD* pBytesReturned)
1133 {
1134  return FALSE;
1135 }
1136 
1137 BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId,
1138  WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer,
1139  DWORD* pBytesReturned)
1140 {
1141  DWORD BytesReturned = 0;
1142  WTSVirtualChannelManager* vcm = NULL;
1143  vcm = (WTSVirtualChannelManager*)hServer;
1144 
1145  if (!vcm)
1146  return FALSE;
1147 
1148  if (WTSInfoClass == WTSSessionId)
1149  {
1150  ULONG* pBuffer = NULL;
1151  BytesReturned = sizeof(ULONG);
1152  pBuffer = (ULONG*)malloc(sizeof(BytesReturned));
1153 
1154  if (!pBuffer)
1155  {
1156  SetLastError(E_OUTOFMEMORY);
1157  return FALSE;
1158  }
1159 
1160  *pBuffer = vcm->SessionId;
1161  *ppBuffer = (LPSTR)pBuffer;
1162  *pBytesReturned = BytesReturned;
1163  return TRUE;
1164  }
1165 
1166  return FALSE;
1167 }
1168 
1169 BOOL WINAPI FreeRDP_WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
1170  WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer,
1171  DWORD* pBytesReturned)
1172 {
1173  return FALSE;
1174 }
1175 
1176 BOOL WINAPI FreeRDP_WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName,
1177  WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer,
1178  DWORD* pBytesReturned)
1179 {
1180  return FALSE;
1181 }
1182 
1183 BOOL WINAPI FreeRDP_WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
1184  WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer,
1185  DWORD DataLength)
1186 {
1187  return FALSE;
1188 }
1189 
1190 BOOL WINAPI FreeRDP_WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName,
1191  WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer,
1192  DWORD DataLength)
1193 {
1194  return FALSE;
1195 }
1196 
1197 BOOL WINAPI FreeRDP_WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle,
1198  DWORD TitleLength, LPWSTR pMessage, DWORD MessageLength,
1199  DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait)
1200 {
1201  return FALSE;
1202 }
1203 
1204 BOOL WINAPI FreeRDP_WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle,
1205  DWORD TitleLength, LPSTR pMessage, DWORD MessageLength,
1206  DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait)
1207 {
1208  return FALSE;
1209 }
1210 
1211 BOOL WINAPI FreeRDP_WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
1212 {
1213  return FALSE;
1214 }
1215 
1216 BOOL WINAPI FreeRDP_WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
1217 {
1218  return FALSE;
1219 }
1220 
1221 BOOL WINAPI FreeRDP_WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag)
1222 {
1223  return FALSE;
1224 }
1225 
1226 BOOL WINAPI FreeRDP_WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags)
1227 {
1228  return FALSE;
1229 }
1230 
1231 static void peer_channel_queue_free_message(void* obj)
1232 {
1233  wMessage* msg = (wMessage*)obj;
1234  if (!msg)
1235  return;
1236 
1237  free(msg->context);
1238  msg->context = NULL;
1239 }
1240 
1241 static rdpPeerChannel* channel_new(WTSVirtualChannelManager* vcm, freerdp_peer* client,
1242  UINT32 ChannelId, UINT16 index, UINT16 type, size_t chunkSize,
1243  const char* name)
1244 {
1245  wObject queueCallbacks = { 0 };
1246  queueCallbacks.fnObjectFree = peer_channel_queue_free_message;
1247 
1248  rdpPeerChannel* channel =
1249  server_channel_common_new(client, index, ChannelId, chunkSize, &queueCallbacks, name);
1250 
1251  WINPR_ASSERT(vcm);
1252  WINPR_ASSERT(client);
1253 
1254  if (!channel)
1255  goto fail;
1256 
1257  channel->vcm = vcm;
1258  channel->channelType = type;
1259  channel->creationStatus =
1260  (type == RDP_PEER_CHANNEL_TYPE_SVC) ? ERROR_SUCCESS : ERROR_OPERATION_IN_PROGRESS;
1261 
1262  return channel;
1263 fail:
1264  channel_free(channel);
1265  return NULL;
1266 }
1267 
1268 HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
1269 {
1270  size_t length = 0;
1271  rdpMcs* mcs = NULL;
1272  rdpMcsChannel* joined_channel = NULL;
1273  freerdp_peer* client = NULL;
1274  rdpPeerChannel* channel = NULL;
1275  WTSVirtualChannelManager* vcm = NULL;
1276  HANDLE hChannelHandle = NULL;
1277  rdpContext* context = NULL;
1278  vcm = (WTSVirtualChannelManager*)hServer;
1279 
1280  if (!vcm)
1281  {
1282  SetLastError(ERROR_INVALID_DATA);
1283  return NULL;
1284  }
1285 
1286  client = vcm->client;
1287  WINPR_ASSERT(client);
1288 
1289  context = client->context;
1290  WINPR_ASSERT(context);
1291  WINPR_ASSERT(context->rdp);
1292  WINPR_ASSERT(context->settings);
1293 
1294  mcs = context->rdp->mcs;
1295  WINPR_ASSERT(mcs);
1296 
1297  length = strnlen(pVirtualName, CHANNEL_NAME_LEN + 1);
1298 
1299  if (length > CHANNEL_NAME_LEN)
1300  {
1301  SetLastError(ERROR_NOT_FOUND);
1302  return NULL;
1303  }
1304 
1305  UINT32 index = 0;
1306  for (; index < mcs->channelCount; index++)
1307  {
1308  rdpMcsChannel* mchannel = &mcs->channels[index];
1309  if (mchannel->joined && (strncmp(mchannel->Name, pVirtualName, length) == 0))
1310  {
1311  joined_channel = mchannel;
1312  break;
1313  }
1314  }
1315 
1316  if (!joined_channel)
1317  {
1318  SetLastError(ERROR_NOT_FOUND);
1319  return NULL;
1320  }
1321 
1322  channel = (rdpPeerChannel*)joined_channel->handle;
1323 
1324  if (!channel)
1325  {
1326  const UINT32 VCChunkSize =
1327  freerdp_settings_get_uint32(context->settings, FreeRDP_VCChunkSize);
1328 
1329  WINPR_ASSERT(index <= UINT16_MAX);
1330  channel = channel_new(vcm, client, joined_channel->ChannelId, (UINT16)index,
1331  RDP_PEER_CHANNEL_TYPE_SVC, VCChunkSize, pVirtualName);
1332 
1333  if (!channel)
1334  goto fail;
1335 
1336  joined_channel->handle = channel;
1337  }
1338 
1339  hChannelHandle = (HANDLE)channel;
1340  return hChannelHandle;
1341 fail:
1342  channel_free(channel);
1343  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1344  return NULL;
1345 }
1346 
1347 HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
1348 {
1349  wStream* s = NULL;
1350  rdpMcs* mcs = NULL;
1351  BOOL joined = FALSE;
1352  freerdp_peer* client = NULL;
1353  rdpPeerChannel* channel = NULL;
1354  ULONG written = 0;
1355  WTSVirtualChannelManager* vcm = NULL;
1356 
1357  if (SessionId == WTS_CURRENT_SESSION)
1358  return NULL;
1359 
1360  vcm = (WTSVirtualChannelManager*)HashTable_GetItemValue(g_ServerHandles,
1361  (void*)(UINT_PTR)SessionId);
1362 
1363  if (!vcm)
1364  return NULL;
1365 
1366  if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC))
1367  {
1368  return FreeRDP_WTSVirtualChannelOpen((HANDLE)vcm, SessionId, pVirtualName);
1369  }
1370 
1371  client = vcm->client;
1372  mcs = client->context->rdp->mcs;
1373 
1374  for (UINT32 index = 0; index < mcs->channelCount; index++)
1375  {
1376  rdpMcsChannel* mchannel = &mcs->channels[index];
1377  if (mchannel->joined &&
1378  (strncmp(mchannel->Name, DRDYNVC_SVC_CHANNEL_NAME, CHANNEL_NAME_LEN + 1) == 0))
1379  {
1380  joined = TRUE;
1381  break;
1382  }
1383  }
1384 
1385  if (!joined)
1386  {
1387  SetLastError(ERROR_NOT_FOUND);
1388  return NULL;
1389  }
1390 
1391  if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY))
1392  {
1393  SetLastError(ERROR_NOT_READY);
1394  return NULL;
1395  }
1396 
1397  WINPR_ASSERT(client);
1398  WINPR_ASSERT(client->context);
1399  WINPR_ASSERT(client->context->settings);
1400 
1401  const UINT32 VCChunkSize =
1402  freerdp_settings_get_uint32(client->context->settings, FreeRDP_VCChunkSize);
1403  channel = channel_new(vcm, client, 0, 0, RDP_PEER_CHANNEL_TYPE_DVC, VCChunkSize, pVirtualName);
1404 
1405  if (!channel)
1406  {
1407  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1408  return NULL;
1409  }
1410 
1411  const LONG hdl = InterlockedIncrement(&vcm->dvc_channel_id_seq);
1412  channel->channelId = WINPR_ASSERTING_INT_CAST(uint32_t, hdl);
1413 
1414  if (!HashTable_Insert(vcm->dynamicVirtualChannels, &channel->channelId, channel))
1415  {
1416  channel_free(channel);
1417  channel = NULL;
1418  goto fail;
1419  }
1420  s = Stream_New(NULL, 64);
1421 
1422  if (!s)
1423  goto fail;
1424 
1425  if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName))
1426  goto fail;
1427 
1428  const size_t pos = Stream_GetPosition(s);
1429  WINPR_ASSERT(pos <= UINT32_MAX);
1430  if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s, char), (UINT32)pos,
1431  &written))
1432  goto fail;
1433 
1434  Stream_Free(s, TRUE);
1435  return channel;
1436 fail:
1437  Stream_Free(s, TRUE);
1438  if (channel)
1439  HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1440 
1441  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1442  return NULL;
1443 }
1444 
1445 BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
1446 {
1447  wStream* s = NULL;
1448  rdpMcs* mcs = NULL;
1449 
1450  rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1451  BOOL ret = TRUE;
1452 
1453  if (channel)
1454  {
1455  WTSVirtualChannelManager* vcm = channel->vcm;
1456 
1457  WINPR_ASSERT(vcm);
1458  WINPR_ASSERT(vcm->client);
1459  WINPR_ASSERT(vcm->client->context);
1460  WINPR_ASSERT(vcm->client->context->rdp);
1461  mcs = vcm->client->context->rdp->mcs;
1462 
1463  if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1464  {
1465  if (channel->index < mcs->channelCount)
1466  {
1467  rdpMcsChannel* cur = &mcs->channels[channel->index];
1468  rdpPeerChannel* peerChannel = (rdpPeerChannel*)cur->handle;
1469  channel_free(peerChannel);
1470  cur->handle = NULL;
1471  }
1472  }
1473  else
1474  {
1475  if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
1476  {
1477  ULONG written = 0;
1478  s = Stream_New(NULL, 8);
1479 
1480  if (!s)
1481  {
1482  WLog_ERR(TAG, "Stream_New failed!");
1483  ret = FALSE;
1484  }
1485  else
1486  {
1487  wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId);
1488 
1489  const size_t pos = Stream_GetPosition(s);
1490  WINPR_ASSERT(pos <= UINT32_MAX);
1491  ret = WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_BufferAs(s, char),
1492  (UINT32)pos, &written);
1493  Stream_Free(s, TRUE);
1494  }
1495  }
1496  HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1497  }
1498  }
1499 
1500  return ret;
1501 }
1502 
1503 BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer,
1504  ULONG BufferSize, PULONG pBytesRead)
1505 {
1506  BYTE* buffer = NULL;
1507  wMessage message = { 0 };
1508  wtsChannelMessage* messageCtx = NULL;
1509  rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1510 
1511  WINPR_ASSERT(channel);
1512 
1513  if (!MessageQueue_Peek(channel->queue, &message, FALSE))
1514  {
1515  SetLastError(ERROR_NO_DATA);
1516  *pBytesRead = 0;
1517  return FALSE;
1518  }
1519 
1520  messageCtx = message.context;
1521 
1522  if (messageCtx == NULL)
1523  return FALSE;
1524 
1525  buffer = (BYTE*)(messageCtx + 1);
1526  *pBytesRead = messageCtx->length - messageCtx->offset;
1527 
1528  if (Buffer == NULL || BufferSize == 0)
1529  {
1530  return TRUE;
1531  }
1532 
1533  if (*pBytesRead > BufferSize)
1534  *pBytesRead = BufferSize;
1535 
1536  CopyMemory(Buffer, buffer + messageCtx->offset, *pBytesRead);
1537  messageCtx->offset += *pBytesRead;
1538 
1539  if (messageCtx->offset >= messageCtx->length)
1540  {
1541  (void)MessageQueue_Peek(channel->queue, &message, TRUE);
1542  peer_channel_queue_free_message(&message);
1543  }
1544 
1545  return TRUE;
1546 }
1547 
1548 BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length,
1549  PULONG pBytesWritten)
1550 {
1551  wStream* s = NULL;
1552  int cbLen = 0;
1553  int cbChId = 0;
1554  int first = 0;
1555  BYTE* buffer = NULL;
1556  UINT32 totalWritten = 0;
1557  rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1558  BOOL ret = FALSE;
1559 
1560  if (!channel)
1561  return FALSE;
1562 
1563  EnterCriticalSection(&channel->writeLock);
1564  WINPR_ASSERT(channel->vcm);
1565  if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1566  {
1567  const ULONG length = Length;
1568  buffer = (BYTE*)malloc(length);
1569 
1570  if (!buffer)
1571  {
1572  SetLastError(E_OUTOFMEMORY);
1573  goto fail;
1574  }
1575 
1576  CopyMemory(buffer, Buffer, length);
1577  totalWritten = Length;
1578  if (!wts_queue_send_item(channel, buffer, length))
1579  goto fail;
1580  }
1581  else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
1582  {
1583  DEBUG_DVC("drdynvc not ready");
1584  goto fail;
1585  }
1586  else
1587  {
1588  rdpContext* context = NULL;
1589 
1590  first = TRUE;
1591  WINPR_ASSERT(channel->client);
1592  context = channel->client->context;
1593  WINPR_ASSERT(context);
1594  while (Length > 0)
1595  {
1596  s = Stream_New(NULL, DVC_MAX_DATA_PDU_SIZE);
1597 
1598  if (!s)
1599  {
1600  WLog_ERR(TAG, "Stream_New failed!");
1601  SetLastError(E_OUTOFMEMORY);
1602  goto fail;
1603  }
1604 
1605  buffer = Stream_Buffer(s);
1606  Stream_Seek_UINT8(s);
1607  cbChId = wts_write_variable_uint(s, channel->channelId);
1608 
1609  if (first && (Length > Stream_GetRemainingLength(s)))
1610  {
1611  cbLen = wts_write_variable_uint(s, Length);
1612  buffer[0] = ((DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId) & 0xFF;
1613  }
1614  else
1615  {
1616  buffer[0] = ((DATA_PDU << 4) | cbChId) & 0xFF;
1617  }
1618 
1619  first = FALSE;
1620  size_t written = Stream_GetRemainingLength(s);
1621 
1622  if (written > Length)
1623  written = Length;
1624 
1625  Stream_Write(s, Buffer, written);
1626  const size_t length = Stream_GetPosition(s);
1627  Stream_Free(s, FALSE);
1628  if (length > UINT32_MAX)
1629  goto fail;
1630  Length -= written;
1631  Buffer += written;
1632  totalWritten += written;
1633  if (!wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, (UINT32)length))
1634  goto fail;
1635  }
1636  }
1637 
1638  if (pBytesWritten)
1639  *pBytesWritten = totalWritten;
1640 
1641  ret = TRUE;
1642 fail:
1643  LeaveCriticalSection(&channel->writeLock);
1644  return ret;
1645 }
1646 
1647 BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(HANDLE hChannelHandle)
1648 {
1649  return TRUE;
1650 }
1651 
1652 BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle)
1653 {
1654  return TRUE;
1655 }
1656 
1657 BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
1658  PVOID* ppBuffer, DWORD* pBytesReturned)
1659 {
1660  void* pfd = NULL;
1661  BOOL bval = 0;
1662  void* fds[10] = { 0 };
1663  HANDLE hEvent = NULL;
1664  int fds_count = 0;
1665  BOOL status = FALSE;
1666  rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1667 
1668  WINPR_ASSERT(channel);
1669 
1670  switch ((UINT32)WtsVirtualClass)
1671  {
1672  case WTSVirtualFileHandle:
1673  hEvent = MessageQueue_Event(channel->queue);
1674  pfd = GetEventWaitObject(hEvent);
1675 
1676  if (pfd)
1677  {
1678  fds[fds_count] = pfd;
1679  (fds_count)++;
1680  }
1681 
1682  *ppBuffer = malloc(sizeof(void*));
1683 
1684  if (!*ppBuffer)
1685  {
1686  SetLastError(E_OUTOFMEMORY);
1687  }
1688  else
1689  {
1690  CopyMemory(*ppBuffer, (void*)&fds[0], sizeof(void*));
1691  *pBytesReturned = sizeof(void*);
1692  status = TRUE;
1693  }
1694 
1695  break;
1696 
1697  case WTSVirtualEventHandle:
1698  hEvent = MessageQueue_Event(channel->queue);
1699 
1700  *ppBuffer = malloc(sizeof(HANDLE));
1701 
1702  if (!*ppBuffer)
1703  {
1704  SetLastError(E_OUTOFMEMORY);
1705  }
1706  else
1707  {
1708  CopyMemory(*ppBuffer, (void*)&hEvent, sizeof(HANDLE));
1709  *pBytesReturned = sizeof(void*);
1710  status = TRUE;
1711  }
1712 
1713  break;
1714 
1715  case WTSVirtualChannelReady:
1716  if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1717  {
1718  bval = TRUE;
1719  status = TRUE;
1720  }
1721  else
1722  {
1723  switch (channel->dvc_open_state)
1724  {
1725  case DVC_OPEN_STATE_NONE:
1726  bval = FALSE;
1727  status = TRUE;
1728  break;
1729 
1730  case DVC_OPEN_STATE_SUCCEEDED:
1731  bval = TRUE;
1732  status = TRUE;
1733  break;
1734 
1735  default:
1736  *ppBuffer = NULL;
1737  *pBytesReturned = 0;
1738  return FALSE;
1739  }
1740  }
1741 
1742  *ppBuffer = malloc(sizeof(BOOL));
1743 
1744  if (!*ppBuffer)
1745  {
1746  SetLastError(E_OUTOFMEMORY);
1747  status = FALSE;
1748  }
1749  else
1750  {
1751  CopyMemory(*ppBuffer, &bval, sizeof(BOOL));
1752  *pBytesReturned = sizeof(BOOL);
1753  }
1754 
1755  break;
1756  case WTSVirtualChannelOpenStatus:
1757  {
1758  INT32 value = channel->creationStatus;
1759  status = TRUE;
1760 
1761  *ppBuffer = malloc(sizeof(value));
1762  if (!*ppBuffer)
1763  {
1764  SetLastError(E_OUTOFMEMORY);
1765  status = FALSE;
1766  }
1767  else
1768  {
1769  CopyMemory(*ppBuffer, &value, sizeof(value));
1770  *pBytesReturned = sizeof(value);
1771  }
1772  break;
1773  }
1774  default:
1775  break;
1776  }
1777 
1778  return status;
1779 }
1780 
1781 VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory)
1782 {
1783  free(pMemory);
1784 }
1785 
1786 BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
1787  ULONG NumberOfEntries)
1788 {
1789  return FALSE;
1790 }
1791 
1792 BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
1793  ULONG NumberOfEntries)
1794 {
1795  return FALSE;
1796 }
1797 
1798 BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)
1799 {
1800  return FALSE;
1801 }
1802 
1803 BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(HWND hWnd)
1804 {
1805  return FALSE;
1806 }
1807 
1808 BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags)
1809 {
1810  return FALSE;
1811 }
1812 
1813 BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd)
1814 {
1815  return FALSE;
1816 }
1817 
1818 BOOL WINAPI FreeRDP_WTSQueryUserToken(ULONG SessionId, PHANDLE phToken)
1819 {
1820  return FALSE;
1821 }
1822 
1823 BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
1824  LPWSTR* ppProcessInfo, DWORD* pCount)
1825 {
1826  return FALSE;
1827 }
1828 
1829 BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
1830  LPSTR* ppProcessInfo, DWORD* pCount)
1831 {
1832  return FALSE;
1833 }
1834 
1835 BOOL WINAPI FreeRDP_WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1836  PWTSLISTENERNAMEW pListeners, DWORD* pCount)
1837 {
1838  return FALSE;
1839 }
1840 
1841 BOOL WINAPI FreeRDP_WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1842  PWTSLISTENERNAMEA pListeners, DWORD* pCount)
1843 {
1844  return FALSE;
1845 }
1846 
1847 BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1848  LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer)
1849 {
1850  return FALSE;
1851 }
1852 
1853 BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1854  LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer)
1855 {
1856  return FALSE;
1857 }
1858 
1859 BOOL WINAPI FreeRDP_WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1860  LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer,
1861  DWORD flag)
1862 {
1863  return FALSE;
1864 }
1865 
1866 BOOL WINAPI FreeRDP_WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1867  LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag)
1868 {
1869  return FALSE;
1870 }
1871 
1872 BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1873  LPWSTR pListenerName,
1874  SECURITY_INFORMATION SecurityInformation,
1875  PSECURITY_DESCRIPTOR pSecurityDescriptor)
1876 {
1877  return FALSE;
1878 }
1879 
1880 BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1881  LPSTR pListenerName,
1882  SECURITY_INFORMATION SecurityInformation,
1883  PSECURITY_DESCRIPTOR pSecurityDescriptor)
1884 {
1885  return FALSE;
1886 }
1887 
1888 BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1889  LPWSTR pListenerName,
1890  SECURITY_INFORMATION SecurityInformation,
1891  PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
1892  LPDWORD lpnLengthNeeded)
1893 {
1894  return FALSE;
1895 }
1896 
1897 BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1898  LPSTR pListenerName,
1899  SECURITY_INFORMATION SecurityInformation,
1900  PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
1901  LPDWORD lpnLengthNeeded)
1902 {
1903  return FALSE;
1904 }
1905 
1906 BOOL CDECL FreeRDP_WTSEnableChildSessions(BOOL bEnable)
1907 {
1908  return FALSE;
1909 }
1910 
1911 BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(PBOOL pbEnabled)
1912 {
1913  return FALSE;
1914 }
1915 
1916 BOOL CDECL FreeRDP_WTSGetChildSessionId(PULONG pSessionId)
1917 {
1918  return FALSE;
1919 }
1920 
1921 DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(void)
1922 {
1923  return 0xFFFFFFFF;
1924 }
1925 BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer)
1926 {
1927  return FALSE;
1928 }
1929 
1930 BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain)
1931 {
1932  return FALSE;
1933 }
1934 
1935 void server_channel_common_free(rdpPeerChannel* channel)
1936 {
1937  if (!channel)
1938  return;
1939  MessageQueue_Free(channel->queue);
1940  Stream_Free(channel->receiveData, TRUE);
1941  DeleteCriticalSection(&channel->writeLock);
1942  free(channel);
1943 }
1944 
1945 rdpPeerChannel* server_channel_common_new(freerdp_peer* client, UINT16 index, UINT32 channelId,
1946  size_t chunkSize, const wObject* callback,
1947  const char* name)
1948 {
1949  rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel));
1950  if (!channel)
1951  return NULL;
1952 
1953  InitializeCriticalSection(&channel->writeLock);
1954 
1955  channel->receiveData = Stream_New(NULL, chunkSize);
1956  if (!channel->receiveData)
1957  goto fail;
1958 
1959  channel->queue = MessageQueue_New(callback);
1960  if (!channel->queue)
1961  goto fail;
1962 
1963  channel->index = index;
1964  channel->client = client;
1965  channel->channelId = channelId;
1966  strncpy(channel->channelName, name, ARRAYSIZE(channel->channelName) - 1);
1967  return channel;
1968 fail:
1969  WINPR_PRAGMA_DIAG_PUSH
1970  WINPR_PRAGMA_DIAG_IGNORED_MISMATCHED_DEALLOC
1971  server_channel_common_free(channel);
1972  WINPR_PRAGMA_DIAG_POP
1973  return NULL;
1974 }
FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
This struct contains function pointer to initialize/free objects.
Definition: collections.h:57