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