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