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