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());
173 freerdp_settings_set_bool(
174 settings, FreeRDP_RedirectClipboard, m_pParameter->GetClipboard());
176#if FREERDP_VERSION_MAJOR >= 3
177 bool bOnlyView = m_pParameter->GetOnlyView();
178 freerdp_settings_set_bool(
179 settings, FreeRDP_SuspendInput, bOnlyView);
182 freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
183 m_pParameter->GetDesktopWidth());
184 freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
185 m_pParameter->GetDesktopHeight());
186 freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth,
187 m_pParameter->GetColorDepth());
189 freerdp_settings_set_bool(settings, FreeRDP_UseMultimon,
190 m_pParameter->GetUseMultimon());
192 if(m_pParameter->GetReconnectInterval()) {
193 freerdp_settings_set_bool(
194 settings, FreeRDP_AutoReconnectionEnabled,
true);
195 freerdp_settings_set_uint32(
197 FreeRDP_AutoReconnectMaxRetries,
198 m_pParameter->GetReconnectInterval());
201 freerdp_settings_set_bool(
202 settings, FreeRDP_AutoReconnectionEnabled,
false);
206 RedirectionMicrophone();
208 RedirectionPrinter();
213 switch(m_pParameter->m_Proxy.GetUsedType())
215 case CParameterProxy::TYPE::System:
217 case CParameterProxy::TYPE::Http:
218 case CParameterProxy::TYPE::SockesV5:
221 if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_SOCKS))
222 return OnInitReturnValue::Fail;
223 if(CParameterProxy::TYPE::Http == m_pParameter->m_Proxy.GetUsedType()) {
224 net = &m_pParameter->m_Proxy.m_Http;
225 if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP))
226 return OnInitReturnValue::Fail;
229 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyHostname,
230 net->GetHost().toStdString().c_str()))
231 return OnInitReturnValue::Fail;
232 if (!freerdp_settings_set_uint16(settings, FreeRDP_ProxyPort, net->GetPort()))
233 return OnInitReturnValue::Fail;
235 if(((user.GetUsedType() == CParameterUser::TYPE::UserPassword)
236 && (user.GetPassword().isEmpty() || user.GetUser().isEmpty()))
237 || ((user.GetUsedType() == CParameterUser::TYPE::PublicKey)
238 && user.GetPassphrase().isEmpty())) {
239 int nRet = QDialog::Rejected;
241 if(QDialog::Accepted != nRet)
243 return OnInitReturnValue::Fail;
246 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyUsername,
247 user.GetUser().toStdString().c_str()))
248 return OnInitReturnValue::Fail;
249 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyPassword,
250 user.GetPassword().toStdString().c_str()))
251 return OnInitReturnValue::Fail;
262 case CParameterProxy::TYPE::None:
264 if(!m_pParameter->GetDomain().isEmpty())
265 freerdp_settings_set_string(
266 settings, FreeRDP_Domain,
267 m_pParameter->GetDomain().toStdString().c_str());
268 if(m_pParameter->m_Net.GetHost().isEmpty())
271 szErr = tr(
"The server is empty, please input it");
272 qCritical(log) << szErr;
274 emit
sigError(-1, szErr.toStdString().c_str());
275 return OnInitReturnValue::Fail;
277 auto &net = m_pParameter->m_Net;
278 freerdp_settings_set_string(
279 settings, FreeRDP_ServerHostname,
280 net.GetHost().toStdString().c_str());
281 freerdp_settings_set_uint32(
282 settings, FreeRDP_ServerPort,
285 nRet = freerdp_client_start(pRdpContext);
288 qCritical(log) <<
"freerdp_client_start fail";
289 return OnInitReturnValue::Fail;
294 case CParameterProxy::TYPE::SSHTunnel:
296#if FREERDP_VERSION_MAJOR >= 3
298 if(!m_pConnectLayer)
return OnInitReturnValue::Fail;
299 nRet = m_pConnectLayer->Initialize(pRdpContext);
300 if(nRet)
return OnInitReturnValue::Fail;
303 return InitSSHTunnelPipe();
308 qCritical(log) <<
"Don't support proxy type:" << m_pParameter->m_Proxy.GetUsedType();
312 return OnInitReturnValue::UseOnProcess;
317 qDebug(log) << Q_FUNC_INFO;
321 CloseHandle(m_writeEvent);
322 m_writeEvent =
nullptr;
326 rdpContext* pRdpContext = (rdpContext*)m_pContext;
327 if(!freerdp_disconnect(pRdpContext->instance))
328 qCritical(log) <<
"freerdp_disconnect fail";
330 if(freerdp_client_stop(pRdpContext))
331 qCritical(log) <<
"freerdp_client_stop fail";
333 freerdp_client_context_free(pRdpContext);
334 m_pContext =
nullptr;
337#if FREERDP_VERSION_MAJOR >= 3
338 if(m_pConnectLayer) {
339 m_pConnectLayer->Clean();
340 m_pConnectLayer->deleteLater();
341 m_pConnectLayer =
nullptr;
346 CleanSSHTunnelPipe();
388 rdpContext* pRdpContext = (rdpContext*)m_pContext;
390 if(
nullptr == freerdp_settings_get_string(pRdpContext->settings, FreeRDP_ServerHostname))
398 nCount += freerdp_get_event_handles(pRdpContext, &handles[nCount],
399 ARRAYSIZE(handles) - nCount);
402 qCritical(log) <<
"freerdp_get_event_handles failed";
408 handles[nCount++] = m_writeEvent;
410 DWORD waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, nTimeout);
413 ResetEvent(m_writeEvent);
415 if (waitStatus == WAIT_FAILED)
417 qCritical(log) <<
"WaitForMultipleObjects: WAIT_FAILED";
422 if(waitStatus == WAIT_TIMEOUT)
429 if (!freerdp_check_event_handles(pRdpContext))
433 UINT32 err = freerdp_get_last_error(pRdpContext);
435 szErr =
"freerdp_check_event_handles fail.";
437 szErr += QString::number(err);
439 szErr += freerdp_get_last_error_category(err);
441 szErr += freerdp_get_last_error_name(err);
443 szErr += freerdp_get_last_error_string(err);
444 qCritical(log) << szErr;
468#if FREERDP_VERSION_MAJOR >= 3
469 if(freerdp_shall_disconnect_context(pRdpContext))
471 if(freerdp_shall_disconnect(pRdpContext->instance))
474 qCritical(log) <<
"freerdp_shall_disconnect false";
482void CBackendFreeRDP::slotClipBoardChanged()
484 qDebug(log) << Q_FUNC_INFO;
485 if(m_pParameter && m_pParameter->GetOnlyView())
return;
486 if(m_pParameter->GetClipboard())
487 m_ClipBoard.slotClipBoardChanged();
490BOOL CBackendFreeRDP::cbGlobalInit()
492 qDebug(log) << Q_FUNC_INFO;
496void CBackendFreeRDP::cbGlobalUninit()
498 qDebug(log) << Q_FUNC_INFO;
501BOOL CBackendFreeRDP::cbClientNew(freerdp *instance, rdpContext *context)
503 qDebug(log) << Q_FUNC_INFO;
506 instance->PostDisconnect = cb_post_disconnect;
509#if FREERDP_VERSION_MAJOR < 3
510 instance->Authenticate = cb_authenticate;
511 instance->GatewayAuthenticate = cb_GatewayAuthenticate;
513 instance->AuthenticateEx = cb_authenticate_ex;
514 instance->ChooseSmartcard = cb_choose_smartcard;
519 instance->PresentGatewayMessage = cb_present_gateway_message;
521 instance->LogonErrorInfo = cb_logon_error_info;
526void CBackendFreeRDP::cbClientFree(freerdp *instance, rdpContext *context)
528 qDebug(log) << Q_FUNC_INFO;
531int CBackendFreeRDP::cbClientStart(rdpContext *context)
533 qDebug(log) << Q_FUNC_INFO;
536 if (!context || !context->settings)
538 freerdp* instance = freerdp_client_get_instance(context);
542 auto settings = context->settings;
544 QString szDomainHost;
546 szDomainHost = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
547 nPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
549 auto &net = pThis->m_pParameter->m_Net;
550 szServer = net.GetHost() +
":" + QString::number(net.GetPort());
551 auto &proxy = pThis->m_pParameter->m_Proxy;
552 switch(proxy.GetUsedType()) {
553 case CParameterProxy::TYPE::SockesV5:
555 auto &sockesV5 = proxy.m_SockesV5;
556 szServer = sockesV5.GetHost() +
":" + QString::number(sockesV5.GetPort())
560 case CParameterProxy::TYPE::Http:
562 auto &http = proxy.m_Http;
563 szServer = http.GetHost() +
":" + QString::number(http.GetPort())
567 case CParameterProxy::TYPE::SSHTunnel:
569 auto &sshNet = proxy.m_SSH.m_Net;
570#if FREERDP_VERSION_MAJOR < 3
571 szServer = szDomainHost +
":" + QString::number(nPort)
572 +
" -> " + sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
575 szServer = sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
584 BOOL status = freerdp_connect(instance);
586 QString szInfo = tr(
"Connected to ") + szServer;
587 qInfo(log) << szInfo;
591 UINT32 nRet = freerdp_get_last_error(context);
594 szErr = tr(
"Connect to ") + szServer + tr(
" fail.");
596 szErr += QString::number(nRet) +
" - ";
597 szErr += freerdp_get_last_error_name(nRet);
602 szErr += freerdp_get_last_error_string(nRet);
606 case FREERDP_ERROR_CONNECT_LOGON_FAILURE:
608 szErr = tr(
"Logon to ") + szServer;
609 szErr += tr(
" fail. Please check that the username and password are correct.") +
"\n";
612 case FREERDP_ERROR_CONNECT_WRONG_PASSWORD:
614 szErr = tr(
"Logon to ") + szServer;
615 szErr += tr(
" fail. Please check password are correct.") +
"\n";
618 case FREERDP_ERROR_AUTHENTICATION_FAILED:
620 szErr = tr(
"Logon to ") + szServer;
621 szErr += tr(
" authentication fail. please add a CA certificate to the store.") +
"\n";
624 case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED:
626 szErr = tr(
"Logon to ") + szServer;
627 szErr += tr(
" connect transport layer fail.") +
"\n\n";
628 szErr += tr(
"Please:") +
"\n";
629 szErr += tr(
"1. Check for any network related issues") +
"\n";
630 szErr += tr(
"2. Check you have proper security settings ('NLA' enabled is required for most connections nowadays)") +
"\n";
631 szErr +=
" " + tr(
"If you do not know the server security settings, contact your server administrator.") +
"\n";
632 szErr += tr(
"3. Check the certificate is proper (and guacd properly checks that)") +
"\n";
635 case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED:
637 szErr += tr(
"Please check you have proper security settings.") +
"\n";
638 szErr += tr(
"If you do not know the server security settings, contact your server administrator.");
640 case FREERDP_ERROR_CONNECT_CANCELLED:
641 szErr = tr(
"The connect was canceled.") +
"\n\n" + szErr;
648 qCritical(log) << szErr;
649 emit pThis->
sigError(nRet, szErr.toStdString().c_str());
655int CBackendFreeRDP::cbClientStop(rdpContext *context)
658 qDebug(log) << Q_FUNC_INFO;
659#if FREERDP_VERSION_MAJOR >= 3
660 nRet = freerdp_client_common_stop(context);
662 BOOL bRet = freerdp_abort_connect(context->instance);
664 { qCritical(log) <<
"freerdp_abort_connect fail";
691 qDebug(log) << Q_FUNC_INFO;
692 rdpChannels* channels =
nullptr;
693 rdpSettings* settings =
nullptr;
694 rdpContext* context = instance->context;
696 if (!instance || !instance->context || !instance->context->settings)
700 if(!pThis)
return FALSE;
701 settings = instance->context->settings;
702 channels = context->channels;
704 if(!channels || !pParameter)
708#if defined (Q_OS_WIN)
709 if (!freerdp_settings_set_uint32(
710 settings, FreeRDP_OsMajorType, OSMAJORTYPE_WINDOWS))
712 if (!freerdp_settings_set_uint32(
713 settings, FreeRDP_OsMinorType, OSMINORTYPE_WINDOWS_NT))
715#elif defined(Q_OS_ANDROID)
716 if (!freerdp_settings_set_uint32(
717 settings, FreeRDP_OsMajorType, OSMAJORTYPE_ANDROID))
719 if (!freerdp_settings_set_uint32(
720 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
722#elif defined(Q_OS_IOS)
723 if (!freerdp_settings_set_uint32(
724 settings, FreeRDP_OsMajorType, OSMAJORTYPE_IOS))
726 if (!freerdp_settings_set_uint32(
727 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
729#elif defined (Q_OS_UNIX)
730 if (!freerdp_settings_set_uint32(
731 settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX))
733 if (!freerdp_settings_set_uint32(
734 settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_XSERVER))
737 if (!freerdp_settings_set_uint32(
738 settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNSPECIFIED))
740 if (!freerdp_settings_set_uint32(
741 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
746 PubSub_SubscribeChannelConnected(instance->context->pubSub,
747 OnChannelConnectedEventHandler);
748 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
749 OnChannelDisconnectedEventHandler);
751#if FREERDP_VERSION_MAJOR < 3
752 if (!freerdp_client_load_addins(channels, instance->context->settings))
755 #if defined(Q_OS_LINUX) || (defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE))
756 if (!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, TRUE))
761 if(!freerdp_settings_set_bool(
762 settings, FreeRDP_NegotiateSecurityLayer,
763 pParameter->GetNegotiateSecurityLayer()))
765 CParameterFreeRDP::Security security = pParameter->GetSecurity();
767 if(!freerdp_settings_set_bool(
768 settings, FreeRDP_RdpSecurity,
769 CParameterFreeRDP::Security::RDP & security))
771 if (!freerdp_settings_set_bool(
772 settings, FreeRDP_UseRdpSecurityLayer,
773 CParameterFreeRDP::Security::RDP & security))
776 if(!freerdp_settings_set_bool(
777 settings, FreeRDP_TlsSecurity,
778 CParameterFreeRDP::Security::TLS & security))
780 if(!freerdp_settings_set_bool(
781 settings, FreeRDP_NlaSecurity,
782 CParameterFreeRDP::Security::NLA & security))
784 if(!freerdp_settings_set_bool(
785 settings, FreeRDP_ExtSecurity,
786 CParameterFreeRDP::Security::NLA_Ext & security))
788#if FREERDP_VERSION_MAJOR >= 3
789 if(!freerdp_settings_set_bool(
790 settings, FreeRDP_AadSecurity,
791 CParameterFreeRDP::Security::RDSAAD & security))
793 if(!freerdp_settings_set_bool(
794 settings, FreeRDP_RdstlsSecurity,
795 CParameterFreeRDP::Security::RDSTLS & security))
797 freerdp_settings_set_uint16(settings, FreeRDP_TLSMinVersion,
798 pParameter->GetTlsVersion());
802 if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly))
805 auto &user = pParameter->m_Net.
m_User;
806 if(!freerdp_settings_get_string(settings, FreeRDP_Username)) {
807 if(user.GetUser().isEmpty()) {
808 if(user.GetUser().isEmpty()) {
810 qWarning(log) <<
"Auth-only, but no user name set. Will be call instance->Authenticate.";
813 freerdp_settings_set_string(
814 settings, FreeRDP_Username,
815 user.GetUser().toStdString().c_str());
817 if (!freerdp_settings_get_string(settings, FreeRDP_Password)) {
818 if (user.GetPassword().isEmpty()) {
820 qWarning(log) <<
"auth-only, but no password set. Will be call instance->Authenticate";
822 freerdp_settings_set_string(
823 settings, FreeRDP_Password,
824 user.GetPassword().toStdString().c_str());
826#if FREERDP_VERSION_MAJOR >= 3
827 if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE))
830 }
else if(freerdp_settings_get_bool(settings, FreeRDP_CredentialsFromStdin)){
832 }
else if(freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon)) {
843 UINT32 width = pParameter->GetDesktopWidth();
844 UINT32 height = pParameter->GetDesktopHeight();
845 if ((width < 64) || (height < 64) ||
846 (width > 4096) || (height > 4096))
848 QString szErr = tr(
"Invalid dimensions:")
849 + QString::number(width)
850 +
"*" + QString::number(height);
851 qCritical(log) << szErr;
855 qInfo(log) <<
"Init desktop size " << width <<
"*" << height;
859 <<
"width:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)
860 <<
"height:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)
861 <<
"ColorDepth:" << freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
872 if(!freerdp_set_connection_type(settings, pParameter->GetConnectType()))
874 freerdp_settings_set_uint32(
875 settings, FreeRDP_PerformanceFlags, pParameter->GetPerformanceFlags());
876 freerdp_performance_flags_split(settings);
878 freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, pParameter->GetEnableLocalInputMethod());
882const char* CBackendFreeRDP::GetTitle(freerdp* instance)
884 const char* windowTitle;
887 const char* name =
nullptr;
890 rdpSettings* settings = instance->context->settings;
895 windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
899#if FREERDP_VERSION_MAJOR >= 3
900 name = freerdp_settings_get_server_name(settings);
902 name = pThis->m_pParameter->m_Net.GetHost().toStdString().c_str();
904 port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
906 addPort = (port != 3389);
908 char buffer[MAX_PATH + 64] = { 0 };
911 sprintf_s(buffer,
sizeof(buffer),
"%s", name);
913 sprintf_s(buffer,
sizeof(buffer),
"%s:%" PRIu32, name, port);
915 freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer);
916 return freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
926 qDebug(log) << Q_FUNC_INFO;
928 rdpContext* context = instance->context;
929 rdpSettings* settings = instance->context->settings;
930 rdpUpdate* update = instance->context->update;
933 const char* pWindowTitle = GetTitle(instance);
936 WCHAR* windowTitle = NULL;
937#if FREERDP_VERSION_MAJOR >= 3
938 windowTitle = ConvertUtf8ToWCharAlloc(pWindowTitle, NULL);
940 ConvertToUnicode(CP_UTF8, 0, pWindowTitle, -1, &windowTitle, 0);
944 QString title = QString::fromUtf16((
const char16_t*)windowTitle);
946 if(pThis->m_pParameter->GetServerName().isEmpty())
947 emit pThis->sigServerName(title);
951 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
952 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
953 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
955 if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
958 if(!pThis->CreateImage(instance->context))
961 Q_ASSERT(instance->context->cache);
964 if(pThis->m_Cursor.RegisterPointer(context->graphics))
967 update->BeginPaint = cb_begin_paint;
968 update->EndPaint = cb_end_paint;
969 update->DesktopResize = cb_desktop_resize;
971 update->PlaySound = cb_play_bell_sound;
973 update->SetKeyboardIndicators = cb_keyboard_set_indicators;
974 update->SetKeyboardImeStatus = cb_keyboard_set_ime_status;
980void CBackendFreeRDP::cb_post_disconnect(freerdp* instance)
982 qDebug(log) << Q_FUNC_INFO;
983 rdpContext* context =
nullptr;
985 if (!instance || !instance->context)
988 context = instance->context;
990 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
991 OnChannelConnectedEventHandler);
992 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
993 OnChannelDisconnectedEventHandler);
997int CBackendFreeRDP::cb_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
1000 const char* str_data = freerdp_get_logon_error_info_data(data);
1001 const char* str_type = freerdp_get_logon_error_info_type(type);
1002 QString szErr = tr(
"FreeRDP logon info: [");
1006 qDebug(log) << szErr;
1012void CBackendFreeRDP::OnChannelConnectedEventHandler(
void *context,
1013 #
if FREERDP_VERSION_MAJOR >= 3
1016 ChannelConnectedEventArgs *e)
1018 rdpContext* pContext = (rdpContext*)context;
1020 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
1021 qDebug(log) <<
"channel" << e->name <<
"connected";
1022 pThis->m_ClipBoard.Init((CliprdrClientContext*)e->pInterface,
1023 pThis->m_pParameter->GetClipboard());
1025#if FREERDP_VERSION_MAJOR >= 3
1027 freerdp_client_OnChannelConnectedEventHandler(pContext, e);
1029 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
1031 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
1032 rdpGdi* gdi = pContext->gdi;
1034 gdi_graphics_pipeline_init(gdi, (RdpgfxClientContext*) e->pInterface);
1037 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
1039 else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
1041 gdi_video_geometry_init(pContext->gdi, (GeometryClientContext*)e->pInterface);
1043 else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
1045 gdi_video_data_init(pContext->gdi, (VideoClientContext*)e->pInterface);
1047 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"connected but we can’t use it";
1051void CBackendFreeRDP::OnChannelDisconnectedEventHandler(
void *context,
1052 #
if FREERDP_VERSION_MAJOR >= 3
1055 ChannelDisconnectedEventArgs *e)
1057 rdpContext* pContext = (rdpContext*)context;
1060 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
1061 qDebug(log) <<
"channel" << e->name <<
"disconnected";
1062 pThis->m_ClipBoard.UnInit((CliprdrClientContext*)e->pInterface,
1063 pThis->m_pParameter->GetClipboard());
1065#if FREERDP_VERSION_MAJOR >= 3
1067 freerdp_client_OnChannelDisconnectedEventHandler(pContext, e);
1069 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
1071 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
1072 rdpGdi* gdi = pContext->gdi;
1073 gdi_graphics_pipeline_uninit(gdi, (RdpgfxClientContext*) e->pInterface);
1076 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
1079 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"disconnected but we can’t use it";
1084UINT32 CBackendFreeRDP::GetImageFormat(QImage::Format format)
1087#if (QT_VERSION >= QT_VERSION_CHECK(5,2,0))
1088 case QImage::Format_RGBA8888:
1089 return PIXEL_FORMAT_RGBA32;
1090 case QImage::Format_RGBX8888:
1091 return PIXEL_FORMAT_RGBX32;
1093 case QImage::Format_RGB16:
1094 return PIXEL_FORMAT_RGB16;
1095 case QImage::Format_ARGB32:
1096 return PIXEL_FORMAT_BGRA32;
1097 case QImage::Format_RGB32:
1098 return PIXEL_FORMAT_BGRA32;
1105UINT32 CBackendFreeRDP::GetImageFormat()
1107 return GetImageFormat(m_Image.format());
1110BOOL CBackendFreeRDP::CreateImage(rdpContext *context)
1113 ClientContext* pContext = (ClientContext*)context;
1115 rdpGdi* gdi = context->gdi;
1116 Q_ASSERT(pThis && gdi);
1117 pThis->m_Image = QImage(gdi->primary_buffer,
1118 static_cast<int>(gdi->width),
1119 static_cast<int>(gdi->height),
1120 QImage::Format_ARGB32);
1124#if FREERDP_VERSION_MAJOR >= 3
1126static CREDUI_INFOW wfUiInfo = {
sizeof(CREDUI_INFOW), NULL, L
"Enter your credentials",
1127 L
"Remote Desktop Security", NULL };
1130BOOL CBackendFreeRDP::cb_authenticate_ex(freerdp* instance,
1131 char** username,
char** password,
1132 char** domain, rdp_auth_reason reason)
1134 qDebug(log) << Q_FUNC_INFO <<
"reason:" << reason;
1138 if(!username || !password || !domain)
return FALSE;
1140 rdpContext* pContext = (rdpContext*)instance->context;
1145 WCHAR UserNameW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1146 WCHAR UserW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1147 WCHAR DomainW[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1148 WCHAR PasswordW[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 };
1150 WINPR_ASSERT(instance);
1151 WINPR_ASSERT(instance->context);
1152 WINPR_ASSERT(instance->context->settings);
1154 WINPR_ASSERT(username);
1155 WINPR_ASSERT(domain);
1156 WINPR_ASSERT(password);
1158 const WCHAR auth[] = L
"Target credentials requested";
1159 const WCHAR authPin[] = L
"PIN requested";
1160 const WCHAR gwAuth[] = L
"Gateway credentials requested";
1161 const WCHAR* titleW = auth;
1164 dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
1165 CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1172 if ((*username) && (*password))
1175 case AUTH_SMARTCARD_PIN:
1176 dwFlags &= ~CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1177 dwFlags |= CREDUI_FLAGS_PASSWORD_ONLY_OK | CREDUI_FLAGS_KEEP_USERNAME;
1182 *username = _strdup(
"PIN");
1195 ConvertUtf8ToWChar(*username, UserNameW, ARRAYSIZE(UserNameW));
1196 ConvertUtf8ToWChar(*username, UserW, ARRAYSIZE(UserW));
1200 ConvertUtf8ToWChar(*password, PasswordW, ARRAYSIZE(PasswordW));
1203 ConvertUtf8ToWChar(*domain, DomainW, ARRAYSIZE(DomainW));
1205 if (_wcsnlen(PasswordW, ARRAYSIZE(PasswordW)) == 0)
1207 status = CredUIPromptForCredentialsW(&wfUiInfo, titleW, NULL, 0, UserNameW,
1208 ARRAYSIZE(UserNameW), PasswordW,
1209 ARRAYSIZE(PasswordW), &fSave, dwFlags);
1210 if (status != NO_ERROR)
1213 "CredUIPromptForCredentials unexpected status: 0x%08lX",
1218 if ((dwFlags & CREDUI_FLAGS_KEEP_USERNAME) == 0)
1220 status = CredUIParseUserNameW(UserNameW, UserW, ARRAYSIZE(UserW), DomainW,
1221 ARRAYSIZE(DomainW));
1222 if (status != NO_ERROR)
1224 CHAR User[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1225 CHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1226 CHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1228 ConvertWCharNToUtf8(UserNameW, ARRAYSIZE(UserNameW), UserName, ARRAYSIZE(UserName));
1229 ConvertWCharNToUtf8(UserW, ARRAYSIZE(UserW), User, ARRAYSIZE(User));
1230 ConvertWCharNToUtf8(DomainW, ARRAYSIZE(DomainW), Domain, ARRAYSIZE(Domain));
1232 "Failed to parse UserName: %s into User: %s Domain: %s",
1233 UserName, User, Domain);
1239 *username = ConvertWCharNToUtf8Alloc(UserW, ARRAYSIZE(UserW), NULL);
1242 qCritical(log) <<
"ConvertWCharNToUtf8Alloc failed" << status;
1246 if (_wcsnlen(DomainW, ARRAYSIZE(DomainW)) > 0)
1247 *domain = ConvertWCharNToUtf8Alloc(DomainW, ARRAYSIZE(DomainW), NULL);
1249 *domain = _strdup(
"\0");
1254 qCritical(log) <<
"strdup failed" << status;
1258 *password = ConvertWCharNToUtf8Alloc(PasswordW, ARRAYSIZE(PasswordW), NULL);
1267 return cb_authenticate(instance, username, password, domain);
1272BOOL CBackendFreeRDP::cb_choose_smartcard(freerdp* instance,
1273 SmartcardCertInfo** cert_list,
1275 DWORD* choice, BOOL gateway)
1277 rdpContext* pContext = (rdpContext*)instance->context;
1279 QString msg(
"Multiple smartcards are available for use:\n");
1280 for (DWORD i = 0; i < count; i++)
1282 const SmartcardCertInfo* cert = cert_list[i];
1283 char* reader = ConvertWCharToUtf8Alloc(cert->reader, NULL);
1284 char* container_name = ConvertWCharToUtf8Alloc(cert->containerName, NULL);
1286 msg += QString::number(i) +
" ";
1287 msg += QString(container_name) +
"\n\t";
1288 msg +=
"Reader: " + QString(reader) +
"\n\t";
1289 msg +=
"User: " + QString(cert->userHint) + +
"@" + QString(cert->domainHint) +
"\n\t";
1290 msg +=
"Subject: " + QString(cert->subject) +
"\n\t";
1291 msg +=
"Issuer: " + QString(cert->issuer) +
"\n\t";
1292 msg +=
"UPN: " + QString(cert->upn) +
"\n";
1295 free(container_name);
1298 msg +=
"\nChoose a smartcard to use for ";
1300 msg +=
"gateway authentication";
1304 msg +=
"(0 - " + QString::number(count - 1) +
")";
1312 int n = num.toInt(&ok);
1322#ifdef WITH_WINDOWS_CERT_STORE
1330static void wf_report_error(
char* wszMessage, DWORD dwErrCode)
1332 LPSTR pwszMsgBuf = NULL;
1334 if (NULL != wszMessage && 0 != *wszMessage)
1336 WLog_ERR(TAG,
"%s", wszMessage);
1339 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1344 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1354 if (NULL != pwszMsgBuf)
1356 WLog_ERR(TAG,
"Error: 0x%08x (%d) %s", dwErrCode, dwErrCode, pwszMsgBuf);
1357 LocalFree(pwszMsgBuf);
1361 WLog_ERR(TAG,
"Error: 0x%08x (%d)", dwErrCode, dwErrCode);
1365static DWORD wf_is_x509_certificate_trusted(
const char* common_name,
const char* subject,
1366 const char* issuer,
const char* fingerprint)
1368 HRESULT hr = CRYPT_E_NOT_FOUND;
1370 DWORD dwChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
1371 PCCERT_CONTEXT pCert = NULL;
1372 HCERTCHAINENGINE hChainEngine = NULL;
1373 PCCERT_CHAIN_CONTEXT pChainContext = NULL;
1375 CERT_ENHKEY_USAGE EnhkeyUsage = { 0 };
1376 CERT_USAGE_MATCH CertUsage = { 0 };
1377 CERT_CHAIN_PARA ChainPara = { 0 };
1378 CERT_CHAIN_POLICY_PARA ChainPolicy = { 0 };
1379 CERT_CHAIN_POLICY_STATUS PolicyStatus = { 0 };
1380 CERT_CHAIN_ENGINE_CONFIG EngineConfig = { 0 };
1382 DWORD derPubKeyLen = WINPR_ASSERTING_INT_CAST(uint32_t, strlen(fingerprint));
1383 char* derPubKey = calloc(derPubKeyLen,
sizeof(
char));
1384 if (NULL == derPubKey)
1386 WLog_ERR(TAG,
"Could not allocate derPubKey");
1393 if (!CryptStringToBinaryA(fingerprint, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen,
1396 WLog_ERR(TAG,
"CryptStringToBinary failed. Err: %d", GetLastError());
1403 EnhkeyUsage.cUsageIdentifier = 0;
1404 EnhkeyUsage.rgpszUsageIdentifier = NULL;
1406 CertUsage.dwType = USAGE_MATCH_TYPE_AND;
1407 CertUsage.Usage = EnhkeyUsage;
1409 ChainPara.cbSize =
sizeof(ChainPara);
1410 ChainPara.RequestedUsage = CertUsage;
1412 ChainPolicy.cbSize =
sizeof(ChainPolicy);
1414 PolicyStatus.cbSize =
sizeof(PolicyStatus);
1416 EngineConfig.cbSize =
sizeof(EngineConfig);
1417 EngineConfig.dwUrlRetrievalTimeout = 0;
1419 pCert = CertCreateCertificateContext(X509_ASN_ENCODING, derPubKey, derPubKeyLen);
1422 WLog_ERR(TAG,
"FAILED: Certificate could not be parsed.");
1426 dwChainFlags |= CERT_CHAIN_ENABLE_PEER_TRUST;
1435 if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
1437 hr = HRESULT_FROM_WIN32(GetLastError());
1444 if (!CertGetCertificateChain(hChainEngine,
1455 hr = HRESULT_FROM_WIN32(GetLastError());
1462 if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
1467 hr = HRESULT_FROM_WIN32(GetLastError());
1471 if (PolicyStatus.dwError != S_OK)
1473 wf_report_error(
"CertVerifyCertificateChainPolicy: Chain Status", PolicyStatus.dwError);
1474 hr = PolicyStatus.dwError;
1480 if (PolicyStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
1481 PolicyStatus.dwError == CRYPT_E_REVOCATION_OFFLINE)
1489 WLog_INFO(TAG,
"CertVerifyCertificateChainPolicy succeeded for %s (%s) issued by %s",
1490 common_name, subject, issuer);
1497 WLog_INFO(TAG,
"CertVerifyCertificateChainPolicy failed for %s (%s) issued by %s",
1498 common_name, subject, issuer);
1499 wf_report_error(NULL, hr);
1504 if (NULL != pChainContext)
1506 CertFreeCertificateChain(pChainContext);
1509 if (NULL != hChainEngine)
1511 CertFreeCertificateChainEngine(hChainEngine);
1516 CertFreeCertificateContext(pCert);
1525BOOL CBackendFreeRDP::cb_authenticate(freerdp* instance,
char** username,
1526 char** password,
char** domain)
1528 qDebug(log) << Q_FUNC_INFO;
1531 rdpContext* pContext = (rdpContext*)instance->context;
1533 if(!username || !password || !domain)
return FALSE;
1534 if(*username && *password )
return TRUE;
1536 int nRet = QDialog::Rejected;
1538 nRet, pThis->m_pParameter);
1539 if(QDialog::Accepted == nRet)
1541 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1542 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1543 QString szDomain = pThis->m_pParameter->GetDomain();
1544 if(!szDomain.isEmpty() && domain)
1545 *domain = _strdup(szDomain.toStdString().c_str());
1546 if(!szName.isEmpty() && username)
1547 *username = _strdup(szName.toStdString().c_str());
1548 if(!szPassword.isEmpty() && password)
1549 *password = _strdup(szPassword.toStdString().c_str());
1556BOOL CBackendFreeRDP::cb_GatewayAuthenticate(freerdp *instance,
1557 char **username,
char **password,
char **domain)
1559 qDebug(log) << Q_FUNC_INFO;
1563 rdpContext* pContext = (rdpContext*)instance->context;
1565 if(!username || !password || !domain)
return FALSE;
1566 if(*username && *password )
return TRUE;
1568 int nRet = QDialog::Rejected;
1569 emit pThis->
sigBlockShowWidget(
"CDlgGetUserPasswordFreeRDP", nRet, pThis->m_pParameter);
1570 if(QDialog::Accepted == nRet)
1572 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1573 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1574 QString szDomain = pThis->m_pParameter->GetDomain();
1575 if(!szDomain.isEmpty() && domain)
1576 *domain = _strdup(szDomain.toStdString().c_str());
1577 if(!szName.isEmpty() && username)
1578 *username = _strdup(szName.toStdString().c_str());
1579 if(!szPassword.isEmpty() && password)
1580 *password = _strdup(szPassword.toStdString().c_str());
1588 const BYTE* data,
size_t length,
1589 const char* hostname, UINT16 port, DWORD flags)
1591 qDebug(log) << Q_FUNC_INFO;
1592 rdpContext* pContext = (rdpContext*)instance->context;
1593 QSslCertificate cert(QByteArray((
const char*)data, length));
1594#if FREERDP_VERSION_MAJOR >= 3
1598 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM) {
1600 instance, hostname, port,
1601 cert.issuerDisplayName().toStdString().c_str(),
1602 cert.subjectDisplayName().toStdString().c_str(),
1603 cert.issuerDisplayName().toStdString().c_str(),
1609 instance, hostname, port,
1610 cert.issuerDisplayName().toStdString().c_str(),
1611 cert.subjectDisplayName().toStdString().c_str(),
1612 cert.issuerDisplayName().toStdString().c_str(),
1613 cert.serialNumber().toStdString().c_str(),
1617static QString pem_cert_fingerprint(
const char* pem, DWORD flags)
1619 QString szFingerPrint;
1620#if FREERDP_VERSION_MAJOR >= 3
1624 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM)
1626 rdpCertificate* cert = freerdp_certificate_new_from_pem(pem);
1630 char* fp = freerdp_certificate_get_fingerprint(cert);
1631 char* start = freerdp_certificate_get_validity(cert, TRUE);
1632 char* end = freerdp_certificate_get_validity(cert, FALSE);
1633 freerdp_certificate_free(cert);
1635 szFingerPrint = QObject::tr(
"Valid from: ") + QString(start) +
"\n";
1636 szFingerPrint += QObject::tr(
"Valid to: ") + QString(end) +
"\n";
1637 szFingerPrint += QObject::tr(
"Fingerprint: ") + QString(fp) +
"\n";
1644 szFingerPrint = QObject::tr(
"Fingerprint: ") + QString(pem) +
"\n";
1645 return szFingerPrint;
1664 const char *host, UINT16 port,
1665 const char *common_name,
const char *subject,
1666 const char *issuer,
const char *fingerprint, DWORD flags)
1668 qDebug(log) << Q_FUNC_INFO;
1670 rdpContext* pContext = (rdpContext*)instance->context;
1677 emit pThis->sigServerName(common_name);
1680 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1686#if FREERDP_VERSION_MAJOR >= 3
1687#if defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE)
1688 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM && !(flags & VERIFY_CERT_FLAG_MISMATCH))
1690 if (wf_is_x509_certificate_trusted(common_name, subject, issuer, fingerprint) == S_OK)
1698 QString szType = tr(
"RDP-Server");
1699 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1700 szType = tr(
"RDP-Gateway");
1701 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1702 szType = tr(
"RDP-Redirect");
1704 QString title(tr(
"Verify certificate"));
1707 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1708 message += tr(
"Common name: ") + common_name +
"\n";
1709 message += tr(
"Subject: ") + subject +
"\n";
1710 message += tr(
"Issuer: ") + issuer +
"\n";
1711 message += pem_cert_fingerprint(fingerprint, flags);
1713 if(VERIFY_CERT_FLAG_CHANGED & flags) {
1714 message += tr(
"The above X.509 certificate is changed.\n"
1715 "It is possible that the server has changed its certificate, "
1716 "or Maybe it was attacked."
1717 "Please look at the OpenSSL documentation on "
1718 "how to add a private CA to the store.");
1720 message += tr(
"The above X.509 certificate could not be verified.\n"
1721 "Possibly because you do not have the CA certificate "
1722 "in your certificate store, or the certificate has expired.\n"
1723 "Please look at the OpenSSL documentation on "
1724 "how to add a private CA to the store.");
1728 message += tr(
"Yes - trusted") +
"\n";
1729 message += tr(
"Ignore - temporary trusted") +
"\n";
1730 message += tr(
"No - no trusted") +
"\n";
1732 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1733 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1734 bool bCheckBox =
false;
1736 tr(
"Don't show again"));
1737 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1743 case QMessageBox::StandardButton::Yes:
1745 case QMessageBox::StandardButton::Ignore:
1773 const char *host, UINT16 port,
1774 const char *common_name,
const char *subject,
1775 const char *issuer,
const char *fingerprint,
1776 const char *old_subject,
const char *old_issuer,
1777 const char *old_fingerprint, DWORD flags)
1779 qDebug(log) << Q_FUNC_INFO;
1780 rdpContext* pContext = (rdpContext*)instance->context;
1783 emit pThis->sigServerName(common_name);
1785 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1791 QString szType = tr(
"RDP-Server");
1792 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1793 szType = tr(
"RDP-Gateway");
1794 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1795 szType = tr(
"RDP-Redirect");
1797 QString title(tr(
"Verify changed certificate"));
1799 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1800 message += tr(
"New Certificate details:") +
"\n";
1801 message +=
" " + tr(
"name: ") + common_name +
"\n";
1802 message +=
" " + tr(
"subject: ") + subject +
"\n";
1803 message +=
" " + tr(
"issuer: ") + issuer +
"\n";
1804 message +=
" " + pem_cert_fingerprint(fingerprint, flags) +
"\n";
1805 message += tr(
"Old Certificate details:") +
"\n";
1806 message +=
" " + tr(
"subject: ") + old_subject +
"\n";
1807 message +=
" " + tr(
"issuer: ") + old_issuer +
"\n";
1808 message +=
" " + pem_cert_fingerprint(old_fingerprint, flags) +
"\n";
1810 message += tr(
"The above X.509 certificate could not be verified, "
1811 "possibly because you do not have the CA certificate "
1812 "in your certificate store, or the certificate has expired. "
1813 "Please look at the OpenSSL documentation on "
1814 "how to add a private CA to the store.");
1817 message += tr(
"Yes - trusted") +
"\n";
1818 message += tr(
"Ignore - temporary trusted") +
"\n";
1819 message += tr(
"No - no trusted") +
"\n";
1821 bool bCheckBox =
false;
1822 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1823 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1825 tr(
"Don't show again"));
1826 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1833 case QMessageBox::StandardButton::Yes:
1835 case QMessageBox::StandardButton::Ignore:
1846BOOL CBackendFreeRDP::cb_present_gateway_message(
1847 freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
1848 BOOL isConsentMandatory,
size_t length,
const WCHAR* message)
1850 qDebug(log) << Q_FUNC_INFO;
1852 if (!isDisplayMandatory && !isConsentMandatory)
1856 if (type == GATEWAY_MESSAGE_CONSENT && isConsentMandatory)
1858 QString msgType = (type == GATEWAY_MESSAGE_CONSENT)
1859 ? tr(
"Consent message") : tr(
"Service message");
1861#if FREERDP_VERSION_MAJOR >= 3
1862 char* pMsg = ConvertWCharToUtf8Alloc(message, NULL);
1868 msgType += QString::fromStdWString((
wchar_t*)message);
1871 msgType += tr(
"I understand and agree to the terms of this policy (Y/N)");
1873 rdpContext* pContext = (rdpContext*)instance->context;
1875 QMessageBox::StandardButton nRet = QMessageBox::No;
1876 bool bCheckBox =
false;
1878 QMessageBox::Yes|QMessageBox::No,
1881 case QMessageBox::Yes:
1889 return client_cli_present_gateway_message(
1890 instance, type, isDisplayMandatory,
1891 isConsentMandatory, length, message);
1896BOOL CBackendFreeRDP::cb_begin_paint(rdpContext *context)
1900 if (!context || !context->gdi || !context->gdi->primary
1901 || !context->gdi->primary->hdc)
1904 hdc = context->gdi->primary->hdc;
1906 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1909 hdc->hwnd->invalid->null = TRUE;
1910 hdc->hwnd->ninvalid = 0;
1914BOOL CBackendFreeRDP::UpdateBuffer(INT32 x, INT32 y, INT32 w, INT32 h)
1916 if(x > m_Image.width() || y > m_Image.height()) {
1917 qCritical(log) <<
"The width and height out of range."
1918 <<
"Image width:" << m_Image.width()
1919 <<
"Image height:" << m_Image.height()
1920 <<
"w:" << w <<
"h:" << h;
1924 QRect rect(x, y, w, h);
1925 QImage img = m_Image.copy(rect);
1931BOOL CBackendFreeRDP::cb_end_paint(rdpContext *context)
1934 ClientContext* pContext = (ClientContext*)context;
1938 REGION16 invalidRegion;
1939 RECTANGLE_16 invalidRect;
1940 const RECTANGLE_16* extents;
1944 if (!context || !context->gdi || !context->gdi->primary
1945 || !context->gdi->primary->hdc)
1948 hdc = context->gdi->primary->hdc;
1950 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1953 rdpGdi* gdi = context->gdi;
1954 if (gdi->suppressOutput)
1957 HGDI_WND hwnd = context->gdi->primary->hdc->hwnd;
1958 ninvalid = hwnd->ninvalid;
1959 cinvalid = hwnd->cinvalid;
1963 region16_init(&invalidRegion);
1965 for (i = 0; i < ninvalid; i++)
1967 if(cinvalid[i].null)
1969 qWarning(log) <<
"is null region" << cinvalid[i].x << cinvalid[i].y
1970 << cinvalid[i].w << cinvalid[i].h;
1973 invalidRect.left = cinvalid[i].x;
1974 invalidRect.top = cinvalid[i].y;
1975 invalidRect.right = cinvalid[i].x + cinvalid[i].w;
1976 invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;
1977 region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
1980 if (!region16_is_empty(&invalidRegion))
1982 extents = region16_extents(&invalidRegion);
1984 pThis->UpdateBuffer(extents->left,
1986 extents->right - extents->left,
1987 extents->bottom - extents->top);
1990 region16_uninit(&invalidRegion);
1995BOOL CBackendFreeRDP::cb_desktop_resize(rdpContext* context)
1997 qDebug(log) << Q_FUNC_INFO;
1998 ClientContext* pContext = (ClientContext*)context;
2000 rdpSettings* settings;
2001 if (!context || !context->settings)
2003 settings = context->settings;
2004 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
2005 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
2007 if(!gdi_resize(context->gdi, desktopWidth, desktopHeight))
2009 if(!pThis->CreateImage(context))
2012 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
2013 pThis->UpdateBuffer(0, 0, desktopWidth, desktopHeight);
2017BOOL CBackendFreeRDP::cb_play_bell_sound(rdpContext *context,
const PLAY_SOUND_UPDATE *play_sound)
2019 qDebug(log) << Q_FUNC_INFO;
2020 ClientContext* pContext = (ClientContext*)context;
2022 WINPR_UNUSED(play_sound);
2023 QApplication::beep();
2027#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2028 QSoundEffect effect;
2029 effect.setSource(QUrl::fromLocalFile(szFile));
2034 QSound::play(szFile);
2040BOOL CBackendFreeRDP::cb_keyboard_set_indicators(rdpContext *context, UINT16 led_flags)
2042 qDebug(log) << Q_FUNC_INFO;
2043 ClientContext* pContext = (ClientContext*)context;
2046 int state = CFrmViewer::LED_STATE::Unknown;
2048 if (led_flags & KBD_SYNC_NUM_LOCK)
2049 state |= CFrmViewer::LED_STATE::NumLock;
2050 if (led_flags & KBD_SYNC_CAPS_LOCK)
2051 state |= CFrmViewer::LED_STATE::CapsLock;
2052 if (led_flags & KBD_SYNC_SCROLL_LOCK)
2053 state |= CFrmViewer::LED_STATE::ScrollLock;
2055 emit pThis->sigUpdateLedState(state);
2061BOOL CBackendFreeRDP::cb_keyboard_set_ime_status(
2062 rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode)
2068 "KeyboardSetImeStatus(unitId=%04" PRIx16
", imeState=%08" PRIx32
2069 ", imeConvMode=%08" PRIx32
") ignored",
2070 imeId, imeState, imeConvMode);
2078 SetEvent(m_writeEvent);
2083bool CBackendFreeRDP::SendMouseEvent(UINT16 flags, QPoint pos,
bool isExtended)
2085 if(m_pParameter && m_pParameter->GetOnlyView())
return true;
2086 if(!m_pContext)
return false;
2088#if FREERDP_VERSION_MAJOR >= 3
2090 freerdp_client_send_extended_button_event(
2091 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
2093 freerdp_client_send_button_event(
2094 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
2096 if(!m_pContext->Context.input)
return false;
2097 return freerdp_input_send_mouse_event(
2098 m_pContext->Context.input, flags, pos.x(), pos.y());
2103void CBackendFreeRDP::wheelEvent(QWheelEvent *event)
2105 qDebug(logMouse) << Q_FUNC_INFO << event;
2106 if(!m_pContext)
return;
2107 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2111#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2112 pos =
event->position();
2116 QPoint p =
event->angleDelta();
2119 flags |= PTR_FLAGS_WHEEL | p.y();
2123 flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.y();
2128 flags |= PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.x();
2132 flags |= PTR_FLAGS_HWHEEL | p.x();
2134#if FREERDP_VERSION_MAJOR >= 3
2135 freerdp_client_send_wheel_event(&m_pContext->Context, flags);
2140 freerdp_input_send_mouse_event(
2141 m_pContext->Context.input, flags, pos.x(), pos.y());
2146void CBackendFreeRDP::mouseMoveEvent(QMouseEvent *event)
2148 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
2149 if(!m_pContext)
return;
2150 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2151 UINT16 flags = PTR_FLAGS_MOVE;
2152 SendMouseEvent(flags, event->pos(),
false);
2155void CBackendFreeRDP::mousePressEvent(QMouseEvent *event)
2157 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
2158 if(!m_pContext)
return;
2159 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2162 bool isExtended =
false;
2163 Qt::MouseButton button =
event->button();
2164 if (button & Qt::MouseButton::LeftButton)
2166 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
2168 else if (button & Qt::MouseButton::RightButton)
2170 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
2172 else if (button & Qt::MouseButton::MiddleButton)
2174 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
2176 else if (button & Qt::MouseButton::ForwardButton)
2178 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
2181 else if (button & Qt::MouseButton::BackButton)
2183 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
2188 SendMouseEvent(flags, event->pos(), isExtended);
2192void CBackendFreeRDP::mouseReleaseEvent(QMouseEvent *event)
2194 qDebug(logMouse) << Q_FUNC_INFO <<
event <<
event->buttons() <<
event->button();
2195 if(!m_pContext)
return;
2196 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2199 bool isExtended =
false;
2200 Qt::MouseButton button =
event->button();
2201 if (button & Qt::MouseButton::LeftButton)
2203 flags = PTR_FLAGS_BUTTON1;
2205 else if (button & Qt::MouseButton::MiddleButton)
2207 flags = PTR_FLAGS_BUTTON3;
2209 else if (button & Qt::MouseButton::RightButton)
2211 flags = PTR_FLAGS_BUTTON2;
2213 else if (button & Qt::MouseButton::ForwardButton)
2215 flags = PTR_XFLAGS_BUTTON2;
2218 else if (button & Qt::MouseButton::BackButton)
2220 flags = PTR_XFLAGS_BUTTON1;
2225 SendMouseEvent(flags, event->pos(), isExtended);
2229void CBackendFreeRDP::keyPressEvent(QKeyEvent *event)
2231 qDebug(logKey) << Q_FUNC_INFO << event;
2232 if(!m_pContext)
return;
2233 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2236 if(RDP_SCANCODE_UNKNOWN != k)
2237#if FREERDP_VERSION_MAJOR >= 3
2238 freerdp_input_send_keyboard_event_ex(
2239 m_pContext->Context.context.input,
true,
true, k);
2241 freerdp_input_send_keyboard_event_ex(
2242 m_pContext->Context.input,
true, k);
2246void CBackendFreeRDP::keyReleaseEvent(QKeyEvent *event)
2248 qDebug(logKey) << Q_FUNC_INFO << event;
2249 if(!m_pContext)
return;
2250 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2252 if(RDP_SCANCODE_UNKNOWN != k)
2253#if FREERDP_VERSION_MAJOR >= 3
2254 freerdp_input_send_keyboard_event_ex(
2255 m_pContext->Context.context.input,
false,
false, k);
2257 freerdp_input_send_keyboard_event_ex(
2258 m_pContext->Context.input,
false, k);
2262void CBackendFreeRDP::InputMethodEvent(QInputMethodEvent *event)
2264 qDebug(logKey) << Q_FUNC_INFO << event;
2265 if(!m_pContext)
return;
2266 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2267 QString szText =
event->commitString();
2268 if(szText.isEmpty())
2270 for(
int i = 0; i < szText.length(); i++) {
2271 QChar c = szText.at(i);
2272#if FREERDP_VERSION_MAJOR >= 3
2273 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.context.input, 0, (UINT16)c.unicode());
2275 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.input, 0, (UINT16)c.unicode());
2280int CBackendFreeRDP::RedirectionSound()
2282 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2283 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2284 rdpSettings* settings = instance->context->settings;
2287 if(m_pParameter->GetRedirectionSound()
2288 == CParameterFreeRDP::RedirecionSoundType::Disable)
2291 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE);
2292 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE);
2294 }
else if(m_pParameter->GetRedirectionSound()
2295 == CParameterFreeRDP::RedirecionSoundType::Local)
2297 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, TRUE);
2298 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
2299 }
else if(m_pParameter->GetRedirectionSound()
2300 == CParameterFreeRDP::RedirecionSoundType::Remote)
2302 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, TRUE);
2317 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"rdpsnd",
2318 m_pParameter->GetRedirectionSoundParameters().toStdString().c_str(),
2320 BOOL status = freerdp_client_add_static_channel(settings, count,
2321 #
if FREERDP_VERSION_MAJOR < 3
2329 status = freerdp_client_add_dynamic_channel(settings, count,
2330 #
if FREERDP_VERSION_MAJOR < 3
2340 qCritical(log) <<
"Load rdpsnd fail";
2347int CBackendFreeRDP::RedirectionMicrophone()
2349 if(m_pParameter->GetRedirectionSound()
2350 == CParameterFreeRDP::RedirecionSoundType::Remote)
2352 if(!m_pParameter->GetRedirectionMicrophone())
2355 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2356 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2358 rdpSettings* settings = instance->context->settings;
2361 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
2372 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"audin",
2373 m_pParameter->GetRedirectionMicrophoneParameters().toStdString().c_str(),
2375 BOOL status = freerdp_client_add_dynamic_channel(settings, count,
2376 #
if FREERDP_VERSION_MAJOR < 3
2385 qCritical(log) <<
"Load audin fail";
2392int CBackendFreeRDP::RedirectionDriver()
2394 QStringList lstDrives = m_pParameter->GetRedirectionDrives();
2395 if(lstDrives.isEmpty())
2398 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2399 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2400 rdpSettings* settings = instance->context->settings;
2403 foreach (
auto drive, lstDrives) {
2405 char* pDrive = _strdup(drive.toStdString().c_str());
2406 const char* argvDrive[] = {
"drive", pDrive};
2407 int count =
sizeof(argvDrive) /
sizeof(
const char*);
2408 BOOL status = freerdp_client_add_device_channel(settings, count,
2409 #
if FREERDP_VERSION_MAJOR < 3
2413 if(pDrive) free(pDrive);
2416 qCritical(log) <<
"Load drive fail";
2424int CBackendFreeRDP::RedirectionPrinter()
2426 if(!m_pParameter->GetRedirectionPrinter())
2429 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2430 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2431 rdpSettings* settings = instance->context->settings;
2434 QStringList printerList = QPrinterInfo::availablePrinterNames();
2435 if(printerList.isEmpty())
2437 qCritical(log) <<
"The printer is empty";
2440 qDebug(log) << printerList;
2443 const char* argvPrinter[] = {
"printer",
nullptr,
nullptr};
2444 int count =
sizeof(argvPrinter) /
sizeof(
const char*);
2445 BOOL status = freerdp_client_add_device_channel(settings, count,
2446 #
if FREERDP_VERSION_MAJOR < 3
2451 qCritical(log) <<
"Load printer fail";
2458int CBackendFreeRDP::RedirectionSerial()
2462 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2463 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2464 rdpSettings* settings = instance->context->settings;
2467 QList<QSerialPortInfo> lstSerial = QSerialPortInfo::availablePorts();
2470 foreach (
auto serial, lstSerial) {
2473 qDebug(log) <<
"systemLocation:" << serial.systemLocation()
2474 <<
"portName:" << serial.portName()
2475 <<
"serialNumber:" << serial.serialNumber();
2476 char* pSerial = _strdup(serial.systemLocation().toStdString().c_str());
2477 char* pName = _strdup(serial.portName().toStdString().c_str());
2478 const char* argvSerial[] = {
"serial", pName, pSerial};
2479 int count =
sizeof(argvSerial) /
sizeof(
const char*);
2480 BOOL status = freerdp_client_add_device_channel(settings, count,
2481 #
if FREERDP_VERSION_MAJOR < 3
2485 if(pSerial) free(pSerial);
2486 if(pName) free(pName);
2490 qCritical(log) <<
"Load drive fail";
2498void CBackendFreeRDP::slotConnectProxyServer(QString szHost, quint16 nPort)
2500 qDebug(log) <<
"Connect proxy server:" << szHost +
":" + QString::number(nPort);
2501 rdpContext* pContext = (rdpContext*)m_pContext;
2502 rdpSettings* settings = pContext->settings;
2504 qCritical(log) <<
"settings is null";
2507 freerdp_settings_set_string(
2508 settings, FreeRDP_ServerHostname,
2509 szHost.toStdString().c_str());
2510 freerdp_settings_set_uint32(
2511 settings, FreeRDP_ServerPort,
2514 int nRet = freerdp_client_start(pContext);
2517 qCritical(log) <<
"freerdp_client_start fail";
2519 qDebug(log) <<
"Connect proxy server:" << szHost +
":" + QString::number(nPort) <<
"end";
2523CBackendFreeRDP::OnInitReturnValue CBackendFreeRDP::InitSSHTunnelPipe()
2528 &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net,
this);
2530 return OnInitReturnValue::Fail;
2531 bool check = connect(m_pThreadSSH, SIGNAL(sigServer(QString, quint16)),
2532 this, SLOT(slotConnectProxyServer(QString, quint16)));
2534 check = connect(m_pThreadSSH, SIGNAL(
sigError(
int,QString)),
2535 this, SIGNAL(
sigError(
int,QString)));
2537 check = connect(m_pThreadSSH, SIGNAL(
sigStop()),
2540 m_pThreadSSH->start();
2541 return OnInitReturnValue::UseOnProcess;
2544int CBackendFreeRDP::CleanSSHTunnelPipe()
2548 m_pThreadSSH->Exit();
2549 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 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.