22#include <freerdp/config.h>
35#include "connection.h"
37#include <freerdp/buildflags.h>
38#include "gateway/rpc_fault.h"
40#include <winpr/assert.h>
43#include <winpr/string.h>
44#include <winpr/stream.h>
45#include <winpr/wtsapi.h>
47#include <winpr/debug.h>
49#include <freerdp/freerdp.h>
50#include <freerdp/streamdump.h>
51#include <freerdp/error.h>
52#include <freerdp/event.h>
53#include <freerdp/locale/keyboard.h>
54#include <freerdp/locale/locale.h>
55#include <freerdp/channels/channels.h>
56#include <freerdp/version.h>
57#include <freerdp/log.h>
58#include <freerdp/utils/signal.h>
60#include "../cache/pointer.h"
63#define TAG FREERDP_TAG("core")
65static void sig_abort_connect(
int signum,
const char* signame,
void* ctx)
67 rdpContext* context = (rdpContext*)ctx;
69 WLog_INFO(TAG,
"Signal %s [%d], terminating session %p", signame, signum,
70 WINPR_CXX_COMPAT_CAST(
const void*, context));
72 freerdp_abort_connect_context(context);
86static int freerdp_connect_begin(freerdp* instance)
89 rdpRdp* rdp =
nullptr;
91 rdpSettings* settings =
nullptr;
96 WINPR_ASSERT(instance->context);
99 instance->ConnectionCallbackState = CLIENT_STATE_INITIAL;
100 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS);
101 clearChannelError(instance->context);
102 if (!utils_reset_abort(instance->context->rdp))
105 rdp = instance->context->rdp;
108 settings = instance->context->settings;
109 WINPR_ASSERT(settings);
111 freerdp_channels_register_instance(instance->context->channels, instance);
113 if (!freerdp_settings_set_default_order_support(settings))
116 if (!freerdp_add_signal_cleanup_handler(instance->context, sig_abort_connect))
119 IFCALLRET(instance->PreConnect, status, instance);
120 instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED;
122 freerdp_settings_print_warnings(settings);
124 status = freerdp_settings_enforce_monitor_exists(settings);
127 status = freerdp_settings_enforce_consistency(settings);
130 status = freerdp_settings_check_client_after_preconnect(settings);
133 status = rdp_set_backup_settings(rdp);
135 status = utils_reload_channels(instance->context);
138 int64_t KeyboardLayout = freerdp_get_keyboard_default_layout_for_locale(cp);
139 if (KeyboardLayout == 0)
142 switch (KeyboardLayout)
145 case KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002:
148 WINPR_KBD_TYPE_JAPANESE))
162 rdpContext* context = instance->context;
163 WINPR_ASSERT(context);
164 freerdp_set_last_error_if_not(context, FREERDP_ERROR_PRE_CONNECT_FAILED);
166 WLog_Print(context->log, WLOG_ERROR,
"freerdp_pre_connect failed: %s",
167 rdp_client_connection_state_string(instance->ConnectionCallbackState));
171 rc = rdp_client_connect(rdp);
176 rdpContext* context = rdp->context;
177 WINPR_ASSERT(context);
178 WLog_Print(context->log, WLOG_ERROR,
"Authentication only, exit status %" PRId32
"", rc);
185BOOL freerdp_connect(freerdp* instance)
188 ConnectionResultEventArgs e = WINPR_C_ARRAY_INIT;
189 const int rc = freerdp_connect_begin(instance);
190 rdpRdp* rdp =
nullptr;
191 UINT status2 = ERROR_INTERNAL_ERROR;
193 WINPR_ASSERT(instance);
194 WINPR_ASSERT(instance->context);
196 rdp = instance->context->rdp;
198 WINPR_ASSERT(rdp->settings);
207 up->pcap_rfx = pcap_open(
214 pointer_cache_register_callbacks(instance->context->update);
215 status = IFCALLRESULT(TRUE, instance->PostConnect, instance);
216 instance->ConnectionCallbackState = CLIENT_STATE_POSTCONNECT_PASSED;
219 status2 = freerdp_channels_post_connect(instance->context->channels, instance);
223 status2 = CHANNEL_RC_OK;
224 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)
225 status = freerdp_reconnect(instance);
227 goto freerdp_connect_finally;
230 if (!status || (status2 != CHANNEL_RC_OK) || !update_post_connect(instance->context->update))
232 rdpContext* context = instance->context;
233 WINPR_ASSERT(context);
234 WLog_Print(context->log, WLOG_ERROR,
"freerdp_post_connect failed");
236 freerdp_set_last_error_if_not(context, FREERDP_ERROR_POST_CONNECT_FAILED);
239 goto freerdp_connect_finally;
246 pcap_record record = WINPR_C_ARRAY_INIT;
248 WINPR_ASSERT(update);
249 const char* PlayRemoteFxFile =
251 update->pcap_rfx = pcap_open(PlayRemoteFxFile, FALSE);
254 if (!update->pcap_rfx)
255 goto freerdp_connect_finally;
257 update->play_rfx = TRUE;
261 while (pcap_has_next_record(update->pcap_rfx) && status)
263 if (!pcap_get_next_record_header(update->pcap_rfx, &record))
266 s = transport_take_from_pool(rdp->transport, record.length);
270 record.data = Stream_Buffer(s);
271 if (!pcap_get_next_record_content(update->pcap_rfx, &record))
273 if (!Stream_SetLength(s, record.length))
278 Stream_ResetPosition(s);
280 if (!update_begin_paint(&update->common))
284 if (!update_recv_surfcmds(&update->common, s))
287 if (!update_end_paint(&update->common))
294 pcap_close(update->pcap_rfx);
295 update->pcap_rfx =
nullptr;
296 goto freerdp_connect_finally;
299 if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
300 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
303 status = transport_set_connected_event(rdp->transport);
305freerdp_connect_finally:
306 EventArgsInit(&e,
"freerdp");
307 e.result = status ? 0 : -1;
308 if (PubSub_OnConnectionResult(rdp->pubSub, instance->context, &e) < 0)
312 freerdp_disconnect(instance);
317#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
318BOOL freerdp_abort_connect(freerdp* instance)
323 return freerdp_abort_connect_context(instance->context);
327BOOL freerdp_abort_connect_context(rdpContext* context)
332 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
333 return utils_abort_connect(context->rdp);
336#if defined(WITH_FREERDP_DEPRECATED)
337BOOL freerdp_get_fds(freerdp* instance,
void** rfds,
int* rcount, WINPR_ATTR_UNUSED
void** wfds,
338 WINPR_ATTR_UNUSED
int* wcount)
340 rdpRdp* rdp =
nullptr;
342 WINPR_ASSERT(instance);
343 WINPR_ASSERT(instance->context);
345 rdp = instance->context->rdp;
348 transport_get_fds(rdp->transport, rfds, rcount);
353BOOL freerdp_check_fds(freerdp* instance)
356 rdpRdp* rdp =
nullptr;
361 if (!instance->context)
364 if (!instance->context->rdp)
367 rdp = instance->context->rdp;
368 status = rdp_check_fds(rdp);
372 TerminateEventArgs e;
373 rdpContext* context = instance->context;
374 WINPR_ASSERT(context);
376 WLog_Print(context->log, WLOG_DEBUG,
"rdp_check_fds() - %i", status);
377 EventArgsInit(&e,
"freerdp");
379 if (PubSub_OnTerminate(rdp->pubSub, context, &e) < 0)
387DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count)
391 WINPR_ASSERT(context);
392 WINPR_ASSERT(context->rdp);
393 WINPR_ASSERT(events || (count == 0));
395 const size_t rrc = rdp_get_event_handles(context->rdp, &events[nCount], count - nCount);
399 nCount += WINPR_ASSERTING_INT_CAST(uint32_t, rrc);
401 if (events && (nCount < count + 2))
403 events[nCount++] = freerdp_channels_get_event_handle(context->instance);
404 events[nCount++] = getChannelErrorEventHandle(context);
409 const SSIZE_T rc = freerdp_client_channel_get_registered_event_handles(
410 context->channels, &events[nCount], count - nCount);
413 return nCount + (DWORD)rc;
417static BOOL freerdp_prevent_session_lock(rdpContext* context)
419 WINPR_ASSERT(context);
420 WINPR_ASSERT(context->input);
424 UINT32 FakeMouseMotionInterval =
426 if (FakeMouseMotionInterval && in->lastInputTimestamp)
428 const time_t now = time(
nullptr);
429 if (WINPR_ASSERTING_INT_CAST(
size_t, now) - in->lastInputTimestamp >
430 FakeMouseMotionInterval)
432 WLog_Print(context->log, WLOG_DEBUG,
433 "fake mouse move: x=%d y=%d lastInputTimestamp=%" PRIu64
" "
434 "FakeMouseMotionInterval=%" PRIu32,
435 in->lastX, in->lastY, in->lastInputTimestamp, FakeMouseMotionInterval);
437 BOOL status = freerdp_input_send_mouse_event(context->input, PTR_FLAGS_MOVE, in->lastX,
441 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
442 WLog_Print(context->log, WLOG_ERROR,
443 "freerdp_prevent_session_lock() failed - %" PRIi32
"", status);
455BOOL freerdp_check_event_handles(rdpContext* context)
457 WINPR_ASSERT(context);
459 BOOL status = freerdp_check_fds(context->instance);
463 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
464 WLog_Print(context->log, WLOG_ERROR,
"freerdp_check_fds() failed - %" PRIi32
"",
470 status = freerdp_channels_check_fds(context->channels, context->instance);
474 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
475 WLog_Print(context->log, WLOG_ERROR,
476 "freerdp_channels_check_fds() failed - %" PRIi32
"", status);
481 status = checkChannelErrorEvent(context);
485 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
486 WLog_Print(context->log, WLOG_ERROR,
"checkChannelErrorEvent() failed - %" PRIi32
"",
492 status = freerdp_prevent_session_lock(context);
497wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD
id)
499 wMessageQueue* queue =
nullptr;
501 WINPR_ASSERT(instance);
503 rdpContext* context = instance->context;
504 WINPR_ASSERT(context);
508 case FREERDP_UPDATE_MESSAGE_QUEUE:
511 queue = update->queue;
515 case FREERDP_INPUT_MESSAGE_QUEUE:
518 queue = input->queue;
528HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD
id)
530 HANDLE
event =
nullptr;
531 wMessageQueue* queue = freerdp_get_message_queue(instance,
id);
534 event = MessageQueue_Event(queue);
539int freerdp_message_queue_process_message(freerdp* instance, DWORD
id, wMessage* message)
542 rdpContext* context =
nullptr;
544 WINPR_ASSERT(instance);
546 context = instance->context;
547 WINPR_ASSERT(context);
551 case FREERDP_UPDATE_MESSAGE_QUEUE:
552 status = update_message_queue_process_message(context->update, message);
555 case FREERDP_INPUT_MESSAGE_QUEUE:
556 status = input_message_queue_process_message(context->input, message);
565int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD
id)
568 rdpContext* context =
nullptr;
570 WINPR_ASSERT(instance);
572 context = instance->context;
573 WINPR_ASSERT(context);
577 case FREERDP_UPDATE_MESSAGE_QUEUE:
578 status = update_message_queue_process_pending_messages(context->update);
581 case FREERDP_INPUT_MESSAGE_QUEUE:
582 status = input_message_queue_process_pending_messages(context->input);
591static BOOL freerdp_send_channel_data(freerdp* instance, UINT16 channelId,
const BYTE* data,
594 WINPR_ASSERT(instance);
595 WINPR_ASSERT(instance->context);
596 WINPR_ASSERT(instance->context->rdp);
597 return rdp_send_channel_data(instance->context->rdp, channelId, data, size);
600static BOOL freerdp_send_channel_packet(freerdp* instance, UINT16 channelId,
size_t totalSize,
601 UINT32 flags,
const BYTE* data,
size_t chunkSize)
603 WINPR_ASSERT(instance);
604 WINPR_ASSERT(instance->context);
605 WINPR_ASSERT(instance->context->rdp);
606 return rdp_channel_send_packet(instance->context->rdp, channelId, totalSize, flags, data,
610BOOL freerdp_disconnect(freerdp* instance)
614 if (!instance || !instance->context)
617 rdpRdp* rdp = instance->context->rdp;
622 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
624 (void)mcs_send_disconnect_provider_ultimatum(rdp->mcs,
625 Disconnect_Ultimatum_user_requested);
629 utils_abort_connect(rdp);
631 if (!rdp_client_disconnect(rdp))
635 if (rdp && rdp->update)
637 up = update_cast(rdp->update);
639 update_post_disconnect(rdp->update);
642 IFCALL(instance->PostDisconnect, instance);
648 up->dump_rfx = FALSE;
649 pcap_close(up->pcap_rfx);
650 up->pcap_rfx =
nullptr;
654 if (instance->context->channels)
655 freerdp_channels_close(instance->context->channels, instance);
657 IFCALL(instance->PostFinalDisconnect, instance);
659 freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
663#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
664BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
666 WINPR_ASSERT(instance);
667 return freerdp_disconnect_before_reconnect_context(instance->context);
671BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
673 rdpRdp* rdp =
nullptr;
675 WINPR_ASSERT(context);
678 return rdp_client_disconnect_and_clear(rdp);
681BOOL freerdp_reconnect(freerdp* instance)
683 rdpRdp* rdp =
nullptr;
685 WINPR_ASSERT(instance);
686 WINPR_ASSERT(instance->context);
688 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
691 rdp = instance->context->rdp;
693 if (!utils_reset_abort(instance->context->rdp))
695 return rdp_client_reconnect(rdp);
698#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
699BOOL freerdp_shall_disconnect(
const freerdp* instance)
704 return freerdp_shall_disconnect_context(instance->context);
708BOOL freerdp_shall_disconnect_context(
const rdpContext* context)
713 return utils_abort_event_is_set(context->rdp);
716BOOL freerdp_focus_required(freerdp* instance)
718 rdpRdp* rdp =
nullptr;
719 BOOL bRetCode = FALSE;
721 WINPR_ASSERT(instance);
722 WINPR_ASSERT(instance->context);
724 rdp = instance->context->rdp;
727 if (rdp->resendFocus)
730 rdp->resendFocus = FALSE;
736void freerdp_set_focus(freerdp* instance)
738 rdpRdp* rdp =
nullptr;
740 WINPR_ASSERT(instance);
741 WINPR_ASSERT(instance->context);
743 rdp = instance->context->rdp;
746 rdp->resendFocus = TRUE;
749void freerdp_get_version(
int* major,
int* minor,
int* revision)
751 if (major !=
nullptr)
752 *major = FREERDP_VERSION_MAJOR;
754 if (minor !=
nullptr)
755 *minor = FREERDP_VERSION_MINOR;
757 if (revision !=
nullptr)
758 *revision = FREERDP_VERSION_REVISION;
761const char* freerdp_get_version_string(
void)
763 return FREERDP_VERSION_FULL;
766const char* freerdp_get_build_config(
void)
768 WINPR_PRAGMA_DIAG_PUSH
769 WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
770 static const char build_config[] =
771 "Build configuration: " FREERDP_BUILD_CONFIG
"\n"
772 "Build type: " FREERDP_BUILD_TYPE
"\n"
773 "CFLAGS: " FREERDP_CFLAGS
"\n"
774 "Compiler: " FREERDP_COMPILER_ID
", " FREERDP_COMPILER_VERSION
"\n"
775 "Target architecture: " FREERDP_TARGET_ARCH
"\n";
776 WINPR_PRAGMA_DIAG_POP
780const char* freerdp_get_build_revision(
void)
782 return FREERDP_GIT_REVISION;
786 DEFINE_EVENT_ENTRY(WindowStateChange), DEFINE_EVENT_ENTRY(ResizeWindow),
787 DEFINE_EVENT_ENTRY(LocalResizeWindow), DEFINE_EVENT_ENTRY(EmbedWindow),
788 DEFINE_EVENT_ENTRY(PanningChange), DEFINE_EVENT_ENTRY(ZoomingChange),
789 DEFINE_EVENT_ENTRY(ErrorInfo), DEFINE_EVENT_ENTRY(Terminate),
790 DEFINE_EVENT_ENTRY(ConnectionResult), DEFINE_EVENT_ENTRY(ChannelConnected),
791 DEFINE_EVENT_ENTRY(ChannelDisconnected), DEFINE_EVENT_ENTRY(MouseEvent),
792 DEFINE_EVENT_ENTRY(Activated), DEFINE_EVENT_ENTRY(Timer),
793 DEFINE_EVENT_ENTRY(GraphicsReset), DEFINE_EVENT_ENTRY(UserNotification),
794 DEFINE_EVENT_ENTRY(ChannelInitialized), DEFINE_EVENT_ENTRY(ChannelTerminated)
807BOOL freerdp_context_new(freerdp* instance)
809 return freerdp_context_new_ex(instance,
nullptr);
812static BOOL freerdp_common_context(rdpContext* context, AccessTokenType tokenType,
char** token,
817 WINPR_ASSERT(context);
818 if (!context->instance || !context->instance->GetAccessToken)
821 va_list ap = WINPR_C_ARRAY_INIT;
825 case ACCESS_TOKEN_TYPE_AAD:
829 "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
835 const char* scope = va_arg(ap,
const char*);
836 const char* req_cnf = va_arg(ap,
const char*);
837 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count,
841 case ACCESS_TOKEN_TYPE_AVD:
845 "ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
851 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count);
860 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
865BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
867 rdpRdp* rdp =
nullptr;
868 rdpContext* context =
nullptr;
871 WINPR_ASSERT(instance);
873 instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
878 context->log = WLog_Get(TAG);
883 context->settings = settings;
884 context->instance = instance;
885 context->ServerMode = FALSE;
886 context->disconnectUltimatum = 0;
888 context->metrics = metrics_new(context);
890 if (!context->metrics)
893 rdp = rdp_new(context);
899 context->pubSub = rdp->pubSub;
901 if (!context->pubSub)
904 PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
906#if defined(WITH_FREERDP_DEPRECATED)
907 instance->input = rdp->input;
908 instance->update = rdp->update;
909 instance->settings = rdp->settings;
910 instance->autodetect = rdp->autodetect;
913 instance->heartbeat = rdp->heartbeat;
914 context->graphics = graphics_new(context);
916 if (!context->graphics)
919 context->input = rdp->input;
920 context->update = rdp->update;
921 context->settings = rdp->settings;
922 context->autodetect = rdp->autodetect;
924 if (!(context->errorDescription = calloc(1, 500)))
926 WLog_Print(context->log, WLOG_ERROR,
"calloc failed!");
930 if (!(context->channelErrorEvent = CreateEvent(
nullptr, TRUE, FALSE,
nullptr)))
932 WLog_Print(context->log, WLOG_ERROR,
"CreateEvent failed!");
936 update_register_client_callbacks(rdp->update);
938 if (!(context->channels = freerdp_channels_new(instance)))
941 context->dump = stream_dump_new();
949 if (!freerdp_set_common_access_token(context, freerdp_common_context))
952 IFCALLRET(instance->ContextNew, ret, instance, context);
960 freerdp_context_free(instance);
964BOOL freerdp_context_reset(freerdp* instance)
969 WINPR_ASSERT(instance->context);
970 rdpRdp* rdp = instance->context->rdp;
972 return rdp_reset_runtime_settings(rdp);
983void freerdp_context_free(freerdp* instance)
985 rdpContext* ctx =
nullptr;
990 if (!instance->context)
993 ctx = instance->context;
995 IFCALL(instance->ContextFree, instance, ctx);
998 ctx->settings =
nullptr;
1000 graphics_free(ctx->graphics);
1001 ctx->graphics =
nullptr;
1003 metrics_free(ctx->metrics);
1004 ctx->metrics =
nullptr;
1006 if (ctx->channelErrorEvent)
1007 (void)CloseHandle(ctx->channelErrorEvent);
1008 ctx->channelErrorEvent =
nullptr;
1010 free(ctx->errorDescription);
1011 ctx->errorDescription =
nullptr;
1013 freerdp_channels_free(ctx->channels);
1014 ctx->channels =
nullptr;
1016 freerdp_client_codecs_free(ctx->codecs);
1017 ctx->codecs =
nullptr;
1019 stream_dump_free(ctx->dump);
1020 ctx->dump =
nullptr;
1022 ctx->input =
nullptr;
1023 ctx->update =
nullptr;
1024 ctx->settings =
nullptr;
1025 ctx->autodetect =
nullptr;
1028 instance->context =
nullptr;
1029#if defined(WITH_FREERDP_DEPRECATED)
1030 instance->input =
nullptr;
1031 instance->update =
nullptr;
1032 instance->settings =
nullptr;
1033 instance->autodetect =
nullptr;
1035 instance->heartbeat =
nullptr;
1038int freerdp_get_disconnect_ultimatum(
const rdpContext* context)
1040 WINPR_ASSERT(context);
1041 return context->disconnectUltimatum;
1044UINT32 freerdp_error_info(
const freerdp* instance)
1046 WINPR_ASSERT(instance);
1047 WINPR_ASSERT(instance->context);
1048 WINPR_ASSERT(instance->context->rdp);
1049 return instance->context->rdp->errorInfo;
1052void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
1057 rdp_set_error_info(rdp, error);
1060BOOL freerdp_send_error_info(rdpRdp* rdp)
1065 return rdp_send_error_info(rdp);
1068UINT32 freerdp_get_last_error(
const rdpContext* context)
1070 WINPR_ASSERT(context);
1071 return context->LastError;
1074const char* freerdp_get_last_error_name(UINT32 code)
1076 const char* name =
nullptr;
1077 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1078 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1082 case FREERDP_ERROR_ERRBASE_CLASS:
1083 name = freerdp_get_error_base_name(type);
1086 case FREERDP_ERROR_ERRINFO_CLASS:
1087 name = freerdp_get_error_info_name(type);
1090 case FREERDP_ERROR_CONNECT_CLASS:
1091 name = freerdp_get_error_connect_name(type);
1095 name = rpc_error_to_string(code);
1102const char* freerdp_get_last_error_string(UINT32 code)
1104 const char*
string =
nullptr;
1105 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1106 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1110 case FREERDP_ERROR_ERRBASE_CLASS:
1111 string = freerdp_get_error_base_string(type);
1114 case FREERDP_ERROR_ERRINFO_CLASS:
1115 string = freerdp_get_error_info_string(type);
1118 case FREERDP_ERROR_CONNECT_CLASS:
1119 string = freerdp_get_error_connect_string(type);
1123 string = rpc_error_to_string(code);
1130const char* freerdp_get_last_error_category(UINT32 code)
1132 const char*
string =
nullptr;
1133 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1134 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1138 case FREERDP_ERROR_ERRBASE_CLASS:
1139 string = freerdp_get_error_base_category(type);
1142 case FREERDP_ERROR_ERRINFO_CLASS:
1143 string = freerdp_get_error_info_category(type);
1146 case FREERDP_ERROR_CONNECT_CLASS:
1147 string = freerdp_get_error_connect_category(type);
1151 string = rpc_error_to_category(code);
1158void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError,
const char* fkt,
1159 const char* file,
int line)
1161 WINPR_ASSERT(context);
1162 WINPR_ASSERT(line >= 0);
1166 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1168 WLog_PrintTextMessage(context->log, WLOG_ERROR, (
size_t)line, file, fkt,
1169 "%s [0x%08" PRIX32
"]", freerdp_get_last_error_name(lastError),
1174 if (lastError == FREERDP_ERROR_SUCCESS)
1176 if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1177 WLog_PrintTextMessage(context->log, WLOG_DEBUG, (
size_t)line, file, fkt,
1178 "resetting error state");
1180 else if (context->LastError != FREERDP_ERROR_SUCCESS)
1182 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1184 WLog_PrintTextMessage(context->log, WLOG_ERROR, (
size_t)line, file, fkt,
1185 "TODO: Trying to set error code %s, but %s already set!",
1186 freerdp_get_last_error_name(lastError),
1187 freerdp_get_last_error_name(context->LastError));
1190 context->LastError = lastError;
1193const char* freerdp_get_logon_error_info_type_ex(UINT32 type,
char* buffer,
size_t size)
1195 const char* str = freerdp_get_logon_error_info_type(type);
1196 (void)_snprintf(buffer, size,
"%s(0x%04" PRIx32
")", str, type);
1200const char* freerdp_get_logon_error_info_type(UINT32 type)
1202#define CASE_ENTRY(x) \
1207 CASE_ENTRY(LOGON_MSG_SESSION_BUSY_OPTIONS);
1208 CASE_ENTRY(LOGON_MSG_DISCONNECT_REFUSED);
1209 CASE_ENTRY(LOGON_MSG_NO_PERMISSION);
1210 CASE_ENTRY(LOGON_MSG_BUMP_OPTIONS);
1211 CASE_ENTRY(LOGON_MSG_RECONNECT_OPTIONS);
1212 CASE_ENTRY(LOGON_MSG_SESSION_TERMINATE);
1213 CASE_ENTRY(LOGON_MSG_SESSION_CONTINUE);
1214 CASE_ENTRY(ERROR_CODE_ACCESS_DENIED);
1222const char* freerdp_get_logon_error_info_data(UINT32 data)
1226 case LOGON_FAILED_BAD_PASSWORD:
1227 return "LOGON_FAILED_BAD_PASSWORD";
1229 case LOGON_FAILED_UPDATE_PASSWORD:
1230 return "LOGON_FAILED_UPDATE_PASSWORD";
1232 case LOGON_FAILED_OTHER:
1233 return "LOGON_FAILED_OTHER";
1236 return "LOGON_WARNING";
1239 return "SESSION_ID";
1243const char* freerdp_get_logon_error_info_data_ex(UINT32 data,
char* buffer,
size_t size)
1245 const char* str = freerdp_get_logon_error_info_data(data);
1246 (void)_snprintf(buffer, size,
"%s(0x%04" PRIx32
")", str, data);
1253freerdp* freerdp_new(
void)
1255 freerdp* instance =
nullptr;
1256 instance = (freerdp*)calloc(1,
sizeof(freerdp));
1261 instance->ContextSize =
sizeof(rdpContext);
1262 instance->SendChannelData = freerdp_send_channel_data;
1263 instance->SendChannelPacket = freerdp_send_channel_packet;
1264 instance->ReceiveChannelData = freerdp_channels_data;
1272void freerdp_free(freerdp* instance)
1277ULONG freerdp_get_transport_sent(
const rdpContext* context, BOOL resetCount)
1279 WINPR_ASSERT(context);
1280 WINPR_ASSERT(context->rdp);
1281 UINT64 rc = transport_get_bytes_sent(context->rdp->transport, resetCount);
1282 return WINPR_CXX_COMPAT_CAST(ULONG, MIN(rc, UINT32_MAX));
1285BOOL freerdp_nla_impersonate(rdpContext* context)
1287 rdpNla* nla =
nullptr;
1295 if (!context->rdp->transport)
1298 nla = transport_get_nla(context->rdp->transport);
1299 return nla_impersonate(nla);
1302BOOL freerdp_nla_revert_to_self(rdpContext* context)
1304 rdpNla* nla =
nullptr;
1312 if (!context->rdp->transport)
1315 nla = transport_get_nla(context->rdp->transport);
1316 return nla_revert_to_self(nla);
1319UINT32 freerdp_get_nla_sspi_error(
const rdpContext* context)
1321 WINPR_ASSERT(context);
1322 WINPR_ASSERT(context->rdp);
1323 WINPR_ASSERT(context->rdp->transport);
1325 rdpNla* nla = context->rdp->nla;
1327 nla = transport_get_nla(context->rdp->transport);
1328 return (UINT32)nla_get_sspi_error(nla);
1331BOOL freerdp_nla_encrypt(rdpContext* context,
const SecBuffer* inBuffer,
SecBuffer* outBuffer)
1333 WINPR_ASSERT(context);
1334 WINPR_ASSERT(context->rdp);
1336 rdpNla* nla = context->rdp->nla;
1337 return nla_encrypt(nla, inBuffer, outBuffer);
1340BOOL freerdp_nla_decrypt(rdpContext* context,
const SecBuffer* inBuffer,
SecBuffer* outBuffer)
1342 WINPR_ASSERT(context);
1343 WINPR_ASSERT(context->rdp);
1345 rdpNla* nla = context->rdp->nla;
1346 return nla_decrypt(nla, inBuffer, outBuffer);
1349SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ulAttr, PVOID pBuffer)
1351 WINPR_ASSERT(context);
1352 WINPR_ASSERT(context->rdp);
1354 rdpNla* nla = context->rdp->nla;
1356 nla = transport_get_nla(context->rdp->transport);
1360 return nla_QueryContextAttributes(nla, ulAttr, pBuffer);
1363SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, PVOID pBuffer)
1365 WINPR_ASSERT(context);
1366 WINPR_ASSERT(context->rdp);
1368 rdpNla* nla = context->rdp->nla;
1370 nla = transport_get_nla(context->rdp->transport);
1374 return nla_FreeContextBuffer(nla, pBuffer);
1377HANDLE getChannelErrorEventHandle(rdpContext* context)
1379 WINPR_ASSERT(context);
1380 return context->channelErrorEvent;
1383BOOL checkChannelErrorEvent(rdpContext* context)
1385 WINPR_ASSERT(context);
1387 if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1389 WLog_Print(context->log, WLOG_ERROR,
"%s. Error was %" PRIu32
"", context->errorDescription,
1390 context->channelErrorNum);
1402UINT getChannelError(
const rdpContext* context)
1404 WINPR_ASSERT(context);
1405 return context->channelErrorNum;
1408const char* getChannelErrorDescription(
const rdpContext* context)
1410 WINPR_ASSERT(context);
1411 return context->errorDescription;
1414void clearChannelError(rdpContext* context)
1416 WINPR_ASSERT(context);
1417 context->channelErrorNum = 0;
1418 memset(context->errorDescription, 0, 500);
1419 (void)ResetEvent(context->channelErrorEvent);
1422WINPR_ATTR_FORMAT_ARG(3, 4)
1423void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const
char* format, ...)
1425 va_list ap = WINPR_C_ARRAY_INIT;
1426 va_start(ap, format);
1428 WINPR_ASSERT(context);
1430 context->channelErrorNum = errorNum;
1431 (void)vsnprintf(context->errorDescription, 499, format, ap);
1433 (void)SetEvent(context->channelErrorEvent);
1436const char* freerdp_nego_get_routing_token(
const rdpContext* context, DWORD* length)
1438 if (!context || !context->rdp)
1441 return (
const char*)nego_get_routing_token(context->rdp->nego, length);
1444BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1446 WINPR_ASSERT(context);
1447 return rdp_io_callback_set_event(context->rdp, set);
1450const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1452 WINPR_ASSERT(context);
1453 return rdp_get_io_callbacks(context->rdp);
1456BOOL freerdp_set_io_callbacks(rdpContext* context,
const rdpTransportIo* io_callbacks)
1458 WINPR_ASSERT(context);
1459 return rdp_set_io_callbacks(context->rdp, io_callbacks);
1462BOOL freerdp_set_io_callback_context(rdpContext* context,
void* usercontext)
1464 WINPR_ASSERT(context);
1465 return rdp_set_io_callback_context(context->rdp, usercontext);
1468void* freerdp_get_io_callback_context(rdpContext* context)
1470 WINPR_ASSERT(context);
1471 return rdp_get_io_callback_context(context->rdp);
1474CONNECTION_STATE freerdp_get_state(
const rdpContext* context)
1476 WINPR_ASSERT(context);
1477 return rdp_get_state(context->rdp);
1480const char* freerdp_state_string(CONNECTION_STATE state)
1482 return rdp_state_string(state);
1485BOOL freerdp_is_active_state(
const rdpContext* context)
1487 WINPR_ASSERT(context);
1488 return rdp_is_active_state(context->rdp);
1491BOOL freerdp_channels_from_mcs(rdpSettings* settings,
const rdpContext* context)
1493 WINPR_ASSERT(context);
1494 return rdp_channels_from_mcs(settings, context->rdp);
1497HANDLE freerdp_abort_event(rdpContext* context)
1499 WINPR_ASSERT(context);
1500 return utils_get_abort_event(context->rdp);
1503static void test_mcs_free(rdpMcs* mcs)
1510 rdpSettings* settings = mcs->context->settings;
1518static rdpMcs* test_mcs_new(
void)
1521 rdpContext* context = calloc(1,
sizeof(rdpContext));
1530 context->settings = settings;
1531 return mcs_new(context);
1540BOOL freerdp_is_valid_mcs_create_request(
const BYTE* data,
size_t size)
1543 wStream sbuffer = WINPR_C_ARRAY_INIT;
1544 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1546 WINPR_ASSERT(data || (size == 0));
1549 rdpMcs* mcs = test_mcs_new();
1552 BOOL result = mcs_recv_connect_initial(mcs, s);
1557BOOL freerdp_is_valid_mcs_create_response(
const BYTE* data,
size_t size)
1560 wStream sbuffer = WINPR_C_ARRAY_INIT;
1561 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1563 WINPR_ASSERT(data || (size == 0));
1566 rdpMcs* mcs = test_mcs_new();
1569 BOOL result = mcs_recv_connect_response(mcs, s);
1574BOOL freerdp_persist_credentials(rdpContext* context)
1578 WINPR_ASSERT(context->rdp);
1579 return utils_persist_credentials(context->rdp->originalSettings, context->rdp->settings);
1582const char* freerdp_disconnect_reason_string(
int reason)
1586 case Disconnect_Ultimatum_domain_disconnected:
1587 return "rn-domain-disconnected";
1588 case Disconnect_Ultimatum_provider_initiated:
1589 return "rn-provider-initiated";
1590 case Disconnect_Ultimatum_token_purged:
1591 return "rn-token-purged";
1592 case Disconnect_Ultimatum_user_requested:
1593 return "rn-user-requested";
1594 case Disconnect_Ultimatum_channel_purged:
1595 return "rn-channel-purged";
1597 return "rn-unknown";
1601BOOL freerdp_set_common_access_token(rdpContext* context,
1602 pGetCommonAccessToken GetCommonAccessToken)
1604 WINPR_ASSERT(context);
1605 WINPR_ASSERT(context->rdp);
1606 context->rdp->GetCommonAccessToken = GetCommonAccessToken;
1610pGetCommonAccessToken freerdp_get_common_access_token(
const rdpContext* context)
1612 WINPR_ASSERT(context);
1613 WINPR_ASSERT(context->rdp);
1614 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.