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