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