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)
91 rdpSettings* settings = NULL;
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 freerdp_add_signal_cleanup_handler(instance->context, sig_abort_connect);
118 IFCALLRET(instance->PreConnect, status, instance);
119 instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED;
121 freerdp_settings_print_warnings(settings);
123 status = freerdp_settings_enforce_monitor_exists(settings);
126 status = freerdp_settings_enforce_consistency(settings);
129 status = freerdp_settings_check_client_after_preconnect(settings);
132 status = rdp_set_backup_settings(rdp);
134 status = utils_reload_channels(instance->context);
137 int64_t KeyboardLayout = freerdp_get_keyboard_default_layout_for_locale(cp);
138 if (KeyboardLayout == 0)
141 switch (KeyboardLayout)
144 case KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002:
147 WINPR_KBD_TYPE_JAPANESE))
161 rdpContext* context = instance->context;
162 WINPR_ASSERT(context);
163 freerdp_set_last_error_if_not(context, FREERDP_ERROR_PRE_CONNECT_FAILED);
165 WLog_Print(context->log, WLOG_ERROR,
"freerdp_pre_connect failed: %s",
166 rdp_client_connection_state_string(instance->ConnectionCallbackState));
170 rc = rdp_client_connect(rdp);
175 rdpContext* context = rdp->context;
176 WINPR_ASSERT(context);
177 WLog_Print(context->log, WLOG_ERROR,
"Authentication only, exit status %" PRId32
"", rc);
184BOOL freerdp_connect(freerdp* instance)
187 ConnectionResultEventArgs e = { 0 };
188 const int rc = freerdp_connect_begin(instance);
190 UINT status2 = ERROR_INTERNAL_ERROR;
192 WINPR_ASSERT(instance);
193 WINPR_ASSERT(instance->context);
195 rdp = instance->context->rdp;
197 WINPR_ASSERT(rdp->settings);
206 up->pcap_rfx = pcap_open(
213 pointer_cache_register_callbacks(instance->context->update);
214 status = IFCALLRESULT(TRUE, instance->PostConnect, instance);
215 instance->ConnectionCallbackState = CLIENT_STATE_POSTCONNECT_PASSED;
218 status2 = freerdp_channels_post_connect(instance->context->channels, instance);
222 status2 = CHANNEL_RC_OK;
223 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)
224 status = freerdp_reconnect(instance);
226 goto freerdp_connect_finally;
229 if (!status || (status2 != CHANNEL_RC_OK) || !update_post_connect(instance->context->update))
231 rdpContext* context = instance->context;
232 WINPR_ASSERT(context);
233 WLog_Print(context->log, WLOG_ERROR,
"freerdp_post_connect failed");
235 freerdp_set_last_error_if_not(context, FREERDP_ERROR_POST_CONNECT_FAILED);
238 goto freerdp_connect_finally;
241 if (rdp->settings->PlayRemoteFx)
245 pcap_record record = { 0 };
247 WINPR_ASSERT(update);
248 update->pcap_rfx = pcap_open(rdp->settings->PlayRemoteFxFile, FALSE);
251 if (!update->pcap_rfx)
252 goto freerdp_connect_finally;
254 update->play_rfx = TRUE;
258 while (pcap_has_next_record(update->pcap_rfx) && status)
260 if (!pcap_get_next_record_header(update->pcap_rfx, &record))
263 s = transport_take_from_pool(rdp->transport, record.length);
267 record.data = Stream_Buffer(s);
268 if (!pcap_get_next_record_content(update->pcap_rfx, &record))
270 Stream_SetLength(s, record.length);
271 Stream_SetPosition(s, 0);
273 if (!update_begin_paint(&update->common))
277 if (update_recv_surfcmds(&update->common, s) < 0)
280 if (!update_end_paint(&update->common))
287 pcap_close(update->pcap_rfx);
288 update->pcap_rfx = NULL;
289 goto freerdp_connect_finally;
292 if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)
293 freerdp_set_last_error_log(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);
295 transport_set_connected_event(rdp->transport);
297freerdp_connect_finally:
298 EventArgsInit(&e,
"freerdp");
299 e.result = status ? 0 : -1;
300 PubSub_OnConnectionResult(rdp->pubSub, instance->context, &e);
303 freerdp_disconnect(instance);
308#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
309BOOL freerdp_abort_connect(freerdp* instance)
314 return freerdp_abort_connect_context(instance->context);
318BOOL freerdp_abort_connect_context(rdpContext* context)
323 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_CANCELLED);
324 return utils_abort_connect(context->rdp);
327#if defined(WITH_FREERDP_DEPRECATED)
328BOOL freerdp_get_fds(freerdp* instance,
void** rfds,
int* rcount, WINPR_ATTR_UNUSED
void** wfds,
329 WINPR_ATTR_UNUSED
int* wcount)
333 WINPR_ASSERT(instance);
334 WINPR_ASSERT(instance->context);
336 rdp = instance->context->rdp;
339 transport_get_fds(rdp->transport, rfds, rcount);
344BOOL freerdp_check_fds(freerdp* instance)
352 if (!instance->context)
355 if (!instance->context->rdp)
358 rdp = instance->context->rdp;
359 status = rdp_check_fds(rdp);
363 TerminateEventArgs e;
364 rdpContext* context = instance->context;
365 WINPR_ASSERT(context);
367 WLog_Print(context->log, WLOG_DEBUG,
"rdp_check_fds() - %i", status);
368 EventArgsInit(&e,
"freerdp");
370 PubSub_OnTerminate(rdp->pubSub, context, &e);
377DWORD freerdp_get_event_handles(rdpContext* context, HANDLE* events, DWORD count)
381 WINPR_ASSERT(context);
382 WINPR_ASSERT(context->rdp);
383 WINPR_ASSERT(events || (count == 0));
385 const size_t rrc = rdp_get_event_handles(context->rdp, &events[nCount], count - nCount);
389 nCount += WINPR_ASSERTING_INT_CAST(uint32_t, rrc);
391 if (events && (nCount < count + 2))
393 events[nCount++] = freerdp_channels_get_event_handle(context->instance);
394 events[nCount++] = getChannelErrorEventHandle(context);
399 const SSIZE_T rc = freerdp_client_channel_get_registered_event_handles(
400 context->channels, &events[nCount], count - nCount);
403 return nCount + (DWORD)rc;
407static BOOL freerdp_prevent_session_lock(rdpContext* context)
409 WINPR_ASSERT(context);
410 WINPR_ASSERT(context->input);
414 UINT32 FakeMouseMotionInterval =
416 if (FakeMouseMotionInterval && in->lastInputTimestamp)
418 const time_t now = time(NULL);
419 if (WINPR_ASSERTING_INT_CAST(
size_t, now) - in->lastInputTimestamp >
420 FakeMouseMotionInterval)
422 WLog_Print(context->log, WLOG_DEBUG,
423 "fake mouse move: x=%d y=%d lastInputTimestamp=%" PRIu64
" "
424 "FakeMouseMotionInterval=%" PRIu32,
425 in->lastX, in->lastY, in->lastInputTimestamp, FakeMouseMotionInterval);
427 BOOL status = freerdp_input_send_mouse_event(context->input, PTR_FLAGS_MOVE, in->lastX,
431 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
432 WLog_Print(context->log, WLOG_ERROR,
433 "freerdp_prevent_session_lock() failed - %" PRIi32
"", status);
445BOOL freerdp_check_event_handles(rdpContext* context)
447 WINPR_ASSERT(context);
449 BOOL status = freerdp_check_fds(context->instance);
453 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
454 WLog_Print(context->log, WLOG_ERROR,
"freerdp_check_fds() failed - %" PRIi32
"",
460 status = freerdp_channels_check_fds(context->channels, context->instance);
464 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
465 WLog_Print(context->log, WLOG_ERROR,
466 "freerdp_channels_check_fds() failed - %" PRIi32
"", status);
471 status = checkChannelErrorEvent(context);
475 if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS)
476 WLog_Print(context->log, WLOG_ERROR,
"checkChannelErrorEvent() failed - %" PRIi32
"",
482 status = freerdp_prevent_session_lock(context);
487wMessageQueue* freerdp_get_message_queue(freerdp* instance, DWORD
id)
489 wMessageQueue* queue = NULL;
491 WINPR_ASSERT(instance);
493 rdpContext* context = instance->context;
494 WINPR_ASSERT(context);
498 case FREERDP_UPDATE_MESSAGE_QUEUE:
501 queue = update->queue;
505 case FREERDP_INPUT_MESSAGE_QUEUE:
508 queue = input->queue;
518HANDLE freerdp_get_message_queue_event_handle(freerdp* instance, DWORD
id)
521 wMessageQueue* queue = freerdp_get_message_queue(instance,
id);
524 event = MessageQueue_Event(queue);
529int freerdp_message_queue_process_message(freerdp* instance, DWORD
id, wMessage* message)
532 rdpContext* context = NULL;
534 WINPR_ASSERT(instance);
536 context = instance->context;
537 WINPR_ASSERT(context);
541 case FREERDP_UPDATE_MESSAGE_QUEUE:
542 status = update_message_queue_process_message(context->update, message);
545 case FREERDP_INPUT_MESSAGE_QUEUE:
546 status = input_message_queue_process_message(context->input, message);
555int freerdp_message_queue_process_pending_messages(freerdp* instance, DWORD
id)
558 rdpContext* context = NULL;
560 WINPR_ASSERT(instance);
562 context = instance->context;
563 WINPR_ASSERT(context);
567 case FREERDP_UPDATE_MESSAGE_QUEUE:
568 status = update_message_queue_process_pending_messages(context->update);
571 case FREERDP_INPUT_MESSAGE_QUEUE:
572 status = input_message_queue_process_pending_messages(context->input);
581static BOOL freerdp_send_channel_data(freerdp* instance, UINT16 channelId,
const BYTE* data,
584 WINPR_ASSERT(instance);
585 WINPR_ASSERT(instance->context);
586 WINPR_ASSERT(instance->context->rdp);
587 return rdp_send_channel_data(instance->context->rdp, channelId, data, size);
590static BOOL freerdp_send_channel_packet(freerdp* instance, UINT16 channelId,
size_t totalSize,
591 UINT32 flags,
const BYTE* data,
size_t chunkSize)
593 WINPR_ASSERT(instance);
594 WINPR_ASSERT(instance->context);
595 WINPR_ASSERT(instance->context->rdp);
596 return rdp_channel_send_packet(instance->context->rdp, channelId, totalSize, flags, data,
600BOOL freerdp_disconnect(freerdp* instance)
604 if (!instance || !instance->context)
607 rdpRdp* rdp = instance->context->rdp;
612 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
614 (void)mcs_send_disconnect_provider_ultimatum(rdp->mcs,
615 Disconnect_Ultimatum_user_requested);
619 utils_abort_connect(rdp);
621 if (!rdp_client_disconnect(rdp))
625 if (rdp && rdp->update)
627 up = update_cast(rdp->update);
629 update_post_disconnect(rdp->update);
632 IFCALL(instance->PostDisconnect, instance);
638 up->dump_rfx = FALSE;
639 pcap_close(up->pcap_rfx);
644 freerdp_channels_close(instance->context->channels, instance);
646 IFCALL(instance->PostFinalDisconnect, instance);
648 freerdp_del_signal_cleanup_handler(instance->context, sig_abort_connect);
652#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
653BOOL freerdp_disconnect_before_reconnect(freerdp* instance)
655 WINPR_ASSERT(instance);
656 return freerdp_disconnect_before_reconnect_context(instance->context);
660BOOL freerdp_disconnect_before_reconnect_context(rdpContext* context)
664 WINPR_ASSERT(context);
667 return rdp_client_disconnect_and_clear(rdp);
670BOOL freerdp_reconnect(freerdp* instance)
674 WINPR_ASSERT(instance);
675 WINPR_ASSERT(instance->context);
677 if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_CANCELLED)
680 rdp = instance->context->rdp;
682 if (!utils_reset_abort(instance->context->rdp))
684 return rdp_client_reconnect(rdp);
687#if !defined(WITHOUT_FREERDP_3x_DEPRECATED)
688BOOL freerdp_shall_disconnect(
const freerdp* instance)
693 return freerdp_shall_disconnect_context(instance->context);
697BOOL freerdp_shall_disconnect_context(
const rdpContext* context)
702 return utils_abort_event_is_set(context->rdp);
705BOOL freerdp_focus_required(freerdp* instance)
708 BOOL bRetCode = FALSE;
710 WINPR_ASSERT(instance);
711 WINPR_ASSERT(instance->context);
713 rdp = instance->context->rdp;
716 if (rdp->resendFocus)
719 rdp->resendFocus = FALSE;
725void freerdp_set_focus(freerdp* instance)
729 WINPR_ASSERT(instance);
730 WINPR_ASSERT(instance->context);
732 rdp = instance->context->rdp;
735 rdp->resendFocus = TRUE;
738void freerdp_get_version(
int* major,
int* minor,
int* revision)
741 *major = FREERDP_VERSION_MAJOR;
744 *minor = FREERDP_VERSION_MINOR;
746 if (revision != NULL)
747 *revision = FREERDP_VERSION_REVISION;
750const char* freerdp_get_version_string(
void)
752 return FREERDP_VERSION_FULL;
755const char* freerdp_get_build_config(
void)
757 WINPR_PRAGMA_DIAG_PUSH
758 WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
759 static const char build_config[] =
760 "Build configuration: " FREERDP_BUILD_CONFIG
"\n"
761 "Build type: " FREERDP_BUILD_TYPE
"\n"
762 "CFLAGS: " FREERDP_CFLAGS
"\n"
763 "Compiler: " FREERDP_COMPILER_ID
", " FREERDP_COMPILER_VERSION
"\n"
764 "Target architecture: " FREERDP_TARGET_ARCH
"\n";
765 WINPR_PRAGMA_DIAG_POP
769const char* freerdp_get_build_revision(
void)
771 return FREERDP_GIT_REVISION;
775 DEFINE_EVENT_ENTRY(WindowStateChange), DEFINE_EVENT_ENTRY(ResizeWindow),
776 DEFINE_EVENT_ENTRY(LocalResizeWindow), DEFINE_EVENT_ENTRY(EmbedWindow),
777 DEFINE_EVENT_ENTRY(PanningChange), DEFINE_EVENT_ENTRY(ZoomingChange),
778 DEFINE_EVENT_ENTRY(ErrorInfo), DEFINE_EVENT_ENTRY(Terminate),
779 DEFINE_EVENT_ENTRY(ConnectionResult), DEFINE_EVENT_ENTRY(ChannelConnected),
780 DEFINE_EVENT_ENTRY(ChannelDisconnected), DEFINE_EVENT_ENTRY(MouseEvent),
781 DEFINE_EVENT_ENTRY(Activated), DEFINE_EVENT_ENTRY(Timer),
782 DEFINE_EVENT_ENTRY(GraphicsReset)
795BOOL freerdp_context_new(freerdp* instance)
797 return freerdp_context_new_ex(instance, NULL);
800static BOOL freerdp_common_context(rdpContext* context, AccessTokenType tokenType,
char** token,
805 WINPR_ASSERT(context);
806 if (!context->instance || !context->instance->GetAccessToken)
813 case ACCESS_TOKEN_TYPE_AAD:
817 "ACCESS_TOKEN_TYPE_AAD expected 2 additional arguments, but got %" PRIuz
823 const char* scope = va_arg(ap,
const char*);
824 const char* req_cnf = va_arg(ap,
const char*);
825 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count,
829 case ACCESS_TOKEN_TYPE_AVD:
833 "ACCESS_TOKEN_TYPE_AVD expected 0 additional arguments, but got %" PRIuz
839 rc = context->instance->GetAccessToken(context->instance, tokenType, token, count);
848 freerdp_set_last_error_if_not(context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
853BOOL freerdp_context_new_ex(freerdp* instance, rdpSettings* settings)
856 rdpContext* context = NULL;
859 WINPR_ASSERT(instance);
861 instance->context = context = (rdpContext*)calloc(1, instance->ContextSize);
866 context->log = WLog_Get(TAG);
871 context->settings = settings;
872 context->instance = instance;
873 context->ServerMode = FALSE;
874 context->disconnectUltimatum = 0;
876 context->metrics = metrics_new(context);
878 if (!context->metrics)
881 rdp = rdp_new(context);
887 context->pubSub = rdp->pubSub;
889 if (!context->pubSub)
892 PubSub_AddEventTypes(rdp->pubSub, FreeRDP_Events, ARRAYSIZE(FreeRDP_Events));
894#if defined(WITH_FREERDP_DEPRECATED)
895 instance->input = rdp->input;
896 instance->update = rdp->update;
897 instance->settings = rdp->settings;
898 instance->autodetect = rdp->autodetect;
901 instance->heartbeat = rdp->heartbeat;
902 context->graphics = graphics_new(context);
904 if (!context->graphics)
907 context->input = rdp->input;
908 context->update = rdp->update;
909 context->settings = rdp->settings;
910 context->autodetect = rdp->autodetect;
912 if (!(context->errorDescription = calloc(1, 500)))
914 WLog_Print(context->log, WLOG_ERROR,
"calloc failed!");
918 if (!(context->channelErrorEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
920 WLog_Print(context->log, WLOG_ERROR,
"CreateEvent failed!");
924 update_register_client_callbacks(rdp->update);
926 if (!(context->channels = freerdp_channels_new(instance)))
929 context->dump = stream_dump_new();
937 if (!freerdp_set_common_access_token(context, freerdp_common_context))
940 IFCALLRET(instance->ContextNew, ret, instance, context);
948 freerdp_context_free(instance);
952BOOL freerdp_context_reset(freerdp* instance)
957 WINPR_ASSERT(instance->context);
958 rdpRdp* rdp = instance->context->rdp;
960 return rdp_reset_runtime_settings(rdp);
971void freerdp_context_free(freerdp* instance)
973 rdpContext* ctx = NULL;
978 if (!instance->context)
981 ctx = instance->context;
983 IFCALL(instance->ContextFree, instance, ctx);
986 ctx->settings = NULL;
988 graphics_free(ctx->graphics);
989 ctx->graphics = NULL;
991 metrics_free(ctx->metrics);
994 if (ctx->channelErrorEvent)
995 (void)CloseHandle(ctx->channelErrorEvent);
996 ctx->channelErrorEvent = NULL;
998 free(ctx->errorDescription);
999 ctx->errorDescription = NULL;
1001 freerdp_channels_free(ctx->channels);
1002 ctx->channels = NULL;
1004 freerdp_client_codecs_free(ctx->codecs);
1007 stream_dump_free(ctx->dump);
1012 ctx->settings = NULL;
1013 ctx->autodetect = NULL;
1016 instance->context = NULL;
1017#if defined(WITH_FREERDP_DEPRECATED)
1018 instance->input = NULL;
1019 instance->update = NULL;
1020 instance->settings = NULL;
1021 instance->autodetect = NULL;
1023 instance->heartbeat = NULL;
1026int freerdp_get_disconnect_ultimatum(
const rdpContext* context)
1028 WINPR_ASSERT(context);
1029 return context->disconnectUltimatum;
1032UINT32 freerdp_error_info(
const freerdp* instance)
1034 WINPR_ASSERT(instance);
1035 WINPR_ASSERT(instance->context);
1036 WINPR_ASSERT(instance->context->rdp);
1037 return instance->context->rdp->errorInfo;
1040void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
1045 rdp_set_error_info(rdp, error);
1048BOOL freerdp_send_error_info(rdpRdp* rdp)
1053 return rdp_send_error_info(rdp);
1056UINT32 freerdp_get_last_error(
const rdpContext* context)
1058 WINPR_ASSERT(context);
1059 return context->LastError;
1062const char* freerdp_get_last_error_name(UINT32 code)
1064 const char* name = NULL;
1065 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1066 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1070 case FREERDP_ERROR_ERRBASE_CLASS:
1071 name = freerdp_get_error_base_name(type);
1074 case FREERDP_ERROR_ERRINFO_CLASS:
1075 name = freerdp_get_error_info_name(type);
1078 case FREERDP_ERROR_CONNECT_CLASS:
1079 name = freerdp_get_error_connect_name(type);
1083 name = rpc_error_to_string(code);
1090const char* freerdp_get_last_error_string(UINT32 code)
1092 const char*
string = NULL;
1093 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1094 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1098 case FREERDP_ERROR_ERRBASE_CLASS:
1099 string = freerdp_get_error_base_string(type);
1102 case FREERDP_ERROR_ERRINFO_CLASS:
1103 string = freerdp_get_error_info_string(type);
1106 case FREERDP_ERROR_CONNECT_CLASS:
1107 string = freerdp_get_error_connect_string(type);
1111 string = rpc_error_to_string(code);
1118const char* freerdp_get_last_error_category(UINT32 code)
1120 const char*
string = NULL;
1121 const UINT32 cls = GET_FREERDP_ERROR_CLASS(code);
1122 const UINT32 type = GET_FREERDP_ERROR_TYPE(code);
1126 case FREERDP_ERROR_ERRBASE_CLASS:
1127 string = freerdp_get_error_base_category(type);
1130 case FREERDP_ERROR_ERRINFO_CLASS:
1131 string = freerdp_get_error_info_category(type);
1134 case FREERDP_ERROR_CONNECT_CLASS:
1135 string = freerdp_get_error_connect_category(type);
1139 string = rpc_error_to_category(code);
1146void freerdp_set_last_error_ex(rdpContext* context, UINT32 lastError,
const char* fkt,
1147 const char* file,
int line)
1149 WINPR_ASSERT(context);
1150 WINPR_ASSERT(line >= 0);
1154 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1156 WLog_PrintTextMessage(context->log, WLOG_ERROR, (
size_t)line, file, fkt,
1157 "%s [0x%08" PRIX32
"]", freerdp_get_last_error_name(lastError),
1162 if (lastError == FREERDP_ERROR_SUCCESS)
1164 if (WLog_IsLevelActive(context->log, WLOG_DEBUG))
1165 WLog_PrintTextMessage(context->log, WLOG_DEBUG, (
size_t)line, file, fkt,
1166 "resetting error state");
1168 else if (context->LastError != FREERDP_ERROR_SUCCESS)
1170 if (WLog_IsLevelActive(context->log, WLOG_ERROR))
1172 WLog_PrintTextMessage(context->log, WLOG_ERROR, (
size_t)line, file, fkt,
1173 "TODO: Trying to set error code %s, but %s already set!",
1174 freerdp_get_last_error_name(lastError),
1175 freerdp_get_last_error_name(context->LastError));
1178 context->LastError = lastError;
1181const char* freerdp_get_logon_error_info_type_ex(UINT32 type,
char* buffer,
size_t size)
1183 const char* str = freerdp_get_logon_error_info_type(type);
1184 (void)_snprintf(buffer, size,
"%s(0x%04" PRIx32
")", str, type);
1188const char* freerdp_get_logon_error_info_type(UINT32 type)
1192 case LOGON_MSG_DISCONNECT_REFUSED:
1193 return "LOGON_MSG_DISCONNECT_REFUSED";
1195 case LOGON_MSG_NO_PERMISSION:
1196 return "LOGON_MSG_NO_PERMISSION";
1198 case LOGON_MSG_BUMP_OPTIONS:
1199 return "LOGON_MSG_BUMP_OPTIONS";
1201 case LOGON_MSG_RECONNECT_OPTIONS:
1202 return "LOGON_MSG_RECONNECT_OPTIONS";
1204 case LOGON_MSG_SESSION_TERMINATE:
1205 return "LOGON_MSG_SESSION_TERMINATE";
1207 case LOGON_MSG_SESSION_CONTINUE:
1208 return "LOGON_MSG_SESSION_CONTINUE";
1215const char* freerdp_get_logon_error_info_data(UINT32 data)
1219 case LOGON_FAILED_BAD_PASSWORD:
1220 return "LOGON_FAILED_BAD_PASSWORD";
1222 case LOGON_FAILED_UPDATE_PASSWORD:
1223 return "LOGON_FAILED_UPDATE_PASSWORD";
1225 case LOGON_FAILED_OTHER:
1226 return "LOGON_FAILED_OTHER";
1229 return "LOGON_WARNING";
1232 return "SESSION_ID";
1236const char* freerdp_get_logon_error_info_data_ex(UINT32 data,
char* buffer,
size_t size)
1238 const char* str = freerdp_get_logon_error_info_data(data);
1239 (void)_snprintf(buffer, size,
"%s(0x%04" PRIx32
")", str, data);
1246freerdp* freerdp_new(
void)
1248 freerdp* instance = NULL;
1249 instance = (freerdp*)calloc(1,
sizeof(freerdp));
1254 instance->ContextSize =
sizeof(rdpContext);
1255 instance->SendChannelData = freerdp_send_channel_data;
1256 instance->SendChannelPacket = freerdp_send_channel_packet;
1257 instance->ReceiveChannelData = freerdp_channels_data;
1265void freerdp_free(freerdp* instance)
1270ULONG freerdp_get_transport_sent(
const rdpContext* context, BOOL resetCount)
1272 WINPR_ASSERT(context);
1273 WINPR_ASSERT(context->rdp);
1274 UINT64 rc = transport_get_bytes_sent(context->rdp->transport, resetCount);
1275 return WINPR_CXX_COMPAT_CAST(ULONG, MIN(rc, UINT32_MAX));
1278BOOL freerdp_nla_impersonate(rdpContext* context)
1288 if (!context->rdp->transport)
1291 nla = transport_get_nla(context->rdp->transport);
1292 return nla_impersonate(nla);
1295BOOL freerdp_nla_revert_to_self(rdpContext* context)
1305 if (!context->rdp->transport)
1308 nla = transport_get_nla(context->rdp->transport);
1309 return nla_revert_to_self(nla);
1312UINT32 freerdp_get_nla_sspi_error(
const rdpContext* context)
1314 WINPR_ASSERT(context);
1315 WINPR_ASSERT(context->rdp);
1316 WINPR_ASSERT(context->rdp->transport);
1318 rdpNla* nla = transport_get_nla(context->rdp->transport);
1319 return (UINT32)nla_get_sspi_error(nla);
1322BOOL freerdp_nla_encrypt(rdpContext* context,
const SecBuffer* inBuffer,
SecBuffer* outBuffer)
1324 WINPR_ASSERT(context);
1325 WINPR_ASSERT(context->rdp);
1327 rdpNla* nla = context->rdp->nla;
1328 return nla_encrypt(nla, inBuffer, outBuffer);
1331BOOL freerdp_nla_decrypt(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_decrypt(nla, inBuffer, outBuffer);
1340SECURITY_STATUS freerdp_nla_QueryContextAttributes(rdpContext* context, DWORD ulAttr, PVOID pBuffer)
1342 WINPR_ASSERT(context);
1343 WINPR_ASSERT(context->rdp);
1345 rdpNla* nla = context->rdp->nla;
1347 nla = transport_get_nla(context->rdp->transport);
1351 return nla_QueryContextAttributes(nla, ulAttr, pBuffer);
1354SECURITY_STATUS freerdp_nla_FreeContextBuffer(rdpContext* context, 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_FreeContextBuffer(nla, pBuffer);
1368HANDLE getChannelErrorEventHandle(rdpContext* context)
1370 WINPR_ASSERT(context);
1371 return context->channelErrorEvent;
1374BOOL checkChannelErrorEvent(rdpContext* context)
1376 WINPR_ASSERT(context);
1378 if (WaitForSingleObject(context->channelErrorEvent, 0) == WAIT_OBJECT_0)
1380 WLog_Print(context->log, WLOG_ERROR,
"%s. Error was %" PRIu32
"", context->errorDescription,
1381 context->channelErrorNum);
1393UINT getChannelError(
const rdpContext* context)
1395 WINPR_ASSERT(context);
1396 return context->channelErrorNum;
1399const char* getChannelErrorDescription(
const rdpContext* context)
1401 WINPR_ASSERT(context);
1402 return context->errorDescription;
1405void clearChannelError(rdpContext* context)
1407 WINPR_ASSERT(context);
1408 context->channelErrorNum = 0;
1409 memset(context->errorDescription, 0, 500);
1410 (void)ResetEvent(context->channelErrorEvent);
1413WINPR_ATTR_FORMAT_ARG(3, 4)
1414void setChannelError(rdpContext* context, UINT errorNum, WINPR_FORMAT_ARG const
char* format, ...)
1417 va_start(ap, format);
1419 WINPR_ASSERT(context);
1421 context->channelErrorNum = errorNum;
1422 (void)vsnprintf(context->errorDescription, 499, format, ap);
1424 (void)SetEvent(context->channelErrorEvent);
1427const char* freerdp_nego_get_routing_token(
const rdpContext* context, DWORD* length)
1429 if (!context || !context->rdp)
1432 return (
const char*)nego_get_routing_token(context->rdp->nego, length);
1435BOOL freerdp_io_callback_set_event(rdpContext* context, BOOL set)
1437 WINPR_ASSERT(context);
1438 return rdp_io_callback_set_event(context->rdp, set);
1441const rdpTransportIo* freerdp_get_io_callbacks(rdpContext* context)
1443 WINPR_ASSERT(context);
1444 return rdp_get_io_callbacks(context->rdp);
1447BOOL freerdp_set_io_callbacks(rdpContext* context,
const rdpTransportIo* io_callbacks)
1449 WINPR_ASSERT(context);
1450 return rdp_set_io_callbacks(context->rdp, io_callbacks);
1453BOOL freerdp_set_io_callback_context(rdpContext* context,
void* usercontext)
1455 WINPR_ASSERT(context);
1456 return rdp_set_io_callback_context(context->rdp, usercontext);
1459void* freerdp_get_io_callback_context(rdpContext* context)
1461 WINPR_ASSERT(context);
1462 return rdp_get_io_callback_context(context->rdp);
1465CONNECTION_STATE freerdp_get_state(
const rdpContext* context)
1467 WINPR_ASSERT(context);
1468 return rdp_get_state(context->rdp);
1471const char* freerdp_state_string(CONNECTION_STATE state)
1473 return rdp_state_string(state);
1476BOOL freerdp_is_active_state(
const rdpContext* context)
1478 WINPR_ASSERT(context);
1479 return rdp_is_active_state(context->rdp);
1482BOOL freerdp_channels_from_mcs(rdpSettings* settings,
const rdpContext* context)
1484 WINPR_ASSERT(context);
1485 return rdp_channels_from_mcs(settings, context->rdp);
1488HANDLE freerdp_abort_event(rdpContext* context)
1490 WINPR_ASSERT(context);
1491 return utils_get_abort_event(context->rdp);
1494static void test_mcs_free(rdpMcs* mcs)
1501 rdpSettings* settings = mcs->context->settings;
1509static rdpMcs* test_mcs_new(
void)
1512 rdpContext* context = calloc(1,
sizeof(rdpContext));
1521 context->settings = settings;
1522 return mcs_new(context);
1531BOOL freerdp_is_valid_mcs_create_request(
const BYTE* data,
size_t size)
1535 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1537 WINPR_ASSERT(data || (size == 0));
1540 rdpMcs* mcs = test_mcs_new();
1543 BOOL result = mcs_recv_connect_initial(mcs, s);
1548BOOL freerdp_is_valid_mcs_create_response(
const BYTE* data,
size_t size)
1552 wStream* s = Stream_StaticConstInit(&sbuffer, data, size);
1554 WINPR_ASSERT(data || (size == 0));
1557 rdpMcs* mcs = test_mcs_new();
1560 BOOL result = mcs_recv_connect_response(mcs, s);
1565BOOL freerdp_persist_credentials(rdpContext* context)
1569 WINPR_ASSERT(context->rdp);
1570 return utils_persist_credentials(context->rdp->originalSettings, context->rdp->settings);
1573const char* freerdp_disconnect_reason_string(
int reason)
1577 case Disconnect_Ultimatum_domain_disconnected:
1578 return "rn-domain-disconnected";
1579 case Disconnect_Ultimatum_provider_initiated:
1580 return "rn-provider-initiated";
1581 case Disconnect_Ultimatum_token_purged:
1582 return "rn-token-purged";
1583 case Disconnect_Ultimatum_user_requested:
1584 return "rn-user-requested";
1585 case Disconnect_Ultimatum_channel_purged:
1586 return "rn-channel-purged";
1588 return "rn-unknown";
1592BOOL freerdp_set_common_access_token(rdpContext* context,
1593 pGetCommonAccessToken GetCommonAccessToken)
1595 WINPR_ASSERT(context);
1596 WINPR_ASSERT(context->rdp);
1597 context->rdp->GetCommonAccessToken = GetCommonAccessToken;
1601pGetCommonAccessToken freerdp_get_common_access_token(
const rdpContext* context)
1603 WINPR_ASSERT(context);
1604 WINPR_ASSERT(context->rdp);
1605 return context->rdp->GetCommonAccessToken;
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.
FREERDP_API void freerdp_settings_free(rdpSettings *settings)
Free a settings struct with all data in it.
WINPR_ATTR_NODISCARD FREERDP_API rdpSettings * freerdp_settings_new(DWORD flags)
creates a new setting struct
WINPR_ATTR_NODISCARD FREERDP_API UINT32 freerdp_settings_get_uint32(const rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id)
Returns a UINT32 settings value.
FREERDP_API BOOL freerdp_settings_set_uint32(rdpSettings *settings, FreeRDP_Settings_Keys_UInt32 id, UINT32 param)
Sets 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.
FREERDP_API BOOL freerdp_settings_set_bool(rdpSettings *settings, FreeRDP_Settings_Keys_Bool id, BOOL param)
Sets a BOOL settings value.