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 update_dump_stats(rdp->update);
647 if (up->pcap_rfx)
648 {
649 up->dump_rfx = FALSE;
650 pcap_close(up->pcap_rfx);
651 up->pcap_rfx = nullptr;
652 }
653 }
654
655 if (instance->context->channels)
656 freerdp_channels_close(instance->context->channels, instance);
657
658 IFCALL(instance->PostFinalDisconnect, instance);
659
660 freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
661 return rc;
662}
663
664#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
665BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
666{
667 WINPR_ASSERT(instance);
668 return freerdp_disconnect_before_reconnect_context(instance->context);
669}
670#endif
671
672BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
673{
674 rdpRdp* rdp = nullptr;
675
676 WINPR_ASSERT(context);
677
678 rdp = context->rdp;
679 return rdp_client_disconnect_and_clear(rdp);
680}
681
682BOOL freerdp_reconnect(freerdp* instance)
683{
684 rdpRdp* rdp = nullptr;
685
686 WINPR_ASSERT(instance);
687 WINPR_ASSERT(instance->context);
688
689 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
690 return FALSE;
691
692 rdp = instance->context->rdp;
693
694 if (!utils_reset_abort(instance->context->rdp))
695 return FALSE;
696 return rdp_client_reconnect(rdp);
697}
698
699#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
700BOOL freerdp_shall_disconnect(const freerdp* instance)
701{
702 if (!instance)
703 return FALSE;
704
705 return freerdp_shall_disconnect_context(instance->context);
706}
707#endif
708
709BOOL freerdp_shall_disconnect_context(const rdpContext* context)
710{
711 if (!context)
712 return FALSE;
713
714 return utils_abort_event_is_set(context->rdp);
715}
716
717BOOL freerdp_focus_required(freerdp* instance)
718{
719 rdpRdp* rdp = nullptr;
720 BOOL bRetCode = FALSE;
721
722 WINPR_ASSERT(instance);
723 WINPR_ASSERT(instance->context);
724
725 rdp = instance->context->rdp;
726 WINPR_ASSERT(rdp);
727
728 if (rdp->resendFocus)
729 {
730 bRetCode = TRUE;
731 rdp->resendFocus = FALSE;
732 }
733
734 return bRetCode;
735}
736
737void freerdp_set_focus(freerdp* instance)
738{
739 rdpRdp* rdp = nullptr;
740
741 WINPR_ASSERT(instance);
742 WINPR_ASSERT(instance->context);
743
744 rdp = instance->context->rdp;
745 WINPR_ASSERT(rdp);
746
747 rdp->resendFocus = TRUE;
748}
749
750void freerdp_get_version(int* major, int* minor, int* revision)
751{
752 if (major != nullptr)
753 *major = FREERDP_VERSION_MAJOR;
754
755 if (minor != nullptr)
756 *minor = FREERDP_VERSION_MINOR;
757
758 if (revision != nullptr)
759 *revision = FREERDP_VERSION_REVISION;
760}
761
762const char* freerdp_get_version_string(void)
763{
764 return FREERDP_VERSION_FULL;
765}
766
767const char* freerdp_get_build_config(void)
768{
769 WINPR_PRAGMA_DIAG_PUSH
770 WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
771 static const char build_config[] =
772 "Build configuration: " FREERDP_BUILD_CONFIG "\n"
773 "Build type: " FREERDP_BUILD_TYPE "\n"
774 "CFLAGS: " FREERDP_CFLAGS "\n"
775 "Compiler: " FREERDP_COMPILER_ID ", " FREERDP_COMPILER_VERSION "\n"
776 "Target architecture: " FREERDP_TARGET_ARCH "\n";
777 WINPR_PRAGMA_DIAG_POP
778 return build_config;
779}
780
781const char* freerdp_get_build_revision(void)
782{
783 return FREERDP_GIT_REVISION;
784}
785
786static wEventType FreeRDP_Events[] = {
787 DEFINE_EVENT_ENTRY(WindowStateChange), DEFINE_EVENT_ENTRY(ResizeWindow),
788 DEFINE_EVENT_ENTRY(LocalResizeWindow), DEFINE_EVENT_ENTRY(EmbedWindow),
789 DEFINE_EVENT_ENTRY(PanningChange), DEFINE_EVENT_ENTRY(ZoomingChange),
790 DEFINE_EVENT_ENTRY(ErrorInfo), DEFINE_EVENT_ENTRY(Terminate),
791 DEFINE_EVENT_ENTRY(ConnectionResult), DEFINE_EVENT_ENTRY(ChannelConnected),
792 DEFINE_EVENT_ENTRY(ChannelDisconnected), DEFINE_EVENT_ENTRY(MouseEvent),
793 DEFINE_EVENT_ENTRY(Activated), DEFINE_EVENT_ENTRY(Timer),
794 DEFINE_EVENT_ENTRY(GraphicsReset), DEFINE_EVENT_ENTRY(UserNotification),
795 DEFINE_EVENT_ENTRY(ChannelInitialized), DEFINE_EVENT_ENTRY(ChannelTerminated),
796 DEFINE_EVENT_ENTRY(StateChanged)
797};
798
809BOOL freerdp_context_new(freerdp* instance)
810{
811 return freerdp_context_new_ex(instance, nullptr);
812}
813
814static BOOL freerdp_common_context(rdpContext* context, AccessTokenType tokenType, char** token,
815 size_t count, ...)
816{
817 BOOL rc = FALSE;
818
819 WINPR_ASSERT(context);
820 if (!context->instance || !context->instance->GetAccessToken)
821 return TRUE;
822
823 va_list ap = WINPR_C_ARRAY_INIT;
824 va_start(ap, count);
825 switch (tokenType)
826 {
827 case ACCESS_TOKEN_TYPE_AAD:
828 if (count != 2)
829 {
830 WLog_ERR(TAG,
831 "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
832 ", aborting",
833 count);
834 }
835 else
836 {
837 const char* scope = va_arg(ap, const char*);
838 const char* req_cnf = va_arg(ap, const char*);
839 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count,
840 scope, req_cnf);
841 }
842 break;
843 case ACCESS_TOKEN_TYPE_AVD:
844 if (count != 0)
845 {
846 WLog_WARN(TAG,
847 "ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
848 ", ignoring",
849 count);
850 }
851 else
852 {
853 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count);
854 }
855 break;
856 default:
857 break;
858 }
859 va_end(ap);
860
861 if (!rc)
862 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
863
864 return rc;
865}
866
867BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
868{
869 rdpRdp* rdp = nullptr;
870 rdpContext* context = nullptr;
871 BOOL ret = TRUE;
872
873 WINPR_ASSERT(instance);
874
875 instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
876
877 if (!context)
878 return FALSE;
879
880 context->log = WLog_Get(TAG);
881 if (!context->log)
882 goto fail;
883
884 /* Set to external settings, prevents rdp_new from creating its own instance */
885 context->settings = settings;
886 context->instance = instance;
887 context->ServerMode = FALSE;
888 context->disconnectUltimatum = 0;
889
890 context->metrics = metrics_new(context);
891
892 if (!context->metrics)
893 goto fail;
894
895 rdp = rdp_new(context);
896
897 if (!rdp)
898 goto fail;
899
900 context->rdp = rdp;
901 context->pubSub = rdp->pubSub;
902
903 if (!context->pubSub)
904 goto fail;
905
906 PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
907
908#if defined(WITH_FREERDP_DEPRECATED)
909 instance->input = rdp->input;
910 instance->update = rdp->update;
911 instance->settings = rdp->settings;
912 instance->autodetect = rdp->autodetect;
913#endif
914
915 instance->heartbeat = rdp->heartbeat;
916 context->graphics = graphics_new(context);
917
918 if (!context->graphics)
919 goto fail;
920
921 context->input = rdp->input;
922 context->update = rdp->update;
923 context->settings = rdp->settings;
924 context->autodetect = rdp->autodetect;
925
926 if (!(context->errorDescription = calloc(1, 500)))
927 {
928 WLog_Print(context->log, WLOG_ERROR, "calloc failed!");
929 goto fail;
930 }
931
932 if (!(context->channelErrorEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)))
933 {
934 WLog_Print(context->log, WLOG_ERROR, "CreateEvent failed!");
935 goto fail;
936 }
937
938 update_register_client_callbacks(rdp->update);
939
940 if (!(context->channels = freerdp_channels_new(instance)))
941 goto fail;
942
943 context->dump = stream_dump_new();
944 if (!context->dump)
945 goto fail;
946
947 /* Fallback:
948 * Client common library might set a function pointer to handle this, but here we provide a
949 * default implementation that simply calls instance->GetAccessToken.
950 */
951 if (!freerdp_set_common_access_token(context, freerdp_common_context))
952 goto fail;
953
954 IFCALLRET(instance->ContextNew, ret, instance, context);
955
956 if (!ret)
957 goto fail;
958
959 return TRUE;
960
961fail:
962 freerdp_context_free(instance);
963 return FALSE;
964}
965
966BOOL freerdp_context_reset(freerdp* instance)
967{
968 if (!instance)
969 return FALSE;
970
971 WINPR_ASSERT(instance->context);
972 rdpRdp* rdp = instance->context->rdp;
973
974 return rdp_reset_runtime_settings(rdp);
975}
976
985void freerdp_context_free(freerdp* instance)
986{
987 rdpContext* ctx = nullptr;
988
989 if (!instance)
990 return;
991
992 if (!instance->context)
993 return;
994
995 ctx = instance->context;
996
997 IFCALL(instance->ContextFree, instance, ctx);
998 rdp_free(ctx->rdp);
999 ctx->rdp = nullptr;
1000 ctx->settings = nullptr; /* owned by rdpRdp */
1001
1002 graphics_free(ctx->graphics);
1003 ctx->graphics = nullptr;
1004
1005 metrics_free(ctx->metrics);
1006 ctx->metrics = nullptr;
1007
1008 if (ctx->channelErrorEvent)
1009 (void)CloseHandle(ctx->channelErrorEvent);
1010 ctx->channelErrorEvent = nullptr;
1011
1012 free(ctx->errorDescription);
1013 ctx->errorDescription = nullptr;
1014
1015 freerdp_channels_free(ctx->channels);
1016 ctx->channels = nullptr;
1017
1018 freerdp_client_codecs_free(ctx->codecs);
1019 ctx->codecs = nullptr;
1020
1021 stream_dump_free(ctx->dump);
1022 ctx->dump = nullptr;
1023
1024 ctx->input = nullptr; /* owned by rdpRdp */
1025 ctx->update = nullptr; /* owned by rdpRdp */
1026 ctx->settings = nullptr; /* owned by rdpRdp */
1027 ctx->autodetect = nullptr; /* owned by rdpRdp */
1028
1029 free(ctx);
1030 instance->context = nullptr;
1031#if defined(WITH_FREERDP_DEPRECATED)
1032 instance->input = nullptr; /* owned by rdpRdp */
1033 instance->update = nullptr; /* owned by rdpRdp */
1034 instance->settings = nullptr; /* owned by rdpRdp */
1035 instance->autodetect = nullptr; /* owned by rdpRdp */
1036#endif
1037 instance->heartbeat = nullptr; /* owned by rdpRdp */
1038}
1039
1040int freerdp_get_disconnect_ultimatum(const rdpContext* context)
1041{
1042 WINPR_ASSERT(context);
1043 return context->disconnectUltimatum;
1044}
1045
1046UINT32 freerdp_error_info(const freerdp* instance)
1047{
1048 WINPR_ASSERT(instance);
1049 WINPR_ASSERT(instance->context);
1050 WINPR_ASSERT(instance->context->rdp);
1051 return instance->context->rdp->errorInfo;
1052}
1053
1054void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
1055{
1056 if (!rdp)
1057 return;
1058
1059 rdp_set_error_info(rdp, error);
1060}
1061
1062BOOL freerdp_send_error_info(rdpRdp* rdp)
1063{
1064 if (!rdp)
1065 return FALSE;
1066
1067 return rdp_send_error_info(rdp);
1068}
1069
1070UINT32 freerdp_get_last_error(const rdpContext* context)
1071{
1072 WINPR_ASSERT(context);
1073 return context->LastError;
1074}
1075
1076const char* freerdp_get_last_error_name(UINT32 code)
1077{
1078 const char* name = nullptr;
1079 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1080 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1081
1082 switch (cls)
1083 {
1084 case FREERDP_ERROR_ERRBASE_CLASS:
1085 name = freerdp_get_error_base_name(type);
1086 break;
1087
1088 case FREERDP_ERROR_ERRINFO_CLASS:
1089 name = freerdp_get_error_info_name(type);
1090 break;
1091
1092 case FREERDP_ERROR_CONNECT_CLASS:
1093 name = freerdp_get_error_connect_name(type);
1094 break;
1095
1096 default:
1097 name = rpc_error_to_string(code);
1098 break;
1099 }
1100
1101 return name;
1102}
1103
1104const char* freerdp_get_last_error_string(UINT32 code)
1105{
1106 const char* string = nullptr;
1107 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1108 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1109
1110 switch (cls)
1111 {
1112 case FREERDP_ERROR_ERRBASE_CLASS:
1113 string = freerdp_get_error_base_string(type);
1114 break;
1115
1116 case FREERDP_ERROR_ERRINFO_CLASS:
1117 string = freerdp_get_error_info_string(type);
1118 break;
1119
1120 case FREERDP_ERROR_CONNECT_CLASS:
1121 string = freerdp_get_error_connect_string(type);
1122 break;
1123
1124 default:
1125 string = rpc_error_to_string(code);
1126 break;
1127 }
1128
1129 return string;
1130}
1131
1132const char* freerdp_get_last_error_category(UINT32 code)
1133{
1134 const char* string = nullptr;
1135 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1136 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1137
1138 switch (cls)
1139 {
1140 case FREERDP_ERROR_ERRBASE_CLASS:
1141 string = freerdp_get_error_base_category(type);
1142 break;
1143
1144 case FREERDP_ERROR_ERRINFO_CLASS:
1145 string = freerdp_get_error_info_category(type);
1146 break;
1147
1148 case FREERDP_ERROR_CONNECT_CLASS:
1149 string = freerdp_get_error_connect_category(type);
1150 break;
1151
1152 default:
1153 string = rpc_error_to_category(code);
1154 break;
1155 }
1156
1157 return string;
1158}
1159
1160void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError, const char* fkt,
1161 const char* file, int line)
1162{
1163 WINPR_ASSERT(context);
1164 WINPR_ASSERT(line >= 0);
1165
1166 if (lastError)
1167 {
1168 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1169 {
1170 WLog_PrintTextMessage(context->log, WLOG_ERROR, (size_t)line, file, fkt,
1171 "%s [0x%08" PRIX32 "]", freerdp_get_last_error_name(lastError),
1172 lastError);
1173 }
1174 }
1175
1176 if (lastError == FREERDP_ERROR_SUCCESS)
1177 {
1178 if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1179 WLog_PrintTextMessage(context->log, WLOG_DEBUG, (size_t)line, file, fkt,
1180 "resetting error state");
1181 }
1182 else if (context->LastError != FREERDP_ERROR_SUCCESS)
1183 {
1184 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1185 {
1186 WLog_PrintTextMessage(context->log, WLOG_ERROR, (size_t)line, file, fkt,
1187 "TODO: Trying to set error code %s, but %s already set!",
1188 freerdp_get_last_error_name(lastError),
1189 freerdp_get_last_error_name(context->LastError));
1190 }
1191 }
1192 context->LastError = lastError;
1193}
1194
1195const char* freerdp_get_logon_error_info_type_ex(UINT32 type, char* buffer, size_t size)
1196{
1197 const char* str = freerdp_get_logon_error_info_type(type);
1198 (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, type);
1199 return buffer;
1200}
1201
1202const char* freerdp_get_logon_error_info_type(UINT32 type)
1203{
1204#define CASE_ENTRY(x) \
1205 case x: \
1206 return #x
1207 switch (type)
1208 {
1209 CASE_ENTRY(LOGON_MSG_SESSION_BUSY_OPTIONS);
1210 CASE_ENTRY(LOGON_MSG_DISCONNECT_REFUSED);
1211 CASE_ENTRY(LOGON_MSG_NO_PERMISSION);
1212 CASE_ENTRY(LOGON_MSG_BUMP_OPTIONS);
1213 CASE_ENTRY(LOGON_MSG_RECONNECT_OPTIONS);
1214 CASE_ENTRY(LOGON_MSG_SESSION_TERMINATE);
1215 CASE_ENTRY(LOGON_MSG_SESSION_CONTINUE);
1216 CASE_ENTRY(ERROR_CODE_ACCESS_DENIED);
1217
1218 default:
1219 return "UNKNOWN";
1220 }
1221#undef CASE_ENTRY
1222}
1223
1224const char* freerdp_get_logon_error_info_data(UINT32 data)
1225{
1226 switch (data)
1227 {
1228 case LOGON_FAILED_BAD_PASSWORD:
1229 return "LOGON_FAILED_BAD_PASSWORD";
1230
1231 case LOGON_FAILED_UPDATE_PASSWORD:
1232 return "LOGON_FAILED_UPDATE_PASSWORD";
1233
1234 case LOGON_FAILED_OTHER:
1235 return "LOGON_FAILED_OTHER";
1236
1237 case LOGON_WARNING:
1238 return "LOGON_WARNING";
1239
1240 default:
1241 return "SESSION_ID";
1242 }
1243}
1244
1245const char* freerdp_get_logon_error_info_data_ex(UINT32 data, char* buffer, size_t size)
1246{
1247 const char* str = freerdp_get_logon_error_info_data(data);
1248 (void)_snprintf(buffer, size, "%s(0x%04" PRIx32 ")", str, data);
1249 return buffer;
1250}
1251
1255freerdp* freerdp_new(void)
1256{
1257 freerdp* instance = nullptr;
1258 instance = (freerdp*)calloc(1, sizeof(freerdp));
1259
1260 if (!instance)
1261 return nullptr;
1262
1263 instance->ContextSize = sizeof(rdpContext);
1264 instance->SendChannelData = freerdp_send_channel_data;
1265 instance->SendChannelPacket = freerdp_send_channel_packet;
1266 instance->ReceiveChannelData = freerdp_channels_data;
1267 return instance;
1268}
1269
1274void freerdp_free(freerdp* instance)
1275{
1276 free(instance);
1277}
1278
1279ULONG freerdp_get_transport_sent(const rdpContext* context, BOOL resetCount)
1280{
1281 WINPR_ASSERT(context);
1282 WINPR_ASSERT(context->rdp);
1283 UINT64 rc = transport_get_bytes_sent(context->rdp->transport, resetCount);
1284 return WINPR_CXX_COMPAT_CAST(ULONG, MIN(rc, UINT32_MAX));
1285}
1286
1287BOOL freerdp_nla_impersonate(rdpContext* context)
1288{
1289 rdpNla* nla = nullptr;
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_impersonate(nla);
1302}
1303
1304BOOL freerdp_nla_revert_to_self(rdpContext* context)
1305{
1306 rdpNla* nla = nullptr;
1307
1308 if (!context)
1309 return FALSE;
1310
1311 if (!context->rdp)
1312 return FALSE;
1313
1314 if (!context->rdp->transport)
1315 return FALSE;
1316
1317 nla = transport_get_nla(context->rdp->transport);
1318 return nla_revert_to_self(nla);
1319}
1320
1321UINT32 freerdp_get_nla_sspi_error(const rdpContext* context)
1322{
1323 WINPR_ASSERT(context);
1324 WINPR_ASSERT(context->rdp);
1325 WINPR_ASSERT(context->rdp->transport);
1326
1327 rdpNla* nla = context->rdp->nla;
1328 if (!nla)
1329 nla = transport_get_nla(context->rdp->transport);
1330 return (UINT32)nla_get_sspi_error(nla);
1331}
1332
1333BOOL freerdp_nla_encrypt(rdpContext* context, const SecBuffer* inBuffer, SecBuffer* outBuffer)
1334{
1335 WINPR_ASSERT(context);
1336 WINPR_ASSERT(context->rdp);
1337
1338 rdpNla* nla = context->rdp->nla;
1339 return nla_encrypt(nla, inBuffer, outBuffer);
1340}
1341
1342BOOL freerdp_nla_decrypt(rdpContext* context, const SecBuffer* inBuffer, SecBuffer* outBuffer)
1343{
1344 WINPR_ASSERT(context);
1345 WINPR_ASSERT(context->rdp);
1346
1347 rdpNla* nla = context->rdp->nla;
1348 return nla_decrypt(nla, inBuffer, outBuffer);
1349}
1350
1351SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ulAttr, PVOID pBuffer)
1352{
1353 WINPR_ASSERT(context);
1354 WINPR_ASSERT(context->rdp);
1355
1356 rdpNla* nla = context->rdp->nla;
1357 if (!nla)
1358 nla = transport_get_nla(context->rdp->transport);
1359
1360 WINPR_ASSERT(nla);
1361
1362 return nla_QueryContextAttributes(nla, ulAttr, pBuffer);
1363}
1364
1365SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, PVOID pBuffer)
1366{
1367 WINPR_ASSERT(context);
1368 WINPR_ASSERT(context->rdp);
1369
1370 rdpNla* nla = context->rdp->nla;
1371 if (!nla)
1372 nla = transport_get_nla(context->rdp->transport);
1373
1374 WINPR_ASSERT(nla);
1375
1376 return nla_FreeContextBuffer(nla, pBuffer);
1377}
1378
1379HANDLE getChannelErrorEventHandle(rdpContext* context)
1380{
1381 WINPR_ASSERT(context);
1382 return context->channelErrorEvent;
1383}
1384
1385BOOL checkChannelErrorEvent(rdpContext* context)
1386{
1387 WINPR_ASSERT(context);
1388
1389 if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1390 {
1391 WLog_Print(context->log, WLOG_ERROR, "%s. Error was %" PRIu32 "", context->errorDescription,
1392 context->channelErrorNum);
1393 return FALSE;
1394 }
1395
1396 return TRUE;
1397}
1398
1404UINT getChannelError(const rdpContext* context)
1405{
1406 WINPR_ASSERT(context);
1407 return context->channelErrorNum;
1408}
1409
1410const char* getChannelErrorDescription(const rdpContext* context)
1411{
1412 WINPR_ASSERT(context);
1413 return context->errorDescription;
1414}
1415
1416void clearChannelError(rdpContext* context)
1417{
1418 WINPR_ASSERT(context);
1419 context->channelErrorNum = 0;
1420 memset(context->errorDescription, 0, 500);
1421 (void)ResetEvent(context->channelErrorEvent);
1422}
1423
1424WINPR_ATTR_FORMAT_ARG(3, 4)
1425void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const char* format, ...)
1426{
1427 va_list ap = WINPR_C_ARRAY_INIT;
1428 va_start(ap, format);
1429
1430 WINPR_ASSERT(context);
1431
1432 context->channelErrorNum = errorNum;
1433 (void)vsnprintf(context->errorDescription, 499, format, ap);
1434 va_end(ap);
1435 (void)SetEvent(context->channelErrorEvent);
1436}
1437
1438const char* freerdp_nego_get_routing_token(const rdpContext* context, DWORD* length)
1439{
1440 if (!context || !context->rdp)
1441 return nullptr;
1442
1443 return (const char*)nego_get_routing_token(context->rdp->nego, length);
1444}
1445
1446BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1447{
1448 WINPR_ASSERT(context);
1449 return rdp_io_callback_set_event(context->rdp, set);
1450}
1451
1452const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1453{
1454 WINPR_ASSERT(context);
1455 return rdp_get_io_callbacks(context->rdp);
1456}
1457
1458BOOL freerdp_set_io_callbacks(rdpContext* context, const rdpTransportIo* io_callbacks)
1459{
1460 WINPR_ASSERT(context);
1461 return rdp_set_io_callbacks(context->rdp, io_callbacks);
1462}
1463
1464BOOL freerdp_set_io_callback_context(rdpContext* context, void* usercontext)
1465{
1466 WINPR_ASSERT(context);
1467 return rdp_set_io_callback_context(context->rdp, usercontext);
1468}
1469
1470void* freerdp_get_io_callback_context(rdpContext* context)
1471{
1472 WINPR_ASSERT(context);
1473 return rdp_get_io_callback_context(context->rdp);
1474}
1475
1476CONNECTION_STATE freerdp_get_state(const rdpContext* context)
1477{
1478 WINPR_ASSERT(context);
1479 return rdp_get_state(context->rdp);
1480}
1481
1482const char* freerdp_state_string(CONNECTION_STATE state)
1483{
1484 return rdp_state_string(state);
1485}
1486
1487BOOL freerdp_is_active_state(const rdpContext* context)
1488{
1489 WINPR_ASSERT(context);
1490 return rdp_is_active_state(context->rdp);
1491}
1492
1493BOOL freerdp_channels_from_mcs(rdpSettings* settings, const rdpContext* context)
1494{
1495 WINPR_ASSERT(context);
1496 return rdp_channels_from_mcs(settings, context->rdp);
1497}
1498
1499HANDLE freerdp_abort_event(rdpContext* context)
1500{
1501 WINPR_ASSERT(context);
1502 return utils_get_abort_event(context->rdp);
1503}
1504
1505static void test_mcs_free(rdpMcs* mcs)
1506{
1507 if (!mcs)
1508 return;
1509
1510 if (mcs->context)
1511 {
1512 rdpSettings* settings = mcs->context->settings;
1513 freerdp_settings_free(settings);
1514 }
1515 free(mcs->context);
1516
1517 mcs_free(mcs);
1518}
1519
1520static rdpMcs* test_mcs_new(void)
1521{
1522 rdpSettings* settings = freerdp_settings_new(0);
1523 rdpContext* context = calloc(1, sizeof(rdpContext));
1524
1525 if (!settings)
1526 goto fail;
1527 if (!freerdp_settings_set_bool(settings, FreeRDP_TransportDumpReplay, TRUE))
1528 goto fail;
1529
1530 if (!context)
1531 goto fail;
1532 context->settings = settings;
1533 return mcs_new(context);
1534
1535fail:
1536 free(context);
1537 freerdp_settings_free(settings);
1538
1539 return nullptr;
1540}
1541
1542BOOL freerdp_is_valid_mcs_create_request(const BYTE* data, size_t size)
1543{
1544
1545 wStream sbuffer = WINPR_C_ARRAY_INIT;
1546 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1547
1548 WINPR_ASSERT(data || (size == 0));
1549 WINPR_ASSERT(s);
1550
1551 rdpMcs* mcs = test_mcs_new();
1552 WINPR_ASSERT(mcs);
1553
1554 BOOL result = mcs_recv_connect_initial(mcs, s);
1555 test_mcs_free(mcs);
1556 return result;
1557}
1558
1559BOOL freerdp_is_valid_mcs_create_response(const BYTE* data, size_t size)
1560{
1561
1562 wStream sbuffer = WINPR_C_ARRAY_INIT;
1563 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1564
1565 WINPR_ASSERT(data || (size == 0));
1566 WINPR_ASSERT(s);
1567
1568 rdpMcs* mcs = test_mcs_new();
1569 WINPR_ASSERT(mcs);
1570
1571 BOOL result = mcs_recv_connect_response(mcs, s);
1572 test_mcs_free(mcs);
1573 return result;
1574}
1575
1576BOOL freerdp_persist_credentials(rdpContext* context)
1577{
1578 if (!context)
1579 return FALSE;
1580 WINPR_ASSERT(context->rdp);
1581 return utils_persist_credentials(context->rdp->originalSettings, context->rdp->settings);
1582}
1583
1584const char* freerdp_disconnect_reason_string(int reason)
1585{
1586 switch (reason)
1587 {
1588 case Disconnect_Ultimatum_domain_disconnected:
1589 return "rn-domain-disconnected";
1590 case Disconnect_Ultimatum_provider_initiated:
1591 return "rn-provider-initiated";
1592 case Disconnect_Ultimatum_token_purged:
1593 return "rn-token-purged";
1594 case Disconnect_Ultimatum_user_requested:
1595 return "rn-user-requested";
1596 case Disconnect_Ultimatum_channel_purged:
1597 return "rn-channel-purged";
1598 default:
1599 return "rn-unknown";
1600 }
1601}
1602
1603BOOL freerdp_set_common_access_token(rdpContext* context,
1604 pGetCommonAccessToken GetCommonAccessToken)
1605{
1606 WINPR_ASSERT(context);
1607 WINPR_ASSERT(context->rdp);
1608 context->rdp->GetCommonAccessToken = GetCommonAccessToken;
1609 return TRUE;
1610}
1611
1612pGetCommonAccessToken freerdp_get_common_access_token(const rdpContext* context)
1613{
1614 WINPR_ASSERT(context);
1615 WINPR_ASSERT(context->rdp);
1616 return context->rdp->GetCommonAccessToken;
1617}
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.