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 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <winpr/crt.h>
31 #include <winpr/synch.h>
32 #include <winpr/stream.h>
33
34 #include <freerdp/log.h>
35 #include <freerdp/constants.h>
36 #include <freerdp/server/channels.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 do \
48 { \
49 } while (0)
50 #endif
51
52 struct _wtsChannelMessage
53 {
54 UINT16 channelId;
55 UINT16 reserved;
56 UINT32 length;
57 UINT32 offset;
58 };
59 typedef struct _wtsChannelMessage wtsChannelMessage;
60
61 static DWORD g_SessionId = 1;
62 static wHashTable* g_ServerHandles = NULL;
63
wts_get_dvc_channel_by_id(WTSVirtualChannelManager * vcm,UINT32 ChannelId)64 static rdpPeerChannel* wts_get_dvc_channel_by_id(WTSVirtualChannelManager* vcm, UINT32 ChannelId)
65 {
66 int index;
67 int count;
68 BOOL found = FALSE;
69 rdpPeerChannel* channel = NULL;
70 ArrayList_Lock(vcm->dynamicVirtualChannels);
71 count = ArrayList_Count(vcm->dynamicVirtualChannels);
72
73 for (index = 0; index < count; index++)
74 {
75 channel = (rdpPeerChannel*)ArrayList_GetItem(vcm->dynamicVirtualChannels, index);
76
77 if (channel->channelId == ChannelId)
78 {
79 found = TRUE;
80 break;
81 }
82 }
83
84 ArrayList_Unlock(vcm->dynamicVirtualChannels);
85 return found ? channel : NULL;
86 }
87
wts_queue_receive_data(rdpPeerChannel * channel,const BYTE * Buffer,UINT32 Length)88 static BOOL wts_queue_receive_data(rdpPeerChannel* channel, const BYTE* Buffer, UINT32 Length)
89 {
90 BYTE* buffer;
91 wtsChannelMessage* messageCtx;
92 messageCtx = (wtsChannelMessage*)malloc(sizeof(wtsChannelMessage) + Length);
93
94 if (!messageCtx)
95 return FALSE;
96
97 messageCtx->channelId = channel->channelId;
98 messageCtx->length = Length;
99 messageCtx->offset = 0;
100 buffer = (BYTE*)(messageCtx + 1);
101 CopyMemory(buffer, Buffer, Length);
102 return MessageQueue_Post(channel->queue, messageCtx, 0, NULL, NULL);
103 }
104
wts_queue_send_item(rdpPeerChannel * channel,BYTE * Buffer,UINT32 Length)105 static BOOL wts_queue_send_item(rdpPeerChannel* channel, BYTE* Buffer, UINT32 Length)
106 {
107 BYTE* buffer;
108 UINT32 length;
109 UINT16 channelId;
110 buffer = Buffer;
111 length = Length;
112 channelId = channel->channelId;
113 return MessageQueue_Post(channel->vcm->queue, (void*)(UINT_PTR)channelId, 0, (void*)buffer,
114 (void*)(UINT_PTR)length);
115 }
116
wts_read_variable_uint(wStream * s,int cbLen,UINT32 * val)117 static int wts_read_variable_uint(wStream* s, int cbLen, UINT32* val)
118 {
119 switch (cbLen)
120 {
121 case 0:
122 if (Stream_GetRemainingLength(s) < 1)
123 return 0;
124
125 Stream_Read_UINT8(s, *val);
126 return 1;
127
128 case 1:
129 if (Stream_GetRemainingLength(s) < 2)
130 return 0;
131
132 Stream_Read_UINT16(s, *val);
133 return 2;
134
135 default:
136 if (Stream_GetRemainingLength(s) < 4)
137 return 0;
138
139 Stream_Read_UINT32(s, *val);
140 return 4;
141 }
142 }
143
wts_read_drdynvc_capabilities_response(rdpPeerChannel * channel,UINT32 length)144 static BOOL wts_read_drdynvc_capabilities_response(rdpPeerChannel* channel, UINT32 length)
145 {
146 UINT16 Version;
147
148 if (length < 3)
149 return FALSE;
150
151 Stream_Seek_UINT8(channel->receiveData); /* Pad (1 byte) */
152 Stream_Read_UINT16(channel->receiveData, Version);
153 DEBUG_DVC("Version: %" PRIu16 "", Version);
154 channel->vcm->drdynvc_state = DRDYNVC_STATE_READY;
155 return TRUE;
156 }
157
wts_read_drdynvc_create_response(rdpPeerChannel * channel,wStream * s,UINT32 length)158 static BOOL wts_read_drdynvc_create_response(rdpPeerChannel* channel, wStream* s, UINT32 length)
159 {
160 UINT32 CreationStatus;
161
162 if (length < 4)
163 return FALSE;
164
165 Stream_Read_UINT32(s, CreationStatus);
166
167 if ((INT32)CreationStatus < 0)
168 {
169 DEBUG_DVC("ChannelId %" PRIu32 " creation failed (%" PRId32 ")", channel->channelId,
170 (INT32)CreationStatus);
171 channel->dvc_open_state = DVC_OPEN_STATE_FAILED;
172 }
173 else
174 {
175 DEBUG_DVC("ChannelId %" PRIu32 " creation succeeded", channel->channelId);
176 channel->dvc_open_state = DVC_OPEN_STATE_SUCCEEDED;
177 }
178
179 return TRUE;
180 }
181
wts_read_drdynvc_data_first(rdpPeerChannel * channel,wStream * s,int cbLen,UINT32 length)182 static BOOL wts_read_drdynvc_data_first(rdpPeerChannel* channel, wStream* s, int cbLen,
183 UINT32 length)
184 {
185 int value;
186 value = wts_read_variable_uint(s, cbLen, &channel->dvc_total_length);
187
188 if (value == 0)
189 return FALSE;
190
191 length -= value;
192
193 if (length > channel->dvc_total_length)
194 return FALSE;
195
196 Stream_SetPosition(channel->receiveData, 0);
197
198 if (!Stream_EnsureRemainingCapacity(channel->receiveData, channel->dvc_total_length))
199 return FALSE;
200
201 Stream_Write(channel->receiveData, Stream_Pointer(s), length);
202 return TRUE;
203 }
204
wts_read_drdynvc_data(rdpPeerChannel * channel,wStream * s,UINT32 length)205 static BOOL wts_read_drdynvc_data(rdpPeerChannel* channel, wStream* s, UINT32 length)
206 {
207 BOOL ret = FALSE;
208
209 if (channel->dvc_total_length > 0)
210 {
211 if (Stream_GetPosition(channel->receiveData) + length > channel->dvc_total_length)
212 {
213 channel->dvc_total_length = 0;
214 WLog_ERR(TAG, "incorrect fragment data, discarded.");
215 return FALSE;
216 }
217
218 Stream_Write(channel->receiveData, Stream_Pointer(s), length);
219
220 if (Stream_GetPosition(channel->receiveData) >= channel->dvc_total_length)
221 {
222 ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData),
223 channel->dvc_total_length);
224 channel->dvc_total_length = 0;
225 }
226 else
227 ret = TRUE;
228 }
229 else
230 {
231 ret = wts_queue_receive_data(channel, Stream_Pointer(s), length);
232 }
233
234 return ret;
235 }
236
wts_read_drdynvc_close_response(rdpPeerChannel * channel)237 static void wts_read_drdynvc_close_response(rdpPeerChannel* channel)
238 {
239 DEBUG_DVC("ChannelId %" PRIu32 " close response", channel->channelId);
240 channel->dvc_open_state = DVC_OPEN_STATE_CLOSED;
241 MessageQueue_PostQuit(channel->queue, 0);
242 }
243
wts_read_drdynvc_pdu(rdpPeerChannel * channel)244 static BOOL wts_read_drdynvc_pdu(rdpPeerChannel* channel)
245 {
246 UINT32 length;
247 int value;
248 int Cmd;
249 int Sp;
250 int cbChId;
251 UINT32 ChannelId;
252 rdpPeerChannel* dvc;
253 length = Stream_GetPosition(channel->receiveData);
254
255 if (length < 1)
256 return FALSE;
257
258 Stream_SetPosition(channel->receiveData, 0);
259 Stream_Read_UINT8(channel->receiveData, value);
260 length--;
261 Cmd = (value & 0xf0) >> 4;
262 Sp = (value & 0x0c) >> 2;
263 cbChId = (value & 0x03) >> 0;
264
265 if (Cmd == CAPABILITY_REQUEST_PDU)
266 {
267 return wts_read_drdynvc_capabilities_response(channel, length);
268 }
269 else if (channel->vcm->drdynvc_state == DRDYNVC_STATE_READY)
270 {
271 value = wts_read_variable_uint(channel->receiveData, cbChId, &ChannelId);
272
273 if (value == 0)
274 return FALSE;
275
276 length -= value;
277 DEBUG_DVC("Cmd %d ChannelId %" PRIu32 " length %" PRIu32 "", Cmd, ChannelId, length);
278 dvc = wts_get_dvc_channel_by_id(channel->vcm, ChannelId);
279
280 if (dvc)
281 {
282 switch (Cmd)
283 {
284 case CREATE_REQUEST_PDU:
285 return wts_read_drdynvc_create_response(dvc, channel->receiveData, length);
286
287 case DATA_FIRST_PDU:
288 return wts_read_drdynvc_data_first(dvc, channel->receiveData, Sp, length);
289
290 case DATA_PDU:
291 return wts_read_drdynvc_data(dvc, channel->receiveData, length);
292
293 case CLOSE_REQUEST_PDU:
294 wts_read_drdynvc_close_response(dvc);
295 break;
296
297 default:
298 WLog_ERR(TAG, "Cmd %d not recognized.", Cmd);
299 break;
300 }
301 }
302 else
303 {
304 DEBUG_DVC("ChannelId %" PRIu32 " not exists.", ChannelId);
305 }
306 }
307 else
308 {
309 WLog_ERR(TAG, "received Cmd %d but channel is not ready.", Cmd);
310 }
311
312 return TRUE;
313 }
314
wts_write_variable_uint(wStream * s,UINT32 val)315 static int wts_write_variable_uint(wStream* s, UINT32 val)
316 {
317 int cb;
318
319 if (val <= 0xFF)
320 {
321 cb = 0;
322 Stream_Write_UINT8(s, val);
323 }
324 else if (val <= 0xFFFF)
325 {
326 cb = 1;
327 Stream_Write_UINT16(s, val);
328 }
329 else
330 {
331 cb = 2;
332 Stream_Write_UINT32(s, val);
333 }
334
335 return cb;
336 }
337
wts_write_drdynvc_header(wStream * s,BYTE Cmd,UINT32 ChannelId)338 static void wts_write_drdynvc_header(wStream* s, BYTE Cmd, UINT32 ChannelId)
339 {
340 BYTE* bm;
341 int cbChId;
342 Stream_GetPointer(s, bm);
343 Stream_Seek_UINT8(s);
344 cbChId = wts_write_variable_uint(s, ChannelId);
345 *bm = ((Cmd & 0x0F) << 4) | cbChId;
346 }
347
wts_write_drdynvc_create_request(wStream * s,UINT32 ChannelId,const char * ChannelName)348 static BOOL wts_write_drdynvc_create_request(wStream* s, UINT32 ChannelId, const char* ChannelName)
349 {
350 size_t len;
351 wts_write_drdynvc_header(s, CREATE_REQUEST_PDU, ChannelId);
352 len = strlen(ChannelName) + 1;
353
354 if (!Stream_EnsureRemainingCapacity(s, len))
355 return FALSE;
356
357 Stream_Write(s, ChannelName, len);
358 return TRUE;
359 }
360
WTSProcessChannelData(rdpPeerChannel * channel,UINT16 channelId,const BYTE * data,size_t s,UINT32 flags,size_t t)361 static BOOL WTSProcessChannelData(rdpPeerChannel* channel, UINT16 channelId, const BYTE* data,
362 size_t s, UINT32 flags, size_t t)
363 {
364 BOOL ret = TRUE;
365 const size_t size = (size_t)s;
366 const size_t totalSize = (size_t)t;
367
368 WINPR_UNUSED(channelId);
369
370 if (flags & CHANNEL_FLAG_FIRST)
371 {
372 Stream_SetPosition(channel->receiveData, 0);
373 }
374
375 if (!Stream_EnsureRemainingCapacity(channel->receiveData, size))
376 return FALSE;
377
378 Stream_Write(channel->receiveData, data, size);
379
380 if (flags & CHANNEL_FLAG_LAST)
381 {
382 if (Stream_GetPosition(channel->receiveData) != totalSize)
383 {
384 WLog_ERR(TAG, "read error");
385 }
386
387 if (channel == channel->vcm->drdynvc_channel)
388 {
389 ret = wts_read_drdynvc_pdu(channel);
390 }
391 else
392 {
393 ret = wts_queue_receive_data(channel, Stream_Buffer(channel->receiveData),
394 Stream_GetPosition(channel->receiveData));
395 }
396
397 Stream_SetPosition(channel->receiveData, 0);
398 }
399
400 return ret;
401 }
402
WTSReceiveChannelData(freerdp_peer * client,UINT16 channelId,const BYTE * data,size_t size,UINT32 flags,size_t totalSize)403 static BOOL WTSReceiveChannelData(freerdp_peer* client, UINT16 channelId, const BYTE* data,
404 size_t size, UINT32 flags, size_t totalSize)
405 {
406 UINT32 i;
407 BOOL status = FALSE;
408 rdpMcs* mcs = client->context->rdp->mcs;
409
410 for (i = 0; i < mcs->channelCount; i++)
411 {
412 if (mcs->channels[i].ChannelId == channelId)
413 {
414 rdpPeerChannel* channel = (rdpPeerChannel*)mcs->channels[i].handle;
415
416 if (channel)
417 status = WTSProcessChannelData(channel, channelId, data, size, flags, totalSize);
418 break;
419 }
420 }
421
422 return status;
423 }
424
WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer,void ** fds,int * fds_count)425 void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer, void** fds, int* fds_count)
426 {
427 void* fd;
428 WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
429 fd = GetEventWaitObject(MessageQueue_Event(vcm->queue));
430
431 if (fd)
432 {
433 fds[*fds_count] = fd;
434 (*fds_count)++;
435 }
436
437 #if 0
438
439 if (vcm->drdynvc_channel)
440 {
441 fd = GetEventWaitObject(vcm->drdynvc_channel->receiveEvent);
442
443 if (fd)
444 {
445 fds[*fds_count] = fd;
446 (*fds_count)++;
447 }
448 }
449
450 #endif
451 }
452
WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)453 BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer)
454 {
455 wMessage message;
456 BOOL status = TRUE;
457 rdpPeerChannel* channel;
458 UINT32 dynvc_caps;
459 WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
460
461 if ((vcm->drdynvc_state == DRDYNVC_STATE_NONE) && vcm->client->activated)
462 {
463 /* Initialize drdynvc channel once and only once. */
464 vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
465 channel =
466 (rdpPeerChannel*)WTSVirtualChannelOpen((HANDLE)vcm, WTS_CURRENT_SESSION, "drdynvc");
467
468 if (channel)
469 {
470 ULONG written;
471 vcm->drdynvc_channel = channel;
472 dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */
473
474 if (!WTSVirtualChannelWrite(channel, (PCHAR)&dynvc_caps, sizeof(dynvc_caps), &written))
475 return FALSE;
476 }
477 }
478
479 while (MessageQueue_Peek(vcm->queue, &message, TRUE))
480 {
481 BYTE* buffer;
482 UINT32 length;
483 UINT16 channelId;
484 channelId = (UINT16)(UINT_PTR)message.context;
485 buffer = (BYTE*)message.wParam;
486 length = (UINT32)(UINT_PTR)message.lParam;
487
488 if (!vcm->client->SendChannelData(vcm->client, channelId, buffer, length))
489 {
490 status = FALSE;
491 }
492
493 free(buffer);
494
495 if (!status)
496 break;
497 }
498
499 return status;
500 }
501
WTSVirtualChannelManagerGetEventHandle(HANDLE hServer)502 HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer)
503 {
504 WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
505 return MessageQueue_Event(vcm->queue);
506 }
507
wts_get_joined_channel_by_name(rdpMcs * mcs,const char * channel_name)508 static rdpMcsChannel* wts_get_joined_channel_by_name(rdpMcs* mcs, const char* channel_name)
509 {
510 UINT32 index;
511
512 if (!mcs || !channel_name || !strnlen(channel_name, CHANNEL_NAME_LEN))
513 return NULL;
514
515 for (index = 0; index < mcs->channelCount; index++)
516 {
517 if (mcs->channels[index].joined)
518 {
519 if (_strnicmp(mcs->channels[index].Name, channel_name,
520 strnlen(channel_name, CHANNEL_NAME_LEN)) == 0)
521 return &mcs->channels[index];
522 }
523 }
524
525 return NULL;
526 }
527
wts_get_joined_channel_by_id(rdpMcs * mcs,const UINT16 channel_id)528 static rdpMcsChannel* wts_get_joined_channel_by_id(rdpMcs* mcs, const UINT16 channel_id)
529 {
530 UINT32 index;
531
532 if (!mcs || !channel_id)
533 return NULL;
534
535 for (index = 0; index < mcs->channelCount; index++)
536 {
537 if (mcs->channels[index].joined)
538 {
539 if (mcs->channels[index].ChannelId == channel_id)
540 return &mcs->channels[index];
541 }
542 }
543
544 return NULL;
545 }
546
WTSIsChannelJoinedByName(freerdp_peer * client,const char * channel_name)547 BOOL WTSIsChannelJoinedByName(freerdp_peer* client, const char* channel_name)
548 {
549 if (!client || !client->context || !client->context->rdp)
550 return FALSE;
551
552 return wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name) == NULL ? FALSE
553 : TRUE;
554 }
555
WTSIsChannelJoinedById(freerdp_peer * client,const UINT16 channel_id)556 BOOL WTSIsChannelJoinedById(freerdp_peer* client, const UINT16 channel_id)
557 {
558 if (!client || !client->context || !client->context->rdp)
559 return FALSE;
560
561 return wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id) == NULL ? FALSE
562 : TRUE;
563 }
564
WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer,const char * name)565 BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer, const char* name)
566 {
567 WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
568
569 if (!vcm || !vcm->rdp)
570 return FALSE;
571
572 return wts_get_joined_channel_by_name(vcm->rdp->mcs, name) == NULL ? FALSE : TRUE;
573 }
574
WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)575 BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)
576 {
577 WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*)hServer;
578 return vcm->drdynvc_state;
579 }
580
WTSChannelGetId(freerdp_peer * client,const char * channel_name)581 UINT16 WTSChannelGetId(freerdp_peer* client, const char* channel_name)
582 {
583 rdpMcsChannel* channel;
584
585 if (!client || !client->context || !client->context->rdp)
586 return 0;
587
588 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
589
590 if (!channel)
591 return 0;
592
593 return channel->ChannelId;
594 }
595
WTSChannelSetHandleByName(freerdp_peer * client,const char * channel_name,void * handle)596 BOOL WTSChannelSetHandleByName(freerdp_peer* client, const char* channel_name, void* handle)
597 {
598 rdpMcsChannel* channel;
599
600 if (!client || !client->context || !client->context->rdp)
601 return FALSE;
602
603 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
604
605 if (!channel)
606 return FALSE;
607
608 channel->handle = handle;
609 return TRUE;
610 }
611
WTSChannelSetHandleById(freerdp_peer * client,const UINT16 channel_id,void * handle)612 BOOL WTSChannelSetHandleById(freerdp_peer* client, const UINT16 channel_id, void* handle)
613 {
614 rdpMcsChannel* channel;
615
616 if (!client || !client->context || !client->context->rdp)
617 return FALSE;
618
619 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
620
621 if (!channel)
622 return FALSE;
623
624 channel->handle = handle;
625 return TRUE;
626 }
627
WTSChannelGetHandleByName(freerdp_peer * client,const char * channel_name)628 void* WTSChannelGetHandleByName(freerdp_peer* client, const char* channel_name)
629 {
630 rdpMcsChannel* channel;
631
632 if (!client || !client->context || !client->context->rdp)
633 return NULL;
634
635 channel = wts_get_joined_channel_by_name(client->context->rdp->mcs, channel_name);
636
637 if (!channel)
638 return NULL;
639
640 return channel->handle;
641 }
642
WTSChannelGetHandleById(freerdp_peer * client,const UINT16 channel_id)643 void* WTSChannelGetHandleById(freerdp_peer* client, const UINT16 channel_id)
644 {
645 rdpMcsChannel* channel;
646
647 if (!client || !client->context || !client->context->rdp)
648 return NULL;
649
650 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
651
652 if (!channel)
653 return NULL;
654
655 return channel->handle;
656 }
657
WTSChannelGetName(freerdp_peer * client,UINT16 channel_id)658 const char* WTSChannelGetName(freerdp_peer* client, UINT16 channel_id)
659 {
660 rdpMcsChannel* channel;
661
662 if (!client || !client->context || !client->context->rdp)
663 return NULL;
664
665 channel = wts_get_joined_channel_by_id(client->context->rdp->mcs, channel_id);
666
667 if (!channel)
668 return NULL;
669
670 return (const char*)channel->Name;
671 }
672
FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName,ULONG TargetLogonId,BYTE HotkeyVk,USHORT HotkeyModifiers)673 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionW(LPWSTR pTargetServerName, ULONG TargetLogonId,
674 BYTE HotkeyVk, USHORT HotkeyModifiers)
675 {
676 return FALSE;
677 }
678
FreeRDP_WTSStartRemoteControlSessionA(LPSTR pTargetServerName,ULONG TargetLogonId,BYTE HotkeyVk,USHORT HotkeyModifiers)679 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionA(LPSTR pTargetServerName, ULONG TargetLogonId,
680 BYTE HotkeyVk, USHORT HotkeyModifiers)
681 {
682 return FALSE;
683 }
684
FreeRDP_WTSStartRemoteControlSessionExW(LPWSTR pTargetServerName,ULONG TargetLogonId,BYTE HotkeyVk,USHORT HotkeyModifiers,DWORD flags)685 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExW(LPWSTR pTargetServerName, ULONG TargetLogonId,
686 BYTE HotkeyVk, USHORT HotkeyModifiers,
687 DWORD flags)
688 {
689 return FALSE;
690 }
691
FreeRDP_WTSStartRemoteControlSessionExA(LPSTR pTargetServerName,ULONG TargetLogonId,BYTE HotkeyVk,USHORT HotkeyModifiers,DWORD flags)692 BOOL WINAPI FreeRDP_WTSStartRemoteControlSessionExA(LPSTR pTargetServerName, ULONG TargetLogonId,
693 BYTE HotkeyVk, USHORT HotkeyModifiers,
694 DWORD flags)
695 {
696 return FALSE;
697 }
698
FreeRDP_WTSStopRemoteControlSession(ULONG LogonId)699 BOOL WINAPI FreeRDP_WTSStopRemoteControlSession(ULONG LogonId)
700 {
701 return FALSE;
702 }
703
FreeRDP_WTSConnectSessionW(ULONG LogonId,ULONG TargetLogonId,PWSTR pPassword,BOOL bWait)704 BOOL WINAPI FreeRDP_WTSConnectSessionW(ULONG LogonId, ULONG TargetLogonId, PWSTR pPassword,
705 BOOL bWait)
706 {
707 return FALSE;
708 }
709
FreeRDP_WTSConnectSessionA(ULONG LogonId,ULONG TargetLogonId,PSTR pPassword,BOOL bWait)710 BOOL WINAPI FreeRDP_WTSConnectSessionA(ULONG LogonId, ULONG TargetLogonId, PSTR pPassword,
711 BOOL bWait)
712 {
713 return FALSE;
714 }
715
FreeRDP_WTSEnumerateServersW(LPWSTR pDomainName,DWORD Reserved,DWORD Version,PWTS_SERVER_INFOW * ppServerInfo,DWORD * pCount)716 BOOL WINAPI FreeRDP_WTSEnumerateServersW(LPWSTR pDomainName, DWORD Reserved, DWORD Version,
717 PWTS_SERVER_INFOW* ppServerInfo, DWORD* pCount)
718 {
719 return FALSE;
720 }
721
FreeRDP_WTSEnumerateServersA(LPSTR pDomainName,DWORD Reserved,DWORD Version,PWTS_SERVER_INFOA * ppServerInfo,DWORD * pCount)722 BOOL WINAPI FreeRDP_WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version,
723 PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount)
724 {
725 return FALSE;
726 }
727
FreeRDP_WTSOpenServerW(LPWSTR pServerName)728 HANDLE WINAPI FreeRDP_WTSOpenServerW(LPWSTR pServerName)
729 {
730 return INVALID_HANDLE_VALUE;
731 }
732
wts_virtual_channel_manager_free_message(void * obj)733 static void wts_virtual_channel_manager_free_message(void* obj)
734 {
735 wMessage* msg = (wMessage*)obj;
736
737 if (msg)
738 {
739 BYTE* buffer = (BYTE*)msg->wParam;
740
741 if (buffer)
742 free(buffer);
743 }
744 }
745
FreeRDP_WTSOpenServerA(LPSTR pServerName)746 HANDLE WINAPI FreeRDP_WTSOpenServerA(LPSTR pServerName)
747 {
748 rdpContext* context;
749 freerdp_peer* client;
750 WTSVirtualChannelManager* vcm;
751 HANDLE hServer = INVALID_HANDLE_VALUE;
752 wObject queueCallbacks = { 0 };
753
754 context = (rdpContext*)pServerName;
755
756 if (!context)
757 return INVALID_HANDLE_VALUE;
758
759 client = context->peer;
760
761 if (!client)
762 {
763 SetLastError(ERROR_INVALID_DATA);
764 return INVALID_HANDLE_VALUE;
765 }
766
767 vcm = (WTSVirtualChannelManager*)calloc(1, sizeof(WTSVirtualChannelManager));
768
769 if (!vcm)
770 goto error_vcm_alloc;
771
772 vcm->client = client;
773 vcm->rdp = context->rdp;
774 vcm->SessionId = g_SessionId++;
775
776 if (!g_ServerHandles)
777 {
778 g_ServerHandles = HashTable_New(TRUE);
779
780 if (!g_ServerHandles)
781 goto error_free;
782 }
783
784 if (HashTable_Add(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId, (void*)vcm) < 0)
785 goto error_free;
786
787 queueCallbacks.fnObjectFree = wts_virtual_channel_manager_free_message;
788 vcm->queue = MessageQueue_New(&queueCallbacks);
789
790 if (!vcm->queue)
791 goto error_queue;
792
793 vcm->dvc_channel_id_seq = 0;
794 vcm->dynamicVirtualChannels = ArrayList_New(TRUE);
795
796 if (!vcm->dynamicVirtualChannels)
797 goto error_dynamicVirtualChannels;
798
799 client->ReceiveChannelData = WTSReceiveChannelData;
800 hServer = (HANDLE)vcm;
801 return hServer;
802 error_dynamicVirtualChannels:
803 MessageQueue_Free(vcm->queue);
804 error_queue:
805 HashTable_Remove(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId);
806 error_free:
807 free(vcm);
808 error_vcm_alloc:
809 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
810 return INVALID_HANDLE_VALUE;
811 }
812
FreeRDP_WTSOpenServerExW(LPWSTR pServerName)813 HANDLE WINAPI FreeRDP_WTSOpenServerExW(LPWSTR pServerName)
814 {
815 return INVALID_HANDLE_VALUE;
816 }
817
FreeRDP_WTSOpenServerExA(LPSTR pServerName)818 HANDLE WINAPI FreeRDP_WTSOpenServerExA(LPSTR pServerName)
819 {
820 return FreeRDP_WTSOpenServerA(pServerName);
821 }
822
FreeRDP_WTSCloseServer(HANDLE hServer)823 VOID WINAPI FreeRDP_WTSCloseServer(HANDLE hServer)
824 {
825 int index;
826 int count;
827 rdpPeerChannel* channel;
828 WTSVirtualChannelManager* vcm;
829 vcm = (WTSVirtualChannelManager*)hServer;
830
831 if (vcm)
832 {
833 HashTable_Remove(g_ServerHandles, (void*)(UINT_PTR)vcm->SessionId);
834 ArrayList_Lock(vcm->dynamicVirtualChannels);
835 count = ArrayList_Count(vcm->dynamicVirtualChannels);
836
837 for (index = 0; index < count; index++)
838 {
839 channel = (rdpPeerChannel*)ArrayList_GetItem(vcm->dynamicVirtualChannels, index);
840 WTSVirtualChannelClose(channel);
841 }
842
843 ArrayList_Unlock(vcm->dynamicVirtualChannels);
844 ArrayList_Free(vcm->dynamicVirtualChannels);
845
846 if (vcm->drdynvc_channel)
847 {
848 WTSVirtualChannelClose(vcm->drdynvc_channel);
849 vcm->drdynvc_channel = NULL;
850 }
851
852 MessageQueue_Free(vcm->queue);
853 free(vcm);
854 }
855 }
856
FreeRDP_WTSEnumerateSessionsW(HANDLE hServer,DWORD Reserved,DWORD Version,PWTS_SESSION_INFOW * ppSessionInfo,DWORD * pCount)857 BOOL WINAPI FreeRDP_WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version,
858 PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount)
859 {
860 return FALSE;
861 }
862
FreeRDP_WTSEnumerateSessionsA(HANDLE hServer,DWORD Reserved,DWORD Version,PWTS_SESSION_INFOA * ppSessionInfo,DWORD * pCount)863 BOOL WINAPI FreeRDP_WTSEnumerateSessionsA(HANDLE hServer, DWORD Reserved, DWORD Version,
864 PWTS_SESSION_INFOA* ppSessionInfo, DWORD* pCount)
865 {
866 return FALSE;
867 }
868
FreeRDP_WTSEnumerateSessionsExW(HANDLE hServer,DWORD * pLevel,DWORD Filter,PWTS_SESSION_INFO_1W * ppSessionInfo,DWORD * pCount)869 BOOL WINAPI FreeRDP_WTSEnumerateSessionsExW(HANDLE hServer, DWORD* pLevel, DWORD Filter,
870 PWTS_SESSION_INFO_1W* ppSessionInfo, DWORD* pCount)
871 {
872 return FALSE;
873 }
874
FreeRDP_WTSEnumerateSessionsExA(HANDLE hServer,DWORD * pLevel,DWORD Filter,PWTS_SESSION_INFO_1A * ppSessionInfo,DWORD * pCount)875 BOOL WINAPI FreeRDP_WTSEnumerateSessionsExA(HANDLE hServer, DWORD* pLevel, DWORD Filter,
876 PWTS_SESSION_INFO_1A* ppSessionInfo, DWORD* pCount)
877 {
878 return FALSE;
879 }
880
FreeRDP_WTSEnumerateProcessesW(HANDLE hServer,DWORD Reserved,DWORD Version,PWTS_PROCESS_INFOW * ppProcessInfo,DWORD * pCount)881 BOOL WINAPI FreeRDP_WTSEnumerateProcessesW(HANDLE hServer, DWORD Reserved, DWORD Version,
882 PWTS_PROCESS_INFOW* ppProcessInfo, DWORD* pCount)
883 {
884 return FALSE;
885 }
886
FreeRDP_WTSEnumerateProcessesA(HANDLE hServer,DWORD Reserved,DWORD Version,PWTS_PROCESS_INFOA * ppProcessInfo,DWORD * pCount)887 BOOL WINAPI FreeRDP_WTSEnumerateProcessesA(HANDLE hServer, DWORD Reserved, DWORD Version,
888 PWTS_PROCESS_INFOA* ppProcessInfo, DWORD* pCount)
889 {
890 return FALSE;
891 }
892
FreeRDP_WTSTerminateProcess(HANDLE hServer,DWORD ProcessId,DWORD ExitCode)893 BOOL WINAPI FreeRDP_WTSTerminateProcess(HANDLE hServer, DWORD ProcessId, DWORD ExitCode)
894 {
895 return FALSE;
896 }
897
FreeRDP_WTSQuerySessionInformationW(HANDLE hServer,DWORD SessionId,WTS_INFO_CLASS WTSInfoClass,LPWSTR * ppBuffer,DWORD * pBytesReturned)898 BOOL WINAPI FreeRDP_WTSQuerySessionInformationW(HANDLE hServer, DWORD SessionId,
899 WTS_INFO_CLASS WTSInfoClass, LPWSTR* ppBuffer,
900 DWORD* pBytesReturned)
901 {
902 return FALSE;
903 }
904
FreeRDP_WTSQuerySessionInformationA(HANDLE hServer,DWORD SessionId,WTS_INFO_CLASS WTSInfoClass,LPSTR * ppBuffer,DWORD * pBytesReturned)905 BOOL WINAPI FreeRDP_WTSQuerySessionInformationA(HANDLE hServer, DWORD SessionId,
906 WTS_INFO_CLASS WTSInfoClass, LPSTR* ppBuffer,
907 DWORD* pBytesReturned)
908 {
909 DWORD BytesReturned;
910 WTSVirtualChannelManager* vcm;
911 vcm = (WTSVirtualChannelManager*)hServer;
912
913 if (!vcm)
914 return FALSE;
915
916 if (WTSInfoClass == WTSSessionId)
917 {
918 ULONG* pBuffer;
919 BytesReturned = sizeof(ULONG);
920 pBuffer = (ULONG*)malloc(sizeof(BytesReturned));
921
922 if (!pBuffer)
923 {
924 SetLastError(E_OUTOFMEMORY);
925 return FALSE;
926 }
927
928 *pBuffer = vcm->SessionId;
929 *ppBuffer = (LPSTR)pBuffer;
930 *pBytesReturned = BytesReturned;
931 return TRUE;
932 }
933
934 return FALSE;
935 }
936
FreeRDP_WTSQueryUserConfigW(LPWSTR pServerName,LPWSTR pUserName,WTS_CONFIG_CLASS WTSConfigClass,LPWSTR * ppBuffer,DWORD * pBytesReturned)937 BOOL WINAPI FreeRDP_WTSQueryUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
938 WTS_CONFIG_CLASS WTSConfigClass, LPWSTR* ppBuffer,
939 DWORD* pBytesReturned)
940 {
941 return FALSE;
942 }
943
FreeRDP_WTSQueryUserConfigA(LPSTR pServerName,LPSTR pUserName,WTS_CONFIG_CLASS WTSConfigClass,LPSTR * ppBuffer,DWORD * pBytesReturned)944 BOOL WINAPI FreeRDP_WTSQueryUserConfigA(LPSTR pServerName, LPSTR pUserName,
945 WTS_CONFIG_CLASS WTSConfigClass, LPSTR* ppBuffer,
946 DWORD* pBytesReturned)
947 {
948 return FALSE;
949 }
950
FreeRDP_WTSSetUserConfigW(LPWSTR pServerName,LPWSTR pUserName,WTS_CONFIG_CLASS WTSConfigClass,LPWSTR pBuffer,DWORD DataLength)951 BOOL WINAPI FreeRDP_WTSSetUserConfigW(LPWSTR pServerName, LPWSTR pUserName,
952 WTS_CONFIG_CLASS WTSConfigClass, LPWSTR pBuffer,
953 DWORD DataLength)
954 {
955 return FALSE;
956 }
957
FreeRDP_WTSSetUserConfigA(LPSTR pServerName,LPSTR pUserName,WTS_CONFIG_CLASS WTSConfigClass,LPSTR pBuffer,DWORD DataLength)958 BOOL WINAPI FreeRDP_WTSSetUserConfigA(LPSTR pServerName, LPSTR pUserName,
959 WTS_CONFIG_CLASS WTSConfigClass, LPSTR pBuffer,
960 DWORD DataLength)
961 {
962 return FALSE;
963 }
964
FreeRDP_WTSSendMessageW(HANDLE hServer,DWORD SessionId,LPWSTR pTitle,DWORD TitleLength,LPWSTR pMessage,DWORD MessageLength,DWORD Style,DWORD Timeout,DWORD * pResponse,BOOL bWait)965 BOOL WINAPI FreeRDP_WTSSendMessageW(HANDLE hServer, DWORD SessionId, LPWSTR pTitle,
966 DWORD TitleLength, LPWSTR pMessage, DWORD MessageLength,
967 DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait)
968 {
969 return FALSE;
970 }
971
FreeRDP_WTSSendMessageA(HANDLE hServer,DWORD SessionId,LPSTR pTitle,DWORD TitleLength,LPSTR pMessage,DWORD MessageLength,DWORD Style,DWORD Timeout,DWORD * pResponse,BOOL bWait)972 BOOL WINAPI FreeRDP_WTSSendMessageA(HANDLE hServer, DWORD SessionId, LPSTR pTitle,
973 DWORD TitleLength, LPSTR pMessage, DWORD MessageLength,
974 DWORD Style, DWORD Timeout, DWORD* pResponse, BOOL bWait)
975 {
976 return FALSE;
977 }
978
FreeRDP_WTSDisconnectSession(HANDLE hServer,DWORD SessionId,BOOL bWait)979 BOOL WINAPI FreeRDP_WTSDisconnectSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
980 {
981 return FALSE;
982 }
983
FreeRDP_WTSLogoffSession(HANDLE hServer,DWORD SessionId,BOOL bWait)984 BOOL WINAPI FreeRDP_WTSLogoffSession(HANDLE hServer, DWORD SessionId, BOOL bWait)
985 {
986 return FALSE;
987 }
988
FreeRDP_WTSShutdownSystem(HANDLE hServer,DWORD ShutdownFlag)989 BOOL WINAPI FreeRDP_WTSShutdownSystem(HANDLE hServer, DWORD ShutdownFlag)
990 {
991 return FALSE;
992 }
993
FreeRDP_WTSWaitSystemEvent(HANDLE hServer,DWORD EventMask,DWORD * pEventFlags)994 BOOL WINAPI FreeRDP_WTSWaitSystemEvent(HANDLE hServer, DWORD EventMask, DWORD* pEventFlags)
995 {
996 return FALSE;
997 }
998
peer_channel_queue_free_message(void * obj)999 static void peer_channel_queue_free_message(void* obj)
1000 {
1001 wMessage* msg = (wMessage*)obj;
1002 if (!msg)
1003 return;
1004
1005 free(msg->context);
1006 }
1007
channel_free(rdpPeerChannel * channel)1008 static void channel_free(rdpPeerChannel* channel)
1009 {
1010 if (!channel)
1011 return;
1012
1013 MessageQueue_Free(channel->queue);
1014 Stream_Free(channel->receiveData, TRUE);
1015 free(channel);
1016 }
1017
channel_new(WTSVirtualChannelManager * vcm,freerdp_peer * client,UINT32 ChannelId,UINT16 index,UINT16 type,size_t chunkSize)1018 static rdpPeerChannel* channel_new(WTSVirtualChannelManager* vcm, freerdp_peer* client,
1019 UINT32 ChannelId, UINT16 index, UINT16 type, size_t chunkSize)
1020 {
1021 wObject queueCallbacks = { 0 };
1022 rdpPeerChannel* channel = (rdpPeerChannel*)calloc(1, sizeof(rdpPeerChannel));
1023
1024 if (!channel)
1025 goto fail;
1026
1027 channel->vcm = vcm;
1028 channel->client = client;
1029 channel->channelId = ChannelId;
1030 channel->index = index;
1031 channel->channelType = type;
1032 channel->receiveData = Stream_New(NULL, chunkSize);
1033
1034 if (!channel->receiveData)
1035 goto fail;
1036
1037 queueCallbacks.fnObjectFree = peer_channel_queue_free_message;
1038 channel->queue = MessageQueue_New(&queueCallbacks);
1039
1040 if (!channel->queue)
1041 goto fail;
1042
1043 return channel;
1044 fail:
1045 channel_free(channel);
1046 return NULL;
1047 }
1048
FreeRDP_WTSVirtualChannelOpen(HANDLE hServer,DWORD SessionId,LPSTR pVirtualName)1049 HANDLE WINAPI FreeRDP_WTSVirtualChannelOpen(HANDLE hServer, DWORD SessionId, LPSTR pVirtualName)
1050 {
1051 size_t length;
1052 UINT32 index;
1053 rdpMcs* mcs;
1054 BOOL joined = FALSE;
1055 freerdp_peer* client;
1056 rdpPeerChannel* channel;
1057 WTSVirtualChannelManager* vcm;
1058 HANDLE hChannelHandle = NULL;
1059 vcm = (WTSVirtualChannelManager*)hServer;
1060
1061 if (!vcm)
1062 {
1063 SetLastError(ERROR_INVALID_DATA);
1064 return NULL;
1065 }
1066
1067 client = vcm->client;
1068 mcs = client->context->rdp->mcs;
1069 length = strlen(pVirtualName);
1070
1071 if (length > 8)
1072 {
1073 SetLastError(ERROR_NOT_FOUND);
1074 return NULL;
1075 }
1076
1077 for (index = 0; index < mcs->channelCount; index++)
1078 {
1079 if (mcs->channels[index].joined &&
1080 (strncmp(mcs->channels[index].Name, pVirtualName, length) == 0))
1081 {
1082 joined = TRUE;
1083 break;
1084 }
1085 }
1086
1087 if (!joined)
1088 {
1089 SetLastError(ERROR_NOT_FOUND);
1090 return NULL;
1091 }
1092
1093 channel = (rdpPeerChannel*)mcs->channels[index].handle;
1094
1095 if (!channel)
1096 {
1097 channel = channel_new(vcm, client, mcs->channels[index].ChannelId, index,
1098 RDP_PEER_CHANNEL_TYPE_SVC, client->settings->VirtualChannelChunkSize);
1099
1100 if (!channel)
1101 goto fail;
1102
1103 mcs->channels[index].handle = channel;
1104 }
1105
1106 hChannelHandle = (HANDLE)channel;
1107 return hChannelHandle;
1108 fail:
1109 channel_free(channel);
1110 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1111 return NULL;
1112 }
1113
FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId,LPSTR pVirtualName,DWORD flags)1114 HANDLE WINAPI FreeRDP_WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags)
1115 {
1116 UINT32 index;
1117 wStream* s = NULL;
1118 rdpMcs* mcs;
1119 BOOL joined = FALSE;
1120 freerdp_peer* client;
1121 rdpPeerChannel* channel = NULL;
1122 ULONG written;
1123 WTSVirtualChannelManager* vcm = NULL;
1124
1125 if (SessionId == WTS_CURRENT_SESSION)
1126 return NULL;
1127
1128 vcm = (WTSVirtualChannelManager*)HashTable_GetItemValue(g_ServerHandles,
1129 (void*)(UINT_PTR)SessionId);
1130
1131 if (!vcm)
1132 return NULL;
1133
1134 if (!(flags & WTS_CHANNEL_OPTION_DYNAMIC))
1135 {
1136 return FreeRDP_WTSVirtualChannelOpen((HANDLE)vcm, SessionId, pVirtualName);
1137 }
1138
1139 client = vcm->client;
1140 mcs = client->context->rdp->mcs;
1141
1142 for (index = 0; index < mcs->channelCount; index++)
1143 {
1144 if (mcs->channels[index].joined && (strncmp(mcs->channels[index].Name, "drdynvc", 7) == 0))
1145 {
1146 joined = TRUE;
1147 break;
1148 }
1149 }
1150
1151 if (!joined)
1152 {
1153 SetLastError(ERROR_NOT_FOUND);
1154 return NULL;
1155 }
1156
1157 if (!vcm->drdynvc_channel || (vcm->drdynvc_state != DRDYNVC_STATE_READY))
1158 {
1159 SetLastError(ERROR_NOT_READY);
1160 return NULL;
1161 }
1162
1163 channel = channel_new(vcm, client, 0, 0, RDP_PEER_CHANNEL_TYPE_DVC,
1164 client->settings->VirtualChannelChunkSize);
1165
1166 if (!channel)
1167 {
1168 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1169 return NULL;
1170 }
1171
1172 channel->channelId = InterlockedIncrement(&vcm->dvc_channel_id_seq);
1173
1174 if (ArrayList_Add(vcm->dynamicVirtualChannels, channel) < 0)
1175 goto fail;
1176
1177 s = Stream_New(NULL, 64);
1178
1179 if (!s)
1180 goto fail;
1181
1182 if (!wts_write_drdynvc_create_request(s, channel->channelId, pVirtualName))
1183 goto fail;
1184
1185 if (!WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR)Stream_Buffer(s),
1186 Stream_GetPosition(s), &written))
1187 goto fail;
1188
1189 Stream_Free(s, TRUE);
1190 return channel;
1191 fail:
1192 Stream_Free(s, TRUE);
1193 if (vcm)
1194 ArrayList_Remove(vcm->dynamicVirtualChannels, channel);
1195 channel_free(channel);
1196 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1197 return NULL;
1198 }
1199
FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)1200 BOOL WINAPI FreeRDP_WTSVirtualChannelClose(HANDLE hChannelHandle)
1201 {
1202 wStream* s;
1203 rdpMcs* mcs;
1204 WTSVirtualChannelManager* vcm;
1205 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1206 BOOL ret = TRUE;
1207
1208 if (channel)
1209 {
1210 vcm = channel->vcm;
1211 mcs = vcm->client->context->rdp->mcs;
1212
1213 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1214 {
1215 if (channel->index < mcs->channelCount)
1216 mcs->channels[channel->index].handle = NULL;
1217 }
1218 else
1219 {
1220 ArrayList_Remove(vcm->dynamicVirtualChannels, channel);
1221
1222 if (channel->dvc_open_state == DVC_OPEN_STATE_SUCCEEDED)
1223 {
1224 ULONG written;
1225 s = Stream_New(NULL, 8);
1226
1227 if (!s)
1228 {
1229 WLog_ERR(TAG, "Stream_New failed!");
1230 ret = FALSE;
1231 }
1232 else
1233 {
1234 wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channelId);
1235 ret = WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR)Stream_Buffer(s),
1236 Stream_GetPosition(s), &written);
1237 Stream_Free(s, TRUE);
1238 }
1239 }
1240 }
1241
1242 if (channel->receiveData)
1243 Stream_Free(channel->receiveData, TRUE);
1244
1245 if (channel->queue)
1246 {
1247 MessageQueue_Free(channel->queue);
1248 channel->queue = NULL;
1249 }
1250
1251 free(channel);
1252 }
1253
1254 return ret;
1255 }
1256
FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle,ULONG TimeOut,PCHAR Buffer,ULONG BufferSize,PULONG pBytesRead)1257 BOOL WINAPI FreeRDP_WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer,
1258 ULONG BufferSize, PULONG pBytesRead)
1259 {
1260 BYTE* buffer;
1261 wMessage message;
1262 wtsChannelMessage* messageCtx;
1263 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1264
1265 if (!MessageQueue_Peek(channel->queue, &message, FALSE))
1266 {
1267 SetLastError(ERROR_NO_DATA);
1268 *pBytesRead = 0;
1269 return FALSE;
1270 }
1271
1272 messageCtx = (wtsChannelMessage*)(UINT_PTR)message.context;
1273
1274 if (messageCtx == NULL)
1275 return FALSE;
1276
1277 buffer = (BYTE*)(messageCtx + 1);
1278 *pBytesRead = messageCtx->length - messageCtx->offset;
1279
1280 if (Buffer == NULL || BufferSize == 0)
1281 {
1282 return TRUE;
1283 }
1284
1285 if (*pBytesRead > BufferSize)
1286 *pBytesRead = BufferSize;
1287
1288 CopyMemory(Buffer, buffer + messageCtx->offset, *pBytesRead);
1289 messageCtx->offset += *pBytesRead;
1290
1291 if (messageCtx->offset >= messageCtx->length)
1292 {
1293 MessageQueue_Peek(channel->queue, &message, TRUE);
1294 peer_channel_queue_free_message(&message);
1295 }
1296
1297 return TRUE;
1298 }
1299
FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle,PCHAR Buffer,ULONG Length,PULONG pBytesWritten)1300 BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length,
1301 PULONG pBytesWritten)
1302 {
1303 wStream* s;
1304 int cbLen;
1305 int cbChId;
1306 int first;
1307 BYTE* buffer;
1308 UINT32 length;
1309 UINT32 written;
1310 UINT32 totalWritten = 0;
1311 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1312 BOOL ret = TRUE;
1313
1314 if (!channel)
1315 return FALSE;
1316
1317 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1318 {
1319 length = Length;
1320 buffer = (BYTE*)malloc(length);
1321
1322 if (!buffer)
1323 {
1324 SetLastError(E_OUTOFMEMORY);
1325 return FALSE;
1326 }
1327
1328 CopyMemory(buffer, Buffer, length);
1329 totalWritten = Length;
1330 ret = wts_queue_send_item(channel, buffer, length);
1331 }
1332 else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
1333 {
1334 DEBUG_DVC("drdynvc not ready");
1335 return FALSE;
1336 }
1337 else
1338 {
1339 first = TRUE;
1340
1341 while (Length > 0)
1342 {
1343 s = Stream_New(NULL, channel->client->settings->VirtualChannelChunkSize);
1344
1345 if (!s)
1346 {
1347 WLog_ERR(TAG, "Stream_New failed!");
1348 SetLastError(E_OUTOFMEMORY);
1349 return FALSE;
1350 }
1351
1352 buffer = Stream_Buffer(s);
1353 Stream_Seek_UINT8(s);
1354 cbChId = wts_write_variable_uint(s, channel->channelId);
1355
1356 if (first && (Length > (UINT32)Stream_GetRemainingLength(s)))
1357 {
1358 cbLen = wts_write_variable_uint(s, Length);
1359 buffer[0] = (DATA_FIRST_PDU << 4) | (cbLen << 2) | cbChId;
1360 }
1361 else
1362 {
1363 buffer[0] = (DATA_PDU << 4) | cbChId;
1364 }
1365
1366 first = FALSE;
1367 written = Stream_GetRemainingLength(s);
1368
1369 if (written > Length)
1370 written = Length;
1371
1372 Stream_Write(s, Buffer, written);
1373 length = Stream_GetPosition(s);
1374 Stream_Free(s, FALSE);
1375 Length -= written;
1376 Buffer += written;
1377 totalWritten += written;
1378 ret = wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length);
1379 }
1380 }
1381
1382 if (pBytesWritten)
1383 *pBytesWritten = totalWritten;
1384
1385 return ret;
1386 }
1387
FreeRDP_WTSVirtualChannelPurgeInput(HANDLE hChannelHandle)1388 BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeInput(HANDLE hChannelHandle)
1389 {
1390 return TRUE;
1391 }
1392
FreeRDP_WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle)1393 BOOL WINAPI FreeRDP_WTSVirtualChannelPurgeOutput(HANDLE hChannelHandle)
1394 {
1395 return TRUE;
1396 }
1397
FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle,WTS_VIRTUAL_CLASS WtsVirtualClass,PVOID * ppBuffer,DWORD * pBytesReturned)1398 BOOL WINAPI FreeRDP_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass,
1399 PVOID* ppBuffer, DWORD* pBytesReturned)
1400 {
1401 void* pfd;
1402 BOOL bval;
1403 void* fds[10];
1404 HANDLE hEvent;
1405 int fds_count = 0;
1406 BOOL status = FALSE;
1407 rdpPeerChannel* channel = (rdpPeerChannel*)hChannelHandle;
1408 ZeroMemory(fds, sizeof(fds));
1409 hEvent = MessageQueue_Event(channel->queue);
1410
1411 switch ((UINT32)WtsVirtualClass)
1412 {
1413 case WTSVirtualFileHandle:
1414 pfd = GetEventWaitObject(hEvent);
1415
1416 if (pfd)
1417 {
1418 fds[fds_count] = pfd;
1419 (fds_count)++;
1420 }
1421
1422 *ppBuffer = malloc(sizeof(void*));
1423
1424 if (!*ppBuffer)
1425 {
1426 SetLastError(E_OUTOFMEMORY);
1427 }
1428 else
1429 {
1430 CopyMemory(*ppBuffer, &fds[0], sizeof(void*));
1431 *pBytesReturned = sizeof(void*);
1432 status = TRUE;
1433 }
1434
1435 break;
1436
1437 case WTSVirtualEventHandle:
1438 *ppBuffer = malloc(sizeof(HANDLE));
1439
1440 if (!*ppBuffer)
1441 {
1442 SetLastError(E_OUTOFMEMORY);
1443 }
1444 else
1445 {
1446 CopyMemory(*ppBuffer, &(hEvent), sizeof(HANDLE));
1447 *pBytesReturned = sizeof(void*);
1448 status = TRUE;
1449 }
1450
1451 break;
1452
1453 case WTSVirtualChannelReady:
1454 if (channel->channelType == RDP_PEER_CHANNEL_TYPE_SVC)
1455 {
1456 bval = TRUE;
1457 status = TRUE;
1458 }
1459 else
1460 {
1461 switch (channel->dvc_open_state)
1462 {
1463 case DVC_OPEN_STATE_NONE:
1464 bval = FALSE;
1465 status = TRUE;
1466 break;
1467
1468 case DVC_OPEN_STATE_SUCCEEDED:
1469 bval = TRUE;
1470 status = TRUE;
1471 break;
1472
1473 default:
1474 bval = FALSE;
1475 status = FALSE;
1476 break;
1477 }
1478 }
1479
1480 *ppBuffer = malloc(sizeof(BOOL));
1481
1482 if (!*ppBuffer)
1483 {
1484 SetLastError(E_OUTOFMEMORY);
1485 status = FALSE;
1486 }
1487 else
1488 {
1489 CopyMemory(*ppBuffer, &bval, sizeof(BOOL));
1490 *pBytesReturned = sizeof(BOOL);
1491 }
1492
1493 break;
1494
1495 default:
1496 break;
1497 }
1498
1499 return status;
1500 }
1501
FreeRDP_WTSFreeMemory(PVOID pMemory)1502 VOID WINAPI FreeRDP_WTSFreeMemory(PVOID pMemory)
1503 {
1504 free(pMemory);
1505 }
1506
FreeRDP_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass,PVOID pMemory,ULONG NumberOfEntries)1507 BOOL WINAPI FreeRDP_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
1508 ULONG NumberOfEntries)
1509 {
1510 return FALSE;
1511 }
1512
FreeRDP_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass,PVOID pMemory,ULONG NumberOfEntries)1513 BOOL WINAPI FreeRDP_WTSFreeMemoryExA(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory,
1514 ULONG NumberOfEntries)
1515 {
1516 return FALSE;
1517 }
1518
FreeRDP_WTSRegisterSessionNotification(HWND hWnd,DWORD dwFlags)1519 BOOL WINAPI FreeRDP_WTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)
1520 {
1521 return FALSE;
1522 }
1523
FreeRDP_WTSUnRegisterSessionNotification(HWND hWnd)1524 BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotification(HWND hWnd)
1525 {
1526 return FALSE;
1527 }
1528
FreeRDP_WTSRegisterSessionNotificationEx(HANDLE hServer,HWND hWnd,DWORD dwFlags)1529 BOOL WINAPI FreeRDP_WTSRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd, DWORD dwFlags)
1530 {
1531 return FALSE;
1532 }
1533
FreeRDP_WTSUnRegisterSessionNotificationEx(HANDLE hServer,HWND hWnd)1534 BOOL WINAPI FreeRDP_WTSUnRegisterSessionNotificationEx(HANDLE hServer, HWND hWnd)
1535 {
1536 return FALSE;
1537 }
1538
FreeRDP_WTSQueryUserToken(ULONG SessionId,PHANDLE phToken)1539 BOOL WINAPI FreeRDP_WTSQueryUserToken(ULONG SessionId, PHANDLE phToken)
1540 {
1541 return FALSE;
1542 }
1543
FreeRDP_WTSEnumerateProcessesExW(HANDLE hServer,DWORD * pLevel,DWORD SessionId,LPWSTR * ppProcessInfo,DWORD * pCount)1544 BOOL WINAPI FreeRDP_WTSEnumerateProcessesExW(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
1545 LPWSTR* ppProcessInfo, DWORD* pCount)
1546 {
1547 return FALSE;
1548 }
1549
FreeRDP_WTSEnumerateProcessesExA(HANDLE hServer,DWORD * pLevel,DWORD SessionId,LPSTR * ppProcessInfo,DWORD * pCount)1550 BOOL WINAPI FreeRDP_WTSEnumerateProcessesExA(HANDLE hServer, DWORD* pLevel, DWORD SessionId,
1551 LPSTR* ppProcessInfo, DWORD* pCount)
1552 {
1553 return FALSE;
1554 }
1555
FreeRDP_WTSEnumerateListenersW(HANDLE hServer,PVOID pReserved,DWORD Reserved,PWTSLISTENERNAMEW pListeners,DWORD * pCount)1556 BOOL WINAPI FreeRDP_WTSEnumerateListenersW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1557 PWTSLISTENERNAMEW pListeners, DWORD* pCount)
1558 {
1559 return FALSE;
1560 }
1561
FreeRDP_WTSEnumerateListenersA(HANDLE hServer,PVOID pReserved,DWORD Reserved,PWTSLISTENERNAMEA pListeners,DWORD * pCount)1562 BOOL WINAPI FreeRDP_WTSEnumerateListenersA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1563 PWTSLISTENERNAMEA pListeners, DWORD* pCount)
1564 {
1565 return FALSE;
1566 }
1567
FreeRDP_WTSQueryListenerConfigW(HANDLE hServer,PVOID pReserved,DWORD Reserved,LPWSTR pListenerName,PWTSLISTENERCONFIGW pBuffer)1568 BOOL WINAPI FreeRDP_WTSQueryListenerConfigW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1569 LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer)
1570 {
1571 return FALSE;
1572 }
1573
FreeRDP_WTSQueryListenerConfigA(HANDLE hServer,PVOID pReserved,DWORD Reserved,LPSTR pListenerName,PWTSLISTENERCONFIGA pBuffer)1574 BOOL WINAPI FreeRDP_WTSQueryListenerConfigA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1575 LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer)
1576 {
1577 return FALSE;
1578 }
1579
FreeRDP_WTSCreateListenerW(HANDLE hServer,PVOID pReserved,DWORD Reserved,LPWSTR pListenerName,PWTSLISTENERCONFIGW pBuffer,DWORD flag)1580 BOOL WINAPI FreeRDP_WTSCreateListenerW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1581 LPWSTR pListenerName, PWTSLISTENERCONFIGW pBuffer,
1582 DWORD flag)
1583 {
1584 return FALSE;
1585 }
1586
FreeRDP_WTSCreateListenerA(HANDLE hServer,PVOID pReserved,DWORD Reserved,LPSTR pListenerName,PWTSLISTENERCONFIGA pBuffer,DWORD flag)1587 BOOL WINAPI FreeRDP_WTSCreateListenerA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1588 LPSTR pListenerName, PWTSLISTENERCONFIGA pBuffer, DWORD flag)
1589 {
1590 return FALSE;
1591 }
1592
FreeRDP_WTSSetListenerSecurityW(HANDLE hServer,PVOID pReserved,DWORD Reserved,LPWSTR pListenerName,SECURITY_INFORMATION SecurityInformation,PSECURITY_DESCRIPTOR pSecurityDescriptor)1593 BOOL WINAPI FreeRDP_WTSSetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1594 LPWSTR pListenerName,
1595 SECURITY_INFORMATION SecurityInformation,
1596 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1597 {
1598 return FALSE;
1599 }
1600
FreeRDP_WTSSetListenerSecurityA(HANDLE hServer,PVOID pReserved,DWORD Reserved,LPSTR pListenerName,SECURITY_INFORMATION SecurityInformation,PSECURITY_DESCRIPTOR pSecurityDescriptor)1601 BOOL WINAPI FreeRDP_WTSSetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1602 LPSTR pListenerName,
1603 SECURITY_INFORMATION SecurityInformation,
1604 PSECURITY_DESCRIPTOR pSecurityDescriptor)
1605 {
1606 return FALSE;
1607 }
1608
FreeRDP_WTSGetListenerSecurityW(HANDLE hServer,PVOID pReserved,DWORD Reserved,LPWSTR pListenerName,SECURITY_INFORMATION SecurityInformation,PSECURITY_DESCRIPTOR pSecurityDescriptor,DWORD nLength,LPDWORD lpnLengthNeeded)1609 BOOL WINAPI FreeRDP_WTSGetListenerSecurityW(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1610 LPWSTR pListenerName,
1611 SECURITY_INFORMATION SecurityInformation,
1612 PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
1613 LPDWORD lpnLengthNeeded)
1614 {
1615 return FALSE;
1616 }
1617
FreeRDP_WTSGetListenerSecurityA(HANDLE hServer,PVOID pReserved,DWORD Reserved,LPSTR pListenerName,SECURITY_INFORMATION SecurityInformation,PSECURITY_DESCRIPTOR pSecurityDescriptor,DWORD nLength,LPDWORD lpnLengthNeeded)1618 BOOL WINAPI FreeRDP_WTSGetListenerSecurityA(HANDLE hServer, PVOID pReserved, DWORD Reserved,
1619 LPSTR pListenerName,
1620 SECURITY_INFORMATION SecurityInformation,
1621 PSECURITY_DESCRIPTOR pSecurityDescriptor, DWORD nLength,
1622 LPDWORD lpnLengthNeeded)
1623 {
1624 return FALSE;
1625 }
1626
FreeRDP_WTSEnableChildSessions(BOOL bEnable)1627 BOOL CDECL FreeRDP_WTSEnableChildSessions(BOOL bEnable)
1628 {
1629 return FALSE;
1630 }
1631
FreeRDP_WTSIsChildSessionsEnabled(PBOOL pbEnabled)1632 BOOL CDECL FreeRDP_WTSIsChildSessionsEnabled(PBOOL pbEnabled)
1633 {
1634 return FALSE;
1635 }
1636
FreeRDP_WTSGetChildSessionId(PULONG pSessionId)1637 BOOL CDECL FreeRDP_WTSGetChildSessionId(PULONG pSessionId)
1638 {
1639 return FALSE;
1640 }
1641
FreeRDP_WTSGetActiveConsoleSessionId(void)1642 DWORD WINAPI FreeRDP_WTSGetActiveConsoleSessionId(void)
1643 {
1644 return 0xFFFFFFFF;
1645 }
FreeRDP_WTSLogoffUser(HANDLE hServer)1646 BOOL WINAPI FreeRDP_WTSLogoffUser(HANDLE hServer)
1647 {
1648 return FALSE;
1649 }
1650
FreeRDP_WTSLogonUser(HANDLE hServer,LPCSTR username,LPCSTR password,LPCSTR domain)1651 BOOL WINAPI FreeRDP_WTSLogonUser(HANDLE hServer, LPCSTR username, LPCSTR password, LPCSTR domain)
1652 {
1653 return FALSE;
1654 }
1655