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 freerdp_channels_close(instance->context->channels, instance);
647
648 IFCALL(instance->PostFinalDisconnect, instance);
649
650 freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
651 return rc;
652}
653
654#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
655BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
656{
657 WINPR_ASSERT(instance);
658 return freerdp_disconnect_before_reconnect_context(instance->context);
659}
660#endif
661
662BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
663{
664 rdpRdp* rdp = nullptr;
665
666 WINPR_ASSERT(context);
667
668 rdp = context->rdp;
669 return rdp_client_disconnect_and_clear(rdp);
670}
671
672BOOL freerdp_reconnect(freerdp* instance)
673{
674 rdpRdp* rdp = nullptr;
675
676 WINPR_ASSERT(instance);
677 WINPR_ASSERT(instance->context);
678
679 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
680 return FALSE;
681
682 rdp = instance->context->rdp;
683
684 if (!utils_reset_abort(instance->context->rdp))
685 return FALSE;
686 return rdp_client_reconnect(rdp);
687}
688
689#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
690BOOL freerdp_shall_disconnect(const freerdp* instance)
691{
692 if (!instance)
693 return FALSE;
694
695 return freerdp_shall_disconnect_context(instance->context);
696}
697#endif
698
699BOOL freerdp_shall_disconnect_context(const rdpContext* context)
700{
701 if (!context)
702 return FALSE;
703
704 return utils_abort_event_is_set(context->rdp);
705}
706
707BOOL freerdp_focus_required(freerdp* instance)
708{
709 rdpRdp* rdp = nullptr;
710 BOOL bRetCode = FALSE;
711
712 WINPR_ASSERT(instance);
713 WINPR_ASSERT(instance->context);
714
715 rdp = instance->context->rdp;
716 WINPR_ASSERT(rdp);
717
718 if (rdp->resendFocus)
719 {
720 bRetCode = TRUE;
721 rdp->resendFocus = FALSE;
722 }
723
724 return bRetCode;
725}
726
727void freerdp_set_focus(freerdp* instance)
728{
729 rdpRdp* rdp = nullptr;
730
731 WINPR_ASSERT(instance);
732 WINPR_ASSERT(instance->context);
733
734 rdp = instance->context->rdp;
735 WINPR_ASSERT(rdp);
736
737 rdp->resendFocus = TRUE;
738}
739
740void freerdp_get_version(int* major, int* minor, int* revision)
741{
742 if (major != nullptr)
743 *major = FREERDP_VERSION_MAJOR;
744
745 if (minor != nullptr)
746 *minor = FREERDP_VERSION_MINOR;
747
748 if (revision != nullptr)
749 *revision = FREERDP_VERSION_REVISION;
750}
751
752const char* freerdp_get_version_string(void)
753{
754 return FREERDP_VERSION_FULL;
755}
756
757const char* freerdp_get_build_config(void)
758{
759 WINPR_PRAGMA_DIAG_PUSH
760 WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
761 static const char build_config[] =
762 "Build configuration: " FREERDP_BUILD_CONFIG "\n"
763 "Build type: " FREERDP_BUILD_TYPE "\n"
764 "CFLAGS: " FREERDP_CFLAGS "\n"
765 "Compiler: " FREERDP_COMPILER_ID ", " FREERDP_COMPILER_VERSION "\n"
766 "Target architecture: " FREERDP_TARGET_ARCH "\n";
767 WINPR_PRAGMA_DIAG_POP
768 return build_config;
769}
770
771const char* freerdp_get_build_revision(void)
772{
773 return FREERDP_GIT_REVISION;
774}
775
776static wEventType FreeRDP_Events[] = {
777 DEFINE_EVENT_ENTRY(WindowStateChange), DEFINE_EVENT_ENTRY(ResizeWindow),
778 DEFINE_EVENT_ENTRY(LocalResizeWindow), DEFINE_EVENT_ENTRY(EmbedWindow),
779 DEFINE_EVENT_ENTRY(PanningChange), DEFINE_EVENT_ENTRY(ZoomingChange),
780 DEFINE_EVENT_ENTRY(ErrorInfo), DEFINE_EVENT_ENTRY(Terminate),
781 DEFINE_EVENT_ENTRY(ConnectionResult), DEFINE_EVENT_ENTRY(ChannelConnected),
782 DEFINE_EVENT_ENTRY(ChannelDisconnected), DEFINE_EVENT_ENTRY(MouseEvent),
783 DEFINE_EVENT_ENTRY(Activated), DEFINE_EVENT_ENTRY(Timer),
784 DEFINE_EVENT_ENTRY(GraphicsReset)
785};
786
797BOOL freerdp_context_new(freerdp* instance)
798{
799 return freerdp_context_new_ex(instance, nullptr);
800}
801
802static BOOL freerdp_common_context(rdpContext* context, AccessTokenType tokenType, char** token,
803 size_t count, ...)
804{
805 BOOL rc = FALSE;
806
807 WINPR_ASSERT(context);
808 if (!context->instance || !context->instance->GetAccessToken)
809 return TRUE;
810
811 va_list ap = WINPR_C_ARRAY_INIT;
812 va_start(ap, count);
813 switch (tokenType)
814 {
815 case ACCESS_TOKEN_TYPE_AAD:
816 if (count != 2)
817 {
818 WLog_ERR(TAG,
819 "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
820 ", aborting",
821 count);
822 }
823 else
824 {
825 const char* scope = va_arg(ap, const char*);
826 const char* req_cnf = va_arg(ap, const char*);
827 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count,
828 scope, req_cnf);
829 }
830 break;
831 case ACCESS_TOKEN_TYPE_AVD:
832 if (count != 0)
833 {
834 WLog_WARN(TAG,
835 "ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
836 ", ignoring",
837 count);
838 }
839 else
840 {
841 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count);
842 }
843 break;
844 default:
845 break;
846 }
847 va_end(ap);
848
849 if (!rc)
850 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
851
852 return rc;
853}
854
855BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
856{
857 rdpRdp* rdp = nullptr;
858 rdpContext* context = nullptr;
859 BOOL ret = TRUE;
860
861 WINPR_ASSERT(instance);
862
863 instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
864
865 if (!context)
866 return FALSE;
867
868 context->log = WLog_Get(TAG);
869 if (!context->log)
870 goto fail;
871
872 /* Set to external settings, prevents rdp_new from creating its own instance */
873 context->settings = settings;
874 context->instance = instance;
875 context->ServerMode = FALSE;
876 context->disconnectUltimatum = 0;
877
878 context->metrics = metrics_new(context);
879
880 if (!context->metrics)
881 goto fail;
882
883 rdp = rdp_new(context);
884
885 if (!rdp)
886 goto fail;
887
888 context->rdp = rdp;
889 context->pubSub = rdp->pubSub;
890
891 if (!context->pubSub)
892 goto fail;
893
894 PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
895
896#if defined(WITH_FREERDP_DEPRECATED)
897 instance->input = rdp->input;
898 instance->update = rdp->update;
899 instance->settings = rdp->settings;
900 instance->autodetect = rdp->autodetect;
901#endif
902
903 instance->heartbeat = rdp->heartbeat;
904 context->graphics = graphics_new(context);
905
906 if (!context->graphics)
907 goto fail;
908
909 context->input = rdp->input;
910 context->update = rdp->update;
911 context->settings = rdp->settings;
912 context->autodetect = rdp->autodetect;
913
914 if (!(context->errorDescription = calloc(1, 500)))
915 {
916 WLog_Print(context->log, WLOG_ERROR, "calloc failed!");
917 goto fail;
918 }
919
920 if (!(context->channelErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
921 {
922 WLog_Print(context->log, WLOG_ERROR, "CreateEvent failed!");
923 goto fail;
924 }
925
926 update_register_client_callbacks(rdp->update);
927
928 if (!(context->channels = freerdp_channels_new(instance)))
929 goto fail;
930
931 context->dump = stream_dump_new();
932 if (!context->dump)
933 goto fail;
934
935 /* Fallback:
936 * Client common library might set a function pointer to handle this, but here we provide a
937 * default implementation that simply calls instance->GetAccessToken.
938 */
939 if (!freerdp_set_common_access_token(context, freerdp_common_context))
940 goto fail;
941
942 IFCALLRET(instance->ContextNew, ret, instance, context);
943
944 if (!ret)
945 goto fail;
946
947 return TRUE;
948
949fail:
950 freerdp_context_free(instance);
951 return FALSE;
952}
953
954BOOL freerdp_context_reset(freerdp* instance)
955{
956 if (!instance)
957 return FALSE;
958
959 WINPR_ASSERT(instance->context);
960 rdpRdp* rdp = instance->context->rdp;
961
962 return rdp_reset_runtime_settings(rdp);
963}
964
973void freerdp_context_free(freerdp* instance)
974{
975 rdpContext* ctx = nullptr;
976
977 if (!instance)
978 return;
979
980 if (!instance->context)
981 return;
982
983 ctx = instance->context;
984
985 IFCALL(instance->ContextFree, instance, ctx);
986 rdp_free(ctx->rdp);
987 ctx->rdp = nullptr;
988 ctx->settings = nullptr; /* owned by rdpRdp */
989
990 graphics_free(ctx->graphics);
991 ctx->graphics = nullptr;
992
993 metrics_free(ctx->metrics);
994 ctx->metrics = nullptr;
995
996 if (ctx->channelErrorEvent)
997 (void)CloseHandle(ctx->channelErrorEvent);
998 ctx->channelErrorEvent = nullptr;
999
1000 free(ctx->errorDescription);
1001 ctx->errorDescription = nullptr;
1002
1003 freerdp_channels_free(ctx->channels);
1004 ctx->channels = nullptr;
1005
1006 freerdp_client_codecs_free(ctx->codecs);
1007 ctx->codecs = nullptr;
1008
1009 stream_dump_free(ctx->dump);
1010 ctx->dump = nullptr;
1011
1012 ctx->input = nullptr; /* owned by rdpRdp */
1013 ctx->update = nullptr; /* owned by rdpRdp */
1014 ctx->settings = nullptr; /* owned by rdpRdp */
1015 ctx->autodetect = nullptr; /* owned by rdpRdp */
1016
1017 free(ctx);
1018 instance->context = nullptr;
1019#if defined(WITH_FREERDP_DEPRECATED)
1020 instance->input = nullptr; /* owned by rdpRdp */
1021 instance->update = nullptr; /* owned by rdpRdp */
1022 instance->settings = nullptr; /* owned by rdpRdp */
1023 instance->autodetect = nullptr; /* owned by rdpRdp */
1024#endif
1025 instance->heartbeat = nullptr; /* owned by rdpRdp */
1026}
1027
1028int freerdp_get_disconnect_ultimatum(const rdpContext* context)
1029{
1030 WINPR_ASSERT(context);
1031 return context->disconnectUltimatum;
1032}
1033
1034UINT32 freerdp_error_info(const freerdp* instance)
1035{
1036 WINPR_ASSERT(instance);
1037 WINPR_ASSERT(instance->context);
1038 WINPR_ASSERT(instance->context->rdp);
1039 return instance->context->rdp->errorInfo;
1040}
1041
1042void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
1043{
1044 if (!rdp)
1045 return;
1046
1047 rdp_set_error_info(rdp, error);
1048}
1049
1050BOOL freerdp_send_error_info(rdpRdp* rdp)
1051{
1052 if (!rdp)
1053 return FALSE;
1054
1055 return rdp_send_error_info(rdp);
1056}
1057
1058UINT32 freerdp_get_last_error(const rdpContext* context)
1059{
1060 WINPR_ASSERT(context);
1061 return context->LastError;
1062}
1063
1064const char* freerdp_get_last_error_name(UINT32 code)
1065{
1066 const char* name = nullptr;
1067 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1068 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1069
1070 switch (cls)
1071 {
1072 case FREERDP_ERROR_ERRBASE_CLASS:
1073 name = freerdp_get_error_base_name(type);
1074 break;
1075
1076 case FREERDP_ERROR_ERRINFO_CLASS:
1077 name = freerdp_get_error_info_name(type);
1078 break;
1079
1080 case FREERDP_ERROR_CONNECT_CLASS:
1081 name = freerdp_get_error_connect_name(type);
1082 break;
1083
1084 default:
1085 name = rpc_error_to_string(code);
1086 break;
1087 }
1088
1089 return name;
1090}
1091
1092const char* freerdp_get_last_error_string(UINT32 code)
1093{
1094 const char* string = nullptr;
1095 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1096 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1097
1098 switch (cls)
1099 {
1100 case FREERDP_ERROR_ERRBASE_CLASS:
1101 string = freerdp_get_error_base_string(type);
1102 break;
1103
1104 case FREERDP_ERROR_ERRINFO_CLASS:
1105 string = freerdp_get_error_info_string(type);
1106 break;
1107
1108 case FREERDP_ERROR_CONNECT_CLASS:
1109 string = freerdp_get_error_connect_string(type);
1110 break;
1111
1112 default:
1113 string = rpc_error_to_string(code);
1114 break;
1115 }
1116
1117 return string;
1118}
1119
1120const char* freerdp_get_last_error_category(UINT32 code)
1121{
1122 const char* string = nullptr;
1123 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1124 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1125
1126 switch (cls)
1127 {
1128 case FREERDP_ERROR_ERRBASE_CLASS:
1129 string = freerdp_get_error_base_category(type);
1130 break;
1131
1132 case FREERDP_ERROR_ERRINFO_CLASS:
1133 string = freerdp_get_error_info_category(type);
1134 break;
1135
1136 case FREERDP_ERROR_CONNECT_CLASS:
1137 string = freerdp_get_error_connect_category(type);
1138 break;
1139
1140 default:
1141 string = rpc_error_to_category(code);
1142 break;
1143 }
1144
1145 return string;
1146}
1147
1148void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError, const char* fkt,
1149 const char* file, int line)
1150{
1151 WINPR_ASSERT(context);
1152 WINPR_ASSERT(line >= 0);
1153
1154 if (lastError)
1155 {
1156 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1157 {
1158 WLog_PrintTextMessage(context->log, WLOG_ERROR, (size_t)line, file, fkt,
1159 "%s [0x%08" PRIX32 "]", freerdp_get_last_error_name(lastError),
1160 lastError);
1161 }
1162 }
1163
1164 if (lastError == FREERDP_ERROR_SUCCESS)
1165 {
1166 if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1167 WLog_PrintTextMessage(context->log, WLOG_DEBUG, (size_t)line, file, fkt,
1168 "resetting error state");
1169 }
1170 else if (context->LastError != FREERDP_ERROR_SUCCESS)
1171 {
1172 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1173 {
1174 WLog_PrintTextMessage(context->log, WLOG_ERROR, (size_t)line, file, fkt,
1175 "TODO: Trying to set error code %s, but %s already set!",
1176 freerdp_get_last_error_name(lastError),
1177 freerdp_get_last_error_name(context->LastError));
1178 }
1179 }
1180 context->LastError = lastError;
1181}
1182
1183const char* freerdp_get_logon_error_info_type_ex(UINT32 type, char* buffer, size_t size)
1184{
1185 const char* str = freerdp_get_logon_error_info_type(type);
1186 (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, type);
1187 return buffer;
1188}
1189
1190const char* freerdp_get_logon_error_info_type(UINT32 type)
1191{
1192#define CASE_ENTRY(x) \
1193 case x: \
1194 return #x
1195 switch (type)
1196 {
1197 CASE_ENTRY(LOGON_MSG_SESSION_BUSY_OPTIONS);
1198 CASE_ENTRY(LOGON_MSG_DISCONNECT_REFUSED);
1199 CASE_ENTRY(LOGON_MSG_NO_PERMISSION);
1200 CASE_ENTRY(LOGON_MSG_BUMP_OPTIONS);
1201 CASE_ENTRY(LOGON_MSG_RECONNECT_OPTIONS);
1202 CASE_ENTRY(LOGON_MSG_SESSION_TERMINATE);
1203 CASE_ENTRY(LOGON_MSG_SESSION_CONTINUE);
1204 CASE_ENTRY(ERROR_CODE_ACCESS_DENIED);
1205
1206 default:
1207 return "UNKNOWN";
1208 }
1209#undef CASE_ENTRY
1210}
1211
1212const char* freerdp_get_logon_error_info_data(UINT32 data)
1213{
1214 switch (data)
1215 {
1216 case LOGON_FAILED_BAD_PASSWORD:
1217 return "LOGON_FAILED_BAD_PASSWORD";
1218
1219 case LOGON_FAILED_UPDATE_PASSWORD:
1220 return "LOGON_FAILED_UPDATE_PASSWORD";
1221
1222 case LOGON_FAILED_OTHER:
1223 return "LOGON_FAILED_OTHER";
1224
1225 case LOGON_WARNING:
1226 return "LOGON_WARNING";
1227
1228 default:
1229 return "SESSION_ID";
1230 }
1231}
1232
1233const char* freerdp_get_logon_error_info_data_ex(UINT32 data, char* buffer, size_t size)
1234{
1235 const char* str = freerdp_get_logon_error_info_data(data);
1236 (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, data);
1237 return buffer;
1238}
1239
1243freerdp* freerdp_new(void)
1244{
1245 freerdp* instance = nullptr;
1246 instance = (freerdp*)calloc(1, sizeof(freerdp));
1247
1248 if (!instance)
1249 return nullptr;
1250
1251 instance->ContextSize = sizeof(rdpContext);
1252 instance->SendChannelData = freerdp_send_channel_data;
1253 instance->SendChannelPacket = freerdp_send_channel_packet;
1254 instance->ReceiveChannelData = freerdp_channels_data;
1255 return instance;
1256}
1257
1262void freerdp_free(freerdp* instance)
1263{
1264 free(instance);
1265}
1266
1267ULONG freerdp_get_transport_sent(const rdpContext* context, BOOL resetCount)
1268{
1269 WINPR_ASSERT(context);
1270 WINPR_ASSERT(context->rdp);
1271 UINT64 rc = transport_get_bytes_sent(context->rdp->transport, resetCount);
1272 return WINPR_CXX_COMPAT_CAST(ULONG, MIN(rc, UINT32_MAX));
1273}
1274
1275BOOL freerdp_nla_impersonate(rdpContext* context)
1276{
1277 rdpNla* nla = nullptr;
1278
1279 if (!context)
1280 return FALSE;
1281
1282 if (!context->rdp)
1283 return FALSE;
1284
1285 if (!context->rdp->transport)
1286 return FALSE;
1287
1288 nla = transport_get_nla(context->rdp->transport);
1289 return nla_impersonate(nla);
1290}
1291
1292BOOL freerdp_nla_revert_to_self(rdpContext* context)
1293{
1294 rdpNla* nla = nullptr;
1295
1296 if (!context)
1297 return FALSE;
1298
1299 if (!context->rdp)
1300 return FALSE;
1301
1302 if (!context->rdp->transport)
1303 return FALSE;
1304
1305 nla = transport_get_nla(context->rdp->transport);
1306 return nla_revert_to_self(nla);
1307}
1308
1309UINT32 freerdp_get_nla_sspi_error(const rdpContext* context)
1310{
1311 WINPR_ASSERT(context);
1312 WINPR_ASSERT(context->rdp);
1313 WINPR_ASSERT(context->rdp->transport);
1314
1315 rdpNla* nla = transport_get_nla(context->rdp->transport);
1316 return (UINT32)nla_get_sspi_error(nla);
1317}
1318
1319BOOL freerdp_nla_encrypt(rdpContext* context, const SecBuffer* inBuffer, SecBuffer* outBuffer)
1320{
1321 WINPR_ASSERT(context);
1322 WINPR_ASSERT(context->rdp);
1323
1324 rdpNla* nla = context->rdp->nla;
1325 return nla_encrypt(nla, inBuffer, outBuffer);
1326}
1327
1328BOOL freerdp_nla_decrypt(rdpContext* context, const SecBuffer* inBuffer, SecBuffer* outBuffer)
1329{
1330 WINPR_ASSERT(context);
1331 WINPR_ASSERT(context->rdp);
1332
1333 rdpNla* nla = context->rdp->nla;
1334 return nla_decrypt(nla, inBuffer, outBuffer);
1335}
1336
1337SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ulAttr, PVOID pBuffer)
1338{
1339 WINPR_ASSERT(context);
1340 WINPR_ASSERT(context->rdp);
1341
1342 rdpNla* nla = context->rdp->nla;
1343 if (!nla)
1344 nla = transport_get_nla(context->rdp->transport);
1345
1346 WINPR_ASSERT(nla);
1347
1348 return nla_QueryContextAttributes(nla, ulAttr, pBuffer);
1349}
1350
1351SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, PVOID pBuffer)
1352{
1353 WINPR_ASSERT(context);
1354 WINPR_ASSERT(context->rdp);
1355
1356 rdpNla* nla = context->rdp->nla;
1357 if (!nla)
1358 nla = transport_get_nla(context->rdp->transport);
1359
1360 WINPR_ASSERT(nla);
1361
1362 return nla_FreeContextBuffer(nla, pBuffer);
1363}
1364
1365HANDLE getChannelErrorEventHandle(rdpContext* context)
1366{
1367 WINPR_ASSERT(context);
1368 return context->channelErrorEvent;
1369}
1370
1371BOOL checkChannelErrorEvent(rdpContext* context)
1372{
1373 WINPR_ASSERT(context);
1374
1375 if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1376 {
1377 WLog_Print(context->log, WLOG_ERROR, "%s. Error was %" PRIu32 "", context->errorDescription,
1378 context->channelErrorNum);
1379 return FALSE;
1380 }
1381
1382 return TRUE;
1383}
1384
1390UINT getChannelError(const rdpContext* context)
1391{
1392 WINPR_ASSERT(context);
1393 return context->channelErrorNum;
1394}
1395
1396const char* getChannelErrorDescription(const rdpContext* context)
1397{
1398 WINPR_ASSERT(context);
1399 return context->errorDescription;
1400}
1401
1402void clearChannelError(rdpContext* context)
1403{
1404 WINPR_ASSERT(context);
1405 context->channelErrorNum = 0;
1406 memset(context->errorDescription, 0, 500);
1407 (void)ResetEvent(context->channelErrorEvent);
1408}
1409
1410WINPR_ATTR_FORMAT_ARG(3, 4)
1411void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const char* format, ...)
1412{
1413 va_list ap = WINPR_C_ARRAY_INIT;
1414 va_start(ap, format);
1415
1416 WINPR_ASSERT(context);
1417
1418 context->channelErrorNum = errorNum;
1419 (void)vsnprintf(context->errorDescription, 499, format, ap);
1420 va_end(ap);
1421 (void)SetEvent(context->channelErrorEvent);
1422}
1423
1424const char* freerdp_nego_get_routing_token(const rdpContext* context, DWORD* length)
1425{
1426 if (!context || !context->rdp)
1427 return nullptr;
1428
1429 return (const char*)nego_get_routing_token(context->rdp->nego, length);
1430}
1431
1432BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1433{
1434 WINPR_ASSERT(context);
1435 return rdp_io_callback_set_event(context->rdp, set);
1436}
1437
1438const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1439{
1440 WINPR_ASSERT(context);
1441 return rdp_get_io_callbacks(context->rdp);
1442}
1443
1444BOOL freerdp_set_io_callbacks(rdpContext* context, const rdpTransportIo* io_callbacks)
1445{
1446 WINPR_ASSERT(context);
1447 return rdp_set_io_callbacks(context->rdp, io_callbacks);
1448}
1449
1450BOOL freerdp_set_io_callback_context(rdpContext* context, void* usercontext)
1451{
1452 WINPR_ASSERT(context);
1453 return rdp_set_io_callback_context(context->rdp, usercontext);
1454}
1455
1456void* freerdp_get_io_callback_context(rdpContext* context)
1457{
1458 WINPR_ASSERT(context);
1459 return rdp_get_io_callback_context(context->rdp);
1460}
1461
1462CONNECTION_STATE freerdp_get_state(const rdpContext* context)
1463{
1464 WINPR_ASSERT(context);
1465 return rdp_get_state(context->rdp);
1466}
1467
1468const char* freerdp_state_string(CONNECTION_STATE state)
1469{
1470 return rdp_state_string(state);
1471}
1472
1473BOOL freerdp_is_active_state(const rdpContext* context)
1474{
1475 WINPR_ASSERT(context);
1476 return rdp_is_active_state(context->rdp);
1477}
1478
1479BOOL freerdp_channels_from_mcs(rdpSettings* settings, const rdpContext* context)
1480{
1481 WINPR_ASSERT(context);
1482 return rdp_channels_from_mcs(settings, context->rdp);
1483}
1484
1485HANDLE freerdp_abort_event(rdpContext* context)
1486{
1487 WINPR_ASSERT(context);
1488 return utils_get_abort_event(context->rdp);
1489}
1490
1491static void test_mcs_free(rdpMcs* mcs)
1492{
1493 if (!mcs)
1494 return;
1495
1496 if (mcs->context)
1497 {
1498 rdpSettings* settings = mcs->context->settings;
1499 freerdp_settings_free(settings);
1500 }
1501 free(mcs->context);
1502
1503 mcs_free(mcs);
1504}
1505
1506static rdpMcs* test_mcs_new(void)
1507{
1508 rdpSettings* settings = freerdp_settings_new(0);
1509 rdpContext* context = calloc(1, sizeof(rdpContext));
1510
1511 if (!settings)
1512 goto fail;
1513 if (!freerdp_settings_set_bool(settings, FreeRDP_TransportDumpReplay, TRUE))
1514 goto fail;
1515
1516 if (!context)
1517 goto fail;
1518 context->settings = settings;
1519 return mcs_new(context);
1520
1521fail:
1522 free(context);
1523 freerdp_settings_free(settings);
1524
1525 return nullptr;
1526}
1527
1528BOOL freerdp_is_valid_mcs_create_request(const BYTE* data, size_t size)
1529{
1530
1531 wStream sbuffer = WINPR_C_ARRAY_INIT;
1532 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1533
1534 WINPR_ASSERT(data || (size == 0));
1535 WINPR_ASSERT(s);
1536
1537 rdpMcs* mcs = test_mcs_new();
1538 WINPR_ASSERT(mcs);
1539
1540 BOOL result = mcs_recv_connect_initial(mcs, s);
1541 test_mcs_free(mcs);
1542 return result;
1543}
1544
1545BOOL freerdp_is_valid_mcs_create_response(const BYTE* data, size_t size)
1546{
1547
1548 wStream sbuffer = WINPR_C_ARRAY_INIT;
1549 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1550
1551 WINPR_ASSERT(data || (size == 0));
1552 WINPR_ASSERT(s);
1553
1554 rdpMcs* mcs = test_mcs_new();
1555 WINPR_ASSERT(mcs);
1556
1557 BOOL result = mcs_recv_connect_response(mcs, s);
1558 test_mcs_free(mcs);
1559 return result;
1560}
1561
1562BOOL freerdp_persist_credentials(rdpContext* context)
1563{
1564 if (!context)
1565 return FALSE;
1566 WINPR_ASSERT(context->rdp);
1567 return utils_persist_credentials(context->rdp->originalSettings, context->rdp->settings);
1568}
1569
1570const char* freerdp_disconnect_reason_string(int reason)
1571{
1572 switch (reason)
1573 {
1574 case Disconnect_Ultimatum_domain_disconnected:
1575 return "rn-domain-disconnected";
1576 case Disconnect_Ultimatum_provider_initiated:
1577 return "rn-provider-initiated";
1578 case Disconnect_Ultimatum_token_purged:
1579 return "rn-token-purged";
1580 case Disconnect_Ultimatum_user_requested:
1581 return "rn-user-requested";
1582 case Disconnect_Ultimatum_channel_purged:
1583 return "rn-channel-purged";
1584 default:
1585 return "rn-unknown";
1586 }
1587}
1588
1589BOOL freerdp_set_common_access_token(rdpContext* context,
1590 pGetCommonAccessToken GetCommonAccessToken)
1591{
1592 WINPR_ASSERT(context);
1593 WINPR_ASSERT(context->rdp);
1594 context->rdp->GetCommonAccessToken = GetCommonAccessToken;
1595 return TRUE;
1596}
1597
1598pGetCommonAccessToken freerdp_get_common_access_token(const rdpContext* context)
1599{
1600 WINPR_ASSERT(context);
1601 WINPR_ASSERT(context->rdp);
1602 return context->rdp->GetCommonAccessToken;
1603}
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.