Coverage Report

Created: 2026-03-04 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/channels/encomsp/client/encomsp_main.c
Line
Count
Source
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Multiparty Virtual Channel
4
 *
5
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 * Copyright 2015 Thincast Technologies GmbH
7
 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21
22
#include <freerdp/config.h>
23
24
#include <winpr/crt.h>
25
#include <winpr/assert.h>
26
#include <winpr/print.h>
27
28
#include <freerdp/freerdp.h>
29
#include <freerdp/channels/log.h>
30
#include <freerdp/client/encomsp.h>
31
32
#include "encomsp_main.h"
33
34
struct encomsp_plugin
35
{
36
  CHANNEL_DEF channelDef;
37
  CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints;
38
39
  EncomspClientContext* context;
40
41
  HANDLE thread;
42
  wStream* data_in;
43
  void* InitHandle;
44
  DWORD OpenHandle;
45
  wMessageQueue* queue;
46
  rdpContext* rdpcontext;
47
};
48
49
/**
50
 * Function description
51
 *
52
 * @return 0 on success, otherwise a Win32 error code
53
 */
54
static UINT encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header)
55
0
{
56
0
  WINPR_ASSERT(header);
57
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, ENCOMSP_ORDER_HEADER_SIZE))
58
0
    return ERROR_INVALID_DATA;
59
60
0
  Stream_Read_UINT16(s, header->Type);   /* Type (2 bytes) */
61
0
  Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */
62
0
  return CHANNEL_RC_OK;
63
0
}
64
65
/**
66
 * Function description
67
 *
68
 * @return 0 on success, otherwise a Win32 error code
69
 */
70
static UINT encomsp_write_header(wStream* s, const ENCOMSP_ORDER_HEADER* header)
71
0
{
72
0
  WINPR_ASSERT(header);
73
0
  Stream_Write_UINT16(s, header->Type);   /* Type (2 bytes) */
74
0
  Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */
75
0
  return CHANNEL_RC_OK;
76
0
}
77
78
/**
79
 * Function description
80
 *
81
 * @return 0 on success, otherwise a Win32 error code
82
 */
83
static UINT encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
84
0
{
85
0
  WINPR_ASSERT(str);
86
0
  const ENCOMSP_UNICODE_STRING empty = WINPR_C_ARRAY_INIT;
87
0
  *str = empty;
88
89
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 2))
90
0
    return ERROR_INVALID_DATA;
91
92
0
  Stream_Read_UINT16(s, str->cchString); /* cchString (2 bytes) */
93
94
0
  if (str->cchString > 1024)
95
0
  {
96
0
    WLog_ERR(TAG, "cchString was %" PRIu16 " but has to be < 1025!", str->cchString);
97
0
    return ERROR_INVALID_DATA;
98
0
  }
99
100
0
  if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, str->cchString, sizeof(WCHAR)))
101
0
    return ERROR_INVALID_DATA;
102
103
0
  Stream_Read(s, &(str->wString), (sizeof(WCHAR) * str->cchString)); /* String (variable) */
104
0
  return CHANNEL_RC_OK;
105
0
}
106
107
static EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp)
108
0
{
109
0
  WINPR_ASSERT(encomsp);
110
0
  return (EncomspClientContext*)encomsp->channelEntryPoints.pInterface;
111
0
}
112
113
/**
114
 * Function description
115
 *
116
 * @return 0 on success, otherwise a Win32 error code
117
 */
118
static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s)
119
0
{
120
0
  if (!encomsp)
121
0
  {
122
0
    Stream_Free(s, TRUE);
123
0
    return ERROR_INVALID_HANDLE;
124
0
  }
125
126
0
  const UINT status = encomsp->channelEntryPoints.pVirtualChannelWriteEx(
127
0
      encomsp->InitHandle, encomsp->OpenHandle, Stream_Buffer(s), (UINT32)Stream_Length(s), s);
128
129
0
  if (status != CHANNEL_RC_OK)
130
0
  {
131
0
    Stream_Free(s, TRUE);
132
0
    WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08" PRIX32 "]",
133
0
             WTSErrorToString(status), status);
134
0
  }
135
0
  return status;
136
0
}
137
138
/**
139
 * Function description
140
 *
141
 * @return 0 on success, otherwise a Win32 error code
142
 */
143
static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s,
144
                                            const ENCOMSP_ORDER_HEADER* header)
145
0
{
146
0
  ENCOMSP_FILTER_UPDATED_PDU pdu = WINPR_C_ARRAY_INIT;
147
0
  UINT error = CHANNEL_RC_OK;
148
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
149
150
0
  if (!context)
151
0
    return ERROR_INVALID_HANDLE;
152
153
0
  WINPR_ASSERT(header);
154
0
  const size_t pos = Stream_GetPosition(s);
155
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
156
0
    return ERROR_INVALID_DATA;
157
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
158
0
  pdu.Length = header->Length;
159
0
  pdu.Type = header->Type;
160
161
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
162
0
    return ERROR_INVALID_DATA;
163
164
0
  Stream_Read_UINT8(s, pdu.Flags); /* Flags (1 byte) */
165
0
  const size_t end = Stream_GetPosition(s);
166
0
  const size_t body = beg + header->Length;
167
168
0
  if (body < end)
169
0
  {
170
0
    WLog_ERR(TAG, "Not enough data!");
171
0
    return ERROR_INVALID_DATA;
172
0
  }
173
174
0
  if (body > end)
175
0
  {
176
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
177
0
      return ERROR_INVALID_DATA;
178
179
0
    if (!Stream_SetPosition(s, body))
180
0
      return ERROR_INVALID_DATA;
181
0
  }
182
183
0
  IFCALLRET(context->FilterUpdated, error, context, &pdu);
184
185
0
  if (error)
186
0
    WLog_ERR(TAG, "context->FilterUpdated failed with error %" PRIu32 "", error);
187
188
0
  return error;
189
0
}
190
191
/**
192
 * Function description
193
 *
194
 * @return 0 on success, otherwise a Win32 error code
195
 */
196
static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp, wStream* s,
197
                                                 const ENCOMSP_ORDER_HEADER* header)
198
0
{
199
0
  ENCOMSP_APPLICATION_CREATED_PDU pdu = WINPR_C_ARRAY_INIT;
200
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
201
202
0
  if (!context)
203
0
    return ERROR_INVALID_HANDLE;
204
205
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
206
0
    return ERROR_INVALID_DATA;
207
208
0
  const size_t pos = Stream_GetPosition(s);
209
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
210
0
    return ERROR_INVALID_DATA;
211
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
212
213
0
  WINPR_ASSERT(header);
214
0
  pdu.Length = header->Length;
215
0
  pdu.Type = header->Type;
216
217
0
  Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
218
0
  Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */
219
220
0
  UINT error = encomsp_read_unicode_string(s, &(pdu.Name));
221
0
  if (error != CHANNEL_RC_OK)
222
0
  {
223
0
    WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %" PRIu32 "", error);
224
0
    return error;
225
0
  }
226
227
0
  const size_t end = Stream_GetPosition(s);
228
0
  const size_t body = beg + header->Length;
229
230
0
  if (body < end)
231
0
  {
232
0
    WLog_ERR(TAG, "Not enough data!");
233
0
    return ERROR_INVALID_DATA;
234
0
  }
235
236
0
  if (body > end)
237
0
  {
238
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
239
0
      return ERROR_INVALID_DATA;
240
241
0
    if (!Stream_SetPosition(s, body))
242
0
      return ERROR_INVALID_DATA;
243
0
  }
244
245
0
  IFCALLRET(context->ApplicationCreated, error, context, &pdu);
246
247
0
  if (error)
248
0
    WLog_ERR(TAG, "context->ApplicationCreated failed with error %" PRIu32 "", error);
249
250
0
  return error;
251
0
}
252
253
/**
254
 * Function description
255
 *
256
 * @return 0 on success, otherwise a Win32 error code
257
 */
258
static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, wStream* s,
259
                                                 const ENCOMSP_ORDER_HEADER* header)
260
0
{
261
0
  ENCOMSP_APPLICATION_REMOVED_PDU pdu = WINPR_C_ARRAY_INIT;
262
0
  UINT error = CHANNEL_RC_OK;
263
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
264
265
0
  if (!context)
266
0
    return ERROR_INVALID_HANDLE;
267
268
0
  const size_t pos = Stream_GetPosition(s);
269
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
270
0
    return ERROR_INVALID_DATA;
271
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
272
273
0
  WINPR_ASSERT(header);
274
0
  pdu.Length = header->Length;
275
0
  pdu.Type = header->Type;
276
277
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
278
0
    return ERROR_INVALID_DATA;
279
280
0
  Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */
281
0
  const size_t end = Stream_GetPosition(s);
282
0
  const size_t body = beg + header->Length;
283
284
0
  if (body < end)
285
0
  {
286
0
    WLog_ERR(TAG, "Not enough data!");
287
0
    return ERROR_INVALID_DATA;
288
0
  }
289
290
0
  if (body > end)
291
0
  {
292
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
293
0
      return ERROR_INVALID_DATA;
294
295
0
    if (!Stream_SetPosition(s, body))
296
0
      return ERROR_INVALID_DATA;
297
0
  }
298
299
0
  IFCALLRET(context->ApplicationRemoved, error, context, &pdu);
300
301
0
  if (error)
302
0
    WLog_ERR(TAG, "context->ApplicationRemoved failed with error %" PRIu32 "", error);
303
304
0
  return error;
305
0
}
306
307
/**
308
 * Function description
309
 *
310
 * @return 0 on success, otherwise a Win32 error code
311
 */
312
static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s,
313
                                            const ENCOMSP_ORDER_HEADER* header)
314
0
{
315
0
  ENCOMSP_WINDOW_CREATED_PDU pdu = WINPR_C_ARRAY_INIT;
316
0
  UINT error = CHANNEL_RC_OK;
317
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
318
319
0
  if (!context)
320
0
    return ERROR_INVALID_HANDLE;
321
322
0
  const size_t pos = Stream_GetPosition(s);
323
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
324
0
    return ERROR_INVALID_DATA;
325
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
326
327
0
  WINPR_ASSERT(header);
328
0
  pdu.Length = header->Length;
329
0
  pdu.Type = header->Type;
330
331
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
332
0
    return ERROR_INVALID_DATA;
333
334
0
  Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */
335
0
  Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */
336
0
  Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */
337
338
0
  if ((error = encomsp_read_unicode_string(s, &(pdu.Name))))
339
0
  {
340
0
    WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %" PRIu32 "", error);
341
0
    return error;
342
0
  }
343
344
0
  const size_t end = Stream_GetPosition(s);
345
0
  const size_t body = beg + header->Length;
346
347
0
  if (body < end)
348
0
  {
349
0
    WLog_ERR(TAG, "Not enough data!");
350
0
    return ERROR_INVALID_DATA;
351
0
  }
352
353
0
  if (body > end)
354
0
  {
355
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
356
0
      return ERROR_INVALID_DATA;
357
358
0
    if (!Stream_SetPosition(s, body))
359
0
      return ERROR_INVALID_DATA;
360
0
  }
361
362
0
  IFCALLRET(context->WindowCreated, error, context, &pdu);
363
364
0
  if (error)
365
0
    WLog_ERR(TAG, "context->WindowCreated failed with error %" PRIu32 "", error);
366
367
0
  return error;
368
0
}
369
370
/**
371
 * Function description
372
 *
373
 * @return 0 on success, otherwise a Win32 error code
374
 */
375
static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s,
376
                                            const ENCOMSP_ORDER_HEADER* header)
377
0
{
378
0
  ENCOMSP_WINDOW_REMOVED_PDU pdu = WINPR_C_ARRAY_INIT;
379
0
  UINT error = CHANNEL_RC_OK;
380
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
381
382
0
  if (!context)
383
0
    return ERROR_INVALID_HANDLE;
384
385
0
  const size_t pos = Stream_GetPosition(s);
386
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
387
0
    return ERROR_INVALID_DATA;
388
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
389
390
0
  WINPR_ASSERT(header);
391
0
  pdu.Length = header->Length;
392
0
  pdu.Type = header->Type;
393
394
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
395
0
    return ERROR_INVALID_DATA;
396
397
0
  Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */
398
0
  const size_t end = Stream_GetPosition(s);
399
0
  const size_t body = beg + header->Length;
400
401
0
  if (body < end)
402
0
  {
403
0
    WLog_ERR(TAG, "Not enough data!");
404
0
    return ERROR_INVALID_DATA;
405
0
  }
406
407
0
  if (body > end)
408
0
  {
409
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
410
0
      return ERROR_INVALID_DATA;
411
412
0
    if (!Stream_SetPosition(s, body))
413
0
      return ERROR_INVALID_DATA;
414
0
  }
415
416
0
  IFCALLRET(context->WindowRemoved, error, context, &pdu);
417
418
0
  if (error)
419
0
    WLog_ERR(TAG, "context->WindowRemoved failed with error %" PRIu32 "", error);
420
421
0
  return error;
422
0
}
423
424
/**
425
 * Function description
426
 *
427
 * @return 0 on success, otherwise a Win32 error code
428
 */
429
static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s,
430
                                         const ENCOMSP_ORDER_HEADER* header)
431
0
{
432
0
  ENCOMSP_SHOW_WINDOW_PDU pdu = WINPR_C_ARRAY_INIT;
433
0
  UINT error = CHANNEL_RC_OK;
434
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
435
436
0
  if (!context)
437
0
    return ERROR_INVALID_HANDLE;
438
439
0
  const size_t pos = Stream_GetPosition(s);
440
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
441
0
    return ERROR_INVALID_DATA;
442
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
443
444
0
  WINPR_ASSERT(header);
445
0
  pdu.Length = header->Length;
446
0
  pdu.Type = header->Type;
447
448
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
449
0
    return ERROR_INVALID_DATA;
450
451
0
  Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */
452
0
  const size_t end = Stream_GetPosition(s);
453
0
  const size_t body = beg + header->Length;
454
455
0
  if (body < end)
456
0
  {
457
0
    WLog_ERR(TAG, "Not enough data!");
458
0
    return ERROR_INVALID_DATA;
459
0
  }
460
461
0
  if (body > end)
462
0
  {
463
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
464
0
      return ERROR_INVALID_DATA;
465
466
0
    if (!Stream_SetPosition(s, body))
467
0
      return ERROR_INVALID_DATA;
468
0
  }
469
470
0
  IFCALLRET(context->ShowWindow, error, context, &pdu);
471
472
0
  if (error)
473
0
    WLog_ERR(TAG, "context->ShowWindow failed with error %" PRIu32 "", error);
474
475
0
  return error;
476
0
}
477
478
/**
479
 * Function description
480
 *
481
 * @return 0 on success, otherwise a Win32 error code
482
 */
483
static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, wStream* s,
484
                                                 const ENCOMSP_ORDER_HEADER* header)
485
0
{
486
0
  ENCOMSP_PARTICIPANT_CREATED_PDU pdu = WINPR_C_ARRAY_INIT;
487
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
488
489
0
  if (!context)
490
0
    return ERROR_INVALID_HANDLE;
491
492
0
  const size_t pos = Stream_GetPosition(s);
493
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
494
0
    return ERROR_INVALID_DATA;
495
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
496
497
0
  WINPR_ASSERT(header);
498
0
  pdu.Length = header->Length;
499
0
  pdu.Type = header->Type;
500
501
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
502
0
    return ERROR_INVALID_DATA;
503
504
0
  Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
505
0
  Stream_Read_UINT32(s, pdu.GroupId);       /* GroupId (4 bytes) */
506
0
  Stream_Read_UINT16(s, pdu.Flags);         /* Flags (2 bytes) */
507
508
0
  UINT error = encomsp_read_unicode_string(s, &(pdu.FriendlyName));
509
0
  if (error != CHANNEL_RC_OK)
510
0
  {
511
0
    WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %" PRIu32 "", error);
512
0
    return error;
513
0
  }
514
515
0
  const size_t end = Stream_GetPosition(s);
516
0
  const size_t body = beg + header->Length;
517
518
0
  if (body < end)
519
0
  {
520
0
    WLog_ERR(TAG, "Not enough data!");
521
0
    return ERROR_INVALID_DATA;
522
0
  }
523
524
0
  if (body > end)
525
0
  {
526
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
527
0
      return ERROR_INVALID_DATA;
528
529
0
    if (!Stream_SetPosition(s, body))
530
0
      return ERROR_INVALID_DATA;
531
0
  }
532
533
0
  IFCALLRET(context->ParticipantCreated, error, context, &pdu);
534
535
0
  if (error)
536
0
    WLog_ERR(TAG, "context->ParticipantCreated failed with error %" PRIu32 "", error);
537
538
0
  return error;
539
0
}
540
541
/**
542
 * Function description
543
 *
544
 * @return 0 on success, otherwise a Win32 error code
545
 */
546
static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, wStream* s,
547
                                                 const ENCOMSP_ORDER_HEADER* header)
548
0
{
549
0
  ENCOMSP_PARTICIPANT_REMOVED_PDU pdu = WINPR_C_ARRAY_INIT;
550
0
  UINT error = CHANNEL_RC_OK;
551
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
552
553
0
  if (!context)
554
0
    return ERROR_INVALID_HANDLE;
555
556
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
557
0
    return ERROR_INVALID_DATA;
558
559
0
  const size_t beg = (Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE;
560
561
0
  WINPR_ASSERT(header);
562
0
  pdu.Length = header->Length;
563
0
  pdu.Type = header->Type;
564
565
0
  Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
566
0
  Stream_Read_UINT32(s, pdu.DiscType);      /* DiscType (4 bytes) */
567
0
  Stream_Read_UINT32(s, pdu.DiscCode);      /* DiscCode (4 bytes) */
568
0
  const size_t end = Stream_GetPosition(s);
569
0
  const size_t body = beg + header->Length;
570
571
0
  if (body < end)
572
0
  {
573
0
    WLog_ERR(TAG, "Not enough data!");
574
0
    return ERROR_INVALID_DATA;
575
0
  }
576
577
0
  if (body > end)
578
0
  {
579
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
580
0
      return ERROR_INVALID_DATA;
581
582
0
    if (!Stream_SetPosition(s, body))
583
0
      return ERROR_INVALID_DATA;
584
0
  }
585
586
0
  IFCALLRET(context->ParticipantRemoved, error, context, &pdu);
587
588
0
  if (error)
589
0
    WLog_ERR(TAG, "context->ParticipantRemoved failed with error %" PRIu32 "", error);
590
591
0
  return error;
592
0
}
593
594
/**
595
 * Function description
596
 *
597
 * @return 0 on success, otherwise a Win32 error code
598
 */
599
static UINT encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp, wStream* s,
600
                                                              const ENCOMSP_ORDER_HEADER* header)
601
0
{
602
0
  ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu = WINPR_C_ARRAY_INIT;
603
0
  UINT error = CHANNEL_RC_OK;
604
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
605
606
0
  if (!context)
607
0
    return ERROR_INVALID_HANDLE;
608
609
0
  const size_t pos = Stream_GetPosition(s);
610
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
611
0
    return ERROR_INVALID_DATA;
612
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
613
614
0
  WINPR_ASSERT(header);
615
0
  pdu.Length = header->Length;
616
0
  pdu.Type = header->Type;
617
618
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
619
0
    return ERROR_INVALID_DATA;
620
621
0
  Stream_Read_UINT16(s, pdu.Flags);         /* Flags (2 bytes) */
622
0
  Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */
623
0
  const size_t end = Stream_GetPosition(s);
624
0
  const size_t body = beg + header->Length;
625
626
0
  if (body < end)
627
0
  {
628
0
    WLog_ERR(TAG, "Not enough data!");
629
0
    return ERROR_INVALID_DATA;
630
0
  }
631
632
0
  if (body > end)
633
0
  {
634
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
635
0
      return ERROR_INVALID_DATA;
636
637
0
    if (!Stream_SetPosition(s, body))
638
0
      return ERROR_INVALID_DATA;
639
0
  }
640
641
0
  IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu);
642
643
0
  if (error)
644
0
    WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %" PRIu32 "",
645
0
             error);
646
647
0
  return error;
648
0
}
649
650
/**
651
 * Function description
652
 *
653
 * @return 0 on success, otherwise a Win32 error code
654
 */
655
static UINT encomsp_send_change_participant_control_level_pdu(
656
    EncomspClientContext* context, const ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu)
657
0
{
658
0
  ENCOMSP_ORDER_HEADER header = WINPR_C_ARRAY_INIT;
659
660
0
  WINPR_ASSERT(context);
661
0
  encomspPlugin* encomsp = (encomspPlugin*)context->handle;
662
663
0
  header.Type = ODTYPE_PARTICIPANT_CTRL_CHANGED;
664
0
  header.Length = ENCOMSP_ORDER_HEADER_SIZE + 6;
665
666
0
  wStream* s = Stream_New(nullptr, header.Length);
667
668
0
  if (!s)
669
0
  {
670
0
    WLog_ERR(TAG, "Stream_New failed!");
671
0
    return CHANNEL_RC_NO_MEMORY;
672
0
  }
673
674
0
  const UINT error = encomsp_write_header(s, &header);
675
0
  if (error != CHANNEL_RC_OK)
676
0
  {
677
0
    WLog_ERR(TAG, "encomsp_write_header failed with error %" PRIu32 "!", error);
678
0
    return error;
679
0
  }
680
681
0
  Stream_Write_UINT16(s, pdu->Flags);         /* Flags (2 bytes) */
682
0
  Stream_Write_UINT32(s, pdu->ParticipantId); /* ParticipantId (4 bytes) */
683
0
  Stream_SealLength(s);
684
0
  return encomsp_virtual_channel_write(encomsp, s);
685
0
}
686
687
/**
688
 * Function description
689
 *
690
 * @return 0 on success, otherwise a Win32 error code
691
 */
692
static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStream* s,
693
                                                    const ENCOMSP_ORDER_HEADER* header)
694
0
{
695
0
  ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU pdu = WINPR_C_ARRAY_INIT;
696
0
  UINT error = CHANNEL_RC_OK;
697
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
698
699
0
  if (!context)
700
0
    return ERROR_INVALID_HANDLE;
701
702
0
  const size_t pos = Stream_GetPosition(s);
703
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
704
0
    return ERROR_INVALID_DATA;
705
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
706
707
0
  WINPR_ASSERT(header);
708
0
  pdu.Length = header->Length;
709
0
  pdu.Type = header->Type;
710
711
0
  const size_t end = Stream_GetPosition(s);
712
0
  const size_t body = beg + header->Length;
713
714
0
  if (body < end)
715
0
  {
716
0
    WLog_ERR(TAG, "Not enough data!");
717
0
    return ERROR_INVALID_DATA;
718
0
  }
719
720
0
  if (body > end)
721
0
  {
722
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
723
0
      return ERROR_INVALID_DATA;
724
725
0
    if (!Stream_SetPosition(s, body))
726
0
      return ERROR_INVALID_DATA;
727
0
  }
728
729
0
  IFCALLRET(context->GraphicsStreamPaused, error, context, &pdu);
730
731
0
  if (error)
732
0
    WLog_ERR(TAG, "context->GraphicsStreamPaused failed with error %" PRIu32 "", error);
733
734
0
  return error;
735
0
}
736
737
/**
738
 * Function description
739
 *
740
 * @return 0 on success, otherwise a Win32 error code
741
 */
742
static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, wStream* s,
743
                                                     const ENCOMSP_ORDER_HEADER* header)
744
0
{
745
0
  ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU pdu = WINPR_C_ARRAY_INIT;
746
0
  UINT error = CHANNEL_RC_OK;
747
0
  EncomspClientContext* context = encomsp_get_client_interface(encomsp);
748
749
0
  if (!context)
750
0
    return ERROR_INVALID_HANDLE;
751
752
0
  const size_t pos = Stream_GetPosition(s);
753
0
  if (pos < ENCOMSP_ORDER_HEADER_SIZE)
754
0
    return ERROR_INVALID_DATA;
755
0
  const size_t beg = pos - ENCOMSP_ORDER_HEADER_SIZE;
756
757
0
  WINPR_ASSERT(header);
758
0
  pdu.Length = header->Length;
759
0
  pdu.Type = header->Type;
760
761
0
  const size_t end = Stream_GetPosition(s);
762
0
  const size_t body = beg + header->Length;
763
764
0
  if (body < end)
765
0
  {
766
0
    WLog_ERR(TAG, "Not enough data!");
767
0
    return ERROR_INVALID_DATA;
768
0
  }
769
770
0
  if (body > end)
771
0
  {
772
0
    if (!Stream_CheckAndLogRequiredLength(TAG, s, (size_t)(body - end)))
773
0
      return ERROR_INVALID_DATA;
774
775
0
    if (!Stream_SetPosition(s, body))
776
0
      return ERROR_INVALID_DATA;
777
0
  }
778
779
0
  IFCALLRET(context->GraphicsStreamResumed, error, context, &pdu);
780
781
0
  if (error)
782
0
    WLog_ERR(TAG, "context->GraphicsStreamResumed failed with error %" PRIu32 "", error);
783
784
0
  return error;
785
0
}
786
787
/**
788
 * Function description
789
 *
790
 * @return 0 on success, otherwise a Win32 error code
791
 */
792
static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s)
793
0
{
794
0
  UINT error = CHANNEL_RC_OK;
795
0
  ENCOMSP_ORDER_HEADER header = WINPR_C_ARRAY_INIT;
796
797
0
  WINPR_ASSERT(encomsp);
798
0
  while (Stream_GetRemainingLength(s) > 0)
799
0
  {
800
0
    if ((error = encomsp_read_header(s, &header)))
801
0
    {
802
0
      WLog_ERR(TAG, "encomsp_read_header failed with error %" PRIu32 "!", error);
803
0
      return error;
804
0
    }
805
806
    // WLog_DBG(TAG, "EncomspReceive: Type: %"PRIu16" Length: %"PRIu16"", header.Type,
807
    // header.Length);
808
809
0
    switch (header.Type)
810
0
    {
811
0
      case ODTYPE_FILTER_STATE_UPDATED:
812
0
        if ((error = encomsp_recv_filter_updated_pdu(encomsp, s, &header)))
813
0
        {
814
0
          WLog_ERR(TAG, "encomsp_recv_filter_updated_pdu failed with error %" PRIu32 "!",
815
0
                   error);
816
0
          return error;
817
0
        }
818
819
0
        break;
820
821
0
      case ODTYPE_APP_REMOVED:
822
0
        if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header)))
823
0
        {
824
0
          WLog_ERR(TAG,
825
0
                   "encomsp_recv_application_removed_pdu failed with error %" PRIu32 "!",
826
0
                   error);
827
0
          return error;
828
0
        }
829
830
0
        break;
831
832
0
      case ODTYPE_APP_CREATED:
833
0
        if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header)))
834
0
        {
835
0
          WLog_ERR(TAG,
836
0
                   "encomsp_recv_application_removed_pdu failed with error %" PRIu32 "!",
837
0
                   error);
838
0
          return error;
839
0
        }
840
841
0
        break;
842
843
0
      case ODTYPE_WND_REMOVED:
844
0
        if ((error = encomsp_recv_window_removed_pdu(encomsp, s, &header)))
845
0
        {
846
0
          WLog_ERR(TAG, "encomsp_recv_window_removed_pdu failed with error %" PRIu32 "!",
847
0
                   error);
848
0
          return error;
849
0
        }
850
851
0
        break;
852
853
0
      case ODTYPE_WND_CREATED:
854
0
        if ((error = encomsp_recv_window_created_pdu(encomsp, s, &header)))
855
0
        {
856
0
          WLog_ERR(TAG, "encomsp_recv_window_created_pdu failed with error %" PRIu32 "!",
857
0
                   error);
858
0
          return error;
859
0
        }
860
861
0
        break;
862
863
0
      case ODTYPE_WND_SHOW:
864
0
        if ((error = encomsp_recv_show_window_pdu(encomsp, s, &header)))
865
0
        {
866
0
          WLog_ERR(TAG, "encomsp_recv_show_window_pdu failed with error %" PRIu32 "!",
867
0
                   error);
868
0
          return error;
869
0
        }
870
871
0
        break;
872
873
0
      case ODTYPE_PARTICIPANT_REMOVED:
874
0
        if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header)))
875
0
        {
876
0
          WLog_ERR(TAG,
877
0
                   "encomsp_recv_participant_removed_pdu failed with error %" PRIu32 "!",
878
0
                   error);
879
0
          return error;
880
0
        }
881
882
0
        break;
883
884
0
      case ODTYPE_PARTICIPANT_CREATED:
885
0
        if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header)))
886
0
        {
887
0
          WLog_ERR(TAG,
888
0
                   "encomsp_recv_participant_created_pdu failed with error %" PRIu32 "!",
889
0
                   error);
890
0
          return error;
891
0
        }
892
893
0
        break;
894
895
0
      case ODTYPE_PARTICIPANT_CTRL_CHANGED:
896
0
        if ((error =
897
0
                 encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header)))
898
0
        {
899
0
          WLog_ERR(TAG,
900
0
                   "encomsp_recv_change_participant_control_level_pdu failed with error "
901
0
                   "%" PRIu32 "!",
902
0
                   error);
903
0
          return error;
904
0
        }
905
906
0
        break;
907
908
0
      case ODTYPE_GRAPHICS_STREAM_PAUSED:
909
0
        if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header)))
910
0
        {
911
0
          WLog_ERR(TAG,
912
0
                   "encomsp_recv_graphics_stream_paused_pdu failed with error %" PRIu32
913
0
                   "!",
914
0
                   error);
915
0
          return error;
916
0
        }
917
918
0
        break;
919
920
0
      case ODTYPE_GRAPHICS_STREAM_RESUMED:
921
0
        if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header)))
922
0
        {
923
0
          WLog_ERR(TAG,
924
0
                   "encomsp_recv_graphics_stream_resumed_pdu failed with error %" PRIu32
925
0
                   "!",
926
0
                   error);
927
0
          return error;
928
0
        }
929
930
0
        break;
931
932
0
      default:
933
0
        WLog_ERR(TAG, "header.Type %" PRIu16 " not found", header.Type);
934
0
        return ERROR_INVALID_DATA;
935
0
    }
936
0
  }
937
938
0
  return error;
939
0
}
940
941
/**
942
 * Function description
943
 *
944
 * @return 0 on success, otherwise a Win32 error code
945
 */
946
static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, const void* pData,
947
                                                        UINT32 dataLength, UINT32 totalLength,
948
                                                        UINT32 dataFlags)
949
0
{
950
0
  WINPR_ASSERT(encomsp);
951
952
0
  if ((dataFlags & CHANNEL_FLAG_SUSPEND) || (dataFlags & CHANNEL_FLAG_RESUME))
953
0
    return CHANNEL_RC_OK;
954
955
0
  if (dataFlags & CHANNEL_FLAG_FIRST)
956
0
  {
957
0
    if (encomsp->data_in)
958
0
      Stream_Free(encomsp->data_in, TRUE);
959
960
0
    encomsp->data_in = Stream_New(nullptr, totalLength);
961
962
0
    if (!encomsp->data_in)
963
0
    {
964
0
      WLog_ERR(TAG, "Stream_New failed!");
965
0
      return CHANNEL_RC_NO_MEMORY;
966
0
    }
967
0
  }
968
969
0
  wStream* data_in = encomsp->data_in;
970
971
0
  if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
972
0
  {
973
0
    WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
974
0
    return ERROR_INTERNAL_ERROR;
975
0
  }
976
977
0
  Stream_Write(data_in, pData, dataLength);
978
979
0
  if (dataFlags & CHANNEL_FLAG_LAST)
980
0
  {
981
0
    if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
982
0
    {
983
0
      WLog_ERR(TAG, "encomsp_plugin_process_received: read error");
984
0
      return ERROR_INVALID_DATA;
985
0
    }
986
987
0
    encomsp->data_in = nullptr;
988
0
    Stream_SealLength(data_in);
989
0
    Stream_ResetPosition(data_in);
990
991
0
    if (!MessageQueue_Post(encomsp->queue, nullptr, 0, (void*)data_in, nullptr))
992
0
    {
993
0
      WLog_ERR(TAG, "MessageQueue_Post failed!");
994
0
      return ERROR_INTERNAL_ERROR;
995
0
    }
996
0
  }
997
998
0
  return CHANNEL_RC_OK;
999
0
}
1000
1001
static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
1002
                                                            UINT event, LPVOID pData,
1003
                                                            UINT32 dataLength, UINT32 totalLength,
1004
                                                            UINT32 dataFlags)
1005
0
{
1006
0
  UINT error = CHANNEL_RC_OK;
1007
0
  encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1008
1009
0
  switch (event)
1010
0
  {
1011
0
    case CHANNEL_EVENT_DATA_RECEIVED:
1012
0
      if (!encomsp || (encomsp->OpenHandle != openHandle))
1013
0
      {
1014
0
        WLog_ERR(TAG, "error no match");
1015
0
        return;
1016
0
      }
1017
0
      if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength,
1018
0
                                                               totalLength, dataFlags)))
1019
0
        WLog_ERR(TAG,
1020
0
                 "encomsp_virtual_channel_event_data_received failed with error %" PRIu32
1021
0
                 "",
1022
0
                 error);
1023
1024
0
      break;
1025
1026
0
    case CHANNEL_EVENT_WRITE_CANCELLED:
1027
0
    case CHANNEL_EVENT_WRITE_COMPLETE:
1028
0
    {
1029
0
      wStream* s = (wStream*)pData;
1030
0
      Stream_Free(s, TRUE);
1031
0
    }
1032
0
    break;
1033
1034
0
    case CHANNEL_EVENT_USER:
1035
0
      break;
1036
0
    default:
1037
0
      break;
1038
0
  }
1039
1040
0
  if (error && encomsp && encomsp->rdpcontext)
1041
0
    setChannelError(encomsp->rdpcontext, error,
1042
0
                    "encomsp_virtual_channel_open_event reported an error");
1043
0
}
1044
1045
static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg)
1046
0
{
1047
0
  wStream* data = nullptr;
1048
0
  wMessage message = WINPR_C_ARRAY_INIT;
1049
0
  encomspPlugin* encomsp = (encomspPlugin*)arg;
1050
0
  UINT error = CHANNEL_RC_OK;
1051
1052
0
  WINPR_ASSERT(encomsp);
1053
0
  while (1)
1054
0
  {
1055
0
    if (!MessageQueue_Wait(encomsp->queue))
1056
0
    {
1057
0
      WLog_ERR(TAG, "MessageQueue_Wait failed!");
1058
0
      error = ERROR_INTERNAL_ERROR;
1059
0
      break;
1060
0
    }
1061
1062
0
    if (!MessageQueue_Peek(encomsp->queue, &message, TRUE))
1063
0
    {
1064
0
      WLog_ERR(TAG, "MessageQueue_Peek failed!");
1065
0
      error = ERROR_INTERNAL_ERROR;
1066
0
      break;
1067
0
    }
1068
1069
0
    if (message.id == WMQ_QUIT)
1070
0
      break;
1071
1072
0
    if (message.id == 0)
1073
0
    {
1074
0
      data = (wStream*)message.wParam;
1075
1076
0
      if ((error = encomsp_process_receive(encomsp, data)))
1077
0
      {
1078
0
        WLog_ERR(TAG, "encomsp_process_receive failed with error %" PRIu32 "!", error);
1079
0
        Stream_Free(data, TRUE);
1080
0
        break;
1081
0
      }
1082
1083
0
      Stream_Free(data, TRUE);
1084
0
    }
1085
0
  }
1086
1087
0
  if (error && encomsp->rdpcontext)
1088
0
    setChannelError(encomsp->rdpcontext, error,
1089
0
                    "encomsp_virtual_channel_client_thread reported an error");
1090
1091
0
  ExitThread(error);
1092
0
  return error;
1093
0
}
1094
1095
/**
1096
 * Function description
1097
 *
1098
 * @return 0 on success, otherwise a Win32 error code
1099
 */
1100
static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp,
1101
                                                    WINPR_ATTR_UNUSED LPVOID pData,
1102
                                                    WINPR_ATTR_UNUSED UINT32 dataLength)
1103
0
{
1104
0
  WINPR_ASSERT(encomsp);
1105
1106
0
  encomsp->queue = MessageQueue_New(nullptr);
1107
1108
0
  if (!encomsp->queue)
1109
0
  {
1110
0
    WLog_ERR(TAG, "MessageQueue_New failed!");
1111
0
    return CHANNEL_RC_NO_MEMORY;
1112
0
  }
1113
1114
0
  if (!(encomsp->thread = CreateThread(nullptr, 0, encomsp_virtual_channel_client_thread,
1115
0
                                       (void*)encomsp, 0, nullptr)))
1116
0
  {
1117
0
    WLog_ERR(TAG, "CreateThread failed!");
1118
0
    MessageQueue_Free(encomsp->queue);
1119
0
    return ERROR_INTERNAL_ERROR;
1120
0
  }
1121
1122
0
  return encomsp->channelEntryPoints.pVirtualChannelOpenEx(
1123
0
      encomsp->InitHandle, &encomsp->OpenHandle, encomsp->channelDef.name,
1124
0
      encomsp_virtual_channel_open_event_ex);
1125
0
}
1126
1127
/**
1128
 * Function description
1129
 *
1130
 * @return 0 on success, otherwise a Win32 error code
1131
 */
1132
static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
1133
0
{
1134
0
  WINPR_ASSERT(encomsp);
1135
0
  if (encomsp->OpenHandle == 0)
1136
0
    return CHANNEL_RC_OK;
1137
1138
0
  if (encomsp->queue && encomsp->thread)
1139
0
  {
1140
0
    if (MessageQueue_PostQuit(encomsp->queue, 0) &&
1141
0
        (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED))
1142
0
    {
1143
0
      const UINT rc = GetLastError();
1144
0
      WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc);
1145
0
      return rc;
1146
0
    }
1147
0
  }
1148
1149
0
  MessageQueue_Free(encomsp->queue);
1150
0
  (void)CloseHandle(encomsp->thread);
1151
0
  encomsp->queue = nullptr;
1152
0
  encomsp->thread = nullptr;
1153
1154
0
  WINPR_ASSERT(encomsp->channelEntryPoints.pVirtualChannelCloseEx);
1155
0
  const UINT rc = encomsp->channelEntryPoints.pVirtualChannelCloseEx(encomsp->InitHandle,
1156
0
                                                                     encomsp->OpenHandle);
1157
1158
0
  if (CHANNEL_RC_OK != rc)
1159
0
  {
1160
0
    WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08" PRIX32 "]", WTSErrorToString(rc),
1161
0
             rc);
1162
0
    return rc;
1163
0
  }
1164
1165
0
  encomsp->OpenHandle = 0;
1166
1167
0
  if (encomsp->data_in)
1168
0
  {
1169
0
    Stream_Free(encomsp->data_in, TRUE);
1170
0
    encomsp->data_in = nullptr;
1171
0
  }
1172
1173
0
  return CHANNEL_RC_OK;
1174
0
}
1175
1176
/**
1177
 * Function description
1178
 *
1179
 * @return 0 on success, otherwise a Win32 error code
1180
 */
1181
static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
1182
0
{
1183
0
  WINPR_ASSERT(encomsp);
1184
1185
0
  encomsp->InitHandle = nullptr;
1186
0
  free(encomsp->context);
1187
0
  free(encomsp);
1188
0
  return CHANNEL_RC_OK;
1189
0
}
1190
1191
static VOID VCAPITYPE encomsp_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle,
1192
                                                            UINT event, LPVOID pData,
1193
                                                            UINT dataLength)
1194
0
{
1195
0
  UINT error = CHANNEL_RC_OK;
1196
0
  encomspPlugin* encomsp = (encomspPlugin*)lpUserParam;
1197
1198
0
  if (!encomsp || (encomsp->InitHandle != pInitHandle))
1199
0
  {
1200
0
    WLog_ERR(TAG, "error no match");
1201
0
    return;
1202
0
  }
1203
1204
0
  switch (event)
1205
0
  {
1206
0
    case CHANNEL_EVENT_INITIALIZED:
1207
0
      break;
1208
1209
0
    case CHANNEL_EVENT_CONNECTED:
1210
0
      if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength)))
1211
0
        WLog_ERR(TAG,
1212
0
                 "encomsp_virtual_channel_event_connected failed with error %" PRIu32 "",
1213
0
                 error);
1214
1215
0
      break;
1216
1217
0
    case CHANNEL_EVENT_DISCONNECTED:
1218
0
      if ((error = encomsp_virtual_channel_event_disconnected(encomsp)))
1219
0
        WLog_ERR(TAG,
1220
0
                 "encomsp_virtual_channel_event_disconnected failed with error %" PRIu32 "",
1221
0
                 error);
1222
1223
0
      break;
1224
1225
0
    case CHANNEL_EVENT_TERMINATED:
1226
0
      encomsp_virtual_channel_event_terminated(encomsp);
1227
0
      break;
1228
1229
0
    default:
1230
0
      break;
1231
0
  }
1232
1233
0
  if (error && encomsp->rdpcontext)
1234
0
    setChannelError(encomsp->rdpcontext, error,
1235
0
                    "encomsp_virtual_channel_init_event reported an error");
1236
0
}
1237
1238
/* encomsp is always built-in */
1239
#define VirtualChannelEntryEx encomsp_VirtualChannelEntryEx
1240
1241
FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints,
1242
                                                         PVOID pInitHandle))
1243
0
{
1244
0
  BOOL isFreerdp = FALSE;
1245
0
  encomspPlugin* encomsp = (encomspPlugin*)calloc(1, sizeof(encomspPlugin));
1246
1247
0
  if (!encomsp)
1248
0
  {
1249
0
    WLog_ERR(TAG, "calloc failed!");
1250
0
    return FALSE;
1251
0
  }
1252
1253
0
  encomsp->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
1254
0
                                CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
1255
0
  (void)sprintf_s(encomsp->channelDef.name, ARRAYSIZE(encomsp->channelDef.name),
1256
0
                  ENCOMSP_SVC_CHANNEL_NAME);
1257
0
  CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx =
1258
0
      (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints;
1259
0
  WINPR_ASSERT(pEntryPointsEx);
1260
1261
0
  EncomspClientContext* context = nullptr;
1262
0
  if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) &&
1263
0
      (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER))
1264
0
  {
1265
0
    context = (EncomspClientContext*)calloc(1, sizeof(EncomspClientContext));
1266
1267
0
    if (!context)
1268
0
    {
1269
0
      WLog_ERR(TAG, "calloc failed!");
1270
0
      goto error_out;
1271
0
    }
1272
1273
0
    context->handle = (void*)encomsp;
1274
0
    context->FilterUpdated = nullptr;
1275
0
    context->ApplicationCreated = nullptr;
1276
0
    context->ApplicationRemoved = nullptr;
1277
0
    context->WindowCreated = nullptr;
1278
0
    context->WindowRemoved = nullptr;
1279
0
    context->ShowWindow = nullptr;
1280
0
    context->ParticipantCreated = nullptr;
1281
0
    context->ParticipantRemoved = nullptr;
1282
0
    context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu;
1283
0
    context->GraphicsStreamPaused = nullptr;
1284
0
    context->GraphicsStreamResumed = nullptr;
1285
0
    encomsp->context = context;
1286
0
    encomsp->rdpcontext = pEntryPointsEx->context;
1287
0
    isFreerdp = TRUE;
1288
0
  }
1289
1290
0
  CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints,
1291
0
             sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX));
1292
0
  encomsp->InitHandle = pInitHandle;
1293
1294
0
  {
1295
0
    const UINT rc = encomsp->channelEntryPoints.pVirtualChannelInitEx(
1296
0
        encomsp, context, pInitHandle, &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000,
1297
0
        encomsp_virtual_channel_init_event_ex);
1298
1299
0
    if (CHANNEL_RC_OK != rc)
1300
0
    {
1301
0
      WLog_ERR(TAG, "failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), rc);
1302
0
      goto error_out;
1303
0
    }
1304
0
  }
1305
1306
0
  encomsp->channelEntryPoints.pInterface = context;
1307
0
  return TRUE;
1308
0
error_out:
1309
1310
0
  if (isFreerdp)
1311
0
    free(encomsp->context);
1312
1313
0
  free(encomsp);
1314
0
  return FALSE;
1315
0
}