Coverage Report

Created: 2023-11-19 06:16

/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;
74
0
  wtsChannelMessage* messageCtx;
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;
93
0
  UINT32 length;
94
0
  UINT16 channelId;
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;
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;
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;
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;
268
0
  UINT8 value;
269
0
  UINT8 Cmd;
270
0
  UINT8 Sp;
271
0
  UINT8 cbChId;
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;
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;
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;
412
0
  int cbChId;
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;
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
  UINT32 i;
487
0
  rdpMcs* mcs;
488
489
0
  WINPR_ASSERT(client);
490
0
  WINPR_ASSERT(client->context);
491
0
  WINPR_ASSERT(client->context->rdp);
492
493
0
  mcs = client->context->rdp->mcs;
494
0
  WINPR_ASSERT(mcs);
495
496
0
  for (i = 0; i < mcs->channelCount; i++)
497
0
  {
498
0
    rdpMcsChannel* cur = &mcs->channels[i];
499
0
    if (cur->ChannelId == channelId)
500
0
    {
501
0
      rdpPeerChannel* channel = (rdpPeerChannel*)cur->handle;
502
503
0
      if (channel)
504
0
        return WTSProcessChannelData(channel, channelId, data, size, flags, totalSize);
505
0
    }
506
0
  }
507
508
0
  WLog_WARN(TAG, "unknown channelId %" PRIu16 " ignored", channelId);
509
510
0
  return TRUE;
511
0
}
512
513
#if defined(WITH_FREERDP_DEPRECATED)
514
void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer, void** fds, int* fds_count)
515
{
516
  void* fd;
517
  WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
518
  WINPR_ASSERT(vcm);
519
  WINPR_ASSERT(fds);
520
  WINPR_ASSERT(fds_count);
521
522
  fd = GetEventWaitObject(MessageQueue_Event(vcm->queue));
523
524
  if (fd)
525
  {
526
    fds[*fds_count] = fd;
527
    (*fds_count)++;
528
  }
529
530
#if 0
531
532
  if (vcm->drdynvc_channel)
533
  {
534
    fd = GetEventWaitObject(vcm->drdynvc_channel->receiveEvent);
535
536
    if (fd)
537
    {
538
      fds[*fds_count] = fd;
539
      (*fds_count)++;
540
    }
541
  }
542
543
#endif
544
}
545
#endif
546
547
BOOL WTSVirtualChannelManagerOpen(HANDLE hServer)
548
0
{
549
0
  WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
550
551
0
  if (!vcm)
552
0
    return FALSE;
553
554
0
  if (vcm->drdynvc_state == DRDYNVC_STATE_NONE)
555
0
  {
556
0
    rdpPeerChannel* channel;
557
558
    /* Initialize drdynvc channel once and only once. */
559
0
    vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
560
0
    channel = (rdpPeerChannel*)WTSVirtualChannelOpen((HANDLE)vcm, WTS_CURRENT_SESSION,
561
0
                                                     DRDYNVC_SVC_CHANNEL_NAME);
562
563
0
    if (channel)
564
0
    {
565
0
      BYTE capaBuffer[12];
566
0
      wStream staticS;
567
0
      wStream* s = Stream_StaticInit(&staticS, capaBuffer, sizeof(capaBuffer));
568
569
0
      vcm->drdynvc_channel = channel;
570
0
      vcm->dvc_spoken_version = 1;
571
0
      Stream_Write_UINT8(s, 0x50);    /* Cmd=5 sp=0 cbId=0 */
572
0
      Stream_Write_UINT8(s, 0x00);    /* Pad */
573
0
      Stream_Write_UINT16(s, 0x0001); /* Version */
574
575
      /* TODO: shall implement version 2 and 3 */
576
577
0
      ULONG written;
578
0
      if (!WTSVirtualChannelWrite(channel, (PCHAR)capaBuffer, Stream_GetPosition(s),
579
0
                                  &written))
580
0
        return FALSE;
581
0
    }
582
0
  }
583
584
0
  return TRUE;
585
0
}
586
587
BOOL WTSVirtualChannelManagerCheckFileDescriptorEx(HANDLE hServer, BOOL autoOpen)
588
0
{
589
0
  wMessage message = { 0 };
590
0
  BOOL status = TRUE;
591
0
  WTSVirtualChannelManager* vcm = NULL;
592
593
0
  if (!hServer || hServer == INVALID_HANDLE_VALUE)
594
0
    return FALSE;
595
596
0
  vcm = (WTSVirtualChannelManager*)hServer;
597
598
0
  if (autoOpen)
599
0
  {
600
0
    if (!WTSVirtualChannelManagerOpen(hServer))
601
0
      return FALSE;
602
0
  }
603
604
0
  while (MessageQueue_Peek(vcm->queue, &message, TRUE))
605
0
  {
606
0
    BYTE* buffer;
607
0
    UINT32 length;
608
0
    UINT16 channelId;
609
0
    channelId = (UINT16)(UINT_PTR)message.context;
610
0
    buffer = (BYTE*)message.wParam;
611
0
    length = (UINT32)(UINT_PTR)message.lParam;
612
613
0
    WINPR_ASSERT(vcm->client);
614
0
    WINPR_ASSERT(vcm->client->SendChannelData);
615
0
    if (!vcm->client->SendChannelData(vcm->client, channelId, buffer, length))
616
0
    {
617
0
      status = FALSE;
618
0
    }
619
620
0
    free(buffer);
621
622
0
    if (!status)
623
0
      break;
624
0
  }
625
626
0
  return status;
627
0
}
628
629
BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)
630
0
{
631
0
  return WTSVirtualChannelManagerCheckFileDescriptorEx(hServer, TRUE);
632
0
}
633
634
HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer)
635
0
{
636
0
  WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
637
0
  WINPR_ASSERT(vcm);
638
0
  return MessageQueue_Event(vcm->queue);
639
0
}
640
641
static rdpMcsChannel* wts_get_joined_channel_by_name(rdpMcs* mcs, const char* channel_name)
642
0
{
643
0
  UINT32 index;
644
645
0
  if (!mcs || !channel_name || !strnlen(channel_name, CHANNEL_NAME_LEN + 1))
646
0
    return NULL;
647
648
0
  for (index = 0; index < mcs->channelCount; index++)
649
0
  {
650
0
    rdpMcsChannel* mchannel = &mcs->channels[index];
651
0
    if (mchannel->joined)
652
0
    {
653
0
      if (_strnicmp(mchannel->Name, channel_name, CHANNEL_NAME_LEN + 1) == 0)
654
0
        return mchannel;
655
0
    }
656
0
  }
657
658
0
  return NULL;
659
0
}
660
661
static rdpMcsChannel* wts_get_joined_channel_by_id(rdpMcs* mcs, const UINT16 channel_id)
662
0
{
663
0
  UINT32 index;
664
665
0
  if (!mcs || !channel_id)
666
0
    return NULL;
667
668
0
  WINPR_ASSERT(mcs->channels);
669
0
  for (index = 0; index < mcs->channelCount; index++)
670
0
  {
671
0
    rdpMcsChannel* mchannel = &mcs->channels[index];
672
0
    if (mchannel->joined)
673
0
    {
674
0
      if (mchannel->ChannelId == channel_id)
675
0
        return &mcs->channels[index];
676
0
    }
677
0
  }
678
679
0
  return NULL;
680
0
}
681
682
BOOL WTSIsChannelJoinedByName(freerdp_peer* client, const char* channel_name)
683
0
{
684
0
  if (!client || !client->context || !client->context->rdp)
685
0
    return FALSE;
686
687
0
  return wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name) == NULL ? FALSE
688
0
                                                                                         : TRUE;
689
0
}
690
691
BOOL WTSIsChannelJoinedById(freerdp_peer* client, const UINT16 channel_id)
692
0
{
693
0
  if (!client || !client->context || !client->context->rdp)
694
0
    return FALSE;
695
696
0
  return wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id) == NULL ? FALSE
697
0
                                                                                     : TRUE;
698
0
}
699
700
BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer, const char* name)
701
0
{
702
0
  WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
703
704
0
  if (!vcm || !vcm->rdp)
705
0
    return FALSE;
706
707
0
  return wts_get_joined_channel_by_name(vcm->rdp->mcs, name) == NULL ? FALSE : TRUE;
708
0
}
709
710
BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)
711
0
{
712
0
  WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
713
0
  WINPR_ASSERT(vcm);
714
0
  return vcm->drdynvc_state;
715
0
}
716
717
void WTSVirtualChannelManagerSetDVCCreationCallback(HANDLE hServer, psDVCCreationStatusCallback cb,
718
                                                    void* userdata)
719
0
{
720
0
  WTSVirtualChannelManager* vcm = hServer;
721
722
0
  WINPR_ASSERT(vcm);
723
724
0
  vcm->dvc_creation_status = cb;
725
0
  vcm->dvc_creation_status_userdata = userdata;
726
0
}
727
728
UINT16 WTSChannelGetId(freerdp_peer* client, const char* channel_name)
729
0
{
730
0
  rdpMcsChannel* channel;
731
732
0
  WINPR_ASSERT(channel_name);
733
0
  if (!client || !client->context || !client->context->rdp)
734
0
    return 0;
735
736
0
  channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
737
738
0
  if (!channel)
739
0
    return 0;
740
741
0
  return channel->ChannelId;
742
0
}
743
744
UINT32 WTSChannelGetIdByHandle(HANDLE hChannelHandle)
745
0
{
746
0
  rdpPeerChannel* channel = hChannelHandle;
747
748
0
  WINPR_ASSERT(channel);
749
750
0
  return channel->channelId;
751
0
}
752
753
BOOL WTSChannelSetHandleByName(freerdp_peer* client, const char* channel_name, void* handle)
754
0
{
755
0
  rdpMcsChannel* channel;
756
757
0
  WINPR_ASSERT(channel_name);
758
0
  if (!client || !client->context || !client->context->rdp)
759
0
    return FALSE;
760
761
0
  channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
762
763
0
  if (!channel)
764
0
    return FALSE;
765
766
0
  channel->handle = handle;
767
0
  return TRUE;
768
0
}
769
770
BOOL WTSChannelSetHandleById(freerdp_peer* client, const UINT16 channel_id, void* handle)
771
0
{
772
0
  rdpMcsChannel* channel;
773
774
0
  if (!client || !client->context || !client->context->rdp)
775
0
    return FALSE;
776
777
0
  channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
778
779
0
  if (!channel)
780
0
    return FALSE;
781
782
0
  channel->handle = handle;
783
0
  return TRUE;
784
0
}
785
786
void* WTSChannelGetHandleByName(freerdp_peer* client, const char* channel_name)
787
0
{
788
0
  rdpMcsChannel* channel;
789
790
0
  WINPR_ASSERT(channel_name);
791
0
  if (!client || !client->context || !client->context->rdp)
792
0
    return NULL;
793
794
0
  channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
795
796
0
  if (!channel)
797
0
    return NULL;
798
799
0
  return channel->handle;
800
0
}
801
802
void* WTSChannelGetHandleById(freerdp_peer* client, const UINT16 channel_id)
803
0
{
804
0
  rdpMcsChannel* channel;
805
806
0
  if (!client || !client->context || !client->context->rdp)
807
0
    return NULL;
808
809
0
  channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
810
811
0
  if (!channel)
812
0
    return NULL;
813
814
0
  return channel->handle;
815
0
}
816
817
const char* WTSChannelGetName(freerdp_peer* client, UINT16 channel_id)
818
0
{
819
0
  rdpMcsChannel* channel;
820
821
0
  if (!client || !client->context || !client->context->rdp)
822
0
    return NULL;
823
824
0
  channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
825
826
0
  if (!channel)
827
0
    return NULL;
828
829
0
  return (const char*)channel->Name;
830
0
}
831
832
char** WTSGetAcceptedChannelNames(freerdp_peer* client, size_t* count)
833
0
{
834
0
  rdpMcs* mcs;
835
0
  char** names;
836
0
  UINT32 index;
837
838
0
  if (!client || !client->context || !count)
839
0
    return NULL;
840
841
0
  WINPR_ASSERT(client->context->rdp);
842
0
  mcs = client->context->rdp->mcs;
843
0
  WINPR_ASSERT(mcs);
844
0
  *count = mcs->channelCount;
845
846
0
  names = (char**)calloc(mcs->channelCount, sizeof(char*));
847
0
  if (!names)
848
0
    return NULL;
849
850
0
  for (index = 0; index < mcs->channelCount; index++)
851
0
  {
852
0
    rdpMcsChannel* mchannel = &mcs->channels[index];
853
0
    names[index] = mchannel->Name;
854
0
  }
855
856
0
  return names;
857
0
}
858
859
INT64 WTSChannelGetOptions(freerdp_peer* client, UINT16 channel_id)
860
0
{
861
0
  rdpMcsChannel* channel;
862
863
0
  if (!client || !client->context || !client->context->rdp)
864
0
    return -1;
865
866
0
  channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
867
868
0
  if (!channel)
869
0
    return -1;
870
871
0
  return (INT64)channel->options;
872
0
}
873
874
BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId,
875
                                                  BYTE HotkeyVk, USHORT HotkeyModifiers)
876
0
{
877
0
  return FALSE;
878
0
}
879
880
BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId,
881
                                                  BYTE HotkeyVk, USHORT HotkeyModifiers)
882
0
{
883
0
  return FALSE;
884
0
}
885
886
BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExW(LPWSTR pTargetServerName, ULONG TargetLogonId,
887
                                                    BYTE HotkeyVk, USHORT HotkeyModifiers,
888
                                                    DWORD flags)
889
0
{
890
0
  return FALSE;
891
0
}
892
893
BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExA(LPSTR pTargetServerName, ULONG TargetLogonId,
894
                                                    BYTE HotkeyVk, USHORT HotkeyModifiers,
895
                                                    DWORD flags)
896
0
{
897
0
  return FALSE;
898
0
}
899
900
BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(ULONG LogonId)
901
0
{
902
0
  return FALSE;
903
0
}
904
905
BOOL WINAPI FreeRDP_WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword,
906
                                       BOOL bWait)
907
0
{
908
0
  return FALSE;
909
0
}
910
911
BOOL WINAPI FreeRDP_WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword,
912
                                       BOOL bWait)
913
0
{
914
0
  return FALSE;
915
0
}
916
917
BOOL WINAPI FreeRDP_WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version,
918
                                         PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount)
919
0
{
920
0
  return FALSE;
921
0
}
922
923
BOOL WINAPI FreeRDP_WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version,
924
                                         PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount)
925
0
{
926
0
  return FALSE;
927
0
}
928
929
HANDLE WINAPI FreeRDP_WTSOpenServerW(LPWSTR pServerName)
930
0
{
931
0
  return INVALID_HANDLE_VALUE;
932
0
}
933
934
static void wts_virtual_channel_manager_free_message(void* obj)
935
0
{
936
0
  wMessage* msg = (wMessage*)obj;
937
938
0
  if (msg)
939
0
  {
940
0
    BYTE* buffer = (BYTE*)msg->wParam;
941
942
0
    if (buffer)
943
0
      free(buffer);
944
0
  }
945
0
}
946
947
static void channel_free(rdpPeerChannel* channel);
948
949
static void array_channel_free(void* ptr)
950
0
{
951
0
  rdpPeerChannel* channel = ptr;
952
0
  channel_free(channel);
953
0
}
954
955
static BOOL dynChannelMatch(const void* v1, const void* v2)
956
0
{
957
0
  const UINT32* p1 = (const UINT32*)v1;
958
0
  const UINT32* p2 = (const UINT32*)v2;
959
0
  return *p1 == *p2;
960
0
}
961
962
static UINT32 channelId_Hash(const void* key)
963
0
{
964
0
  const UINT32* v = (const UINT32*)key;
965
0
  return *v;
966
0
}
967
968
HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName)
969
0
{
970
0
  rdpContext* context;
971
0
  freerdp_peer* client;
972
0
  WTSVirtualChannelManager* vcm;
973
0
  HANDLE hServer = INVALID_HANDLE_VALUE;
974
0
  wObject queueCallbacks = { 0 };
975
976
0
  context = (rdpContext*)pServerName;
977
978
0
  if (!context)
979
0
    return INVALID_HANDLE_VALUE;
980
981
0
  client = context->peer;
982
983
0
  if (!client)
984
0
  {
985
0
    SetLastError(ERROR_INVALID_DATA);
986
0
    return INVALID_HANDLE_VALUE;
987
0
  }
988
989
0
  vcm = (WTSVirtualChannelManager*)calloc(1, sizeof(WTSVirtualChannelManager));
990
991
0
  if (!vcm)
992
0
    goto error_vcm_alloc;
993
994
0
  vcm->client = client;
995
0
  vcm->rdp = context->rdp;
996
0
  vcm->SessionId = g_SessionId++;
997
998
0
  if (!g_ServerHandles)
999
0
  {
1000
0
    g_ServerHandles = HashTable_New(TRUE);
1001
1002
0
    if (!g_ServerHandles)
1003
0
      goto error_free;
1004
0
  }
1005
1006
0
  if (!HashTable_Insert(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId, (void*)vcm))
1007
0
    goto error_free;
1008
1009
0
  queueCallbacks.fnObjectFree = wts_virtual_channel_manager_free_message;
1010
0
  vcm->queue = MessageQueue_New(&queueCallbacks);
1011
1012
0
  if (!vcm->queue)
1013
0
    goto error_queue;
1014
1015
0
  vcm->dvc_channel_id_seq = 0;
1016
0
  vcm->dynamicVirtualChannels = HashTable_New(TRUE);
1017
1018
0
  if (!vcm->dynamicVirtualChannels)
1019
0
    goto error_dynamicVirtualChannels;
1020
1021
0
  if (!HashTable_SetHashFunction(vcm->dynamicVirtualChannels, channelId_Hash))
1022
0
    goto error_hashFunction;
1023
1024
0
  {
1025
0
    wObject* obj = HashTable_ValueObject(vcm->dynamicVirtualChannels);
1026
0
    WINPR_ASSERT(obj);
1027
0
    obj->fnObjectFree = array_channel_free;
1028
1029
0
    obj = HashTable_KeyObject(vcm->dynamicVirtualChannels);
1030
0
    obj->fnObjectEquals = dynChannelMatch;
1031
0
  }
1032
0
  client->ReceiveChannelData = WTSReceiveChannelData;
1033
0
  hServer = (HANDLE)vcm;
1034
0
  return hServer;
1035
1036
0
error_hashFunction:
1037
0
  HashTable_Free(vcm->dynamicVirtualChannels);
1038
0
error_dynamicVirtualChannels:
1039
0
  MessageQueue_Free(vcm->queue);
1040
0
error_queue:
1041
0
  HashTable_Remove(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId);
1042
0
error_free:
1043
0
  free(vcm);
1044
0
error_vcm_alloc:
1045
0
  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1046
0
  return INVALID_HANDLE_VALUE;
1047
0
}
1048
1049
HANDLE WINAPI FreeRDP_WTSOpenServerExW(LPWSTR pServerName)
1050
0
{
1051
0
  return INVALID_HANDLE_VALUE;
1052
0
}
1053
1054
HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName)
1055
0
{
1056
0
  return FreeRDP_WTSOpenServerA(pServerName);
1057
0
}
1058
1059
VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer)
1060
0
{
1061
0
  WTSVirtualChannelManager* vcm;
1062
0
  vcm = (WTSVirtualChannelManager*)hServer;
1063
1064
0
  if (vcm && (vcm != INVALID_HANDLE_VALUE))
1065
0
  {
1066
0
    HashTable_Remove(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId);
1067
1068
0
    HashTable_Free(vcm->dynamicVirtualChannels);
1069
1070
0
    if (vcm->drdynvc_channel)
1071
0
    {
1072
0
      WTSVirtualChannelClose(vcm->drdynvc_channel);
1073
0
      vcm->drdynvc_channel = NULL;
1074
0
    }
1075
1076
0
    MessageQueue_Free(vcm->queue);
1077
0
    free(vcm);
1078
0
  }
1079
0
}
1080
1081
BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version,
1082
                                          PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount)
1083
0
{
1084
0
  return FALSE;
1085
0
}
1086
1087
BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version,
1088
                                          PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount)
1089
0
{
1090
0
  return FALSE;
1091
0
}
1092
1093
BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter,
1094
                                            PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount)
1095
0
{
1096
0
  return FALSE;
1097
0
}
1098
1099
BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter,
1100
                                            PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount)
1101
0
{
1102
0
  return FALSE;
1103
0
}
1104
1105
BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version,
1106
                                           PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount)
1107
0
{
1108
0
  return FALSE;
1109
0
}
1110
1111
BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version,
1112
                                           PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount)
1113
0
{
1114
0
  return FALSE;
1115
0
}
1116
1117
BOOL WINAPI FreeRDP_WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode)
1118
0
{
1119
0
  return FALSE;
1120
0
}
1121
1122
BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId,
1123
                                                WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer,
1124
                                                DWORD* pBytesReturned)
1125
0
{
1126
0
  return FALSE;
1127
0
}
1128
1129
BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId,
1130
                                                WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer,
1131
                                                DWORD* pBytesReturned)
1132
0
{
1133
0
  DWORD BytesReturned;
1134
0
  WTSVirtualChannelManager* vcm;
1135
0
  vcm = (WTSVirtualChannelManager*)hServer;
1136
1137
0
  if (!vcm)
1138
0
    return FALSE;
1139
1140
0
  if (WTSInfoClass == WTSSessionId)
1141
0
  {
1142
0
    ULONG* pBuffer;
1143
0
    BytesReturned = sizeof(ULONG);
1144
0
    pBuffer = (ULONG*)malloc(sizeof(BytesReturned));
1145
1146
0
    if (!pBuffer)
1147
0
    {
1148
0
      SetLastError(E_OUTOFMEMORY);
1149
0
      return FALSE;
1150
0
    }
1151
1152
0
    *pBuffer = vcm->SessionId;
1153
0
    *ppBuffer = (LPSTR)pBuffer;
1154
0
    *pBytesReturned = BytesReturned;
1155
0
    return TRUE;
1156
0
  }
1157
1158
0
  return FALSE;
1159
0
}
1160
1161
BOOL WINAPI FreeRDP_WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
1162
                                        WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer,
1163
                                        DWORD* pBytesReturned)
1164
0
{
1165
0
  return FALSE;
1166
0
}
1167
1168
BOOL WINAPI FreeRDP_WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName,
1169
                                        WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer,
1170
                                        DWORD* pBytesReturned)
1171
0
{
1172
0
  return FALSE;
1173
0
}
1174
1175
BOOL WINAPI FreeRDP_WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
1176
                                      WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer,
1177
                                      DWORD DataLength)
1178
0
{
1179
0
  return FALSE;
1180
0
}
1181
1182
BOOL WINAPI FreeRDP_WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName,
1183
                                      WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer,
1184
                                      DWORD DataLength)
1185
0
{
1186
0
  return FALSE;
1187
0
}
1188
1189
BOOL WINAPI FreeRDP_WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle,
1190
                                    DWORD TitleLength, LPWSTR pMessage, DWORD MessageLength,
1191
                                    DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait)
1192
0
{
1193
0
  return FALSE;
1194
0
}
1195
1196
BOOL WINAPI FreeRDP_WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle,
1197
                                    DWORD TitleLength, LPSTR pMessage, DWORD MessageLength,
1198
                                    DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait)
1199
0
{
1200
0
  return FALSE;
1201
0
}
1202
1203
BOOL WINAPI FreeRDP_WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
1204
0
{
1205
0
  return FALSE;
1206
0
}
1207
1208
BOOL WINAPI FreeRDP_WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
1209
0
{
1210
0
  return FALSE;
1211
0
}
1212
1213
BOOL WINAPI FreeRDP_WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag)
1214
0
{
1215
0
  return FALSE;
1216
0
}
1217
1218
BOOL WINAPI FreeRDP_WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags)
1219
0
{
1220
0
  return FALSE;
1221
0
}
1222
1223
static void peer_channel_queue_free_message(void* obj)
1224
0
{
1225
0
  wMessage* msg = (wMessage*)obj;
1226
0
  if (!msg)
1227
0
    return;
1228
1229
0
  free(msg->context);
1230
0
  msg->context = NULL;
1231
0
}
1232
1233
void channel_free(rdpPeerChannel* channel)
1234
0
{
1235
0
  if (!channel)
1236
0
    return;
1237
1238
0
  MessageQueue_Free(channel->queue);
1239
0
  Stream_Free(channel->receiveData, TRUE);
1240
0
  free(channel);
1241
0
}
1242
1243
static rdpPeerChannel* channel_new(WTSVirtualChannelManager* vcm, freerdp_peer* client,
1244
                                   UINT32 ChannelId, UINT16 index, UINT16 type, size_t chunkSize,
1245
                                   const char* name)
1246
0
{
1247
0
  size_t len;
1248
0
  wObject queueCallbacks = { 0 };
1249
0
  rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel));
1250
1251
0
  WINPR_ASSERT(vcm);
1252
0
  WINPR_ASSERT(client);
1253
1254
0
  if (!channel)
1255
0
    goto fail;
1256
1257
0
  len = strnlen(name, sizeof(channel->channelName) - 1);
1258
0
  strncpy(channel->channelName, name, len);
1259
1260
0
  channel->vcm = vcm;
1261
0
  channel->client = client;
1262
0
  channel->channelId = ChannelId;
1263
0
  channel->index = index;
1264
0
  channel->channelType = type;
1265
0
  channel->creationStatus =
1266
0
      (type == RDP_PEER_CHANNEL_TYPE_SVC) ? ERROR_SUCCESS : ERROR_OPERATION_IN_PROGRESS;
1267
0
  channel->receiveData = Stream_New(NULL, chunkSize);
1268
1269
0
  if (!channel->receiveData)
1270
0
    goto fail;
1271
1272
0
  queueCallbacks.fnObjectFree = peer_channel_queue_free_message;
1273
1274
0
  channel->queue = MessageQueue_New(&queueCallbacks);
1275
1276
0
  if (!channel->queue)
1277
0
    goto fail;
1278
1279
0
  return channel;
1280
0
fail:
1281
0
  channel_free(channel);
1282
0
  return NULL;
1283
0
}
1284
1285
HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
1286
0
{
1287
0
  size_t length;
1288
0
  UINT32 index;
1289
0
  rdpMcs* mcs;
1290
0
  rdpMcsChannel* joined_channel = NULL;
1291
0
  freerdp_peer* client;
1292
0
  rdpPeerChannel* channel = NULL;
1293
0
  WTSVirtualChannelManager* vcm;
1294
0
  HANDLE hChannelHandle = NULL;
1295
0
  rdpContext* context;
1296
0
  vcm = (WTSVirtualChannelManager*)hServer;
1297
1298
0
  if (!vcm)
1299
0
  {
1300
0
    SetLastError(ERROR_INVALID_DATA);
1301
0
    return NULL;
1302
0
  }
1303
1304
0
  client = vcm->client;
1305
0
  WINPR_ASSERT(client);
1306
1307
0
  context = client->context;
1308
0
  WINPR_ASSERT(context);
1309
0
  WINPR_ASSERT(context->rdp);
1310
0
  WINPR_ASSERT(context->settings);
1311
1312
0
  mcs = context->rdp->mcs;
1313
0
  WINPR_ASSERT(mcs);
1314
1315
0
  length = strnlen(pVirtualName, CHANNEL_NAME_LEN + 1);
1316
1317
0
  if (length > CHANNEL_NAME_LEN)
1318
0
  {
1319
0
    SetLastError(ERROR_NOT_FOUND);
1320
0
    return NULL;
1321
0
  }
1322
1323
0
  for (index = 0; index < mcs->channelCount; index++)
1324
0
  {
1325
0
    rdpMcsChannel* mchannel = &mcs->channels[index];
1326
0
    if (mchannel->joined && (strncmp(mchannel->Name, pVirtualName, length) == 0))
1327
0
    {
1328
0
      joined_channel = mchannel;
1329
0
      break;
1330
0
    }
1331
0
  }
1332
1333
0
  if (!joined_channel)
1334
0
  {
1335
0
    SetLastError(ERROR_NOT_FOUND);
1336
0
    return NULL;
1337
0
  }
1338
1339
0
  channel = (rdpPeerChannel*)joined_channel->handle;
1340
1341
0
  if (!channel)
1342
0
  {
1343
0
    const UINT32 VirtualChannelChunkSize =
1344
0
        freerdp_settings_get_uint32(context->settings, FreeRDP_VirtualChannelChunkSize);
1345
0
    channel = channel_new(vcm, client, joined_channel->ChannelId, index,
1346
0
                          RDP_PEER_CHANNEL_TYPE_SVC, VirtualChannelChunkSize, pVirtualName);
1347
1348
0
    if (!channel)
1349
0
      goto fail;
1350
1351
0
    joined_channel->handle = channel;
1352
0
  }
1353
1354
0
  hChannelHandle = (HANDLE)channel;
1355
0
  return hChannelHandle;
1356
0
fail:
1357
0
  channel_free(channel);
1358
0
  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1359
0
  return NULL;
1360
0
}
1361
1362
HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
1363
0
{
1364
0
  UINT32 index;
1365
0
  wStream* s = NULL;
1366
0
  rdpMcs* mcs;
1367
0
  BOOL joined = FALSE;
1368
0
  freerdp_peer* client;
1369
0
  rdpPeerChannel* channel = NULL;
1370
0
  ULONG written;
1371
0
  WTSVirtualChannelManager* vcm = NULL;
1372
1373
0
  if (SessionId == WTS_CURRENT_SESSION)
1374
0
    return NULL;
1375
1376
0
  vcm = (WTSVirtualChannelManager*)HashTable_GetItemValue(g_ServerHandles,
1377
0
                                                          (void*)(UINT_PTR)SessionId);
1378
1379
0
  if (!vcm)
1380
0
    return NULL;
1381
1382
0
  if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC))
1383
0
  {
1384
0
    return FreeRDP_WTSVirtualChannelOpen((HANDLE)vcm, SessionId, pVirtualName);
1385
0
  }
1386
1387
0
  client = vcm->client;
1388
0
  mcs = client->context->rdp->mcs;
1389
1390
0
  for (index = 0; index < mcs->channelCount; index++)
1391
0
  {
1392
0
    rdpMcsChannel* mchannel = &mcs->channels[index];
1393
0
    if (mchannel->joined &&
1394
0
        (strncmp(mchannel->Name, DRDYNVC_SVC_CHANNEL_NAME, CHANNEL_NAME_LEN + 1) == 0))
1395
0
    {
1396
0
      joined = TRUE;
1397
0
      break;
1398
0
    }
1399
0
  }
1400
1401
0
  if (!joined)
1402
0
  {
1403
0
    SetLastError(ERROR_NOT_FOUND);
1404
0
    return NULL;
1405
0
  }
1406
1407
0
  if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY))
1408
0
  {
1409
0
    SetLastError(ERROR_NOT_READY);
1410
0
    return NULL;
1411
0
  }
1412
1413
0
  WINPR_ASSERT(client);
1414
0
  WINPR_ASSERT(client->context);
1415
0
  WINPR_ASSERT(client->context->settings);
1416
1417
0
  const UINT32 VirtualChannelChunkSize =
1418
0
      freerdp_settings_get_uint32(client->context->settings, FreeRDP_VirtualChannelChunkSize);
1419
0
  channel = channel_new(vcm, client, 0, 0, RDP_PEER_CHANNEL_TYPE_DVC, VirtualChannelChunkSize,
1420
0
                        pVirtualName);
1421
1422
0
  if (!channel)
1423
0
  {
1424
0
    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1425
0
    return NULL;
1426
0
  }
1427
1428
0
  channel->channelId = InterlockedIncrement(&vcm->dvc_channel_id_seq);
1429
1430
0
  if (!HashTable_Insert(vcm->dynamicVirtualChannels, &channel->channelId, channel))
1431
0
  {
1432
0
    channel_free(channel);
1433
0
    channel = NULL;
1434
0
    goto fail;
1435
0
  }
1436
0
  s = Stream_New(NULL, 64);
1437
1438
0
  if (!s)
1439
0
    goto fail;
1440
1441
0
  if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName))
1442
0
    goto fail;
1443
1444
0
  if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR)Stream_Buffer(s),
1445
0
                              Stream_GetPosition(s), &written))
1446
0
    goto fail;
1447
1448
0
  Stream_Free(s, TRUE);
1449
0
  return channel;
1450
0
fail:
1451
0
  Stream_Free(s, TRUE);
1452
0
  if (channel)
1453
0
    HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1454
1455
0
  SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1456
0
  return NULL;
1457
0
}
1458
1459
BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
1460
0
{
1461
0
  wStream* s;
1462
0
  rdpMcs* mcs;
1463
1464
0
  rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1465
0
  BOOL ret = TRUE;
1466
1467
0
  if (channel)
1468
0
  {
1469
0
    WTSVirtualChannelManager* vcm = channel->vcm;
1470
1471
0
    WINPR_ASSERT(vcm);
1472
0
    WINPR_ASSERT(vcm->client);
1473
0
    WINPR_ASSERT(vcm->client->context);
1474
0
    WINPR_ASSERT(vcm->client->context->rdp);
1475
0
    mcs = vcm->client->context->rdp->mcs;
1476
1477
0
    if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1478
0
    {
1479
0
      if (channel->index < mcs->channelCount)
1480
0
      {
1481
0
        rdpMcsChannel* cur = &mcs->channels[channel->index];
1482
0
        rdpPeerChannel* peerChannel = (rdpPeerChannel*)cur->handle;
1483
0
        if (peerChannel)
1484
0
          channel_free(peerChannel);
1485
0
        cur->handle = NULL;
1486
0
      }
1487
0
    }
1488
0
    else
1489
0
    {
1490
0
      if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
1491
0
      {
1492
0
        ULONG written;
1493
0
        s = Stream_New(NULL, 8);
1494
1495
0
        if (!s)
1496
0
        {
1497
0
          WLog_ERR(TAG, "Stream_New failed!");
1498
0
          ret = FALSE;
1499
0
        }
1500
0
        else
1501
0
        {
1502
0
          wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId);
1503
0
          ret = WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR)Stream_Buffer(s),
1504
0
                                       Stream_GetPosition(s), &written);
1505
0
          Stream_Free(s, TRUE);
1506
0
        }
1507
0
      }
1508
0
      HashTable_Remove(vcm->dynamicVirtualChannels, &channel->channelId);
1509
0
    }
1510
0
  }
1511
1512
0
  return ret;
1513
0
}
1514
1515
BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer,
1516
                                          ULONG BufferSize, PULONG pBytesRead)
1517
0
{
1518
0
  BYTE* buffer = NULL;
1519
0
  wMessage message = { 0 };
1520
0
  wtsChannelMessage* messageCtx = NULL;
1521
0
  rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1522
1523
0
  WINPR_ASSERT(channel);
1524
1525
0
  if (!MessageQueue_Peek(channel->queue, &message, FALSE))
1526
0
  {
1527
0
    SetLastError(ERROR_NO_DATA);
1528
0
    *pBytesRead = 0;
1529
0
    return FALSE;
1530
0
  }
1531
1532
0
  messageCtx = message.context;
1533
1534
0
  if (messageCtx == NULL)
1535
0
    return FALSE;
1536
1537
0
  buffer = (BYTE*)(messageCtx + 1);
1538
0
  *pBytesRead = messageCtx->length - messageCtx->offset;
1539
1540
0
  if (Buffer == NULL || BufferSize == 0)
1541
0
  {
1542
0
    return TRUE;
1543
0
  }
1544
1545
0
  if (*pBytesRead > BufferSize)
1546
0
    *pBytesRead = BufferSize;
1547
1548
0
  CopyMemory(Buffer, buffer + messageCtx->offset, *pBytesRead);
1549
0
  messageCtx->offset += *pBytesRead;
1550
1551
0
  if (messageCtx->offset >= messageCtx->length)
1552
0
  {
1553
0
    MessageQueue_Peek(channel->queue, &message, TRUE);
1554
0
    peer_channel_queue_free_message(&message);
1555
0
  }
1556
1557
0
  return TRUE;
1558
0
}
1559
1560
BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length,
1561
                                           PULONG pBytesWritten)
1562
0
{
1563
0
  wStream* s;
1564
0
  int cbLen;
1565
0
  int cbChId;
1566
0
  int first;
1567
0
  BYTE* buffer;
1568
0
  UINT32 length;
1569
0
  UINT32 written;
1570
0
  UINT32 totalWritten = 0;
1571
0
  rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1572
0
  BOOL ret = TRUE;
1573
1574
0
  if (!channel)
1575
0
    return FALSE;
1576
1577
0
  WINPR_ASSERT(channel->vcm);
1578
0
  if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1579
0
  {
1580
0
    length = Length;
1581
0
    buffer = (BYTE*)malloc(length);
1582
1583
0
    if (!buffer)
1584
0
    {
1585
0
      SetLastError(E_OUTOFMEMORY);
1586
0
      return FALSE;
1587
0
    }
1588
1589
0
    CopyMemory(buffer, Buffer, length);
1590
0
    totalWritten = Length;
1591
0
    ret = wts_queue_send_item(channel, buffer, length);
1592
0
  }
1593
0
  else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
1594
0
  {
1595
0
    DEBUG_DVC("drdynvc not ready");
1596
0
    return FALSE;
1597
0
  }
1598
0
  else
1599
0
  {
1600
0
    rdpContext* context;
1601
1602
0
    first = TRUE;
1603
0
    WINPR_ASSERT(channel->client);
1604
0
    context = channel->client->context;
1605
0
    WINPR_ASSERT(context);
1606
0
    while (Length > 0)
1607
0
    {
1608
0
      s = Stream_New(NULL, DVC_MAX_DATA_PDU_SIZE);
1609
1610
0
      if (!s)
1611
0
      {
1612
0
        WLog_ERR(TAG, "Stream_New failed!");
1613
0
        SetLastError(E_OUTOFMEMORY);
1614
0
        return FALSE;
1615
0
      }
1616
1617
0
      buffer = Stream_Buffer(s);
1618
0
      Stream_Seek_UINT8(s);
1619
0
      cbChId = wts_write_variable_uint(s, channel->channelId);
1620
1621
0
      if (first && (Length > Stream_GetRemainingLength(s)))
1622
0
      {
1623
0
        cbLen = wts_write_variable_uint(s, Length);
1624
0
        buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId;
1625
0
      }
1626
0
      else
1627
0
      {
1628
0
        buffer[0] = (DATA_PDU << 4) | cbChId;
1629
0
      }
1630
1631
0
      first = FALSE;
1632
0
      written = Stream_GetRemainingLength(s);
1633
1634
0
      if (written > Length)
1635
0
        written = Length;
1636
1637
0
      Stream_Write(s, Buffer, written);
1638
0
      length = Stream_GetPosition(s);
1639
0
      Stream_Free(s, FALSE);
1640
0
      Length -= written;
1641
0
      Buffer += written;
1642
0
      totalWritten += written;
1643
0
      ret = wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length);
1644
0
    }
1645
0
  }
1646
1647
0
  if (pBytesWritten)
1648
0
    *pBytesWritten = totalWritten;
1649
1650
0
  return ret;
1651
0
}
1652
1653
BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(HANDLE hChannelHandle)
1654
0
{
1655
0
  return TRUE;
1656
0
}
1657
1658
BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle)
1659
0
{
1660
0
  return TRUE;
1661
0
}
1662
1663
BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
1664
                                           PVOID* ppBuffer, DWORD* pBytesReturned)
1665
0
{
1666
0
  void* pfd;
1667
0
  BOOL bval;
1668
0
  void* fds[10] = { 0 };
1669
0
  HANDLE hEvent;
1670
0
  int fds_count = 0;
1671
0
  BOOL status = FALSE;
1672
0
  rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1673
1674
0
  WINPR_ASSERT(channel);
1675
1676
0
  switch ((UINT32)WtsVirtualClass)
1677
0
  {
1678
0
    case WTSVirtualFileHandle:
1679
0
      hEvent = MessageQueue_Event(channel->queue);
1680
0
      pfd = GetEventWaitObject(hEvent);
1681
1682
0
      if (pfd)
1683
0
      {
1684
0
        fds[fds_count] = pfd;
1685
0
        (fds_count)++;
1686
0
      }
1687
1688
0
      *ppBuffer = malloc(sizeof(void*));
1689
1690
0
      if (!*ppBuffer)
1691
0
      {
1692
0
        SetLastError(E_OUTOFMEMORY);
1693
0
      }
1694
0
      else
1695
0
      {
1696
0
        CopyMemory(*ppBuffer, &fds[0], sizeof(void*));
1697
0
        *pBytesReturned = sizeof(void*);
1698
0
        status = TRUE;
1699
0
      }
1700
1701
0
      break;
1702
1703
0
    case WTSVirtualEventHandle:
1704
0
      hEvent = MessageQueue_Event(channel->queue);
1705
1706
0
      *ppBuffer = malloc(sizeof(HANDLE));
1707
1708
0
      if (!*ppBuffer)
1709
0
      {
1710
0
        SetLastError(E_OUTOFMEMORY);
1711
0
      }
1712
0
      else
1713
0
      {
1714
0
        CopyMemory(*ppBuffer, &(hEvent), sizeof(HANDLE));
1715
0
        *pBytesReturned = sizeof(void*);
1716
0
        status = TRUE;
1717
0
      }
1718
1719
0
      break;
1720
1721
0
    case WTSVirtualChannelReady:
1722
0
      if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1723
0
      {
1724
0
        bval = TRUE;
1725
0
        status = TRUE;
1726
0
      }
1727
0
      else
1728
0
      {
1729
0
        switch (channel->dvc_open_state)
1730
0
        {
1731
0
          case DVC_OPEN_STATE_NONE:
1732
0
            bval = FALSE;
1733
0
            status = TRUE;
1734
0
            break;
1735
1736
0
          case DVC_OPEN_STATE_SUCCEEDED:
1737
0
            bval = TRUE;
1738
0
            status = TRUE;
1739
0
            break;
1740
1741
0
          default:
1742
0
            *ppBuffer = NULL;
1743
0
            *pBytesReturned = 0;
1744
0
            return FALSE;
1745
0
        }
1746
0
      }
1747
1748
0
      *ppBuffer = malloc(sizeof(BOOL));
1749
1750
0
      if (!*ppBuffer)
1751
0
      {
1752
0
        SetLastError(E_OUTOFMEMORY);
1753
0
        status = FALSE;
1754
0
      }
1755
0
      else
1756
0
      {
1757
0
        CopyMemory(*ppBuffer, &bval, sizeof(BOOL));
1758
0
        *pBytesReturned = sizeof(BOOL);
1759
0
      }
1760
1761
0
      break;
1762
0
    case WTSVirtualChannelOpenStatus:
1763
0
    {
1764
0
      INT32 value = channel->creationStatus;
1765
0
      status = TRUE;
1766
1767
0
      *ppBuffer = malloc(sizeof(value));
1768
0
      if (!*ppBuffer)
1769
0
      {
1770
0
        SetLastError(E_OUTOFMEMORY);
1771
0
        status = FALSE;
1772
0
      }
1773
0
      else
1774
0
      {
1775
0
        CopyMemory(*ppBuffer, &value, sizeof(value));
1776
0
        *pBytesReturned = sizeof(value);
1777
0
      }
1778
0
      break;
1779
0
    }
1780
0
    default:
1781
0
      break;
1782
0
  }
1783
1784
0
  return status;
1785
0
}
1786
1787
VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory)
1788
0
{
1789
0
  free(pMemory);
1790
0
}
1791
1792
BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
1793
                                     ULONG NumberOfEntries)
1794
0
{
1795
0
  return FALSE;
1796
0
}
1797
1798
BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
1799
                                     ULONG NumberOfEntries)
1800
0
{
1801
0
  return FALSE;
1802
0
}
1803
1804
BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)
1805
0
{
1806
0
  return FALSE;
1807
0
}
1808
1809
BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(HWND hWnd)
1810
0
{
1811
0
  return FALSE;
1812
0
}
1813
1814
BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags)
1815
0
{
1816
0
  return FALSE;
1817
0
}
1818
1819
BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd)
1820
0
{
1821
0
  return FALSE;
1822
0
}
1823
1824
BOOL WINAPI FreeRDP_WTSQueryUserToken(ULONG SessionId, PHANDLE phToken)
1825
0
{
1826
0
  return FALSE;
1827
0
}
1828
1829
BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
1830
                                             LPWSTR* ppProcessInfo, DWORD* pCount)
1831
0
{
1832
0
  return FALSE;
1833
0
}
1834
1835
BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
1836
                                             LPSTR* ppProcessInfo, DWORD* pCount)
1837
0
{
1838
0
  return FALSE;
1839
0
}
1840
1841
BOOL WINAPI FreeRDP_WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1842
                                           PWTSLISTENERNAMEW pListeners, DWORD* pCount)
1843
0
{
1844
0
  return FALSE;
1845
0
}
1846
1847
BOOL WINAPI FreeRDP_WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1848
                                           PWTSLISTENERNAMEA pListeners, DWORD* pCount)
1849
0
{
1850
0
  return FALSE;
1851
0
}
1852
1853
BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1854
                                            LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer)
1855
0
{
1856
0
  return FALSE;
1857
0
}
1858
1859
BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1860
                                            LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer)
1861
0
{
1862
0
  return FALSE;
1863
0
}
1864
1865
BOOL WINAPI FreeRDP_WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1866
                                       LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer,
1867
                                       DWORD flag)
1868
0
{
1869
0
  return FALSE;
1870
0
}
1871
1872
BOOL WINAPI FreeRDP_WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1873
                                       LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag)
1874
0
{
1875
0
  return FALSE;
1876
0
}
1877
1878
BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1879
                                            LPWSTR pListenerName,
1880
                                            SECURITY_INFORMATION SecurityInformation,
1881
                                            PSECURITY_DESCRIPTOR pSecurityDescriptor)
1882
0
{
1883
0
  return FALSE;
1884
0
}
1885
1886
BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1887
                                            LPSTR pListenerName,
1888
                                            SECURITY_INFORMATION SecurityInformation,
1889
                                            PSECURITY_DESCRIPTOR pSecurityDescriptor)
1890
0
{
1891
0
  return FALSE;
1892
0
}
1893
1894
BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1895
                                            LPWSTR pListenerName,
1896
                                            SECURITY_INFORMATION SecurityInformation,
1897
                                            PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
1898
                                            LPDWORD lpnLengthNeeded)
1899
0
{
1900
0
  return FALSE;
1901
0
}
1902
1903
BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1904
                                            LPSTR pListenerName,
1905
                                            SECURITY_INFORMATION SecurityInformation,
1906
                                            PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
1907
                                            LPDWORD lpnLengthNeeded)
1908
0
{
1909
0
  return FALSE;
1910
0
}
1911
1912
BOOL CDECL FreeRDP_WTSEnableChildSessions(BOOL bEnable)
1913
0
{
1914
0
  return FALSE;
1915
0
}
1916
1917
BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(PBOOL pbEnabled)
1918
0
{
1919
0
  return FALSE;
1920
0
}
1921
1922
BOOL CDECL FreeRDP_WTSGetChildSessionId(PULONG pSessionId)
1923
0
{
1924
0
  return FALSE;
1925
0
}
1926
1927
DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(void)
1928
0
{
1929
0
  return 0xFFFFFFFF;
1930
0
}
1931
BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer)
1932
0
{
1933
0
  return FALSE;
1934
0
}
1935
1936
BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain)
1937
0
{
1938
0
  return FALSE;
1939
0
}