Coverage Report

Created: 2026-02-26 06:54

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