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