6#undef PEN_FLAG_INVERTED
7#include "freerdp/client.h"
8#include "freerdp/client/channels.h"
9#include "freerdp/channels/rdpei.h"
10#include "freerdp/channels/rdpdr.h"
11#include "freerdp/channels/disp.h"
12#include "freerdp/channels/tsmf.h"
13#include "freerdp/channels/rdpsnd.h"
14#include "freerdp/client/encomsp.h"
15#include "freerdp/gdi/gfx.h"
16#include "freerdp/settings.h"
17#include "freerdp/locale/keyboard.h"
18#include "freerdp/channels/rdpgfx.h"
19#include "freerdp/channels/cliprdr.h"
20#include "freerdp/client/cmdline.h"
21#include "freerdp/gdi/video.h"
22#include "winpr/winsock.h"
24#include "BackendFreeRDP.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 <QSerialPort>
39 #include <QSerialPortInfo>
41#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
42 #include <QSoundEffect>
47#ifdef WINPR_HAVE_POLL_H
54#include <sys/select.h>
58#if FREERDP_VERSION_MAJOR >= 3
59#include "ConnectLayerQTcpSocket.h"
61#include "ConnectLayerSSHTunnel.h"
66static Q_LOGGING_CATEGORY(log,
"FreeRDP.Backend")
67static Q_LOGGING_CATEGORY(logKey,
"FreeRDP.Backend.Key")
68static Q_LOGGING_CATEGORY(logInputMethod,
"FreeRDP.Backend.InputMethod")
69static Q_LOGGING_CATEGORY(logMouse,
"FreeRDP.Backend.Mouse")
73 , m_pOperate(pOperate)
75 , m_pParameter(
nullptr)
78 , m_writeEvent(
nullptr)
79#if FREERDP_VERSION_MAJOR >= 3
80 , m_pConnectLayer(
nullptr)
83 , m_pThreadSSH(
nullptr)
86 qDebug(log) << Q_FUNC_INFO;
87 m_pParameter = qobject_cast<CParameterFreeRDP*>(pOperate->GetParameter());
88 Q_ASSERT(m_pParameter);
91CBackendFreeRDP::~CBackendFreeRDP()
93 qDebug(log) << Q_FUNC_INFO;
104 qDebug(log) << Q_FUNC_INFO;
107 m_writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
109 qCritical(log) <<
"CreateEvent failed";
110 return OnStartReturnValue::Fail;
112 ZeroMemory(&m_ClientEntryPoints,
sizeof(RDP_CLIENT_ENTRY_POINTS));
113 m_ClientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
114 m_ClientEntryPoints.Size =
sizeof(RDP_CLIENT_ENTRY_POINTS);
116 m_ClientEntryPoints.GlobalInit = cbGlobalInit;
117 m_ClientEntryPoints.GlobalUninit = cbGlobalUninit;
118 m_ClientEntryPoints.ClientNew = cbClientNew;
119 m_ClientEntryPoints.ClientFree = cbClientFree;
120 m_ClientEntryPoints.ClientStart = cbClientStart;
121 m_ClientEntryPoints.ClientStop = cbClientStop;
124 auto pRdpContext = freerdp_client_context_new(&m_ClientEntryPoints);
128 m_pContext->pThis =
this;
130 qCritical(log) <<
"freerdp_client_context_new fail";
131 return OnStartReturnValue::Fail;
134 rdpSettings* settings = pRdpContext->settings;
136 qCritical(log) <<
"settings is null";
137 return OnStartReturnValue::Fail;
150 char* argv[]= {(
char*)QApplication::applicationFilePath().toStdString().c_str()};
151 int argc =
sizeof(argv) /
sizeof(
char*);
152 nRet = freerdp_client_settings_parse_command_line(settings, argc, argv, TRUE);
155 freerdp_client_settings_command_line_status_print(settings, nRet, argc, argv);
156 return OnStartReturnValue::Fail;
159#if FREERDP_VERSION_MAJOR >= 3
160 if (!stream_dump_register_handlers(pRdpContext,
161 CONNECTION_STATE_MCS_CREATE_REQUEST,
163 return OnStartReturnValue::Fail;
166 auto &user = m_pParameter->m_Net.m_User;
167 if(!user.GetUser().isEmpty())
168 freerdp_settings_set_string(
169 settings, FreeRDP_Username,
170 user.GetUser().toStdString().c_str());
171 if(!user.GetPassword().isEmpty()) {
172 freerdp_settings_set_string(
173 settings, FreeRDP_Password,
174 user.GetPassword().toStdString().c_str());
175 m_SecurityLevel |= CSecurityLevel::Level::Authentication;
178 freerdp_settings_set_bool(
179 settings, FreeRDP_RedirectClipboard, m_pParameter->GetClipboard());
181#if FREERDP_VERSION_MAJOR >= 3
182 bool bOnlyView = m_pParameter->GetOnlyView();
183 freerdp_settings_set_bool(
184 settings, FreeRDP_SuspendInput, bOnlyView);
187 freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
188 m_pParameter->GetDesktopWidth());
189 freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
190 m_pParameter->GetDesktopHeight());
191 freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth,
192 m_pParameter->GetColorDepth());
194 freerdp_settings_set_bool(settings, FreeRDP_UseMultimon,
195 m_pParameter->GetUseMultimon());
197 if(m_pParameter->GetReconnectInterval()) {
198 freerdp_settings_set_bool(
199 settings, FreeRDP_AutoReconnectionEnabled,
true);
200 freerdp_settings_set_uint32(
202 FreeRDP_AutoReconnectMaxRetries,
203 m_pParameter->GetReconnectInterval());
206 freerdp_settings_set_bool(
207 settings, FreeRDP_AutoReconnectionEnabled,
false);
211 RedirectionMicrophone();
213 RedirectionPrinter();
218 switch(m_pParameter->m_Proxy.GetUsedType())
220 case CParameterProxy::TYPE::System:
222 case CParameterProxy::TYPE::Http:
223 case CParameterProxy::TYPE::SockesV5:
226 if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_SOCKS))
227 return OnStartReturnValue::Fail;
228 if(CParameterProxy::TYPE::Http == m_pParameter->m_Proxy.GetUsedType()) {
229 net = &m_pParameter->m_Proxy.m_Http;
230 if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP))
231 return OnStartReturnValue::Fail;
234 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyHostname,
235 net->GetHost().toStdString().c_str()))
236 return OnStartReturnValue::Fail;
237 if (!freerdp_settings_set_uint16(settings, FreeRDP_ProxyPort, net->GetPort()))
238 return OnStartReturnValue::Fail;
240 if(((user.GetUsedType() == CParameterUser::TYPE::UserPassword)
241 && (user.GetPassword().isEmpty() || user.GetUser().isEmpty()))
242 || ((user.GetUsedType() == CParameterUser::TYPE::PublicKey)
243 && user.GetPassphrase().isEmpty())) {
244 int nRet = QDialog::Rejected;
246 if(QDialog::Accepted != nRet)
248 return OnStartReturnValue::Fail;
251 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyUsername,
252 user.GetUser().toStdString().c_str()))
253 return OnStartReturnValue::Fail;
254 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyPassword,
255 user.GetPassword().toStdString().c_str()))
256 return OnStartReturnValue::Fail;
267 case CParameterProxy::TYPE::None:
269 if(!m_pParameter->GetDomain().isEmpty())
270 freerdp_settings_set_string(
271 settings, FreeRDP_Domain,
272 m_pParameter->GetDomain().toStdString().c_str());
273 if(m_pParameter->m_Net.GetHost().isEmpty())
276 szErr = tr(
"The server is empty, please input it");
277 qCritical(log) << szErr;
279 emit
sigError(-1, szErr.toStdString().c_str());
280 return OnStartReturnValue::Fail;
282 auto &net = m_pParameter->m_Net;
283 freerdp_settings_set_string(
284 settings, FreeRDP_ServerHostname,
285 net.GetHost().toStdString().c_str());
286 freerdp_settings_set_uint32(
287 settings, FreeRDP_ServerPort,
290 nRet = freerdp_client_start(pRdpContext);
293 qCritical(log) <<
"freerdp_client_start fail";
294 return OnStartReturnValue::Fail;
299 case CParameterProxy::TYPE::SSHTunnel:
301#if FREERDP_VERSION_MAJOR >= 3
303 if(!m_pConnectLayer)
return OnStartReturnValue::Fail;
304 nRet = m_pConnectLayer->Initialize(pRdpContext);
305 if(nRet)
return OnStartReturnValue::Fail;
308 return InitSSHTunnelPipe();
313 qCritical(log) <<
"Don't support proxy type:" << m_pParameter->m_Proxy.GetUsedType();
317 return OnStartReturnValue::UseOnProcess;
322 qDebug(log) << Q_FUNC_INFO;
326 CloseHandle(m_writeEvent);
327 m_writeEvent =
nullptr;
331 rdpContext* pRdpContext = (rdpContext*)m_pContext;
332 if(!freerdp_disconnect(pRdpContext->instance))
333 qCritical(log) <<
"freerdp_disconnect fail";
335 if(freerdp_client_stop(pRdpContext))
336 qCritical(log) <<
"freerdp_client_stop fail";
338 freerdp_client_context_free(pRdpContext);
339 m_pContext =
nullptr;
342#if FREERDP_VERSION_MAJOR >= 3
343 if(m_pConnectLayer) {
344 m_pConnectLayer->Clean();
345 m_pConnectLayer->deleteLater();
346 m_pConnectLayer =
nullptr;
351 CleanSSHTunnelPipe();
394 rdpContext* pRdpContext = (rdpContext*)m_pContext;
396 if(
nullptr == freerdp_settings_get_string(pRdpContext->settings, FreeRDP_ServerHostname))
404 nCount += freerdp_get_event_handles(pRdpContext, &handles[nCount],
405 ARRAYSIZE(handles) - nCount);
408 qCritical(log) <<
"freerdp_get_event_handles failed";
414 handles[nCount++] = m_writeEvent;
416 DWORD waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, nTimeout);
419 ResetEvent(m_writeEvent);
421 if (waitStatus == WAIT_FAILED)
423 qCritical(log) <<
"WaitForMultipleObjects: WAIT_FAILED";
428 if(waitStatus == WAIT_TIMEOUT)
435 if (!freerdp_check_event_handles(pRdpContext))
439 UINT32 err = freerdp_get_last_error(pRdpContext);
441 szErr =
"freerdp_check_event_handles fail.";
443 szErr += QString::number(err);
445 szErr += freerdp_get_last_error_category(err);
447 szErr += freerdp_get_last_error_name(err);
449 szErr += freerdp_get_last_error_string(err);
450 qCritical(log) << szErr;
474#if FREERDP_VERSION_MAJOR >= 3
475 if(freerdp_shall_disconnect_context(pRdpContext))
477 if(freerdp_shall_disconnect(pRdpContext->instance))
480 qCritical(log) <<
"freerdp_shall_disconnect false";
490 qDebug(log) << Q_FUNC_INFO;
491 if(m_pParameter && m_pParameter->GetOnlyView())
return;
492 if(m_pParameter->GetClipboard())
493 m_ClipBoard.slotClipBoardChanged();
496BOOL CBackendFreeRDP::cbGlobalInit()
498 qDebug(log) << Q_FUNC_INFO;
502void CBackendFreeRDP::cbGlobalUninit()
504 qDebug(log) << Q_FUNC_INFO;
507BOOL CBackendFreeRDP::cbClientNew(freerdp *instance, rdpContext *context)
509 qDebug(log) << Q_FUNC_INFO;
512 instance->PostDisconnect = cb_post_disconnect;
515#if FREERDP_VERSION_MAJOR < 3
516 instance->Authenticate = cb_authenticate;
517 instance->GatewayAuthenticate = cb_GatewayAuthenticate;
519 instance->AuthenticateEx = cb_authenticate_ex;
520 instance->ChooseSmartcard = cb_choose_smartcard;
525 instance->PresentGatewayMessage = cb_present_gateway_message;
527 instance->LogonErrorInfo = cb_logon_error_info;
532void CBackendFreeRDP::cbClientFree(freerdp *instance, rdpContext *context)
534 qDebug(log) << Q_FUNC_INFO;
537int CBackendFreeRDP::cbClientStart(rdpContext *context)
539 qDebug(log) << Q_FUNC_INFO;
542 if (!context || !context->settings)
544 freerdp* instance = freerdp_client_get_instance(context);
548 auto settings = context->settings;
550 QString szDomainHost;
552 szDomainHost = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
553 nPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
555 auto &net = pThis->m_pParameter->m_Net;
556 szServer = net.GetHost() +
":" + QString::number(net.GetPort());
557 auto &proxy = pThis->m_pParameter->m_Proxy;
558 switch(proxy.GetUsedType()) {
559 case CParameterProxy::TYPE::SockesV5:
561 auto &sockesV5 = proxy.m_SockesV5;
562 szServer = sockesV5.GetHost() +
":" + QString::number(sockesV5.GetPort())
566 case CParameterProxy::TYPE::Http:
568 auto &http = proxy.m_Http;
569 szServer = http.GetHost() +
":" + QString::number(http.GetPort())
573 case CParameterProxy::TYPE::SSHTunnel:
575 auto &sshNet = proxy.m_SSH.m_Net;
576#if FREERDP_VERSION_MAJOR < 3
577 szServer = szDomainHost +
":" + QString::number(nPort)
578 +
" -> " + sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
581 szServer = sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
590 BOOL status = freerdp_connect(instance);
592 QString szInfo = tr(
"Connected to ") + szServer;
593 qInfo(log) << szInfo;
598 UINT32 nRet = freerdp_get_last_error(context);
601 szErr = tr(
"Connect to ") + szServer + tr(
" fail.");
603 szErr += QString::number(nRet) +
" - ";
604 szErr += freerdp_get_last_error_name(nRet);
609 szErr += freerdp_get_last_error_string(nRet);
613 case FREERDP_ERROR_CONNECT_LOGON_FAILURE:
615 szErr = tr(
"Logon to ") + szServer;
616 szErr += tr(
" fail. Please check that the username and password are correct.") +
"\n";
619 case FREERDP_ERROR_CONNECT_WRONG_PASSWORD:
621 szErr = tr(
"Logon to ") + szServer;
622 szErr += tr(
" fail. Please check password are correct.") +
"\n";
625 case FREERDP_ERROR_AUTHENTICATION_FAILED:
627 szErr = tr(
"Logon to ") + szServer;
628 szErr += tr(
" authentication fail. please add a CA certificate to the store.") +
"\n";
631 case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED:
633 szErr = tr(
"Logon to ") + szServer;
634 szErr += tr(
" connect transport layer fail.") +
"\n\n";
635 szErr += tr(
"Please:") +
"\n";
636 szErr += tr(
"1. Check for any network related issues") +
"\n";
637 szErr += tr(
"2. Check you have proper security settings ('NLA' enabled is required for most connections nowadays)") +
"\n";
638 szErr +=
" " + tr(
"If you do not know the server security settings, contact your server administrator.") +
"\n";
639 szErr += tr(
"3. Check the certificate is proper (and guacd properly checks that)") +
"\n";
642 case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED:
644 szErr += tr(
"Please check you have proper security settings.") +
"\n";
645 szErr += tr(
"If you do not know the server security settings, contact your server administrator.");
647 case FREERDP_ERROR_CONNECT_CANCELLED:
648 szErr = tr(
"The connect was canceled.") +
"\n\n" + szErr;
655 qCritical(log) << szErr;
656 emit pThis->
sigError(nRet, szErr.toStdString().c_str());
662int CBackendFreeRDP::cbClientStop(rdpContext *context)
665 qDebug(log) << Q_FUNC_INFO;
666#if FREERDP_VERSION_MAJOR >= 3
667 nRet = freerdp_client_common_stop(context);
669 BOOL bRet = freerdp_abort_connect(context->instance);
671 { qCritical(log) <<
"freerdp_abort_connect fail";
698 qDebug(log) << Q_FUNC_INFO;
699 rdpChannels* channels =
nullptr;
700 rdpSettings* settings =
nullptr;
701 rdpContext* context = instance->context;
703 if (!instance || !instance->context || !instance->context->settings)
707 if(!pThis)
return FALSE;
708 settings = instance->context->settings;
709 channels = context->channels;
711 if(!channels || !pParameter)
715#if defined (Q_OS_WIN)
716 if (!freerdp_settings_set_uint32(
717 settings, FreeRDP_OsMajorType, OSMAJORTYPE_WINDOWS))
719 if (!freerdp_settings_set_uint32(
720 settings, FreeRDP_OsMinorType, OSMINORTYPE_WINDOWS_NT))
722#elif defined(Q_OS_ANDROID)
723 if (!freerdp_settings_set_uint32(
724 settings, FreeRDP_OsMajorType, OSMAJORTYPE_ANDROID))
726 if (!freerdp_settings_set_uint32(
727 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
729#elif defined(Q_OS_IOS)
730 if (!freerdp_settings_set_uint32(
731 settings, FreeRDP_OsMajorType, OSMAJORTYPE_IOS))
733 if (!freerdp_settings_set_uint32(
734 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
736#elif defined (Q_OS_UNIX)
737 if (!freerdp_settings_set_uint32(
738 settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX))
740 if (!freerdp_settings_set_uint32(
741 settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_XSERVER))
744 if (!freerdp_settings_set_uint32(
745 settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNSPECIFIED))
747 if (!freerdp_settings_set_uint32(
748 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
753 PubSub_SubscribeChannelConnected(instance->context->pubSub,
754 OnChannelConnectedEventHandler);
755 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
756 OnChannelDisconnectedEventHandler);
758#if FREERDP_VERSION_MAJOR < 3
759 if (!freerdp_client_load_addins(channels, instance->context->settings))
762 #if defined(Q_OS_LINUX) || (defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE))
763 if (!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, TRUE))
768 if(!freerdp_settings_set_bool(
769 settings, FreeRDP_NegotiateSecurityLayer,
770 pParameter->GetNegotiateSecurityLayer()))
772 CParameterFreeRDP::Security security = pParameter->GetSecurity();
774 if(!freerdp_settings_set_bool(
775 settings, FreeRDP_RdpSecurity,
776 CParameterFreeRDP::Security::RDP & security))
778 if (!freerdp_settings_set_bool(
779 settings, FreeRDP_UseRdpSecurityLayer,
780 CParameterFreeRDP::Security::RDP & security))
783 if(!freerdp_settings_set_bool(
784 settings, FreeRDP_TlsSecurity,
785 CParameterFreeRDP::Security::TLS & security))
787 if(!freerdp_settings_set_bool(
788 settings, FreeRDP_NlaSecurity,
789 CParameterFreeRDP::Security::NLA & security))
791 if(!freerdp_settings_set_bool(
792 settings, FreeRDP_ExtSecurity,
793 CParameterFreeRDP::Security::NLA_Ext & security))
795#if FREERDP_VERSION_MAJOR >= 3
796 if(!freerdp_settings_set_bool(
797 settings, FreeRDP_AadSecurity,
798 CParameterFreeRDP::Security::RDSAAD & security))
800 if(!freerdp_settings_set_bool(
801 settings, FreeRDP_RdstlsSecurity,
802 CParameterFreeRDP::Security::RDSTLS & security))
804 freerdp_settings_set_uint16(settings, FreeRDP_TLSMinVersion,
805 pParameter->GetTlsVersion());
809 if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly))
812 auto &user = pParameter->m_Net.
m_User;
813 if(!freerdp_settings_get_string(settings, FreeRDP_Username)) {
814 if(user.GetUser().isEmpty()) {
816 qWarning(log) <<
"Auth-only, but no user name set. Will be call instance->Authenticate.";
818 freerdp_settings_set_string(
819 settings, FreeRDP_Username,
820 user.GetUser().toStdString().c_str());
822 if (!freerdp_settings_get_string(settings, FreeRDP_Password)) {
823 if (user.GetPassword().isEmpty()) {
825 qWarning(log) <<
"auth-only, but no password set. Will be call instance->Authenticate";
827 freerdp_settings_set_string(
828 settings, FreeRDP_Password,
829 user.GetPassword().toStdString().c_str());
836 }
else if(freerdp_settings_get_bool(settings, FreeRDP_CredentialsFromStdin)){
838 }
else if(freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon)) {
849 UINT32 width = pParameter->GetDesktopWidth();
850 UINT32 height = pParameter->GetDesktopHeight();
851 if ((width < 64) || (height < 64) ||
852 (width > 4096) || (height > 4096))
854 QString szErr = tr(
"Invalid dimensions:")
855 + QString::number(width)
856 +
"*" + QString::number(height);
857 qCritical(log) << szErr;
861 qInfo(log) <<
"Init desktop size " << width <<
"*" << height;
865 <<
"width:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)
866 <<
"height:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)
867 <<
"ColorDepth:" << freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
878 if(!freerdp_set_connection_type(settings, pParameter->GetConnectType()))
880 freerdp_settings_set_uint32(
881 settings, FreeRDP_PerformanceFlags, pParameter->GetPerformanceFlags());
882 freerdp_performance_flags_split(settings);
884 freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, pParameter->GetEnableLocalInputMethod());
888const char* CBackendFreeRDP::GetTitle(freerdp* instance)
890 const char* windowTitle;
893 const char* name =
nullptr;
896 rdpSettings* settings = instance->context->settings;
901 windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
905#if FREERDP_VERSION_MAJOR >= 3
906 name = freerdp_settings_get_server_name(settings);
908 name = pThis->m_pParameter->m_Net.GetHost().toStdString().c_str();
910 port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
912 addPort = (port != 3389);
914 char buffer[MAX_PATH + 64] = { 0 };
917 sprintf_s(buffer,
sizeof(buffer),
"%s", name);
919 sprintf_s(buffer,
sizeof(buffer),
"%s:%" PRIu32, name, port);
921 freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer);
922 return freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
932 qDebug(log) << Q_FUNC_INFO;
934 rdpContext* context = instance->context;
935 rdpSettings* settings = instance->context->settings;
936 rdpUpdate* update = instance->context->update;
937 CBackendFreeRDP* pThis = ((
ClientContext*)instance->context)->pThis;
939 const char* pWindowTitle = GetTitle(instance);
942 WCHAR* windowTitle = NULL;
943#if FREERDP_VERSION_MAJOR >= 3
944 windowTitle = ConvertUtf8ToWCharAlloc(pWindowTitle, NULL);
946 ConvertToUnicode(CP_UTF8, 0, pWindowTitle, -1, &windowTitle, 0);
950 QString title = QString::fromUtf16((
const char16_t*)windowTitle);
952 if(pThis->m_pParameter->GetServerName().isEmpty())
953 emit pThis->sigServerName(title);
957 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
958 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
959 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
961 if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
964 if(!pThis->CreateImage(instance->context))
967 Q_ASSERT(instance->context->cache);
970 if(pThis->m_Cursor.RegisterPointer(context->graphics))
973 update->BeginPaint = cb_begin_paint;
974 update->EndPaint = cb_end_paint;
975 update->DesktopResize = cb_desktop_resize;
977 update->PlaySound = cb_play_bell_sound;
979 update->SetKeyboardIndicators = cb_keyboard_set_indicators;
980 update->SetKeyboardImeStatus = cb_keyboard_set_ime_status;
986void CBackendFreeRDP::cb_post_disconnect(freerdp* instance)
988 qDebug(log) << Q_FUNC_INFO;
989 rdpContext* context =
nullptr;
991 if (!instance || !instance->context)
994 context = instance->context;
996 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
997 OnChannelConnectedEventHandler);
998 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
999 OnChannelDisconnectedEventHandler);
1003int CBackendFreeRDP::cb_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
1005 CBackendFreeRDP* pThis = ((
ClientContext*)instance->context)->pThis;
1006 const char* str_data = freerdp_get_logon_error_info_data(data);
1007 const char* str_type = freerdp_get_logon_error_info_type(type);
1008 QString szErr = tr(
"FreeRDP logon info: [");
1012 qDebug(log) << szErr;
1018void CBackendFreeRDP::OnChannelConnectedEventHandler(
void *context,
1019 #
if FREERDP_VERSION_MAJOR >= 3
1022 ChannelConnectedEventArgs *e)
1024 rdpContext* pContext = (rdpContext*)context;
1026 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
1027 qDebug(log) <<
"channel" << e->name <<
"connected";
1028 pThis->m_ClipBoard.Init((CliprdrClientContext*)e->pInterface,
1029 pThis->m_pParameter->GetClipboard());
1031#if FREERDP_VERSION_MAJOR >= 3
1033 freerdp_client_OnChannelConnectedEventHandler(pContext, e);
1035 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
1037 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
1038 rdpGdi* gdi = pContext->gdi;
1040 gdi_graphics_pipeline_init(gdi, (RdpgfxClientContext*) e->pInterface);
1043 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
1045 else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
1047 gdi_video_geometry_init(pContext->gdi, (GeometryClientContext*)e->pInterface);
1049 else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
1051 gdi_video_data_init(pContext->gdi, (VideoClientContext*)e->pInterface);
1053 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"connected but we can’t use it";
1057void CBackendFreeRDP::OnChannelDisconnectedEventHandler(
void *context,
1058 #
if FREERDP_VERSION_MAJOR >= 3
1061 ChannelDisconnectedEventArgs *e)
1063 rdpContext* pContext = (rdpContext*)context;
1066 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
1067 qDebug(log) <<
"channel" << e->name <<
"disconnected";
1068 pThis->m_ClipBoard.UnInit((CliprdrClientContext*)e->pInterface,
1069 pThis->m_pParameter->GetClipboard());
1071#if FREERDP_VERSION_MAJOR >= 3
1073 freerdp_client_OnChannelDisconnectedEventHandler(pContext, e);
1075 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
1077 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
1078 rdpGdi* gdi = pContext->gdi;
1079 gdi_graphics_pipeline_uninit(gdi, (RdpgfxClientContext*) e->pInterface);
1082 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
1085 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"disconnected but we can’t use it";
1090UINT32 CBackendFreeRDP::GetImageFormat(QImage::Format format)
1093#if (QT_VERSION >= QT_VERSION_CHECK(5,2,0))
1094 case QImage::Format_RGBA8888:
1095 return PIXEL_FORMAT_RGBA32;
1096 case QImage::Format_RGBX8888:
1097 return PIXEL_FORMAT_RGBX32;
1099 case QImage::Format_RGB16:
1100 return PIXEL_FORMAT_RGB16;
1101 case QImage::Format_ARGB32:
1102 return PIXEL_FORMAT_BGRA32;
1103 case QImage::Format_RGB32:
1104 return PIXEL_FORMAT_BGRA32;
1111UINT32 CBackendFreeRDP::GetImageFormat()
1113 return GetImageFormat(m_Image.format());
1116BOOL CBackendFreeRDP::CreateImage(rdpContext *context)
1120 CBackendFreeRDP* pThis = pContext->pThis;
1121 rdpGdi* gdi = context->gdi;
1122 Q_ASSERT(pThis && gdi);
1123 pThis->m_Image = QImage(gdi->primary_buffer,
1124 static_cast<int>(gdi->width),
1125 static_cast<int>(gdi->height),
1126 QImage::Format_ARGB32);
1130#if FREERDP_VERSION_MAJOR >= 3
1132static CREDUI_INFOW wfUiInfo = {
sizeof(CREDUI_INFOW), NULL, L
"Enter your credentials",
1133 L
"Remote Desktop Security", NULL };
1136BOOL CBackendFreeRDP::cb_authenticate_ex(freerdp* instance,
1137 char** username,
char** password,
1138 char** domain, rdp_auth_reason reason)
1140 qDebug(log) << Q_FUNC_INFO <<
"reason:" << reason;
1144 if(!username || !password || !domain)
return FALSE;
1146 return cb_authenticate(instance, username, password, domain);
1147 rdpContext* pContext = (rdpContext*)instance->context;
1152 WCHAR UserNameW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1153 WCHAR UserW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1154 WCHAR DomainW[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1155 WCHAR PasswordW[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 };
1157 WINPR_ASSERT(instance);
1158 WINPR_ASSERT(instance->context);
1159 WINPR_ASSERT(instance->context->settings);
1161 WINPR_ASSERT(username);
1162 WINPR_ASSERT(domain);
1163 WINPR_ASSERT(password);
1165 const WCHAR auth[] = L
"Target credentials requested";
1166 const WCHAR authPin[] = L
"PIN requested";
1167 const WCHAR gwAuth[] = L
"Gateway credentials requested";
1168 const WCHAR* titleW = auth;
1171 dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
1172 CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1179 if ((*username) && (*password))
1182 case AUTH_SMARTCARD_PIN:
1183 dwFlags &= ~CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1184 dwFlags |= CREDUI_FLAGS_PASSWORD_ONLY_OK | CREDUI_FLAGS_KEEP_USERNAME;
1189 *username = _strdup(
"PIN");
1202 ConvertUtf8ToWChar(*username, UserNameW, ARRAYSIZE(UserNameW));
1203 ConvertUtf8ToWChar(*username, UserW, ARRAYSIZE(UserW));
1207 ConvertUtf8ToWChar(*password, PasswordW, ARRAYSIZE(PasswordW));
1210 ConvertUtf8ToWChar(*domain, DomainW, ARRAYSIZE(DomainW));
1212 if (_wcsnlen(PasswordW, ARRAYSIZE(PasswordW)) == 0)
1214 status = CredUIPromptForCredentialsW(&wfUiInfo, titleW, NULL, 0, UserNameW,
1215 ARRAYSIZE(UserNameW), PasswordW,
1216 ARRAYSIZE(PasswordW), &fSave, dwFlags);
1217 if (status != NO_ERROR)
1220 "CredUIPromptForCredentials unexpected status: 0x%08lX",
1225 if ((dwFlags & CREDUI_FLAGS_KEEP_USERNAME) == 0)
1227 status = CredUIParseUserNameW(UserNameW, UserW, ARRAYSIZE(UserW), DomainW,
1228 ARRAYSIZE(DomainW));
1229 if (status != NO_ERROR)
1231 CHAR User[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1232 CHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1233 CHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1235 ConvertWCharNToUtf8(UserNameW, ARRAYSIZE(UserNameW), UserName, ARRAYSIZE(UserName));
1236 ConvertWCharNToUtf8(UserW, ARRAYSIZE(UserW), User, ARRAYSIZE(User));
1237 ConvertWCharNToUtf8(DomainW, ARRAYSIZE(DomainW), Domain, ARRAYSIZE(Domain));
1239 "Failed to parse UserName: %s into User: %s Domain: %s",
1240 UserName, User, Domain);
1246 *username = ConvertWCharNToUtf8Alloc(UserW, ARRAYSIZE(UserW), NULL);
1249 qCritical(log) <<
"ConvertWCharNToUtf8Alloc failed" << status;
1253 if (_wcsnlen(DomainW, ARRAYSIZE(DomainW)) > 0)
1254 *domain = ConvertWCharNToUtf8Alloc(DomainW, ARRAYSIZE(DomainW), NULL);
1256 *domain = _strdup(
"\0");
1261 qCritical(log) <<
"strdup failed" << status;
1265 *password = ConvertWCharNToUtf8Alloc(PasswordW, ARRAYSIZE(PasswordW), NULL);
1274 return cb_authenticate(instance, username, password, domain);
1279BOOL CBackendFreeRDP::cb_choose_smartcard(freerdp* instance,
1280 SmartcardCertInfo** cert_list,
1282 DWORD* choice, BOOL gateway)
1284 rdpContext* pContext = (rdpContext*)instance->context;
1286 QString msg(
"Multiple smartcards are available for use:\n");
1287 for (DWORD i = 0; i < count; i++)
1289 const SmartcardCertInfo* cert = cert_list[i];
1290 char* reader = ConvertWCharToUtf8Alloc(cert->reader, NULL);
1291 char* container_name = ConvertWCharToUtf8Alloc(cert->containerName, NULL);
1293 msg += QString::number(i) +
" ";
1294 msg += QString(container_name) +
"\n\t";
1295 msg +=
"Reader: " + QString(reader) +
"\n\t";
1296 msg +=
"User: " + QString(cert->userHint) + +
"@" + QString(cert->domainHint) +
"\n\t";
1297 msg +=
"Subject: " + QString(cert->subject) +
"\n\t";
1298 msg +=
"Issuer: " + QString(cert->issuer) +
"\n\t";
1299 msg +=
"UPN: " + QString(cert->upn) +
"\n";
1302 free(container_name);
1305 msg +=
"\nChoose a smartcard to use for ";
1307 msg +=
"gateway authentication";
1311 msg +=
"(0 - " + QString::number(count - 1) +
")";
1319 int n = num.toInt(&ok);
1329#ifdef WITH_WINDOWS_CERT_STORE
1337static void wf_report_error(
char* wszMessage, DWORD dwErrCode)
1339 LPSTR pwszMsgBuf = NULL;
1341 if (NULL != wszMessage && 0 != *wszMessage)
1343 WLog_ERR(TAG,
"%s", wszMessage);
1346 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1351 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1361 if (NULL != pwszMsgBuf)
1363 WLog_ERR(TAG,
"Error: 0x%08x (%d) %s", dwErrCode, dwErrCode, pwszMsgBuf);
1364 LocalFree(pwszMsgBuf);
1368 WLog_ERR(TAG,
"Error: 0x%08x (%d)", dwErrCode, dwErrCode);
1372static DWORD wf_is_x509_certificate_trusted(
const char* common_name,
const char* subject,
1373 const char* issuer,
const char* fingerprint)
1375 HRESULT hr = CRYPT_E_NOT_FOUND;
1377 DWORD dwChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
1378 PCCERT_CONTEXT pCert = NULL;
1379 HCERTCHAINENGINE hChainEngine = NULL;
1380 PCCERT_CHAIN_CONTEXT pChainContext = NULL;
1382 CERT_ENHKEY_USAGE EnhkeyUsage = { 0 };
1383 CERT_USAGE_MATCH CertUsage = { 0 };
1384 CERT_CHAIN_PARA ChainPara = { 0 };
1385 CERT_CHAIN_POLICY_PARA ChainPolicy = { 0 };
1386 CERT_CHAIN_POLICY_STATUS PolicyStatus = { 0 };
1387 CERT_CHAIN_ENGINE_CONFIG EngineConfig = { 0 };
1389 DWORD derPubKeyLen = WINPR_ASSERTING_INT_CAST(uint32_t, strlen(fingerprint));
1390 char* derPubKey = calloc(derPubKeyLen,
sizeof(
char));
1391 if (NULL == derPubKey)
1393 WLog_ERR(TAG,
"Could not allocate derPubKey");
1400 if (!CryptStringToBinaryA(fingerprint, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen,
1403 WLog_ERR(TAG,
"CryptStringToBinary failed. Err: %d", GetLastError());
1410 EnhkeyUsage.cUsageIdentifier = 0;
1411 EnhkeyUsage.rgpszUsageIdentifier = NULL;
1413 CertUsage.dwType = USAGE_MATCH_TYPE_AND;
1414 CertUsage.Usage = EnhkeyUsage;
1416 ChainPara.cbSize =
sizeof(ChainPara);
1417 ChainPara.RequestedUsage = CertUsage;
1419 ChainPolicy.cbSize =
sizeof(ChainPolicy);
1421 PolicyStatus.cbSize =
sizeof(PolicyStatus);
1423 EngineConfig.cbSize =
sizeof(EngineConfig);
1424 EngineConfig.dwUrlRetrievalTimeout = 0;
1426 pCert = CertCreateCertificateContext(X509_ASN_ENCODING, derPubKey, derPubKeyLen);
1429 WLog_ERR(TAG,
"FAILED: Certificate could not be parsed.");
1433 dwChainFlags |= CERT_CHAIN_ENABLE_PEER_TRUST;
1442 if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
1444 hr = HRESULT_FROM_WIN32(GetLastError());
1451 if (!CertGetCertificateChain(hChainEngine,
1462 hr = HRESULT_FROM_WIN32(GetLastError());
1469 if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
1474 hr = HRESULT_FROM_WIN32(GetLastError());
1478 if (PolicyStatus.dwError != S_OK)
1480 wf_report_error(
"CertVerifyCertificateChainPolicy: Chain Status", PolicyStatus.dwError);
1481 hr = PolicyStatus.dwError;
1487 if (PolicyStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
1488 PolicyStatus.dwError == CRYPT_E_REVOCATION_OFFLINE)
1496 WLog_INFO(TAG,
"CertVerifyCertificateChainPolicy succeeded for %s (%s) issued by %s",
1497 common_name, subject, issuer);
1504 WLog_INFO(TAG,
"CertVerifyCertificateChainPolicy failed for %s (%s) issued by %s",
1505 common_name, subject, issuer);
1506 wf_report_error(NULL, hr);
1511 if (NULL != pChainContext)
1513 CertFreeCertificateChain(pChainContext);
1516 if (NULL != hChainEngine)
1518 CertFreeCertificateChainEngine(hChainEngine);
1523 CertFreeCertificateContext(pCert);
1532BOOL CBackendFreeRDP::cb_authenticate(freerdp* instance,
char** username,
1533 char** password,
char** domain)
1535 qDebug(log) << Q_FUNC_INFO;
1538 rdpContext* pContext = (rdpContext*)instance->context;
1540 if(!username || !password || !domain)
return FALSE;
1541 if(*username && *password )
return TRUE;
1542 if(!pThis || !pThis->m_pParameter)
return FALSE;
1544 auto &user = pThis->m_pParameter->m_Net.
m_User;
1545 if(user.GetUser().isEmpty() || user.GetPassword().isEmpty()) {
1546 int nRet = QDialog::Rejected;
1548 nRet, pThis->m_pParameter);
1549 if(QDialog::Accepted != nRet)
1553 QString szPassword = user.GetPassword();
1554 QString szName = user.GetUser();
1555 QString szDomain = pThis->m_pParameter->GetDomain();
1556 if(!szDomain.isEmpty() && domain)
1557 *domain = _strdup(szDomain.toStdString().c_str());
1558 if(!szName.isEmpty() && username)
1559 *username = _strdup(szName.toStdString().c_str());
1560 if(!szPassword.isEmpty() && password) {
1561 *password = _strdup(szPassword.toStdString().c_str());
1562 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
1568BOOL CBackendFreeRDP::cb_GatewayAuthenticate(freerdp *instance,
1569 char **username,
char **password,
char **domain)
1571 qDebug(log) << Q_FUNC_INFO;
1575 rdpContext* pContext = (rdpContext*)instance->context;
1577 if(!username || !password || !domain)
return FALSE;
1578 if(*username && *password )
return TRUE;
1579 if(!pThis || !pThis->m_pParameter)
return FALSE;
1581 auto &user = pThis->m_pParameter->m_Net.
m_User;
1582 if(user.GetUser().isEmpty() || user.GetPassword().isEmpty()) {
1583 int nRet = QDialog::Rejected;
1585 nRet, pThis->m_pParameter);
1586 if(QDialog::Accepted != nRet)
1590 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1591 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1592 QString szDomain = pThis->m_pParameter->GetDomain();
1593 if(!szDomain.isEmpty() && domain)
1594 *domain = _strdup(szDomain.toStdString().c_str());
1595 if(!szName.isEmpty() && username)
1596 *username = _strdup(szName.toStdString().c_str());
1598 *password = _strdup(szPassword.toStdString().c_str());
1599 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
1601 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1607 const BYTE* data,
size_t length,
1608 const char* hostname, UINT16 port, DWORD flags)
1610 qDebug(log) << Q_FUNC_INFO;
1611 rdpContext* pContext = (rdpContext*)instance->context;
1612 QSslCertificate cert(QByteArray((
const char*)data, length));
1613#if FREERDP_VERSION_MAJOR >= 3
1617 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM) {
1619 instance, hostname, port,
1620 cert.issuerDisplayName().toStdString().c_str(),
1621 cert.subjectDisplayName().toStdString().c_str(),
1622 cert.issuerDisplayName().toStdString().c_str(),
1628 instance, hostname, port,
1629 cert.issuerDisplayName().toStdString().c_str(),
1630 cert.subjectDisplayName().toStdString().c_str(),
1631 cert.issuerDisplayName().toStdString().c_str(),
1632 cert.serialNumber().toStdString().c_str(),
1636static QString pem_cert_fingerprint(
const char* pem, DWORD flags)
1638 QString szFingerPrint;
1639#if FREERDP_VERSION_MAJOR >= 3
1643 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM)
1645 rdpCertificate* cert = freerdp_certificate_new_from_pem(pem);
1649 char* fp = freerdp_certificate_get_fingerprint(cert);
1650 char* start = freerdp_certificate_get_validity(cert, TRUE);
1651 char* end = freerdp_certificate_get_validity(cert, FALSE);
1652 freerdp_certificate_free(cert);
1654 szFingerPrint = QObject::tr(
"Valid from: ") + QString(start) +
"\n";
1655 szFingerPrint += QObject::tr(
"Valid to: ") + QString(end) +
"\n";
1656 szFingerPrint += QObject::tr(
"Fingerprint: ") + QString(fp) +
"\n";
1663 szFingerPrint = QObject::tr(
"Fingerprint: ") + QString(pem) +
"\n";
1664 return szFingerPrint;
1683 const char *host, UINT16 port,
1684 const char *common_name,
const char *subject,
1685 const char *issuer,
const char *fingerprint, DWORD flags)
1687 qDebug(log) << Q_FUNC_INFO;
1689 rdpContext* pContext = (rdpContext*)instance->context;
1696 emit pThis->sigServerName(common_name);
1700 pThis->m_SecurityLevel |= CSecurityLevel::Level::SecureChannel;
1701 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1702 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1703 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1704 pThis->m_SecurityLevel |= CSecurityLevel::Level::Redirect;
1706 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1712#if FREERDP_VERSION_MAJOR >= 3
1713#if defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE)
1714 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM && !(flags & VERIFY_CERT_FLAG_MISMATCH))
1716 if (wf_is_x509_certificate_trusted(common_name, subject, issuer, fingerprint) == S_OK)
1724 QString szType = tr(
"RDP-Server");
1725 if (flags & VERIFY_CERT_FLAG_GATEWAY) {
1726 szType = tr(
"RDP-Gateway");
1728 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1729 szType = tr(
"RDP-Redirect");
1731 QString title(tr(
"Verify certificate"));
1734 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1735 message += tr(
"Common name: ") + common_name +
"\n";
1736 message += tr(
"Subject: ") + subject +
"\n";
1737 message += tr(
"Issuer: ") + issuer +
"\n";
1738 message += pem_cert_fingerprint(fingerprint, flags);
1740 if(VERIFY_CERT_FLAG_CHANGED & flags) {
1741 message += tr(
"The above X.509 certificate is changed.\n"
1742 "It is possible that the server has changed its certificate, "
1743 "or Maybe it was attacked."
1744 "Please look at the OpenSSL documentation on "
1745 "how to add a private CA to the store.");
1747 message += tr(
"The above X.509 certificate could not be verified.\n"
1748 "Possibly because you do not have the CA certificate "
1749 "in your certificate store, or the certificate has expired.\n"
1750 "Please look at the OpenSSL documentation on "
1751 "how to add a private CA to the store.");
1755 message += tr(
"Yes - trusted") +
"\n";
1756 message += tr(
"Ignore - temporary trusted") +
"\n";
1757 message += tr(
"No - no trusted") +
"\n";
1759 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1760 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1761 bool bCheckBox =
false;
1763 tr(
"Don't show again"));
1764 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1770 case QMessageBox::StandardButton::Yes:
1772 case QMessageBox::StandardButton::Ignore:
1800 const char *host, UINT16 port,
1801 const char *common_name,
const char *subject,
1802 const char *issuer,
const char *fingerprint,
1803 const char *old_subject,
const char *old_issuer,
1804 const char *old_fingerprint, DWORD flags)
1806 qDebug(log) << Q_FUNC_INFO;
1807 rdpContext* pContext = (rdpContext*)instance->context;
1810 emit pThis->sigServerName(common_name);
1813 pThis->m_SecurityLevel |= CSecurityLevel::Level::SecureChannel;
1814 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1815 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1816 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1817 pThis->m_SecurityLevel |= CSecurityLevel::Level::Redirect;
1819 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1825 QString szType = tr(
"RDP-Server");
1826 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1827 szType = tr(
"RDP-Gateway");
1828 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1829 szType = tr(
"RDP-Redirect");
1831 QString title(tr(
"Verify changed certificate"));
1833 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1834 message += tr(
"New Certificate details:") +
"\n";
1835 message +=
" " + tr(
"name: ") + common_name +
"\n";
1836 message +=
" " + tr(
"subject: ") + subject +
"\n";
1837 message +=
" " + tr(
"issuer: ") + issuer +
"\n";
1838 message +=
" " + pem_cert_fingerprint(fingerprint, flags) +
"\n";
1839 message += tr(
"Old Certificate details:") +
"\n";
1840 message +=
" " + tr(
"subject: ") + old_subject +
"\n";
1841 message +=
" " + tr(
"issuer: ") + old_issuer +
"\n";
1842 message +=
" " + pem_cert_fingerprint(old_fingerprint, flags) +
"\n";
1844 message += tr(
"The above X.509 certificate could not be verified, "
1845 "possibly because you do not have the CA certificate "
1846 "in your certificate store, or the certificate has expired. "
1847 "Please look at the OpenSSL documentation on "
1848 "how to add a private CA to the store.");
1851 message += tr(
"Yes - trusted") +
"\n";
1852 message += tr(
"Ignore - temporary trusted") +
"\n";
1853 message += tr(
"No - no trusted") +
"\n";
1855 bool bCheckBox =
false;
1856 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1857 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1859 tr(
"Don't show again"));
1860 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1867 case QMessageBox::StandardButton::Yes:
1869 case QMessageBox::StandardButton::Ignore:
1880BOOL CBackendFreeRDP::cb_present_gateway_message(
1881 freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
1882 BOOL isConsentMandatory,
size_t length,
const WCHAR* message)
1884 qDebug(log) << Q_FUNC_INFO;
1886 if (!isDisplayMandatory && !isConsentMandatory)
1890 if (type == GATEWAY_MESSAGE_CONSENT && isConsentMandatory)
1892 QString msgType = (type == GATEWAY_MESSAGE_CONSENT)
1893 ? tr(
"Consent message") : tr(
"Service message");
1895#if FREERDP_VERSION_MAJOR >= 3
1896 char* pMsg = ConvertWCharToUtf8Alloc(message, NULL);
1902 msgType += QString::fromStdWString((
wchar_t*)message);
1905 msgType += tr(
"I understand and agree to the terms of this policy (Y/N)");
1907 rdpContext* pContext = (rdpContext*)instance->context;
1909 QMessageBox::StandardButton nRet = QMessageBox::No;
1910 bool bCheckBox =
false;
1912 QMessageBox::Yes|QMessageBox::No,
1915 case QMessageBox::Yes:
1923 return client_cli_present_gateway_message(
1924 instance, type, isDisplayMandatory,
1925 isConsentMandatory, length, message);
1930BOOL CBackendFreeRDP::cb_begin_paint(rdpContext *context)
1934 if (!context || !context->gdi || !context->gdi->primary
1935 || !context->gdi->primary->hdc)
1938 hdc = context->gdi->primary->hdc;
1940 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1943 hdc->hwnd->invalid->null = TRUE;
1944 hdc->hwnd->ninvalid = 0;
1948BOOL CBackendFreeRDP::UpdateBuffer(INT32 x, INT32 y, INT32 w, INT32 h)
1950 if(x > m_Image.width() || y > m_Image.height()) {
1951 qCritical(log) <<
"The width and height out of range."
1952 <<
"Image width:" << m_Image.width()
1953 <<
"Image height:" << m_Image.height()
1954 <<
"w:" << w <<
"h:" << h;
1958 QRect rect(x, y, w, h);
1959 QImage img = m_Image.copy(rect);
1965BOOL CBackendFreeRDP::cb_end_paint(rdpContext *context)
1969 CBackendFreeRDP* pThis = pContext->pThis;
1972 REGION16 invalidRegion;
1973 RECTANGLE_16 invalidRect;
1974 const RECTANGLE_16* extents;
1978 if (!context || !context->gdi || !context->gdi->primary
1979 || !context->gdi->primary->hdc)
1982 hdc = context->gdi->primary->hdc;
1984 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1987 rdpGdi* gdi = context->gdi;
1988 if (gdi->suppressOutput)
1991 HGDI_WND hwnd = context->gdi->primary->hdc->hwnd;
1992 ninvalid = hwnd->ninvalid;
1993 cinvalid = hwnd->cinvalid;
1997 region16_init(&invalidRegion);
1999 for (i = 0; i < ninvalid; i++)
2001 if(cinvalid[i].null)
2003 qWarning(log) <<
"is null region" << cinvalid[i].x << cinvalid[i].y
2004 << cinvalid[i].w << cinvalid[i].h;
2007 invalidRect.left = cinvalid[i].x;
2008 invalidRect.top = cinvalid[i].y;
2009 invalidRect.right = cinvalid[i].x + cinvalid[i].w;
2010 invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;
2011 region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
2014 if (!region16_is_empty(&invalidRegion))
2016 extents = region16_extents(&invalidRegion);
2018 pThis->UpdateBuffer(extents->left,
2020 extents->right - extents->left,
2021 extents->bottom - extents->top);
2024 region16_uninit(&invalidRegion);
2029BOOL CBackendFreeRDP::cb_desktop_resize(rdpContext* context)
2031 qDebug(log) << Q_FUNC_INFO;
2033 CBackendFreeRDP* pThis = pContext->pThis;
2034 rdpSettings* settings;
2035 if (!context || !context->settings)
2037 settings = context->settings;
2038 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
2039 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
2041 if(!gdi_resize(context->gdi, desktopWidth, desktopHeight))
2043 if(!pThis->CreateImage(context))
2046 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
2047 pThis->UpdateBuffer(0, 0, desktopWidth, desktopHeight);
2051BOOL CBackendFreeRDP::cb_play_bell_sound(rdpContext *context,
const PLAY_SOUND_UPDATE *play_sound)
2053 qDebug(log) << Q_FUNC_INFO;
2055 CBackendFreeRDP* pThis = pContext->pThis;
2056 WINPR_UNUSED(play_sound);
2057 QApplication::beep();
2061#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2062 QSoundEffect effect;
2063 effect.setSource(QUrl::fromLocalFile(szFile));
2068 QSound::play(szFile);
2074BOOL CBackendFreeRDP::cb_keyboard_set_indicators(rdpContext *context, UINT16 led_flags)
2076 qDebug(log) << Q_FUNC_INFO;
2078 CBackendFreeRDP* pThis = pContext->pThis;
2080 int state = CFrmViewer::LED_STATE::Unknown;
2082 if (led_flags & KBD_SYNC_NUM_LOCK)
2083 state |= CFrmViewer::LED_STATE::NumLock;
2084 if (led_flags & KBD_SYNC_CAPS_LOCK)
2085 state |= CFrmViewer::LED_STATE::CapsLock;
2086 if (led_flags & KBD_SYNC_SCROLL_LOCK)
2087 state |= CFrmViewer::LED_STATE::ScrollLock;
2089 emit pThis->sigUpdateLedState(state);
2095BOOL CBackendFreeRDP::cb_keyboard_set_ime_status(
2096 rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode)
2102 "KeyboardSetImeStatus(unitId=%04" PRIx16
", imeState=%08" PRIx32
2103 ", imeConvMode=%08" PRIx32
") ignored",
2104 imeId, imeState, imeConvMode);
2112 SetEvent(m_writeEvent);
2117bool CBackendFreeRDP::SendMouseEvent(UINT16 flags, QPoint pos,
bool isExtended)
2119 if(m_pParameter && m_pParameter->GetOnlyView())
return true;
2120 if(!m_pContext)
return false;
2122#if FREERDP_VERSION_MAJOR >= 3
2124 freerdp_client_send_extended_button_event(
2125 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
2127 freerdp_client_send_button_event(
2128 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
2130 if(!m_pContext->Context.input)
return false;
2131 return freerdp_input_send_mouse_event(
2132 m_pContext->Context.input, flags, pos.x(), pos.y());
2137void CBackendFreeRDP::wheelEvent(QWheelEvent *event)
2140 if(!m_pContext)
return;
2141 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2145#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2146 pos =
event->position();
2150 QPoint p =
event->angleDelta();
2153 flags |= PTR_FLAGS_WHEEL | p.y();
2157 flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.y();
2162 flags |= PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.x();
2166 flags |= PTR_FLAGS_HWHEEL | p.x();
2168#if FREERDP_VERSION_MAJOR >= 3
2169 freerdp_client_send_wheel_event(&m_pContext->Context, flags);
2174 freerdp_input_send_mouse_event(
2175 m_pContext->Context.input, flags, pos.x(), pos.y());
2180void CBackendFreeRDP::mouseMoveEvent(QMouseEvent *event)
2183 if(!m_pContext)
return;
2184 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2185 UINT16 flags = PTR_FLAGS_MOVE;
2186 SendMouseEvent(flags, event->pos(),
false);
2189void CBackendFreeRDP::mousePressEvent(QMouseEvent *event)
2192 if(!m_pContext)
return;
2193 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2196 bool isExtended =
false;
2197 Qt::MouseButton button =
event->button();
2198 if (button & Qt::MouseButton::LeftButton)
2200 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
2202 else if (button & Qt::MouseButton::RightButton)
2204 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
2206 else if (button & Qt::MouseButton::MiddleButton)
2208 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
2210 else if (button & Qt::MouseButton::ForwardButton)
2212 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
2215 else if (button & Qt::MouseButton::BackButton)
2217 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
2222 SendMouseEvent(flags, event->pos(), isExtended);
2226void CBackendFreeRDP::mouseReleaseEvent(QMouseEvent *event)
2229 if(!m_pContext)
return;
2230 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2233 bool isExtended =
false;
2234 Qt::MouseButton button =
event->button();
2235 if (button & Qt::MouseButton::LeftButton)
2237 flags = PTR_FLAGS_BUTTON1;
2239 else if (button & Qt::MouseButton::MiddleButton)
2241 flags = PTR_FLAGS_BUTTON3;
2243 else if (button & Qt::MouseButton::RightButton)
2245 flags = PTR_FLAGS_BUTTON2;
2247 else if (button & Qt::MouseButton::ForwardButton)
2249 flags = PTR_XFLAGS_BUTTON2;
2252 else if (button & Qt::MouseButton::BackButton)
2254 flags = PTR_XFLAGS_BUTTON1;
2259 SendMouseEvent(flags, event->pos(), isExtended);
2263void CBackendFreeRDP::keyPressEvent(QKeyEvent *event)
2265 if(!m_pContext)
return;
2266 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2270 if(RDP_SCANCODE_UNKNOWN != k)
2271#if FREERDP_VERSION_MAJOR >= 3
2272 freerdp_input_send_keyboard_event_ex(
2273 m_pContext->Context.context.input,
true,
true, k);
2275 freerdp_input_send_keyboard_event_ex(
2276 m_pContext->Context.input,
true, k);
2280void CBackendFreeRDP::keyReleaseEvent(QKeyEvent *event)
2282 if(!m_pContext)
return;
2283 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2286 if(RDP_SCANCODE_UNKNOWN != k)
2287#if FREERDP_VERSION_MAJOR >= 3
2288 freerdp_input_send_keyboard_event_ex(
2289 m_pContext->Context.context.input,
false,
false, k);
2291 freerdp_input_send_keyboard_event_ex(
2292 m_pContext->Context.input,
false, k);
2296void CBackendFreeRDP::InputMethodEvent(QInputMethodEvent *event)
2303 if(!m_pContext)
return;
2304 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2305 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2307 rdpSettings* settings = pRdpContext->settings;
2308 if(settings && !freerdp_settings_get_bool(settings, FreeRDP_UnicodeInput)) {
2309 qWarning(log) <<
"Don't set unicode input in server, please"
2310 << tr(
"Settings") <<
"→" << tr(
"Local resource") <<
"→" << tr(
"Enable local input method(Takes effect after reboot)");
2314 QString szText =
event->commitString();
2315 if(szText.isEmpty())
2317 for(
int i = 0; i < szText.length(); i++) {
2318 QChar c = szText.at(i);
2320#if FREERDP_VERSION_MAJOR >= 3
2322 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.context.input, 0, (UINT16)c.unicode());
2323 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.context.input, KBD_FLAGS_RELEASE, (UINT16)c.unicode());
2325 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.input, 0, (UINT16)c.unicode());
2326 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.input, KBD_FLAGS_RELEASE, (UINT16)c.unicode());
2331int CBackendFreeRDP::RedirectionSound()
2333 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2334 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2335 rdpSettings* settings = instance->context->settings;
2338 if(m_pParameter->GetRedirectionSound()
2339 == CParameterFreeRDP::RedirecionSoundType::Disable)
2342 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE);
2343 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE);
2345 }
else if(m_pParameter->GetRedirectionSound()
2346 == CParameterFreeRDP::RedirecionSoundType::Local)
2348 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, TRUE);
2349 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
2350 }
else if(m_pParameter->GetRedirectionSound()
2351 == CParameterFreeRDP::RedirecionSoundType::Remote)
2353 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, TRUE);
2368 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"rdpsnd",
2369 m_pParameter->GetRedirectionSoundParameters().toStdString().c_str(),
2371 BOOL status = freerdp_client_add_static_channel(settings, count,
2372 #
if FREERDP_VERSION_MAJOR < 3
2380 status = freerdp_client_add_dynamic_channel(settings, count,
2381 #
if FREERDP_VERSION_MAJOR < 3
2391 qCritical(log) <<
"Load rdpsnd fail";
2398int CBackendFreeRDP::RedirectionMicrophone()
2400 if(m_pParameter->GetRedirectionSound()
2401 == CParameterFreeRDP::RedirecionSoundType::Remote)
2403 if(!m_pParameter->GetRedirectionMicrophone())
2406 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2407 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2409 rdpSettings* settings = instance->context->settings;
2412 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
2423 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"audin",
2424 m_pParameter->GetRedirectionMicrophoneParameters().toStdString().c_str(),
2426 BOOL status = freerdp_client_add_dynamic_channel(settings, count,
2427 #
if FREERDP_VERSION_MAJOR < 3
2436 qCritical(log) <<
"Load audin fail";
2443int CBackendFreeRDP::RedirectionDriver()
2445 QStringList lstDrives = m_pParameter->GetRedirectionDrives();
2446 if(lstDrives.isEmpty())
2449 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2450 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2451 rdpSettings* settings = instance->context->settings;
2454 foreach (
auto drive, lstDrives) {
2456 char* pDrive = _strdup(drive.toStdString().c_str());
2457 const char* argvDrive[] = {
"drive", pDrive};
2458 int count =
sizeof(argvDrive) /
sizeof(
const char*);
2459 BOOL status = freerdp_client_add_device_channel(settings, count,
2460 #
if FREERDP_VERSION_MAJOR < 3
2464 if(pDrive) free(pDrive);
2467 qCritical(log) <<
"Load drive fail";
2475int CBackendFreeRDP::RedirectionPrinter()
2477 if(!m_pParameter->GetRedirectionPrinter())
2480 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2481 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2482 rdpSettings* settings = instance->context->settings;
2485 QStringList printerList = QPrinterInfo::availablePrinterNames();
2486 if(printerList.isEmpty())
2488 qCritical(log) <<
"The printer is empty";
2491 qDebug(log) << printerList;
2494 const char* argvPrinter[] = {
"printer",
nullptr,
nullptr};
2495 int count =
sizeof(argvPrinter) /
sizeof(
const char*);
2496 BOOL status = freerdp_client_add_device_channel(settings, count,
2497 #
if FREERDP_VERSION_MAJOR < 3
2502 qCritical(log) <<
"Load printer fail";
2509int CBackendFreeRDP::RedirectionSerial()
2514 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2515 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2516 rdpSettings* settings = instance->context->settings;
2519 QList<QSerialPortInfo> lstSerial = QSerialPortInfo::availablePorts();
2522 foreach (
auto serial, lstSerial) {
2525 qDebug(log) <<
"systemLocation:" << serial.systemLocation()
2526 <<
"portName:" << serial.portName()
2527 <<
"serialNumber:" << serial.serialNumber();
2528 char* pSerial = _strdup(serial.systemLocation().toStdString().c_str());
2529 char* pName = _strdup(serial.portName().toStdString().c_str());
2530 const char* argvSerial[] = {
"serial", pName, pSerial};
2531 int count =
sizeof(argvSerial) /
sizeof(
const char*);
2532 BOOL status = freerdp_client_add_device_channel(settings, count,
2533 #
if FREERDP_VERSION_MAJOR < 3
2537 if(pSerial) free(pSerial);
2538 if(pName) free(pName);
2542 qCritical(log) <<
"Load drive fail";
2551void CBackendFreeRDP::slotConnectProxyServer(QString szHost, quint16 nPort)
2553 qDebug(log) <<
"Connect proxy server:" << szHost +
":" + QString::number(nPort);
2554 rdpContext* pContext = (rdpContext*)m_pContext;
2555 rdpSettings* settings = pContext->settings;
2557 qCritical(log) <<
"settings is null";
2560 freerdp_settings_set_string(
2561 settings, FreeRDP_ServerHostname,
2562 szHost.toStdString().c_str());
2563 freerdp_settings_set_uint32(
2564 settings, FreeRDP_ServerPort,
2567 int nRet = freerdp_client_start(pContext);
2570 qCritical(log) <<
"freerdp_client_start fail";
2572 qDebug(log) <<
"Connect proxy server:" << szHost +
":" + QString::number(nPort) <<
"end";
2576CBackendFreeRDP::OnStartReturnValue CBackendFreeRDP::InitSSHTunnelPipe()
2580 m_pThreadSSH =
new CSSHTunnelThread(
2581 &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net,
this);
2583 return OnStartReturnValue::Fail;
2584 bool check = connect(m_pThreadSSH, SIGNAL(sigServer(QString, quint16)),
2585 this, SLOT(slotConnectProxyServer(QString, quint16)));
2587 check = connect(m_pThreadSSH, SIGNAL(
sigError(
int,QString)),
2588 this, SIGNAL(
sigError(
int,QString)));
2590 check = connect(m_pThreadSSH, SIGNAL(
sigStop()),
2593 m_pThreadSSH->start();
2594 return OnStartReturnValue::UseOnProcess;
2597int CBackendFreeRDP::CleanSSHTunnelPipe()
2601 m_pThreadSSH->Exit();
2602 m_pThreadSSH =
nullptr;
Remote desktop interface.
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
virtual void slotClipBoardChanged()=0
Be called when the clip board change.
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...
static BOOL cb_pre_connect(freerdp *instance)
Callback given to freerdp_connect() to process the pre-connect operations.
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.
virtual int OnStop() override
Clean.
virtual OnStartReturnValue OnStart() override
Initialization.
static BOOL cb_post_connect(freerdp *instance)
Callback given to freerdp_connect() to perform post-connection operations.
virtual int OnProcess() override
Specific operation processing of plug-in connection.
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 backend thread(background thread).
void sigInformation(const QString &szInfo)
Triggering from a background thread displays information in the main thread without blocking the back...
void sigStop()
Notify the user to stop.
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 sigError(const int nError, const QString &szError=QString())
Triggered when an error is generated.
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 sigRunning()
Emitted when the plugin is successfully started.
void sigFinished()
Successful stopped signal.
void sigSecurityLevel(CSecurityLevel::Levels level)
Triggered when the security level changes.
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
Blocks the background thread and displays the window in the foreground thread.
void sigBlockInputDialog(const QString &szTitle, const QString &szLable, const QString &szMessage, QString &szText)
Block background threads and display input dialogs in foreground threads (QInputDialog).
static quint32 QtToScanCode(int key, Qt::KeyboardModifiers modifiers)
CConvertKeyCode::QtToScanCode.
[Declare CParameterFreeRDP]
Basic network parameters.
CParameterUser m_User
[Instance user]
void sigChanged()
emit when the parameter changes Usually if required, the corresponding parameter corresponds to a cha...