Coverage Report

Created: 2023-11-19 06:16

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