Coverage Report

Created: 2024-05-20 06:11

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