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>
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>
61#include "../cache/pointer.h"
64#define TAG FREERDP_TAG("core")
66static void sig_abort_connect(
int signum,
const char* signame,
void* ctx)
68 rdpContext* context = (rdpContext*)ctx;
70 WLog_INFO(TAG,
"Signal %s [%d], terminating session %p", signame, signum,
71 WINPR_CXX_COMPAT_CAST(
const void*, context));
73 freerdp_abort_connect_context(context);
87static int freerdp_connect_begin(freerdp* instance)
90 rdpRdp* rdp =
nullptr;
92 rdpSettings* settings =
nullptr;
97 WINPR_ASSERT(instance->context);
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))
106 rdp = instance->context->rdp;
109 settings = instance->context->settings;
110 WINPR_ASSERT(settings);
112 freerdp_channels_register_instance(instance->context->channels, instance);
114 if (!freerdp_settings_set_default_order_support(settings))
117 if (!freerdp_add_signal_cleanup_handler(instance->context, sig_abort_connect))
120 IFCALLRET(instance->PreConnect, status, instance);
121 instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED;
123 freerdp_settings_print_warnings(settings);
125 status = freerdp_settings_enforce_monitor_exists(settings);
128 status = freerdp_settings_enforce_consistency(settings);
131 status = freerdp_settings_check_client_after_preconnect(settings);
134 status = rdp_set_backup_settings(rdp);
136 status = utils_reload_channels(instance->context);
139 int64_t KeyboardLayout = freerdp_get_keyboard_default_layout_for_locale(cp);
140 if (KeyboardLayout == 0)
143 switch (KeyboardLayout)
146 case KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002:
149 WINPR_KBD_TYPE_JAPANESE))
163 rdpContext* context = instance->context;
164 WINPR_ASSERT(context);
165 freerdp_set_last_error_if_not(context, FREERDP_ERROR_PRE_CONNECT_FAILED);
167 WLog_Print(context->log, WLOG_ERROR,
"freerdp_pre_connect failed: %s",
168 rdp_client_connection_state_string(instance->ConnectionCallbackState));
172 rc = rdp_client_connect(rdp);
177 rdpContext* context = rdp->context;
178 WINPR_ASSERT(context);
179 WLog_Print(context->log, WLOG_ERROR,
"Authentication only, exit status %" PRId32
"", rc);
186BOOL freerdp_connect(freerdp* instance)
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;
194 WINPR_ASSERT(instance);
195 WINPR_ASSERT(instance->context);
197 rdp = instance->context->rdp;
199 WINPR_ASSERT(rdp->settings);
208 up->pcap_rfx = pcap_open(
215 pointer_cache_register_callbacks(instance->context->update);
216 status = IFCALLRESULT(TRUE, instance->PostConnect, instance);
217 instance->ConnectionCallbackState = CLIENT_STATE_POSTCONNECT_PASSED;
220 status2 = freerdp_channels_post_connect(instance->context->channels, instance);
224 status2 = CHANNEL_RC_OK;
225 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)
226 status = freerdp_reconnect(instance);
228 goto freerdp_connect_finally;
231 if (!status || (status2 != CHANNEL_RC_OK) || !update_post_connect(instance->context->update))
233 rdpContext* context = instance->context;
234 WINPR_ASSERT(context);
235 WLog_Print(context->log, WLOG_ERROR,
"freerdp_post_connect failed");
237 freerdp_set_last_error_if_not(context, FREERDP_ERROR_POST_CONNECT_FAILED);
240 goto freerdp_connect_finally;
247 pcap_record record = WINPR_C_ARRAY_INIT;
249 WINPR_ASSERT(update);
250 const char* PlayRemoteFxFile =
252 update->pcap_rfx = pcap_open(PlayRemoteFxFile, FALSE);
255 if (!update->pcap_rfx)
256 goto freerdp_connect_finally;
258 update->play_rfx = TRUE;
262 while (pcap_has_next_record(update->pcap_rfx) && status)
264 if (!pcap_get_next_record_header(update->pcap_rfx, &record))
267 s = transport_take_from_pool(rdp->transport, record.length);
271 record.data = Stream_Buffer(s);
272 if (!pcap_get_next_record_content(update->pcap_rfx, &record))
274 if (!Stream_SetLength(s, record.length))
279 Stream_ResetPosition(s);
281 if (!update_begin_paint(&update->common))
285 if (!update_recv_surfcmds(&update->common, s))
288 if (!update_end_paint(&update->common))
295 pcap_close(update->pcap_rfx);
296 update->pcap_rfx =
nullptr;
297 goto freerdp_connect_finally;
300 if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
301 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
304 status = transport_set_connected_event(rdp->transport);
306freerdp_connect_finally:
307 EventArgsInit(&e,
"freerdp");
308 e.result = status ? 0 : -1;
309 if (PubSub_OnConnectionResult(rdp->pubSub, instance->context, &e) < 0)
313 freerdp_disconnect(instance);
318#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
319BOOL freerdp_abort_connect(freerdp* instance)
324 return freerdp_abort_connect_context(instance->context);
328BOOL freerdp_abort_connect_context(rdpContext* context)
333 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
334 return utils_abort_connect(context->rdp);
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)
341 rdpRdp* rdp =
nullptr;
343 WINPR_ASSERT(instance);
344 WINPR_ASSERT(instance->context);
346 rdp = instance->context->rdp;
349 transport_get_fds(rdp->transport, rfds, rcount);
354BOOL freerdp_check_fds(freerdp* instance)
357 rdpRdp* rdp =
nullptr;
362 if (!instance->context)
365 if (!instance->context->rdp)
368 rdp = instance->context->rdp;
369 status = rdp_check_fds(rdp);
373 TerminateEventArgs e;
374 rdpContext* context = instance->context;
375 WINPR_ASSERT(context);
377 WLog_Print(context->log, WLOG_DEBUG,
"rdp_check_fds() - %i", status);
378 EventArgsInit(&e,
"freerdp");
380 if (PubSub_OnTerminate(rdp->pubSub, context, &e) < 0)
388DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count)
392 WINPR_ASSERT(context);
393 WINPR_ASSERT(context->rdp);
394 WINPR_ASSERT(events || (count == 0));
396 const size_t rrc = rdp_get_event_handles(context->rdp, &events[nCount], count - nCount);
400 nCount += WINPR_ASSERTING_INT_CAST(uint32_t, rrc);
402 if (events && (nCount < count + 2))
404 events[nCount++] = freerdp_channels_get_event_handle(context->instance);
405 events[nCount++] = getChannelErrorEventHandle(context);
410 const SSIZE_T rc = freerdp_client_channel_get_registered_event_handles(
411 context->channels, &events[nCount], count - nCount);
414 return nCount + (DWORD)rc;
418static BOOL freerdp_prevent_session_lock(rdpContext* context)
420 WINPR_ASSERT(context);
421 WINPR_ASSERT(context->input);
425 UINT32 FakeMouseMotionInterval =
427 if (FakeMouseMotionInterval && in->lastInputTimestamp)
429 const time_t now = time(
nullptr);
430 if (WINPR_ASSERTING_INT_CAST(
size_t, now) - in->lastInputTimestamp >
431 FakeMouseMotionInterval)
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);
438 BOOL status = freerdp_input_send_mouse_event(context->input, PTR_FLAGS_MOVE, in->lastX,
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);
456BOOL freerdp_check_event_handles(rdpContext* context)
458 WINPR_ASSERT(context);
460 BOOL status = freerdp_check_fds(context->instance);
464 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
465 WLog_Print(context->log, WLOG_ERROR,
"freerdp_check_fds() failed - %" PRIi32
"",
471 status = freerdp_channels_check_fds(context->channels, context->instance);
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);
482 status = checkChannelErrorEvent(context);
486 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
487 WLog_Print(context->log, WLOG_ERROR,
"checkChannelErrorEvent() failed - %" PRIi32
"",
493 status = freerdp_prevent_session_lock(context);
498wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD
id)
500 wMessageQueue* queue =
nullptr;
502 WINPR_ASSERT(instance);
504 rdpContext* context = instance->context;
505 WINPR_ASSERT(context);
509 case FREERDP_UPDATE_MESSAGE_QUEUE:
512 queue = update->queue;
516 case FREERDP_INPUT_MESSAGE_QUEUE:
519 queue = input->queue;
529HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD
id)
531 HANDLE
event =
nullptr;
532 wMessageQueue* queue = freerdp_get_message_queue(instance,
id);
535 event = MessageQueue_Event(queue);
540int freerdp_message_queue_process_message(freerdp* instance, DWORD
id, wMessage* message)
543 rdpContext* context =
nullptr;
545 WINPR_ASSERT(instance);
547 context = instance->context;
548 WINPR_ASSERT(context);
552 case FREERDP_UPDATE_MESSAGE_QUEUE:
553 status = update_message_queue_process_message(context->update, message);
556 case FREERDP_INPUT_MESSAGE_QUEUE:
557 status = input_message_queue_process_message(context->input, message);
566int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD
id)
569 rdpContext* context =
nullptr;
571 WINPR_ASSERT(instance);
573 context = instance->context;
574 WINPR_ASSERT(context);
578 case FREERDP_UPDATE_MESSAGE_QUEUE:
579 status = update_message_queue_process_pending_messages(context->update);
582 case FREERDP_INPUT_MESSAGE_QUEUE:
583 status = input_message_queue_process_pending_messages(context->input);
592static BOOL freerdp_send_channel_data(freerdp* instance, UINT16 channelId,
const BYTE* data,
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);
601static BOOL freerdp_send_channel_packet(freerdp* instance, UINT16 channelId,
size_t totalSize,
602 UINT32 flags,
const BYTE* data,
size_t chunkSize)
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,
611BOOL freerdp_disconnect(freerdp* instance)
615 if (!instance || !instance->context)
618 rdpRdp* rdp = instance->context->rdp;
623 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
625 (void)mcs_send_disconnect_provider_ultimatum(rdp->mcs,
626 Disconnect_Ultimatum_user_requested);
630 utils_abort_connect(rdp);
632 if (!rdp_client_disconnect(rdp))
636 if (rdp && rdp->update)
638 up = update_cast(rdp->update);
640 update_post_disconnect(rdp->update);
643 IFCALL(instance->PostDisconnect, instance);
644 cache_free(instance->context->cache);
645 instance->context->cache =
nullptr;
649 update_dump_stats(rdp->update);
652 up->dump_rfx = FALSE;
653 pcap_close(up->pcap_rfx);
654 up->pcap_rfx =
nullptr;
658 if (instance->context->channels)
659 freerdp_channels_close(instance->context->channels, instance);
661 IFCALL(instance->PostFinalDisconnect, instance);
663 freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
667#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
668BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
670 WINPR_ASSERT(instance);
671 return freerdp_disconnect_before_reconnect_context(instance->context);
675BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
677 rdpRdp* rdp =
nullptr;
679 WINPR_ASSERT(context);
682 return rdp_client_disconnect_and_clear(rdp);
685BOOL freerdp_reconnect(freerdp* instance)
687 rdpRdp* rdp =
nullptr;
689 WINPR_ASSERT(instance);
690 WINPR_ASSERT(instance->context);
692 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
695 rdp = instance->context->rdp;
697 if (!utils_reset_abort(instance->context->rdp))
699 return rdp_client_reconnect(rdp);
702#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
703BOOL freerdp_shall_disconnect(
const freerdp* instance)
708 return freerdp_shall_disconnect_context(instance->context);
712BOOL freerdp_shall_disconnect_context(
const rdpContext* context)
717 return utils_abort_event_is_set(context->rdp);
720BOOL freerdp_focus_required(freerdp* instance)
722 rdpRdp* rdp =
nullptr;
723 BOOL bRetCode = FALSE;
725 WINPR_ASSERT(instance);
726 WINPR_ASSERT(instance->context);
728 rdp = instance->context->rdp;
731 if (rdp->resendFocus)
734 rdp->resendFocus = FALSE;
740void freerdp_set_focus(freerdp* instance)
742 rdpRdp* rdp =
nullptr;
744 WINPR_ASSERT(instance);
745 WINPR_ASSERT(instance->context);
747 rdp = instance->context->rdp;
750 rdp->resendFocus = TRUE;
753void freerdp_get_version(
int* major,
int* minor,
int* revision)
755 if (major !=
nullptr)
756 *major = FREERDP_VERSION_MAJOR;
758 if (minor !=
nullptr)
759 *minor = FREERDP_VERSION_MINOR;
761 if (revision !=
nullptr)
762 *revision = FREERDP_VERSION_REVISION;
765const char* freerdp_get_version_string(
void)
767 return FREERDP_VERSION_FULL;
770const char* freerdp_get_build_config(
void)
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
784const char* freerdp_get_build_revision(
void)
786 return FREERDP_GIT_REVISION;
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)
812BOOL freerdp_context_new(freerdp* instance)
814 return freerdp_context_new_ex(instance,
nullptr);
817static BOOL freerdp_common_context(rdpContext* context, AccessTokenType tokenType,
char** token,
822 WINPR_ASSERT(context);
823 if (!context->instance || !context->instance->GetAccessToken)
826 va_list ap = WINPR_C_ARRAY_INIT;
830 case ACCESS_TOKEN_TYPE_AAD:
834 "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
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,
846 case ACCESS_TOKEN_TYPE_AVD:
850 "ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
856 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count);
865 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
870BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
872 rdpRdp* rdp =
nullptr;
873 rdpContext* context =
nullptr;
876 WINPR_ASSERT(instance);
878 instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
883 context->log = WLog_Get(TAG);
888 context->settings = settings;
889 context->instance = instance;
890 context->ServerMode = FALSE;
891 context->disconnectUltimatum = 0;
893 context->metrics = metrics_new(context);
895 if (!context->metrics)
898 rdp = rdp_new(context);
904 context->pubSub = rdp->pubSub;
906 if (!context->pubSub)
909 PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
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;
918 instance->heartbeat = rdp->heartbeat;
919 context->graphics = graphics_new(context);
921 if (!context->graphics)
924 context->input = rdp->input;
925 context->update = rdp->update;
926 context->settings = rdp->settings;
927 context->autodetect = rdp->autodetect;
929 if (!(context->errorDescription = calloc(1, 500)))
931 WLog_Print(context->log, WLOG_ERROR,
"calloc failed!");
935 if (!(context->channelErrorEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
937 WLog_Print(context->log, WLOG_ERROR,
"CreateEvent failed!");
941 update_register_client_callbacks(rdp->update);
943 if (!(context->channels = freerdp_channels_new(instance)))
946 context->dump = stream_dump_new();
954 if (!freerdp_set_common_access_token(context, freerdp_common_context))
957 IFCALLRET(instance->ContextNew, ret, instance, context);
965 freerdp_context_free(instance);
969BOOL freerdp_context_reset(freerdp* instance)
974 WINPR_ASSERT(instance->context);
975 rdpRdp* rdp = instance->context->rdp;
977 return rdp_reset_runtime_settings(rdp);
988void freerdp_context_free(freerdp* instance)
990 rdpContext* ctx =
nullptr;
995 if (!instance->context)
998 ctx = instance->context;
1000 IFCALL(instance->ContextFree, instance, ctx);
1003 ctx->settings =
nullptr;
1005 graphics_free(ctx->graphics);
1006 ctx->graphics =
nullptr;
1008 metrics_free(ctx->metrics);
1009 ctx->metrics =
nullptr;
1011 if (ctx->channelErrorEvent)
1012 (void)CloseHandle(ctx->channelErrorEvent);
1013 ctx->channelErrorEvent =
nullptr;
1015 free(ctx->errorDescription);
1016 ctx->errorDescription =
nullptr;
1018 freerdp_channels_free(ctx->channels);
1019 ctx->channels =
nullptr;
1021 freerdp_client_codecs_free(ctx->codecs);
1022 ctx->codecs =
nullptr;
1024 stream_dump_free(ctx->dump);
1025 ctx->dump =
nullptr;
1027 ctx->input =
nullptr;
1028 ctx->update =
nullptr;
1029 ctx->settings =
nullptr;
1030 ctx->autodetect =
nullptr;
1033 instance->context =
nullptr;
1034#if defined(WITH_FREERDP_DEPRECATED)
1035 instance->input =
nullptr;
1036 instance->update =
nullptr;
1037 instance->settings =
nullptr;
1038 instance->autodetect =
nullptr;
1040 instance->heartbeat =
nullptr;
1043int freerdp_get_disconnect_ultimatum(
const rdpContext* context)
1045 WINPR_ASSERT(context);
1046 return context->disconnectUltimatum;
1049UINT32 freerdp_error_info(
const freerdp* instance)
1051 WINPR_ASSERT(instance);
1052 WINPR_ASSERT(instance->context);
1053 WINPR_ASSERT(instance->context->rdp);
1054 return instance->context->rdp->errorInfo;
1057void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
1062 rdp_set_error_info(rdp, error);
1065BOOL freerdp_send_error_info(rdpRdp* rdp)
1070 return rdp_send_error_info(rdp);
1073UINT32 freerdp_get_last_error(
const rdpContext* context)
1075 WINPR_ASSERT(context);
1076 return context->LastError;
1079const char* freerdp_get_last_error_name(UINT32 code)
1081 const char* name =
nullptr;
1082 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1083 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1087 case FREERDP_ERROR_ERRBASE_CLASS:
1088 name = freerdp_get_error_base_name(type);
1091 case FREERDP_ERROR_ERRINFO_CLASS:
1092 name = freerdp_get_error_info_name(type);
1095 case FREERDP_ERROR_CONNECT_CLASS:
1096 name = freerdp_get_error_connect_name(type);
1100 name = rpc_error_to_string(code);
1107const char* freerdp_get_last_error_string(UINT32 code)
1109 const char*
string =
nullptr;
1110 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1111 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1115 case FREERDP_ERROR_ERRBASE_CLASS:
1116 string = freerdp_get_error_base_string(type);
1119 case FREERDP_ERROR_ERRINFO_CLASS:
1120 string = freerdp_get_error_info_string(type);
1123 case FREERDP_ERROR_CONNECT_CLASS:
1124 string = freerdp_get_error_connect_string(type);
1128 string = rpc_error_to_string(code);
1135const char* freerdp_get_last_error_category(UINT32 code)
1137 const char*
string =
nullptr;
1138 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1139 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1143 case FREERDP_ERROR_ERRBASE_CLASS:
1144 string = freerdp_get_error_base_category(type);
1147 case FREERDP_ERROR_ERRINFO_CLASS:
1148 string = freerdp_get_error_info_category(type);
1151 case FREERDP_ERROR_CONNECT_CLASS:
1152 string = freerdp_get_error_connect_category(type);
1156 string = rpc_error_to_category(code);
1163void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError,
const char* fkt,
1164 const char* file,
int line)
1166 WINPR_ASSERT(context);
1167 WINPR_ASSERT(line >= 0);
1171 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1173 WLog_PrintTextMessage(context->log, WLOG_ERROR, (
size_t)line, file, fkt,
1174 "%s [0x%08" PRIX32
"]", freerdp_get_last_error_name(lastError),
1179 if (lastError == FREERDP_ERROR_SUCCESS)
1181 if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1182 WLog_PrintTextMessage(context->log, WLOG_DEBUG, (
size_t)line, file, fkt,
1183 "resetting error state");
1185 else if (context->LastError != FREERDP_ERROR_SUCCESS)
1187 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
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));
1195 context->LastError = lastError;
1198const char* freerdp_get_logon_error_info_type_ex(UINT32 type,
char* buffer,
size_t size)
1200 const char* str = freerdp_get_logon_error_info_type(type);
1201 (void)_snprintf(buffer, size,
"%s(0x%04" PRIx32
")", str, type);
1205const char* freerdp_get_logon_error_info_type(UINT32 type)
1207#define CASE_ENTRY(x) \
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);
1227const char* freerdp_get_logon_error_info_data(UINT32 data)
1231 case LOGON_FAILED_BAD_PASSWORD:
1232 return "LOGON_FAILED_BAD_PASSWORD";
1234 case LOGON_FAILED_UPDATE_PASSWORD:
1235 return "LOGON_FAILED_UPDATE_PASSWORD";
1237 case LOGON_FAILED_OTHER:
1238 return "LOGON_FAILED_OTHER";
1241 return "LOGON_WARNING";
1244 return "SESSION_ID";
1248const char* freerdp_get_logon_error_info_data_ex(UINT32 data,
char* buffer,
size_t size)
1250 const char* str = freerdp_get_logon_error_info_data(data);
1251 (void)_snprintf(buffer, size,
"%s(0x%04" PRIx32
")", str, data);
1258freerdp* freerdp_new(
void)
1260 freerdp* instance =
nullptr;
1261 instance = (freerdp*)calloc(1,
sizeof(freerdp));
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;
1277void freerdp_free(freerdp* instance)
1282ULONG freerdp_get_transport_sent(
const rdpContext* context, BOOL resetCount)
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));
1290BOOL freerdp_nla_impersonate(rdpContext* context)
1292 rdpNla* nla =
nullptr;
1300 if (!context->rdp->transport)
1303 nla = transport_get_nla(context->rdp->transport);
1304 return nla_impersonate(nla);
1307BOOL freerdp_nla_revert_to_self(rdpContext* context)
1309 rdpNla* nla =
nullptr;
1317 if (!context->rdp->transport)
1320 nla = transport_get_nla(context->rdp->transport);
1321 return nla_revert_to_self(nla);
1324UINT32 freerdp_get_nla_sspi_error(
const rdpContext* context)
1326 WINPR_ASSERT(context);
1327 WINPR_ASSERT(context->rdp);
1328 WINPR_ASSERT(context->rdp->transport);
1330 rdpNla* nla = context->rdp->nla;
1332 nla = transport_get_nla(context->rdp->transport);
1333 return (UINT32)nla_get_sspi_error(nla);
1336BOOL freerdp_nla_encrypt(rdpContext* context,
const SecBuffer* inBuffer,
SecBuffer* outBuffer)
1338 WINPR_ASSERT(context);
1339 WINPR_ASSERT(context->rdp);
1341 rdpNla* nla = context->rdp->nla;
1342 return nla_encrypt(nla, inBuffer, outBuffer);
1345BOOL freerdp_nla_decrypt(rdpContext* context,
const SecBuffer* inBuffer,
SecBuffer* outBuffer)
1347 WINPR_ASSERT(context);
1348 WINPR_ASSERT(context->rdp);
1350 rdpNla* nla = context->rdp->nla;
1351 return nla_decrypt(nla, inBuffer, outBuffer);
1354SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ulAttr, PVOID pBuffer)
1356 WINPR_ASSERT(context);
1357 WINPR_ASSERT(context->rdp);
1359 rdpNla* nla = context->rdp->nla;
1361 nla = transport_get_nla(context->rdp->transport);
1365 return nla_QueryContextAttributes(nla, ulAttr, pBuffer);
1368SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, PVOID pBuffer)
1370 WINPR_ASSERT(context);
1371 WINPR_ASSERT(context->rdp);
1373 rdpNla* nla = context->rdp->nla;
1375 nla = transport_get_nla(context->rdp->transport);
1379 return nla_FreeContextBuffer(nla, pBuffer);
1382HANDLE getChannelErrorEventHandle(rdpContext* context)
1384 WINPR_ASSERT(context);
1385 return context->channelErrorEvent;
1388BOOL checkChannelErrorEvent(rdpContext* context)
1390 WINPR_ASSERT(context);
1392 if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1394 WLog_Print(context->log, WLOG_ERROR,
"%s. Error was %" PRIu32
"", context->errorDescription,
1395 context->channelErrorNum);
1407UINT getChannelError(
const rdpContext* context)
1409 WINPR_ASSERT(context);
1410 return context->channelErrorNum;
1413const char* getChannelErrorDescription(
const rdpContext* context)
1415 WINPR_ASSERT(context);
1416 return context->errorDescription;
1419void clearChannelError(rdpContext* context)
1421 WINPR_ASSERT(context);
1422 context->channelErrorNum = 0;
1423 memset(context->errorDescription, 0, 500);
1424 (void)ResetEvent(context->channelErrorEvent);
1427WINPR_ATTR_FORMAT_ARG(3, 4)
1428void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const
char* format, ...)
1430 va_list ap = WINPR_C_ARRAY_INIT;
1431 va_start(ap, format);
1433 WINPR_ASSERT(context);
1435 context->channelErrorNum = errorNum;
1436 (void)vsnprintf(context->errorDescription, 499, format, ap);
1438 (void)SetEvent(context->channelErrorEvent);
1441const char* freerdp_nego_get_routing_token(
const rdpContext* context, DWORD* length)
1443 if (!context || !context->rdp)
1446 return (
const char*)nego_get_routing_token(context->rdp->nego, length);
1449BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1451 WINPR_ASSERT(context);
1452 return rdp_io_callback_set_event(context->rdp, set);
1455const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1457 WINPR_ASSERT(context);
1458 return rdp_get_io_callbacks(context->rdp);
1461BOOL freerdp_set_io_callbacks(rdpContext* context,
const rdpTransportIo* io_callbacks)
1463 WINPR_ASSERT(context);
1464 return rdp_set_io_callbacks(context->rdp, io_callbacks);
1467BOOL freerdp_set_io_callback_context(rdpContext* context,
void* usercontext)
1469 WINPR_ASSERT(context);
1470 return rdp_set_io_callback_context(context->rdp, usercontext);
1473void* freerdp_get_io_callback_context(rdpContext* context)
1475 WINPR_ASSERT(context);
1476 return rdp_get_io_callback_context(context->rdp);
1479CONNECTION_STATE freerdp_get_state(
const rdpContext* context)
1481 WINPR_ASSERT(context);
1482 return rdp_get_state(context->rdp);
1485const char* freerdp_state_string(CONNECTION_STATE state)
1487 return rdp_state_string(state);
1490BOOL freerdp_is_active_state(
const rdpContext* context)
1492 WINPR_ASSERT(context);
1493 return rdp_is_active_state(context->rdp);
1496BOOL freerdp_channels_from_mcs(rdpSettings* settings,
const rdpContext* context)
1498 WINPR_ASSERT(context);
1499 return rdp_channels_from_mcs(settings, context->rdp);
1502HANDLE freerdp_abort_event(rdpContext* context)
1504 WINPR_ASSERT(context);
1505 return utils_get_abort_event(context->rdp);
1508static void test_mcs_free(rdpMcs* mcs)
1515 rdpSettings* settings = mcs->context->settings;
1523static rdpMcs* test_mcs_new(
void)
1526 rdpContext* context = calloc(1,
sizeof(rdpContext));
1535 context->settings = settings;
1536 return mcs_new(context);
1545BOOL freerdp_is_valid_mcs_create_request(
const BYTE* data,
size_t size)
1548 wStream sbuffer = WINPR_C_ARRAY_INIT;
1549 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1551 WINPR_ASSERT(data || (size == 0));
1554 rdpMcs* mcs = test_mcs_new();
1557 BOOL result = mcs_recv_connect_initial(mcs, s);
1562BOOL freerdp_is_valid_mcs_create_response(
const BYTE* data,
size_t size)
1565 wStream sbuffer = WINPR_C_ARRAY_INIT;
1566 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1568 WINPR_ASSERT(data || (size == 0));
1571 rdpMcs* mcs = test_mcs_new();
1574 BOOL result = mcs_recv_connect_response(mcs, s);
1579BOOL freerdp_persist_credentials(rdpContext* context)
1583 WINPR_ASSERT(context->rdp);
1584 return utils_persist_credentials(context->rdp->originalSettings, context->rdp->settings);
1587const char* freerdp_disconnect_reason_string(
int reason)
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";
1602 return "rn-unknown";
1606BOOL freerdp_set_common_access_token(rdpContext* context,
1607 pGetCommonAccessToken GetCommonAccessToken)
1609 WINPR_ASSERT(context);
1610 WINPR_ASSERT(context->rdp);
1611 context->rdp->GetCommonAccessToken = GetCommonAccessToken;
1615pGetCommonAccessToken freerdp_get_common_access_token(
const rdpContext* context)
1617 WINPR_ASSERT(context);
1618 WINPR_ASSERT(context->rdp);
1619 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.