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