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