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";
void sigUpdateRect(const QRect &r, const QImage &image)
通知视图,图像更新
virtual OnInitReturnValue OnInit() override
具体的插件实现连接初始化
virtual int OnClean() override
清理
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
唤醒连接线程(后台线程)
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
插件连接的具体操作处理。因为此插件是非Qt事件,所以在此函数中等待。
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())
当有错误产生时触发
void sigInformation(const QString &szInfo)
从后台线程中触发在主线程中显示信息,不阻塞后台线程
void sigBlockShowMessageBox(const QString &szTitle, const QString &szMessage, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton &nRet, bool &checkBox, QString checkBoxContext=QString())
阻塞后台线程,并在前台线程中显示消息对话框(QMessageBox)
void sigShowMessageBox(const QString &szTitle, const QString &szMessage, const QMessageBox::Icon &icon=QMessageBox::Information)
从后台线程中触发在主线程中显示消息对话框(QMessageBox),不阻塞后台线程
void sigBlockInputDialog(const QString &szTitle, const QString &szLable, const QString &szMessage, QString &szText)
阻塞后台线程,并在前台线程中显示输入对话框 (QInputDialog)
void sigConnected()
当插件连接成功后触发。仅由插件触发
void sigDisconnect()
通知用户断开连接。仅由插件触发。 当从插件中需要要断开连接时触发。例如:对端断开连接、重置连接或者连接出错。
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
阻塞后台线程,并在前台线程中显示窗口。
static UINT32 QtToScanCode(int key, Qt::KeyboardModifiers modifiers)
CConvertKeyCode::QtToScanCode
CParameterUser m_User
[Instance user]
void sigChanged()
当参数改变时,触发 通常如果需要,则相应的参数会对应一个改变事件。
实现通过本地 SOCKET 与 SSH 隧道转发数据。适用于库没有实现传输层接口,只有 socket 的情况。