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.Backend")
65static Q_LOGGING_CATEGORY(logKey,
"FreeRDP.Backend.Key")
66static Q_LOGGING_CATEGORY(logInputMethod,
"FreeRDP.Backend.InputMethod")
67static Q_LOGGING_CATEGORY(logMouse,
"FreeRDP.Backend.Mouse")
71 , m_pOperate(pOperate)
73 , m_pParameter(
nullptr)
76 , m_writeEvent(
nullptr)
77#if FREERDP_VERSION_MAJOR >= 3
78 , m_pConnectLayer(
nullptr)
81 , m_pThreadSSH(
nullptr)
84 qDebug(log) << Q_FUNC_INFO;
85 m_pParameter = qobject_cast<CParameterFreeRDP*>(pOperate->GetParameter());
86 Q_ASSERT(m_pParameter);
89CBackendFreeRDP::~CBackendFreeRDP()
91 qDebug(log) << Q_FUNC_INFO;
102 qDebug(log) << Q_FUNC_INFO;
105 m_writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
107 qCritical(log) <<
"CreateEvent failed";
108 return OnInitReturnValue::Fail;
110 ZeroMemory(&m_ClientEntryPoints,
sizeof(RDP_CLIENT_ENTRY_POINTS));
111 m_ClientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
112 m_ClientEntryPoints.Size =
sizeof(RDP_CLIENT_ENTRY_POINTS);
114 m_ClientEntryPoints.GlobalInit = cbGlobalInit;
115 m_ClientEntryPoints.GlobalUninit = cbGlobalUninit;
116 m_ClientEntryPoints.ClientNew = cbClientNew;
117 m_ClientEntryPoints.ClientFree = cbClientFree;
118 m_ClientEntryPoints.ClientStart = cbClientStart;
119 m_ClientEntryPoints.ClientStop = cbClientStop;
122 auto pRdpContext = freerdp_client_context_new(&m_ClientEntryPoints);
126 m_pContext->pThis =
this;
128 qCritical(log) <<
"freerdp_client_context_new fail";
129 return OnInitReturnValue::Fail;
132 rdpSettings* settings = pRdpContext->settings;
134 qCritical(log) <<
"settings is null";
135 return OnInitReturnValue::Fail;
148 char* argv[]= {(
char*)QApplication::applicationFilePath().toStdString().c_str()};
149 int argc =
sizeof(argv) /
sizeof(
char*);
150 nRet = freerdp_client_settings_parse_command_line(settings, argc, argv, TRUE);
153 nRet = freerdp_client_settings_command_line_status_print(settings, nRet, argc, argv);
154 return OnInitReturnValue::Fail;
157#if FREERDP_VERSION_MAJOR >= 3
158 if (!stream_dump_register_handlers(pRdpContext,
159 CONNECTION_STATE_MCS_CREATE_REQUEST,
161 return OnInitReturnValue::Fail;
164 auto &user = m_pParameter->m_Net.m_User;
165 if(!user.GetUser().isEmpty())
166 freerdp_settings_set_string(
167 settings, FreeRDP_Username,
168 user.GetUser().toStdString().c_str());
169 if(!user.GetPassword().isEmpty()) {
170 freerdp_settings_set_string(
171 settings, FreeRDP_Password,
172 user.GetPassword().toStdString().c_str());
173 m_SecurityLevel |= CSecurityLevel::Level::Authentication;
176 freerdp_settings_set_bool(
177 settings, FreeRDP_RedirectClipboard, m_pParameter->GetClipboard());
179#if FREERDP_VERSION_MAJOR >= 3
180 bool bOnlyView = m_pParameter->GetOnlyView();
181 freerdp_settings_set_bool(
182 settings, FreeRDP_SuspendInput, bOnlyView);
185 freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
186 m_pParameter->GetDesktopWidth());
187 freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
188 m_pParameter->GetDesktopHeight());
189 freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth,
190 m_pParameter->GetColorDepth());
192 freerdp_settings_set_bool(settings, FreeRDP_UseMultimon,
193 m_pParameter->GetUseMultimon());
195 if(m_pParameter->GetReconnectInterval()) {
196 freerdp_settings_set_bool(
197 settings, FreeRDP_AutoReconnectionEnabled,
true);
198 freerdp_settings_set_uint32(
200 FreeRDP_AutoReconnectMaxRetries,
201 m_pParameter->GetReconnectInterval());
204 freerdp_settings_set_bool(
205 settings, FreeRDP_AutoReconnectionEnabled,
false);
209 RedirectionMicrophone();
211 RedirectionPrinter();
216 switch(m_pParameter->m_Proxy.GetUsedType())
218 case CParameterProxy::TYPE::System:
220 case CParameterProxy::TYPE::Http:
221 case CParameterProxy::TYPE::SockesV5:
224 if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_SOCKS))
225 return OnInitReturnValue::Fail;
226 if(CParameterProxy::TYPE::Http == m_pParameter->m_Proxy.GetUsedType()) {
227 net = &m_pParameter->m_Proxy.m_Http;
228 if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP))
229 return OnInitReturnValue::Fail;
232 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyHostname,
233 net->GetHost().toStdString().c_str()))
234 return OnInitReturnValue::Fail;
235 if (!freerdp_settings_set_uint16(settings, FreeRDP_ProxyPort, net->GetPort()))
236 return OnInitReturnValue::Fail;
238 if(((user.GetUsedType() == CParameterUser::TYPE::UserPassword)
239 && (user.GetPassword().isEmpty() || user.GetUser().isEmpty()))
240 || ((user.GetUsedType() == CParameterUser::TYPE::PublicKey)
241 && user.GetPassphrase().isEmpty())) {
242 int nRet = QDialog::Rejected;
244 if(QDialog::Accepted != nRet)
246 return OnInitReturnValue::Fail;
249 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyUsername,
250 user.GetUser().toStdString().c_str()))
251 return OnInitReturnValue::Fail;
252 if (!freerdp_settings_set_string(settings, FreeRDP_ProxyPassword,
253 user.GetPassword().toStdString().c_str()))
254 return OnInitReturnValue::Fail;
265 case CParameterProxy::TYPE::None:
267 if(!m_pParameter->GetDomain().isEmpty())
268 freerdp_settings_set_string(
269 settings, FreeRDP_Domain,
270 m_pParameter->GetDomain().toStdString().c_str());
271 if(m_pParameter->m_Net.GetHost().isEmpty())
274 szErr = tr(
"The server is empty, please input it");
275 qCritical(log) << szErr;
277 emit
sigError(-1, szErr.toStdString().c_str());
278 return OnInitReturnValue::Fail;
280 auto &net = m_pParameter->m_Net;
281 freerdp_settings_set_string(
282 settings, FreeRDP_ServerHostname,
283 net.GetHost().toStdString().c_str());
284 freerdp_settings_set_uint32(
285 settings, FreeRDP_ServerPort,
288 nRet = freerdp_client_start(pRdpContext);
291 qCritical(log) <<
"freerdp_client_start fail";
292 return OnInitReturnValue::Fail;
297 case CParameterProxy::TYPE::SSHTunnel:
299#if FREERDP_VERSION_MAJOR >= 3
301 if(!m_pConnectLayer)
return OnInitReturnValue::Fail;
302 nRet = m_pConnectLayer->Initialize(pRdpContext);
303 if(nRet)
return OnInitReturnValue::Fail;
306 return InitSSHTunnelPipe();
311 qCritical(log) <<
"Don't support proxy type:" << m_pParameter->m_Proxy.GetUsedType();
315 return OnInitReturnValue::UseOnProcess;
320 qDebug(log) << Q_FUNC_INFO;
324 CloseHandle(m_writeEvent);
325 m_writeEvent =
nullptr;
329 rdpContext* pRdpContext = (rdpContext*)m_pContext;
330 if(!freerdp_disconnect(pRdpContext->instance))
331 qCritical(log) <<
"freerdp_disconnect fail";
333 if(freerdp_client_stop(pRdpContext))
334 qCritical(log) <<
"freerdp_client_stop fail";
336 freerdp_client_context_free(pRdpContext);
337 m_pContext =
nullptr;
340#if FREERDP_VERSION_MAJOR >= 3
341 if(m_pConnectLayer) {
342 m_pConnectLayer->Clean();
343 m_pConnectLayer->deleteLater();
344 m_pConnectLayer =
nullptr;
349 CleanSSHTunnelPipe();
392 rdpContext* pRdpContext = (rdpContext*)m_pContext;
394 if(
nullptr == freerdp_settings_get_string(pRdpContext->settings, FreeRDP_ServerHostname))
402 nCount += freerdp_get_event_handles(pRdpContext, &handles[nCount],
403 ARRAYSIZE(handles) - nCount);
406 qCritical(log) <<
"freerdp_get_event_handles failed";
412 handles[nCount++] = m_writeEvent;
414 DWORD waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, nTimeout);
417 ResetEvent(m_writeEvent);
419 if (waitStatus == WAIT_FAILED)
421 qCritical(log) <<
"WaitForMultipleObjects: WAIT_FAILED";
426 if(waitStatus == WAIT_TIMEOUT)
433 if (!freerdp_check_event_handles(pRdpContext))
437 UINT32 err = freerdp_get_last_error(pRdpContext);
439 szErr =
"freerdp_check_event_handles fail.";
441 szErr += QString::number(err);
443 szErr += freerdp_get_last_error_category(err);
445 szErr += freerdp_get_last_error_name(err);
447 szErr += freerdp_get_last_error_string(err);
448 qCritical(log) << szErr;
472#if FREERDP_VERSION_MAJOR >= 3
473 if(freerdp_shall_disconnect_context(pRdpContext))
475 if(freerdp_shall_disconnect(pRdpContext->instance))
478 qCritical(log) <<
"freerdp_shall_disconnect false";
488 qDebug(log) << Q_FUNC_INFO;
489 if(m_pParameter && m_pParameter->GetOnlyView())
return;
490 if(m_pParameter->GetClipboard())
491 m_ClipBoard.slotClipBoardChanged();
494BOOL CBackendFreeRDP::cbGlobalInit()
496 qDebug(log) << Q_FUNC_INFO;
500void CBackendFreeRDP::cbGlobalUninit()
502 qDebug(log) << Q_FUNC_INFO;
505BOOL CBackendFreeRDP::cbClientNew(freerdp *instance, rdpContext *context)
507 qDebug(log) << Q_FUNC_INFO;
510 instance->PostDisconnect = cb_post_disconnect;
513#if FREERDP_VERSION_MAJOR < 3
514 instance->Authenticate = cb_authenticate;
515 instance->GatewayAuthenticate = cb_GatewayAuthenticate;
517 instance->AuthenticateEx = cb_authenticate_ex;
518 instance->ChooseSmartcard = cb_choose_smartcard;
523 instance->PresentGatewayMessage = cb_present_gateway_message;
525 instance->LogonErrorInfo = cb_logon_error_info;
530void CBackendFreeRDP::cbClientFree(freerdp *instance, rdpContext *context)
532 qDebug(log) << Q_FUNC_INFO;
535int CBackendFreeRDP::cbClientStart(rdpContext *context)
537 qDebug(log) << Q_FUNC_INFO;
540 if (!context || !context->settings)
542 freerdp* instance = freerdp_client_get_instance(context);
546 auto settings = context->settings;
548 QString szDomainHost;
550 szDomainHost = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
551 nPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
553 auto &net = pThis->m_pParameter->m_Net;
554 szServer = net.GetHost() +
":" + QString::number(net.GetPort());
555 auto &proxy = pThis->m_pParameter->m_Proxy;
556 switch(proxy.GetUsedType()) {
557 case CParameterProxy::TYPE::SockesV5:
559 auto &sockesV5 = proxy.m_SockesV5;
560 szServer = sockesV5.GetHost() +
":" + QString::number(sockesV5.GetPort())
564 case CParameterProxy::TYPE::Http:
566 auto &http = proxy.m_Http;
567 szServer = http.GetHost() +
":" + QString::number(http.GetPort())
571 case CParameterProxy::TYPE::SSHTunnel:
573 auto &sshNet = proxy.m_SSH.m_Net;
574#if FREERDP_VERSION_MAJOR < 3
575 szServer = szDomainHost +
":" + QString::number(nPort)
576 +
" -> " + sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
579 szServer = sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
588 BOOL status = freerdp_connect(instance);
590 QString szInfo = tr(
"Connected to ") + szServer;
591 qInfo(log) << szInfo;
596 UINT32 nRet = freerdp_get_last_error(context);
599 szErr = tr(
"Connect to ") + szServer + tr(
" fail.");
601 szErr += QString::number(nRet) +
" - ";
602 szErr += freerdp_get_last_error_name(nRet);
607 szErr += freerdp_get_last_error_string(nRet);
611 case FREERDP_ERROR_CONNECT_LOGON_FAILURE:
613 szErr = tr(
"Logon to ") + szServer;
614 szErr += tr(
" fail. Please check that the username and password are correct.") +
"\n";
617 case FREERDP_ERROR_CONNECT_WRONG_PASSWORD:
619 szErr = tr(
"Logon to ") + szServer;
620 szErr += tr(
" fail. Please check password are correct.") +
"\n";
623 case FREERDP_ERROR_AUTHENTICATION_FAILED:
625 szErr = tr(
"Logon to ") + szServer;
626 szErr += tr(
" authentication fail. please add a CA certificate to the store.") +
"\n";
629 case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED:
631 szErr = tr(
"Logon to ") + szServer;
632 szErr += tr(
" connect transport layer fail.") +
"\n\n";
633 szErr += tr(
"Please:") +
"\n";
634 szErr += tr(
"1. Check for any network related issues") +
"\n";
635 szErr += tr(
"2. Check you have proper security settings ('NLA' enabled is required for most connections nowadays)") +
"\n";
636 szErr +=
" " + tr(
"If you do not know the server security settings, contact your server administrator.") +
"\n";
637 szErr += tr(
"3. Check the certificate is proper (and guacd properly checks that)") +
"\n";
640 case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED:
642 szErr += tr(
"Please check you have proper security settings.") +
"\n";
643 szErr += tr(
"If you do not know the server security settings, contact your server administrator.");
645 case FREERDP_ERROR_CONNECT_CANCELLED:
646 szErr = tr(
"The connect was canceled.") +
"\n\n" + szErr;
653 qCritical(log) << szErr;
654 emit pThis->
sigError(nRet, szErr.toStdString().c_str());
660int CBackendFreeRDP::cbClientStop(rdpContext *context)
663 qDebug(log) << Q_FUNC_INFO;
664#if FREERDP_VERSION_MAJOR >= 3
665 nRet = freerdp_client_common_stop(context);
667 BOOL bRet = freerdp_abort_connect(context->instance);
669 { qCritical(log) <<
"freerdp_abort_connect fail";
696 qDebug(log) << Q_FUNC_INFO;
697 rdpChannels* channels =
nullptr;
698 rdpSettings* settings =
nullptr;
699 rdpContext* context = instance->context;
701 if (!instance || !instance->context || !instance->context->settings)
705 if(!pThis)
return FALSE;
706 settings = instance->context->settings;
707 channels = context->channels;
709 if(!channels || !pParameter)
713#if defined (Q_OS_WIN)
714 if (!freerdp_settings_set_uint32(
715 settings, FreeRDP_OsMajorType, OSMAJORTYPE_WINDOWS))
717 if (!freerdp_settings_set_uint32(
718 settings, FreeRDP_OsMinorType, OSMINORTYPE_WINDOWS_NT))
720#elif defined(Q_OS_ANDROID)
721 if (!freerdp_settings_set_uint32(
722 settings, FreeRDP_OsMajorType, OSMAJORTYPE_ANDROID))
724 if (!freerdp_settings_set_uint32(
725 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
727#elif defined(Q_OS_IOS)
728 if (!freerdp_settings_set_uint32(
729 settings, FreeRDP_OsMajorType, OSMAJORTYPE_IOS))
731 if (!freerdp_settings_set_uint32(
732 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
734#elif defined (Q_OS_UNIX)
735 if (!freerdp_settings_set_uint32(
736 settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX))
738 if (!freerdp_settings_set_uint32(
739 settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_XSERVER))
742 if (!freerdp_settings_set_uint32(
743 settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNSPECIFIED))
745 if (!freerdp_settings_set_uint32(
746 settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
751 PubSub_SubscribeChannelConnected(instance->context->pubSub,
752 OnChannelConnectedEventHandler);
753 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
754 OnChannelDisconnectedEventHandler);
756#if FREERDP_VERSION_MAJOR < 3
757 if (!freerdp_client_load_addins(channels, instance->context->settings))
760 #if defined(Q_OS_LINUX) || (defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE))
761 if (!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, TRUE))
766 if(!freerdp_settings_set_bool(
767 settings, FreeRDP_NegotiateSecurityLayer,
768 pParameter->GetNegotiateSecurityLayer()))
770 CParameterFreeRDP::Security security = pParameter->GetSecurity();
772 if(!freerdp_settings_set_bool(
773 settings, FreeRDP_RdpSecurity,
774 CParameterFreeRDP::Security::RDP & security))
776 if (!freerdp_settings_set_bool(
777 settings, FreeRDP_UseRdpSecurityLayer,
778 CParameterFreeRDP::Security::RDP & security))
781 if(!freerdp_settings_set_bool(
782 settings, FreeRDP_TlsSecurity,
783 CParameterFreeRDP::Security::TLS & security))
785 if(!freerdp_settings_set_bool(
786 settings, FreeRDP_NlaSecurity,
787 CParameterFreeRDP::Security::NLA & security))
789 if(!freerdp_settings_set_bool(
790 settings, FreeRDP_ExtSecurity,
791 CParameterFreeRDP::Security::NLA_Ext & security))
793#if FREERDP_VERSION_MAJOR >= 3
794 if(!freerdp_settings_set_bool(
795 settings, FreeRDP_AadSecurity,
796 CParameterFreeRDP::Security::RDSAAD & security))
798 if(!freerdp_settings_set_bool(
799 settings, FreeRDP_RdstlsSecurity,
800 CParameterFreeRDP::Security::RDSTLS & security))
802 freerdp_settings_set_uint16(settings, FreeRDP_TLSMinVersion,
803 pParameter->GetTlsVersion());
807 if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly))
810 auto &user = pParameter->m_Net.
m_User;
811 if(!freerdp_settings_get_string(settings, FreeRDP_Username)) {
812 if(user.GetUser().isEmpty()) {
814 qWarning(log) <<
"Auth-only, but no user name set. Will be call instance->Authenticate.";
816 freerdp_settings_set_string(
817 settings, FreeRDP_Username,
818 user.GetUser().toStdString().c_str());
820 if (!freerdp_settings_get_string(settings, FreeRDP_Password)) {
821 if (user.GetPassword().isEmpty()) {
823 qWarning(log) <<
"auth-only, but no password set. Will be call instance->Authenticate";
825 freerdp_settings_set_string(
826 settings, FreeRDP_Password,
827 user.GetPassword().toStdString().c_str());
829#if FREERDP_VERSION_MAJOR >= 3
830 if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE))
833 }
else if(freerdp_settings_get_bool(settings, FreeRDP_CredentialsFromStdin)){
835 }
else if(freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon)) {
846 UINT32 width = pParameter->GetDesktopWidth();
847 UINT32 height = pParameter->GetDesktopHeight();
848 if ((width < 64) || (height < 64) ||
849 (width > 4096) || (height > 4096))
851 QString szErr = tr(
"Invalid dimensions:")
852 + QString::number(width)
853 +
"*" + QString::number(height);
854 qCritical(log) << szErr;
858 qInfo(log) <<
"Init desktop size " << width <<
"*" << height;
862 <<
"width:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)
863 <<
"height:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)
864 <<
"ColorDepth:" << freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
875 if(!freerdp_set_connection_type(settings, pParameter->GetConnectType()))
877 freerdp_settings_set_uint32(
878 settings, FreeRDP_PerformanceFlags, pParameter->GetPerformanceFlags());
879 freerdp_performance_flags_split(settings);
881 freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, pParameter->GetEnableLocalInputMethod());
885const char* CBackendFreeRDP::GetTitle(freerdp* instance)
887 const char* windowTitle;
890 const char* name =
nullptr;
893 rdpSettings* settings = instance->context->settings;
898 windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
902#if FREERDP_VERSION_MAJOR >= 3
903 name = freerdp_settings_get_server_name(settings);
905 name = pThis->m_pParameter->m_Net.GetHost().toStdString().c_str();
907 port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
909 addPort = (port != 3389);
911 char buffer[MAX_PATH + 64] = { 0 };
914 sprintf_s(buffer,
sizeof(buffer),
"%s", name);
916 sprintf_s(buffer,
sizeof(buffer),
"%s:%" PRIu32, name, port);
918 freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer);
919 return freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
929 qDebug(log) << Q_FUNC_INFO;
931 rdpContext* context = instance->context;
932 rdpSettings* settings = instance->context->settings;
933 rdpUpdate* update = instance->context->update;
934 CBackendFreeRDP* pThis = ((
ClientContext*)instance->context)->pThis;
936 const char* pWindowTitle = GetTitle(instance);
939 WCHAR* windowTitle = NULL;
940#if FREERDP_VERSION_MAJOR >= 3
941 windowTitle = ConvertUtf8ToWCharAlloc(pWindowTitle, NULL);
943 ConvertToUnicode(CP_UTF8, 0, pWindowTitle, -1, &windowTitle, 0);
947 QString title = QString::fromUtf16((
const char16_t*)windowTitle);
949 if(pThis->m_pParameter->GetServerName().isEmpty())
950 emit pThis->sigServerName(title);
954 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
955 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
956 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
958 if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
961 if(!pThis->CreateImage(instance->context))
964 Q_ASSERT(instance->context->cache);
967 if(pThis->m_Cursor.RegisterPointer(context->graphics))
970 update->BeginPaint = cb_begin_paint;
971 update->EndPaint = cb_end_paint;
972 update->DesktopResize = cb_desktop_resize;
974 update->PlaySound = cb_play_bell_sound;
976 update->SetKeyboardIndicators = cb_keyboard_set_indicators;
977 update->SetKeyboardImeStatus = cb_keyboard_set_ime_status;
983void CBackendFreeRDP::cb_post_disconnect(freerdp* instance)
985 qDebug(log) << Q_FUNC_INFO;
986 rdpContext* context =
nullptr;
988 if (!instance || !instance->context)
991 context = instance->context;
993 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
994 OnChannelConnectedEventHandler);
995 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
996 OnChannelDisconnectedEventHandler);
1000int CBackendFreeRDP::cb_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
1002 CBackendFreeRDP* pThis = ((
ClientContext*)instance->context)->pThis;
1003 const char* str_data = freerdp_get_logon_error_info_data(data);
1004 const char* str_type = freerdp_get_logon_error_info_type(type);
1005 QString szErr = tr(
"FreeRDP logon info: [");
1009 qDebug(log) << szErr;
1015void CBackendFreeRDP::OnChannelConnectedEventHandler(
void *context,
1016 #
if FREERDP_VERSION_MAJOR >= 3
1019 ChannelConnectedEventArgs *e)
1021 rdpContext* pContext = (rdpContext*)context;
1023 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
1024 qDebug(log) <<
"channel" << e->name <<
"connected";
1025 pThis->m_ClipBoard.Init((CliprdrClientContext*)e->pInterface,
1026 pThis->m_pParameter->GetClipboard());
1028#if FREERDP_VERSION_MAJOR >= 3
1030 freerdp_client_OnChannelConnectedEventHandler(pContext, e);
1032 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
1034 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
1035 rdpGdi* gdi = pContext->gdi;
1037 gdi_graphics_pipeline_init(gdi, (RdpgfxClientContext*) e->pInterface);
1040 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
1042 else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
1044 gdi_video_geometry_init(pContext->gdi, (GeometryClientContext*)e->pInterface);
1046 else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
1048 gdi_video_data_init(pContext->gdi, (VideoClientContext*)e->pInterface);
1050 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"connected but we can’t use it";
1054void CBackendFreeRDP::OnChannelDisconnectedEventHandler(
void *context,
1055 #
if FREERDP_VERSION_MAJOR >= 3
1058 ChannelDisconnectedEventArgs *e)
1060 rdpContext* pContext = (rdpContext*)context;
1063 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
1064 qDebug(log) <<
"channel" << e->name <<
"disconnected";
1065 pThis->m_ClipBoard.UnInit((CliprdrClientContext*)e->pInterface,
1066 pThis->m_pParameter->GetClipboard());
1068#if FREERDP_VERSION_MAJOR >= 3
1070 freerdp_client_OnChannelDisconnectedEventHandler(pContext, e);
1072 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
1074 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
1075 rdpGdi* gdi = pContext->gdi;
1076 gdi_graphics_pipeline_uninit(gdi, (RdpgfxClientContext*) e->pInterface);
1079 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
1082 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"disconnected but we can’t use it";
1087UINT32 CBackendFreeRDP::GetImageFormat(QImage::Format format)
1090#if (QT_VERSION >= QT_VERSION_CHECK(5,2,0))
1091 case QImage::Format_RGBA8888:
1092 return PIXEL_FORMAT_RGBA32;
1093 case QImage::Format_RGBX8888:
1094 return PIXEL_FORMAT_RGBX32;
1096 case QImage::Format_RGB16:
1097 return PIXEL_FORMAT_RGB16;
1098 case QImage::Format_ARGB32:
1099 return PIXEL_FORMAT_BGRA32;
1100 case QImage::Format_RGB32:
1101 return PIXEL_FORMAT_BGRA32;
1108UINT32 CBackendFreeRDP::GetImageFormat()
1110 return GetImageFormat(m_Image.format());
1113BOOL CBackendFreeRDP::CreateImage(rdpContext *context)
1117 CBackendFreeRDP* pThis = pContext->pThis;
1118 rdpGdi* gdi = context->gdi;
1119 Q_ASSERT(pThis && gdi);
1120 pThis->m_Image = QImage(gdi->primary_buffer,
1121 static_cast<int>(gdi->width),
1122 static_cast<int>(gdi->height),
1123 QImage::Format_ARGB32);
1127#if FREERDP_VERSION_MAJOR >= 3
1129static CREDUI_INFOW wfUiInfo = {
sizeof(CREDUI_INFOW), NULL, L
"Enter your credentials",
1130 L
"Remote Desktop Security", NULL };
1133BOOL CBackendFreeRDP::cb_authenticate_ex(freerdp* instance,
1134 char** username,
char** password,
1135 char** domain, rdp_auth_reason reason)
1137 qDebug(log) << Q_FUNC_INFO <<
"reason:" << reason;
1141 if(!username || !password || !domain)
return FALSE;
1143 return cb_authenticate(instance, username, password, domain);
1144 rdpContext* pContext = (rdpContext*)instance->context;
1149 WCHAR UserNameW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1150 WCHAR UserW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1151 WCHAR DomainW[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1152 WCHAR PasswordW[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 };
1154 WINPR_ASSERT(instance);
1155 WINPR_ASSERT(instance->context);
1156 WINPR_ASSERT(instance->context->settings);
1158 WINPR_ASSERT(username);
1159 WINPR_ASSERT(domain);
1160 WINPR_ASSERT(password);
1162 const WCHAR auth[] = L
"Target credentials requested";
1163 const WCHAR authPin[] = L
"PIN requested";
1164 const WCHAR gwAuth[] = L
"Gateway credentials requested";
1165 const WCHAR* titleW = auth;
1168 dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
1169 CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1176 if ((*username) && (*password))
1179 case AUTH_SMARTCARD_PIN:
1180 dwFlags &= ~CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1181 dwFlags |= CREDUI_FLAGS_PASSWORD_ONLY_OK | CREDUI_FLAGS_KEEP_USERNAME;
1186 *username = _strdup(
"PIN");
1199 ConvertUtf8ToWChar(*username, UserNameW, ARRAYSIZE(UserNameW));
1200 ConvertUtf8ToWChar(*username, UserW, ARRAYSIZE(UserW));
1204 ConvertUtf8ToWChar(*password, PasswordW, ARRAYSIZE(PasswordW));
1207 ConvertUtf8ToWChar(*domain, DomainW, ARRAYSIZE(DomainW));
1209 if (_wcsnlen(PasswordW, ARRAYSIZE(PasswordW)) == 0)
1211 status = CredUIPromptForCredentialsW(&wfUiInfo, titleW, NULL, 0, UserNameW,
1212 ARRAYSIZE(UserNameW), PasswordW,
1213 ARRAYSIZE(PasswordW), &fSave, dwFlags);
1214 if (status != NO_ERROR)
1217 "CredUIPromptForCredentials unexpected status: 0x%08lX",
1222 if ((dwFlags & CREDUI_FLAGS_KEEP_USERNAME) == 0)
1224 status = CredUIParseUserNameW(UserNameW, UserW, ARRAYSIZE(UserW), DomainW,
1225 ARRAYSIZE(DomainW));
1226 if (status != NO_ERROR)
1228 CHAR User[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1229 CHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1230 CHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1232 ConvertWCharNToUtf8(UserNameW, ARRAYSIZE(UserNameW), UserName, ARRAYSIZE(UserName));
1233 ConvertWCharNToUtf8(UserW, ARRAYSIZE(UserW), User, ARRAYSIZE(User));
1234 ConvertWCharNToUtf8(DomainW, ARRAYSIZE(DomainW), Domain, ARRAYSIZE(Domain));
1236 "Failed to parse UserName: %s into User: %s Domain: %s",
1237 UserName, User, Domain);
1243 *username = ConvertWCharNToUtf8Alloc(UserW, ARRAYSIZE(UserW), NULL);
1246 qCritical(log) <<
"ConvertWCharNToUtf8Alloc failed" << status;
1250 if (_wcsnlen(DomainW, ARRAYSIZE(DomainW)) > 0)
1251 *domain = ConvertWCharNToUtf8Alloc(DomainW, ARRAYSIZE(DomainW), NULL);
1253 *domain = _strdup(
"\0");
1258 qCritical(log) <<
"strdup failed" << status;
1262 *password = ConvertWCharNToUtf8Alloc(PasswordW, ARRAYSIZE(PasswordW), NULL);
1271 return cb_authenticate(instance, username, password, domain);
1276BOOL CBackendFreeRDP::cb_choose_smartcard(freerdp* instance,
1277 SmartcardCertInfo** cert_list,
1279 DWORD* choice, BOOL gateway)
1281 rdpContext* pContext = (rdpContext*)instance->context;
1283 QString msg(
"Multiple smartcards are available for use:\n");
1284 for (DWORD i = 0; i < count; i++)
1286 const SmartcardCertInfo* cert = cert_list[i];
1287 char* reader = ConvertWCharToUtf8Alloc(cert->reader, NULL);
1288 char* container_name = ConvertWCharToUtf8Alloc(cert->containerName, NULL);
1290 msg += QString::number(i) +
" ";
1291 msg += QString(container_name) +
"\n\t";
1292 msg +=
"Reader: " + QString(reader) +
"\n\t";
1293 msg +=
"User: " + QString(cert->userHint) + +
"@" + QString(cert->domainHint) +
"\n\t";
1294 msg +=
"Subject: " + QString(cert->subject) +
"\n\t";
1295 msg +=
"Issuer: " + QString(cert->issuer) +
"\n\t";
1296 msg +=
"UPN: " + QString(cert->upn) +
"\n";
1299 free(container_name);
1302 msg +=
"\nChoose a smartcard to use for ";
1304 msg +=
"gateway authentication";
1308 msg +=
"(0 - " + QString::number(count - 1) +
")";
1316 int n = num.toInt(&ok);
1326#ifdef WITH_WINDOWS_CERT_STORE
1334static void wf_report_error(
char* wszMessage, DWORD dwErrCode)
1336 LPSTR pwszMsgBuf = NULL;
1338 if (NULL != wszMessage && 0 != *wszMessage)
1340 WLog_ERR(TAG,
"%s", wszMessage);
1343 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1348 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1358 if (NULL != pwszMsgBuf)
1360 WLog_ERR(TAG,
"Error: 0x%08x (%d) %s", dwErrCode, dwErrCode, pwszMsgBuf);
1361 LocalFree(pwszMsgBuf);
1365 WLog_ERR(TAG,
"Error: 0x%08x (%d)", dwErrCode, dwErrCode);
1369static DWORD wf_is_x509_certificate_trusted(
const char* common_name,
const char* subject,
1370 const char* issuer,
const char* fingerprint)
1372 HRESULT hr = CRYPT_E_NOT_FOUND;
1374 DWORD dwChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
1375 PCCERT_CONTEXT pCert = NULL;
1376 HCERTCHAINENGINE hChainEngine = NULL;
1377 PCCERT_CHAIN_CONTEXT pChainContext = NULL;
1379 CERT_ENHKEY_USAGE EnhkeyUsage = { 0 };
1380 CERT_USAGE_MATCH CertUsage = { 0 };
1381 CERT_CHAIN_PARA ChainPara = { 0 };
1382 CERT_CHAIN_POLICY_PARA ChainPolicy = { 0 };
1383 CERT_CHAIN_POLICY_STATUS PolicyStatus = { 0 };
1384 CERT_CHAIN_ENGINE_CONFIG EngineConfig = { 0 };
1386 DWORD derPubKeyLen = WINPR_ASSERTING_INT_CAST(uint32_t, strlen(fingerprint));
1387 char* derPubKey = calloc(derPubKeyLen,
sizeof(
char));
1388 if (NULL == derPubKey)
1390 WLog_ERR(TAG,
"Could not allocate derPubKey");
1397 if (!CryptStringToBinaryA(fingerprint, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen,
1400 WLog_ERR(TAG,
"CryptStringToBinary failed. Err: %d", GetLastError());
1407 EnhkeyUsage.cUsageIdentifier = 0;
1408 EnhkeyUsage.rgpszUsageIdentifier = NULL;
1410 CertUsage.dwType = USAGE_MATCH_TYPE_AND;
1411 CertUsage.Usage = EnhkeyUsage;
1413 ChainPara.cbSize =
sizeof(ChainPara);
1414 ChainPara.RequestedUsage = CertUsage;
1416 ChainPolicy.cbSize =
sizeof(ChainPolicy);
1418 PolicyStatus.cbSize =
sizeof(PolicyStatus);
1420 EngineConfig.cbSize =
sizeof(EngineConfig);
1421 EngineConfig.dwUrlRetrievalTimeout = 0;
1423 pCert = CertCreateCertificateContext(X509_ASN_ENCODING, derPubKey, derPubKeyLen);
1426 WLog_ERR(TAG,
"FAILED: Certificate could not be parsed.");
1430 dwChainFlags |= CERT_CHAIN_ENABLE_PEER_TRUST;
1439 if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
1441 hr = HRESULT_FROM_WIN32(GetLastError());
1448 if (!CertGetCertificateChain(hChainEngine,
1459 hr = HRESULT_FROM_WIN32(GetLastError());
1466 if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE,
1471 hr = HRESULT_FROM_WIN32(GetLastError());
1475 if (PolicyStatus.dwError != S_OK)
1477 wf_report_error(
"CertVerifyCertificateChainPolicy: Chain Status", PolicyStatus.dwError);
1478 hr = PolicyStatus.dwError;
1484 if (PolicyStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
1485 PolicyStatus.dwError == CRYPT_E_REVOCATION_OFFLINE)
1493 WLog_INFO(TAG,
"CertVerifyCertificateChainPolicy succeeded for %s (%s) issued by %s",
1494 common_name, subject, issuer);
1501 WLog_INFO(TAG,
"CertVerifyCertificateChainPolicy failed for %s (%s) issued by %s",
1502 common_name, subject, issuer);
1503 wf_report_error(NULL, hr);
1508 if (NULL != pChainContext)
1510 CertFreeCertificateChain(pChainContext);
1513 if (NULL != hChainEngine)
1515 CertFreeCertificateChainEngine(hChainEngine);
1520 CertFreeCertificateContext(pCert);
1529BOOL CBackendFreeRDP::cb_authenticate(freerdp* instance,
char** username,
1530 char** password,
char** domain)
1532 qDebug(log) << Q_FUNC_INFO;
1535 rdpContext* pContext = (rdpContext*)instance->context;
1537 if(!username || !password || !domain)
return FALSE;
1538 if(*username && *password )
return TRUE;
1540 int nRet = QDialog::Rejected;
1542 nRet, pThis->m_pParameter);
1543 if(QDialog::Accepted == nRet)
1545 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1546 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1547 QString szDomain = pThis->m_pParameter->GetDomain();
1548 if(!szDomain.isEmpty() && domain)
1549 *domain = _strdup(szDomain.toStdString().c_str());
1550 if(!szName.isEmpty() && username)
1551 *username = _strdup(szName.toStdString().c_str());
1553 *password = _strdup(szPassword.toStdString().c_str());
1554 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
1562BOOL CBackendFreeRDP::cb_GatewayAuthenticate(freerdp *instance,
1563 char **username,
char **password,
char **domain)
1565 qDebug(log) << Q_FUNC_INFO;
1569 rdpContext* pContext = (rdpContext*)instance->context;
1571 if(!username || !password || !domain)
return FALSE;
1572 if(*username && *password )
return TRUE;
1574 int nRet = QDialog::Rejected;
1575 emit pThis->
sigBlockShowWidget(
"CDlgGetUserPasswordFreeRDP", nRet, pThis->m_pParameter);
1576 if(QDialog::Accepted == nRet)
1578 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1579 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1580 QString szDomain = pThis->m_pParameter->GetDomain();
1581 if(!szDomain.isEmpty() && domain)
1582 *domain = _strdup(szDomain.toStdString().c_str());
1583 if(!szName.isEmpty() && username)
1584 *username = _strdup(szName.toStdString().c_str());
1586 *password = _strdup(szPassword.toStdString().c_str());
1587 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
1589 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1597 const BYTE* data,
size_t length,
1598 const char* hostname, UINT16 port, DWORD flags)
1600 qDebug(log) << Q_FUNC_INFO;
1601 rdpContext* pContext = (rdpContext*)instance->context;
1602 QSslCertificate cert(QByteArray((
const char*)data, length));
1603#if FREERDP_VERSION_MAJOR >= 3
1607 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM) {
1609 instance, hostname, port,
1610 cert.issuerDisplayName().toStdString().c_str(),
1611 cert.subjectDisplayName().toStdString().c_str(),
1612 cert.issuerDisplayName().toStdString().c_str(),
1618 instance, hostname, port,
1619 cert.issuerDisplayName().toStdString().c_str(),
1620 cert.subjectDisplayName().toStdString().c_str(),
1621 cert.issuerDisplayName().toStdString().c_str(),
1622 cert.serialNumber().toStdString().c_str(),
1626static QString pem_cert_fingerprint(
const char* pem, DWORD flags)
1628 QString szFingerPrint;
1629#if FREERDP_VERSION_MAJOR >= 3
1633 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM)
1635 rdpCertificate* cert = freerdp_certificate_new_from_pem(pem);
1639 char* fp = freerdp_certificate_get_fingerprint(cert);
1640 char* start = freerdp_certificate_get_validity(cert, TRUE);
1641 char* end = freerdp_certificate_get_validity(cert, FALSE);
1642 freerdp_certificate_free(cert);
1644 szFingerPrint = QObject::tr(
"Valid from: ") + QString(start) +
"\n";
1645 szFingerPrint += QObject::tr(
"Valid to: ") + QString(end) +
"\n";
1646 szFingerPrint += QObject::tr(
"Fingerprint: ") + QString(fp) +
"\n";
1653 szFingerPrint = QObject::tr(
"Fingerprint: ") + QString(pem) +
"\n";
1654 return szFingerPrint;
1673 const char *host, UINT16 port,
1674 const char *common_name,
const char *subject,
1675 const char *issuer,
const char *fingerprint, DWORD flags)
1677 qDebug(log) << Q_FUNC_INFO;
1679 rdpContext* pContext = (rdpContext*)instance->context;
1686 emit pThis->sigServerName(common_name);
1690 pThis->m_SecurityLevel |= CSecurityLevel::Level::SecureChannel;
1691 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1692 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1693 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1694 pThis->m_SecurityLevel |= CSecurityLevel::Level::Redirect;
1696 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1702#if FREERDP_VERSION_MAJOR >= 3
1703#if defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE)
1704 if (flags & VERIFY_CERT_FLAG_FP_IS_PEM && !(flags & VERIFY_CERT_FLAG_MISMATCH))
1706 if (wf_is_x509_certificate_trusted(common_name, subject, issuer, fingerprint) == S_OK)
1714 QString szType = tr(
"RDP-Server");
1715 if (flags & VERIFY_CERT_FLAG_GATEWAY) {
1716 szType = tr(
"RDP-Gateway");
1718 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1719 szType = tr(
"RDP-Redirect");
1721 QString title(tr(
"Verify certificate"));
1724 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1725 message += tr(
"Common name: ") + common_name +
"\n";
1726 message += tr(
"Subject: ") + subject +
"\n";
1727 message += tr(
"Issuer: ") + issuer +
"\n";
1728 message += pem_cert_fingerprint(fingerprint, flags);
1730 if(VERIFY_CERT_FLAG_CHANGED & flags) {
1731 message += tr(
"The above X.509 certificate is changed.\n"
1732 "It is possible that the server has changed its certificate, "
1733 "or Maybe it was attacked."
1734 "Please look at the OpenSSL documentation on "
1735 "how to add a private CA to the store.");
1737 message += tr(
"The above X.509 certificate could not be verified.\n"
1738 "Possibly because you do not have the CA certificate "
1739 "in your certificate store, or the certificate has expired.\n"
1740 "Please look at the OpenSSL documentation on "
1741 "how to add a private CA to the store.");
1745 message += tr(
"Yes - trusted") +
"\n";
1746 message += tr(
"Ignore - temporary trusted") +
"\n";
1747 message += tr(
"No - no trusted") +
"\n";
1749 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1750 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1751 bool bCheckBox =
false;
1753 tr(
"Don't show again"));
1754 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1760 case QMessageBox::StandardButton::Yes:
1762 case QMessageBox::StandardButton::Ignore:
1790 const char *host, UINT16 port,
1791 const char *common_name,
const char *subject,
1792 const char *issuer,
const char *fingerprint,
1793 const char *old_subject,
const char *old_issuer,
1794 const char *old_fingerprint, DWORD flags)
1796 qDebug(log) << Q_FUNC_INFO;
1797 rdpContext* pContext = (rdpContext*)instance->context;
1800 emit pThis->sigServerName(common_name);
1803 pThis->m_SecurityLevel |= CSecurityLevel::Level::SecureChannel;
1804 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1805 pThis->m_SecurityLevel |= CSecurityLevel::Level::Gateway;
1806 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1807 pThis->m_SecurityLevel |= CSecurityLevel::Level::Redirect;
1809 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1815 QString szType = tr(
"RDP-Server");
1816 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1817 szType = tr(
"RDP-Gateway");
1818 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1819 szType = tr(
"RDP-Redirect");
1821 QString title(tr(
"Verify changed certificate"));
1823 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1824 message += tr(
"New Certificate details:") +
"\n";
1825 message +=
" " + tr(
"name: ") + common_name +
"\n";
1826 message +=
" " + tr(
"subject: ") + subject +
"\n";
1827 message +=
" " + tr(
"issuer: ") + issuer +
"\n";
1828 message +=
" " + pem_cert_fingerprint(fingerprint, flags) +
"\n";
1829 message += tr(
"Old Certificate details:") +
"\n";
1830 message +=
" " + tr(
"subject: ") + old_subject +
"\n";
1831 message +=
" " + tr(
"issuer: ") + old_issuer +
"\n";
1832 message +=
" " + pem_cert_fingerprint(old_fingerprint, flags) +
"\n";
1834 message += tr(
"The above X.509 certificate could not be verified, "
1835 "possibly because you do not have the CA certificate "
1836 "in your certificate store, or the certificate has expired. "
1837 "Please look at the OpenSSL documentation on "
1838 "how to add a private CA to the store.");
1841 message += tr(
"Yes - trusted") +
"\n";
1842 message += tr(
"Ignore - temporary trusted") +
"\n";
1843 message += tr(
"No - no trusted") +
"\n";
1845 bool bCheckBox =
false;
1846 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1847 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1849 tr(
"Don't show again"));
1850 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1857 case QMessageBox::StandardButton::Yes:
1859 case QMessageBox::StandardButton::Ignore:
1870BOOL CBackendFreeRDP::cb_present_gateway_message(
1871 freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
1872 BOOL isConsentMandatory,
size_t length,
const WCHAR* message)
1874 qDebug(log) << Q_FUNC_INFO;
1876 if (!isDisplayMandatory && !isConsentMandatory)
1880 if (type == GATEWAY_MESSAGE_CONSENT && isConsentMandatory)
1882 QString msgType = (type == GATEWAY_MESSAGE_CONSENT)
1883 ? tr(
"Consent message") : tr(
"Service message");
1885#if FREERDP_VERSION_MAJOR >= 3
1886 char* pMsg = ConvertWCharToUtf8Alloc(message, NULL);
1892 msgType += QString::fromStdWString((
wchar_t*)message);
1895 msgType += tr(
"I understand and agree to the terms of this policy (Y/N)");
1897 rdpContext* pContext = (rdpContext*)instance->context;
1899 QMessageBox::StandardButton nRet = QMessageBox::No;
1900 bool bCheckBox =
false;
1902 QMessageBox::Yes|QMessageBox::No,
1905 case QMessageBox::Yes:
1913 return client_cli_present_gateway_message(
1914 instance, type, isDisplayMandatory,
1915 isConsentMandatory, length, message);
1920BOOL CBackendFreeRDP::cb_begin_paint(rdpContext *context)
1924 if (!context || !context->gdi || !context->gdi->primary
1925 || !context->gdi->primary->hdc)
1928 hdc = context->gdi->primary->hdc;
1930 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1933 hdc->hwnd->invalid->null = TRUE;
1934 hdc->hwnd->ninvalid = 0;
1938BOOL CBackendFreeRDP::UpdateBuffer(INT32 x, INT32 y, INT32 w, INT32 h)
1940 if(x > m_Image.width() || y > m_Image.height()) {
1941 qCritical(log) <<
"The width and height out of range."
1942 <<
"Image width:" << m_Image.width()
1943 <<
"Image height:" << m_Image.height()
1944 <<
"w:" << w <<
"h:" << h;
1948 QRect rect(x, y, w, h);
1949 QImage img = m_Image.copy(rect);
1955BOOL CBackendFreeRDP::cb_end_paint(rdpContext *context)
1959 CBackendFreeRDP* pThis = pContext->pThis;
1962 REGION16 invalidRegion;
1963 RECTANGLE_16 invalidRect;
1964 const RECTANGLE_16* extents;
1968 if (!context || !context->gdi || !context->gdi->primary
1969 || !context->gdi->primary->hdc)
1972 hdc = context->gdi->primary->hdc;
1974 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1977 rdpGdi* gdi = context->gdi;
1978 if (gdi->suppressOutput)
1981 HGDI_WND hwnd = context->gdi->primary->hdc->hwnd;
1982 ninvalid = hwnd->ninvalid;
1983 cinvalid = hwnd->cinvalid;
1987 region16_init(&invalidRegion);
1989 for (i = 0; i < ninvalid; i++)
1991 if(cinvalid[i].null)
1993 qWarning(log) <<
"is null region" << cinvalid[i].x << cinvalid[i].y
1994 << cinvalid[i].w << cinvalid[i].h;
1997 invalidRect.left = cinvalid[i].x;
1998 invalidRect.top = cinvalid[i].y;
1999 invalidRect.right = cinvalid[i].x + cinvalid[i].w;
2000 invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;
2001 region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
2004 if (!region16_is_empty(&invalidRegion))
2006 extents = region16_extents(&invalidRegion);
2008 pThis->UpdateBuffer(extents->left,
2010 extents->right - extents->left,
2011 extents->bottom - extents->top);
2014 region16_uninit(&invalidRegion);
2019BOOL CBackendFreeRDP::cb_desktop_resize(rdpContext* context)
2021 qDebug(log) << Q_FUNC_INFO;
2023 CBackendFreeRDP* pThis = pContext->pThis;
2024 rdpSettings* settings;
2025 if (!context || !context->settings)
2027 settings = context->settings;
2028 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
2029 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
2031 if(!gdi_resize(context->gdi, desktopWidth, desktopHeight))
2033 if(!pThis->CreateImage(context))
2036 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
2037 pThis->UpdateBuffer(0, 0, desktopWidth, desktopHeight);
2041BOOL CBackendFreeRDP::cb_play_bell_sound(rdpContext *context,
const PLAY_SOUND_UPDATE *play_sound)
2043 qDebug(log) << Q_FUNC_INFO;
2045 CBackendFreeRDP* pThis = pContext->pThis;
2046 WINPR_UNUSED(play_sound);
2047 QApplication::beep();
2051#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2052 QSoundEffect effect;
2053 effect.setSource(QUrl::fromLocalFile(szFile));
2058 QSound::play(szFile);
2064BOOL CBackendFreeRDP::cb_keyboard_set_indicators(rdpContext *context, UINT16 led_flags)
2066 qDebug(log) << Q_FUNC_INFO;
2068 CBackendFreeRDP* pThis = pContext->pThis;
2070 int state = CFrmViewer::LED_STATE::Unknown;
2072 if (led_flags & KBD_SYNC_NUM_LOCK)
2073 state |= CFrmViewer::LED_STATE::NumLock;
2074 if (led_flags & KBD_SYNC_CAPS_LOCK)
2075 state |= CFrmViewer::LED_STATE::CapsLock;
2076 if (led_flags & KBD_SYNC_SCROLL_LOCK)
2077 state |= CFrmViewer::LED_STATE::ScrollLock;
2079 emit pThis->sigUpdateLedState(state);
2085BOOL CBackendFreeRDP::cb_keyboard_set_ime_status(
2086 rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode)
2092 "KeyboardSetImeStatus(unitId=%04" PRIx16
", imeState=%08" PRIx32
2093 ", imeConvMode=%08" PRIx32
") ignored",
2094 imeId, imeState, imeConvMode);
2102 SetEvent(m_writeEvent);
2107bool CBackendFreeRDP::SendMouseEvent(UINT16 flags, QPoint pos,
bool isExtended)
2109 if(m_pParameter && m_pParameter->GetOnlyView())
return true;
2110 if(!m_pContext)
return false;
2112#if FREERDP_VERSION_MAJOR >= 3
2114 freerdp_client_send_extended_button_event(
2115 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
2117 freerdp_client_send_button_event(
2118 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
2120 if(!m_pContext->Context.input)
return false;
2121 return freerdp_input_send_mouse_event(
2122 m_pContext->Context.input, flags, pos.x(), pos.y());
2127void CBackendFreeRDP::wheelEvent(QWheelEvent *event)
2129 qDebug(logMouse) << Q_FUNC_INFO << event;
2130 if(!m_pContext)
return;
2131 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2135#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2136 pos =
event->position();
2140 QPoint p =
event->angleDelta();
2143 flags |= PTR_FLAGS_WHEEL | p.y();
2147 flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.y();
2152 flags |= PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.x();
2156 flags |= PTR_FLAGS_HWHEEL | p.x();
2158#if FREERDP_VERSION_MAJOR >= 3
2159 freerdp_client_send_wheel_event(&m_pContext->Context, flags);
2164 freerdp_input_send_mouse_event(
2165 m_pContext->Context.input, flags, pos.x(), pos.y());
2170void CBackendFreeRDP::mouseMoveEvent(QMouseEvent *event)
2173 if(!m_pContext)
return;
2174 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2175 UINT16 flags = PTR_FLAGS_MOVE;
2176 SendMouseEvent(flags, event->pos(),
false);
2179void CBackendFreeRDP::mousePressEvent(QMouseEvent *event)
2182 if(!m_pContext)
return;
2183 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2186 bool isExtended =
false;
2187 Qt::MouseButton button =
event->button();
2188 if (button & Qt::MouseButton::LeftButton)
2190 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
2192 else if (button & Qt::MouseButton::RightButton)
2194 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
2196 else if (button & Qt::MouseButton::MiddleButton)
2198 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
2200 else if (button & Qt::MouseButton::ForwardButton)
2202 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
2205 else if (button & Qt::MouseButton::BackButton)
2207 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
2212 SendMouseEvent(flags, event->pos(), isExtended);
2216void CBackendFreeRDP::mouseReleaseEvent(QMouseEvent *event)
2219 if(!m_pContext)
return;
2220 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2223 bool isExtended =
false;
2224 Qt::MouseButton button =
event->button();
2225 if (button & Qt::MouseButton::LeftButton)
2227 flags = PTR_FLAGS_BUTTON1;
2229 else if (button & Qt::MouseButton::MiddleButton)
2231 flags = PTR_FLAGS_BUTTON3;
2233 else if (button & Qt::MouseButton::RightButton)
2235 flags = PTR_FLAGS_BUTTON2;
2237 else if (button & Qt::MouseButton::ForwardButton)
2239 flags = PTR_XFLAGS_BUTTON2;
2242 else if (button & Qt::MouseButton::BackButton)
2244 flags = PTR_XFLAGS_BUTTON1;
2249 SendMouseEvent(flags, event->pos(), isExtended);
2253void CBackendFreeRDP::keyPressEvent(QKeyEvent *event)
2255 if(!m_pContext)
return;
2256 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2260 if(RDP_SCANCODE_UNKNOWN != k)
2261#if FREERDP_VERSION_MAJOR >= 3
2262 freerdp_input_send_keyboard_event_ex(
2263 m_pContext->Context.context.input,
true,
true, k);
2265 freerdp_input_send_keyboard_event_ex(
2266 m_pContext->Context.input,
true, k);
2270void CBackendFreeRDP::keyReleaseEvent(QKeyEvent *event)
2272 if(!m_pContext)
return;
2273 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2276 if(RDP_SCANCODE_UNKNOWN != k)
2277#if FREERDP_VERSION_MAJOR >= 3
2278 freerdp_input_send_keyboard_event_ex(
2279 m_pContext->Context.context.input,
false,
false, k);
2281 freerdp_input_send_keyboard_event_ex(
2282 m_pContext->Context.input,
false, k);
2286void CBackendFreeRDP::InputMethodEvent(QInputMethodEvent *event)
2293 if(!m_pContext)
return;
2294 if(m_pParameter && m_pParameter->GetOnlyView())
return;
2295 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2297 rdpSettings* settings = pRdpContext->settings;
2298 if(settings && !freerdp_settings_get_bool(settings, FreeRDP_UnicodeInput)) {
2299 qWarning(log) <<
"Don't set unicode input in server, please"
2300 << tr(
"Settings") <<
"→" << tr(
"Local resource") <<
"→" << tr(
"Enable local input method(Takes effect after reboot)");
2304 QString szText =
event->commitString();
2305 if(szText.isEmpty())
2307 for(
int i = 0; i < szText.length(); i++) {
2308 QChar c = szText.at(i);
2310#if FREERDP_VERSION_MAJOR >= 3
2312 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.context.input, 0, (UINT16)c.unicode());
2313 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.context.input, KBD_FLAGS_RELEASE, (UINT16)c.unicode());
2315 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.input, 0, (UINT16)c.unicode());
2316 freerdp_input_send_unicode_keyboard_event(m_pContext->Context.input, KBD_FLAGS_RELEASE, (UINT16)c.unicode());
2321int CBackendFreeRDP::RedirectionSound()
2323 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2324 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2325 rdpSettings* settings = instance->context->settings;
2328 if(m_pParameter->GetRedirectionSound()
2329 == CParameterFreeRDP::RedirecionSoundType::Disable)
2332 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE);
2333 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE);
2335 }
else if(m_pParameter->GetRedirectionSound()
2336 == CParameterFreeRDP::RedirecionSoundType::Local)
2338 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, TRUE);
2339 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
2340 }
else if(m_pParameter->GetRedirectionSound()
2341 == CParameterFreeRDP::RedirecionSoundType::Remote)
2343 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, TRUE);
2358 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"rdpsnd",
2359 m_pParameter->GetRedirectionSoundParameters().toStdString().c_str(),
2361 BOOL status = freerdp_client_add_static_channel(settings, count,
2362 #
if FREERDP_VERSION_MAJOR < 3
2370 status = freerdp_client_add_dynamic_channel(settings, count,
2371 #
if FREERDP_VERSION_MAJOR < 3
2381 qCritical(log) <<
"Load rdpsnd fail";
2388int CBackendFreeRDP::RedirectionMicrophone()
2390 if(m_pParameter->GetRedirectionSound()
2391 == CParameterFreeRDP::RedirecionSoundType::Remote)
2393 if(!m_pParameter->GetRedirectionMicrophone())
2396 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2397 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2399 rdpSettings* settings = instance->context->settings;
2402 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
2413 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"audin",
2414 m_pParameter->GetRedirectionMicrophoneParameters().toStdString().c_str(),
2416 BOOL status = freerdp_client_add_dynamic_channel(settings, count,
2417 #
if FREERDP_VERSION_MAJOR < 3
2426 qCritical(log) <<
"Load audin fail";
2433int CBackendFreeRDP::RedirectionDriver()
2435 QStringList lstDrives = m_pParameter->GetRedirectionDrives();
2436 if(lstDrives.isEmpty())
2439 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2440 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2441 rdpSettings* settings = instance->context->settings;
2444 foreach (
auto drive, lstDrives) {
2446 char* pDrive = _strdup(drive.toStdString().c_str());
2447 const char* argvDrive[] = {
"drive", pDrive};
2448 int count =
sizeof(argvDrive) /
sizeof(
const char*);
2449 BOOL status = freerdp_client_add_device_channel(settings, count,
2450 #
if FREERDP_VERSION_MAJOR < 3
2454 if(pDrive) free(pDrive);
2457 qCritical(log) <<
"Load drive fail";
2465int CBackendFreeRDP::RedirectionPrinter()
2467 if(!m_pParameter->GetRedirectionPrinter())
2470 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2471 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2472 rdpSettings* settings = instance->context->settings;
2475 QStringList printerList = QPrinterInfo::availablePrinterNames();
2476 if(printerList.isEmpty())
2478 qCritical(log) <<
"The printer is empty";
2481 qDebug(log) << printerList;
2484 const char* argvPrinter[] = {
"printer",
nullptr,
nullptr};
2485 int count =
sizeof(argvPrinter) /
sizeof(
const char*);
2486 BOOL status = freerdp_client_add_device_channel(settings, count,
2487 #
if FREERDP_VERSION_MAJOR < 3
2492 qCritical(log) <<
"Load printer fail";
2499int CBackendFreeRDP::RedirectionSerial()
2503 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2504 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2505 rdpSettings* settings = instance->context->settings;
2508 QList<QSerialPortInfo> lstSerial = QSerialPortInfo::availablePorts();
2511 foreach (
auto serial, lstSerial) {
2514 qDebug(log) <<
"systemLocation:" << serial.systemLocation()
2515 <<
"portName:" << serial.portName()
2516 <<
"serialNumber:" << serial.serialNumber();
2517 char* pSerial = _strdup(serial.systemLocation().toStdString().c_str());
2518 char* pName = _strdup(serial.portName().toStdString().c_str());
2519 const char* argvSerial[] = {
"serial", pName, pSerial};
2520 int count =
sizeof(argvSerial) /
sizeof(
const char*);
2521 BOOL status = freerdp_client_add_device_channel(settings, count,
2522 #
if FREERDP_VERSION_MAJOR < 3
2526 if(pSerial) free(pSerial);
2527 if(pName) free(pName);
2531 qCritical(log) <<
"Load drive fail";
2539void CBackendFreeRDP::slotConnectProxyServer(QString szHost, quint16 nPort)
2541 qDebug(log) <<
"Connect proxy server:" << szHost +
":" + QString::number(nPort);
2542 rdpContext* pContext = (rdpContext*)m_pContext;
2543 rdpSettings* settings = pContext->settings;
2545 qCritical(log) <<
"settings is null";
2548 freerdp_settings_set_string(
2549 settings, FreeRDP_ServerHostname,
2550 szHost.toStdString().c_str());
2551 freerdp_settings_set_uint32(
2552 settings, FreeRDP_ServerPort,
2555 int nRet = freerdp_client_start(pContext);
2558 qCritical(log) <<
"freerdp_client_start fail";
2560 qDebug(log) <<
"Connect proxy server:" << szHost +
":" + QString::number(nPort) <<
"end";
2564CBackendFreeRDP::OnInitReturnValue CBackendFreeRDP::InitSSHTunnelPipe()
2568 m_pThreadSSH =
new CSSHTunnelThread(
2569 &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net,
this);
2571 return OnInitReturnValue::Fail;
2572 bool check = connect(m_pThreadSSH, SIGNAL(sigServer(QString, quint16)),
2573 this, SLOT(slotConnectProxyServer(QString, quint16)));
2575 check = connect(m_pThreadSSH, SIGNAL(
sigError(
int,QString)),
2576 this, SIGNAL(
sigError(
int,QString)));
2578 check = connect(m_pThreadSSH, SIGNAL(
sigStop()),
2581 m_pThreadSSH->start();
2582 return OnInitReturnValue::UseOnProcess;
2585int CBackendFreeRDP::CleanSSHTunnelPipe()
2589 m_pThreadSSH->Exit();
2590 m_pThreadSSH =
nullptr;
void sigUpdateRect(const QRect &r, const QImage &image)
通知视图,图像更新
virtual void slotClipBoardChanged()=0
当剪切板发生改变时调用
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
初始化
static BOOL cb_post_connect(freerdp *instance)
Callback given to freerdp_connect() to perform post-connection operations.
virtual int OnClean() override
清理
virtual int OnProcess() override
插件连接的具体操作处理。因为此插件是非Qt事件,所以在此函数中等待。
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
唤醒后台线程。
void sigInformation(const QString &szInfo)
从后台线程中触发在主线程中显示信息,不阻塞后台线程
void sigStop()
需要通知用户停止时触发。仅由插件触发。 当从插件中需要停止时触发。例如:对端断开连接、重置连接或者连接出错。
void sigShowMessageBox(const QString &szTitle, const QString &szMessage, const QMessageBox::Icon &icon=QMessageBox::Information)
从后台线程中触发在主线程中显示消息对话框(QMessageBox),不阻塞后台线程
void sigError(const int nError, const QString &szError=QString())
当有错误产生时触发
void sigBlockShowMessageBox(const QString &szTitle, const QString &szMessage, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton &nRet, bool &checkBox, QString checkBoxContext=QString())
阻塞后台线程,并在前台线程中显示消息对话框(QMessageBox)
void sigRunning()
当插件开始成功后触发。仅由插件触发
void sigFinished()
停止成功信号。仅由插件触发
void sigSecurityLevel(CSecurityLevel::Levels level)
当安全级别改变时触发
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
阻塞后台线程,并在前台线程中显示窗口。
void sigBlockInputDialog(const QString &szTitle, const QString &szLable, const QString &szMessage, QString &szText)
阻塞后台线程,并在前台线程中显示输入对话框 (QInputDialog)
static UINT32 QtToScanCode(int key, Qt::KeyboardModifiers modifiers)
CConvertKeyCode::QtToScanCode
[Declare CParameterFreeRDP]
网络连接参数接口。此类仅在插件内有效。 其界面为 CParameterNetUI
CParameterUser m_User
[Instance user]
void sigChanged()
当参数改变时,触发 通常如果需要,则相应的参数会对应一个改变事件。