FreeRDP
Loading...
Searching...
No Matches
freerdp.c
1
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#define TAG FREERDP_TAG("core")
64
65static void sig_abort_connect(int signum, const char* signame, void* ctx)
66{
67 rdpContext* context = (rdpContext*)ctx;
68
69 WLog_INFO(TAG, "Signal %s [%d], terminating session %p", signame, signum,
70 WINPR_CXX_COMPAT_CAST(const void*, context));
71 if (context)
72 freerdp_abort_connect_context(context);
73}
74
86static int freerdp_connect_begin(freerdp* instance)
87{
88 BOOL rc = 0;
89 rdpRdp* rdp = nullptr;
90 BOOL status = TRUE;
91 rdpSettings* settings = nullptr;
92
93 if (!instance)
94 return -1;
95
96 WINPR_ASSERT(instance->context);
97
98 /* We always set the return code to 0 before we start the connect sequence*/
99 instance->ConnectionCallbackState = CLIENT_STATE_INITIAL;
100 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS);
101 clearChannelError(instance->context);
102 if (!utils_reset_abort(instance->context->rdp))
103 return -1;
104
105 rdp = instance->context->rdp;
106 WINPR_ASSERT(rdp);
107
108 settings = instance->context->settings;
109 WINPR_ASSERT(settings);
110
111 freerdp_channels_register_instance(instance->context->channels, instance);
112
113 if (!freerdp_settings_set_default_order_support(settings))
114 return -1;
115
116 if (!freerdp_add_signal_cleanup_handler(instance->context, sig_abort_connect))
117 return -1;
118
119 IFCALLRET(instance->PreConnect, status, instance);
120 instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED;
121
122 freerdp_settings_print_warnings(settings);
123 if (status)
124 status = freerdp_settings_enforce_monitor_exists(settings);
125
126 if (status)
127 status = freerdp_settings_enforce_consistency(settings);
128
129 if (status)
130 status = freerdp_settings_check_client_after_preconnect(settings);
131
132 if (status)
133 status = rdp_set_backup_settings(rdp);
134 if (status)
135 status = utils_reload_channels(instance->context);
136
137 const UINT32 cp = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardCodePage);
138 int64_t KeyboardLayout = freerdp_get_keyboard_default_layout_for_locale(cp);
139 if (KeyboardLayout == 0)
140 KeyboardLayout = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardLayout);
141
142 switch (KeyboardLayout)
143 {
144 case KBD_JAPANESE:
145 case KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002:
146 {
147 if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardType,
148 WINPR_KBD_TYPE_JAPANESE))
149 return -1;
150 if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardSubType, 2))
151 return -1;
152 if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardFunctionKey, 12))
153 return -1;
154 }
155 break;
156 default:
157 break;
158 }
159
160 if (!status)
161 {
162 rdpContext* context = instance->context;
163 WINPR_ASSERT(context);
164 freerdp_set_last_error_if_not(context, FREERDP_ERROR_PRE_CONNECT_FAILED);
165
166 WLog_Print(context->log, WLOG_ERROR, "freerdp_pre_connect failed: %s",
167 rdp_client_connection_state_string(instance->ConnectionCallbackState));
168 return 0;
169 }
170
171 rc = rdp_client_connect(rdp);
172
173 /* --authonly tests the connection without a UI */
174 if (freerdp_settings_get_bool(rdp->settings, FreeRDP_AuthenticationOnly))
175 {
176 rdpContext* context = rdp->context;
177 WINPR_ASSERT(context);
178 WLog_Print(context->log, WLOG_ERROR, "Authentication only, exit status %" PRId32 "", rc);
179 return 0;
180 }
181
182 return rc ? 1 : 0;
183}
184
185BOOL freerdp_connect(freerdp* instance)
186{
187 BOOL status = FALSE;
188 ConnectionResultEventArgs e = WINPR_C_ARRAY_INIT;
189 const int rc = freerdp_connect_begin(instance);
190 rdpRdp* rdp = nullptr;
191 UINT status2 = ERROR_INTERNAL_ERROR;
192
193 WINPR_ASSERT(instance);
194 WINPR_ASSERT(instance->context);
195
196 rdp = instance->context->rdp;
197 WINPR_ASSERT(rdp);
198 WINPR_ASSERT(rdp->settings);
199
200 if (rc > 0)
201 /* Pointers might have changed in between */
202 {
203 rdp_update_internal* up = update_cast(rdp->update);
204
205 if (freerdp_settings_get_bool(rdp->settings, FreeRDP_DumpRemoteFx))
206 {
207 up->pcap_rfx = pcap_open(
208 freerdp_settings_get_string(rdp->settings, FreeRDP_DumpRemoteFxFile), TRUE);
209
210 if (up->pcap_rfx)
211 up->dump_rfx = TRUE;
212 }
213
214 pointer_cache_register_callbacks(instance->context->update);
215 status = IFCALLRESULT(TRUE, instance->PostConnect, instance);
216 instance->ConnectionCallbackState = CLIENT_STATE_POSTCONNECT_PASSED;
217
218 if (status)
219 status2 = freerdp_channels_post_connect(instance->context->channels, instance);
220 }
221 else
222 {
223 status2 = CHANNEL_RC_OK;
224 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)
225 status = freerdp_reconnect(instance);
226 else
227 goto freerdp_connect_finally;
228 }
229
230 if (!status || (status2 != CHANNEL_RC_OK) || !update_post_connect(instance->context->update))
231 {
232 rdpContext* context = instance->context;
233 WINPR_ASSERT(context);
234 WLog_Print(context->log, WLOG_ERROR, "freerdp_post_connect failed");
235
236 freerdp_set_last_error_if_not(context, FREERDP_ERROR_POST_CONNECT_FAILED);
237
238 status = FALSE;
239 goto freerdp_connect_finally;
240 }
241
242 if (rdp->settings->PlayRemoteFx)
243 {
244 wStream* s = nullptr;
245 rdp_update_internal* update = update_cast(instance->context->update);
246 pcap_record record = WINPR_C_ARRAY_INIT;
247
248 WINPR_ASSERT(update);
249 update->pcap_rfx = pcap_open(rdp->settings->PlayRemoteFxFile, FALSE);
250 status = FALSE;
251
252 if (!update->pcap_rfx)
253 goto freerdp_connect_finally;
254 else
255 update->play_rfx = TRUE;
256
257 status = TRUE;
258
259 while (pcap_has_next_record(update->pcap_rfx) && status)
260 {
261 if (!pcap_get_next_record_header(update->pcap_rfx, &record))
262 break;
263
264 s = transport_take_from_pool(rdp->transport, record.length);
265 if (!s)
266 break;
267
268 record.data = Stream_Buffer(s);
269 if (!pcap_get_next_record_content(update->pcap_rfx, &record))
270 break;
271 if (!Stream_SetLength(s, record.length))
272 {
273 status = FALSE;
274 continue;
275 }
276 Stream_ResetPosition(s);
277
278 if (!update_begin_paint(&update->common))
279 status = FALSE;
280 else
281 {
282 if (update_recv_surfcmds(&update->common, s) < 0)
283 status = FALSE;
284
285 if (!update_end_paint(&update->common))
286 status = FALSE;
287 }
288
289 Stream_Release(s);
290 }
291
292 pcap_close(update->pcap_rfx);
293 update->pcap_rfx = nullptr;
294 goto freerdp_connect_finally;
295 }
296
297 if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
298 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
299
300 if (status)
301 status = transport_set_connected_event(rdp->transport);
302
303freerdp_connect_finally:
304 EventArgsInit(&e, "freerdp");
305 e.result = status ? 0 : -1;
306 if (PubSub_OnConnectionResult(rdp->pubSub, instance->context, &e) < 0)
307 return FALSE;
308
309 if (!status)
310 freerdp_disconnect(instance);
311
312 return status;
313}
314
315#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
316BOOL freerdp_abort_connect(freerdp* instance)
317{
318 if (!instance)
319 return FALSE;
320
321 return freerdp_abort_connect_context(instance->context);
322}
323#endif
324
325BOOL freerdp_abort_connect_context(rdpContext* context)
326{
327 if (!context)
328 return FALSE;
329
330 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
331 return utils_abort_connect(context->rdp);
332}
333
334#if defined(WITH_FREERDP_DEPRECATED)
335BOOL freerdp_get_fds(freerdp* instance, void** rfds, int* rcount, WINPR_ATTR_UNUSED void** wfds,
336 WINPR_ATTR_UNUSED int* wcount)
337{
338 rdpRdp* rdp = nullptr;
339
340 WINPR_ASSERT(instance);
341 WINPR_ASSERT(instance->context);
342
343 rdp = instance->context->rdp;
344 WINPR_ASSERT(rdp);
345
346 transport_get_fds(rdp->transport, rfds, rcount);
347 return TRUE;
348}
349#endif
350
351BOOL freerdp_check_fds(freerdp* instance)
352{
353 int status = 0;
354 rdpRdp* rdp = nullptr;
355
356 if (!instance)
357 return FALSE;
358
359 if (!instance->context)
360 return FALSE;
361
362 if (!instance->context->rdp)
363 return FALSE;
364
365 rdp = instance->context->rdp;
366 status = rdp_check_fds(rdp);
367
368 if (status < 0)
369 {
370 TerminateEventArgs e;
371 rdpContext* context = instance->context;
372 WINPR_ASSERT(context);
373
374 WLog_Print(context->log, WLOG_DEBUG, "rdp_check_fds() - %i", status);
375 EventArgsInit(&e, "freerdp");
376 e.code = 0;
377 if (PubSub_OnTerminate(rdp->pubSub, context, &e) < 0)
378 return FALSE;
379 return FALSE;
380 }
381
382 return TRUE;
383}
384
385DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count)
386{
387 DWORD nCount = 0;
388
389 WINPR_ASSERT(context);
390 WINPR_ASSERT(context->rdp);
391 WINPR_ASSERT(events || (count == 0));
392
393 const size_t rrc = rdp_get_event_handles(context->rdp, &events[nCount], count - nCount);
394 if (rrc == 0)
395 return 0;
396
397 nCount += WINPR_ASSERTING_INT_CAST(uint32_t, rrc);
398
399 if (events && (nCount < count + 2))
400 {
401 events[nCount++] = freerdp_channels_get_event_handle(context->instance);
402 events[nCount++] = getChannelErrorEventHandle(context);
403 }
404 else
405 return 0;
406
407 const SSIZE_T rc = freerdp_client_channel_get_registered_event_handles(
408 context->channels, &events[nCount], count - nCount);
409 if (rc < 0)
410 return 0;
411 return nCount + (DWORD)rc;
412}
413
414/* Resend mouse cursor position to prevent session lock in prevent-session-lock mode */
415static BOOL freerdp_prevent_session_lock(rdpContext* context)
416{
417 WINPR_ASSERT(context);
418 WINPR_ASSERT(context->input);
419
420 rdp_input_internal* in = input_cast(context->input);
421
422 UINT32 FakeMouseMotionInterval =
423 freerdp_settings_get_uint32(context->settings, FreeRDP_FakeMouseMotionInterval);
424 if (FakeMouseMotionInterval && in->lastInputTimestamp)
425 {
426 const time_t now = time(nullptr);
427 if (WINPR_ASSERTING_INT_CAST(size_t, now) - in->lastInputTimestamp >
428 FakeMouseMotionInterval)
429 {
430 WLog_Print(context->log, WLOG_DEBUG,
431 "fake mouse move: x=%d y=%d lastInputTimestamp=%" PRIu64 " "
432 "FakeMouseMotionInterval=%" PRIu32,
433 in->lastX, in->lastY, in->lastInputTimestamp, FakeMouseMotionInterval);
434
435 BOOL status = freerdp_input_send_mouse_event(context->input, PTR_FLAGS_MOVE, in->lastX,
436 in->lastY);
437 if (!status)
438 {
439 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
440 WLog_Print(context->log, WLOG_ERROR,
441 "freerdp_prevent_session_lock() failed - %" PRIi32 "", status);
442
443 return FALSE;
444 }
445
446 return status;
447 }
448 }
449
450 return TRUE;
451}
452
453BOOL freerdp_check_event_handles(rdpContext* context)
454{
455 WINPR_ASSERT(context);
456
457 BOOL status = freerdp_check_fds(context->instance);
458
459 if (!status)
460 {
461 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
462 WLog_Print(context->log, WLOG_ERROR, "freerdp_check_fds() failed - %" PRIi32 "",
463 status);
464
465 return FALSE;
466 }
467
468 status = freerdp_channels_check_fds(context->channels, context->instance);
469
470 if (!status)
471 {
472 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
473 WLog_Print(context->log, WLOG_ERROR,
474 "freerdp_channels_check_fds() failed - %" PRIi32 "", status);
475
476 return FALSE;
477 }
478
479 status = checkChannelErrorEvent(context);
480
481 if (!status)
482 {
483 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
484 WLog_Print(context->log, WLOG_ERROR, "checkChannelErrorEvent() failed - %" PRIi32 "",
485 status);
486
487 return FALSE;
488 }
489
490 status = freerdp_prevent_session_lock(context);
491
492 return status;
493}
494
495wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD id)
496{
497 wMessageQueue* queue = nullptr;
498
499 WINPR_ASSERT(instance);
500
501 rdpContext* context = instance->context;
502 WINPR_ASSERT(context);
503
504 switch (id)
505 {
506 case FREERDP_UPDATE_MESSAGE_QUEUE:
507 {
508 rdp_update_internal* update = update_cast(context->update);
509 queue = update->queue;
510 }
511 break;
512
513 case FREERDP_INPUT_MESSAGE_QUEUE:
514 {
515 rdp_input_internal* input = input_cast(context->input);
516 queue = input->queue;
517 }
518 break;
519 default:
520 break;
521 }
522
523 return queue;
524}
525
526HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD id)
527{
528 HANDLE event = nullptr;
529 wMessageQueue* queue = freerdp_get_message_queue(instance, id);
530
531 if (queue)
532 event = MessageQueue_Event(queue);
533
534 return event;
535}
536
537int freerdp_message_queue_process_message(freerdp* instance, DWORD id, wMessage* message)
538{
539 int status = -1;
540 rdpContext* context = nullptr;
541
542 WINPR_ASSERT(instance);
543
544 context = instance->context;
545 WINPR_ASSERT(context);
546
547 switch (id)
548 {
549 case FREERDP_UPDATE_MESSAGE_QUEUE:
550 status = update_message_queue_process_message(context->update, message);
551 break;
552
553 case FREERDP_INPUT_MESSAGE_QUEUE:
554 status = input_message_queue_process_message(context->input, message);
555 break;
556 default:
557 break;
558 }
559
560 return status;
561}
562
563int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD id)
564{
565 int status = -1;
566 rdpContext* context = nullptr;
567
568 WINPR_ASSERT(instance);
569
570 context = instance->context;
571 WINPR_ASSERT(context);
572
573 switch (id)
574 {
575 case FREERDP_UPDATE_MESSAGE_QUEUE:
576 status = update_message_queue_process_pending_messages(context->update);
577 break;
578
579 case FREERDP_INPUT_MESSAGE_QUEUE:
580 status = input_message_queue_process_pending_messages(context->input);
581 break;
582 default:
583 break;
584 }
585
586 return status;
587}
588
589static BOOL freerdp_send_channel_data(freerdp* instance, UINT16 channelId, const BYTE* data,
590 size_t size)
591{
592 WINPR_ASSERT(instance);
593 WINPR_ASSERT(instance->context);
594 WINPR_ASSERT(instance->context->rdp);
595 return rdp_send_channel_data(instance->context->rdp, channelId, data, size);
596}
597
598static BOOL freerdp_send_channel_packet(freerdp* instance, UINT16 channelId, size_t totalSize,
599 UINT32 flags, const BYTE* data, size_t chunkSize)
600{
601 WINPR_ASSERT(instance);
602 WINPR_ASSERT(instance->context);
603 WINPR_ASSERT(instance->context->rdp);
604 return rdp_channel_send_packet(instance->context->rdp, channelId, totalSize, flags, data,
605 chunkSize);
606}
607
608BOOL freerdp_disconnect(freerdp* instance)
609{
610 BOOL rc = TRUE;
611
612 if (!instance || !instance->context)
613 return FALSE;
614
615 rdpRdp* rdp = instance->context->rdp;
616 if (rdp)
617 {
618 /* Try to send a [MS-RDPBCGR] 1.3.1.4.1 User-Initiated on Client PDU, we don't care about
619 * success */
620 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
621 {
622 (void)mcs_send_disconnect_provider_ultimatum(rdp->mcs,
623 Disconnect_Ultimatum_user_requested);
624 }
625 }
626
627 utils_abort_connect(rdp);
628
629 if (!rdp_client_disconnect(rdp))
630 rc = FALSE;
631
632 rdp_update_internal* up = nullptr;
633 if (rdp && rdp->update)
634 {
635 up = update_cast(rdp->update);
636
637 update_post_disconnect(rdp->update);
638 }
639
640 IFCALL(instance->PostDisconnect, instance);
641
642 if (up)
643 {
644 if (up->pcap_rfx)
645 {
646 up->dump_rfx = FALSE;
647 pcap_close(up->pcap_rfx);
648 up->pcap_rfx = nullptr;
649 }
650 }
651
652 if (instance->context->channels)
653 freerdp_channels_close(instance->context->channels, instance);
654
655 IFCALL(instance->PostFinalDisconnect, instance);
656
657 freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
658 return rc;
659}
660
661#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
662BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
663{
664 WINPR_ASSERT(instance);
665 return freerdp_disconnect_before_reconnect_context(instance->context);
666}
667#endif
668
669BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
670{
671 rdpRdp* rdp = nullptr;
672
673 WINPR_ASSERT(context);
674
675 rdp = context->rdp;
676 return rdp_client_disconnect_and_clear(rdp);
677}
678
679BOOL freerdp_reconnect(freerdp* instance)
680{
681 rdpRdp* rdp = nullptr;
682
683 WINPR_ASSERT(instance);
684 WINPR_ASSERT(instance->context);
685
686 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
687 return FALSE;
688
689 rdp = instance->context->rdp;
690
691 if (!utils_reset_abort(instance->context->rdp))
692 return FALSE;
693 return rdp_client_reconnect(rdp);
694}
695
696#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
697BOOL freerdp_shall_disconnect(const freerdp* instance)
698{
699 if (!instance)
700 return FALSE;
701
702 return freerdp_shall_disconnect_context(instance->context);
703}
704#endif
705
706BOOL freerdp_shall_disconnect_context(const rdpContext* context)
707{
708 if (!context)
709 return FALSE;
710
711 return utils_abort_event_is_set(context->rdp);
712}
713
714BOOL freerdp_focus_required(freerdp* instance)
715{
716 rdpRdp* rdp = nullptr;
717 BOOL bRetCode = FALSE;
718
719 WINPR_ASSERT(instance);
720 WINPR_ASSERT(instance->context);
721
722 rdp = instance->context->rdp;
723 WINPR_ASSERT(rdp);
724
725 if (rdp->resendFocus)
726 {
727 bRetCode = TRUE;
728 rdp->resendFocus = FALSE;
729 }
730
731 return bRetCode;
732}
733
734void freerdp_set_focus(freerdp* instance)
735{
736 rdpRdp* rdp = nullptr;
737
738 WINPR_ASSERT(instance);
739 WINPR_ASSERT(instance->context);
740
741 rdp = instance->context->rdp;
742 WINPR_ASSERT(rdp);
743
744 rdp->resendFocus = TRUE;
745}
746
747void freerdp_get_version(int* major, int* minor, int* revision)
748{
749 if (major != nullptr)
750 *major = FREERDP_VERSION_MAJOR;
751
752 if (minor != nullptr)
753 *minor = FREERDP_VERSION_MINOR;
754
755 if (revision != nullptr)
756 *revision = FREERDP_VERSION_REVISION;
757}
758
759const char* freerdp_get_version_string(void)
760{
761 return FREERDP_VERSION_FULL;
762}
763
764const char* freerdp_get_build_config(void)
765{
766 WINPR_PRAGMA_DIAG_PUSH
767 WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
768 static const char build_config[] =
769 "Build configuration: " FREERDP_BUILD_CONFIG "\n"
770 "Build type: " FREERDP_BUILD_TYPE "\n"
771 "CFLAGS: " FREERDP_CFLAGS "\n"
772 "Compiler: " FREERDP_COMPILER_ID ", " FREERDP_COMPILER_VERSION "\n"
773 "Target architecture: " FREERDP_TARGET_ARCH "\n";
774 WINPR_PRAGMA_DIAG_POP
775 return build_config;
776}
777
778const char* freerdp_get_build_revision(void)
779{
780 return FREERDP_GIT_REVISION;
781}
782
783static wEventType FreeRDP_Events[] = {
784 DEFINE_EVENT_ENTRY(WindowStateChange), DEFINE_EVENT_ENTRY(ResizeWindow),
785 DEFINE_EVENT_ENTRY(LocalResizeWindow), DEFINE_EVENT_ENTRY(EmbedWindow),
786 DEFINE_EVENT_ENTRY(PanningChange), DEFINE_EVENT_ENTRY(ZoomingChange),
787 DEFINE_EVENT_ENTRY(ErrorInfo), DEFINE_EVENT_ENTRY(Terminate),
788 DEFINE_EVENT_ENTRY(ConnectionResult), DEFINE_EVENT_ENTRY(ChannelConnected),
789 DEFINE_EVENT_ENTRY(ChannelDisconnected), DEFINE_EVENT_ENTRY(MouseEvent),
790 DEFINE_EVENT_ENTRY(Activated), DEFINE_EVENT_ENTRY(Timer),
791 DEFINE_EVENT_ENTRY(GraphicsReset)
792};
793
804BOOL freerdp_context_new(freerdp* instance)
805{
806 return freerdp_context_new_ex(instance, nullptr);
807}
808
809static BOOL freerdp_common_context(rdpContext* context, AccessTokenType tokenType, char** token,
810 size_t count, ...)
811{
812 BOOL rc = FALSE;
813
814 WINPR_ASSERT(context);
815 if (!context->instance || !context->instance->GetAccessToken)
816 return TRUE;
817
818 va_list ap = WINPR_C_ARRAY_INIT;
819 va_start(ap, count);
820 switch (tokenType)
821 {
822 case ACCESS_TOKEN_TYPE_AAD:
823 if (count != 2)
824 {
825 WLog_ERR(TAG,
826 "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
827 ", aborting",
828 count);
829 }
830 else
831 {
832 const char* scope = va_arg(ap, const char*);
833 const char* req_cnf = va_arg(ap, const char*);
834 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count,
835 scope, req_cnf);
836 }
837 break;
838 case ACCESS_TOKEN_TYPE_AVD:
839 if (count != 0)
840 {
841 WLog_WARN(TAG,
842 "ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
843 ", ignoring",
844 count);
845 }
846 else
847 {
848 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count);
849 }
850 break;
851 default:
852 break;
853 }
854 va_end(ap);
855
856 if (!rc)
857 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
858
859 return rc;
860}
861
862BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
863{
864 rdpRdp* rdp = nullptr;
865 rdpContext* context = nullptr;
866 BOOL ret = TRUE;
867
868 WINPR_ASSERT(instance);
869
870 instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
871
872 if (!context)
873 return FALSE;
874
875 context->log = WLog_Get(TAG);
876 if (!context->log)
877 goto fail;
878
879 /* Set to external settings, prevents rdp_new from creating its own instance */
880 context->settings = settings;
881 context->instance = instance;
882 context->ServerMode = FALSE;
883 context->disconnectUltimatum = 0;
884
885 context->metrics = metrics_new(context);
886
887 if (!context->metrics)
888 goto fail;
889
890 rdp = rdp_new(context);
891
892 if (!rdp)
893 goto fail;
894
895 context->rdp = rdp;
896 context->pubSub = rdp->pubSub;
897
898 if (!context->pubSub)
899 goto fail;
900
901 PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
902
903#if defined(WITH_FREERDP_DEPRECATED)
904 instance->input = rdp->input;
905 instance->update = rdp->update;
906 instance->settings = rdp->settings;
907 instance->autodetect = rdp->autodetect;
908#endif
909
910 instance->heartbeat = rdp->heartbeat;
911 context->graphics = graphics_new(context);
912
913 if (!context->graphics)
914 goto fail;
915
916 context->input = rdp->input;
917 context->update = rdp->update;
918 context->settings = rdp->settings;
919 context->autodetect = rdp->autodetect;
920
921 if (!(context->errorDescription = calloc(1, 500)))
922 {
923 WLog_Print(context->log, WLOG_ERROR, "calloc failed!");
924 goto fail;
925 }
926
927 if (!(context->channelErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
928 {
929 WLog_Print(context->log, WLOG_ERROR, "CreateEvent failed!");
930 goto fail;
931 }
932
933 update_register_client_callbacks(rdp->update);
934
935 if (!(context->channels = freerdp_channels_new(instance)))
936 goto fail;
937
938 context->dump = stream_dump_new();
939 if (!context->dump)
940 goto fail;
941
942 /* Fallback:
943 * Client common library might set a function pointer to handle this, but here we provide a
944 * default implementation that simply calls instance->GetAccessToken.
945 */
946 if (!freerdp_set_common_access_token(context, freerdp_common_context))
947 goto fail;
948
949 IFCALLRET(instance->ContextNew, ret, instance, context);
950
951 if (!ret)
952 goto fail;
953
954 return TRUE;
955
956fail:
957 freerdp_context_free(instance);
958 return FALSE;
959}
960
961BOOL freerdp_context_reset(freerdp* instance)
962{
963 if (!instance)
964 return FALSE;
965
966 WINPR_ASSERT(instance->context);
967 rdpRdp* rdp = instance->context->rdp;
968
969 return rdp_reset_runtime_settings(rdp);
970}
971
980void freerdp_context_free(freerdp* instance)
981{
982 rdpContext* ctx = nullptr;
983
984 if (!instance)
985 return;
986
987 if (!instance->context)
988 return;
989
990 ctx = instance->context;
991
992 IFCALL(instance->ContextFree, instance, ctx);
993 rdp_free(ctx->rdp);
994 ctx->rdp = nullptr;
995 ctx->settings = nullptr; /* owned by rdpRdp */
996
997 graphics_free(ctx->graphics);
998 ctx->graphics = nullptr;
999
1000 metrics_free(ctx->metrics);
1001 ctx->metrics = nullptr;
1002
1003 if (ctx->channelErrorEvent)
1004 (void)CloseHandle(ctx->channelErrorEvent);
1005 ctx->channelErrorEvent = nullptr;
1006
1007 free(ctx->errorDescription);
1008 ctx->errorDescription = nullptr;
1009
1010 freerdp_channels_free(ctx->channels);
1011 ctx->channels = nullptr;
1012
1013 freerdp_client_codecs_free(ctx->codecs);
1014 ctx->codecs = nullptr;
1015
1016 stream_dump_free(ctx->dump);
1017 ctx->dump = nullptr;
1018
1019 ctx->input = nullptr; /* owned by rdpRdp */
1020 ctx->update = nullptr; /* owned by rdpRdp */
1021 ctx->settings = nullptr; /* owned by rdpRdp */
1022 ctx->autodetect = nullptr; /* owned by rdpRdp */
1023
1024 free(ctx);
1025 instance->context = nullptr;
1026#if defined(WITH_FREERDP_DEPRECATED)
1027 instance->input = nullptr; /* owned by rdpRdp */
1028 instance->update = nullptr; /* owned by rdpRdp */
1029 instance->settings = nullptr; /* owned by rdpRdp */
1030 instance->autodetect = nullptr; /* owned by rdpRdp */
1031#endif
1032 instance->heartbeat = nullptr; /* owned by rdpRdp */
1033}
1034
1035int freerdp_get_disconnect_ultimatum(const rdpContext* context)
1036{
1037 WINPR_ASSERT(context);
1038 return context->disconnectUltimatum;
1039}
1040
1041UINT32 freerdp_error_info(const freerdp* instance)
1042{
1043 WINPR_ASSERT(instance);
1044 WINPR_ASSERT(instance->context);
1045 WINPR_ASSERT(instance->context->rdp);
1046 return instance->context->rdp->errorInfo;
1047}
1048
1049void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
1050{
1051 if (!rdp)
1052 return;
1053
1054 rdp_set_error_info(rdp, error);
1055}
1056
1057BOOL freerdp_send_error_info(rdpRdp* rdp)
1058{
1059 if (!rdp)
1060 return FALSE;
1061
1062 return rdp_send_error_info(rdp);
1063}
1064
1065UINT32 freerdp_get_last_error(const rdpContext* context)
1066{
1067 WINPR_ASSERT(context);
1068 return context->LastError;
1069}
1070
1071const char* freerdp_get_last_error_name(UINT32 code)
1072{
1073 const char* name = nullptr;
1074 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1075 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1076
1077 switch (cls)
1078 {
1079 case FREERDP_ERROR_ERRBASE_CLASS:
1080 name = freerdp_get_error_base_name(type);
1081 break;
1082
1083 case FREERDP_ERROR_ERRINFO_CLASS:
1084 name = freerdp_get_error_info_name(type);
1085 break;
1086
1087 case FREERDP_ERROR_CONNECT_CLASS:
1088 name = freerdp_get_error_connect_name(type);
1089 break;
1090
1091 default:
1092 name = rpc_error_to_string(code);
1093 break;
1094 }
1095
1096 return name;
1097}
1098
1099const char* freerdp_get_last_error_string(UINT32 code)
1100{
1101 const char* string = nullptr;
1102 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1103 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1104
1105 switch (cls)
1106 {
1107 case FREERDP_ERROR_ERRBASE_CLASS:
1108 string = freerdp_get_error_base_string(type);
1109 break;
1110
1111 case FREERDP_ERROR_ERRINFO_CLASS:
1112 string = freerdp_get_error_info_string(type);
1113 break;
1114
1115 case FREERDP_ERROR_CONNECT_CLASS:
1116 string = freerdp_get_error_connect_string(type);
1117 break;
1118
1119 default:
1120 string = rpc_error_to_string(code);
1121 break;
1122 }
1123
1124 return string;
1125}
1126
1127const char* freerdp_get_last_error_category(UINT32 code)
1128{
1129 const char* string = nullptr;
1130 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1131 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1132
1133 switch (cls)
1134 {
1135 case FREERDP_ERROR_ERRBASE_CLASS:
1136 string = freerdp_get_error_base_category(type);
1137 break;
1138
1139 case FREERDP_ERROR_ERRINFO_CLASS:
1140 string = freerdp_get_error_info_category(type);
1141 break;
1142
1143 case FREERDP_ERROR_CONNECT_CLASS:
1144 string = freerdp_get_error_connect_category(type);
1145 break;
1146
1147 default:
1148 string = rpc_error_to_category(code);
1149 break;
1150 }
1151
1152 return string;
1153}
1154
1155void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError, const char* fkt,
1156 const char* file, int line)
1157{
1158 WINPR_ASSERT(context);
1159 WINPR_ASSERT(line >= 0);
1160
1161 if (lastError)
1162 {
1163 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1164 {
1165 WLog_PrintTextMessage(context->log, WLOG_ERROR, (size_t)line, file, fkt,
1166 "%s [0x%08" PRIX32 "]", freerdp_get_last_error_name(lastError),
1167 lastError);
1168 }
1169 }
1170
1171 if (lastError == FREERDP_ERROR_SUCCESS)
1172 {
1173 if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1174 WLog_PrintTextMessage(context->log, WLOG_DEBUG, (size_t)line, file, fkt,
1175 "resetting error state");
1176 }
1177 else if (context->LastError != FREERDP_ERROR_SUCCESS)
1178 {
1179 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1180 {
1181 WLog_PrintTextMessage(context->log, WLOG_ERROR, (size_t)line, file, fkt,
1182 "TODO: Trying to set error code %s, but %s already set!",
1183 freerdp_get_last_error_name(lastError),
1184 freerdp_get_last_error_name(context->LastError));
1185 }
1186 }
1187 context->LastError = lastError;
1188}
1189
1190const char* freerdp_get_logon_error_info_type_ex(UINT32 type, char* buffer, size_t size)
1191{
1192 const char* str = freerdp_get_logon_error_info_type(type);
1193 (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, type);
1194 return buffer;
1195}
1196
1197const char* freerdp_get_logon_error_info_type(UINT32 type)
1198{
1199#define CASE_ENTRY(x) \
1200 case x: \
1201 return #x
1202 switch (type)
1203 {
1204 CASE_ENTRY(LOGON_MSG_SESSION_BUSY_OPTIONS);
1205 CASE_ENTRY(LOGON_MSG_DISCONNECT_REFUSED);
1206 CASE_ENTRY(LOGON_MSG_NO_PERMISSION);
1207 CASE_ENTRY(LOGON_MSG_BUMP_OPTIONS);
1208 CASE_ENTRY(LOGON_MSG_RECONNECT_OPTIONS);
1209 CASE_ENTRY(LOGON_MSG_SESSION_TERMINATE);
1210 CASE_ENTRY(LOGON_MSG_SESSION_CONTINUE);
1211 CASE_ENTRY(ERROR_CODE_ACCESS_DENIED);
1212
1213 default:
1214 return "UNKNOWN";
1215 }
1216#undef CASE_ENTRY
1217}
1218
1219const char* freerdp_get_logon_error_info_data(UINT32 data)
1220{
1221 switch (data)
1222 {
1223 case LOGON_FAILED_BAD_PASSWORD:
1224 return "LOGON_FAILED_BAD_PASSWORD";
1225
1226 case LOGON_FAILED_UPDATE_PASSWORD:
1227 return "LOGON_FAILED_UPDATE_PASSWORD";
1228
1229 case LOGON_FAILED_OTHER:
1230 return "LOGON_FAILED_OTHER";
1231
1232 case LOGON_WARNING:
1233 return "LOGON_WARNING";
1234
1235 default:
1236 return "SESSION_ID";
1237 }
1238}
1239
1240const char* freerdp_get_logon_error_info_data_ex(UINT32 data, char* buffer, size_t size)
1241{
1242 const char* str = freerdp_get_logon_error_info_data(data);
1243 (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, data);
1244 return buffer;
1245}
1246
1250freerdp* freerdp_new(void)
1251{
1252 freerdp* instance = nullptr;
1253 instance = (freerdp*)calloc(1, sizeof(freerdp));
1254
1255 if (!instance)
1256 return nullptr;
1257
1258 instance->ContextSize = sizeof(rdpContext);
1259 instance->SendChannelData = freerdp_send_channel_data;
1260 instance->SendChannelPacket = freerdp_send_channel_packet;
1261 instance->ReceiveChannelData = freerdp_channels_data;
1262 return instance;
1263}
1264
1269void freerdp_free(freerdp* instance)
1270{
1271 free(instance);
1272}
1273
1274ULONG freerdp_get_transport_sent(const rdpContext* context, BOOL resetCount)
1275{
1276 WINPR_ASSERT(context);
1277 WINPR_ASSERT(context->rdp);
1278 UINT64 rc = transport_get_bytes_sent(context->rdp->transport, resetCount);
1279 return WINPR_CXX_COMPAT_CAST(ULONG, MIN(rc, UINT32_MAX));
1280}
1281
1282BOOL freerdp_nla_impersonate(rdpContext* context)
1283{
1284 rdpNla* nla = nullptr;
1285
1286 if (!context)
1287 return FALSE;
1288
1289 if (!context->rdp)
1290 return FALSE;
1291
1292 if (!context->rdp->transport)
1293 return FALSE;
1294
1295 nla = transport_get_nla(context->rdp->transport);
1296 return nla_impersonate(nla);
1297}
1298
1299BOOL freerdp_nla_revert_to_self(rdpContext* context)
1300{
1301 rdpNla* nla = nullptr;
1302
1303 if (!context)
1304 return FALSE;
1305
1306 if (!context->rdp)
1307 return FALSE;
1308
1309 if (!context->rdp->transport)
1310 return FALSE;
1311
1312 nla = transport_get_nla(context->rdp->transport);
1313 return nla_revert_to_self(nla);
1314}
1315
1316UINT32 freerdp_get_nla_sspi_error(const rdpContext* context)
1317{
1318 WINPR_ASSERT(context);
1319 WINPR_ASSERT(context->rdp);
1320 WINPR_ASSERT(context->rdp->transport);
1321
1322 rdpNla* nla = transport_get_nla(context->rdp->transport);
1323 return (UINT32)nla_get_sspi_error(nla);
1324}
1325
1326BOOL freerdp_nla_encrypt(rdpContext* context, const SecBuffer* inBuffer, SecBuffer* outBuffer)
1327{
1328 WINPR_ASSERT(context);
1329 WINPR_ASSERT(context->rdp);
1330
1331 rdpNla* nla = context->rdp->nla;
1332 return nla_encrypt(nla, inBuffer, outBuffer);
1333}
1334
1335BOOL freerdp_nla_decrypt(rdpContext* context, const SecBuffer* inBuffer, SecBuffer* outBuffer)
1336{
1337 WINPR_ASSERT(context);
1338 WINPR_ASSERT(context->rdp);
1339
1340 rdpNla* nla = context->rdp->nla;
1341 return nla_decrypt(nla, inBuffer, outBuffer);
1342}
1343
1344SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ulAttr, PVOID pBuffer)
1345{
1346 WINPR_ASSERT(context);
1347 WINPR_ASSERT(context->rdp);
1348
1349 rdpNla* nla = context->rdp->nla;
1350 if (!nla)
1351 nla = transport_get_nla(context->rdp->transport);
1352
1353 WINPR_ASSERT(nla);
1354
1355 return nla_QueryContextAttributes(nla, ulAttr, pBuffer);
1356}
1357
1358SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, PVOID pBuffer)
1359{
1360 WINPR_ASSERT(context);
1361 WINPR_ASSERT(context->rdp);
1362
1363 rdpNla* nla = context->rdp->nla;
1364 if (!nla)
1365 nla = transport_get_nla(context->rdp->transport);
1366
1367 WINPR_ASSERT(nla);
1368
1369 return nla_FreeContextBuffer(nla, pBuffer);
1370}
1371
1372HANDLE getChannelErrorEventHandle(rdpContext* context)
1373{
1374 WINPR_ASSERT(context);
1375 return context->channelErrorEvent;
1376}
1377
1378BOOL checkChannelErrorEvent(rdpContext* context)
1379{
1380 WINPR_ASSERT(context);
1381
1382 if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1383 {
1384 WLog_Print(context->log, WLOG_ERROR, "%s. Error was %" PRIu32 "", context->errorDescription,
1385 context->channelErrorNum);
1386 return FALSE;
1387 }
1388
1389 return TRUE;
1390}
1391
1397UINT getChannelError(const rdpContext* context)
1398{
1399 WINPR_ASSERT(context);
1400 return context->channelErrorNum;
1401}
1402
1403const char* getChannelErrorDescription(const rdpContext* context)
1404{
1405 WINPR_ASSERT(context);
1406 return context->errorDescription;
1407}
1408
1409void clearChannelError(rdpContext* context)
1410{
1411 WINPR_ASSERT(context);
1412 context->channelErrorNum = 0;
1413 memset(context->errorDescription, 0, 500);
1414 (void)ResetEvent(context->channelErrorEvent);
1415}
1416
1417WINPR_ATTR_FORMAT_ARG(3, 4)
1418void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const char* format, ...)
1419{
1420 va_list ap = WINPR_C_ARRAY_INIT;
1421 va_start(ap, format);
1422
1423 WINPR_ASSERT(context);
1424
1425 context->channelErrorNum = errorNum;
1426 (void)vsnprintf(context->errorDescription, 499, format, ap);
1427 va_end(ap);
1428 (void)SetEvent(context->channelErrorEvent);
1429}
1430
1431const char* freerdp_nego_get_routing_token(const rdpContext* context, DWORD* length)
1432{
1433 if (!context || !context->rdp)
1434 return nullptr;
1435
1436 return (const char*)nego_get_routing_token(context->rdp->nego, length);
1437}
1438
1439BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1440{
1441 WINPR_ASSERT(context);
1442 return rdp_io_callback_set_event(context->rdp, set);
1443}
1444
1445const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1446{
1447 WINPR_ASSERT(context);
1448 return rdp_get_io_callbacks(context->rdp);
1449}
1450
1451BOOL freerdp_set_io_callbacks(rdpContext* context, const rdpTransportIo* io_callbacks)
1452{
1453 WINPR_ASSERT(context);
1454 return rdp_set_io_callbacks(context->rdp, io_callbacks);
1455}
1456
1457BOOL freerdp_set_io_callback_context(rdpContext* context, void* usercontext)
1458{
1459 WINPR_ASSERT(context);
1460 return rdp_set_io_callback_context(context->rdp, usercontext);
1461}
1462
1463void* freerdp_get_io_callback_context(rdpContext* context)
1464{
1465 WINPR_ASSERT(context);
1466 return rdp_get_io_callback_context(context->rdp);
1467}
1468
1469CONNECTION_STATE freerdp_get_state(const rdpContext* context)
1470{
1471 WINPR_ASSERT(context);
1472 return rdp_get_state(context->rdp);
1473}
1474
1475const char* freerdp_state_string(CONNECTION_STATE state)
1476{
1477 return rdp_state_string(state);
1478}
1479
1480BOOL freerdp_is_active_state(const rdpContext* context)
1481{
1482 WINPR_ASSERT(context);
1483 return rdp_is_active_state(context->rdp);
1484}
1485
1486BOOL freerdp_channels_from_mcs(rdpSettings* settings, const rdpContext* context)
1487{
1488 WINPR_ASSERT(context);
1489 return rdp_channels_from_mcs(settings, context->rdp);
1490}
1491
1492HANDLE freerdp_abort_event(rdpContext* context)
1493{
1494 WINPR_ASSERT(context);
1495 return utils_get_abort_event(context->rdp);
1496}
1497
1498static void test_mcs_free(rdpMcs* mcs)
1499{
1500 if (!mcs)
1501 return;
1502
1503 if (mcs->context)
1504 {
1505 rdpSettings* settings = mcs->context->settings;
1506 freerdp_settings_free(settings);
1507 }
1508 free(mcs->context);
1509
1510 mcs_free(mcs);
1511}
1512
1513static rdpMcs* test_mcs_new(void)
1514{
1515 rdpSettings* settings = freerdp_settings_new(0);
1516 rdpContext* context = calloc(1, sizeof(rdpContext));
1517
1518 if (!settings)
1519 goto fail;
1520 if (!freerdp_settings_set_bool(settings, FreeRDP_TransportDumpReplay, TRUE))
1521 goto fail;
1522
1523 if (!context)
1524 goto fail;
1525 context->settings = settings;
1526 return mcs_new(context);
1527
1528fail:
1529 free(context);
1530 freerdp_settings_free(settings);
1531
1532 return nullptr;
1533}
1534
1535BOOL freerdp_is_valid_mcs_create_request(const BYTE* data, size_t size)
1536{
1537
1538 wStream sbuffer = WINPR_C_ARRAY_INIT;
1539 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1540
1541 WINPR_ASSERT(data || (size == 0));
1542 WINPR_ASSERT(s);
1543
1544 rdpMcs* mcs = test_mcs_new();
1545 WINPR_ASSERT(mcs);
1546
1547 BOOL result = mcs_recv_connect_initial(mcs, s);
1548 test_mcs_free(mcs);
1549 return result;
1550}
1551
1552BOOL freerdp_is_valid_mcs_create_response(const BYTE* data, size_t size)
1553{
1554
1555 wStream sbuffer = WINPR_C_ARRAY_INIT;
1556 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1557
1558 WINPR_ASSERT(data || (size == 0));
1559 WINPR_ASSERT(s);
1560
1561 rdpMcs* mcs = test_mcs_new();
1562 WINPR_ASSERT(mcs);
1563
1564 BOOL result = mcs_recv_connect_response(mcs, s);
1565 test_mcs_free(mcs);
1566 return result;
1567}
1568
1569BOOL freerdp_persist_credentials(rdpContext* context)
1570{
1571 if (!context)
1572 return FALSE;
1573 WINPR_ASSERT(context->rdp);
1574 return utils_persist_credentials(context->rdp->originalSettings, context->rdp->settings);
1575}
1576
1577const char* freerdp_disconnect_reason_string(int reason)
1578{
1579 switch (reason)
1580 {
1581 case Disconnect_Ultimatum_domain_disconnected:
1582 return "rn-domain-disconnected";
1583 case Disconnect_Ultimatum_provider_initiated:
1584 return "rn-provider-initiated";
1585 case Disconnect_Ultimatum_token_purged:
1586 return "rn-token-purged";
1587 case Disconnect_Ultimatum_user_requested:
1588 return "rn-user-requested";
1589 case Disconnect_Ultimatum_channel_purged:
1590 return "rn-channel-purged";
1591 default:
1592 return "rn-unknown";
1593 }
1594}
1595
1596BOOL freerdp_set_common_access_token(rdpContext* context,
1597 pGetCommonAccessToken GetCommonAccessToken)
1598{
1599 WINPR_ASSERT(context);
1600 WINPR_ASSERT(context->rdp);
1601 context->rdp->GetCommonAccessToken = GetCommonAccessToken;
1602 return TRUE;
1603}
1604
1605pGetCommonAccessToken freerdp_get_common_access_token(const rdpContext* context)
1606{
1607 WINPR_ASSERT(context);
1608 WINPR_ASSERT(context->rdp);
1609 return context->rdp->GetCommonAccessToken;
1610}
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 val)
Sets a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL val)
Sets a BOOL settings value.
WINPR_ATTR_NODISCARD FREERDP_API const char * freerdp_settings_get_string(const rdpSettings *settings, FreeRDP_Settings_Keys_String id)
Returns a immutable string settings value.
FREERDP_API void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
WINPR_ATTR_NODISCARD FREERDP_API rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
WINPR_ATTR_NODISCARD FREERDP_API BOOL freerdp_settings_get_bool(const rdpSettings *settings, FreeRDP_Settings_Keys_Bool id)
Returns a boolean settings value.