Coverage Report

Created: 2024-09-08 06:20

/src/FreeRDP/libfreerdp/core/freerdp.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * FreeRDP Core
4
 *
5
 * Copyright 2011 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 <string.h>
27
#include <stdarg.h>
28
#include <time.h>
29
30
#include "rdp.h"
31
#include "input.h"
32
#include "update.h"
33
#include "surface.h"
34
#include "transport.h"
35
#include "connection.h"
36
#include "message.h"
37
#include <freerdp/buildflags.h>
38
#include "gateway/rpc_fault.h"
39
40
#include <winpr/assert.h>
41
42
#include <winpr/crt.h>
43
#include <winpr/string.h>
44
#include <winpr/stream.h>
45
#include <winpr/wtsapi.h>
46
#include <winpr/ssl.h>
47
#include <winpr/debug.h>
48
49
#include <freerdp/freerdp.h>
50
#include <freerdp/streamdump.h>
51
#include <freerdp/error.h>
52
#include <freerdp/event.h>
53
#include <freerdp/locale/keyboard.h>
54
#include <freerdp/locale/locale.h>
55
#include <freerdp/channels/channels.h>
56
#include <freerdp/version.h>
57
#include <freerdp/log.h>
58
#include <freerdp/utils/signal.h>
59
60
#include "../cache/pointer.h"
61
#include "utils.h"
62
63
6.93k
#define TAG FREERDP_TAG("core")
64
65
static void sig_abort_connect(int signum, const char* signame, void* ctx)
66
0
{
67
0
  rdpContext* context = (rdpContext*)ctx;
68
69
0
  WLog_INFO(TAG, "Signal %s [%d], terminating session %p", signame, signum, context);
70
0
  if (context)
71
0
    freerdp_abort_connect_context(context);
72
0
}
73
74
/** Creates a new connection based on the settings found in the "instance" parameter
75
 *  It will use the callbacks registered on the structure to process the pre/post connect operations
76
 *  that the caller requires.
77
 *  @see struct rdp_freerdp in freerdp.h
78
 *
79
 *  @param instance - pointer to a rdp_freerdp structure that contains base information to establish
80
 * the connection. On return, this function will be initialized with the new connection's settings.
81
 *
82
 *  @return TRUE if successful. FALSE otherwise.
83
 *
84
 */
85
static int freerdp_connect_begin(freerdp* instance)
86
0
{
87
0
  BOOL rc = 0;
88
0
  rdpRdp* rdp = NULL;
89
0
  BOOL status = TRUE;
90
0
  rdpSettings* settings = NULL;
91
0
  UINT32 KeyboardLayout = 0;
92
93
0
  if (!instance)
94
0
    return -1;
95
96
0
  WINPR_ASSERT(instance->context);
97
98
  /* We always set the return code to 0 before we start the connect sequence*/
99
0
  instance->ConnectionCallbackState = CLIENT_STATE_INITIAL;
100
0
  freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS);
101
0
  clearChannelError(instance->context);
102
0
  if (!utils_reset_abort(instance->context->rdp))
103
0
    return -1;
104
105
0
  rdp = instance->context->rdp;
106
0
  WINPR_ASSERT(rdp);
107
108
0
  settings = instance->context->settings;
109
0
  WINPR_ASSERT(settings);
110
111
0
  freerdp_channels_register_instance(instance->context->channels, instance);
112
113
0
  if (!freerdp_settings_set_default_order_support(settings))
114
0
    return -1;
115
116
0
  freerdp_add_signal_cleanup_handler(instance->context, sig_abort_connect);
117
118
0
  IFCALLRET(instance->PreConnect, status, instance);
119
0
  instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED;
120
121
0
  freerdp_settings_print_warnings(settings);
122
123
0
  if (status)
124
0
    status = rdp_set_backup_settings(rdp);
125
0
  if (status)
126
0
    status = utils_reload_channels(instance->context);
127
128
0
  const UINT32 cp = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardCodePage);
129
0
  KeyboardLayout = freerdp_get_keyboard_default_layout_for_locale(cp);
130
0
  if (KeyboardLayout == 0)
131
0
    KeyboardLayout = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardLayout);
132
133
0
  switch (KeyboardLayout)
134
0
  {
135
0
    case KBD_JAPANESE:
136
0
    case KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002:
137
0
    {
138
0
      if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardType,
139
0
                                       WINPR_KBD_TYPE_JAPANESE))
140
0
        return -1;
141
0
      if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardSubType, 2))
142
0
        return -1;
143
0
      if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardFunctionKey, 12))
144
0
        return -1;
145
0
    }
146
0
    break;
147
0
    default:
148
0
      break;
149
0
  }
150
151
0
  if (!status)
152
0
  {
153
0
    rdpContext* context = instance->context;
154
0
    WINPR_ASSERT(context);
155
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_PRE_CONNECT_FAILED);
156
157
0
    WLog_Print(context->log, WLOG_ERROR, "freerdp_pre_connect failed");
158
0
    return 0;
159
0
  }
160
161
0
  rc = rdp_client_connect(rdp);
162
163
  /* --authonly tests the connection without a UI */
164
0
  if (freerdp_settings_get_bool(rdp->settings, FreeRDP_AuthenticationOnly))
165
0
  {
166
0
    rdpContext* context = rdp->context;
167
0
    WINPR_ASSERT(context);
168
0
    WLog_Print(context->log, WLOG_ERROR, "Authentication only, exit status %" PRId32 "", rc);
169
0
    return 0;
170
0
  }
171
172
0
  return rc ? 1 : 0;
173
0
}
174
175
BOOL freerdp_connect(freerdp* instance)
176
0
{
177
0
  BOOL status = FALSE;
178
0
  ConnectionResultEventArgs e = { 0 };
179
0
  const int rc = freerdp_connect_begin(instance);
180
0
  rdpRdp* rdp = NULL;
181
0
  UINT status2 = ERROR_INTERNAL_ERROR;
182
183
0
  WINPR_ASSERT(instance);
184
0
  WINPR_ASSERT(instance->context);
185
186
0
  rdp = instance->context->rdp;
187
0
  WINPR_ASSERT(rdp);
188
0
  WINPR_ASSERT(rdp->settings);
189
190
0
  if (rc < 0)
191
0
    return FALSE;
192
193
0
  if (rc == 0)
194
0
    goto freerdp_connect_finally;
195
196
  /* Pointers might have changed inbetween */
197
0
  {
198
0
    rdp_update_internal* up = update_cast(rdp->update);
199
200
0
    if (freerdp_settings_get_bool(rdp->settings, FreeRDP_DumpRemoteFx))
201
0
    {
202
0
      up->pcap_rfx = pcap_open(
203
0
          freerdp_settings_get_string(rdp->settings, FreeRDP_DumpRemoteFxFile), TRUE);
204
205
0
      if (up->pcap_rfx)
206
0
        up->dump_rfx = TRUE;
207
0
    }
208
0
  }
209
210
0
  if (rc > 0)
211
0
  {
212
0
    pointer_cache_register_callbacks(instance->context->update);
213
0
    status = IFCALLRESULT(TRUE, instance->PostConnect, instance);
214
0
    instance->ConnectionCallbackState = CLIENT_STATE_POSTCONNECT_PASSED;
215
216
0
    if (status)
217
0
      status2 = freerdp_channels_post_connect(instance->context->channels, instance);
218
0
  }
219
0
  else
220
0
  {
221
0
    status2 = CHANNEL_RC_OK;
222
0
    if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)
223
0
      status = freerdp_reconnect(instance);
224
0
    else
225
0
      goto freerdp_connect_finally;
226
0
  }
227
228
0
  if (!status || (status2 != CHANNEL_RC_OK) || !update_post_connect(instance->context->update))
229
0
  {
230
0
    rdpContext* context = instance->context;
231
0
    WINPR_ASSERT(context);
232
0
    WLog_Print(context->log, WLOG_ERROR, "freerdp_post_connect failed");
233
234
0
    freerdp_set_last_error_if_not(context, FREERDP_ERROR_POST_CONNECT_FAILED);
235
236
0
    status = FALSE;
237
0
    goto freerdp_connect_finally;
238
0
  }
239
240
0
  if (rdp->settings->PlayRemoteFx)
241
0
  {
242
0
    wStream* s = NULL;
243
0
    rdp_update_internal* update = update_cast(instance->context->update);
244
0
    pcap_record record = { 0 };
245
246
0
    WINPR_ASSERT(update);
247
0
    update->pcap_rfx = pcap_open(rdp->settings->PlayRemoteFxFile, FALSE);
248
0
    status = FALSE;
249
250
0
    if (!update->pcap_rfx)
251
0
      goto freerdp_connect_finally;
252
0
    else
253
0
      update->play_rfx = TRUE;
254
255
0
    status = TRUE;
256
257
0
    while (pcap_has_next_record(update->pcap_rfx) && status)
258
0
    {
259
0
      pcap_get_next_record_header(update->pcap_rfx, &record);
260
261
0
      s = transport_take_from_pool(rdp->transport, record.length);
262
0
      if (!s)
263
0
        break;
264
265
0
      record.data = Stream_Buffer(s);
266
0
      pcap_get_next_record_content(update->pcap_rfx, &record);
267
0
      Stream_SetLength(s, record.length);
268
0
      Stream_SetPosition(s, 0);
269
270
0
      if (!update_begin_paint(&update->common))
271
0
        status = FALSE;
272
0
      else
273
0
      {
274
0
        if (update_recv_surfcmds(&update->common, s) < 0)
275
0
          status = FALSE;
276
277
0
        if (!update_end_paint(&update->common))
278
0
          status = FALSE;
279
0
      }
280
281
0
      Stream_Release(s);
282
0
    }
283
284
0
    pcap_close(update->pcap_rfx);
285
0
    update->pcap_rfx = NULL;
286
0
    goto freerdp_connect_finally;
287
0
  }
288
289
0
  if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
290
0
    freerdp_set_last_error_log(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
291
292
0
  transport_set_connected_event(rdp->transport);
293
294
0
freerdp_connect_finally:
295
0
  EventArgsInit(&e, "freerdp");
296
0
  e.result = status ? 0 : -1;
297
0
  PubSub_OnConnectionResult(rdp->pubSub, instance->context, &e);
298
299
0
  if (!status)
300
0
    freerdp_disconnect(instance);
301
302
0
  return status;
303
0
}
304
305
BOOL freerdp_abort_connect(freerdp* instance)
306
0
{
307
0
  if (!instance)
308
0
    return FALSE;
309
310
0
  return freerdp_abort_connect_context(instance->context);
311
0
}
312
313
BOOL freerdp_abort_connect_context(rdpContext* context)
314
0
{
315
0
  if (!context)
316
0
    return FALSE;
317
318
0
  freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
319
320
0
  return utils_abort_connect(context->rdp);
321
0
}
322
323
#if defined(WITH_FREERDP_DEPRECATED)
324
BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
325
{
326
  rdpRdp* rdp = NULL;
327
328
  WINPR_ASSERT(instance);
329
  WINPR_ASSERT(instance->context);
330
331
  rdp = instance->context->rdp;
332
  WINPR_ASSERT(rdp);
333
334
  transport_get_fds(rdp->transport, rfds, rcount);
335
  return TRUE;
336
}
337
#endif
338
339
BOOL freerdp_check_fds(freerdp* instance)
340
0
{
341
0
  int status = 0;
342
0
  rdpRdp* rdp = NULL;
343
344
0
  if (!instance)
345
0
    return FALSE;
346
347
0
  if (!instance->context)
348
0
    return FALSE;
349
350
0
  if (!instance->context->rdp)
351
0
    return FALSE;
352
353
0
  rdp = instance->context->rdp;
354
0
  status = rdp_check_fds(rdp);
355
356
0
  if (status < 0)
357
0
  {
358
0
    TerminateEventArgs e;
359
0
    rdpContext* context = instance->context;
360
0
    WINPR_ASSERT(context);
361
362
0
    WLog_Print(context->log, WLOG_DEBUG, "rdp_check_fds() - %i", status);
363
0
    EventArgsInit(&e, "freerdp");
364
0
    e.code = 0;
365
0
    PubSub_OnTerminate(rdp->pubSub, context, &e);
366
0
    return FALSE;
367
0
  }
368
369
0
  return TRUE;
370
0
}
371
372
DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count)
373
0
{
374
0
  DWORD nCount = 0;
375
376
0
  WINPR_ASSERT(context);
377
0
  WINPR_ASSERT(context->rdp);
378
0
  WINPR_ASSERT(events || (count == 0));
379
380
0
  nCount += transport_get_event_handles(context->rdp->transport, events, count);
381
382
0
  if (nCount == 0)
383
0
    return 0;
384
385
0
  if (events && (nCount < count + 2))
386
0
  {
387
0
    events[nCount++] = freerdp_channels_get_event_handle(context->instance);
388
0
    events[nCount++] = getChannelErrorEventHandle(context);
389
0
    events[nCount++] = utils_get_abort_event(context->rdp);
390
0
  }
391
0
  else
392
0
    return 0;
393
394
0
  return nCount;
395
0
}
396
397
/* Resend mouse cursor position to prevent session lock in prevent-session-lock mode */
398
static BOOL freerdp_prevent_session_lock(rdpContext* context)
399
0
{
400
0
  WINPR_ASSERT(context);
401
0
  WINPR_ASSERT(context->input);
402
403
0
  rdp_input_internal* in = input_cast(context->input);
404
405
0
  UINT32 FakeMouseMotionInterval =
406
0
      freerdp_settings_get_uint32(context->settings, FreeRDP_FakeMouseMotionInterval);
407
0
  if (FakeMouseMotionInterval && in->lastInputTimestamp)
408
0
  {
409
0
    const time_t now = time(NULL);
410
0
    if (now - in->lastInputTimestamp > FakeMouseMotionInterval)
411
0
    {
412
0
      WLog_Print(context->log, WLOG_DEBUG,
413
0
                 "fake mouse move: x=%d y=%d lastInputTimestamp=%" PRIu64 " "
414
0
                 "FakeMouseMotionInterval=%" PRIu32,
415
0
                 in->lastX, in->lastY, in->lastInputTimestamp, FakeMouseMotionInterval);
416
417
0
      BOOL status = freerdp_input_send_mouse_event(context->input, PTR_FLAGS_MOVE, in->lastX,
418
0
                                                   in->lastY);
419
0
      if (!status)
420
0
      {
421
0
        if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
422
0
          WLog_Print(context->log, WLOG_ERROR,
423
0
                     "freerdp_prevent_session_lock() failed - %" PRIi32 "", status);
424
425
0
        return FALSE;
426
0
      }
427
428
0
      return status;
429
0
    }
430
0
  }
431
432
0
  return TRUE;
433
0
}
434
435
BOOL freerdp_check_event_handles(rdpContext* context)
436
0
{
437
0
  WINPR_ASSERT(context);
438
439
0
  BOOL status = freerdp_check_fds(context->instance);
440
441
0
  if (!status)
442
0
  {
443
0
    if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
444
0
      WLog_Print(context->log, WLOG_ERROR, "freerdp_check_fds() failed - %" PRIi32 "",
445
0
                 status);
446
447
0
    return FALSE;
448
0
  }
449
450
0
  status = freerdp_channels_check_fds(context->channels, context->instance);
451
452
0
  if (!status)
453
0
  {
454
0
    if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
455
0
      WLog_Print(context->log, WLOG_ERROR,
456
0
                 "freerdp_channels_check_fds() failed - %" PRIi32 "", status);
457
458
0
    return FALSE;
459
0
  }
460
461
0
  status = checkChannelErrorEvent(context);
462
463
0
  if (!status)
464
0
  {
465
0
    if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
466
0
      WLog_Print(context->log, WLOG_ERROR, "checkChannelErrorEvent() failed - %" PRIi32 "",
467
0
                 status);
468
469
0
    return FALSE;
470
0
  }
471
472
0
  status = freerdp_prevent_session_lock(context);
473
474
0
  return status;
475
0
}
476
477
wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD id)
478
0
{
479
0
  wMessageQueue* queue = NULL;
480
481
0
  WINPR_ASSERT(instance);
482
483
0
  rdpContext* context = instance->context;
484
0
  WINPR_ASSERT(context);
485
486
0
  switch (id)
487
0
  {
488
0
    case FREERDP_UPDATE_MESSAGE_QUEUE:
489
0
    {
490
0
      rdp_update_internal* update = update_cast(context->update);
491
0
      queue = update->queue;
492
0
    }
493
0
    break;
494
495
0
    case FREERDP_INPUT_MESSAGE_QUEUE:
496
0
    {
497
0
      rdp_input_internal* input = input_cast(context->input);
498
0
      queue = input->queue;
499
0
    }
500
0
    break;
501
0
  }
502
503
0
  return queue;
504
0
}
505
506
HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD id)
507
0
{
508
0
  HANDLE event = NULL;
509
0
  wMessageQueue* queue = freerdp_get_message_queue(instance, id);
510
511
0
  if (queue)
512
0
    event = MessageQueue_Event(queue);
513
514
0
  return event;
515
0
}
516
517
int freerdp_message_queue_process_message(freerdp* instance, DWORD id, wMessage* message)
518
0
{
519
0
  int status = -1;
520
0
  rdpContext* context = NULL;
521
522
0
  WINPR_ASSERT(instance);
523
524
0
  context = instance->context;
525
0
  WINPR_ASSERT(context);
526
527
0
  switch (id)
528
0
  {
529
0
    case FREERDP_UPDATE_MESSAGE_QUEUE:
530
0
      status = update_message_queue_process_message(context->update, message);
531
0
      break;
532
533
0
    case FREERDP_INPUT_MESSAGE_QUEUE:
534
0
      status = input_message_queue_process_message(context->input, message);
535
0
      break;
536
0
  }
537
538
0
  return status;
539
0
}
540
541
int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD id)
542
0
{
543
0
  int status = -1;
544
0
  rdpContext* context = NULL;
545
546
0
  WINPR_ASSERT(instance);
547
548
0
  context = instance->context;
549
0
  WINPR_ASSERT(context);
550
551
0
  switch (id)
552
0
  {
553
0
    case FREERDP_UPDATE_MESSAGE_QUEUE:
554
0
      status = update_message_queue_process_pending_messages(context->update);
555
0
      break;
556
557
0
    case FREERDP_INPUT_MESSAGE_QUEUE:
558
0
      status = input_message_queue_process_pending_messages(context->input);
559
0
      break;
560
0
  }
561
562
0
  return status;
563
0
}
564
565
static BOOL freerdp_send_channel_data(freerdp* instance, UINT16 channelId, const BYTE* data,
566
                                      size_t size)
567
0
{
568
0
  WINPR_ASSERT(instance);
569
0
  WINPR_ASSERT(instance->context);
570
0
  WINPR_ASSERT(instance->context->rdp);
571
0
  return rdp_send_channel_data(instance->context->rdp, channelId, data, size);
572
0
}
573
574
static BOOL freerdp_send_channel_packet(freerdp* instance, UINT16 channelId, size_t totalSize,
575
                                        UINT32 flags, const BYTE* data, size_t chunkSize)
576
0
{
577
0
  WINPR_ASSERT(instance);
578
0
  WINPR_ASSERT(instance->context);
579
0
  WINPR_ASSERT(instance->context->rdp);
580
0
  return rdp_channel_send_packet(instance->context->rdp, channelId, totalSize, flags, data,
581
0
                                 chunkSize);
582
0
}
583
584
BOOL freerdp_disconnect(freerdp* instance)
585
0
{
586
0
  BOOL rc = TRUE;
587
0
  rdpRdp* rdp = NULL;
588
0
  rdp_update_internal* up = NULL;
589
590
0
  if (!instance || !instance->context)
591
0
    return FALSE;
592
593
0
  rdp = instance->context->rdp;
594
0
  utils_abort_connect(rdp);
595
596
0
  if (!rdp_client_disconnect(rdp))
597
0
    rc = FALSE;
598
599
0
  up = update_cast(rdp->update);
600
601
0
  update_post_disconnect(rdp->update);
602
603
0
  IFCALL(instance->PostDisconnect, instance);
604
605
0
  if (up->pcap_rfx)
606
0
  {
607
0
    up->dump_rfx = FALSE;
608
0
    pcap_close(up->pcap_rfx);
609
0
    up->pcap_rfx = NULL;
610
0
  }
611
612
0
  freerdp_channels_close(instance->context->channels, instance);
613
614
0
  IFCALL(instance->PostFinalDisconnect, instance);
615
616
0
  freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
617
0
  return rc;
618
0
}
619
620
BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
621
0
{
622
0
  WINPR_ASSERT(instance);
623
0
  return freerdp_disconnect_before_reconnect_context(instance->context);
624
0
}
625
626
BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
627
0
{
628
0
  rdpRdp* rdp = NULL;
629
630
0
  WINPR_ASSERT(context);
631
632
0
  rdp = context->rdp;
633
0
  return rdp_client_disconnect_and_clear(rdp);
634
0
}
635
636
BOOL freerdp_reconnect(freerdp* instance)
637
0
{
638
0
  rdpRdp* rdp = NULL;
639
640
0
  WINPR_ASSERT(instance);
641
0
  WINPR_ASSERT(instance->context);
642
643
0
  if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
644
0
    return FALSE;
645
646
0
  rdp = instance->context->rdp;
647
648
0
  if (!utils_reset_abort(instance->context->rdp))
649
0
    return FALSE;
650
0
  return rdp_client_reconnect(rdp);
651
0
}
652
653
BOOL freerdp_shall_disconnect(freerdp* instance)
654
0
{
655
0
  if (!instance)
656
0
    return FALSE;
657
658
0
  return freerdp_shall_disconnect_context(instance->context);
659
0
}
660
661
BOOL freerdp_shall_disconnect_context(const rdpContext* context)
662
204
{
663
204
  if (!context)
664
0
    return FALSE;
665
666
204
  return utils_abort_event_is_set(context->rdp);
667
204
}
668
669
BOOL freerdp_focus_required(freerdp* instance)
670
0
{
671
0
  rdpRdp* rdp = NULL;
672
0
  BOOL bRetCode = FALSE;
673
674
0
  WINPR_ASSERT(instance);
675
0
  WINPR_ASSERT(instance->context);
676
677
0
  rdp = instance->context->rdp;
678
0
  WINPR_ASSERT(rdp);
679
680
0
  if (rdp->resendFocus)
681
0
  {
682
0
    bRetCode = TRUE;
683
0
    rdp->resendFocus = FALSE;
684
0
  }
685
686
0
  return bRetCode;
687
0
}
688
689
void freerdp_set_focus(freerdp* instance)
690
0
{
691
0
  rdpRdp* rdp = NULL;
692
693
0
  WINPR_ASSERT(instance);
694
0
  WINPR_ASSERT(instance->context);
695
696
0
  rdp = instance->context->rdp;
697
0
  WINPR_ASSERT(rdp);
698
699
0
  rdp->resendFocus = TRUE;
700
0
}
701
702
void freerdp_get_version(int* major, int* minor, int* revision)
703
0
{
704
0
  if (major != NULL)
705
0
    *major = FREERDP_VERSION_MAJOR;
706
707
0
  if (minor != NULL)
708
0
    *minor = FREERDP_VERSION_MINOR;
709
710
0
  if (revision != NULL)
711
0
    *revision = FREERDP_VERSION_REVISION;
712
0
}
713
714
const char* freerdp_get_version_string(void)
715
0
{
716
0
  return FREERDP_VERSION_FULL;
717
0
}
718
719
const char* freerdp_get_build_config(void)
720
0
{
721
0
  WINPR_PRAGMA_DIAG_PUSH
722
0
  WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
723
0
  static const char build_config[] =
724
0
      "Build configuration: " FREERDP_BUILD_CONFIG "\n"
725
0
      "Build type:          " FREERDP_BUILD_TYPE "\n"
726
0
      "CFLAGS:              " FREERDP_CFLAGS "\n"
727
0
      "Compiler:            " FREERDP_COMPILER_ID ", " FREERDP_COMPILER_VERSION "\n"
728
0
      "Target architecture: " FREERDP_TARGET_ARCH "\n";
729
0
  WINPR_PRAGMA_DIAG_POP
730
0
  return build_config;
731
0
}
732
733
const char* freerdp_get_build_revision(void)
734
0
{
735
0
  return FREERDP_GIT_REVISION;
736
0
}
737
738
static wEventType FreeRDP_Events[] = {
739
  DEFINE_EVENT_ENTRY(WindowStateChange),   DEFINE_EVENT_ENTRY(ResizeWindow),
740
  DEFINE_EVENT_ENTRY(LocalResizeWindow),   DEFINE_EVENT_ENTRY(EmbedWindow),
741
  DEFINE_EVENT_ENTRY(PanningChange),       DEFINE_EVENT_ENTRY(ZoomingChange),
742
  DEFINE_EVENT_ENTRY(ErrorInfo),           DEFINE_EVENT_ENTRY(Terminate),
743
  DEFINE_EVENT_ENTRY(ConnectionResult),    DEFINE_EVENT_ENTRY(ChannelConnected),
744
  DEFINE_EVENT_ENTRY(ChannelDisconnected), DEFINE_EVENT_ENTRY(MouseEvent),
745
  DEFINE_EVENT_ENTRY(Activated),           DEFINE_EVENT_ENTRY(Timer),
746
  DEFINE_EVENT_ENTRY(GraphicsReset)
747
};
748
749
/** Allocator function for a rdp context.
750
 *  The function will allocate a rdpRdp structure using rdp_new(), then copy
751
 *  its contents to the appropriate fields in the rdp_freerdp structure given in parameters.
752
 *  It will also initialize the 'context' field in the rdp_freerdp structure as needed.
753
 *  If the caller has set the ContextNew callback in the 'instance' parameter, it will be called at
754
 * the end of the function.
755
 *
756
 *  @param instance - Pointer to the rdp_freerdp structure that will be initialized with the new
757
 * context.
758
 */
759
BOOL freerdp_context_new(freerdp* instance)
760
0
{
761
0
  return freerdp_context_new_ex(instance, NULL);
762
0
}
763
764
BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
765
6.93k
{
766
6.93k
  rdpRdp* rdp = NULL;
767
6.93k
  rdpContext* context = NULL;
768
6.93k
  BOOL ret = TRUE;
769
770
6.93k
  WINPR_ASSERT(instance);
771
772
6.93k
  instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
773
774
6.93k
  if (!context)
775
0
    return FALSE;
776
777
6.93k
  context->log = WLog_Get(TAG);
778
6.93k
  if (!context->log)
779
0
    goto fail;
780
781
  /* Set to external settings, prevents rdp_new from creating its own instance */
782
6.93k
  context->settings = settings;
783
6.93k
  context->instance = instance;
784
6.93k
  context->ServerMode = FALSE;
785
6.93k
  context->disconnectUltimatum = 0;
786
787
6.93k
  context->metrics = metrics_new(context);
788
789
6.93k
  if (!context->metrics)
790
0
    goto fail;
791
792
6.93k
  rdp = rdp_new(context);
793
794
6.93k
  if (!rdp)
795
0
    goto fail;
796
797
6.93k
  rdp_log_build_warnings(rdp);
798
6.93k
  context->rdp = rdp;
799
6.93k
  context->pubSub = rdp->pubSub;
800
801
6.93k
  if (!context->pubSub)
802
0
    goto fail;
803
804
6.93k
  PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
805
806
#if defined(WITH_FREERDP_DEPRECATED)
807
  instance->input = rdp->input;
808
  instance->update = rdp->update;
809
  instance->settings = rdp->settings;
810
  instance->autodetect = rdp->autodetect;
811
#endif
812
813
6.93k
  instance->heartbeat = rdp->heartbeat;
814
6.93k
  context->graphics = graphics_new(context);
815
816
6.93k
  if (!context->graphics)
817
0
    goto fail;
818
819
6.93k
  context->input = rdp->input;
820
6.93k
  context->update = rdp->update;
821
6.93k
  context->settings = rdp->settings;
822
6.93k
  context->autodetect = rdp->autodetect;
823
824
6.93k
  if (!(context->errorDescription = calloc(1, 500)))
825
0
  {
826
0
    WLog_Print(context->log, WLOG_ERROR, "calloc failed!");
827
0
    goto fail;
828
0
  }
829
830
6.93k
  if (!(context->channelErrorEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
831
0
  {
832
0
    WLog_Print(context->log, WLOG_ERROR, "CreateEvent failed!");
833
0
    goto fail;
834
0
  }
835
836
6.93k
  update_register_client_callbacks(rdp->update);
837
838
6.93k
  if (!(context->channels = freerdp_channels_new(instance)))
839
0
    goto fail;
840
841
6.93k
  context->dump = stream_dump_new();
842
6.93k
  if (!context->dump)
843
0
    goto fail;
844
845
6.93k
  IFCALLRET(instance->ContextNew, ret, instance, context);
846
847
6.93k
  if (ret)
848
6.93k
    return TRUE;
849
850
0
fail:
851
0
  freerdp_context_free(instance);
852
0
  return FALSE;
853
6.93k
}
854
855
BOOL freerdp_context_reset(freerdp* instance)
856
0
{
857
0
  if (!instance)
858
0
    return FALSE;
859
860
0
  WINPR_ASSERT(instance->context);
861
0
  rdpRdp* rdp = instance->context->rdp;
862
863
0
  return rdp_reset_runtime_settings(rdp);
864
0
}
865
866
/** Deallocator function for a rdp context.
867
 *  The function will deallocate the resources from the 'instance' parameter that were allocated
868
 * from a call to freerdp_context_new(). If the ContextFree callback is set in the 'instance'
869
 * parameter, it will be called before deallocation occurs.
870
 *
871
 *  @param instance - Pointer to the rdp_freerdp structure that was initialized by a call to
872
 * freerdp_context_new(). On return, the fields associated to the context are invalid.
873
 */
874
void freerdp_context_free(freerdp* instance)
875
6.93k
{
876
6.93k
  rdpContext* ctx = NULL;
877
878
6.93k
  if (!instance)
879
0
    return;
880
881
6.93k
  if (!instance->context)
882
0
    return;
883
884
6.93k
  ctx = instance->context;
885
886
6.93k
  IFCALL(instance->ContextFree, instance, ctx);
887
6.93k
  rdp_free(ctx->rdp);
888
6.93k
  ctx->rdp = NULL;
889
6.93k
  ctx->settings = NULL; /* owned by rdpRdp */
890
891
6.93k
  graphics_free(ctx->graphics);
892
6.93k
  ctx->graphics = NULL;
893
894
6.93k
  metrics_free(ctx->metrics);
895
6.93k
  ctx->metrics = NULL;
896
897
6.93k
  if (ctx->channelErrorEvent)
898
6.93k
    CloseHandle(ctx->channelErrorEvent);
899
6.93k
  ctx->channelErrorEvent = NULL;
900
901
6.93k
  free(ctx->errorDescription);
902
6.93k
  ctx->errorDescription = NULL;
903
904
6.93k
  freerdp_channels_free(ctx->channels);
905
6.93k
  ctx->channels = NULL;
906
907
6.93k
  freerdp_client_codecs_free(ctx->codecs);
908
6.93k
  ctx->codecs = NULL;
909
910
6.93k
  stream_dump_free(ctx->dump);
911
6.93k
  ctx->dump = NULL;
912
913
6.93k
  ctx->input = NULL;      /* owned by rdpRdp */
914
6.93k
  ctx->update = NULL;     /* owned by rdpRdp */
915
6.93k
  ctx->settings = NULL;   /* owned by rdpRdp */
916
6.93k
  ctx->autodetect = NULL; /* owned by rdpRdp */
917
918
6.93k
  free(ctx);
919
6.93k
  instance->context = NULL;
920
#if defined(WITH_FREERDP_DEPRECATED)
921
  instance->input = NULL;      /* owned by rdpRdp */
922
  instance->update = NULL;     /* owned by rdpRdp */
923
  instance->settings = NULL;   /* owned by rdpRdp */
924
  instance->autodetect = NULL; /* owned by rdpRdp */
925
#endif
926
6.93k
  instance->heartbeat = NULL; /* owned by rdpRdp */
927
6.93k
}
928
929
int freerdp_get_disconnect_ultimatum(rdpContext* context)
930
0
{
931
0
  WINPR_ASSERT(context);
932
0
  return context->disconnectUltimatum;
933
0
}
934
935
UINT32 freerdp_error_info(freerdp* instance)
936
0
{
937
0
  WINPR_ASSERT(instance);
938
0
  WINPR_ASSERT(instance->context);
939
0
  WINPR_ASSERT(instance->context->rdp);
940
0
  return instance->context->rdp->errorInfo;
941
0
}
942
943
void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
944
0
{
945
0
  if (!rdp)
946
0
    return;
947
948
0
  rdp_set_error_info(rdp, error);
949
0
}
950
951
BOOL freerdp_send_error_info(rdpRdp* rdp)
952
0
{
953
0
  if (!rdp)
954
0
    return FALSE;
955
956
0
  return rdp_send_error_info(rdp);
957
0
}
958
959
UINT32 freerdp_get_last_error(rdpContext* context)
960
2.64k
{
961
2.64k
  WINPR_ASSERT(context);
962
2.64k
  return context->LastError;
963
2.64k
}
964
965
const char* freerdp_get_last_error_name(UINT32 code)
966
3.30k
{
967
3.30k
  const char* name = NULL;
968
3.30k
  const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
969
3.30k
  const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
970
971
3.30k
  switch (cls)
972
3.30k
  {
973
0
    case FREERDP_ERROR_ERRBASE_CLASS:
974
0
      name = freerdp_get_error_base_name(type);
975
0
      break;
976
977
574
    case FREERDP_ERROR_ERRINFO_CLASS:
978
574
      name = freerdp_get_error_info_name(type);
979
574
      break;
980
981
2.50k
    case FREERDP_ERROR_CONNECT_CLASS:
982
2.50k
      name = freerdp_get_error_connect_name(type);
983
2.50k
      break;
984
985
229
    default:
986
229
      name = rpc_error_to_string(code);
987
229
      break;
988
3.30k
  }
989
990
3.30k
  return name;
991
3.30k
}
992
993
const char* freerdp_get_last_error_string(UINT32 code)
994
0
{
995
0
  const char* string = NULL;
996
0
  const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
997
0
  const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
998
999
0
  switch (cls)
1000
0
  {
1001
0
    case FREERDP_ERROR_ERRBASE_CLASS:
1002
0
      string = freerdp_get_error_base_string(type);
1003
0
      break;
1004
1005
0
    case FREERDP_ERROR_ERRINFO_CLASS:
1006
0
      string = freerdp_get_error_info_string(type);
1007
0
      break;
1008
1009
0
    case FREERDP_ERROR_CONNECT_CLASS:
1010
0
      string = freerdp_get_error_connect_string(type);
1011
0
      break;
1012
1013
0
    default:
1014
0
      string = rpc_error_to_string(code);
1015
0
      break;
1016
0
  }
1017
1018
0
  return string;
1019
0
}
1020
1021
const char* freerdp_get_last_error_category(UINT32 code)
1022
0
{
1023
0
  const char* string = NULL;
1024
0
  const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1025
0
  const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1026
1027
0
  switch (cls)
1028
0
  {
1029
0
    case FREERDP_ERROR_ERRBASE_CLASS:
1030
0
      string = freerdp_get_error_base_category(type);
1031
0
      break;
1032
1033
0
    case FREERDP_ERROR_ERRINFO_CLASS:
1034
0
      string = freerdp_get_error_info_category(type);
1035
0
      break;
1036
1037
0
    case FREERDP_ERROR_CONNECT_CLASS:
1038
0
      string = freerdp_get_error_connect_category(type);
1039
0
      break;
1040
1041
0
    default:
1042
0
      string = rpc_error_to_category(code);
1043
0
      break;
1044
0
  }
1045
1046
0
  return string;
1047
0
}
1048
1049
void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError, const char* fkt,
1050
                               const char* file, int line)
1051
3.20k
{
1052
3.20k
  WINPR_ASSERT(context);
1053
3.20k
  WINPR_ASSERT(line >= 0);
1054
1055
3.20k
  if (lastError)
1056
3.19k
  {
1057
3.19k
    if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1058
3.19k
    {
1059
3.19k
      WLog_PrintMessage(context->log, WLOG_MESSAGE_TEXT, WLOG_ERROR, (size_t)line, file, fkt,
1060
3.19k
                        "%s [0x%08" PRIX32 "]", freerdp_get_last_error_name(lastError),
1061
3.19k
                        lastError);
1062
3.19k
    }
1063
3.19k
  }
1064
1065
3.20k
  if (lastError == FREERDP_ERROR_SUCCESS)
1066
16
  {
1067
16
    if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1068
0
      WLog_PrintMessage(context->log, WLOG_MESSAGE_TEXT, WLOG_DEBUG, line, file, fkt,
1069
0
                        "resetting error state");
1070
16
  }
1071
3.19k
  else if (context->LastError != FREERDP_ERROR_SUCCESS)
1072
56
  {
1073
56
    if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1074
56
    {
1075
56
      WLog_PrintMessage(context->log, WLOG_MESSAGE_TEXT, WLOG_ERROR, line, file, fkt,
1076
56
                        "TODO: Trying to set error code %s, but %s already set!",
1077
56
                        freerdp_get_last_error_name(lastError),
1078
56
                        freerdp_get_last_error_name(context->LastError));
1079
56
    }
1080
56
  }
1081
3.20k
  context->LastError = lastError;
1082
3.20k
}
1083
1084
const char* freerdp_get_logon_error_info_type_ex(UINT32 type, char* buffer, size_t size)
1085
0
{
1086
0
  const char* str = freerdp_get_logon_error_info_type(type);
1087
0
  (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, type);
1088
0
  return buffer;
1089
0
}
1090
1091
const char* freerdp_get_logon_error_info_type(UINT32 type)
1092
110
{
1093
110
  switch (type)
1094
110
  {
1095
1
    case LOGON_MSG_DISCONNECT_REFUSED:
1096
1
      return "LOGON_MSG_DISCONNECT_REFUSED";
1097
1098
0
    case LOGON_MSG_NO_PERMISSION:
1099
0
      return "LOGON_MSG_NO_PERMISSION";
1100
1101
0
    case LOGON_MSG_BUMP_OPTIONS:
1102
0
      return "LOGON_MSG_BUMP_OPTIONS";
1103
1104
0
    case LOGON_MSG_RECONNECT_OPTIONS:
1105
0
      return "LOGON_MSG_RECONNECT_OPTIONS";
1106
1107
0
    case LOGON_MSG_SESSION_TERMINATE:
1108
0
      return "LOGON_MSG_SESSION_TERMINATE";
1109
1110
0
    case LOGON_MSG_SESSION_CONTINUE:
1111
0
      return "LOGON_MSG_SESSION_CONTINUE";
1112
1113
109
    default:
1114
109
      return "UNKNOWN";
1115
110
  }
1116
110
}
1117
1118
const char* freerdp_get_logon_error_info_data(UINT32 data)
1119
110
{
1120
110
  switch (data)
1121
110
  {
1122
42
    case LOGON_FAILED_BAD_PASSWORD:
1123
42
      return "LOGON_FAILED_BAD_PASSWORD";
1124
1125
0
    case LOGON_FAILED_UPDATE_PASSWORD:
1126
0
      return "LOGON_FAILED_UPDATE_PASSWORD";
1127
1128
0
    case LOGON_FAILED_OTHER:
1129
0
      return "LOGON_FAILED_OTHER";
1130
1131
0
    case LOGON_WARNING:
1132
0
      return "LOGON_WARNING";
1133
1134
68
    default:
1135
68
      return "SESSION_ID";
1136
110
  }
1137
110
}
1138
1139
const char* freerdp_get_logon_error_info_data_ex(UINT32 data, char* buffer, size_t size)
1140
0
{
1141
0
  const char* str = freerdp_get_logon_error_info_data(data);
1142
0
  (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, data);
1143
0
  return buffer;
1144
0
}
1145
1146
/** Allocator function for the rdp_freerdp structure.
1147
 *  @return an allocated structure filled with 0s. Need to be deallocated using freerdp_free()
1148
 */
1149
freerdp* freerdp_new(void)
1150
6.93k
{
1151
6.93k
  freerdp* instance = NULL;
1152
6.93k
  instance = (freerdp*)calloc(1, sizeof(freerdp));
1153
1154
6.93k
  if (!instance)
1155
0
    return NULL;
1156
1157
6.93k
  instance->ContextSize = sizeof(rdpContext);
1158
6.93k
  instance->SendChannelData = freerdp_send_channel_data;
1159
6.93k
  instance->SendChannelPacket = freerdp_send_channel_packet;
1160
6.93k
  instance->ReceiveChannelData = freerdp_channels_data;
1161
6.93k
  return instance;
1162
6.93k
}
1163
1164
/** Deallocator function for the rdp_freerdp structure.
1165
 *  @param instance - pointer to the rdp_freerdp structure to deallocate.
1166
 *                    On return, this pointer is not valid anymore.
1167
 */
1168
void freerdp_free(freerdp* instance)
1169
6.93k
{
1170
6.93k
  free(instance);
1171
6.93k
}
1172
1173
ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount)
1174
0
{
1175
0
  WINPR_ASSERT(context);
1176
0
  WINPR_ASSERT(context->rdp);
1177
0
  return transport_get_bytes_sent(context->rdp->transport, resetCount);
1178
0
}
1179
1180
BOOL freerdp_nla_impersonate(rdpContext* context)
1181
0
{
1182
0
  rdpNla* nla = NULL;
1183
1184
0
  if (!context)
1185
0
    return FALSE;
1186
1187
0
  if (!context->rdp)
1188
0
    return FALSE;
1189
1190
0
  if (!context->rdp->transport)
1191
0
    return FALSE;
1192
1193
0
  nla = transport_get_nla(context->rdp->transport);
1194
0
  return nla_impersonate(nla);
1195
0
}
1196
1197
BOOL freerdp_nla_revert_to_self(rdpContext* context)
1198
0
{
1199
0
  rdpNla* nla = NULL;
1200
1201
0
  if (!context)
1202
0
    return FALSE;
1203
1204
0
  if (!context->rdp)
1205
0
    return FALSE;
1206
1207
0
  if (!context->rdp->transport)
1208
0
    return FALSE;
1209
1210
0
  nla = transport_get_nla(context->rdp->transport);
1211
0
  return nla_revert_to_self(nla);
1212
0
}
1213
1214
UINT32 freerdp_get_nla_sspi_error(rdpContext* context)
1215
0
{
1216
0
  rdpNla* nla = NULL;
1217
1218
0
  WINPR_ASSERT(context);
1219
0
  WINPR_ASSERT(context->rdp);
1220
0
  WINPR_ASSERT(context->rdp->transport);
1221
1222
0
  nla = transport_get_nla(context->rdp->transport);
1223
1224
0
  return nla_get_sspi_error(nla);
1225
0
}
1226
1227
HANDLE getChannelErrorEventHandle(rdpContext* context)
1228
0
{
1229
0
  WINPR_ASSERT(context);
1230
0
  return context->channelErrorEvent;
1231
0
}
1232
1233
BOOL checkChannelErrorEvent(rdpContext* context)
1234
0
{
1235
0
  WINPR_ASSERT(context);
1236
1237
0
  if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1238
0
  {
1239
0
    WLog_Print(context->log, WLOG_ERROR, "%s. Error was %" PRIu32 "", context->errorDescription,
1240
0
               context->channelErrorNum);
1241
0
    return FALSE;
1242
0
  }
1243
1244
0
  return TRUE;
1245
0
}
1246
1247
/**
1248
 * Function description
1249
 *
1250
 * @return 0 on success, otherwise a Win32 error code
1251
 */
1252
UINT getChannelError(rdpContext* context)
1253
0
{
1254
0
  WINPR_ASSERT(context);
1255
0
  return context->channelErrorNum;
1256
0
}
1257
1258
const char* getChannelErrorDescription(rdpContext* context)
1259
0
{
1260
0
  WINPR_ASSERT(context);
1261
0
  return context->errorDescription;
1262
0
}
1263
1264
void clearChannelError(rdpContext* context)
1265
0
{
1266
0
  WINPR_ASSERT(context);
1267
0
  context->channelErrorNum = 0;
1268
0
  memset(context->errorDescription, 0, 500);
1269
0
  ResetEvent(context->channelErrorEvent);
1270
0
}
1271
1272
WINPR_ATTR_FORMAT_ARG(3, 4)
1273
void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const char* format, ...)
1274
0
{
1275
0
  va_list ap;
1276
0
  va_start(ap, format);
1277
1278
0
  WINPR_ASSERT(context);
1279
1280
0
  context->channelErrorNum = errorNum;
1281
0
  (void)vsnprintf(context->errorDescription, 499, format, ap);
1282
0
  va_end(ap);
1283
0
  SetEvent(context->channelErrorEvent);
1284
0
}
1285
1286
const char* freerdp_nego_get_routing_token(rdpContext* context, DWORD* length)
1287
0
{
1288
0
  if (!context || !context->rdp)
1289
0
    return NULL;
1290
1291
0
  return (const char*)nego_get_routing_token(context->rdp->nego, length);
1292
0
}
1293
1294
BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1295
0
{
1296
0
  WINPR_ASSERT(context);
1297
0
  return rdp_io_callback_set_event(context->rdp, set);
1298
0
}
1299
1300
const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1301
0
{
1302
0
  WINPR_ASSERT(context);
1303
0
  return rdp_get_io_callbacks(context->rdp);
1304
0
}
1305
1306
BOOL freerdp_set_io_callbacks(rdpContext* context, const rdpTransportIo* io_callbacks)
1307
0
{
1308
0
  WINPR_ASSERT(context);
1309
0
  return rdp_set_io_callbacks(context->rdp, io_callbacks);
1310
0
}
1311
1312
BOOL freerdp_set_io_callback_context(rdpContext* context, void* usercontext)
1313
0
{
1314
0
  WINPR_ASSERT(context);
1315
0
  return rdp_set_io_callback_context(context->rdp, usercontext);
1316
0
}
1317
1318
void* freerdp_get_io_callback_context(rdpContext* context)
1319
0
{
1320
0
  WINPR_ASSERT(context);
1321
0
  return rdp_get_io_callback_context(context->rdp);
1322
0
}
1323
1324
CONNECTION_STATE freerdp_get_state(const rdpContext* context)
1325
0
{
1326
0
  WINPR_ASSERT(context);
1327
0
  return rdp_get_state(context->rdp);
1328
0
}
1329
1330
const char* freerdp_state_string(CONNECTION_STATE state)
1331
0
{
1332
0
  return rdp_state_string(state);
1333
0
}
1334
1335
BOOL freerdp_is_active_state(const rdpContext* context)
1336
0
{
1337
0
  WINPR_ASSERT(context);
1338
0
  return rdp_is_active_state(context->rdp);
1339
0
}
1340
1341
BOOL freerdp_channels_from_mcs(rdpSettings* settings, const rdpContext* context)
1342
0
{
1343
0
  WINPR_ASSERT(context);
1344
0
  return rdp_channels_from_mcs(settings, context->rdp);
1345
0
}
1346
1347
HANDLE freerdp_abort_event(rdpContext* context)
1348
0
{
1349
0
  WINPR_ASSERT(context);
1350
0
  return utils_get_abort_event(context->rdp);
1351
0
}
1352
1353
static void test_mcs_free(rdpMcs* mcs)
1354
26.5k
{
1355
26.5k
  if (!mcs)
1356
0
    return;
1357
1358
26.5k
  rdpTransport* transport = mcs->transport;
1359
26.5k
  rdpContext* context = transport_get_context(transport);
1360
26.5k
  if (context)
1361
26.5k
  {
1362
26.5k
    rdpSettings* settings = context->settings;
1363
26.5k
    freerdp_settings_free(settings);
1364
26.5k
  }
1365
26.5k
  free(context);
1366
26.5k
  transport_free(transport);
1367
1368
26.5k
  mcs_free(mcs);
1369
26.5k
}
1370
1371
static rdpMcs* test_mcs_new(void)
1372
26.5k
{
1373
26.5k
  rdpTransport* transport = NULL;
1374
26.5k
  rdpSettings* settings = freerdp_settings_new(0);
1375
26.5k
  rdpContext* context = calloc(1, sizeof(rdpContext));
1376
1377
26.5k
  if (!settings)
1378
0
    goto fail;
1379
26.5k
  if (!freerdp_settings_set_bool(settings, FreeRDP_TransportDumpReplay, TRUE))
1380
0
    goto fail;
1381
1382
26.5k
  if (!context)
1383
0
    goto fail;
1384
26.5k
  context->settings = settings;
1385
26.5k
  transport = transport_new(context);
1386
26.5k
  if (!transport)
1387
0
    goto fail;
1388
26.5k
  return mcs_new(transport);
1389
1390
0
fail:
1391
0
  transport_free(transport);
1392
0
  free(context);
1393
0
  freerdp_settings_free(settings);
1394
1395
0
  return NULL;
1396
26.5k
}
1397
1398
BOOL freerdp_is_valid_mcs_create_request(const BYTE* data, size_t size)
1399
13.2k
{
1400
1401
13.2k
  wStream sbuffer = { 0 };
1402
13.2k
  wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1403
1404
13.2k
  WINPR_ASSERT(data || (size == 0));
1405
13.2k
  WINPR_ASSERT(s);
1406
1407
13.2k
  rdpMcs* mcs = test_mcs_new();
1408
13.2k
  WINPR_ASSERT(mcs);
1409
1410
13.2k
  BOOL result = mcs_recv_connect_initial(mcs, s);
1411
13.2k
  test_mcs_free(mcs);
1412
13.2k
  return result;
1413
13.2k
}
1414
1415
BOOL freerdp_is_valid_mcs_create_response(const BYTE* data, size_t size)
1416
13.2k
{
1417
1418
13.2k
  wStream sbuffer = { 0 };
1419
13.2k
  wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1420
1421
13.2k
  WINPR_ASSERT(data || (size == 0));
1422
13.2k
  WINPR_ASSERT(s);
1423
1424
13.2k
  rdpMcs* mcs = test_mcs_new();
1425
13.2k
  WINPR_ASSERT(mcs);
1426
1427
13.2k
  BOOL result = mcs_recv_connect_response(mcs, s);
1428
13.2k
  test_mcs_free(mcs);
1429
13.2k
  return result;
1430
13.2k
}