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 <QSerialPortInfo>
39#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
40 #include <QSoundEffect>
45#ifdef WINPR_HAVE_POLL_H
52#include <sys/select.h>
56#if FREERDP_VERSION_MAJOR >= 3
57#include "ConnectLayerQTcpSocket.h"
59#include "ConnectLayerSSHTunnel.h"
64static Q_LOGGING_CATEGORY(log,
"FreeRDP.Connect")
65static Q_LOGGING_CATEGORY(logKey, "FreeRDP.Connect.Key")
66static Q_LOGGING_CATEGORY(logMouse, "FreeRDP.Connect.Mouse")
70 , m_pOperate(pOperate)
72 , m_pParameter(
nullptr)
75 , m_writeEvent(
nullptr)
76#if FREERDP_VERSION_MAJOR >= 3
77 , m_pConnectLayer(
nullptr)
80 , m_pThreadSSH(
nullptr)
83 qDebug(log) << Q_FUNC_INFO;
84 m_pParameter = qobject_cast<CParameterFreeRDP*>(pOperate->GetParameter());
85 Q_ASSERT(m_pParameter);
88CBackendFreeRDP::~CBackendFreeRDP()
90 qDebug(log) << Q_FUNC_INFO;
101 qDebug(log) << Q_FUNC_INFO;
104 m_writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
106 qCritical(log) <<
"CreateEvent failed";
107 return OnInitReturnValue::Fail;
109 ZeroMemory(&m_ClientEntryPoints,
sizeof(RDP_CLIENT_ENTRY_POINTS));
110 m_ClientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
111 m_ClientEntryPoints.Size =
sizeof(RDP_CLIENT_ENTRY_POINTS);
113 m_ClientEntryPoints.GlobalInit = cbGlobalInit;
114 m_ClientEntryPoints.GlobalUninit = cbGlobalUninit;
115 m_ClientEntryPoints.ClientNew = cbClientNew;
116 m_ClientEntryPoints.ClientFree = cbClientFree;
117 m_ClientEntryPoints.ClientStart = cbClientStart;
118 m_ClientEntryPoints.ClientStop = cbClientStop;
121 auto pRdpContext = freerdp_client_context_new(&m_ClientEntryPoints);
125 m_pContext->pThis =
this;
127 qCritical(log) <<
"freerdp_client_context_new fail";
128 return OnInitReturnValue::Fail;
131 rdpSettings* settings = pRdpContext->settings;
133 qCritical(log) <<
"settings is null";
134 return OnInitReturnValue::Fail;
147 char* argv[]= {(
char*)QApplication::applicationFilePath().toStdString().c_str()};
148 int argc =
sizeof(argv) /
sizeof(
char*);
149 nRet = freerdp_client_settings_parse_command_line(settings, argc, argv, TRUE);
152 nRet = freerdp_client_settings_command_line_status_print(settings, nRet, argc, argv);
153 return OnInitReturnValue::Fail;
156#if FREERDP_VERSION_MAJOR >= 3
157 if (!stream_dump_register_handlers(pRdpContext,
158 CONNECTION_STATE_MCS_CREATE_REQUEST,
160 return OnInitReturnValue::Fail;
163 auto &user = m_pParameter->m_Net.
m_User;
164 if(!user.GetUser().isEmpty())
165 freerdp_settings_set_string(
166 settings, FreeRDP_Username,
167 user.GetUser().toStdString().c_str());
168 if(!user.GetPassword().isEmpty()) {
169 freerdp_settings_set_string(
170 settings, FreeRDP_Password,
171 user.GetPassword().toStdString().c_str());
172 m_SecurityLevel |= CSecurityLevel::Level::Authentication;
175 freerdp_settings_set_bool(
176 settings, FreeRDP_RedirectClipboard, m_pParameter->GetClipboard());
178#if FREERDP_VERSION_MAJOR >= 3
179 bool bOnlyView = m_pParameter->GetOnlyView();
180 freerdp_settings_set_bool(
181 settings, FreeRDP_SuspendInput, bOnlyView);
184 freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
185 m_pParameter->GetDesktopWidth());
186 freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
187 m_pParameter->GetDesktopHeight());
188 freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth,
189 m_pParameter->GetColorDepth());
191 freerdp_settings_set_bool(settings, FreeRDP_UseMultimon,
192 m_pParameter->GetUseMultimon());
194 if(m_pParameter->GetReconnectInterval()) {
195 freerdp_settings_set_bool(
196 settings, FreeRDP_AutoReconnectionEnabled,
true);
197 freerdp_settings_set_uint32(
199 FreeRDP_AutoReconnectMaxRetries,
200 m_pParameter->GetReconnectInterval());
203 freerdp_settings_set_bool(
204 settings, FreeRDP_AutoReconnectionEnabled,
false);
208 RedirectionMicrophone();
210 RedirectionPrinter();
215 switch(m_pParameter->m_Proxy.GetUsedType())
217 case CParameterProxy::TYPE::System:
219 case CParameterProxy::TYPE::Http:
220 case CParameterProxy::TYPE::SockesV5:
223 if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_SOCKS))
224 return OnInitReturnValue::Fail;
225 if(CParameterProxy::TYPE::Http == m_pParameter->m_Proxy.GetUsedType()) {
226 net = &m_pParameter->m_Proxy.m_Http;
227 if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP))
228 return OnInitReturnValue::Fail;
231 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyHostname,
232 net->GetHost().toStdString().c_str()))
233 return OnInitReturnValue::Fail;
234 if (!freerdp_settings_set_uint16(settings, FreeRDP_ProxyPort, net->GetPort()))
235 return OnInitReturnValue::Fail;
237 if(((user.GetUsedType() == CParameterUser::TYPE::UserPassword)
238 && (user.GetPassword().isEmpty() || user.GetUser().isEmpty()))
239 || ((user.GetUsedType() == CParameterUser::TYPE::PublicKey)
240 && user.GetPassphrase().isEmpty())) {
241 int nRet = QDialog::Rejected;
243 if(QDialog::Accepted != nRet)
245 return OnInitReturnValue::Fail;
248 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyUsername,
249 user.GetUser().toStdString().c_str()))
250 return OnInitReturnValue::Fail;
251 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyPassword,
252 user.GetPassword().toStdString().c_str()))
253 return OnInitReturnValue::Fail;
264 case CParameterProxy::TYPE::None:
266 if(!m_pParameter->GetDomain().isEmpty())
267 freerdp_settings_set_string(
268 settings, FreeRDP_Domain,
269 m_pParameter->GetDomain().toStdString().c_str());
270 if(m_pParameter->m_Net.GetHost().isEmpty())
273 szErr = tr(
"The server is empty, please input it");
274 qCritical(log) << szErr;
276 emit
sigError(-1, szErr.toStdString().c_str());
277 return OnInitReturnValue::Fail;
279 auto &net = m_pParameter->m_Net;
280 freerdp_settings_set_string(
281 settings, FreeRDP_ServerHostname,
282 net.GetHost().toStdString().c_str());
283 freerdp_settings_set_uint32(
284 settings, FreeRDP_ServerPort,
287 nRet = freerdp_client_start(pRdpContext);
290 qCritical(log) <<
"freerdp_client_start fail";
291 return OnInitReturnValue::Fail;
296 case CParameterProxy::TYPE::SSHTunnel:
298#if FREERDP_VERSION_MAJOR >= 3
300 if(!m_pConnectLayer)
return OnInitReturnValue::Fail;
301 nRet = m_pConnectLayer->Initialize(pRdpContext);
302 if(nRet)
return OnInitReturnValue::Fail;
305 return InitSSHTunnelPipe();
310 qCritical(log) <<
"Don't support proxy type:" << m_pParameter->m_Proxy.GetUsedType();
314 return OnInitReturnValue::UseOnProcess;
319 qDebug(log) << Q_FUNC_INFO;
323 CloseHandle(m_writeEvent);
324 m_writeEvent =
nullptr;
328 rdpContext* pRdpContext = (rdpContext*)m_pContext;
329 if(!freerdp_disconnect(pRdpContext->instance))
330 qCritical(log) <<
"freerdp_disconnect fail";
332 if(freerdp_client_stop(pRdpContext))
333 qCritical(log) <<
"freerdp_client_stop fail";
335 freerdp_client_context_free(pRdpContext);
336 m_pContext =
nullptr;
339#if FREERDP_VERSION_MAJOR >= 3
340 if(m_pConnectLayer) {
341 m_pConnectLayer->Clean();
342 m_pConnectLayer->deleteLater();
343 m_pConnectLayer =
nullptr;
348 CleanSSHTunnelPipe();
390 rdpContext* pRdpContext = (rdpContext*)m_pContext;
392 if(
nullptr == freerdp_settings_get_string(pRdpContext->settings, FreeRDP_ServerHostname))
400 nCount += freerdp_get_event_handles(pRdpContext, &handles[nCount],
401 ARRAYSIZE(handles) - nCount);
404 qCritical(log) <<
"freerdp_get_event_handles failed";
410 handles[nCount++] = m_writeEvent;
412 DWORD waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, nTimeout);
415 ResetEvent(m_writeEvent);
417 if (waitStatus == WAIT_FAILED)
419 qCritical(log) <<
"WaitForMultipleObjects: WAIT_FAILED";
424 if(waitStatus == WAIT_TIMEOUT)
431 if (!freerdp_check_event_handles(pRdpContext))
435 UINT32 err = freerdp_get_last_error(pRdpContext);
437 szErr =
"freerdp_check_event_handles fail.";
439 szErr += QString::number(err);
441 szErr += freerdp_get_last_error_category(err);
443 szErr += freerdp_get_last_error_name(err);
445 szErr += freerdp_get_last_error_string(err);
446 qCritical(log) << szErr;
470#if FREERDP_VERSION_MAJOR >= 3
471 if(freerdp_shall_disconnect_context(pRdpContext))
473 if(freerdp_shall_disconnect(pRdpContext->instance))
476 qCritical(log) <<
"freerdp_shall_disconnect false";
484void CBackendFreeRDP::slotClipBoardChanged()
486 qDebug(log) << Q_FUNC_INFO;
487 if(m_pParameter && m_pParameter->GetOnlyView())
return;
488 if(m_pParameter->GetClipboard())
489 m_ClipBoard.slotClipBoardChanged();
492BOOL CBackendFreeRDP::cbGlobalInit()
494 qDebug(log) << Q_FUNC_INFO;
498void CBackendFreeRDP::cbGlobalUninit()
500 qDebug(log) << Q_FUNC_INFO;
503BOOL CBackendFreeRDP::cbClientNew(freerdp *instance, rdpContext *context)
505 qDebug(log) << Q_FUNC_INFO;
508 instance->PostDisconnect = cb_post_disconnect;
511#if FREERDP_VERSION_MAJOR < 3
512 instance->Authenticate = cb_authenticate;
513 instance->GatewayAuthenticate = cb_GatewayAuthenticate;
515 instance->AuthenticateEx = cb_authenticate_ex;
516 instance->ChooseSmartcard = cb_choose_smartcard;
521 instance->PresentGatewayMessage = cb_present_gateway_message;
523 instance->LogonErrorInfo = cb_logon_error_info;
528void CBackendFreeRDP::cbClientFree(freerdp *instance, rdpContext *context)
530 qDebug(log) << Q_FUNC_INFO;
533int CBackendFreeRDP::cbClientStart(rdpContext *context)
535 qDebug(log) << Q_FUNC_INFO;
538 if (!context || !context->settings)
540 freerdp* instance = freerdp_client_get_instance(context);
544 auto settings = context->settings;
546 QString szDomainHost;
548 szDomainHost = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
549 nPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
551 auto &net = pThis->m_pParameter->m_Net;
552 szServer = net.GetHost() +
":" + QString::number(net.GetPort());
553 auto &proxy = pThis->m_pParameter->m_Proxy;
554 switch(proxy.GetUsedType()) {
555 case CParameterProxy::TYPE::SockesV5:
557 auto &sockesV5 = proxy.m_SockesV5;
558 szServer = sockesV5.GetHost() +
":" + QString::number(sockesV5.GetPort())
562 case CParameterProxy::TYPE::Http:
564 auto &http = proxy.m_Http;
565 szServer = http.GetHost() +
":" + QString::number(http.GetPort())
569 case CParameterProxy::TYPE::SSHTunnel:
571 auto &sshNet = proxy.m_SSH.m_Net;
572#if FREERDP_VERSION_MAJOR < 3
573 szServer = szDomainHost +
":" + QString::number(nPort)
574 +
" -> " + sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
577 szServer = sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
586 BOOL status = freerdp_connect(instance);
588 QString szInfo = tr(
"Connected to ") + szServer;
589 qInfo(log) << szInfo;
594 UINT32 nRet = freerdp_get_last_error(context);
597 szErr = tr(
"Connect to ") + szServer + tr(
" fail.");
599 szErr += QString::number(nRet) +
" - ";
600 szErr += freerdp_get_last_error_name(nRet);
605 szErr += freerdp_get_last_error_string(nRet);
609 case FREERDP_ERROR_CONNECT_LOGON_FAILURE:
611 szErr = tr(
"Logon to ") + szServer;
612 szErr += tr(
" fail. Please check that the username and password are correct.") +
"\n";
615 case FREERDP_ERROR_CONNECT_WRONG_PASSWORD:
617 szErr = tr(
"Logon to ") + szServer;
618 szErr += tr(
" fail. Please check password are correct.") +
"\n";
621 case FREERDP_ERROR_AUTHENTICATION_FAILED:
623 szErr = tr(
"Logon to ") + szServer;
624 szErr += tr(
" authentication fail. please add a CA certificate to the store.") +
"\n";
627 case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED:
629 szErr = tr(
"Logon to ") + szServer;
630 szErr += tr(
" connect transport layer fail.") +
"\n\n";
631 szErr += tr(
"Please:") +
"\n";
632 szErr += tr(
"1. Check for any network related issues") +
"\n";
633 szErr += tr(
"2. Check you have proper security settings ('NLA' enabled is required for most connections nowadays)") +
"\n";
634 szErr +=
" " + tr(
"If you do not know the server security settings, contact your server administrator.") +
"\n";
635 szErr += tr(
"3. Check the certificate is proper (and guacd properly checks that)") +
"\n";
638 case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED:
640 szErr += tr(
"Please check you have proper security settings.") +
"\n";
641 szErr += tr(
"If you do not know the server security settings, contact your server administrator.");
643 case FREERDP_ERROR_CONNECT_CANCELLED:
644 szErr = tr(
"The connect was canceled.") +
"\n\n" + szErr;
651 qCritical(log) << szErr;
652 emit pThis->
sigError(nRet, szErr.toStdString().c_str());
658int CBackendFreeRDP::cbClientStop(rdpContext *context)
661 qDebug(log) << Q_FUNC_INFO;
662#if FREERDP_VERSION_MAJOR >= 3
663 nRet = freerdp_client_common_stop(context);
665 BOOL bRet = freerdp_abort_connect(context->instance);
667 { qCritical(log) <<
"freerdp_abort_connect fail";
694 qDebug(log) << Q_FUNC_INFO;
695 rdpChannels* channels =
nullptr;
696 rdpSettings* settings =
nullptr;
697 rdpContext* context = instance->context;
699 if (!instance || !instance->context || !instance->context->settings)
703 if(!pThis)
return FALSE;
704 settings = instance->context->settings;
705 channels = context->channels;
707 if(!channels || !pParameter)
711#if defined (Q_OS_WIN)
712 if (!freerdp_settings_set_uint32(
713 settings, FreeRDP_OsMajorType, OSMAJORTYPE_WINDOWS))
715 if (!freerdp_settings_set_uint32(
716 settings, FreeRDP_OsMinorType, OSMINORTYPE_WINDOWS_NT))
718#elif defined(Q_OS_ANDROID)
719 if (!freerdp_settings_set_uint32(
720 settings, FreeRDP_OsMajorType, OSMAJORTYPE_ANDROID))
722 if (!freerdp_settings_set_uint32(
723 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
725#elif defined(Q_OS_IOS)
726 if (!freerdp_settings_set_uint32(
727 settings, FreeRDP_OsMajorType, OSMAJORTYPE_IOS))
729 if (!freerdp_settings_set_uint32(
730 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
732#elif defined (Q_OS_UNIX)
733 if (!freerdp_settings_set_uint32(
734 settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX))
736 if (!freerdp_settings_set_uint32(
737 settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_XSERVER))
740 if (!freerdp_settings_set_uint32(
741 settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNSPECIFIED))
743 if (!freerdp_settings_set_uint32(
744 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
749 PubSub_SubscribeChannelConnected(instance->context->pubSub,
750 OnChannelConnectedEventHandler);
751 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
752 OnChannelDisconnectedEventHandler);
754#if FREERDP_VERSION_MAJOR < 3
755 if (!freerdp_client_load_addins(channels, instance->context->settings))
758 #if defined(Q_OS_LINUX) || (defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE))
759 if (!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, TRUE))
764 if(!freerdp_settings_set_bool(
765 settings, FreeRDP_NegotiateSecurityLayer,
766 pParameter->GetNegotiateSecurityLayer()))
768 CParameterFreeRDP::Security security = pParameter->GetSecurity();
770 if(!freerdp_settings_set_bool(
771 settings, FreeRDP_RdpSecurity,
772 CParameterFreeRDP::Security::RDP & security))
774 if (!freerdp_settings_set_bool(
775 settings, FreeRDP_UseRdpSecurityLayer,
776 CParameterFreeRDP::Security::RDP & security))
779 if(!freerdp_settings_set_bool(
780 settings, FreeRDP_TlsSecurity,
781 CParameterFreeRDP::Security::TLS & security))
783 if(!freerdp_settings_set_bool(
784 settings, FreeRDP_NlaSecurity,
785 CParameterFreeRDP::Security::NLA & security))
787 if(!freerdp_settings_set_bool(
788 settings, FreeRDP_ExtSecurity,
789 CParameterFreeRDP::Security::NLA_Ext & security))
791#if FREERDP_VERSION_MAJOR >= 3
792 if(!freerdp_settings_set_bool(
793 settings, FreeRDP_AadSecurity,
794 CParameterFreeRDP::Security::RDSAAD & security))
796 if(!freerdp_settings_set_bool(
797 settings, FreeRDP_RdstlsSecurity,
798 CParameterFreeRDP::Security::RDSTLS & security))
800 freerdp_settings_set_uint16(settings, FreeRDP_TLSMinVersion,
801 pParameter->GetTlsVersion());
805 if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly))
808 auto &user = pParameter->m_Net.
m_User;
809 if(!freerdp_settings_get_string(settings, FreeRDP_Username)) {
810 if(user.GetUser().isEmpty()) {
812 qWarning(log) <<
"Auth-only, but no user name set. Will be call instance->Authenticate.";
814 freerdp_settings_set_string(
815 settings, FreeRDP_Username,
816 user.GetUser().toStdString().c_str());
818 if (!freerdp_settings_get_string(settings, FreeRDP_Password)) {
819 if (user.GetPassword().isEmpty()) {
821 qWarning(log) <<
"auth-only, but no password set. Will be call instance->Authenticate";
823 freerdp_settings_set_string(
824 settings, FreeRDP_Password,
825 user.GetPassword().toStdString().c_str());
827#if FREERDP_VERSION_MAJOR >= 3
828 if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE))
831 }
else if(freerdp_settings_get_bool(settings, FreeRDP_CredentialsFromStdin)){
833 }
else if(freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon)) {
844 UINT32 width = pParameter->GetDesktopWidth();
845 UINT32 height = pParameter->GetDesktopHeight();
846 if ((width < 64) || (height < 64) ||
847 (width > 4096) || (height > 4096))
849 QString szErr = tr(
"Invalid dimensions:")
850 + QString::number(width)
851 +
"*" + QString::number(height);
852 qCritical(log) << szErr;
856 qInfo(log) <<
"Init desktop size " << width <<
"*" << height;
860 <<
"width:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)
861 <<
"height:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)
862 <<
"ColorDepth:" << freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
873 if(!freerdp_set_connection_type(settings, pParameter->GetConnectType()))
875 freerdp_settings_set_uint32(
876 settings, FreeRDP_PerformanceFlags, pParameter->GetPerformanceFlags());
877 freerdp_performance_flags_split(settings);
879 freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, pParameter->GetEnableLocalInputMethod());
883const char* CBackendFreeRDP::GetTitle(freerdp* instance)
885 const char* windowTitle;
888 const char* name =
nullptr;
891 rdpSettings* settings = instance->context->settings;
896 windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
900#if FREERDP_VERSION_MAJOR >= 3
901 name = freerdp_settings_get_server_name(settings);
903 name = pThis->m_pParameter->m_Net.GetHost().toStdString().c_str();
905 port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
907 addPort = (port != 3389);
909 char buffer[MAX_PATH + 64] = { 0 };
912 sprintf_s(buffer,
sizeof(buffer),
"%s", name);
914 sprintf_s(buffer,
sizeof(buffer),
"%s:%" PRIu32, name, port);
916 freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer);
917 return freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
927 qDebug(log) << Q_FUNC_INFO;
929 rdpContext* context = instance->context;
930 rdpSettings* settings = instance->context->settings;
931 rdpUpdate* update = instance->context->update;
934 const char* pWindowTitle = GetTitle(instance);
937 WCHAR* windowTitle = NULL;
938#if FREERDP_VERSION_MAJOR >= 3
939 windowTitle = ConvertUtf8ToWCharAlloc(pWindowTitle, NULL);
941 ConvertToUnicode(CP_UTF8, 0, pWindowTitle, -1, &windowTitle, 0);
945 QString title = QString::fromUtf16((
const char16_t*)windowTitle);
947 if(pThis->m_pParameter->GetServerName().isEmpty())
948 emit pThis->sigServerName(title);
952 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
953 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
954 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
956 if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
959 if(!pThis->CreateImage(instance->context))
962 Q_ASSERT(instance->context->cache);
965 if(pThis->m_Cursor.RegisterPointer(context->graphics))
968 update->BeginPaint = cb_begin_paint;
969 update->EndPaint = cb_end_paint;
970 update->DesktopResize = cb_desktop_resize;
972 update->PlaySound = cb_play_bell_sound;
974 update->SetKeyboardIndicators = cb_keyboard_set_indicators;
975 update->SetKeyboardImeStatus = cb_keyboard_set_ime_status;
981void CBackendFreeRDP::cb_post_disconnect(freerdp* instance)
983 qDebug(log) << Q_FUNC_INFO;
984 rdpContext* context =
nullptr;
986 if (!instance || !instance->context)
989 context = instance->context;
991 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
992 OnChannelConnectedEventHandler);
993 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
994 OnChannelDisconnectedEventHandler);
998int CBackendFreeRDP::cb_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
1001 const char* str_data = freerdp_get_logon_error_info_data(data);
1002 const char* str_type = freerdp_get_logon_error_info_type(type);
1003 QString szErr = tr(
"FreeRDP logon info: [");
1007 qDebug(log) << szErr;
1013void CBackendFreeRDP::OnChannelConnectedEventHandler(
void *context,
1014 #
if FREERDP_VERSION_MAJOR >= 3
1017 ChannelConnectedEventArgs *e)
1019 rdpContext* pContext = (rdpContext*)context;
1021 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
1022 qDebug(log) <<
"channel" << e->name <<
"connected";
1023 pThis->m_ClipBoard.Init((CliprdrClientContext*)e->pInterface,
1024 pThis->m_pParameter->GetClipboard());
1026#if FREERDP_VERSION_MAJOR >= 3
1028 freerdp_client_OnChannelConnectedEventHandler(pContext, e);
1030 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
1032 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
1033 rdpGdi* gdi = pContext->gdi;
1035 gdi_graphics_pipeline_init(gdi, (RdpgfxClientContext*) e->pInterface);
1038 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
1040 else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
1042 gdi_video_geometry_init(pContext->gdi, (GeometryClientContext*)e->pInterface);
1044 else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
1046 gdi_video_data_init(pContext->gdi, (VideoClientContext*)e->pInterface);
1048 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"connected but we can’t use it";
1052void CBackendFreeRDP::OnChannelDisconnectedEventHandler(
void *context,
1053 #
if FREERDP_VERSION_MAJOR >= 3
1056 ChannelDisconnectedEventArgs *e)
1058 rdpContext* pContext = (rdpContext*)context;
1061 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
1062 qDebug(log) <<
"channel" << e->name <<
"disconnected";
1063 pThis->m_ClipBoard.UnInit((CliprdrClientContext*)e->pInterface,
1064 pThis->m_pParameter->GetClipboard());
1066#if FREERDP_VERSION_MAJOR >= 3
1068 freerdp_client_OnChannelDisconnectedEventHandler(pContext, e);
1070 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
1072 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
1073 rdpGdi* gdi = pContext->gdi;
1074 gdi_graphics_pipeline_uninit(gdi, (RdpgfxClientContext*) e->pInterface);
1077 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
1080 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"disconnected but we can’t use it";
1085UINT32 CBackendFreeRDP::GetImageFormat(QImage::Format format)
1088#if (QT_VERSION >= QT_VERSION_CHECK(5,2,0))
1089 case QImage::Format_RGBA8888:
1090 return PIXEL_FORMAT_RGBA32;
1091 case QImage::Format_RGBX8888:
1092 return PIXEL_FORMAT_RGBX32;
1094 case QImage::Format_RGB16:
1095 return PIXEL_FORMAT_RGB16;
1096 case QImage::Format_ARGB32:
1097 return PIXEL_FORMAT_BGRA32;
1098 case QImage::Format_RGB32:
1099 return PIXEL_FORMAT_BGRA32;
1106UINT32 CBackendFreeRDP::GetImageFormat()
1108 return GetImageFormat(m_Image.format());
1111BOOL CBackendFreeRDP::CreateImage(rdpContext *context)
1114 ClientContext* pContext = (ClientContext*)context;
1116 rdpGdi* gdi = context->gdi;
1117 Q_ASSERT(pThis && gdi);
1118 pThis->m_Image = QImage(gdi->primary_buffer,
1119 static_cast<int>(gdi->width),
1120 static_cast<int>(gdi->height),
1121 QImage::Format_ARGB32);
1125#if FREERDP_VERSION_MAJOR >= 3
1127static CREDUI_INFOW wfUiInfo = {
sizeof(CREDUI_INFOW), NULL, L
"Enter your credentials",
1128 L
"Remote Desktop Security", NULL };
1131BOOL CBackendFreeRDP::cb_authenticate_ex(freerdp* instance,
1132 char** username,
char** password,
1133 char** domain, rdp_auth_reason reason)
1135 qDebug(log) << Q_FUNC_INFO <<
"reason:" << reason;
1139 if(!username || !password || !domain)
return FALSE;
1141 return cb_authenticate(instance, username, password, domain);
1142 rdpContext* pContext = (rdpContext*)instance->context;
1147 WCHAR UserNameW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1148 WCHAR UserW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1149 WCHAR DomainW[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1150 WCHAR PasswordW[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 };
1152 WINPR_ASSERT(instance);
1153 WINPR_ASSERT(instance->context);
1154 WINPR_ASSERT(instance->context->settings);
1156 WINPR_ASSERT(username);
1157 WINPR_ASSERT(domain);
1158 WINPR_ASSERT(password);
1160 const WCHAR auth[] = L
"Target credentials requested";
1161 const WCHAR authPin[] = L
"PIN requested";
1162 const WCHAR gwAuth[] = L
"Gateway credentials requested";
1163 const WCHAR* titleW = auth;
1166 dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
1167 CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1174 if ((*username) && (*password))
1177 case AUTH_SMARTCARD_PIN:
1178 dwFlags &= ~CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1179 dwFlags |= CREDUI_FLAGS_PASSWORD_ONLY_OK | CREDUI_FLAGS_KEEP_USERNAME;
1184 *username = _strdup(
"PIN");
1197 ConvertUtf8ToWChar(*username, UserNameW, ARRAYSIZE(UserNameW));
1198 ConvertUtf8ToWChar(*username, UserW, ARRAYSIZE(UserW));
1202 ConvertUtf8ToWChar(*password, PasswordW, ARRAYSIZE(PasswordW));
1205 ConvertUtf8ToWChar(*domain, DomainW, ARRAYSIZE(DomainW));
1207 if (_wcsnlen(PasswordW, ARRAYSIZE(PasswordW)) == 0)
1209 status = CredUIPromptForCredentialsW(&wfUiInfo, titleW, NULL, 0, UserNameW,
1210 ARRAYSIZE(UserNameW), PasswordW,
1211 ARRAYSIZE(PasswordW), &fSave, dwFlags);
1212 if (status != NO_ERROR)
1215 "CredUIPromptForCredentials unexpected status: 0x%08lX",
1220 if ((dwFlags & CREDUI_FLAGS_KEEP_USERNAME) == 0)
1222 status = CredUIParseUserNameW(UserNameW, UserW, ARRAYSIZE(UserW), DomainW,
1223 ARRAYSIZE(DomainW));
1224 if (status != NO_ERROR)
1226 CHAR User[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1227 CHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1228 CHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1230 ConvertWCharNToUtf8(UserNameW, ARRAYSIZE(UserNameW), UserName, ARRAYSIZE(UserName));
1231 ConvertWCharNToUtf8(UserW, ARRAYSIZE(UserW), User, ARRAYSIZE(User));
1232 ConvertWCharNToUtf8(DomainW, ARRAYSIZE(DomainW), Domain, ARRAYSIZE(Domain));
1234 "Failed to parse UserName: %s into User: %s Domain: %s",
1235 UserName, User, Domain);
1241 *username = ConvertWCharNToUtf8Alloc(UserW, ARRAYSIZE(UserW), NULL);
1244 qCritical(log) <<
"ConvertWCharNToUtf8Alloc failed" << status;
1248 if (_wcsnlen(DomainW, ARRAYSIZE(DomainW)) > 0)
1249 *domain = ConvertWCharNToUtf8Alloc(DomainW, ARRAYSIZE(DomainW), NULL);
1251 *domain = _strdup(
"\0");
1256 qCritical(log) <<
"strdup failed" << status;
1260 *password = ConvertWCharNToUtf8Alloc(PasswordW, ARRAYSIZE(PasswordW), NULL);
1269 return cb_authenticate(instance, username, password, domain);
1274BOOL CBackendFreeRDP::cb_choose_smartcard(freerdp* instance,
1275 SmartcardCertInfo** cert_list,
1277 DWORD* choice, BOOL gateway)
1279 rdpContext* pContext = (rdpContext*)instance->context;
1281 QString msg(
"Multiple smartcards are available for use:\n");
1282 for (DWORD i = 0; i < count; i++)
1284 const SmartcardCertInfo* cert = cert_list[i];
1285 char* reader = ConvertWCharToUtf8Alloc(cert->reader, NULL);
1286 char* container_name = ConvertWCharToUtf8Alloc(cert->containerName, NULL);
1288 msg += QString::number(i) +
" ";
1289 msg += QString(container_name) +
"\n\t";
1290 msg +=
"Reader: " + QString(reader) +
"\n\t";
1291 msg +=
"User: " + QString(cert->userHint) + +
"@" + QString(cert->domainHint) +
"\n\t";
1292 msg +=
"Subject: " + QString(cert->subject) +
"\n\t";
1293 msg +=
"Issuer: " + QString(cert->issuer) +
"\n\t";
1294 msg +=
"UPN: " + QString(cert->upn) +
"\n";
1297 free(container_name);
1300 msg +=
"\nChoose a smartcard to use for ";
1302 msg +=
"gateway authentication";
1306 msg +=
"(0 - " + QString::number(count - 1) +
")";
1314 int n = num.toInt(&ok);
1324#ifdef WITH_WINDOWS_CERT_STORE
1332static void wf_report_error(
char* wszMessage, DWORD dwErrCode)
1334 LPSTR pwszMsgBuf = NULL;
1336 if (NULL != wszMessage && 0 != *wszMessage)
1338 WLog_ERR(TAG,
"%s", wszMessage);
1341 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1346 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1356 if (NULL != pwszMsgBuf)
1358 WLog_ERR(TAG,
"Error: 0x%08x (%d) %s", dwErrCode, dwErrCode, pwszMsgBuf);
1359 LocalFree(pwszMsgBuf);
1363 WLog_ERR(TAG,
"Error: 0x%08x (%d)", dwErrCode, dwErrCode);
1367static DWORD wf_is_x509_certificate_trusted(
const char* common_name,
const char* subject,
1368 const char* issuer,
const char* fingerprint)
1370 HRESULT hr = CRYPT_E_NOT_FOUND;
1372 DWORD dwChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
1373 PCCERT_CONTEXT pCert = NULL;
1374 HCERTCHAINENGINE hChainEngine = NULL;
1375 PCCERT_CHAIN_CONTEXT pChainContext = NULL;
1377 CERT_ENHKEY_USAGE EnhkeyUsage = { 0 };
1378 CERT_USAGE_MATCH CertUsage = { 0 };
1379 CERT_CHAIN_PARA ChainPara = { 0 };
1380 CERT_CHAIN_POLICY_PARA ChainPolicy = { 0 };
1381 CERT_CHAIN_POLICY_STATUS PolicyStatus = { 0 };
1382 CERT_CHAIN_ENGINE_CONFIG EngineConfig = { 0 };
1384 DWORD derPubKeyLen = WINPR_ASSERTING_INT_CAST(uint32_t, strlen(fingerprint));
1385 char* derPubKey = calloc(derPubKeyLen,
sizeof(
char));
1386 if (NULL == derPubKey)
1388 WLog_ERR(TAG,
"Could not allocate derPubKey");
1395 if (!CryptStringToBinaryA(fingerprint, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen,
1398 WLog_ERR(TAG,
"CryptStringToBinary failed. Err: %d", GetLastError());
1405 EnhkeyUsage.cUsageIdentifier = 0;
1406 EnhkeyUsage.rgpszUsageIdentifier = NULL;
1408 CertUsage.dwType = USAGE_MATCH_TYPE_AND;
1409 CertUsage.Usage = EnhkeyUsage;
1411 ChainPara.cbSize =
sizeof(ChainPara);
1412 ChainPara.RequestedUsage = CertUsage;
1414 ChainPolicy.cbSize =
sizeof(ChainPolicy);
1416 PolicyStatus.cbSize =
sizeof(PolicyStatus);
1418 EngineConfig.cbSize =
sizeof(EngineConfig);
1419 EngineConfig.dwUrlRetrievalTimeout = 0;
1421 pCert = CertCreateCertificateContext(X509_ASN_ENCODING, derPubKey, derPubKeyLen);
1424 WLog_ERR(TAG,
"FAILED: Certificate could not be parsed.");
1428 dwChainFlags |= CERT_CHAIN_ENABLE_PEER_TRUST;
1437 if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
1439 hr = HRESULT_FROM_WIN32(GetLastError());
1446 if (!CertGetCertificateChain(hChainEngine,
1457 hr = HRESULT_FROM_WIN32(GetLastError());
1464 if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
1469 hr = HRESULT_FROM_WIN32(GetLastError());
1473 if (PolicyStatus.dwError != S_OK)
1475 wf_report_error(
"CertVerifyCertificateChainPolicy: Chain Status", PolicyStatus.dwError);
1476 hr = PolicyStatus.dwError;
1482 if (PolicyStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
1483 PolicyStatus.dwError == CRYPT_E_REVOCATION_OFFLINE)
1491 WLog_INFO(TAG,
"CertVerifyCertificateChainPolicy succeeded for %s (%s) issued by %s",
1492 common_name, subject, issuer);
1499 WLog_INFO(TAG,
"CertVerifyCertificateChainPolicy failed for %s (%s) issued by %s",
1500 common_name, subject, issuer);
1501 wf_report_error(NULL, hr);
1506 if (NULL != pChainContext)
1508 CertFreeCertificateChain(pChainContext);
1511 if (NULL != hChainEngine)
1513 CertFreeCertificateChainEngine(hChainEngine);
1518 CertFreeCertificateContext(pCert);
1527BOOL CBackendFreeRDP::cb_authenticate(freerdp* instance,
char** username,
1528 char** password,
char** domain)
1530 qDebug(log) << Q_FUNC_INFO;
1533 rdpContext* pContext = (rdpContext*)instance->context;
1535 if(!username || !password || !domain)
return FALSE;
1536 if(*username && *password )
return TRUE;
1538 int nRet = QDialog::Rejected;
1540 nRet, pThis->m_pParameter);
1541 if(QDialog::Accepted == nRet)
1543 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1544 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1545 QString szDomain = pThis->m_pParameter->GetDomain();
1546 if(!szDomain.isEmpty() && domain)
1547 *domain = _strdup(szDomain.toStdString().c_str());
1548 if(!szName.isEmpty() && username)
1549 *username = _strdup(szName.toStdString().c_str());
1551 *password = _strdup(szPassword.toStdString().c_str());
1552 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
1560BOOL CBackendFreeRDP::cb_GatewayAuthenticate(freerdp *instance,
1561 char **username,
char **password,
char **domain)
1563 qDebug(log) << Q_FUNC_INFO;
1567 rdpContext* pContext = (rdpContext*)instance->context;
1569 if(!username || !password || !domain)
return FALSE;
1570 if(*username && *password )
return TRUE;
1572 int nRet = QDialog::Rejected;
1573 emit pThis->
sigBlockShowWidget(
"CDlgGetUserPasswordFreeRDP", nRet, pThis->m_pParameter);
1574 if(QDialog::Accepted == nRet)
1576 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1577 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1578 QString szDomain = pThis->m_pParameter->GetDomain();
1579 if(!szDomain.isEmpty() && domain)
1580 *domain = _strdup(szDomain.toStdString().c_str());
1581 if(!szName.isEmpty() && username)
1582 *username = _strdup(szName.toStdString().c_str());
1584 *password = _strdup(szPassword.toStdString().c_str());
1585 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
1587 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1595 const BYTE* data,
size_t length,
1596 const char* hostname, UINT16 port, DWORD flags)
1598 qDebug(log) << Q_FUNC_INFO;
1599 rdpContext* pContext = (rdpContext*)instance->context;
1600 QSslCertificate cert(QByteArray((
const char*)data, length));
1601#if FREERDP_VERSION_MAJOR >= 3
1605 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM) {
1607 instance, hostname, port,
1608 cert.issuerDisplayName().toStdString().c_str(),
1609 cert.subjectDisplayName().toStdString().c_str(),
1610 cert.issuerDisplayName().toStdString().c_str(),
1616 instance, hostname, port,
1617 cert.issuerDisplayName().toStdString().c_str(),
1618 cert.subjectDisplayName().toStdString().c_str(),
1619 cert.issuerDisplayName().toStdString().c_str(),
1620 cert.serialNumber().toStdString().c_str(),
1624static QString pem_cert_fingerprint(
const char* pem, DWORD flags)
1626 QString szFingerPrint;
1627#if FREERDP_VERSION_MAJOR >= 3
1631 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM)
1633 rdpCertificate* cert = freerdp_certificate_new_from_pem(pem);
1637 char* fp = freerdp_certificate_get_fingerprint(cert);
1638 char* start = freerdp_certificate_get_validity(cert, TRUE);
1639 char* end = freerdp_certificate_get_validity(cert, FALSE);
1640 freerdp_certificate_free(cert);
1642 szFingerPrint = QObject::tr(
"Valid from: ") + QString(start) +
"\n";
1643 szFingerPrint += QObject::tr(
"Valid to: ") + QString(end) +
"\n";
1644 szFingerPrint += QObject::tr(
"Fingerprint: ") + QString(fp) +
"\n";
1651 szFingerPrint = QObject::tr(
"Fingerprint: ") + QString(pem) +
"\n";
1652 return szFingerPrint;
1671 const char *host, UINT16 port,
1672 const char *common_name,
const char *subject,
1673 const char *issuer,
const char *fingerprint, DWORD flags)
1675 qDebug(log) << Q_FUNC_INFO;
1677 rdpContext* pContext = (rdpContext*)instance->context;
1684 emit pThis->sigServerName(common_name);
1688 pThis->m_SecurityLevel |= CSecurityLevel::Level::SecureChannel;
1689 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1690 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1691 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1692 pThis->m_SecurityLevel |= CSecurityLevel::Level::Redirect;
1694 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1700#if FREERDP_VERSION_MAJOR >= 3
1701#if defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE)
1702 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM && !(flags & VERIFY_CERT_FLAG_MISMATCH))
1704 if (wf_is_x509_certificate_trusted(common_name, subject, issuer, fingerprint) == S_OK)
1712 QString szType = tr(
"RDP-Server");
1713 if (flags & VERIFY_CERT_FLAG_GATEWAY) {
1714 szType = tr(
"RDP-Gateway");
1716 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1717 szType = tr(
"RDP-Redirect");
1719 QString title(tr(
"Verify certificate"));
1722 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1723 message += tr(
"Common name: ") + common_name +
"\n";
1724 message += tr(
"Subject: ") + subject +
"\n";
1725 message += tr(
"Issuer: ") + issuer +
"\n";
1726 message += pem_cert_fingerprint(fingerprint, flags);
1728 if(VERIFY_CERT_FLAG_CHANGED & flags) {
1729 message += tr(
"The above X.509 certificate is changed.\n"
1730 "It is possible that the server has changed its certificate, "
1731 "or Maybe it was attacked."
1732 "Please look at the OpenSSL documentation on "
1733 "how to add a private CA to the store.");
1735 message += tr(
"The above X.509 certificate could not be verified.\n"
1736 "Possibly because you do not have the CA certificate "
1737 "in your certificate store, or the certificate has expired.\n"
1738 "Please look at the OpenSSL documentation on "
1739 "how to add a private CA to the store.");
1743 message += tr(
"Yes - trusted") +
"\n";
1744 message += tr(
"Ignore - temporary trusted") +
"\n";
1745 message += tr(
"No - no trusted") +
"\n";
1747 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1748 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1749 bool bCheckBox =
false;
1751 tr(
"Don't show again"));
1752 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1758 case QMessageBox::StandardButton::Yes:
1760 case QMessageBox::StandardButton::Ignore:
1788 const char *host, UINT16 port,
1789 const char *common_name,
const char *subject,
1790 const char *issuer,
const char *fingerprint,
1791 const char *old_subject,
const char *old_issuer,
1792 const char *old_fingerprint, DWORD flags)
1794 qDebug(log) << Q_FUNC_INFO;
1795 rdpContext* pContext = (rdpContext*)instance->context;
1798 emit pThis->sigServerName(common_name);
1801 pThis->m_SecurityLevel |= CSecurityLevel::Level::SecureChannel;
1802 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1803 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1804 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1805 pThis->m_SecurityLevel |= CSecurityLevel::Level::Redirect;
1807 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1813 QString szType = tr(
"RDP-Server");
1814 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1815 szType = tr(
"RDP-Gateway");
1816 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1817 szType = tr(
"RDP-Redirect");
1819 QString title(tr(
"Verify changed certificate"));
1821 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1822 message += tr(
"New Certificate details:") +
"\n";
1823 message +=
" " + tr(
"name: ") + common_name +
"\n";
1824 message +=
" " + tr(
"subject: ") + subject +
"\n";
1825 message +=
" " + tr(
"issuer: ") + issuer +
"\n";
1826 message +=
" " + pem_cert_fingerprint(fingerprint, flags) +
"\n";
1827 message += tr(
"Old Certificate details:") +
"\n";
1828 message +=
" " + tr(
"subject: ") + old_subject +
"\n";
1829 message +=
" " + tr(
"issuer: ") + old_issuer +
"\n";
1830 message +=
" " + pem_cert_fingerprint(old_fingerprint, flags) +
"\n";
1832 message += tr(
"The above X.509 certificate could not be verified, "
1833 "possibly because you do not have the CA certificate "
1834 "in your certificate store, or the certificate has expired. "
1835 "Please look at the OpenSSL documentation on "
1836 "how to add a private CA to the store.");
1839 message += tr(
"Yes - trusted") +
"\n";
1840 message += tr(
"Ignore - temporary trusted") +
"\n";
1841 message += tr(
"No - no trusted") +
"\n";
1843 bool bCheckBox =
false;
1844 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1845 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1847 tr(
"Don't show again"));
1848 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1855 case QMessageBox::StandardButton::Yes:
1857 case QMessageBox::StandardButton::Ignore:
1868BOOL CBackendFreeRDP::cb_present_gateway_message(
1869 freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
1870 BOOL isConsentMandatory,
size_t length,
const WCHAR* message)
1872 qDebug(log) << Q_FUNC_INFO;
1874 if (!isDisplayMandatory && !isConsentMandatory)
1878 if (type == GATEWAY_MESSAGE_CONSENT && isConsentMandatory)
1880 QString msgType = (type == GATEWAY_MESSAGE_CONSENT)
1881 ? tr(
"Consent message") : tr(
"Service message");
1883#if FREERDP_VERSION_MAJOR >= 3
1884 char* pMsg = ConvertWCharToUtf8Alloc(message, NULL);
1890 msgType += QString::fromStdWString((
wchar_t*)message);
1893 msgType += tr(
"I understand and agree to the terms of this policy (Y/N)");
1895 rdpContext* pContext = (rdpContext*)instance->context;
1897 QMessageBox::StandardButton nRet = QMessageBox::No;
1898 bool bCheckBox =
false;
1900 QMessageBox::Yes|QMessageBox::No,
1903 case QMessageBox::Yes:
1911 return client_cli_present_gateway_message(
1912 instance, type, isDisplayMandatory,
1913 isConsentMandatory, length, message);
1918BOOL CBackendFreeRDP::cb_begin_paint(rdpContext *context)
1922 if (!context || !context->gdi || !context->gdi->primary
1923 || !context->gdi->primary->hdc)
1926 hdc = context->gdi->primary->hdc;
1928 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1931 hdc->hwnd->invalid->null = TRUE;
1932 hdc->hwnd->ninvalid = 0;
1936BOOL CBackendFreeRDP::UpdateBuffer(INT32 x, INT32 y, INT32 w, INT32 h)
1938 if(x > m_Image.width() || y > m_Image.height()) {
1939 qCritical(log) <<
"The width and height out of range."
1940 <<
"Image width:" << m_Image.width()
1941 <<
"Image height:" << m_Image.height()
1942 <<
"w:" << w <<
"h:" << h;
1946 QRect rect(x, y, w, h);
1947 QImage img = m_Image.copy(rect);
1953BOOL CBackendFreeRDP::cb_end_paint(rdpContext *context)
1956 ClientContext* pContext = (ClientContext*)context;
1960 REGION16 invalidRegion;
1961 RECTANGLE_16 invalidRect;
1962 const RECTANGLE_16* extents;
1966 if (!context || !context->gdi || !context->gdi->primary
1967 || !context->gdi->primary->hdc)
1970 hdc = context->gdi->primary->hdc;
1972 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1975 rdpGdi* gdi = context->gdi;
1976 if (gdi->suppressOutput)
1979 HGDI_WND hwnd = context->gdi->primary->hdc->hwnd;
1980 ninvalid = hwnd->ninvalid;
1981 cinvalid = hwnd->cinvalid;
1985 region16_init(&invalidRegion);
1987 for (i = 0; i < ninvalid; i++)
1989 if(cinvalid[i].null)
1991 qWarning(log) <<
"is null region" << cinvalid[i].x << cinvalid[i].y
1992 << cinvalid[i].w << cinvalid[i].h;
1995 invalidRect.left = cinvalid[i].x;
1996 invalidRect.top = cinvalid[i].y;
1997 invalidRect.right = cinvalid[i].x + cinvalid[i].w;
1998 invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;
1999 region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
2002 if (!region16_is_empty(&invalidRegion))
2004 extents = region16_extents(&invalidRegion);
2006 pThis->UpdateBuffer(extents->left,
2008 extents->right - extents->left,
2009 extents->bottom - extents->top);
2012 region16_uninit(&invalidRegion);
2017BOOL CBackendFreeRDP::cb_desktop_resize(rdpContext* context)
2019 qDebug(log) << Q_FUNC_INFO;
2020 ClientContext* pContext = (ClientContext*)context;
2022 rdpSettings* settings;
2023 if (!context || !context->settings)
2025 settings = context->settings;
2026 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
2027 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
2029 if(!gdi_resize(context->gdi, desktopWidth, desktopHeight))
2031 if(!pThis->CreateImage(context))
2034 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
2035 pThis->UpdateBuffer(0, 0, desktopWidth, desktopHeight);
2039BOOL CBackendFreeRDP::cb_play_bell_sound(rdpContext *context,
const PLAY_SOUND_UPDATE *play_sound)
2041 qDebug(log) << Q_FUNC_INFO;
2042 ClientContext* pContext = (ClientContext*)context;
2044 WINPR_UNUSED(play_sound);
2045 QApplication::beep();
2049#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2050 QSoundEffect effect;
2051 effect.setSource(QUrl::fromLocalFile(szFile));
2056 QSound::play(szFile);
2062BOOL CBackendFreeRDP::cb_keyboard_set_indicators(rdpContext *context, UINT16 led_flags)
2064 qDebug(log) << Q_FUNC_INFO;
2065 ClientContext* pContext = (ClientContext*)context;
2068 int state = CFrmViewer::LED_STATE::Unknown;
2070 if (led_flags & KBD_SYNC_NUM_LOCK)
2071 state |= CFrmViewer::LED_STATE::NumLock;
2072 if (led_flags & KBD_SYNC_CAPS_LOCK)
2073 state |= CFrmViewer::LED_STATE::CapsLock;
2074 if (led_flags & KBD_SYNC_SCROLL_LOCK)
2075 state |= CFrmViewer::LED_STATE::ScrollLock;
2077 emit pThis->sigUpdateLedState(state);
2083BOOL CBackendFreeRDP::cb_keyboard_set_ime_status(
2084 rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode)
2090 "KeyboardSetImeStatus(unitId=%04" PRIx16
", imeState=%08" PRIx32
2091 ", imeConvMode=%08" PRIx32
") ignored",
2092 imeId, imeState, imeConvMode);
2100 SetEvent(m_writeEvent);
2105bool CBackendFreeRDP::SendMouseEvent(UINT16 flags, QPoint pos,
bool isExtended)
2107 if(m_pParameter && m_pParameter->GetOnlyView())
return true;
2108 if(!m_pContext)
return false;
2110#if FREERDP_VERSION_MAJOR >= 3
2112 freerdp_client_send_extended_button_event(
2113 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
2115 freerdp_client_send_button_event(
2116 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
2118 if(!m_pContext->Context.input)
return false;
2119 return freerdp_input_send_mouse_event(
2120 m_pContext->Context.input, flags, pos.x(), pos.y());
2125void CBackendFreeRDP::wheelEvent(QWheelEvent *event)
2127 qDebug(logMouse) << Q_FUNC_INFO << event;
2128 if(!m_pContext)
return;
2129 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2133#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2134 pos =
event->position();
2138 QPoint p =
event->angleDelta();
2141 flags |= PTR_FLAGS_WHEEL | p.y();
2145 flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.y();
2150 flags |= PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.x();
2154 flags |= PTR_FLAGS_HWHEEL | p.x();
2156#if FREERDP_VERSION_MAJOR >= 3
2157 freerdp_client_send_wheel_event(&m_pContext->Context, flags);
2162 freerdp_input_send_mouse_event(
2163 m_pContext->Context.input, flags, pos.x(), pos.y());
2168void CBackendFreeRDP::mouseMoveEvent(QMouseEvent *event)
2170 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
2171 if(!m_pContext)
return;
2172 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2173 UINT16 flags = PTR_FLAGS_MOVE;
2174 SendMouseEvent(flags, event->pos(),
false);
2177void CBackendFreeRDP::mousePressEvent(QMouseEvent *event)
2179 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
2180 if(!m_pContext)
return;
2181 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2184 bool isExtended =
false;
2185 Qt::MouseButton button =
event->button();
2186 if (button & Qt::MouseButton::LeftButton)
2188 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
2190 else if (button & Qt::MouseButton::RightButton)
2192 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
2194 else if (button & Qt::MouseButton::MiddleButton)
2196 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
2198 else if (button & Qt::MouseButton::ForwardButton)
2200 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
2203 else if (button & Qt::MouseButton::BackButton)
2205 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
2210 SendMouseEvent(flags, event->pos(), isExtended);
2214void CBackendFreeRDP::mouseReleaseEvent(QMouseEvent *event)
2216 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
2217 if(!m_pContext)
return;
2218 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2221 bool isExtended =
false;
2222 Qt::MouseButton button =
event->button();
2223 if (button & Qt::MouseButton::LeftButton)
2225 flags = PTR_FLAGS_BUTTON1;
2227 else if (button & Qt::MouseButton::MiddleButton)
2229 flags = PTR_FLAGS_BUTTON3;
2231 else if (button & Qt::MouseButton::RightButton)
2233 flags = PTR_FLAGS_BUTTON2;
2235 else if (button & Qt::MouseButton::ForwardButton)
2237 flags = PTR_XFLAGS_BUTTON2;
2240 else if (button & Qt::MouseButton::BackButton)
2242 flags = PTR_XFLAGS_BUTTON1;
2247 SendMouseEvent(flags, event->pos(), isExtended);
2251void CBackendFreeRDP::keyPressEvent(QKeyEvent *event)
2253 qDebug(logKey) << Q_FUNC_INFO << event;
2254 if(!m_pContext)
return;
2255 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2258 if(RDP_SCANCODE_UNKNOWN != k)
2259#if FREERDP_VERSION_MAJOR >= 3
2260 freerdp_input_send_keyboard_event_ex(
2261 m_pContext->Context.context.input,
true,
true, k);
2263 freerdp_input_send_keyboard_event_ex(
2264 m_pContext->Context.input,
true, k);
2268void CBackendFreeRDP::keyReleaseEvent(QKeyEvent *event)
2270 qDebug(logKey) << Q_FUNC_INFO << event;
2271 if(!m_pContext)
return;
2272 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2274 if(RDP_SCANCODE_UNKNOWN != k)
2275#if FREERDP_VERSION_MAJOR >= 3
2276 freerdp_input_send_keyboard_event_ex(
2277 m_pContext->Context.context.input,
false,
false, k);
2279 freerdp_input_send_keyboard_event_ex(
2280 m_pContext->Context.input,
false, k);
2284void CBackendFreeRDP::InputMethodEvent(QInputMethodEvent *event)
2286 qDebug(logKey) << Q_FUNC_INFO << event;
2287 if(!m_pContext)
return;
2288 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2289 QString szText =
event->commitString();
2290 if(szText.isEmpty())
2292 for(
int i = 0; i < szText.length(); i++) {
2293 QChar c = szText.at(i);
2294#if FREERDP_VERSION_MAJOR >= 3
2295 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.context.input, 0, (UINT16)c.unicode());
2297 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.input, 0, (UINT16)c.unicode());
2302int CBackendFreeRDP::RedirectionSound()
2304 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2305 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2306 rdpSettings* settings = instance->context->settings;
2309 if(m_pParameter->GetRedirectionSound()
2310 == CParameterFreeRDP::RedirecionSoundType::Disable)
2313 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE);
2314 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE);
2316 }
else if(m_pParameter->GetRedirectionSound()
2317 == CParameterFreeRDP::RedirecionSoundType::Local)
2319 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, TRUE);
2320 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
2321 }
else if(m_pParameter->GetRedirectionSound()
2322 == CParameterFreeRDP::RedirecionSoundType::Remote)
2324 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, TRUE);
2339 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"rdpsnd",
2340 m_pParameter->GetRedirectionSoundParameters().toStdString().c_str(),
2342 BOOL status = freerdp_client_add_static_channel(settings, count,
2343 #
if FREERDP_VERSION_MAJOR < 3
2351 status = freerdp_client_add_dynamic_channel(settings, count,
2352 #
if FREERDP_VERSION_MAJOR < 3
2362 qCritical(log) <<
"Load rdpsnd fail";
2369int CBackendFreeRDP::RedirectionMicrophone()
2371 if(m_pParameter->GetRedirectionSound()
2372 == CParameterFreeRDP::RedirecionSoundType::Remote)
2374 if(!m_pParameter->GetRedirectionMicrophone())
2377 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2378 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2380 rdpSettings* settings = instance->context->settings;
2383 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
2394 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"audin",
2395 m_pParameter->GetRedirectionMicrophoneParameters().toStdString().c_str(),
2397 BOOL status = freerdp_client_add_dynamic_channel(settings, count,
2398 #
if FREERDP_VERSION_MAJOR < 3
2407 qCritical(log) <<
"Load audin fail";
2414int CBackendFreeRDP::RedirectionDriver()
2416 QStringList lstDrives = m_pParameter->GetRedirectionDrives();
2417 if(lstDrives.isEmpty())
2420 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2421 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2422 rdpSettings* settings = instance->context->settings;
2425 foreach (
auto drive, lstDrives) {
2427 char* pDrive = _strdup(drive.toStdString().c_str());
2428 const char* argvDrive[] = {
"drive", pDrive};
2429 int count =
sizeof(argvDrive) /
sizeof(
const char*);
2430 BOOL status = freerdp_client_add_device_channel(settings, count,
2431 #
if FREERDP_VERSION_MAJOR < 3
2435 if(pDrive) free(pDrive);
2438 qCritical(log) <<
"Load drive fail";
2446int CBackendFreeRDP::RedirectionPrinter()
2448 if(!m_pParameter->GetRedirectionPrinter())
2451 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2452 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2453 rdpSettings* settings = instance->context->settings;
2456 QStringList printerList = QPrinterInfo::availablePrinterNames();
2457 if(printerList.isEmpty())
2459 qCritical(log) <<
"The printer is empty";
2462 qDebug(log) << printerList;
2465 const char* argvPrinter[] = {
"printer",
nullptr,
nullptr};
2466 int count =
sizeof(argvPrinter) /
sizeof(
const char*);
2467 BOOL status = freerdp_client_add_device_channel(settings, count,
2468 #
if FREERDP_VERSION_MAJOR < 3
2473 qCritical(log) <<
"Load printer fail";
2480int CBackendFreeRDP::RedirectionSerial()
2484 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2485 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2486 rdpSettings* settings = instance->context->settings;
2489 QList<QSerialPortInfo> lstSerial = QSerialPortInfo::availablePorts();
2492 foreach (
auto serial, lstSerial) {
2495 qDebug(log) <<
"systemLocation:" << serial.systemLocation()
2496 <<
"portName:" << serial.portName()
2497 <<
"serialNumber:" << serial.serialNumber();
2498 char* pSerial = _strdup(serial.systemLocation().toStdString().c_str());
2499 char* pName = _strdup(serial.portName().toStdString().c_str());
2500 const char* argvSerial[] = {
"serial", pName, pSerial};
2501 int count =
sizeof(argvSerial) /
sizeof(
const char*);
2502 BOOL status = freerdp_client_add_device_channel(settings, count,
2503 #
if FREERDP_VERSION_MAJOR < 3
2507 if(pSerial) free(pSerial);
2508 if(pName) free(pName);
2512 qCritical(log) <<
"Load drive fail";
2520void CBackendFreeRDP::slotConnectProxyServer(QString szHost, quint16 nPort)
2522 qDebug(log) <<
"Connect proxy server:" << szHost +
":" + QString::number(nPort);
2523 rdpContext* pContext = (rdpContext*)m_pContext;
2524 rdpSettings* settings = pContext->settings;
2526 qCritical(log) <<
"settings is null";
2529 freerdp_settings_set_string(
2530 settings, FreeRDP_ServerHostname,
2531 szHost.toStdString().c_str());
2532 freerdp_settings_set_uint32(
2533 settings, FreeRDP_ServerPort,
2536 int nRet = freerdp_client_start(pContext);
2539 qCritical(log) <<
"freerdp_client_start fail";
2541 qDebug(log) <<
"Connect proxy server:" << szHost +
":" + QString::number(nPort) <<
"end";
2545CBackendFreeRDP::OnInitReturnValue CBackendFreeRDP::InitSSHTunnelPipe()
2550 &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net,
this);
2552 return OnInitReturnValue::Fail;
2553 bool check = connect(m_pThreadSSH, SIGNAL(sigServer(QString, quint16)),
2554 this, SLOT(slotConnectProxyServer(QString, quint16)));
2556 check = connect(m_pThreadSSH, SIGNAL(
sigError(
int,QString)),
2557 this, SIGNAL(
sigError(
int,QString)));
2559 check = connect(m_pThreadSSH, SIGNAL(
sigStop()),
2562 m_pThreadSSH->start();
2563 return OnInitReturnValue::UseOnProcess;
2566int CBackendFreeRDP::CleanSSHTunnelPipe()
2570 m_pThreadSSH->Exit();
2571 m_pThreadSSH =
nullptr;
Remote desktop interface.
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
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 OnInitReturnValue OnInit() override
Initialization.
static BOOL cb_post_connect(freerdp *instance)
Callback given to freerdp_connect() to perform post-connection operations.
virtual int OnClean() override
Clean.
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 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 UINT32 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...
Data is forwarded over a local socket and SSH tunnel.