22#include <freerdp/config.h>
35#include "connection.h"
37#include <freerdp/buildflags.h>
38#include "gateway/rpc_fault.h"
39#include "../cache/cache.h"
41#include <winpr/assert.h>
44#include <winpr/string.h>
45#include <winpr/stream.h>
46#include <winpr/wtsapi.h>
48#include <winpr/debug.h>
49#include <winpr/i18n.h>
51#include <freerdp/freerdp.h>
52#include <freerdp/streamdump.h>
53#include <freerdp/error.h>
54#include <freerdp/event.h>
55#include <freerdp/locale/keyboard.h>
56#include <freerdp/locale/locale.h>
57#include <freerdp/channels/channels.h>
58#include <freerdp/version.h>
59#include <freerdp/log.h>
60#include <freerdp/utils/signal.h>
62#include "../cache/pointer.h"
65#define TAG FREERDP_TAG("core")
67BOOL freerdp_enable_translation(
const char* locale,
const char* searchPath)
69 return winpr_i18n_enable_translation(locale) && winpr_i18n_bind_domain(
"freerdp", searchPath);
72static void sig_abort_connect(
int signum,
const char* signame,
void* ctx)
74 rdpContext* context = (rdpContext*)ctx;
76 WLog_INFO(TAG,
"Signal %s [%d], terminating session %p", signame, signum,
77 WINPR_CXX_COMPAT_CAST(
const void*, context));
79 freerdp_abort_connect_context(context);
93static int freerdp_connect_begin(freerdp* instance)
96 rdpRdp* rdp =
nullptr;
98 rdpSettings* settings =
nullptr;
103 WINPR_ASSERT(instance->context);
106 instance->ConnectionCallbackState = CLIENT_STATE_INITIAL;
107 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS);
108 clearChannelError(instance->context);
109 if (!utils_reset_abort(instance->context->rdp))
112 rdp = instance->context->rdp;
115 settings = instance->context->settings;
116 WINPR_ASSERT(settings);
118 freerdp_channels_register_instance(instance->context->channels, instance);
120 if (!freerdp_settings_set_default_order_support(settings))
123 if (!freerdp_add_signal_cleanup_handler(instance->context, sig_abort_connect))
126 IFCALLRET(instance->PreConnect, status, instance);
127 instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED;
129 freerdp_settings_print_warnings(settings);
131 status = freerdp_settings_enforce_monitor_exists(settings);
134 status = freerdp_settings_enforce_consistency(settings);
137 status = freerdp_settings_check_client_after_preconnect(settings);
140 status = rdp_set_backup_settings(rdp);
142 status = utils_reload_channels(instance->context);
145 int64_t KeyboardLayout = freerdp_get_keyboard_default_layout_for_locale(cp);
146 if (KeyboardLayout == 0)
149 switch (KeyboardLayout)
152 case KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002:
155 WINPR_KBD_TYPE_JAPANESE))
169 rdpContext* context = instance->context;
170 WINPR_ASSERT(context);
171 freerdp_set_last_error_if_not(context, FREERDP_ERROR_PRE_CONNECT_FAILED);
173 WLog_Print(context->log, WLOG_ERROR,
"freerdp_pre_connect failed: %s",
174 rdp_client_connection_state_string(instance->ConnectionCallbackState));
178 rc = rdp_client_connect(rdp);
183 rdpContext* context = rdp->context;
184 WINPR_ASSERT(context);
185 WLog_Print(context->log, WLOG_ERROR,
"Authentication only, exit status %" PRId32
"", rc);
192BOOL freerdp_connect(freerdp* instance)
195 ConnectionResultEventArgs e = WINPR_C_ARRAY_INIT;
196 const int rc = freerdp_connect_begin(instance);
197 rdpRdp* rdp =
nullptr;
198 UINT status2 = ERROR_INTERNAL_ERROR;
200 WINPR_ASSERT(instance);
201 WINPR_ASSERT(instance->context);
203 rdp = instance->context->rdp;
205 WINPR_ASSERT(rdp->settings);
214 up->pcap_rfx = pcap_open(
221 pointer_cache_register_callbacks(instance->context->update);
222 status = IFCALLRESULT(TRUE, instance->PostConnect, instance);
223 instance->ConnectionCallbackState = CLIENT_STATE_POSTCONNECT_PASSED;
226 status2 = freerdp_channels_post_connect(instance->context->channels, instance);
230 status2 = CHANNEL_RC_OK;
231 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)
232 status = freerdp_reconnect(instance);
234 goto freerdp_connect_finally;
237 if (!status || (status2 != CHANNEL_RC_OK) || !update_post_connect(instance->context->update))
239 rdpContext* context = instance->context;
240 WINPR_ASSERT(context);
241 WLog_Print(context->log, WLOG_ERROR,
"freerdp_post_connect failed");
243 freerdp_set_last_error_if_not(context, FREERDP_ERROR_POST_CONNECT_FAILED);
246 goto freerdp_connect_finally;
253 pcap_record record = WINPR_C_ARRAY_INIT;
255 WINPR_ASSERT(update);
256 const char* PlayRemoteFxFile =
258 update->pcap_rfx = pcap_open(PlayRemoteFxFile, FALSE);
261 if (!update->pcap_rfx)
262 goto freerdp_connect_finally;
264 update->play_rfx = TRUE;
268 while (pcap_has_next_record(update->pcap_rfx) && status)
270 if (!pcap_get_next_record_header(update->pcap_rfx, &record))
273 s = transport_take_from_pool(rdp->transport, record.length);
277 record.data = Stream_Buffer(s);
278 if (!pcap_get_next_record_content(update->pcap_rfx, &record))
280 if (!Stream_SetLength(s, record.length))
285 Stream_ResetPosition(s);
287 if (!update_begin_paint(&update->common))
291 if (!update_recv_surfcmds(&update->common, s))
294 if (!update_end_paint(&update->common))
301 pcap_close(update->pcap_rfx);
302 update->pcap_rfx =
nullptr;
303 goto freerdp_connect_finally;
306 if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
307 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
310 status = transport_set_connected_event(rdp->transport);
312freerdp_connect_finally:
313 EventArgsInit(&e,
"freerdp");
314 e.result = status ? 0 : -1;
315 if (PubSub_OnConnectionResult(rdp->pubSub, instance->context, &e) < 0)
319 freerdp_disconnect(instance);
324#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
325BOOL freerdp_abort_connect(freerdp* instance)
330 return freerdp_abort_connect_context(instance->context);
334BOOL freerdp_abort_connect_context(rdpContext* context)
339 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
340 return utils_abort_connect(context->rdp);
343#if defined(WITH_FREERDP_DEPRECATED)
344BOOL freerdp_get_fds(freerdp* instance,
void** rfds,
int* rcount, WINPR_ATTR_UNUSED
void** wfds,
345 WINPR_ATTR_UNUSED
int* wcount)
347 rdpRdp* rdp =
nullptr;
349 WINPR_ASSERT(instance);
350 WINPR_ASSERT(instance->context);
352 rdp = instance->context->rdp;
355 transport_get_fds(rdp->transport, rfds, rcount);
360BOOL freerdp_check_fds(freerdp* instance)
363 rdpRdp* rdp =
nullptr;
368 if (!instance->context)
371 if (!instance->context->rdp)
374 rdp = instance->context->rdp;
375 status = rdp_check_fds(rdp);
379 TerminateEventArgs e;
380 rdpContext* context = instance->context;
381 WINPR_ASSERT(context);
383 WLog_Print(context->log, WLOG_DEBUG,
"rdp_check_fds() - %i", status);
384 EventArgsInit(&e,
"freerdp");
386 if (PubSub_OnTerminate(rdp->pubSub, context, &e) < 0)
394DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count)
398 WINPR_ASSERT(context);
399 WINPR_ASSERT(context->rdp);
400 WINPR_ASSERT(events || (count == 0));
402 const size_t rrc = rdp_get_event_handles(context->rdp, &events[nCount], count - nCount);
406 nCount += WINPR_ASSERTING_INT_CAST(uint32_t, rrc);
408 if (events && (nCount < count + 2))
410 events[nCount++] = freerdp_channels_get_event_handle(context->instance);
411 events[nCount++] = getChannelErrorEventHandle(context);
416 const SSIZE_T rc = freerdp_client_channel_get_registered_event_handles(
417 context->channels, &events[nCount], count - nCount);
420 return nCount + (DWORD)rc;
424static BOOL freerdp_prevent_session_lock(rdpContext* context)
426 WINPR_ASSERT(context);
427 WINPR_ASSERT(context->input);
431 UINT32 FakeMouseMotionInterval =
433 if (FakeMouseMotionInterval && in->lastInputTimestamp)
435 const time_t now = time(
nullptr);
436 if (WINPR_ASSERTING_INT_CAST(
size_t, now) - in->lastInputTimestamp >
437 FakeMouseMotionInterval)
439 WLog_Print(context->log, WLOG_DEBUG,
440 "fake mouse move: x=%d y=%d lastInputTimestamp=%" PRIu64
" "
441 "FakeMouseMotionInterval=%" PRIu32,
442 in->lastX, in->lastY, in->lastInputTimestamp, FakeMouseMotionInterval);
444 BOOL status = freerdp_input_send_mouse_event(context->input, PTR_FLAGS_MOVE, in->lastX,
448 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
449 WLog_Print(context->log, WLOG_ERROR,
450 "freerdp_prevent_session_lock() failed - %" PRIi32
"", status);
462BOOL freerdp_check_event_handles(rdpContext* context)
464 WINPR_ASSERT(context);
466 BOOL status = freerdp_check_fds(context->instance);
470 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
471 WLog_Print(context->log, WLOG_ERROR,
"freerdp_check_fds() failed - %" PRIi32
"",
477 status = freerdp_channels_check_fds(context->channels, context->instance);
481 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
482 WLog_Print(context->log, WLOG_ERROR,
483 "freerdp_channels_check_fds() failed - %" PRIi32
"", status);
488 status = checkChannelErrorEvent(context);
492 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
493 WLog_Print(context->log, WLOG_ERROR,
"checkChannelErrorEvent() failed - %" PRIi32
"",
499 status = freerdp_prevent_session_lock(context);
504wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD
id)
506 wMessageQueue* queue =
nullptr;
508 WINPR_ASSERT(instance);
510 rdpContext* context = instance->context;
511 WINPR_ASSERT(context);
515 case FREERDP_UPDATE_MESSAGE_QUEUE:
518 queue = update->queue;
522 case FREERDP_INPUT_MESSAGE_QUEUE:
525 queue = input->queue;
535HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD
id)
537 HANDLE
event =
nullptr;
538 wMessageQueue* queue = freerdp_get_message_queue(instance,
id);
541 event = MessageQueue_Event(queue);
546int freerdp_message_queue_process_message(freerdp* instance, DWORD
id, wMessage* message)
549 rdpContext* context =
nullptr;
551 WINPR_ASSERT(instance);
553 context = instance->context;
554 WINPR_ASSERT(context);
558 case FREERDP_UPDATE_MESSAGE_QUEUE:
559 status = update_message_queue_process_message(context->update, message);
562 case FREERDP_INPUT_MESSAGE_QUEUE:
563 status = input_message_queue_process_message(context->input, message);
572int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD
id)
575 rdpContext* context =
nullptr;
577 WINPR_ASSERT(instance);
579 context = instance->context;
580 WINPR_ASSERT(context);
584 case FREERDP_UPDATE_MESSAGE_QUEUE:
585 status = update_message_queue_process_pending_messages(context->update);
588 case FREERDP_INPUT_MESSAGE_QUEUE:
589 status = input_message_queue_process_pending_messages(context->input);
598static BOOL freerdp_send_channel_data(freerdp* instance, UINT16 channelId,
const BYTE* data,
601 WINPR_ASSERT(instance);
602 WINPR_ASSERT(instance->context);
603 WINPR_ASSERT(instance->context->rdp);
604 return rdp_send_channel_data(instance->context->rdp, channelId, data, size);
607static BOOL freerdp_send_channel_packet(freerdp* instance, UINT16 channelId,
size_t totalSize,
608 UINT32 flags,
const BYTE* data,
size_t chunkSize)
610 WINPR_ASSERT(instance);
611 WINPR_ASSERT(instance->context);
612 WINPR_ASSERT(instance->context->rdp);
613 return rdp_channel_send_packet(instance->context->rdp, channelId, totalSize, flags, data,
617BOOL freerdp_disconnect(freerdp* instance)
621 if (!instance || !instance->context)
624 rdpRdp* rdp = instance->context->rdp;
629 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
631 (void)mcs_send_disconnect_provider_ultimatum(rdp->mcs,
632 Disconnect_Ultimatum_user_requested);
636 utils_abort_connect(rdp);
638 if (!rdp_client_disconnect(rdp))
642 if (rdp && rdp->update)
644 up = update_cast(rdp->update);
646 update_post_disconnect(rdp->update);
649 IFCALL(instance->PostDisconnect, instance);
650 cache_free(instance->context->cache);
651 instance->context->cache =
nullptr;
655 update_dump_stats(rdp->update);
658 up->dump_rfx = FALSE;
659 pcap_close(up->pcap_rfx);
660 up->pcap_rfx =
nullptr;
664 if (instance->context->channels)
665 freerdp_channels_close(instance->context->channels, instance);
667 IFCALL(instance->PostFinalDisconnect, instance);
669 freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
673#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
674BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
676 WINPR_ASSERT(instance);
677 return freerdp_disconnect_before_reconnect_context(instance->context);
681BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
683 rdpRdp* rdp =
nullptr;
685 WINPR_ASSERT(context);
688 return rdp_client_disconnect_and_clear(rdp);
691BOOL freerdp_reconnect(freerdp* instance)
693 rdpRdp* rdp =
nullptr;
695 WINPR_ASSERT(instance);
696 WINPR_ASSERT(instance->context);
698 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
701 rdp = instance->context->rdp;
703 if (!utils_reset_abort(instance->context->rdp))
705 return rdp_client_reconnect(rdp);
708#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
709BOOL freerdp_shall_disconnect(
const freerdp* instance)
714 return freerdp_shall_disconnect_context(instance->context);
718BOOL freerdp_shall_disconnect_context(
const rdpContext* context)
723 return utils_abort_event_is_set(context->rdp);
726BOOL freerdp_focus_required(freerdp* instance)
728 rdpRdp* rdp =
nullptr;
729 BOOL bRetCode = FALSE;
731 WINPR_ASSERT(instance);
732 WINPR_ASSERT(instance->context);
734 rdp = instance->context->rdp;
737 if (rdp->resendFocus)
740 rdp->resendFocus = FALSE;
746void freerdp_set_focus(freerdp* instance)
748 rdpRdp* rdp =
nullptr;
750 WINPR_ASSERT(instance);
751 WINPR_ASSERT(instance->context);
753 rdp = instance->context->rdp;
756 rdp->resendFocus = TRUE;
759void freerdp_get_version(
int* major,
int* minor,
int* revision)
761 if (major !=
nullptr)
762 *major = FREERDP_VERSION_MAJOR;
764 if (minor !=
nullptr)
765 *minor = FREERDP_VERSION_MINOR;
767 if (revision !=
nullptr)
768 *revision = FREERDP_VERSION_REVISION;
771const char* freerdp_get_version_string(
void)
773 return FREERDP_VERSION_FULL;
776const char* freerdp_get_build_config(
void)
778 WINPR_PRAGMA_DIAG_PUSH
779 WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
780 static const char build_config[] =
781 "Build configuration: " FREERDP_BUILD_CONFIG
"\n"
782 "Build type: " FREERDP_BUILD_TYPE
"\n"
783 "CFLAGS: " FREERDP_CFLAGS
"\n"
784 "Compiler: " FREERDP_COMPILER_ID
", " FREERDP_COMPILER_VERSION
"\n"
785 "Target architecture: " FREERDP_TARGET_ARCH
"\n";
786 WINPR_PRAGMA_DIAG_POP
790const char* freerdp_get_build_revision(
void)
792 return FREERDP_GIT_REVISION;
796 DEFINE_EVENT_ENTRY(WindowStateChange), DEFINE_EVENT_ENTRY(ResizeWindow),
797 DEFINE_EVENT_ENTRY(LocalResizeWindow), DEFINE_EVENT_ENTRY(EmbedWindow),
798 DEFINE_EVENT_ENTRY(PanningChange), DEFINE_EVENT_ENTRY(ZoomingChange),
799 DEFINE_EVENT_ENTRY(ErrorInfo), DEFINE_EVENT_ENTRY(Terminate),
800 DEFINE_EVENT_ENTRY(ConnectionResult), DEFINE_EVENT_ENTRY(ChannelConnected),
801 DEFINE_EVENT_ENTRY(ChannelDisconnected), DEFINE_EVENT_ENTRY(MouseEvent),
802 DEFINE_EVENT_ENTRY(Activated), DEFINE_EVENT_ENTRY(Timer),
803 DEFINE_EVENT_ENTRY(GraphicsReset), DEFINE_EVENT_ENTRY(UserNotification),
804 DEFINE_EVENT_ENTRY(ChannelInitialized), DEFINE_EVENT_ENTRY(ChannelTerminated),
805 DEFINE_EVENT_ENTRY(StateChanged)
818BOOL freerdp_context_new(freerdp* instance)
820 return freerdp_context_new_ex(instance,
nullptr);
823static BOOL freerdp_common_context(rdpContext* context, AccessTokenType tokenType,
char** token,
828 WINPR_ASSERT(context);
829 if (!context->instance || !context->instance->GetAccessToken)
832 va_list ap = WINPR_C_ARRAY_INIT;
836 case ACCESS_TOKEN_TYPE_AAD:
840 "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
846 const char* scope = va_arg(ap,
const char*);
847 const char* req_cnf = va_arg(ap,
const char*);
848 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count,
852 case ACCESS_TOKEN_TYPE_AVD:
856 "ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
862 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count);
871 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
876BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
878 rdpRdp* rdp =
nullptr;
879 rdpContext* context =
nullptr;
882 WINPR_ASSERT(instance);
884 instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
889 context->log = WLog_Get(TAG);
894 context->settings = settings;
895 context->instance = instance;
896 context->ServerMode = FALSE;
897 context->disconnectUltimatum = 0;
899 context->metrics = metrics_new(context);
901 if (!context->metrics)
904 rdp = rdp_new(context);
910 context->pubSub = rdp->pubSub;
912 if (!context->pubSub)
915 PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
917#if defined(WITH_FREERDP_DEPRECATED)
918 instance->input = rdp->input;
919 instance->update = rdp->update;
920 instance->settings = rdp->settings;
921 instance->autodetect = rdp->autodetect;
924 instance->heartbeat = rdp->heartbeat;
925 context->graphics = graphics_new(context);
927 if (!context->graphics)
930 context->input = rdp->input;
931 context->update = rdp->update;
932 context->settings = rdp->settings;
933 context->autodetect = rdp->autodetect;
935 if (!(context->errorDescription = calloc(1, 500)))
937 WLog_Print(context->log, WLOG_ERROR,
"calloc failed!");
941 if (!(context->channelErrorEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
943 WLog_Print(context->log, WLOG_ERROR,
"CreateEvent failed!");
947 update_register_client_callbacks(rdp->update);
949 if (!(context->channels = freerdp_channels_new(instance)))
952 context->dump = stream_dump_new();
960 if (!freerdp_set_common_access_token(context, freerdp_common_context))
963 IFCALLRET(instance->ContextNew, ret, instance, context);
971 freerdp_context_free(instance);
975BOOL freerdp_context_reset(freerdp* instance)
980 WINPR_ASSERT(instance->context);
981 rdpRdp* rdp = instance->context->rdp;
983 return rdp_reset_runtime_settings(rdp);
994void freerdp_context_free(freerdp* instance)
996 rdpContext* ctx =
nullptr;
1001 if (!instance->context)
1004 ctx = instance->context;
1006 IFCALL(instance->ContextFree, instance, ctx);
1009 ctx->settings =
nullptr;
1011 graphics_free(ctx->graphics);
1012 ctx->graphics =
nullptr;
1014 metrics_free(ctx->metrics);
1015 ctx->metrics =
nullptr;
1017 if (ctx->channelErrorEvent)
1018 (void)CloseHandle(ctx->channelErrorEvent);
1019 ctx->channelErrorEvent =
nullptr;
1021 free(ctx->errorDescription);
1022 ctx->errorDescription =
nullptr;
1024 freerdp_channels_free(ctx->channels);
1025 ctx->channels =
nullptr;
1027 freerdp_client_codecs_free(ctx->codecs);
1028 ctx->codecs =
nullptr;
1030 stream_dump_free(ctx->dump);
1031 ctx->dump =
nullptr;
1033 ctx->input =
nullptr;
1034 ctx->update =
nullptr;
1035 ctx->settings =
nullptr;
1036 ctx->autodetect =
nullptr;
1039 instance->context =
nullptr;
1040#if defined(WITH_FREERDP_DEPRECATED)
1041 instance->input =
nullptr;
1042 instance->update =
nullptr;
1043 instance->settings =
nullptr;
1044 instance->autodetect =
nullptr;
1046 instance->heartbeat =
nullptr;
1049int freerdp_get_disconnect_ultimatum(
const rdpContext* context)
1051 WINPR_ASSERT(context);
1052 return context->disconnectUltimatum;
1055UINT32 freerdp_error_info(
const freerdp* instance)
1057 WINPR_ASSERT(instance);
1058 WINPR_ASSERT(instance->context);
1059 WINPR_ASSERT(instance->context->rdp);
1060 return instance->context->rdp->errorInfo;
1063void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
1068 rdp_set_error_info(rdp, error);
1071BOOL freerdp_send_error_info(rdpRdp* rdp)
1076 return rdp_send_error_info(rdp);
1079UINT32 freerdp_get_last_error(
const rdpContext* context)
1081 WINPR_ASSERT(context);
1082 return context->LastError;
1085const char* freerdp_get_last_error_name(UINT32 code)
1087 const char* name =
nullptr;
1088 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1089 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1093 case FREERDP_ERROR_ERRBASE_CLASS:
1094 name = freerdp_get_error_base_name(type);
1097 case FREERDP_ERROR_ERRINFO_CLASS:
1098 name = freerdp_get_error_info_name(type);
1101 case FREERDP_ERROR_CONNECT_CLASS:
1102 name = freerdp_get_error_connect_name(type);
1106 name = rpc_error_to_string(code);
1113const char* freerdp_get_last_error_string(UINT32 code)
1115 const char*
string =
nullptr;
1116 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1117 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1121 case FREERDP_ERROR_ERRBASE_CLASS:
1122 string = freerdp_get_error_base_string(type);
1125 case FREERDP_ERROR_ERRINFO_CLASS:
1126 string = freerdp_get_error_info_string(type);
1129 case FREERDP_ERROR_CONNECT_CLASS:
1130 string = freerdp_get_error_connect_string(type);
1134 string = rpc_error_to_string(code);
1141const char* freerdp_get_last_error_category(UINT32 code)
1143 const char*
string =
nullptr;
1144 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1145 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1149 case FREERDP_ERROR_ERRBASE_CLASS:
1150 string = freerdp_get_error_base_category(type);
1153 case FREERDP_ERROR_ERRINFO_CLASS:
1154 string = freerdp_get_error_info_category(type);
1157 case FREERDP_ERROR_CONNECT_CLASS:
1158 string = freerdp_get_error_connect_category(type);
1162 string = rpc_error_to_category(code);
1169void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError,
const char* fkt,
1170 const char* file,
int line)
1172 WINPR_ASSERT(context);
1173 WINPR_ASSERT(line >= 0);
1177 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1179 WLog_PrintTextMessage(context->log, WLOG_ERROR, (
size_t)line, file, fkt,
1180 "%s [0x%08" PRIX32
"]", freerdp_get_last_error_name(lastError),
1185 if (lastError == FREERDP_ERROR_SUCCESS)
1187 if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1188 WLog_PrintTextMessage(context->log, WLOG_DEBUG, (
size_t)line, file, fkt,
1189 "resetting error state");
1191 else if (context->LastError != FREERDP_ERROR_SUCCESS)
1193 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1195 WLog_PrintTextMessage(context->log, WLOG_ERROR, (
size_t)line, file, fkt,
1196 "TODO: Trying to set error code %s, but %s already set!",
1197 freerdp_get_last_error_name(lastError),
1198 freerdp_get_last_error_name(context->LastError));
1201 context->LastError = lastError;
1204const char* freerdp_get_logon_error_info_type_ex(UINT32 type,
char* buffer,
size_t size)
1206 const char* str = freerdp_get_logon_error_info_type(type);
1207 (void)_snprintf(buffer, size,
"%s(0x%04" PRIx32
")", str, type);
1211const char* freerdp_get_logon_error_info_type(UINT32 type)
1213#define CASE_ENTRY(x) \
1218 CASE_ENTRY(LOGON_MSG_SESSION_BUSY_OPTIONS);
1219 CASE_ENTRY(LOGON_MSG_DISCONNECT_REFUSED);
1220 CASE_ENTRY(LOGON_MSG_NO_PERMISSION);
1221 CASE_ENTRY(LOGON_MSG_BUMP_OPTIONS);
1222 CASE_ENTRY(LOGON_MSG_RECONNECT_OPTIONS);
1223 CASE_ENTRY(LOGON_MSG_SESSION_TERMINATE);
1224 CASE_ENTRY(LOGON_MSG_SESSION_CONTINUE);
1225 CASE_ENTRY(ERROR_CODE_ACCESS_DENIED);
1228 return NtStatus2Tag((NTSTATUS)type);
1233const char* freerdp_get_logon_error_info_data(UINT32 data)
1235#define CASE_ENTRY(x) \
1240 CASE_ENTRY(LOGON_FAILED_BAD_PASSWORD);
1241 CASE_ENTRY(LOGON_FAILED_UPDATE_PASSWORD);
1242 CASE_ENTRY(LOGON_FAILED_OTHER);
1243 CASE_ENTRY(LOGON_WARNING);
1246 return "SESSION_ID";
1251const char* freerdp_get_logon_error_info_data_ex(UINT32 data,
char* buffer,
size_t size)
1253 const char* str = freerdp_get_logon_error_info_data(data);
1254 (void)_snprintf(buffer, size,
"%s(0x%04" PRIx32
")", str, data);
1261freerdp* freerdp_new(
void)
1263 if (!utils_set_umask())
1266 freerdp* instance = (freerdp*)calloc(1,
sizeof(freerdp));
1271 instance->ContextSize =
sizeof(rdpContext);
1272 instance->SendChannelData = freerdp_send_channel_data;
1273 instance->SendChannelPacket = freerdp_send_channel_packet;
1274 instance->ReceiveChannelData = freerdp_channels_data;
1282void freerdp_free(freerdp* instance)
1287ULONG freerdp_get_transport_sent(
const rdpContext* context, BOOL resetCount)
1289 WINPR_ASSERT(context);
1290 WINPR_ASSERT(context->rdp);
1291 UINT64 rc = transport_get_bytes_sent(context->rdp->transport, resetCount);
1292 return WINPR_CXX_COMPAT_CAST(ULONG, MIN(rc, UINT32_MAX));
1295BOOL freerdp_nla_impersonate(rdpContext* context)
1297 rdpNla* nla =
nullptr;
1305 if (!context->rdp->transport)
1308 nla = transport_get_nla(context->rdp->transport);
1309 return nla_impersonate(nla);
1312BOOL freerdp_nla_revert_to_self(rdpContext* context)
1314 rdpNla* nla =
nullptr;
1322 if (!context->rdp->transport)
1325 nla = transport_get_nla(context->rdp->transport);
1326 return nla_revert_to_self(nla);
1329UINT32 freerdp_get_nla_sspi_error(
const rdpContext* context)
1331 WINPR_ASSERT(context);
1332 WINPR_ASSERT(context->rdp);
1333 WINPR_ASSERT(context->rdp->transport);
1335 rdpNla* nla = context->rdp->nla;
1337 nla = transport_get_nla(context->rdp->transport);
1338 return (UINT32)nla_get_sspi_error(nla);
1341BOOL freerdp_nla_encrypt(rdpContext* context,
const SecBuffer* inBuffer,
SecBuffer* outBuffer)
1343 WINPR_ASSERT(context);
1344 WINPR_ASSERT(context->rdp);
1346 rdpNla* nla = context->rdp->nla;
1347 return nla_encrypt(nla, inBuffer, outBuffer);
1350BOOL freerdp_nla_decrypt(rdpContext* context,
const SecBuffer* inBuffer,
SecBuffer* outBuffer)
1352 WINPR_ASSERT(context);
1353 WINPR_ASSERT(context->rdp);
1355 rdpNla* nla = context->rdp->nla;
1356 return nla_decrypt(nla, inBuffer, outBuffer);
1359SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ulAttr, PVOID pBuffer)
1361 WINPR_ASSERT(context);
1362 WINPR_ASSERT(context->rdp);
1364 rdpNla* nla = context->rdp->nla;
1366 nla = transport_get_nla(context->rdp->transport);
1370 return nla_QueryContextAttributes(nla, ulAttr, pBuffer);
1373SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, PVOID pBuffer)
1375 WINPR_ASSERT(context);
1376 WINPR_ASSERT(context->rdp);
1378 rdpNla* nla = context->rdp->nla;
1380 nla = transport_get_nla(context->rdp->transport);
1384 return nla_FreeContextBuffer(nla, pBuffer);
1387HANDLE getChannelErrorEventHandle(rdpContext* context)
1389 WINPR_ASSERT(context);
1390 return context->channelErrorEvent;
1393BOOL checkChannelErrorEvent(rdpContext* context)
1395 WINPR_ASSERT(context);
1397 if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1399 WLog_Print(context->log, WLOG_ERROR,
"%s. Error was %" PRIu32
"", context->errorDescription,
1400 context->channelErrorNum);
1412UINT getChannelError(
const rdpContext* context)
1414 WINPR_ASSERT(context);
1415 return context->channelErrorNum;
1418const char* getChannelErrorDescription(
const rdpContext* context)
1420 WINPR_ASSERT(context);
1421 return context->errorDescription;
1424void clearChannelError(rdpContext* context)
1426 WINPR_ASSERT(context);
1427 context->channelErrorNum = 0;
1428 memset(context->errorDescription, 0, 500);
1429 (void)ResetEvent(context->channelErrorEvent);
1432WINPR_ATTR_FORMAT_ARG(3, 4)
1433void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const
char* format, ...)
1435 va_list ap = WINPR_C_ARRAY_INIT;
1436 va_start(ap, format);
1438 WINPR_ASSERT(context);
1440 context->channelErrorNum = errorNum;
1441 (void)vsnprintf(context->errorDescription, 499, format, ap);
1443 (void)SetEvent(context->channelErrorEvent);
1446const char* freerdp_nego_get_routing_token(
const rdpContext* context, DWORD* length)
1448 if (!context || !context->rdp)
1451 return (
const char*)nego_get_routing_token(context->rdp->nego, length);
1454BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1456 WINPR_ASSERT(context);
1457 return rdp_io_callback_set_event(context->rdp, set);
1460const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1462 WINPR_ASSERT(context);
1463 return rdp_get_io_callbacks(context->rdp);
1466BOOL freerdp_set_io_callbacks(rdpContext* context,
const rdpTransportIo* io_callbacks)
1468 WINPR_ASSERT(context);
1469 return rdp_set_io_callbacks(context->rdp, io_callbacks);
1472BOOL freerdp_set_io_callback_context(rdpContext* context,
void* usercontext)
1474 WINPR_ASSERT(context);
1475 return rdp_set_io_callback_context(context->rdp, usercontext);
1478void* freerdp_get_io_callback_context(rdpContext* context)
1480 WINPR_ASSERT(context);
1481 return rdp_get_io_callback_context(context->rdp);
1484CONNECTION_STATE freerdp_get_state(
const rdpContext* context)
1486 WINPR_ASSERT(context);
1487 return rdp_get_state(context->rdp);
1490const char* freerdp_state_string(CONNECTION_STATE state)
1492 return rdp_state_string(state);
1495BOOL freerdp_is_active_state(
const rdpContext* context)
1497 WINPR_ASSERT(context);
1498 return rdp_is_active_state(context->rdp);
1501BOOL freerdp_channels_from_mcs(rdpSettings* settings,
const rdpContext* context)
1503 WINPR_ASSERT(context);
1504 return rdp_channels_from_mcs(settings, context->rdp);
1507HANDLE freerdp_abort_event(rdpContext* context)
1509 WINPR_ASSERT(context);
1510 return utils_get_abort_event(context->rdp);
1513static void test_mcs_free(rdpMcs* mcs)
1520 rdpSettings* settings = mcs->context->settings;
1528static rdpMcs* test_mcs_new(
void)
1531 rdpContext* context = calloc(1,
sizeof(rdpContext));
1540 context->settings = settings;
1541 return mcs_new(context);
1550BOOL freerdp_is_valid_mcs_create_request(
const BYTE* data,
size_t size)
1553 wStream sbuffer = WINPR_C_ARRAY_INIT;
1554 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1556 WINPR_ASSERT(data || (size == 0));
1559 rdpMcs* mcs = test_mcs_new();
1562 BOOL result = mcs_recv_connect_initial(mcs, s);
1567BOOL freerdp_is_valid_mcs_create_response(
const BYTE* data,
size_t size)
1570 wStream sbuffer = WINPR_C_ARRAY_INIT;
1571 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1573 WINPR_ASSERT(data || (size == 0));
1576 rdpMcs* mcs = test_mcs_new();
1579 BOOL result = mcs_recv_connect_response(mcs, s);
1584BOOL freerdp_persist_credentials(rdpContext* context)
1588 WINPR_ASSERT(context->rdp);
1589 return utils_persist_credentials(context->rdp->originalSettings, context->rdp->settings);
1592const char* freerdp_disconnect_reason_string(
int reason)
1596 case Disconnect_Ultimatum_domain_disconnected:
1597 return "rn-domain-disconnected";
1598 case Disconnect_Ultimatum_provider_initiated:
1599 return "rn-provider-initiated";
1600 case Disconnect_Ultimatum_token_purged:
1601 return "rn-token-purged";
1602 case Disconnect_Ultimatum_user_requested:
1603 return "rn-user-requested";
1604 case Disconnect_Ultimatum_channel_purged:
1605 return "rn-channel-purged";
1607 return "rn-unknown";
1611BOOL freerdp_set_common_access_token(rdpContext* context,
1612 pGetCommonAccessToken GetCommonAccessToken)
1614 WINPR_ASSERT(context);
1615 WINPR_ASSERT(context->rdp);
1616 context->rdp->GetCommonAccessToken = GetCommonAccessToken;
1620pGetCommonAccessToken freerdp_get_common_access_token(
const rdpContext* context)
1622 WINPR_ASSERT(context);
1623 WINPR_ASSERT(context->rdp);
1624 return context->rdp->GetCommonAccessToken;
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.