1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * Client 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 <freerdp/log.h>
27 
28 #include "rdp.h"
29 
30 #include "client.h"
31 
32 #define TAG FREERDP_TAG("core.client")
33 
34 static WINPR_TLS void* g_pInterface = NULL;
35 static WINPR_TLS rdpChannels* g_channels = NULL; /* use only for VirtualChannelInit hack */
36 
37 static volatile LONG g_OpenHandleSeq =
38     1; /* use global counter to ensure uniqueness across channel manager instances */
39 static WINPR_TLS rdpChannelHandles g_ChannelHandles = { NULL, NULL };
40 
41 static BOOL freerdp_channels_process_message_free(wMessage* message, DWORD type);
42 
freerdp_channels_find_channel_open_data_by_name(rdpChannels * channels,const char * name)43 static CHANNEL_OPEN_DATA* freerdp_channels_find_channel_open_data_by_name(rdpChannels* channels,
44                                                                           const char* name)
45 {
46 	int index;
47 	CHANNEL_OPEN_DATA* pChannelOpenData;
48 
49 	for (index = 0; index < channels->openDataCount; index++)
50 	{
51 		pChannelOpenData = &channels->openDataList[index];
52 
53 		if (strncmp(name, pChannelOpenData->name, CHANNEL_NAME_LEN) == 0)
54 			return pChannelOpenData;
55 	}
56 
57 	return NULL;
58 }
59 
60 /* returns rdpChannel for the channel name passed in */
freerdp_channels_find_channel_by_name(rdpRdp * rdp,const char * name)61 static rdpMcsChannel* freerdp_channels_find_channel_by_name(rdpRdp* rdp, const char* name)
62 {
63 	UINT32 index;
64 	rdpMcsChannel* channel = NULL;
65 	rdpMcs* mcs = NULL;
66 
67 	if (!rdp)
68 		return NULL;
69 
70 	mcs = rdp->mcs;
71 
72 	for (index = 0; index < mcs->channelCount; index++)
73 	{
74 		channel = &mcs->channels[index];
75 
76 		if (strncmp(name, channel->Name, CHANNEL_NAME_LEN) == 0)
77 		{
78 			return channel;
79 		}
80 	}
81 
82 	return NULL;
83 }
84 
freerdp_channels_find_channel_by_id(rdpRdp * rdp,UINT16 channel_id)85 static rdpMcsChannel* freerdp_channels_find_channel_by_id(rdpRdp* rdp, UINT16 channel_id)
86 {
87 	UINT32 index;
88 	rdpMcsChannel* channel = NULL;
89 	rdpMcs* mcs = NULL;
90 
91 	if (!rdp)
92 		return NULL;
93 
94 	mcs = rdp->mcs;
95 
96 	for (index = 0; index < mcs->channelCount; index++)
97 	{
98 		channel = &mcs->channels[index];
99 
100 		if (channel->ChannelId == channel_id)
101 		{
102 			return channel;
103 		}
104 	}
105 
106 	return NULL;
107 }
108 
channel_queue_message_free(wMessage * msg)109 static void channel_queue_message_free(wMessage* msg)
110 {
111 	CHANNEL_OPEN_EVENT* ev;
112 
113 	if (!msg || (msg->id != 0))
114 		return;
115 
116 	ev = (CHANNEL_OPEN_EVENT*)msg->wParam;
117 	free(ev);
118 }
119 
channel_queue_free(void * obj)120 static void channel_queue_free(void* obj)
121 {
122 	wMessage* msg = (wMessage*)obj;
123 	freerdp_channels_process_message_free(msg, CHANNEL_EVENT_WRITE_CANCELLED);
124 	channel_queue_message_free(msg);
125 }
126 
freerdp_channels_new(freerdp * instance)127 rdpChannels* freerdp_channels_new(freerdp* instance)
128 {
129 	rdpChannels* channels;
130 	channels = (rdpChannels*)calloc(1, sizeof(rdpChannels));
131 
132 	if (!channels)
133 		return NULL;
134 
135 	if (!InitializeCriticalSectionAndSpinCount(&channels->channelsLock, 4000))
136 		goto error;
137 
138 	channels->instance = instance;
139 	channels->queue = MessageQueue_New(NULL);
140 
141 	if (!channels->queue)
142 		goto error;
143 
144 	channels->queue->object.fnObjectFree = channel_queue_free;
145 	channels->openHandles = HashTable_New(TRUE);
146 
147 	if (!channels->openHandles)
148 		goto error;
149 
150 	return channels;
151 error:
152 	freerdp_channels_free(channels);
153 	return NULL;
154 }
155 
freerdp_channels_free(rdpChannels * channels)156 void freerdp_channels_free(rdpChannels* channels)
157 {
158 	if (!channels)
159 		return;
160 
161 	DeleteCriticalSection(&channels->channelsLock);
162 
163 	if (channels->queue)
164 	{
165 		MessageQueue_Free(channels->queue);
166 		channels->queue = NULL;
167 	}
168 
169 	if (channels->openHandles)
170 		HashTable_Free(channels->openHandles);
171 
172 	free(channels);
173 }
174 
175 /**
176  * Function description
177  *
178  * @return 0 on success, otherwise a Win32 error code
179  */
freerdp_drdynvc_on_channel_connected(DrdynvcClientContext * context,const char * name,void * pInterface)180 static UINT freerdp_drdynvc_on_channel_connected(DrdynvcClientContext* context, const char* name,
181                                                  void* pInterface)
182 {
183 	UINT status = CHANNEL_RC_OK;
184 	ChannelConnectedEventArgs e;
185 	rdpChannels* channels = (rdpChannels*)context->custom;
186 	freerdp* instance = channels->instance;
187 	EventArgsInit(&e, "freerdp");
188 	e.name = name;
189 	e.pInterface = pInterface;
190 	PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e);
191 	return status;
192 }
193 
194 /**
195  * Function description
196  *
197  * @return 0 on success, otherwise a Win32 error code
198  */
freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext * context,const char * name,void * pInterface)199 static UINT freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext* context, const char* name,
200                                                     void* pInterface)
201 {
202 	UINT status = CHANNEL_RC_OK;
203 	ChannelDisconnectedEventArgs e;
204 	rdpChannels* channels = (rdpChannels*)context->custom;
205 	freerdp* instance = channels->instance;
206 	EventArgsInit(&e, "freerdp");
207 	e.name = name;
208 	e.pInterface = pInterface;
209 	PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e);
210 	return status;
211 }
212 
freerdp_drdynvc_on_channel_attached(DrdynvcClientContext * context,const char * name,void * pInterface)213 static UINT freerdp_drdynvc_on_channel_attached(DrdynvcClientContext* context, const char* name,
214                                                 void* pInterface)
215 {
216 	UINT status = CHANNEL_RC_OK;
217 	ChannelAttachedEventArgs e;
218 	rdpChannels* channels = (rdpChannels*)context->custom;
219 	freerdp* instance = channels->instance;
220 	EventArgsInit(&e, "freerdp");
221 	e.name = name;
222 	e.pInterface = pInterface;
223 	PubSub_OnChannelAttached(instance->context->pubSub, instance->context, &e);
224 	return status;
225 }
226 
freerdp_drdynvc_on_channel_detached(DrdynvcClientContext * context,const char * name,void * pInterface)227 static UINT freerdp_drdynvc_on_channel_detached(DrdynvcClientContext* context, const char* name,
228                                                 void* pInterface)
229 {
230 	UINT status = CHANNEL_RC_OK;
231 	ChannelDetachedEventArgs e;
232 	rdpChannels* channels = (rdpChannels*)context->custom;
233 	freerdp* instance = channels->instance;
234 	EventArgsInit(&e, "freerdp");
235 	e.name = name;
236 	e.pInterface = pInterface;
237 	PubSub_OnChannelDetached(instance->context->pubSub, instance->context, &e);
238 	return status;
239 }
240 
241 /**
242  * go through and inform all the libraries that we are initialized
243  * called only from main thread
244  */
freerdp_channels_pre_connect(rdpChannels * channels,freerdp * instance)245 UINT freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance)
246 {
247 	UINT error = CHANNEL_RC_OK;
248 	int index;
249 	CHANNEL_CLIENT_DATA* pChannelClientData;
250 
251 	for (index = 0; index < channels->clientDataCount; index++)
252 	{
253 		pChannelClientData = &channels->clientDataList[index];
254 
255 		if (pChannelClientData->pChannelInitEventProc)
256 		{
257 			pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
258 			                                          CHANNEL_EVENT_INITIALIZED, 0, 0);
259 		}
260 		else if (pChannelClientData->pChannelInitEventProcEx)
261 		{
262 			pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
263 			                                            pChannelClientData->pInitHandle,
264 			                                            CHANNEL_EVENT_INITIALIZED, 0, 0);
265 		}
266 
267 		if (CHANNEL_RC_OK != getChannelError(instance->context))
268 			break;
269 	}
270 
271 	return error;
272 }
273 
freerdp_channels_attach(freerdp * instance)274 UINT freerdp_channels_attach(freerdp* instance)
275 {
276 	UINT error = CHANNEL_RC_OK;
277 	int index;
278 	char* hostname;
279 	size_t hostnameLength;
280 	rdpChannels* channels;
281 	CHANNEL_CLIENT_DATA* pChannelClientData;
282 	channels = instance->context->channels;
283 	hostname = instance->settings->ServerHostname;
284 	hostnameLength = strlen(hostname);
285 
286 	for (index = 0; index < channels->clientDataCount; index++)
287 	{
288 		ChannelAttachedEventArgs e;
289 		CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
290 		pChannelClientData = &channels->clientDataList[index];
291 
292 		if (pChannelClientData->pChannelInitEventProc)
293 		{
294 			pChannelClientData->pChannelInitEventProc(
295 			    pChannelClientData->pInitHandle, CHANNEL_EVENT_ATTACHED, hostname, hostnameLength);
296 		}
297 		else if (pChannelClientData->pChannelInitEventProcEx)
298 		{
299 			pChannelClientData->pChannelInitEventProcEx(
300 			    pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
301 			    CHANNEL_EVENT_ATTACHED, hostname, hostnameLength);
302 		}
303 
304 		if (getChannelError(instance->context) != CHANNEL_RC_OK)
305 			goto fail;
306 
307 		pChannelOpenData = &channels->openDataList[index];
308 		EventArgsInit(&e, "freerdp");
309 		e.name = pChannelOpenData->name;
310 		e.pInterface = pChannelOpenData->pInterface;
311 		PubSub_OnChannelAttached(instance->context->pubSub, instance->context, &e);
312 	}
313 
314 fail:
315 	return error;
316 }
317 
freerdp_channels_detach(freerdp * instance)318 UINT freerdp_channels_detach(freerdp* instance)
319 {
320 	UINT error = CHANNEL_RC_OK;
321 	int index;
322 	char* hostname;
323 	size_t hostnameLength;
324 	rdpChannels* channels;
325 	CHANNEL_CLIENT_DATA* pChannelClientData;
326 	channels = instance->context->channels;
327 	hostname = instance->settings->ServerHostname;
328 	hostnameLength = strlen(hostname);
329 
330 	for (index = 0; index < channels->clientDataCount; index++)
331 	{
332 		ChannelDetachedEventArgs e;
333 		CHANNEL_OPEN_DATA* pChannelOpenData;
334 		pChannelClientData = &channels->clientDataList[index];
335 
336 		if (pChannelClientData->pChannelInitEventProc)
337 		{
338 			pChannelClientData->pChannelInitEventProc(
339 			    pChannelClientData->pInitHandle, CHANNEL_EVENT_DETACHED, hostname, hostnameLength);
340 		}
341 		else if (pChannelClientData->pChannelInitEventProcEx)
342 		{
343 			pChannelClientData->pChannelInitEventProcEx(
344 			    pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
345 			    CHANNEL_EVENT_DETACHED, hostname, hostnameLength);
346 		}
347 
348 		if (getChannelError(instance->context) != CHANNEL_RC_OK)
349 			goto fail;
350 
351 		pChannelOpenData = &channels->openDataList[index];
352 		EventArgsInit(&e, "freerdp");
353 		e.name = pChannelOpenData->name;
354 		e.pInterface = pChannelOpenData->pInterface;
355 		PubSub_OnChannelDetached(instance->context->pubSub, instance->context, &e);
356 	}
357 
358 fail:
359 	return error;
360 }
361 
362 /**
363  * go through and inform all the libraries that we are connected
364  * this will tell the libraries that its ok to call MyVirtualChannelOpen
365  * called only from main thread
366  */
freerdp_channels_post_connect(rdpChannels * channels,freerdp * instance)367 UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
368 {
369 	UINT error = CHANNEL_RC_OK;
370 	int index;
371 	char* hostname;
372 	size_t hostnameLength;
373 	CHANNEL_CLIENT_DATA* pChannelClientData;
374 	channels->connected = TRUE;
375 	hostname = instance->settings->ServerHostname;
376 	hostnameLength = strlen(hostname);
377 
378 	for (index = 0; index < channels->clientDataCount; index++)
379 	{
380 		ChannelConnectedEventArgs e;
381 		CHANNEL_OPEN_DATA* pChannelOpenData;
382 		pChannelClientData = &channels->clientDataList[index];
383 
384 		if (pChannelClientData->pChannelInitEventProc)
385 		{
386 			pChannelClientData->pChannelInitEventProc(
387 			    pChannelClientData->pInitHandle, CHANNEL_EVENT_CONNECTED, hostname, hostnameLength);
388 		}
389 		else if (pChannelClientData->pChannelInitEventProcEx)
390 		{
391 			pChannelClientData->pChannelInitEventProcEx(
392 			    pChannelClientData->lpUserParam, pChannelClientData->pInitHandle,
393 			    CHANNEL_EVENT_CONNECTED, hostname, hostnameLength);
394 		}
395 
396 		if (getChannelError(instance->context) != CHANNEL_RC_OK)
397 			goto fail;
398 
399 		pChannelOpenData = &channels->openDataList[index];
400 		EventArgsInit(&e, "freerdp");
401 		e.name = pChannelOpenData->name;
402 		e.pInterface = pChannelOpenData->pInterface;
403 		PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e);
404 	}
405 
406 	channels->drdynvc =
407 	    (DrdynvcClientContext*)freerdp_channels_get_static_channel_interface(channels, "drdynvc");
408 
409 	if (channels->drdynvc)
410 	{
411 		channels->drdynvc->custom = (void*)channels;
412 		channels->drdynvc->OnChannelConnected = freerdp_drdynvc_on_channel_connected;
413 		channels->drdynvc->OnChannelDisconnected = freerdp_drdynvc_on_channel_disconnected;
414 		channels->drdynvc->OnChannelAttached = freerdp_drdynvc_on_channel_attached;
415 		channels->drdynvc->OnChannelDetached = freerdp_drdynvc_on_channel_detached;
416 	}
417 
418 fail:
419 	return error;
420 }
421 
freerdp_channels_data(freerdp * instance,UINT16 channelId,const BYTE * cdata,size_t dataSize,UINT32 flags,size_t totalSize)422 BOOL freerdp_channels_data(freerdp* instance, UINT16 channelId, const BYTE* cdata, size_t dataSize,
423                            UINT32 flags, size_t totalSize)
424 {
425 	UINT32 index;
426 	rdpMcs* mcs;
427 	rdpChannels* channels;
428 	rdpMcsChannel* channel = NULL;
429 	CHANNEL_OPEN_DATA* pChannelOpenData;
430 	union {
431 		const BYTE* pcb;
432 		BYTE* pb;
433 	} data;
434 
435 	data.pcb = cdata;
436 	if (!instance || !data.pcb)
437 	{
438 		WLog_ERR(TAG, "%s(%p, %" PRIu16 ", %p, 0x%08x): Invalid arguments", __FUNCTION__, instance,
439 		         channelId, data, flags);
440 		return FALSE;
441 	}
442 
443 	mcs = instance->context->rdp->mcs;
444 	channels = instance->context->channels;
445 
446 	if (!channels || !mcs)
447 	{
448 		return FALSE;
449 	}
450 
451 	for (index = 0; index < mcs->channelCount; index++)
452 	{
453 		if (mcs->channels[index].ChannelId == channelId)
454 		{
455 			channel = &mcs->channels[index];
456 			break;
457 		}
458 	}
459 
460 	if (!channel)
461 	{
462 		return FALSE;
463 	}
464 
465 	pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, channel->Name);
466 
467 	if (!pChannelOpenData)
468 	{
469 		return FALSE;
470 	}
471 
472 	if (pChannelOpenData->pChannelOpenEventProc)
473 	{
474 		pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle,
475 		                                        CHANNEL_EVENT_DATA_RECEIVED, data.pb, dataSize,
476 		                                        totalSize, flags);
477 	}
478 	else if (pChannelOpenData->pChannelOpenEventProcEx)
479 	{
480 		pChannelOpenData->pChannelOpenEventProcEx(
481 		    pChannelOpenData->lpUserParam, pChannelOpenData->OpenHandle,
482 		    CHANNEL_EVENT_DATA_RECEIVED, data.pb, dataSize, totalSize, flags);
483 	}
484 
485 	return TRUE;
486 }
487 
freerdp_channels_get_id_by_name(freerdp * instance,const char * channel_name)488 UINT16 freerdp_channels_get_id_by_name(freerdp* instance, const char* channel_name)
489 {
490 	rdpMcsChannel* mcsChannel;
491 	if (!instance || !channel_name)
492 		return -1;
493 
494 	mcsChannel = freerdp_channels_find_channel_by_name(instance->context->rdp, channel_name);
495 	if (!mcsChannel)
496 		return -1;
497 
498 	return mcsChannel->ChannelId;
499 }
500 
freerdp_channels_get_name_by_id(freerdp * instance,UINT16 channelId)501 const char* freerdp_channels_get_name_by_id(freerdp* instance, UINT16 channelId)
502 {
503 	rdpMcsChannel* mcsChannel;
504 	if (!instance)
505 		return NULL;
506 
507 	mcsChannel = freerdp_channels_find_channel_by_id(instance->context->rdp, channelId);
508 	if (!mcsChannel)
509 		return NULL;
510 
511 	return (const char*)mcsChannel->Name;
512 }
513 
freerdp_channels_process_message_free(wMessage * message,DWORD type)514 BOOL freerdp_channels_process_message_free(wMessage* message, DWORD type)
515 {
516 	if (message->id == WMQ_QUIT)
517 	{
518 		return FALSE;
519 	}
520 
521 	if (message->id == 0)
522 	{
523 		CHANNEL_OPEN_DATA* pChannelOpenData;
524 		CHANNEL_OPEN_EVENT* item = (CHANNEL_OPEN_EVENT*)message->wParam;
525 
526 		if (!item)
527 			return FALSE;
528 
529 		pChannelOpenData = item->pChannelOpenData;
530 
531 		if (pChannelOpenData->pChannelOpenEventProc)
532 		{
533 			pChannelOpenData->pChannelOpenEventProc(pChannelOpenData->OpenHandle, type,
534 			                                        item->UserData, item->DataLength,
535 			                                        item->DataLength, 0);
536 		}
537 		else if (pChannelOpenData->pChannelOpenEventProcEx)
538 		{
539 			pChannelOpenData->pChannelOpenEventProcEx(
540 			    pChannelOpenData->lpUserParam, pChannelOpenData->OpenHandle, type, item->UserData,
541 			    item->DataLength, item->DataLength, 0);
542 		}
543 	}
544 
545 	return TRUE;
546 }
547 
freerdp_channels_process_message(freerdp * instance,wMessage * message)548 static BOOL freerdp_channels_process_message(freerdp* instance, wMessage* message)
549 {
550 	if (message->id == WMQ_QUIT)
551 	{
552 		return FALSE;
553 	}
554 
555 	if (message->id == 0)
556 	{
557 		rdpMcsChannel* channel;
558 		CHANNEL_OPEN_DATA* pChannelOpenData;
559 		CHANNEL_OPEN_EVENT* item = (CHANNEL_OPEN_EVENT*)message->wParam;
560 
561 		if (!item)
562 			return FALSE;
563 
564 		pChannelOpenData = item->pChannelOpenData;
565 		channel =
566 		    freerdp_channels_find_channel_by_name(instance->context->rdp, pChannelOpenData->name);
567 
568 		if (channel)
569 			instance->SendChannelData(instance, channel->ChannelId, item->Data, item->DataLength);
570 	}
571 
572 	if (!freerdp_channels_process_message_free(message, CHANNEL_EVENT_WRITE_COMPLETE))
573 		return FALSE;
574 
575 	IFCALL(message->Free, message);
576 	return TRUE;
577 }
578 
579 /**
580  * called only from main thread
581  */
freerdp_channels_process_sync(rdpChannels * channels,freerdp * instance)582 static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance)
583 {
584 	int status = TRUE;
585 	wMessage message;
586 
587 	while (MessageQueue_Peek(channels->queue, &message, TRUE))
588 	{
589 		freerdp_channels_process_message(instance, &message);
590 	}
591 
592 	return status;
593 }
594 
595 /**
596  * called only from main thread
597  */
freerdp_channels_get_fds(rdpChannels * channels,freerdp * instance,void ** read_fds,int * read_count,void ** write_fds,int * write_count)598 BOOL freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** read_fds,
599                               int* read_count, void** write_fds, int* write_count)
600 {
601 	void* pfd;
602 	pfd = GetEventWaitObject(MessageQueue_Event(channels->queue));
603 
604 	if (pfd)
605 	{
606 		read_fds[*read_count] = pfd;
607 		(*read_count)++;
608 	}
609 
610 	return TRUE;
611 }
612 
freerdp_channels_get_static_channel_interface(rdpChannels * channels,const char * name)613 void* freerdp_channels_get_static_channel_interface(rdpChannels* channels, const char* name)
614 {
615 	void* pInterface = NULL;
616 	CHANNEL_OPEN_DATA* pChannelOpenData;
617 	pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, name);
618 
619 	if (pChannelOpenData)
620 		pInterface = pChannelOpenData->pInterface;
621 
622 	return pInterface;
623 }
624 
freerdp_channels_get_event_handle(freerdp * instance)625 HANDLE freerdp_channels_get_event_handle(freerdp* instance)
626 {
627 	HANDLE event = NULL;
628 	rdpChannels* channels;
629 	channels = instance->context->channels;
630 	event = MessageQueue_Event(channels->queue);
631 	return event;
632 }
633 
freerdp_channels_process_pending_messages(freerdp * instance)634 int freerdp_channels_process_pending_messages(freerdp* instance)
635 {
636 	rdpChannels* channels;
637 	channels = instance->context->channels;
638 
639 	if (WaitForSingleObject(MessageQueue_Event(channels->queue), 0) == WAIT_OBJECT_0)
640 	{
641 		return freerdp_channels_process_sync(channels, instance);
642 	}
643 
644 	return TRUE;
645 }
646 
647 /**
648  * called only from main thread
649  */
freerdp_channels_check_fds(rdpChannels * channels,freerdp * instance)650 BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance)
651 {
652 	if (WaitForSingleObject(MessageQueue_Event(channels->queue), 0) == WAIT_OBJECT_0)
653 	{
654 		freerdp_channels_process_sync(channels, instance);
655 	}
656 
657 	return TRUE;
658 }
659 
freerdp_channels_disconnect(rdpChannels * channels,freerdp * instance)660 UINT freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
661 {
662 	UINT error = CHANNEL_RC_OK;
663 	int index;
664 	CHANNEL_OPEN_DATA* pChannelOpenData;
665 	CHANNEL_CLIENT_DATA* pChannelClientData;
666 
667 	if (!channels->connected)
668 		return 0;
669 
670 	freerdp_channels_check_fds(channels, instance);
671 
672 	/* tell all libraries we are shutting down */
673 	for (index = 0; index < channels->clientDataCount; index++)
674 	{
675 		ChannelDisconnectedEventArgs e;
676 		pChannelClientData = &channels->clientDataList[index];
677 
678 		if (pChannelClientData->pChannelInitEventProc)
679 		{
680 			pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
681 			                                          CHANNEL_EVENT_DISCONNECTED, 0, 0);
682 		}
683 		else if (pChannelClientData->pChannelInitEventProcEx)
684 		{
685 			pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
686 			                                            pChannelClientData->pInitHandle,
687 			                                            CHANNEL_EVENT_DISCONNECTED, 0, 0);
688 		}
689 
690 		if (getChannelError(instance->context) != CHANNEL_RC_OK)
691 			continue;
692 
693 		pChannelOpenData = &channels->openDataList[index];
694 		EventArgsInit(&e, "freerdp");
695 		e.name = pChannelOpenData->name;
696 		e.pInterface = pChannelOpenData->pInterface;
697 		PubSub_OnChannelDisconnected(instance->context->pubSub, instance->context, &e);
698 	}
699 
700 	channels->connected = FALSE;
701 	return error;
702 }
703 
freerdp_channels_close(rdpChannels * channels,freerdp * instance)704 void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
705 {
706 	int index;
707 	CHANNEL_OPEN_DATA* pChannelOpenData;
708 	CHANNEL_CLIENT_DATA* pChannelClientData;
709 	freerdp_channels_check_fds(channels, instance);
710 
711 	/* tell all libraries we are shutting down */
712 	for (index = 0; index < channels->clientDataCount; index++)
713 	{
714 		pChannelClientData = &channels->clientDataList[index];
715 
716 		if (pChannelClientData->pChannelInitEventProc)
717 		{
718 			pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
719 			                                          CHANNEL_EVENT_TERMINATED, 0, 0);
720 		}
721 		else if (pChannelClientData->pChannelInitEventProcEx)
722 		{
723 			pChannelClientData->pChannelInitEventProcEx(pChannelClientData->lpUserParam,
724 			                                            pChannelClientData->pInitHandle,
725 			                                            CHANNEL_EVENT_TERMINATED, 0, 0);
726 		}
727 	}
728 
729 	channels->clientDataCount = 0;
730 	MessageQueue_PostQuit(channels->queue, 0);
731 
732 	for (index = 0; index < channels->openDataCount; index++)
733 	{
734 		pChannelOpenData = &channels->openDataList[index];
735 		freerdp_channel_remove_open_handle_data(&g_ChannelHandles, pChannelOpenData->OpenHandle);
736 
737 		if (channels->openHandles)
738 			HashTable_Remove(channels->openHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle);
739 	}
740 
741 	channels->openDataCount = 0;
742 	channels->initDataCount = 0;
743 	instance->settings->ChannelCount = 0;
744 }
745 
FreeRDP_VirtualChannelInitEx(LPVOID lpUserParam,LPVOID clientContext,LPVOID pInitHandle,PCHANNEL_DEF pChannel,INT channelCount,ULONG versionRequested,PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx)746 static UINT VCAPITYPE FreeRDP_VirtualChannelInitEx(
747     LPVOID lpUserParam, LPVOID clientContext, LPVOID pInitHandle, PCHANNEL_DEF pChannel,
748     INT channelCount, ULONG versionRequested, PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx)
749 {
750 	INT index;
751 	CHANNEL_DEF* channel;
752 	rdpSettings* settings;
753 	PCHANNEL_DEF pChannelDef;
754 	CHANNEL_INIT_DATA* pChannelInitData;
755 	CHANNEL_OPEN_DATA* pChannelOpenData;
756 	CHANNEL_CLIENT_DATA* pChannelClientData;
757 	rdpChannels* channels = (rdpChannels*)pInitHandle;
758 
759 	if (!pInitHandle)
760 		return CHANNEL_RC_BAD_INIT_HANDLE;
761 
762 	if (!pChannel)
763 		return CHANNEL_RC_BAD_CHANNEL;
764 
765 	if ((channelCount <= 0) || !pChannelInitEventProcEx)
766 		return CHANNEL_RC_INITIALIZATION_ERROR;
767 
768 	pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
769 	channels = pChannelInitData->channels;
770 	pChannelInitData->pInterface = clientContext;
771 
772 	if (!channels->can_call_init)
773 		return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
774 
775 	if ((channels->openDataCount + channelCount) > CHANNEL_MAX_COUNT)
776 		return CHANNEL_RC_TOO_MANY_CHANNELS;
777 
778 	if (channels->connected)
779 		return CHANNEL_RC_ALREADY_CONNECTED;
780 
781 	if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
782 	{
783 	}
784 
785 	for (index = 0; index < channelCount; index++)
786 	{
787 		pChannelDef = &pChannel[index];
788 
789 		if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != 0)
790 		{
791 			return CHANNEL_RC_BAD_CHANNEL;
792 		}
793 	}
794 
795 	pChannelClientData = &channels->clientDataList[channels->clientDataCount];
796 	pChannelClientData->pChannelInitEventProcEx = pChannelInitEventProcEx;
797 	pChannelClientData->pInitHandle = pInitHandle;
798 	pChannelClientData->lpUserParam = lpUserParam;
799 	channels->clientDataCount++;
800 	settings = channels->instance->context->settings;
801 
802 	for (index = 0; index < channelCount; index++)
803 	{
804 		pChannelDef = &pChannel[index];
805 		pChannelOpenData = &channels->openDataList[channels->openDataCount];
806 		pChannelOpenData->OpenHandle = InterlockedIncrement(&g_OpenHandleSeq);
807 		pChannelOpenData->channels = channels;
808 		pChannelOpenData->lpUserParam = lpUserParam;
809 		HashTable_Add(channels->openHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle,
810 		              (void*)pChannelOpenData);
811 		pChannelOpenData->flags = 1; /* init */
812 		strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
813 		pChannelOpenData->options = pChannelDef->options;
814 
815 		if (settings->ChannelCount < CHANNEL_MAX_COUNT)
816 		{
817 			channel = &settings->ChannelDefArray[settings->ChannelCount];
818 			strncpy(channel->name, pChannelDef->name, 7);
819 			channel->options = pChannelDef->options;
820 			settings->ChannelCount++;
821 		}
822 
823 		channels->openDataCount++;
824 	}
825 
826 	return CHANNEL_RC_OK;
827 }
828 
FreeRDP_VirtualChannelInit(LPVOID * ppInitHandle,PCHANNEL_DEF pChannel,INT channelCount,ULONG versionRequested,PCHANNEL_INIT_EVENT_FN pChannelInitEventProc)829 static UINT VCAPITYPE FreeRDP_VirtualChannelInit(LPVOID* ppInitHandle, PCHANNEL_DEF pChannel,
830                                                  INT channelCount, ULONG versionRequested,
831                                                  PCHANNEL_INIT_EVENT_FN pChannelInitEventProc)
832 {
833 	INT index;
834 	void* pInterface;
835 	CHANNEL_DEF* channel;
836 	rdpSettings* settings;
837 	PCHANNEL_DEF pChannelDef;
838 	CHANNEL_INIT_DATA* pChannelInitData;
839 	CHANNEL_OPEN_DATA* pChannelOpenData;
840 	CHANNEL_CLIENT_DATA* pChannelClientData;
841 	rdpChannels* channels = g_channels;
842 
843 	if (!ppInitHandle || !channels)
844 		return CHANNEL_RC_BAD_INIT_HANDLE;
845 
846 	if (!pChannel)
847 		return CHANNEL_RC_BAD_CHANNEL;
848 
849 	if ((channelCount <= 0) || !pChannelInitEventProc)
850 		return CHANNEL_RC_INITIALIZATION_ERROR;
851 
852 	pInterface = g_pInterface;
853 	pChannelInitData = &(channels->initDataList[channels->initDataCount]);
854 	*ppInitHandle = pChannelInitData;
855 	channels->initDataCount++;
856 	pChannelInitData->channels = channels;
857 	pChannelInitData->pInterface = pInterface;
858 
859 	if (!channels->can_call_init)
860 		return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
861 
862 	if (channels->openDataCount + channelCount > CHANNEL_MAX_COUNT)
863 		return CHANNEL_RC_TOO_MANY_CHANNELS;
864 
865 	if (channels->connected)
866 		return CHANNEL_RC_ALREADY_CONNECTED;
867 
868 	if (versionRequested != VIRTUAL_CHANNEL_VERSION_WIN2000)
869 	{
870 	}
871 
872 	for (index = 0; index < channelCount; index++)
873 	{
874 		pChannelDef = &pChannel[index];
875 
876 		if (freerdp_channels_find_channel_open_data_by_name(channels, pChannelDef->name) != 0)
877 		{
878 			return CHANNEL_RC_BAD_CHANNEL;
879 		}
880 	}
881 
882 	pChannelClientData = &channels->clientDataList[channels->clientDataCount];
883 	pChannelClientData->pChannelInitEventProc = pChannelInitEventProc;
884 	pChannelClientData->pInitHandle = *ppInitHandle;
885 	channels->clientDataCount++;
886 	settings = channels->instance->context->settings;
887 
888 	for (index = 0; index < channelCount; index++)
889 	{
890 		pChannelDef = &pChannel[index];
891 		pChannelOpenData = &channels->openDataList[channels->openDataCount];
892 		pChannelOpenData->OpenHandle = InterlockedIncrement(&g_OpenHandleSeq);
893 		pChannelOpenData->channels = channels;
894 		freerdp_channel_add_open_handle_data(&g_ChannelHandles, pChannelOpenData->OpenHandle,
895 		                                     (void*)channels);
896 		HashTable_Add(channels->openHandles, (void*)(UINT_PTR)pChannelOpenData->OpenHandle,
897 		              (void*)pChannelOpenData);
898 		pChannelOpenData->flags = 1; /* init */
899 		strncpy(pChannelOpenData->name, pChannelDef->name, CHANNEL_NAME_LEN);
900 		pChannelOpenData->options = pChannelDef->options;
901 
902 		if (settings->ChannelCount < CHANNEL_MAX_COUNT)
903 		{
904 			channel = &settings->ChannelDefArray[settings->ChannelCount];
905 			strncpy(channel->name, pChannelDef->name, 7);
906 			channel->options = pChannelDef->options;
907 			settings->ChannelCount++;
908 		}
909 
910 		channels->openDataCount++;
911 	}
912 
913 	return CHANNEL_RC_OK;
914 }
915 
916 static UINT VCAPITYPE
FreeRDP_VirtualChannelOpenEx(LPVOID pInitHandle,LPDWORD pOpenHandle,PCHAR pChannelName,PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx)917 FreeRDP_VirtualChannelOpenEx(LPVOID pInitHandle, LPDWORD pOpenHandle, PCHAR pChannelName,
918                              PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx)
919 {
920 	void* pInterface;
921 	rdpChannels* channels;
922 	CHANNEL_INIT_DATA* pChannelInitData;
923 	CHANNEL_OPEN_DATA* pChannelOpenData;
924 	pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
925 	channels = pChannelInitData->channels;
926 	pInterface = pChannelInitData->pInterface;
927 
928 	if (!pOpenHandle)
929 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
930 
931 	if (!pChannelOpenEventProcEx)
932 		return CHANNEL_RC_BAD_PROC;
933 
934 	if (!channels->connected)
935 		return CHANNEL_RC_NOT_CONNECTED;
936 
937 	pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
938 
939 	if (!pChannelOpenData)
940 		return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
941 
942 	if (pChannelOpenData->flags == 2)
943 		return CHANNEL_RC_ALREADY_OPEN;
944 
945 	pChannelOpenData->flags = 2; /* open */
946 	pChannelOpenData->pInterface = pInterface;
947 	pChannelOpenData->pChannelOpenEventProcEx = pChannelOpenEventProcEx;
948 	*pOpenHandle = pChannelOpenData->OpenHandle;
949 	return CHANNEL_RC_OK;
950 }
951 
FreeRDP_VirtualChannelOpen(LPVOID pInitHandle,LPDWORD pOpenHandle,PCHAR pChannelName,PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc)952 static UINT VCAPITYPE FreeRDP_VirtualChannelOpen(LPVOID pInitHandle, LPDWORD pOpenHandle,
953                                                  PCHAR pChannelName,
954                                                  PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc)
955 {
956 	void* pInterface;
957 	rdpChannels* channels;
958 	CHANNEL_INIT_DATA* pChannelInitData;
959 	CHANNEL_OPEN_DATA* pChannelOpenData;
960 	pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
961 	channels = pChannelInitData->channels;
962 	pInterface = pChannelInitData->pInterface;
963 
964 	if (!pOpenHandle)
965 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
966 
967 	if (!pChannelOpenEventProc)
968 		return CHANNEL_RC_BAD_PROC;
969 
970 	if (!channels->connected)
971 		return CHANNEL_RC_NOT_CONNECTED;
972 
973 	pChannelOpenData = freerdp_channels_find_channel_open_data_by_name(channels, pChannelName);
974 
975 	if (!pChannelOpenData)
976 		return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
977 
978 	if (pChannelOpenData->flags == 2)
979 		return CHANNEL_RC_ALREADY_OPEN;
980 
981 	pChannelOpenData->flags = 2; /* open */
982 	pChannelOpenData->pInterface = pInterface;
983 	pChannelOpenData->pChannelOpenEventProc = pChannelOpenEventProc;
984 	*pOpenHandle = pChannelOpenData->OpenHandle;
985 	return CHANNEL_RC_OK;
986 }
987 
FreeRDP_VirtualChannelCloseEx(LPVOID pInitHandle,DWORD openHandle)988 static UINT VCAPITYPE FreeRDP_VirtualChannelCloseEx(LPVOID pInitHandle, DWORD openHandle)
989 {
990 	rdpChannels* channels = NULL;
991 	CHANNEL_INIT_DATA* pChannelInitData = NULL;
992 	CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
993 
994 	if (!pInitHandle)
995 		return CHANNEL_RC_BAD_INIT_HANDLE;
996 
997 	pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
998 	channels = pChannelInitData->channels;
999 
1000 	if (!channels)
1001 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1002 
1003 	pChannelOpenData = HashTable_GetItemValue(channels->openHandles, (void*)(UINT_PTR)openHandle);
1004 
1005 	if (!pChannelOpenData)
1006 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1007 
1008 	if (pChannelOpenData->flags != 2)
1009 		return CHANNEL_RC_NOT_OPEN;
1010 
1011 	pChannelOpenData->flags = 0;
1012 	return CHANNEL_RC_OK;
1013 }
1014 
FreeRDP_VirtualChannelClose(DWORD openHandle)1015 static UINT VCAPITYPE FreeRDP_VirtualChannelClose(DWORD openHandle)
1016 {
1017 	rdpChannels* channels;
1018 	CHANNEL_OPEN_DATA* pChannelOpenData;
1019 	channels = (rdpChannels*)freerdp_channel_get_open_handle_data(&g_ChannelHandles, openHandle);
1020 
1021 	if (!channels)
1022 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1023 
1024 	pChannelOpenData = HashTable_GetItemValue(channels->openHandles, (void*)(UINT_PTR)openHandle);
1025 
1026 	if (!pChannelOpenData)
1027 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1028 
1029 	if (pChannelOpenData->flags != 2)
1030 		return CHANNEL_RC_NOT_OPEN;
1031 
1032 	pChannelOpenData->flags = 0;
1033 	return CHANNEL_RC_OK;
1034 }
1035 
FreeRDP_VirtualChannelWriteEx(LPVOID pInitHandle,DWORD openHandle,LPVOID pData,ULONG dataLength,LPVOID pUserData)1036 static UINT VCAPITYPE FreeRDP_VirtualChannelWriteEx(LPVOID pInitHandle, DWORD openHandle,
1037                                                     LPVOID pData, ULONG dataLength,
1038                                                     LPVOID pUserData)
1039 {
1040 	rdpChannels* channels = NULL;
1041 	CHANNEL_INIT_DATA* pChannelInitData = NULL;
1042 	CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
1043 	CHANNEL_OPEN_EVENT* pChannelOpenEvent = NULL;
1044 	wMessage message;
1045 
1046 	if (!pInitHandle)
1047 		return CHANNEL_RC_BAD_INIT_HANDLE;
1048 
1049 	pChannelInitData = (CHANNEL_INIT_DATA*)pInitHandle;
1050 	channels = pChannelInitData->channels;
1051 
1052 	if (!channels)
1053 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1054 
1055 	pChannelOpenData = HashTable_GetItemValue(channels->openHandles, (void*)(UINT_PTR)openHandle);
1056 
1057 	if (!pChannelOpenData)
1058 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1059 
1060 	if (!channels->connected)
1061 		return CHANNEL_RC_NOT_CONNECTED;
1062 
1063 	if (!pData)
1064 		return CHANNEL_RC_NULL_DATA;
1065 
1066 	if (!dataLength)
1067 		return CHANNEL_RC_ZERO_LENGTH;
1068 
1069 	if (pChannelOpenData->flags != 2)
1070 		return CHANNEL_RC_NOT_OPEN;
1071 
1072 	pChannelOpenEvent = (CHANNEL_OPEN_EVENT*)malloc(sizeof(CHANNEL_OPEN_EVENT));
1073 
1074 	if (!pChannelOpenEvent)
1075 		return CHANNEL_RC_NO_MEMORY;
1076 
1077 	pChannelOpenEvent->Data = pData;
1078 	pChannelOpenEvent->DataLength = dataLength;
1079 	pChannelOpenEvent->UserData = pUserData;
1080 	pChannelOpenEvent->pChannelOpenData = pChannelOpenData;
1081 	message.context = channels;
1082 	message.id = 0;
1083 	message.wParam = pChannelOpenEvent;
1084 	message.lParam = NULL;
1085 	message.Free = channel_queue_message_free;
1086 
1087 	if (!MessageQueue_Dispatch(channels->queue, &message))
1088 	{
1089 		free(pChannelOpenEvent);
1090 		return CHANNEL_RC_NO_MEMORY;
1091 	}
1092 
1093 	return CHANNEL_RC_OK;
1094 }
1095 
FreeRDP_VirtualChannelWrite(DWORD openHandle,LPVOID pData,ULONG dataLength,LPVOID pUserData)1096 static UINT VCAPITYPE FreeRDP_VirtualChannelWrite(DWORD openHandle, LPVOID pData, ULONG dataLength,
1097                                                   LPVOID pUserData)
1098 {
1099 	wMessage message;
1100 	CHANNEL_OPEN_DATA* pChannelOpenData;
1101 	CHANNEL_OPEN_EVENT* pChannelOpenEvent;
1102 	rdpChannels* channels =
1103 	    (rdpChannels*)freerdp_channel_get_open_handle_data(&g_ChannelHandles, openHandle);
1104 
1105 	if (!channels)
1106 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1107 
1108 	pChannelOpenData = HashTable_GetItemValue(channels->openHandles, (void*)(UINT_PTR)openHandle);
1109 
1110 	if (!pChannelOpenData)
1111 		return CHANNEL_RC_BAD_CHANNEL_HANDLE;
1112 
1113 	if (!channels->connected)
1114 		return CHANNEL_RC_NOT_CONNECTED;
1115 
1116 	if (!pData)
1117 		return CHANNEL_RC_NULL_DATA;
1118 
1119 	if (!dataLength)
1120 		return CHANNEL_RC_ZERO_LENGTH;
1121 
1122 	if (pChannelOpenData->flags != 2)
1123 		return CHANNEL_RC_NOT_OPEN;
1124 
1125 	pChannelOpenEvent = (CHANNEL_OPEN_EVENT*)malloc(sizeof(CHANNEL_OPEN_EVENT));
1126 
1127 	if (!pChannelOpenEvent)
1128 		return CHANNEL_RC_NO_MEMORY;
1129 
1130 	pChannelOpenEvent->Data = pData;
1131 	pChannelOpenEvent->DataLength = dataLength;
1132 	pChannelOpenEvent->UserData = pUserData;
1133 	pChannelOpenEvent->pChannelOpenData = pChannelOpenData;
1134 	message.context = channels;
1135 	message.id = 0;
1136 	message.wParam = pChannelOpenEvent;
1137 	message.lParam = NULL;
1138 	message.Free = channel_queue_message_free;
1139 
1140 	if (!MessageQueue_Dispatch(channels->queue, &message))
1141 	{
1142 		free(pChannelOpenEvent);
1143 		return CHANNEL_RC_NO_MEMORY;
1144 	}
1145 
1146 	return CHANNEL_RC_OK;
1147 }
1148 
freerdp_channels_is_loaded(rdpChannels * channels,PVIRTUALCHANNELENTRY entry)1149 static BOOL freerdp_channels_is_loaded(rdpChannels* channels, PVIRTUALCHANNELENTRY entry)
1150 {
1151 	int i;
1152 
1153 	for (i = 0; i < channels->clientDataCount; i++)
1154 	{
1155 		CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[i];
1156 
1157 		if (pChannelClientData->entry == entry)
1158 			return TRUE;
1159 	}
1160 
1161 	return FALSE;
1162 }
1163 
freerdp_channels_is_loaded_ex(rdpChannels * channels,PVIRTUALCHANNELENTRYEX entryEx)1164 static BOOL freerdp_channels_is_loaded_ex(rdpChannels* channels, PVIRTUALCHANNELENTRYEX entryEx)
1165 {
1166 	int i;
1167 
1168 	for (i = 0; i < channels->clientDataCount; i++)
1169 	{
1170 		CHANNEL_CLIENT_DATA* pChannelClientData = &channels->clientDataList[i];
1171 
1172 		if (pChannelClientData->entryEx == entryEx)
1173 			return TRUE;
1174 	}
1175 
1176 	return FALSE;
1177 }
1178 
freerdp_channels_client_load(rdpChannels * channels,rdpSettings * settings,PVIRTUALCHANNELENTRY entry,void * data)1179 int freerdp_channels_client_load(rdpChannels* channels, rdpSettings* settings,
1180                                  PVIRTUALCHANNELENTRY entry, void* data)
1181 {
1182 	int status;
1183 	CHANNEL_ENTRY_POINTS_FREERDP EntryPoints;
1184 	CHANNEL_CLIENT_DATA* pChannelClientData;
1185 
1186 	if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT)
1187 	{
1188 		WLog_ERR(TAG, "error: too many channels");
1189 		return 1;
1190 	}
1191 
1192 	if (freerdp_channels_is_loaded(channels, entry))
1193 	{
1194 		WLog_WARN(TAG, "Skipping, channel already loaded");
1195 		return 0;
1196 	}
1197 
1198 	pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1199 	pChannelClientData->entry = entry;
1200 	ZeroMemory(&EntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
1201 	EntryPoints.cbSize = sizeof(EntryPoints);
1202 	EntryPoints.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
1203 	EntryPoints.pVirtualChannelInit = FreeRDP_VirtualChannelInit;
1204 	EntryPoints.pVirtualChannelOpen = FreeRDP_VirtualChannelOpen;
1205 	EntryPoints.pVirtualChannelClose = FreeRDP_VirtualChannelClose;
1206 	EntryPoints.pVirtualChannelWrite = FreeRDP_VirtualChannelWrite;
1207 	EntryPoints.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER;
1208 	EntryPoints.ppInterface = &g_pInterface;
1209 	EntryPoints.pExtendedData = data;
1210 	EntryPoints.context = ((freerdp*)settings->instance)->context;
1211 	/* enable VirtualChannelInit */
1212 	channels->can_call_init = TRUE;
1213 	EnterCriticalSection(&channels->channelsLock);
1214 	g_pInterface = NULL;
1215 	g_channels = channels;
1216 	status = pChannelClientData->entry((PCHANNEL_ENTRY_POINTS)&EntryPoints);
1217 	LeaveCriticalSection(&channels->channelsLock);
1218 	/* disable MyVirtualChannelInit */
1219 	channels->can_call_init = FALSE;
1220 
1221 	if (!status)
1222 	{
1223 		WLog_ERR(TAG, "error: channel export function call failed");
1224 		return 1;
1225 	}
1226 
1227 	return 0;
1228 }
1229 
freerdp_channels_client_load_ex(rdpChannels * channels,rdpSettings * settings,PVIRTUALCHANNELENTRYEX entryEx,void * data)1230 int freerdp_channels_client_load_ex(rdpChannels* channels, rdpSettings* settings,
1231                                     PVIRTUALCHANNELENTRYEX entryEx, void* data)
1232 {
1233 	int status;
1234 	void* pInitHandle = NULL;
1235 	CHANNEL_ENTRY_POINTS_FREERDP_EX EntryPointsEx;
1236 	CHANNEL_INIT_DATA* pChannelInitData = NULL;
1237 	CHANNEL_CLIENT_DATA* pChannelClientData = NULL;
1238 
1239 	if (channels->clientDataCount + 1 > CHANNEL_MAX_COUNT)
1240 	{
1241 		WLog_ERR(TAG, "error: too many channels");
1242 		return 1;
1243 	}
1244 
1245 	if (freerdp_channels_is_loaded_ex(channels, entryEx))
1246 	{
1247 		WLog_WARN(TAG, "Skipping, channel already loaded");
1248 		return 0;
1249 	}
1250 
1251 	pChannelClientData = &channels->clientDataList[channels->clientDataCount];
1252 	pChannelClientData->entryEx = entryEx;
1253 	pChannelInitData = &(channels->initDataList[channels->initDataCount++]);
1254 	pInitHandle = pChannelInitData;
1255 	pChannelInitData->channels = channels;
1256 	ZeroMemory(&EntryPointsEx, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX));
1257 	EntryPointsEx.cbSize = sizeof(EntryPointsEx);
1258 	EntryPointsEx.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
1259 	EntryPointsEx.pVirtualChannelInitEx = FreeRDP_VirtualChannelInitEx;
1260 	EntryPointsEx.pVirtualChannelOpenEx = FreeRDP_VirtualChannelOpenEx;
1261 	EntryPointsEx.pVirtualChannelCloseEx = FreeRDP_VirtualChannelCloseEx;
1262 	EntryPointsEx.pVirtualChannelWriteEx = FreeRDP_VirtualChannelWriteEx;
1263 	EntryPointsEx.MagicNumber = FREERDP_CHANNEL_MAGIC_NUMBER;
1264 	EntryPointsEx.pExtendedData = data;
1265 	EntryPointsEx.context = ((freerdp*)settings->instance)->context;
1266 	/* enable VirtualChannelInit */
1267 	channels->can_call_init = TRUE;
1268 	EnterCriticalSection(&channels->channelsLock);
1269 	status = pChannelClientData->entryEx((PCHANNEL_ENTRY_POINTS_EX)&EntryPointsEx, pInitHandle);
1270 	LeaveCriticalSection(&channels->channelsLock);
1271 	/* disable MyVirtualChannelInit */
1272 	channels->can_call_init = FALSE;
1273 
1274 	if (!status)
1275 	{
1276 		WLog_ERR(TAG, "error: channel export function call failed");
1277 		return 1;
1278 	}
1279 
1280 	return 0;
1281 }
1282 
1283 /**
1284  * this is called when processing the command line parameters
1285  * called only from main thread
1286  */
freerdp_channels_load_plugin(rdpChannels * channels,rdpSettings * settings,const char * name,void * data)1287 int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings, const char* name,
1288                                  void* data)
1289 {
1290 	PVIRTUALCHANNELENTRY entry;
1291 	entry = freerdp_load_channel_addin_entry(name, NULL, NULL, FREERDP_ADDIN_CHANNEL_STATIC);
1292 
1293 	if (!entry)
1294 		return 1;
1295 
1296 	return freerdp_channels_client_load(channels, settings, entry, data);
1297 }
1298