6#include "ConnectFreeRDP.h"
8#undef PEN_FLAG_INVERTED
9#include "freerdp/client.h"
10#include "freerdp/client/channels.h"
11#include "freerdp/channels/rdpei.h"
12#include "freerdp/channels/rdpdr.h"
13#include "freerdp/channels/disp.h"
14#include "freerdp/channels/tsmf.h"
15#include "freerdp/channels/rdpsnd.h"
16#include "freerdp/client/encomsp.h"
17#include "freerdp/gdi/gfx.h"
18#include "freerdp/settings.h"
19#include "freerdp/locale/keyboard.h"
20#include "freerdp/channels/rdpgfx.h"
21#include "freerdp/channels/cliprdr.h"
22#include "freerdp/client/cmdline.h"
23#include <freerdp/gdi/video.h>
25#include "RabbitCommonTools.h"
26#include "ConvertKeyCode.h"
30#include <QApplication>
32#include <QSslCertificate>
33#include <QInputDialog>
34#include <QMutexLocker>
36#include <QPrinterInfo>
38#include <QSerialPortInfo>
39#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
40 #include <QSoundEffect>
45static Q_LOGGING_CATEGORY(log,
"FreeRDP.Connect")
46static Q_LOGGING_CATEGORY(logKey, "FreeRDP.Connect.Key")
47static Q_LOGGING_CATEGORY(logMouse, "FreeRDP.Connect.Mouse")
52 m_pParameter(
nullptr),
60 qDebug(log) << Q_FUNC_INFO;
61 m_pParameter = qobject_cast<CParameterFreeRDP*>(pConnecter->GetParameter());
62 Q_ASSERT(m_pParameter);
65CConnectFreeRDP::~CConnectFreeRDP()
67 qDebug(log) << Q_FUNC_INFO;
78 qDebug(log) << Q_FUNC_INFO;
81 m_writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
83 qCritical(log) <<
"CreateEvent failed";
85 ZeroMemory(&m_ClientEntryPoints,
sizeof(RDP_CLIENT_ENTRY_POINTS));
86 m_ClientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
87 m_ClientEntryPoints.Size =
sizeof(RDP_CLIENT_ENTRY_POINTS);
89 m_ClientEntryPoints.GlobalInit = cbGlobalInit;
90 m_ClientEntryPoints.GlobalUninit = cbGlobalUninit;
91 m_ClientEntryPoints.ClientNew = cbClientNew;
92 m_ClientEntryPoints.ClientFree = cbClientFree;
93 m_ClientEntryPoints.ClientStart = cbClientStart;
94 m_ClientEntryPoints.ClientStop = cbClientStop;
97 auto pRdpContext = freerdp_client_context_new(&m_ClientEntryPoints);
101 m_pContext->pThis =
this;
103 qCritical(log) <<
"freerdp_client_context_new fail";
104 return OnInitReturnValue::Fail;
107 rdpSettings* settings = pRdpContext->settings;
109 qCritical(log) <<
"settings is null";
110 return OnInitReturnValue::Fail;
113 char* argv[]= {(
char*)QApplication::applicationFilePath().toStdString().c_str()};
114 int argc =
sizeof(argv) /
sizeof(
char*);
115 nRet = freerdp_client_settings_parse_command_line(settings, argc, argv, TRUE);
118 nRet = freerdp_client_settings_command_line_status_print(settings, nRet, argc, argv);
119 return OnInitReturnValue::Fail;
122#if FreeRDP_VERSION_MAJOR >= 3
123 if (!stream_dump_register_handlers(pRdpContext,
124 CONNECTION_STATE_MCS_CREATE_REQUEST,
126 return OnInitReturnValue::Fail;
129 auto &user = m_pParameter->m_Net.
m_User;
130 if(!user.GetUser().isEmpty())
131 freerdp_settings_set_string(
132 settings, FreeRDP_Username,
133 user.GetUser().toStdString().c_str());
134 if(!user.GetPassword().isEmpty())
135 freerdp_settings_set_string(
136 settings, FreeRDP_Password,
137 user.GetPassword().toStdString().c_str());
139 freerdp_settings_set_bool(
140 settings, FreeRDP_RedirectClipboard, m_pParameter->GetClipboard());
142#if FreeRDP_VERSION_MAJOR >= 3
143 bool bOnlyView = m_pParameter->GetOnlyView();
144 freerdp_settings_set_bool(
145 settings, FreeRDP_SuspendInput, bOnlyView);
148 freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
149 m_pParameter->GetDesktopWidth());
150 freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
151 m_pParameter->GetDesktopHeight());
152 freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth,
153 m_pParameter->GetColorDepth());
155 freerdp_settings_set_bool(settings, FreeRDP_UseMultimon,
156 m_pParameter->GetUseMultimon());
158 if(m_pParameter->GetReconnectInterval()) {
159 freerdp_settings_set_bool(
160 settings, FreeRDP_AutoReconnectionEnabled,
true);
161 freerdp_settings_set_uint32(
163 FreeRDP_AutoReconnectMaxRetries,
164 m_pParameter->GetReconnectInterval());
167 freerdp_settings_set_bool(
168 settings, FreeRDP_AutoReconnectionEnabled,
false);
172 RedirectionMicrophone();
174 RedirectionPrinter();
179 switch(m_pParameter->m_Proxy.GetUsedType())
181 case CParameterProxy::TYPE::None:
183 if(!m_pParameter->GetDomain().isEmpty())
184 freerdp_settings_set_string(
185 settings, FreeRDP_Domain,
186 m_pParameter->GetDomain().toStdString().c_str());
187 if(m_pParameter->m_Net.GetHost().isEmpty())
190 szErr = tr(
"The server is empty, please input it");
191 qCritical(log) << szErr;
193 emit
sigError(-1, szErr.toStdString().c_str());
194 return OnInitReturnValue::Fail;
196 auto &net = m_pParameter->m_Net;
197 freerdp_settings_set_string(
198 settings, FreeRDP_ServerHostname,
199 net.GetHost().toStdString().c_str());
200 freerdp_settings_set_uint32(
201 settings, FreeRDP_ServerPort,
204 nRet = freerdp_client_start(pRdpContext);
207 qCritical(log) <<
"freerdp_client_start fail";
208 return OnInitReturnValue::Fail;
213 case CParameterProxy::TYPE::SSHTunnel:
217 auto &ssh = m_pParameter->m_Proxy.m_SSH;
218 parameter->setServer(ssh.GetHost());
219 parameter->setPort(ssh.GetPort());
221 parameter->SetUser(user.GetUser());
222 parameter->SetUseSystemFile(user.GetUseSystemFile());
223 if(CParameterUser::TYPE::UserPassword == user.GetUsedType()) {
224 parameter->SetAuthenticationMethod(SSH_AUTH_METHOD_PASSWORD);
225 parameter->SetPassword(user.GetPassword());
227 if(CParameterUser::TYPE::PublicKey == user.GetUsedType()) {
228 parameter->SetAuthenticationMethod(SSH_AUTH_METHOD_PUBLICKEY);
229 parameter->SetPublicKeyFile(user.GetPublicKeyFile());
230 parameter->SetPrivateKeyFile(user.GetPrivateKeyFile());
231 parameter->SetPassphrase(user.GetPassphrase());
233 auto &net = m_pParameter->m_Net;
234 parameter->SetRemoteHost(net.GetHost());
235 parameter->SetRemotePort(net.GetPort());
241 return OnInitReturnValue::Fail;
242 bool check = connect(m_pThread, SIGNAL(sigServer(QString, quint16)),
243 this, SLOT(slotConnectProxyServer(QString, quint16)));
245 check = connect(m_pThread, SIGNAL(
sigError(
int,QString)),
246 this, SIGNAL(
sigError(
int,QString)));
259 return OnInitReturnValue::UseOnProcess;
264 qDebug(log) << Q_FUNC_INFO;
276 CloseHandle(m_writeEvent);
277 m_writeEvent =
nullptr;
281 rdpContext* pRdpContext = (rdpContext*)m_pContext;
282 if(!freerdp_disconnect(pRdpContext->instance))
283 qCritical(log) <<
"freerdp_disconnect fail";
285 if(freerdp_client_stop(pRdpContext))
286 qCritical(log) <<
"freerdp_client_stop fail";
288 freerdp_client_context_free(pRdpContext);
289 m_pContext =
nullptr;
312 rdpContext* pRdpContext = (rdpContext*)m_pContext;
314 if(
nullptr == freerdp_settings_get_string(pRdpContext->settings, FreeRDP_ServerHostname))
322 nCount = freerdp_get_event_handles(pRdpContext, &handles[nCount],
323 ARRAYSIZE(handles) - nCount);
326 qCritical(log) <<
"freerdp_get_event_handles failed";
331 handles[nCount] = m_writeEvent;
334 DWORD waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, 500);
336 ResetEvent(m_writeEvent);
338 if (waitStatus == WAIT_FAILED)
340 qCritical(log) <<
"WaitForMultipleObjects: WAIT_FAILED";
345 if(waitStatus == WAIT_TIMEOUT)
352 if (!freerdp_check_event_handles(pRdpContext))
356 UINT32 err = freerdp_get_last_error(pRdpContext);
358 szErr =
"freerdp_check_event_handles fail.";
360 szErr += QString::number(err);
362 szErr += freerdp_get_last_error_category(err);
364 szErr += freerdp_get_last_error_name(err);
366 szErr += freerdp_get_last_error_string(err);
367 qCritical(log) << szErr;
391#if FreeRDP_VERSION_MAJOR >= 3
392 if(freerdp_shall_disconnect_context(pRdpContext))
394 if(freerdp_shall_disconnect(pRdpContext->instance))
397 qCritical(log) <<
"freerdp_shall_disconnect false";
405void CConnectFreeRDP::slotClipBoardChanged()
407 qDebug(log) << Q_FUNC_INFO;
408 if(m_pParameter && m_pParameter->GetOnlyView())
return;
409 if(m_pParameter->GetClipboard())
410 m_ClipBoard.slotClipBoardChanged();
413BOOL CConnectFreeRDP::cbGlobalInit()
415 qDebug(log) << Q_FUNC_INFO;
419void CConnectFreeRDP::cbGlobalUninit()
421 qDebug(log) << Q_FUNC_INFO;
424BOOL CConnectFreeRDP::cbClientNew(freerdp *instance, rdpContext *context)
426 qDebug(log) << Q_FUNC_INFO;
429 instance->PostDisconnect = cb_post_disconnect;
432#if FreeRDP_VERSION_MAJOR < 3
433 instance->Authenticate = cb_authenticate;
434 instance->GatewayAuthenticate = cb_GatewayAuthenticate;
436 instance->AuthenticateEx = cb_authenticate_ex;
437 instance->ChooseSmartcard = cb_choose_smartcard;
442 instance->PresentGatewayMessage = cb_present_gateway_message;
444 instance->LogonErrorInfo = cb_logon_error_info;
449void CConnectFreeRDP::cbClientFree(freerdp *instance, rdpContext *context)
451 qDebug(log) << Q_FUNC_INFO;
454int CConnectFreeRDP::cbClientStart(rdpContext *context)
456 qDebug(log) << Q_FUNC_INFO;
459 if (!context || !context->settings)
461 freerdp* instance = freerdp_client_get_instance(context);
465 auto settings = context->settings;
469 szHost = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
470 nPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
472 auto &net = pThis->m_pParameter->m_Net;
473 szServer = net.GetHost() +
":" + QString::number(net.GetPort());
474 auto &proxy = pThis->m_pParameter->m_Proxy;
475 switch(proxy.GetUsedType()) {
476 case CParameterProxy::TYPE::SSHTunnel:
478 auto &sshNet = proxy.m_SSH;
479 szServer = szHost +
":" + QString::number(nPort)
480 +
" <-> " + sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
481 +
" <-> " + szServer;
488 BOOL status = freerdp_connect(instance);
490 QString szInfo = tr(
"Connect to ") + szServer;
491 qInfo(log) << szInfo;
495 UINT32 nErr = freerdp_get_last_error(context);
498 szErr = tr(
"Connect to ") + szServer + tr(
" fail.");
500 szErr += QString::number(nErr) +
" - ";
501 szErr += freerdp_get_last_error_name(nErr);
506 szErr += freerdp_get_last_error_string(nErr);
510 case FREERDP_ERROR_CONNECT_LOGON_FAILURE:
513 QString szErr = tr(
"Logon to ") + szServer;
514 szErr += tr(
" fail. Please check that the username and password are correct.") +
"\n";
518 case FREERDP_ERROR_CONNECT_WRONG_PASSWORD:
521 QString szErr = tr(
"Logon to ") + szServer;
522 szErr += tr(
" fail. Please check password are correct.") +
"\n";
526 case FREERDP_ERROR_AUTHENTICATION_FAILED:
529 QString szErr = tr(
"Logon to ") + szServer;
530 szErr += tr(
" authentication fail. please add a CA certificate to the store.") +
"\n";
534 case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED:
537 QString szErr = tr(
"Logon to ") + szServer;
538 szErr += tr(
" connect transport layer fail.") +
"\n\n";
539 szErr += tr(
"Please:") +
"\n";
540 szErr += tr(
"1. Check for any network related issues") +
"\n";
541 szErr += tr(
"2. Check you have proper security settings ('NLA' enabled is required for most connections nowadays)") +
"\n";
542 szErr += tr(
"3. Check the certificate is proper (and guacd properly checks that)") +
"\n";
546 case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED:
552 qCritical(log) << szErr;
553 emit pThis->
sigError(nRet, szErr.toStdString().c_str());
558int CConnectFreeRDP::cbClientStop(rdpContext *context)
561 qDebug(log) << Q_FUNC_INFO;
562#if FreeRDP_VERSION_MAJOR >= 3
563 nRet = freerdp_client_common_stop(context);
565 BOOL bRet = freerdp_abort_connect(context->instance);
567 { qCritical(log) <<
"freerdp_abort_connect fail";
594 qDebug(log) << Q_FUNC_INFO;
595 rdpChannels* channels =
nullptr;
596 rdpSettings* settings =
nullptr;
597 rdpContext* context = instance->context;
599 if (!instance || !instance->context || !instance->context->settings)
605 if(!pThis)
return FALSE;
606 settings = instance->context->settings;
607 channels = context->channels;
610#if defined (Q_OS_WIN)
611 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_WINDOWS))
613 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_WINDOWS_NT))
615#elif defined(Q_OS_ANDROID)
616 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_ANDROID))
618 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
620#elif defined(Q_OS_IOS)
621 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_IOS))
623 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
625#elif defined (Q_OS_UNIX)
626 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX))
628 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_XSERVER))
631 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNSPECIFIED))
633 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
638 PubSub_SubscribeChannelConnected(instance->context->pubSub,
639 OnChannelConnectedEventHandler);
640 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
641 OnChannelDisconnectedEventHandler);
643#if FreeRDP_VERSION_MAJOR < 3
644 if (!freerdp_client_load_addins(channels, instance->context->settings))
649 if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly))
652 auto &user = pThis->m_pParameter->m_Net.
m_User;
653 if(!freerdp_settings_get_string(settings, FreeRDP_Username)) {
654 if(user.GetUser().isEmpty()) {
655 if(user.GetUser().isEmpty()) {
657 qWarning(log) <<
"Auth-only, but no user name set. Will be call instance->Authenticate.";
660 freerdp_settings_set_string(
661 settings, FreeRDP_Username,
662 user.GetUser().toStdString().c_str());
664 if (!freerdp_settings_get_string(settings, FreeRDP_Password)) {
665 if (user.GetPassword().isEmpty()) {
667 qWarning(log) <<
"auth-only, but no password set. Will be call instance->Authenticate";
669 freerdp_settings_set_string(
670 settings, FreeRDP_Password,
671 user.GetPassword().toStdString().c_str());
673#if FreeRDP_VERSION_MAJOR >= 3
674 if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE))
677 qInfo(log) <<
"Authentication only. Don't connect to X.";
678 }
else if(freerdp_settings_get_bool(settings, FreeRDP_CredentialsFromStdin)){
680 }
else if(freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon)) {
691 UINT32 width = pThis->m_pParameter->GetDesktopWidth();
692 UINT32 height = pThis->m_pParameter->GetDesktopHeight();
693 if ((width < 64) || (height < 64) ||
694 (width > 4096) || (height > 4096))
696 QString szErr = tr(
"Invalid dimensions:")
697 + QString::number(width)
698 +
"*" + QString::number(height);
699 qCritical(log) << szErr;
703 qInfo(log) <<
"Init desktop size " << width <<
"*" << height;
707 <<
"width:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)
708 <<
"height:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)
709 <<
"ColorDepth:" << freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
714const char* CConnectFreeRDP::GetTitle(freerdp* instance)
716 const char* windowTitle;
719 const char* name =
nullptr;
722 rdpSettings* settings = instance->context->settings;
727 windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
731#if FreeRDP_VERSION_MAJOR >= 3
732 name = freerdp_settings_get_server_name(settings);
734 name = pThis->m_pParameter->m_Net.GetHost().toStdString().c_str();
736 port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
738 addPort = (port != 3389);
740 char buffer[MAX_PATH + 64] = { 0 };
743 sprintf_s(buffer,
sizeof(buffer),
"%s", name);
745 sprintf_s(buffer,
sizeof(buffer),
"%s:%" PRIu32, name, port);
747 freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer);
748 return freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
758 qDebug(log) << Q_FUNC_INFO;
760 rdpContext* context = instance->context;
761 rdpSettings* settings = instance->context->settings;
762 rdpUpdate* update = instance->context->update;
765 const char* pWindowTitle = GetTitle(instance);
768 WCHAR* windowTitle = NULL;
769#if FreeRDP_VERSION_MAJOR >= 3
770 windowTitle = ConvertUtf8ToWCharAlloc(pWindowTitle, NULL);
772 ConvertToUnicode(CP_UTF8, 0, pWindowTitle, -1, &windowTitle, 0);
776 QString title = QString::fromUtf16((
const char16_t*)windowTitle);
778 if(pThis->m_pParameter->GetServerName().isEmpty())
779 emit pThis->sigServerName(title);
783 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
784 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
785 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
787 if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
790 if(!pThis->CreateImage(instance->context))
793 Q_ASSERT(instance->context->cache);
796 if(pThis->m_Cursor.RegisterPointer(context->graphics))
799 update->BeginPaint = cb_begin_paint;
800 update->EndPaint = cb_end_paint;
801 update->DesktopResize = cb_desktop_resize;
803 update->PlaySound = cb_play_bell_sound;
805 update->SetKeyboardIndicators = cb_keyboard_set_indicators;
806 update->SetKeyboardImeStatus = cb_keyboard_set_ime_status;
812void CConnectFreeRDP::cb_post_disconnect(freerdp* instance)
814 qDebug(log) << Q_FUNC_INFO;
815 rdpContext* context =
nullptr;
817 if (!instance || !instance->context)
820 context = instance->context;
822 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
823 OnChannelConnectedEventHandler);
824 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
825 OnChannelDisconnectedEventHandler);
829int CConnectFreeRDP::cb_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
832 const char* str_data = freerdp_get_logon_error_info_data(data);
833 const char* str_type = freerdp_get_logon_error_info_type(type);
834 QString szErr = tr(
"FreeRDP logon info: [");
838 qDebug(log) << szErr;
844void CConnectFreeRDP::OnChannelConnectedEventHandler(
void *context,
845 #
if FreeRDP_VERSION_MAJOR >= 3
848 ChannelConnectedEventArgs *e)
850 rdpContext* pContext = (rdpContext*)context;
852 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
853 qDebug(log) <<
"channel" << e->name <<
"connected";
854 pThis->m_ClipBoard.Init((CliprdrClientContext*)e->pInterface,
855 pThis->m_pParameter->GetClipboard());
857#if FreeRDP_VERSION_MAJOR >= 3
859 freerdp_client_OnChannelConnectedEventHandler(pContext, e);
861 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
863 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
864 rdpGdi* gdi = pContext->gdi;
866 gdi_graphics_pipeline_init(gdi, (RdpgfxClientContext*) e->pInterface);
869 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
871 else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
873 gdi_video_geometry_init(pContext->gdi, (GeometryClientContext*)e->pInterface);
875 else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
877 gdi_video_data_init(pContext->gdi, (VideoClientContext*)e->pInterface);
879 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"connected but we can’t use it";
883void CConnectFreeRDP::OnChannelDisconnectedEventHandler(
void *context,
884 #
if FreeRDP_VERSION_MAJOR >= 3
887 ChannelDisconnectedEventArgs *e)
889 rdpContext* pContext = (rdpContext*)context;
892 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
893 qDebug(log) <<
"channel" << e->name <<
"disconnected";
894 pThis->m_ClipBoard.UnInit((CliprdrClientContext*)e->pInterface,
895 pThis->m_pParameter->GetClipboard());
897#if FreeRDP_VERSION_MAJOR >= 3
899 freerdp_client_OnChannelDisconnectedEventHandler(pContext, e);
901 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
903 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
904 rdpGdi* gdi = pContext->gdi;
905 gdi_graphics_pipeline_uninit(gdi, (RdpgfxClientContext*) e->pInterface);
908 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
911 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"disconnected but we can’t use it";
916UINT32 CConnectFreeRDP::GetImageFormat(QImage::Format format)
919#if (QT_VERSION >= QT_VERSION_CHECK(5,2,0))
920 case QImage::Format_RGBA8888:
921 return PIXEL_FORMAT_RGBA32;
922 case QImage::Format_RGBX8888:
923 return PIXEL_FORMAT_RGBX32;
925 case QImage::Format_RGB16:
926 return PIXEL_FORMAT_RGB16;
927 case QImage::Format_ARGB32:
928 return PIXEL_FORMAT_BGRA32;
929 case QImage::Format_RGB32:
930 return PIXEL_FORMAT_BGRA32;
937UINT32 CConnectFreeRDP::GetImageFormat()
939 return GetImageFormat(m_Image.format());
942BOOL CConnectFreeRDP::CreateImage(rdpContext *context)
945 ClientContext* pContext = (ClientContext*)context;
947 rdpGdi* gdi = context->gdi;
948 Q_ASSERT(pThis && gdi);
949 pThis->m_Image = QImage(gdi->primary_buffer,
950 static_cast<int>(gdi->width),
951 static_cast<int>(gdi->height),
952 QImage::Format_ARGB32);
956#if FreeRDP_VERSION_MAJOR >= 3
958static CREDUI_INFOW wfUiInfo = {
sizeof(CREDUI_INFOW), NULL, L
"Enter your credentials",
959 L
"Remote Desktop Security", NULL };
961BOOL CConnectFreeRDP::cb_authenticate_ex(freerdp* instance,
962 char** username,
char** password,
963 char** domain, rdp_auth_reason reason)
965 qDebug(log) << Q_FUNC_INFO <<
"reason:" << reason;
969 if(!username || !password || !domain)
return FALSE;
971 rdpContext* pContext = (rdpContext*)instance->context;
976 WCHAR UserNameW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
977 WCHAR UserW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
978 WCHAR DomainW[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
979 WCHAR PasswordW[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 };
981 WINPR_ASSERT(instance);
982 WINPR_ASSERT(instance->context);
983 WINPR_ASSERT(instance->context->settings);
985 WINPR_ASSERT(username);
986 WINPR_ASSERT(domain);
987 WINPR_ASSERT(password);
989 const WCHAR auth[] = L
"Target credentials requested";
990 const WCHAR authPin[] = L
"PIN requested";
991 const WCHAR gwAuth[] = L
"Gateway credentials requested";
992 const WCHAR* titleW = auth;
995 dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
996 CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1003 if ((*username) && (*password))
1006 case AUTH_SMARTCARD_PIN:
1007 dwFlags &= ~CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1008 dwFlags |= CREDUI_FLAGS_PASSWORD_ONLY_OK | CREDUI_FLAGS_KEEP_USERNAME;
1013 *username = _strdup(
"PIN");
1026 ConvertUtf8ToWChar(*username, UserNameW, ARRAYSIZE(UserNameW));
1027 ConvertUtf8ToWChar(*username, UserW, ARRAYSIZE(UserW));
1031 ConvertUtf8ToWChar(*password, PasswordW, ARRAYSIZE(PasswordW));
1034 ConvertUtf8ToWChar(*domain, DomainW, ARRAYSIZE(DomainW));
1036 if (_wcsnlen(PasswordW, ARRAYSIZE(PasswordW)) == 0)
1038 status = CredUIPromptForCredentialsW(&wfUiInfo, titleW, NULL, 0, UserNameW,
1039 ARRAYSIZE(UserNameW), PasswordW,
1040 ARRAYSIZE(PasswordW), &fSave, dwFlags);
1041 if (status != NO_ERROR)
1044 "CredUIPromptForCredentials unexpected status: 0x%08lX",
1049 if ((dwFlags & CREDUI_FLAGS_KEEP_USERNAME) == 0)
1051 status = CredUIParseUserNameW(UserNameW, UserW, ARRAYSIZE(UserW), DomainW,
1052 ARRAYSIZE(DomainW));
1053 if (status != NO_ERROR)
1055 CHAR User[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1056 CHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1057 CHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1059 ConvertWCharNToUtf8(UserNameW, ARRAYSIZE(UserNameW), UserName, ARRAYSIZE(UserName));
1060 ConvertWCharNToUtf8(UserW, ARRAYSIZE(UserW), User, ARRAYSIZE(User));
1061 ConvertWCharNToUtf8(DomainW, ARRAYSIZE(DomainW), Domain, ARRAYSIZE(Domain));
1063 "Failed to parse UserName: %s into User: %s Domain: %s",
1064 UserName, User, Domain);
1070 *username = ConvertWCharNToUtf8Alloc(UserW, ARRAYSIZE(UserW), NULL);
1073 qCritical(log) <<
"ConvertWCharNToUtf8Alloc failed" << status;
1077 if (_wcsnlen(DomainW, ARRAYSIZE(DomainW)) > 0)
1078 *domain = ConvertWCharNToUtf8Alloc(DomainW, ARRAYSIZE(DomainW), NULL);
1080 *domain = _strdup(
"\0");
1085 qCritical(log) <<
"strdup failed" << status;
1089 *password = ConvertWCharNToUtf8Alloc(PasswordW, ARRAYSIZE(PasswordW), NULL);
1098 return cb_authenticate(instance, username, password, domain);
1103BOOL CConnectFreeRDP::cb_choose_smartcard(freerdp* instance,
1104 SmartcardCertInfo** cert_list,
1106 DWORD* choice, BOOL gateway)
1108 rdpContext* pContext = (rdpContext*)instance->context;
1110 QString msg(
"Multiple smartcards are available for use:\n");
1111 for (DWORD i = 0; i < count; i++)
1113 const SmartcardCertInfo* cert = cert_list[i];
1114 char* reader = ConvertWCharToUtf8Alloc(cert->reader, NULL);
1115 char* container_name = ConvertWCharToUtf8Alloc(cert->containerName, NULL);
1117 msg += QString::number(i) +
" ";
1118 msg += QString(container_name) +
"\n\t";
1119 msg +=
"Reader: " + QString(reader) +
"\n\t";
1120 msg +=
"User: " + QString(cert->userHint) + +
"@" + QString(cert->domainHint) +
"\n\t";
1121 msg +=
"Subject: " + QString(cert->subject) +
"\n\t";
1122 msg +=
"Issuer: " + QString(cert->issuer) +
"\n\t";
1123 msg +=
"UPN: " + QString(cert->upn) +
"\n";
1126 free(container_name);
1129 msg +=
"\nChoose a smartcard to use for ";
1131 msg +=
"gateway authentication";
1135 msg +=
"(0 - " + QString::number(count - 1) +
")";
1143 int n = num.toInt(&ok);
1155BOOL CConnectFreeRDP::cb_authenticate(freerdp* instance,
char** username,
1156 char** password,
char** domain)
1158 qDebug(log) << Q_FUNC_INFO;
1161 rdpContext* pContext = (rdpContext*)instance->context;
1163 if(!username || !password || !domain)
return FALSE;
1164 if(*username && *password )
return TRUE;
1166 int nRet = QDialog::Rejected;
1168 nRet, pThis->m_pParameter);
1169 if(QDialog::Accepted == nRet)
1171 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1172 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1173 QString szDomain = pThis->m_pParameter->GetDomain();
1174 if(!szDomain.isEmpty() && domain)
1175 *domain = _strdup(szDomain.toStdString().c_str());
1176 if(!szName.isEmpty() && username)
1177 *username = _strdup(szName.toStdString().c_str());
1178 if(!szPassword.isEmpty() && password)
1179 *password = _strdup(szPassword.toStdString().c_str());
1186BOOL CConnectFreeRDP::cb_GatewayAuthenticate(freerdp *instance,
1187 char **username,
char **password,
char **domain)
1189 qDebug(log) << Q_FUNC_INFO;
1193 rdpContext* pContext = (rdpContext*)instance->context;
1195 if(!username || !password || !domain)
return FALSE;
1196 if(*username && *password )
return TRUE;
1198 int nRet = QDialog::Rejected;
1199 emit pThis->
sigBlockShowWidget(
"CDlgGetUserPasswordFreeRDP", nRet, pThis->m_pParameter);
1200 if(QDialog::Accepted == nRet)
1202 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1203 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1204 QString szDomain = pThis->m_pParameter->GetDomain();
1205 if(!szDomain.isEmpty() && domain)
1206 *domain = _strdup(szDomain.toStdString().c_str());
1207 if(!szName.isEmpty() && username)
1208 *username = _strdup(szName.toStdString().c_str());
1209 if(!szPassword.isEmpty() && password)
1210 *password = _strdup(szPassword.toStdString().c_str());
1218 const BYTE* data,
size_t length,
1219 const char* hostname, UINT16 port, DWORD flags)
1221 qDebug(log) << Q_FUNC_INFO;
1222 rdpContext* pContext = (rdpContext*)instance->context;
1224 QSslCertificate cert(QByteArray((
const char*)data, length));
1227 instance, hostname, port,
1228 cert.issuerDisplayName().toStdString().c_str(),
1229 cert.subjectDisplayName().toStdString().c_str(),
1230 cert.issuerDisplayName().toStdString().c_str(),
1231 cert.serialNumber().toStdString().c_str(),
1253 const char *host, UINT16 port,
1254 const char *common_name,
const char *subject,
1255 const char *issuer,
const char *fingerprint, DWORD flags)
1257 qDebug(log) << Q_FUNC_INFO;
1259 rdpContext* pContext = (rdpContext*)instance->context;
1266 emit pThis->sigServerName(common_name);
1269 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1275 QString szType = tr(
"RDP-Server");
1276 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1277 szType = tr(
"RDP-Gateway");
1278 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1279 szType = tr(
"RDP-Redirect");
1281 QString title(tr(
"Verify certificate"));
1284 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1285 message += tr(
"Common name: ") + common_name +
"\n";
1286 message += tr(
"Subject: ") + subject +
"\n";
1287 message += tr(
"Issuer: ") + issuer +
"\n";
1288 message += tr(
"Fingerprint: ") + fingerprint +
"\n";
1290 if(VERIFY_CERT_FLAG_CHANGED & flags) {
1291 message += tr(
"The above X.509 certificate is changed.\n"
1292 "It is possible that the server has changed its certificate, "
1293 "or Maybe it was attacked."
1294 "Please look at the OpenSSL documentation on "
1295 "how to add a private CA to the store.");
1297 message += tr(
"The above X.509 certificate could not be verified.\n"
1298 "Possibly because you do not have the CA certificate "
1299 "in your certificate store, or the certificate has expired.\n"
1300 "Please look at the OpenSSL documentation on "
1301 "how to add a private CA to the store.");
1305 message += tr(
"Yes - trusted") +
"\n";
1306 message += tr(
"Ignore - temporary trusted") +
"\n";
1307 message += tr(
"No - no trusted") +
"\n";
1309 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1310 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1311 bool bCheckBox =
false;
1313 tr(
"Don't show again"));
1314 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1320 case QMessageBox::StandardButton::Yes:
1322 case QMessageBox::StandardButton::Ignore:
1350 const char *host, UINT16 port,
1351 const char *common_name,
const char *subject,
1352 const char *issuer,
const char *fingerprint,
1353 const char *old_subject,
const char *old_issuer,
1354 const char *old_fingerprint, DWORD flags)
1356 qDebug(log) << Q_FUNC_INFO;
1357 rdpContext* pContext = (rdpContext*)instance->context;
1360 emit pThis->sigServerName(common_name);
1362 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1368 QString szType = tr(
"RDP-Server");
1369 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1370 szType = tr(
"RDP-Gateway");
1371 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1372 szType = tr(
"RDP-Redirect");
1374 QString title(tr(
"Verify changed certificate"));
1376 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1377 message += tr(
"Common name: ") + common_name +
"\n";
1378 message += tr(
"New subject: ") + subject +
"\n";
1379 message += tr(
"New issuer: ") + issuer +
"\n";
1380 message += tr(
"New fingerprint: ") + fingerprint +
"\n";
1381 message += tr(
"Old subject: ") + old_subject +
"\n";
1382 message += tr(
"Old issuer: ") + old_issuer +
"\n";
1383 message += tr(
"Old fingerprint: ") + old_fingerprint +
"\n";
1385 message += tr(
"The above X.509 certificate could not be verified, "
1386 "possibly because you do not have the CA certificate "
1387 "in your certificate store, or the certificate has expired. "
1388 "Please look at the OpenSSL documentation on "
1389 "how to add a private CA to the store.");
1392 message += tr(
"Yes - trusted") +
"\n";
1393 message += tr(
"Ignore - temporary trusted") +
"\n";
1394 message += tr(
"No - no trusted") +
"\n";
1396 bool bCheckBox =
false;
1397 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1398 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1400 tr(
"Don't show again"));
1401 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1408 case QMessageBox::StandardButton::Yes:
1410 case QMessageBox::StandardButton::Ignore:
1421BOOL CConnectFreeRDP::cb_present_gateway_message(
1422 freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
1423 BOOL isConsentMandatory,
size_t length,
const WCHAR* message)
1425 qDebug(log) << Q_FUNC_INFO;
1427 if (!isDisplayMandatory && !isConsentMandatory)
1431 if (type == GATEWAY_MESSAGE_CONSENT && isConsentMandatory)
1433 QString msgType = (type == GATEWAY_MESSAGE_CONSENT)
1434 ? tr(
"Consent message") : tr(
"Service message");
1436#if FreeRDP_VERSION_MAJOR >= 3
1437 char* pMsg = ConvertWCharToUtf8Alloc(message, NULL);
1443 msgType += QString::fromStdWString((
wchar_t*)message);
1446 msgType += tr(
"I understand and agree to the terms of this policy (Y/N)");
1448 rdpContext* pContext = (rdpContext*)instance->context;
1450 QMessageBox::StandardButton nRet = QMessageBox::No;
1451 bool bCheckBox =
false;
1453 QMessageBox::Yes|QMessageBox::No,
1456 case QMessageBox::Yes:
1464 return client_cli_present_gateway_message(
1465 instance, type, isDisplayMandatory,
1466 isConsentMandatory, length, message);
1471BOOL CConnectFreeRDP::cb_begin_paint(rdpContext *context)
1475 if (!context || !context->gdi || !context->gdi->primary
1476 || !context->gdi->primary->hdc)
1479 hdc = context->gdi->primary->hdc;
1481 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1484 hdc->hwnd->invalid->null = TRUE;
1485 hdc->hwnd->ninvalid = 0;
1489BOOL CConnectFreeRDP::UpdateBuffer(INT32 x, INT32 y, INT32 w, INT32 h)
1491 if(x > m_Image.width() || y > m_Image.height()) {
1492 qCritical(log) <<
"The width and height out of range."
1493 <<
"Image width:" << m_Image.width()
1494 <<
"Image height:" << m_Image.height()
1495 <<
"w:" << w <<
"h:" << h;
1499 QRect rect(x, y, w, h);
1500 QImage img = m_Image.copy(rect);
1506BOOL CConnectFreeRDP::cb_end_paint(rdpContext *context)
1509 ClientContext* pContext = (ClientContext*)context;
1513 REGION16 invalidRegion;
1514 RECTANGLE_16 invalidRect;
1515 const RECTANGLE_16* extents;
1519 if (!context || !context->gdi || !context->gdi->primary
1520 || !context->gdi->primary->hdc)
1523 hdc = context->gdi->primary->hdc;
1525 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1528 rdpGdi* gdi = context->gdi;
1529 if (gdi->suppressOutput)
1532 HGDI_WND hwnd = context->gdi->primary->hdc->hwnd;
1533 ninvalid = hwnd->ninvalid;
1534 cinvalid = hwnd->cinvalid;
1538 region16_init(&invalidRegion);
1540 for (i = 0; i < ninvalid; i++)
1542 if(cinvalid[i].null)
1544 qWarning(log) <<
"is null region" << cinvalid[i].x << cinvalid[i].y
1545 << cinvalid[i].w << cinvalid[i].h;
1548 invalidRect.left = cinvalid[i].x;
1549 invalidRect.top = cinvalid[i].y;
1550 invalidRect.right = cinvalid[i].x + cinvalid[i].w;
1551 invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;
1552 region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
1555 if (!region16_is_empty(&invalidRegion))
1557 extents = region16_extents(&invalidRegion);
1559 pThis->UpdateBuffer(extents->left,
1561 extents->right - extents->left,
1562 extents->bottom - extents->top);
1565 region16_uninit(&invalidRegion);
1570BOOL CConnectFreeRDP::cb_desktop_resize(rdpContext* context)
1572 qDebug(log) << Q_FUNC_INFO;
1573 ClientContext* pContext = (ClientContext*)context;
1575 rdpSettings* settings;
1576 if (!context || !context->settings)
1578 settings = context->settings;
1579 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
1580 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
1582 if(!gdi_resize(context->gdi, desktopWidth, desktopHeight))
1584 if(!pThis->CreateImage(context))
1587 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
1588 pThis->UpdateBuffer(0, 0, desktopWidth, desktopHeight);
1592BOOL CConnectFreeRDP::cb_play_bell_sound(rdpContext *context,
const PLAY_SOUND_UPDATE *play_sound)
1594 qDebug(log) << Q_FUNC_INFO;
1595 ClientContext* pContext = (ClientContext*)context;
1597 WINPR_UNUSED(play_sound);
1598 QApplication::beep();
1602#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1603 QSoundEffect effect;
1604 effect.setSource(QUrl::fromLocalFile(szFile));
1609 QSound::play(szFile);
1615BOOL CConnectFreeRDP::cb_keyboard_set_indicators(rdpContext *context, UINT16 led_flags)
1617 qDebug(log) << Q_FUNC_INFO;
1618 ClientContext* pContext = (ClientContext*)context;
1621 int state = CFrmViewer::LED_STATE::Unknown;
1623 if (led_flags & KBD_SYNC_NUM_LOCK)
1624 state |= CFrmViewer::LED_STATE::NumLock;
1625 if (led_flags & KBD_SYNC_CAPS_LOCK)
1626 state |= CFrmViewer::LED_STATE::CapsLock;
1627 if (led_flags & KBD_SYNC_SCROLL_LOCK)
1628 state |= CFrmViewer::LED_STATE::ScrollLock;
1630 emit pThis->sigUpdateLedState(state);
1636BOOL CConnectFreeRDP::cb_keyboard_set_ime_status(
1637 rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode)
1643 "KeyboardSetImeStatus(unitId=%04" PRIx16
", imeState=%08" PRIx32
1644 ", imeConvMode=%08" PRIx32
") ignored",
1645 imeId, imeState, imeConvMode);
1652 SetEvent(m_writeEvent);
1657bool CConnectFreeRDP::SendMouseEvent(UINT16 flags, QPoint pos,
bool isExtended)
1659 if(m_pParameter && m_pParameter->GetOnlyView())
return true;
1660 if(!m_pContext)
return false;
1662#if FreeRDP_VERSION_MAJOR >= 3
1664 freerdp_client_send_extended_button_event(
1665 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
1667 freerdp_client_send_button_event(
1668 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
1670 if(!m_pContext->Context.input)
return false;
1671 return freerdp_input_send_mouse_event(
1672 m_pContext->Context.input, flags, pos.x(), pos.y());
1677void CConnectFreeRDP::wheelEvent(QWheelEvent *event)
1679 qDebug(logMouse) << Q_FUNC_INFO << event;
1680 if(!m_pContext)
return;
1681 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1685#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1686 pos =
event->position();
1690 QPoint p =
event->angleDelta();
1693 flags |= PTR_FLAGS_WHEEL | p.y();
1697 flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.y();
1702 flags |= PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.x();
1706 flags |= PTR_FLAGS_HWHEEL | p.x();
1708#if FreeRDP_VERSION_MAJOR >= 3
1709 freerdp_client_send_wheel_event(&m_pContext->Context, flags);
1714 freerdp_input_send_mouse_event(
1715 m_pContext->Context.input, flags, pos.x(), pos.y());
1720void CConnectFreeRDP::mouseMoveEvent(QMouseEvent *event)
1722 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
1723 if(!m_pContext)
return;
1724 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1725 UINT16 flags = PTR_FLAGS_MOVE;
1726 SendMouseEvent(flags, event->pos(),
false);
1729void CConnectFreeRDP::mousePressEvent(QMouseEvent *event)
1731 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
1732 if(!m_pContext)
return;
1733 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1736 bool isExtended =
false;
1737 Qt::MouseButton button =
event->button();
1738 if (button & Qt::MouseButton::LeftButton)
1740 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
1742 else if (button & Qt::MouseButton::RightButton)
1744 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
1746 else if (button & Qt::MouseButton::MiddleButton)
1748 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
1750 else if (button & Qt::MouseButton::ForwardButton)
1752 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
1755 else if (button & Qt::MouseButton::BackButton)
1757 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
1762 SendMouseEvent(flags, event->pos(), isExtended);
1766void CConnectFreeRDP::mouseReleaseEvent(QMouseEvent *event)
1768 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
1769 if(!m_pContext)
return;
1770 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1773 bool isExtended =
false;
1774 Qt::MouseButton button =
event->button();
1775 if (button & Qt::MouseButton::LeftButton)
1777 flags = PTR_FLAGS_BUTTON1;
1779 else if (button & Qt::MouseButton::MiddleButton)
1781 flags = PTR_FLAGS_BUTTON3;
1783 else if (button & Qt::MouseButton::RightButton)
1785 flags = PTR_FLAGS_BUTTON2;
1787 else if (button & Qt::MouseButton::ForwardButton)
1789 flags = PTR_XFLAGS_BUTTON2;
1792 else if (button & Qt::MouseButton::BackButton)
1794 flags = PTR_XFLAGS_BUTTON1;
1799 SendMouseEvent(flags, event->pos(), isExtended);
1803void CConnectFreeRDP::keyPressEvent(QKeyEvent *event)
1805 qDebug(logKey) << Q_FUNC_INFO << event;
1806 if(!m_pContext)
return;
1807 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1810 if(RDP_SCANCODE_UNKNOWN != k)
1811#if FreeRDP_VERSION_MAJOR >= 3
1812 freerdp_input_send_keyboard_event_ex(
1813 m_pContext->Context.context.input,
true,
true, k);
1815 freerdp_input_send_keyboard_event_ex(
1816 m_pContext->Context.input,
true, k);
1820void CConnectFreeRDP::keyReleaseEvent(QKeyEvent *event)
1822 qDebug(logKey) << Q_FUNC_INFO << event;
1823 if(!m_pContext)
return;
1824 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1826 if(RDP_SCANCODE_UNKNOWN != k)
1827#if FreeRDP_VERSION_MAJOR >= 3
1828 freerdp_input_send_keyboard_event_ex(
1829 m_pContext->Context.context.input,
false,
false, k);
1831 freerdp_input_send_keyboard_event_ex(
1832 m_pContext->Context.input,
false, k);
1836int CConnectFreeRDP::RedirectionSound()
1838 rdpContext* pRdpContext = (rdpContext*)m_pContext;
1839 freerdp* instance = freerdp_client_get_instance(pRdpContext);
1840 rdpSettings* settings = instance->context->settings;
1843 if(m_pParameter->GetRedirectionSound()
1844 == CParameterFreeRDP::RedirecionSoundType::Disable)
1847 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE);
1848 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE);
1850 }
else if(m_pParameter->GetRedirectionSound()
1851 == CParameterFreeRDP::RedirecionSoundType::Local)
1853 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, TRUE);
1854 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
1855 }
else if(m_pParameter->GetRedirectionSound()
1856 == CParameterFreeRDP::RedirecionSoundType::Remote)
1858 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, TRUE);
1873 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"rdpsnd",
1874 m_pParameter->GetRedirectionSoundParameters().toStdString().c_str(),
1876 BOOL status = freerdp_client_add_static_channel(settings, count,
1877 #
if FreeRDP_VERSION_MAJOR < 3
1885 status = freerdp_client_add_dynamic_channel(settings, count,
1886 #
if FreeRDP_VERSION_MAJOR < 3
1896 qCritical(log) <<
"Load rdpsnd fail";
1903int CConnectFreeRDP::RedirectionMicrophone()
1905 if(m_pParameter->GetRedirectionSound()
1906 == CParameterFreeRDP::RedirecionSoundType::Remote)
1908 if(!m_pParameter->GetRedirectionMicrophone())
1911 rdpContext* pRdpContext = (rdpContext*)m_pContext;
1912 freerdp* instance = freerdp_client_get_instance(pRdpContext);
1914 rdpSettings* settings = instance->context->settings;
1917 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
1928 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"audin",
1929 m_pParameter->GetRedirectionMicrophoneParameters().toStdString().c_str(),
1931 BOOL status = freerdp_client_add_dynamic_channel(settings, count,
1932 #
if FreeRDP_VERSION_MAJOR < 3
1941 qCritical(log) <<
"Load audin fail";
1948int CConnectFreeRDP::RedirectionDriver()
1950 QStringList lstDrives = m_pParameter->GetRedirectionDrives();
1951 if(lstDrives.isEmpty())
1954 rdpContext* pRdpContext = (rdpContext*)m_pContext;
1955 freerdp* instance = freerdp_client_get_instance(pRdpContext);
1956 rdpSettings* settings = instance->context->settings;
1959 foreach (
auto drive, lstDrives) {
1961 char* pDrive = _strdup(drive.toStdString().c_str());
1962 const char* argvDrive[] = {
"drive", pDrive};
1963 int count =
sizeof(argvDrive) /
sizeof(
const char*);
1964 BOOL status = freerdp_client_add_device_channel(settings, count,
1965 #
if FreeRDP_VERSION_MAJOR < 3
1969 if(pDrive) free(pDrive);
1972 qCritical(log) <<
"Load drive fail";
1980int CConnectFreeRDP::RedirectionPrinter()
1982 if(!m_pParameter->GetRedirectionPrinter())
1985 rdpContext* pRdpContext = (rdpContext*)m_pContext;
1986 freerdp* instance = freerdp_client_get_instance(pRdpContext);
1987 rdpSettings* settings = instance->context->settings;
1990 QStringList printerList = QPrinterInfo::availablePrinterNames();
1991 if(printerList.isEmpty())
1993 qCritical(log) <<
"The printer is empty";
1996 qDebug(log) << printerList;
1999 const char* argvPrinter[] = {
"printer",
nullptr,
nullptr};
2000 int count =
sizeof(argvPrinter) /
sizeof(
const char*);
2001 BOOL status = freerdp_client_add_device_channel(settings, count,
2002 #
if FreeRDP_VERSION_MAJOR < 3
2007 qCritical(log) <<
"Load printer fail";
2014int CConnectFreeRDP::RedirectionSerial()
2018 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2019 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2020 rdpSettings* settings = instance->context->settings;
2023 QList<QSerialPortInfo> lstSerial = QSerialPortInfo::availablePorts();
2026 foreach (
auto serial, lstSerial) {
2029 qDebug(log) <<
"systemLocation:" << serial.systemLocation()
2030 <<
"portName:" << serial.portName()
2031 <<
"serialNumber:" << serial.serialNumber();
2032 char* pSerial = _strdup(serial.systemLocation().toStdString().c_str());
2033 char* pName = _strdup(serial.portName().toStdString().c_str());
2034 const char* argvSerial[] = {
"serial", pName, pSerial};
2035 int count =
sizeof(argvSerial) /
sizeof(
const char*);
2036 BOOL status = freerdp_client_add_device_channel(settings, count,
2037 #
if FreeRDP_VERSION_MAJOR < 3
2041 if(pSerial) free(pSerial);
2042 if(pName) free(pName);
2046 qCritical(log) <<
"Load drive fail";
2054void CConnectFreeRDP::slotConnectProxyServer(QString szHost, quint16 nPort)
2056 qDebug(log) <<
"CConnectFreeRDP::slotConnectProxyServer" << nPort;
2057 rdpContext* pContext = (rdpContext*)m_pContext;
2058 rdpSettings* settings = pContext->settings;
2060 qCritical(log) <<
"settings is null";
2063 freerdp_settings_set_string(
2064 settings, FreeRDP_ServerHostname,
2065 szHost.toStdString().c_str());
2066 freerdp_settings_set_uint32(
2067 settings, FreeRDP_ServerPort,
2070 int nRet = freerdp_client_start(pContext);
2073 qCritical(log) <<
"freerdp_client_start fail";
2075 qDebug(log) <<
"CConnectFreeRDP::slotConnectProxyServer end";
Remote desktop connect interface.
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
virtual OnInitReturnValue OnInit() override
Specific plug-in realizes connection initialization.
virtual int OnClean() override
Clean.
static int cb_verify_x509_certificate(freerdp *instance, const BYTE *data, size_t length, const char *hostname, UINT16 port, DWORD flags)
Callback used if user interaction is required to accept a certificate.
static DWORD cb_verify_changed_certificate_ex(freerdp *instance, const char *host, UINT16 port, const char *common_name, const char *subject, const char *issuer, const char *fingerprint, const char *old_subject, const char *old_issuer, const char *old_fingerprint, DWORD flags)
Callback set in the rdp_freerdp structure, and used to make a certificate validation when a stored ce...
virtual int WakeUp() override
Wake up Connect thread(background thread)
static DWORD cb_verify_certificate_ex(freerdp *instance, const char *host, UINT16 port, const char *common_name, const char *subject, const char *issuer, const char *fingerprint, DWORD flags)
Callback set in the rdp_freerdp structure, and used to make a certificate validation when the connect...
virtual int OnProcess() override
Specific operation processing of plug-in connection.
static BOOL cb_post_connect(freerdp *instance)
Callback given to freerdp_connect() to perform post-connection operations.
static BOOL cb_pre_connect(freerdp *instance)
Callback given to freerdp_connect() to process the pre-connect operations.
void sigError(const int nError, const QString &szError=QString())
Triggered when an error is generated.
void sigInformation(const QString &szInfo)
Triggering from a background thread displays information in the main thread without blocking the back...
void sigBlockShowMessageBox(const QString &szTitle, const QString &szMessage, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton &nRet, bool &checkBox, QString checkBoxContext=QString())
Block background threads and display message dialogs in foreground threads (QMessageBox)
void sigShowMessageBox(const QString &szTitle, const QString &szMessage, const QMessageBox::Icon &icon=QMessageBox::Information)
Trigger the display of a message dialog (QMessageBox) in the main thread from a background thread wit...
void sigBlockInputDialog(const QString &szTitle, const QString &szLable, const QString &szMessage, QString &szText)
Block background threads and display input dialogs in foreground threads (QInputDialog)
void sigConnected()
Emitted when the plugin is successfully connected.
void sigDisconnect()
Notify the user to call disconnect.
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
Blocks the background thread and displays the window in the foreground thread.
static UINT32 QtToScanCode(int key, Qt::KeyboardModifiers modifiers)
CConvertKeyCode::QtToScanCode.
CParameterUser m_User
[Instance user]
void sigChanged()
emit when the parameter changes Usually if required, the corresponding parameter corresponds to a cha...
Data is forwarded over a local socket and SSH tunnel.