Coverage Report

Created: 2024-05-20 06:11

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