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