6#include "ConnectFreeRDP.h"
8#undef PEN_FLAG_INVERTED
9#include "freerdp/client.h"
10#include "freerdp/client/channels.h"
11#include "freerdp/channels/rdpei.h"
12#include "freerdp/channels/rdpdr.h"
13#include "freerdp/channels/disp.h"
14#include "freerdp/channels/tsmf.h"
15#include "freerdp/channels/rdpsnd.h"
16#include "freerdp/client/encomsp.h"
17#include "freerdp/gdi/gfx.h"
18#include "freerdp/settings.h"
19#include "freerdp/locale/keyboard.h"
20#include "freerdp/channels/rdpgfx.h"
21#include "freerdp/channels/cliprdr.h"
22#include "freerdp/client/cmdline.h"
23#include <freerdp/gdi/video.h>
25#include "RabbitCommonTools.h"
26#include "ConvertKeyCode.h"
30#include <QApplication>
32#include <QSslCertificate>
33#include <QInputDialog>
34#include <QMutexLocker>
36#include <QPrinterInfo>
38#include <QSerialPortInfo>
39#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
40 #include <QSoundEffect>
45static Q_LOGGING_CATEGORY(log,
"FreeRDP.Connect")
50 m_pParameter(
nullptr),
58 qDebug(log) << Q_FUNC_INFO;
59 m_pParameter = qobject_cast<CParameterFreeRDP*>(pConnecter->GetParameter());
60 Q_ASSERT(m_pParameter);
63CConnectFreeRDP::~CConnectFreeRDP()
65 qDebug(log) << Q_FUNC_INFO;
76 qDebug(log) << Q_FUNC_INFO;
79 m_writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
81 qCritical(log) <<
"CreateEvent failed";
83 ZeroMemory(&m_ClientEntryPoints,
sizeof(RDP_CLIENT_ENTRY_POINTS));
84 m_ClientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
85 m_ClientEntryPoints.Size =
sizeof(RDP_CLIENT_ENTRY_POINTS);
87 m_ClientEntryPoints.GlobalInit = cbGlobalInit;
88 m_ClientEntryPoints.GlobalUninit = cbGlobalUninit;
89 m_ClientEntryPoints.ClientNew = cbClientNew;
90 m_ClientEntryPoints.ClientFree = cbClientFree;
91 m_ClientEntryPoints.ClientStart = cbClientStart;
92 m_ClientEntryPoints.ClientStop = cbClientStop;
95 auto pRdpContext = freerdp_client_context_new(&m_ClientEntryPoints);
99 m_pContext->pThis =
this;
101 qCritical(log) <<
"freerdp_client_context_new fail";
102 return OnInitReturnValue::Fail;
105 rdpSettings* settings = pRdpContext->settings;
107 qCritical(log) <<
"settings is null";
108 return OnInitReturnValue::Fail;
111 char* argv[]= {(
char*)QApplication::applicationFilePath().toStdString().c_str()};
112 int argc =
sizeof(argv) /
sizeof(
char*);
113 nRet = freerdp_client_settings_parse_command_line(settings, argc, argv, TRUE);
116 nRet = freerdp_client_settings_command_line_status_print(settings, nRet, argc, argv);
117 return OnInitReturnValue::Fail;
120#if FreeRDP_VERSION_MAJOR >= 3
121 if (!stream_dump_register_handlers(pRdpContext,
122 CONNECTION_STATE_MCS_CREATE_REQUEST,
124 return OnInitReturnValue::Fail;
127 auto &user = m_pParameter->m_Net.
m_User;
128 if(!user.GetUser().isEmpty())
129 freerdp_settings_set_string(
130 settings, FreeRDP_Username,
131 user.GetUser().toStdString().c_str());
132 if(!user.GetPassword().isEmpty())
133 freerdp_settings_set_string(
134 settings, FreeRDP_Password,
135 user.GetPassword().toStdString().c_str());
137 freerdp_settings_set_bool(
138 settings, FreeRDP_RedirectClipboard, m_pParameter->GetClipboard());
140#if FreeRDP_VERSION_MAJOR >= 3
141 bool bOnlyView = m_pParameter->GetOnlyView();
142 freerdp_settings_set_bool(
143 settings, FreeRDP_SuspendInput, bOnlyView);
146 freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
147 m_pParameter->GetDesktopWidth());
148 freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
149 m_pParameter->GetDesktopHeight());
150 freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth,
151 m_pParameter->GetColorDepth());
153 freerdp_settings_set_bool(settings, FreeRDP_UseMultimon,
154 m_pParameter->GetUseMultimon());
156 if(m_pParameter->GetReconnectInterval()) {
157 freerdp_settings_set_bool(
158 settings, FreeRDP_AutoReconnectionEnabled,
true);
159 freerdp_settings_set_uint32(
161 FreeRDP_AutoReconnectMaxRetries,
162 m_pParameter->GetReconnectInterval());
165 freerdp_settings_set_bool(
166 settings, FreeRDP_AutoReconnectionEnabled,
false);
170 RedirectionMicrophone();
172 RedirectionPrinter();
176 switch(m_pParameter->m_Proxy.GetUsedType())
178 case CParameterProxy::TYPE::None:
180 if(!m_pParameter->GetDomain().isEmpty())
181 freerdp_settings_set_string(
182 settings, FreeRDP_Domain,
183 m_pParameter->GetDomain().toStdString().c_str());
184 if(m_pParameter->m_Net.GetHost().isEmpty())
187 szErr = tr(
"The server is empty, please input it");
188 qCritical(log) << szErr;
190 emit
sigError(-1, szErr.toStdString().c_str());
191 return OnInitReturnValue::Fail;
193 auto &net = m_pParameter->m_Net;
194 freerdp_settings_set_string(
195 settings, FreeRDP_ServerHostname,
196 net.GetHost().toStdString().c_str());
197 freerdp_settings_set_uint32(
198 settings, FreeRDP_ServerPort,
201 nRet = freerdp_client_start(pRdpContext);
204 qCritical(log) <<
"freerdp_client_start fail";
205 return OnInitReturnValue::Fail;
210 case CParameterProxy::TYPE::SSHTunnel:
214 auto &ssh = m_pParameter->m_Proxy.m_SSH;
215 parameter->setServer(ssh.GetHost());
216 parameter->setPort(ssh.GetPort());
218 parameter->SetUser(user.GetUser());
219 parameter->SetUseSystemFile(user.GetUseSystemFile());
220 if(CParameterUser::TYPE::UserPassword == user.GetUsedType()) {
221 parameter->SetAuthenticationMethod(SSH_AUTH_METHOD_PASSWORD);
222 parameter->SetPassword(user.GetPassword());
224 if(CParameterUser::TYPE::PublicKey == user.GetUsedType()) {
225 parameter->SetAuthenticationMethod(SSH_AUTH_METHOD_PUBLICKEY);
226 parameter->SetPublicKeyFile(user.GetPublicKeyFile());
227 parameter->SetPrivateKeyFile(user.GetPrivateKeyFile());
228 parameter->SetPassphrase(user.GetPassphrase());
230 auto &net = m_pParameter->m_Net;
231 parameter->SetRemoteHost(net.GetHost());
232 parameter->SetRemotePort(net.GetPort());
238 return OnInitReturnValue::Fail;
239 bool check = connect(m_pThread, SIGNAL(sigServer(QString, quint16)),
240 this, SLOT(slotConnectProxyServer(QString, quint16)));
242 check = connect(m_pThread, SIGNAL(
sigError(
int,QString)),
243 this, SIGNAL(
sigError(
int,QString)));
256 return OnInitReturnValue::UseOnProcess;
261 qDebug(log) << Q_FUNC_INFO;
273 CloseHandle(m_writeEvent);
274 m_writeEvent =
nullptr;
278 rdpContext* pRdpContext = (rdpContext*)m_pContext;
279 if(!freerdp_disconnect(pRdpContext->instance))
280 qCritical(log) <<
"freerdp_disconnect fail";
282 if(freerdp_client_stop(pRdpContext))
283 qCritical(log) <<
"freerdp_client_stop fail";
285 freerdp_client_context_free(pRdpContext);
286 m_pContext =
nullptr;
309 rdpContext* pRdpContext = (rdpContext*)m_pContext;
311 if(
nullptr == freerdp_settings_get_string(pRdpContext->settings, FreeRDP_ServerHostname))
319 nCount = freerdp_get_event_handles(pRdpContext, &handles[nCount],
320 ARRAYSIZE(handles) - nCount);
323 qCritical(log) <<
"freerdp_get_event_handles failed";
328 handles[nCount] = m_writeEvent;
331 DWORD waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, 500);
333 ResetEvent(m_writeEvent);
335 if (waitStatus == WAIT_FAILED)
337 qCritical(log) <<
"WaitForMultipleObjects: WAIT_FAILED";
342 if(waitStatus == WAIT_TIMEOUT)
349 if (!freerdp_check_event_handles(pRdpContext))
353 UINT32 err = freerdp_get_last_error(pRdpContext);
355 szErr =
"freerdp_check_event_handles fail.";
357 szErr += QString::number(err);
359 szErr += freerdp_get_last_error_category(err);
361 szErr += freerdp_get_last_error_name(err);
363 szErr += freerdp_get_last_error_string(err);
364 qCritical(log) << szErr;
388#if FreeRDP_VERSION_MAJOR >= 3
389 if(freerdp_shall_disconnect_context(pRdpContext))
391 if(freerdp_shall_disconnect(pRdpContext->instance))
394 qCritical(log) <<
"freerdp_shall_disconnect false";
402void CConnectFreeRDP::slotClipBoardChanged()
404 qDebug(log) << Q_FUNC_INFO;
405 if(m_pParameter && m_pParameter->GetOnlyView())
return;
406 if(m_pParameter->GetClipboard())
407 m_ClipBoard.slotClipBoardChanged();
410BOOL CConnectFreeRDP::cbGlobalInit()
412 qDebug(log) << Q_FUNC_INFO;
416void CConnectFreeRDP::cbGlobalUninit()
418 qDebug(log) << Q_FUNC_INFO;
421BOOL CConnectFreeRDP::cbClientNew(freerdp *instance, rdpContext *context)
423 qDebug(log) << Q_FUNC_INFO;
426 instance->PostDisconnect = cb_post_disconnect;
429#if FreeRDP_VERSION_MAJOR < 3
430 instance->Authenticate = cb_authenticate;
431 instance->GatewayAuthenticate = cb_GatewayAuthenticate;
433 instance->AuthenticateEx = cb_authenticate_ex;
434 instance->ChooseSmartcard = cb_choose_smartcard;
439 instance->PresentGatewayMessage = cb_present_gateway_message;
441 instance->LogonErrorInfo = cb_logon_error_info;
446void CConnectFreeRDP::cbClientFree(freerdp *instance, rdpContext *context)
448 qDebug(log) << Q_FUNC_INFO;
451int CConnectFreeRDP::cbClientStart(rdpContext *context)
453 qDebug(log) << Q_FUNC_INFO;
456 if (!context || !context->settings)
458 freerdp* instance = freerdp_client_get_instance(context);
462 auto settings = context->settings;
466 szHost = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
467 nPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
469 auto &net = pThis->m_pParameter->m_Net;
470 szServer = net.GetHost() +
":" + QString::number(net.GetPort());
471 auto &proxy = pThis->m_pParameter->m_Proxy;
472 switch(proxy.GetUsedType()) {
473 case CParameterProxy::TYPE::SSHTunnel:
475 auto &sshNet = proxy.m_SSH;
476 szServer = szHost +
":" + QString::number(nPort)
477 +
" <-> " + sshNet.GetHost() +
":" + QString::number(sshNet.GetPort())
478 +
" <-> " + szServer;
485 BOOL status = freerdp_connect(instance);
487 QString szInfo = tr(
"Connect to ") + szServer;
488 qInfo(log) << szInfo;
492 UINT32 nErr = freerdp_get_last_error(context);
495 szErr = tr(
"Connect to ") + szServer + tr(
" fail.");
497 szErr += QString::number(nErr) +
" - ";
498 szErr += freerdp_get_last_error_name(nErr);
503 szErr += freerdp_get_last_error_string(nErr);
507 case FREERDP_ERROR_CONNECT_LOGON_FAILURE:
510 QString szErr = tr(
"Logon to ") + szServer;
511 szErr += tr(
" fail. Please check that the username and password are correct.") +
"\n";
515 case FREERDP_ERROR_CONNECT_WRONG_PASSWORD:
518 QString szErr = tr(
"Logon to ") + szServer;
519 szErr += tr(
" fail. Please check password are correct.") +
"\n";
523 case FREERDP_ERROR_AUTHENTICATION_FAILED:
526 QString szErr = tr(
"Logon to ") + szServer;
527 szErr += tr(
" authentication fail. please add a CA certificate to the store.") +
"\n";
531 case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED:
534 QString szErr = tr(
"Logon to ") + szServer;
535 szErr += tr(
" connect transport layer fail.") +
"\n\n";
536 szErr += tr(
"Please:") +
"\n";
537 szErr += tr(
"1. Check for any network related issues") +
"\n";
538 szErr += tr(
"2. Check you have proper security settings ('NLA' enabled is required for most connections nowadays)") +
"\n";
539 szErr += tr(
"3. Check the certificate is proper (and guacd properly checks that)") +
"\n";
543 case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED:
549 qCritical(log) << szErr;
550 emit pThis->
sigError(nRet, szErr.toStdString().c_str());
555int CConnectFreeRDP::cbClientStop(rdpContext *context)
558 qDebug(log) << Q_FUNC_INFO;
559#if FreeRDP_VERSION_MAJOR >= 3
560 nRet = freerdp_client_common_stop(context);
562 BOOL bRet = freerdp_abort_connect(context->instance);
564 { qCritical(log) <<
"freerdp_abort_connect fail";
591 qDebug(log) << Q_FUNC_INFO;
592 rdpChannels* channels =
nullptr;
593 rdpSettings* settings =
nullptr;
594 rdpContext* context = instance->context;
596 if (!instance || !instance->context || !instance->context->settings)
602 if(!pThis)
return FALSE;
603 settings = instance->context->settings;
604 channels = context->channels;
607#if defined (Q_OS_WIN)
608 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_WINDOWS))
610 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_WINDOWS_NT))
612#elif defined(Q_OS_ANDROID)
613 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_ANDROID))
615 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
617#elif defined(Q_OS_IOS)
618 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_IOS))
620 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
622#elif defined (Q_OS_UNIX)
623 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX))
625 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_XSERVER))
628 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNSPECIFIED))
630 if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
635 PubSub_SubscribeChannelConnected(instance->context->pubSub,
636 OnChannelConnectedEventHandler);
637 PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
638 OnChannelDisconnectedEventHandler);
640#if FreeRDP_VERSION_MAJOR < 3
641 if (!freerdp_client_load_addins(channels, instance->context->settings))
646 if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly))
649 auto &user = pThis->m_pParameter->m_Net.
m_User;
650 if(!freerdp_settings_get_string(settings, FreeRDP_Username)) {
651 if(user.GetUser().isEmpty()) {
652 if(user.GetUser().isEmpty()) {
654 qWarning(log) <<
"Auth-only, but no user name set. Will be call instance->Authenticate.";
657 freerdp_settings_set_string(
658 settings, FreeRDP_Username,
659 user.GetUser().toStdString().c_str());
661 if (!freerdp_settings_get_string(settings, FreeRDP_Password)) {
662 if (user.GetPassword().isEmpty()) {
664 qWarning(log) <<
"auth-only, but no password set. Will be call instance->Authenticate";
666 freerdp_settings_set_string(
667 settings, FreeRDP_Password,
668 user.GetPassword().toStdString().c_str());
670#if FreeRDP_VERSION_MAJOR >= 3
671 if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE))
674 qInfo(log) <<
"Authentication only. Don't connect to X.";
675 }
else if(freerdp_settings_get_bool(settings, FreeRDP_CredentialsFromStdin)){
677 }
else if(freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon)) {
688 UINT32 width = pThis->m_pParameter->GetDesktopWidth();
689 UINT32 height = pThis->m_pParameter->GetDesktopHeight();
690 if ((width < 64) || (height < 64) ||
691 (width > 4096) || (height > 4096))
693 QString szErr = tr(
"Invalid dimensions:")
694 + QString::number(width)
695 +
"*" + QString::number(height);
696 qCritical(log) << szErr;
700 qInfo(log) <<
"Init desktop size " << width <<
"*" << height;
704 <<
"width:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)
705 <<
"height:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)
706 <<
"ColorDepth:" << freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
711const char* CConnectFreeRDP::GetTitle(freerdp* instance)
713 const char* windowTitle;
716 const char* name =
nullptr;
719 rdpSettings* settings = instance->context->settings;
724 windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
728#if FreeRDP_VERSION_MAJOR >= 3
729 name = freerdp_settings_get_server_name(settings);
731 name = pThis->m_pParameter->m_Net.GetHost().toStdString().c_str();
733 port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
735 addPort = (port != 3389);
737 char buffer[MAX_PATH + 64] = { 0 };
740 sprintf_s(buffer,
sizeof(buffer),
"%s", name);
742 sprintf_s(buffer,
sizeof(buffer),
"%s:%" PRIu32, name, port);
744 freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer);
745 return freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
755 qDebug(log) << Q_FUNC_INFO;
757 rdpContext* context = instance->context;
758 rdpSettings* settings = instance->context->settings;
759 rdpUpdate* update = instance->context->update;
762 const char* pWindowTitle = GetTitle(instance);
765 WCHAR* windowTitle = NULL;
766#if FreeRDP_VERSION_MAJOR >= 3
767 windowTitle = ConvertUtf8ToWCharAlloc(pWindowTitle, NULL);
769 ConvertToUnicode(CP_UTF8, 0, pWindowTitle, -1, &windowTitle, 0);
773 QString title = QString::fromUtf16((
const char16_t*)windowTitle);
775 if(pThis->m_pParameter->GetServerName().isEmpty())
776 emit pThis->sigServerName(title);
780 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
781 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
782 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
784 if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
787 if(!pThis->CreateImage(instance->context))
790 Q_ASSERT(instance->context->cache);
793 if(pThis->m_Cursor.RegisterPointer(context->graphics))
796 update->BeginPaint = cb_begin_paint;
797 update->EndPaint = cb_end_paint;
798 update->DesktopResize = cb_desktop_resize;
800 update->PlaySound = cb_play_bell_sound;
802 update->SetKeyboardIndicators = cb_keyboard_set_indicators;
803 update->SetKeyboardImeStatus = cb_keyboard_set_ime_status;
809void CConnectFreeRDP::cb_post_disconnect(freerdp* instance)
811 qDebug(log) << Q_FUNC_INFO;
812 rdpContext* context =
nullptr;
814 if (!instance || !instance->context)
817 context = instance->context;
819 PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
820 OnChannelConnectedEventHandler);
821 PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
822 OnChannelDisconnectedEventHandler);
826int CConnectFreeRDP::cb_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
829 const char* str_data = freerdp_get_logon_error_info_data(data);
830 const char* str_type = freerdp_get_logon_error_info_type(type);
831 QString szErr = tr(
"FreeRDP logon info: [");
835 qDebug(log) << szErr;
841void CConnectFreeRDP::OnChannelConnectedEventHandler(
void *context,
842 #
if FreeRDP_VERSION_MAJOR >= 3
845 ChannelConnectedEventArgs *e)
847 rdpContext* pContext = (rdpContext*)context;
849 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
850 qDebug(log) <<
"channel" << e->name <<
"connected";
851 pThis->m_ClipBoard.Init((CliprdrClientContext*)e->pInterface,
852 pThis->m_pParameter->GetClipboard());
854#if FreeRDP_VERSION_MAJOR >= 3
856 freerdp_client_OnChannelConnectedEventHandler(pContext, e);
858 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
860 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
861 rdpGdi* gdi = pContext->gdi;
863 gdi_graphics_pipeline_init(gdi, (RdpgfxClientContext*) e->pInterface);
866 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
868 else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
870 gdi_video_geometry_init(pContext->gdi, (GeometryClientContext*)e->pInterface);
872 else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
874 gdi_video_data_init(pContext->gdi, (VideoClientContext*)e->pInterface);
876 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"connected but we can’t use it";
880void CConnectFreeRDP::OnChannelDisconnectedEventHandler(
void *context,
881 #
if FreeRDP_VERSION_MAJOR >= 3
884 ChannelDisconnectedEventArgs *e)
886 rdpContext* pContext = (rdpContext*)context;
889 if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
890 qDebug(log) <<
"channel" << e->name <<
"disconnected";
891 pThis->m_ClipBoard.UnInit((CliprdrClientContext*)e->pInterface,
892 pThis->m_pParameter->GetClipboard());
894#if FreeRDP_VERSION_MAJOR >= 3
896 freerdp_client_OnChannelDisconnectedEventHandler(pContext, e);
898 else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
900 if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
901 rdpGdi* gdi = pContext->gdi;
902 gdi_graphics_pipeline_uninit(gdi, (RdpgfxClientContext*) e->pInterface);
905 qDebug(log,
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
908 qDebug(log) <<
"Unimplemented: channel" << e->name <<
"disconnected but we can’t use it";
913UINT32 CConnectFreeRDP::GetImageFormat(QImage::Format format)
916#if (QT_VERSION >= QT_VERSION_CHECK(5,2,0))
917 case QImage::Format_RGBA8888:
918 return PIXEL_FORMAT_RGBA32;
919 case QImage::Format_RGBX8888:
920 return PIXEL_FORMAT_RGBX32;
922 case QImage::Format_RGB16:
923 return PIXEL_FORMAT_RGB16;
924 case QImage::Format_ARGB32:
925 return PIXEL_FORMAT_BGRA32;
926 case QImage::Format_RGB32:
927 return PIXEL_FORMAT_BGRA32;
934UINT32 CConnectFreeRDP::GetImageFormat()
936 return GetImageFormat(m_Image.format());
939BOOL CConnectFreeRDP::CreateImage(rdpContext *context)
942 ClientContext* pContext = (ClientContext*)context;
944 rdpGdi* gdi = context->gdi;
945 Q_ASSERT(pThis && gdi);
946 pThis->m_Image = QImage(gdi->primary_buffer,
947 static_cast<int>(gdi->width),
948 static_cast<int>(gdi->height),
949 QImage::Format_ARGB32);
953#if FreeRDP_VERSION_MAJOR >= 3
955static CREDUI_INFOW wfUiInfo = {
sizeof(CREDUI_INFOW), NULL, L
"Enter your credentials",
956 L
"Remote Desktop Security", NULL };
958BOOL CConnectFreeRDP::cb_authenticate_ex(freerdp* instance,
959 char** username,
char** password,
960 char** domain, rdp_auth_reason reason)
962 qDebug(log) << Q_FUNC_INFO <<
"reason:" << reason;
966 if(!username || !password || !domain)
return FALSE;
968 rdpContext* pContext = (rdpContext*)instance->context;
973 WCHAR UserNameW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
974 WCHAR UserW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
975 WCHAR DomainW[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
976 WCHAR PasswordW[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 };
978 WINPR_ASSERT(instance);
979 WINPR_ASSERT(instance->context);
980 WINPR_ASSERT(instance->context->settings);
982 WINPR_ASSERT(username);
983 WINPR_ASSERT(domain);
984 WINPR_ASSERT(password);
986 const WCHAR auth[] = L
"Target credentials requested";
987 const WCHAR authPin[] = L
"PIN requested";
988 const WCHAR gwAuth[] = L
"Gateway credentials requested";
989 const WCHAR* titleW = auth;
992 dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
993 CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1000 if ((*username) && (*password))
1003 case AUTH_SMARTCARD_PIN:
1004 dwFlags &= ~CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
1005 dwFlags |= CREDUI_FLAGS_PASSWORD_ONLY_OK | CREDUI_FLAGS_KEEP_USERNAME;
1010 *username = _strdup(
"PIN");
1023 ConvertUtf8ToWChar(*username, UserNameW, ARRAYSIZE(UserNameW));
1024 ConvertUtf8ToWChar(*username, UserW, ARRAYSIZE(UserW));
1028 ConvertUtf8ToWChar(*password, PasswordW, ARRAYSIZE(PasswordW));
1031 ConvertUtf8ToWChar(*domain, DomainW, ARRAYSIZE(DomainW));
1033 if (_wcsnlen(PasswordW, ARRAYSIZE(PasswordW)) == 0)
1035 status = CredUIPromptForCredentialsW(&wfUiInfo, titleW, NULL, 0, UserNameW,
1036 ARRAYSIZE(UserNameW), PasswordW,
1037 ARRAYSIZE(PasswordW), &fSave, dwFlags);
1038 if (status != NO_ERROR)
1041 "CredUIPromptForCredentials unexpected status: 0x%08lX",
1046 if ((dwFlags & CREDUI_FLAGS_KEEP_USERNAME) == 0)
1048 status = CredUIParseUserNameW(UserNameW, UserW, ARRAYSIZE(UserW), DomainW,
1049 ARRAYSIZE(DomainW));
1050 if (status != NO_ERROR)
1052 CHAR User[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1053 CHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
1054 CHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
1056 ConvertWCharNToUtf8(UserNameW, ARRAYSIZE(UserNameW), UserName, ARRAYSIZE(UserName));
1057 ConvertWCharNToUtf8(UserW, ARRAYSIZE(UserW), User, ARRAYSIZE(User));
1058 ConvertWCharNToUtf8(DomainW, ARRAYSIZE(DomainW), Domain, ARRAYSIZE(Domain));
1060 "Failed to parse UserName: %s into User: %s Domain: %s",
1061 UserName, User, Domain);
1067 *username = ConvertWCharNToUtf8Alloc(UserW, ARRAYSIZE(UserW), NULL);
1070 qCritical(log) <<
"ConvertWCharNToUtf8Alloc failed" << status;
1074 if (_wcsnlen(DomainW, ARRAYSIZE(DomainW)) > 0)
1075 *domain = ConvertWCharNToUtf8Alloc(DomainW, ARRAYSIZE(DomainW), NULL);
1077 *domain = _strdup(
"\0");
1082 qCritical(log) <<
"strdup failed" << status;
1086 *password = ConvertWCharNToUtf8Alloc(PasswordW, ARRAYSIZE(PasswordW), NULL);
1095 return cb_authenticate(instance, username, password, domain);
1100BOOL CConnectFreeRDP::cb_choose_smartcard(freerdp* instance,
1101 SmartcardCertInfo** cert_list,
1103 DWORD* choice, BOOL gateway)
1105 rdpContext* pContext = (rdpContext*)instance->context;
1107 QString msg(
"Multiple smartcards are available for use:\n");
1108 for (DWORD i = 0; i < count; i++)
1110 const SmartcardCertInfo* cert = cert_list[i];
1111 char* reader = ConvertWCharToUtf8Alloc(cert->reader, NULL);
1112 char* container_name = ConvertWCharToUtf8Alloc(cert->containerName, NULL);
1114 msg += QString::number(i) +
" ";
1115 msg += QString(container_name) +
"\n\t";
1116 msg +=
"Reader: " + QString(reader) +
"\n\t";
1117 msg +=
"User: " + QString(cert->userHint) + +
"@" + QString(cert->domainHint) +
"\n\t";
1118 msg +=
"Subject: " + QString(cert->subject) +
"\n\t";
1119 msg +=
"Issuer: " + QString(cert->issuer) +
"\n\t";
1120 msg +=
"UPN: " + QString(cert->upn) +
"\n";
1123 free(container_name);
1126 msg +=
"\nChoose a smartcard to use for ";
1128 msg +=
"gateway authentication";
1132 msg +=
"(0 - " + QString::number(count - 1) +
")";
1140 int n = num.toInt(&ok);
1152BOOL CConnectFreeRDP::cb_authenticate(freerdp* instance,
char** username,
1153 char** password,
char** domain)
1155 qDebug(log) << Q_FUNC_INFO;
1158 rdpContext* pContext = (rdpContext*)instance->context;
1160 if(!username || !password || !domain)
return FALSE;
1161 if(*username && *password )
return TRUE;
1163 int nRet = QDialog::Rejected;
1165 nRet, pThis->m_pParameter);
1166 if(QDialog::Accepted == nRet)
1168 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1169 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1170 QString szDomain = pThis->m_pParameter->GetDomain();
1171 if(!szDomain.isEmpty() && domain)
1172 *domain = _strdup(szDomain.toStdString().c_str());
1173 if(!szName.isEmpty() && username)
1174 *username = _strdup(szName.toStdString().c_str());
1175 if(!szPassword.isEmpty() && password)
1176 *password = _strdup(szPassword.toStdString().c_str());
1183BOOL CConnectFreeRDP::cb_GatewayAuthenticate(freerdp *instance,
1184 char **username,
char **password,
char **domain)
1186 qDebug(log) << Q_FUNC_INFO;
1190 rdpContext* pContext = (rdpContext*)instance->context;
1192 if(!username || !password || !domain)
return FALSE;
1193 if(*username && *password )
return TRUE;
1195 int nRet = QDialog::Rejected;
1196 emit pThis->
sigBlockShowWidget(
"CDlgGetUserPasswordFreeRDP", nRet, pThis->m_pParameter);
1197 if(QDialog::Accepted == nRet)
1199 QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
1200 QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
1201 QString szDomain = pThis->m_pParameter->GetDomain();
1202 if(!szDomain.isEmpty() && domain)
1203 *domain = _strdup(szDomain.toStdString().c_str());
1204 if(!szName.isEmpty() && username)
1205 *username = _strdup(szName.toStdString().c_str());
1206 if(!szPassword.isEmpty() && password)
1207 *password = _strdup(szPassword.toStdString().c_str());
1215 const BYTE* data,
size_t length,
1216 const char* hostname, UINT16 port, DWORD flags)
1218 qDebug(log) << Q_FUNC_INFO;
1219 rdpContext* pContext = (rdpContext*)instance->context;
1221 QSslCertificate cert(QByteArray((
const char*)data, length));
1224 instance, hostname, port,
1225 cert.issuerDisplayName().toStdString().c_str(),
1226 cert.subjectDisplayName().toStdString().c_str(),
1227 cert.issuerDisplayName().toStdString().c_str(),
1228 cert.serialNumber().toStdString().c_str(),
1250 const char *host, UINT16 port,
1251 const char *common_name,
const char *subject,
1252 const char *issuer,
const char *fingerprint, DWORD flags)
1254 qDebug(log) << Q_FUNC_INFO;
1256 rdpContext* pContext = (rdpContext*)instance->context;
1263 emit pThis->sigServerName(common_name);
1266 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1272 QString szType = tr(
"RDP-Server");
1273 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1274 szType = tr(
"RDP-Gateway");
1275 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1276 szType = tr(
"RDP-Redirect");
1278 QString title(tr(
"Verify certificate"));
1281 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1282 message += tr(
"Common name: ") + common_name +
"\n";
1283 message += tr(
"Subject: ") + subject +
"\n";
1284 message += tr(
"Issuer: ") + issuer +
"\n";
1285 message += tr(
"Fingerprint: ") + fingerprint +
"\n";
1287 if(VERIFY_CERT_FLAG_CHANGED & flags) {
1288 message += tr(
"The above X.509 certificate is changed.\n"
1289 "It is possible that the server has changed its certificate, "
1290 "or Maybe it was attacked."
1291 "Please look at the OpenSSL documentation on "
1292 "how to add a private CA to the store.");
1294 message += tr(
"The above X.509 certificate could not be verified.\n"
1295 "Possibly because you do not have the CA certificate "
1296 "in your certificate store, or the certificate has expired.\n"
1297 "Please look at the OpenSSL documentation on "
1298 "how to add a private CA to the store.");
1302 message += tr(
"Yes - trusted") +
"\n";
1303 message += tr(
"Ignore - temporary trusted") +
"\n";
1304 message += tr(
"No - no trusted") +
"\n";
1306 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1307 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1308 bool bCheckBox =
false;
1310 tr(
"Don't show again"));
1311 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1317 case QMessageBox::StandardButton::Yes:
1319 case QMessageBox::StandardButton::Ignore:
1347 const char *host, UINT16 port,
1348 const char *common_name,
const char *subject,
1349 const char *issuer,
const char *fingerprint,
1350 const char *old_subject,
const char *old_issuer,
1351 const char *old_fingerprint, DWORD flags)
1353 qDebug(log) << Q_FUNC_INFO;
1354 rdpContext* pContext = (rdpContext*)instance->context;
1357 emit pThis->sigServerName(common_name);
1359 if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
1365 QString szType = tr(
"RDP-Server");
1366 if (flags & VERIFY_CERT_FLAG_GATEWAY)
1367 szType = tr(
"RDP-Gateway");
1368 if (flags & VERIFY_CERT_FLAG_REDIRECT)
1369 szType = tr(
"RDP-Redirect");
1371 QString title(tr(
"Verify changed certificate"));
1373 message += szType + tr(
": %1:%2").arg(host, QString::number(port)) +
"\n";
1374 message += tr(
"Common name: ") + common_name +
"\n";
1375 message += tr(
"New subject: ") + subject +
"\n";
1376 message += tr(
"New issuer: ") + issuer +
"\n";
1377 message += tr(
"New fingerprint: ") + fingerprint +
"\n";
1378 message += tr(
"Old subject: ") + old_subject +
"\n";
1379 message += tr(
"Old issuer: ") + old_issuer +
"\n";
1380 message += tr(
"Old fingerprint: ") + old_fingerprint +
"\n";
1382 message += tr(
"The above X.509 certificate could not be verified, "
1383 "possibly because you do not have the CA certificate "
1384 "in your certificate store, or the certificate has expired. "
1385 "Please look at the OpenSSL documentation on "
1386 "how to add a private CA to the store.");
1389 message += tr(
"Yes - trusted") +
"\n";
1390 message += tr(
"Ignore - temporary trusted") +
"\n";
1391 message += tr(
"No - no trusted") +
"\n";
1393 bool bCheckBox =
false;
1394 QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
1395 QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
1397 tr(
"Don't show again"));
1398 pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
1405 case QMessageBox::StandardButton::Yes:
1407 case QMessageBox::StandardButton::Ignore:
1418BOOL CConnectFreeRDP::cb_present_gateway_message(
1419 freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
1420 BOOL isConsentMandatory,
size_t length,
const WCHAR* message)
1422 qDebug(log) << Q_FUNC_INFO;
1424 if (!isDisplayMandatory && !isConsentMandatory)
1428 if (type == GATEWAY_MESSAGE_CONSENT && isConsentMandatory)
1430 QString msgType = (type == GATEWAY_MESSAGE_CONSENT)
1431 ? tr(
"Consent message") : tr(
"Service message");
1433#if FreeRDP_VERSION_MAJOR >= 3
1434 char* pMsg = ConvertWCharToUtf8Alloc(message, NULL);
1440 msgType += QString::fromStdWString((
wchar_t*)message);
1443 msgType += tr(
"I understand and agree to the terms of this policy (Y/N)");
1445 rdpContext* pContext = (rdpContext*)instance->context;
1447 QMessageBox::StandardButton nRet = QMessageBox::No;
1448 bool bCheckBox =
false;
1450 QMessageBox::Yes|QMessageBox::No,
1453 case QMessageBox::Yes:
1461 return client_cli_present_gateway_message(
1462 instance, type, isDisplayMandatory,
1463 isConsentMandatory, length, message);
1468BOOL CConnectFreeRDP::cb_begin_paint(rdpContext *context)
1472 if (!context || !context->gdi || !context->gdi->primary
1473 || !context->gdi->primary->hdc)
1476 hdc = context->gdi->primary->hdc;
1478 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1481 hdc->hwnd->invalid->null = TRUE;
1482 hdc->hwnd->ninvalid = 0;
1486BOOL CConnectFreeRDP::UpdateBuffer(INT32 x, INT32 y, INT32 w, INT32 h)
1488 if(x > m_Image.width() || y > m_Image.height()) {
1489 qCritical(log) <<
"The width and height out of range."
1490 <<
"Image width:" << m_Image.width()
1491 <<
"Image height:" << m_Image.height()
1492 <<
"w:" << w <<
"h:" << h;
1496 QRect rect(x, y, w, h);
1497 QImage img = m_Image.copy(rect);
1503BOOL CConnectFreeRDP::cb_end_paint(rdpContext *context)
1506 ClientContext* pContext = (ClientContext*)context;
1510 REGION16 invalidRegion;
1511 RECTANGLE_16 invalidRect;
1512 const RECTANGLE_16* extents;
1516 if (!context || !context->gdi || !context->gdi->primary
1517 || !context->gdi->primary->hdc)
1520 hdc = context->gdi->primary->hdc;
1522 if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
1525 rdpGdi* gdi = context->gdi;
1526 if (gdi->suppressOutput)
1529 HGDI_WND hwnd = context->gdi->primary->hdc->hwnd;
1530 ninvalid = hwnd->ninvalid;
1531 cinvalid = hwnd->cinvalid;
1535 region16_init(&invalidRegion);
1537 for (i = 0; i < ninvalid; i++)
1539 if(cinvalid[i].null)
1541 qWarning(log) <<
"is null region" << cinvalid[i].x << cinvalid[i].y
1542 << cinvalid[i].w << cinvalid[i].h;
1545 invalidRect.left = cinvalid[i].x;
1546 invalidRect.top = cinvalid[i].y;
1547 invalidRect.right = cinvalid[i].x + cinvalid[i].w;
1548 invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;
1549 region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
1552 if (!region16_is_empty(&invalidRegion))
1554 extents = region16_extents(&invalidRegion);
1556 pThis->UpdateBuffer(extents->left,
1558 extents->right - extents->left,
1559 extents->bottom - extents->top);
1562 region16_uninit(&invalidRegion);
1567BOOL CConnectFreeRDP::cb_desktop_resize(rdpContext* context)
1569 qDebug(log) << Q_FUNC_INFO;
1570 ClientContext* pContext = (ClientContext*)context;
1572 rdpSettings* settings;
1573 if (!context || !context->settings)
1575 settings = context->settings;
1576 int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
1577 int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
1579 if(!gdi_resize(context->gdi, desktopWidth, desktopHeight))
1581 if(!pThis->CreateImage(context))
1584 emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
1585 pThis->UpdateBuffer(0, 0, desktopWidth, desktopHeight);
1589BOOL CConnectFreeRDP::cb_play_bell_sound(rdpContext *context,
const PLAY_SOUND_UPDATE *play_sound)
1591 qDebug(log) << Q_FUNC_INFO;
1592 ClientContext* pContext = (ClientContext*)context;
1594 WINPR_UNUSED(play_sound);
1595 QApplication::beep();
1599#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1600 QSoundEffect effect;
1601 effect.setSource(QUrl::fromLocalFile(szFile));
1606 QSound::play(szFile);
1612BOOL CConnectFreeRDP::cb_keyboard_set_indicators(rdpContext *context, UINT16 led_flags)
1614 qDebug(log) << Q_FUNC_INFO;
1615 ClientContext* pContext = (ClientContext*)context;
1618 int state = CFrmViewer::LED_STATE::Unknown;
1620 if (led_flags & KBD_SYNC_NUM_LOCK)
1621 state |= CFrmViewer::LED_STATE::NumLock;
1622 if (led_flags & KBD_SYNC_CAPS_LOCK)
1623 state |= CFrmViewer::LED_STATE::CapsLock;
1624 if (led_flags & KBD_SYNC_SCROLL_LOCK)
1625 state |= CFrmViewer::LED_STATE::ScrollLock;
1627 emit pThis->sigUpdateLedState(state);
1633BOOL CConnectFreeRDP::cb_keyboard_set_ime_status(
1634 rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode)
1640 "KeyboardSetImeStatus(unitId=%04" PRIx16
", imeState=%08" PRIx32
1641 ", imeConvMode=%08" PRIx32
") ignored",
1642 imeId, imeState, imeConvMode);
1649 SetEvent(m_writeEvent);
1654bool CConnectFreeRDP::SendMouseEvent(UINT16 flags, QPoint pos,
bool isExtended)
1656 if(m_pParameter && m_pParameter->GetOnlyView())
return true;
1657 if(!m_pContext)
return false;
1659#if FreeRDP_VERSION_MAJOR >= 3
1661 freerdp_client_send_extended_button_event(
1662 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
1664 freerdp_client_send_button_event(
1665 &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
1667 if(!m_pContext->Context.input)
return false;
1668 return freerdp_input_send_mouse_event(
1669 m_pContext->Context.input, flags, pos.x(), pos.y());
1674void CConnectFreeRDP::wheelEvent(QWheelEvent *event)
1677 if(!m_pContext)
return;
1678 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1682#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1683 pos =
event->position();
1687 QPoint p =
event->angleDelta();
1690 flags |= PTR_FLAGS_WHEEL | p.y();
1694 flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.y();
1699 flags |= PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.x();
1703 flags |= PTR_FLAGS_HWHEEL | p.x();
1705#if FreeRDP_VERSION_MAJOR >= 3
1706 freerdp_client_send_wheel_event(&m_pContext->Context, flags);
1711 freerdp_input_send_mouse_event(
1712 m_pContext->Context.input, flags, pos.x(), pos.y());
1717void CConnectFreeRDP::mouseMoveEvent(QMouseEvent *event)
1720 if(!m_pContext)
return;
1721 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1722 UINT16 flags = PTR_FLAGS_MOVE;
1723 SendMouseEvent(flags, event->pos(),
false);
1726void CConnectFreeRDP::mousePressEvent(QMouseEvent *event)
1729 if(!m_pContext)
return;
1730 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1733 bool isExtended =
false;
1734 Qt::MouseButton button =
event->button();
1735 if (button & Qt::MouseButton::LeftButton)
1737 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
1739 else if (button & Qt::MouseButton::RightButton)
1741 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
1743 else if (button & Qt::MouseButton::MiddleButton)
1745 flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
1747 else if (button & Qt::MouseButton::ForwardButton)
1749 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
1752 else if (button & Qt::MouseButton::BackButton)
1754 flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
1759 SendMouseEvent(flags, event->pos(), isExtended);
1763void CConnectFreeRDP::mouseReleaseEvent(QMouseEvent *event)
1766 if(!m_pContext)
return;
1767 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1770 bool isExtended =
false;
1771 Qt::MouseButton button =
event->button();
1772 if (button & Qt::MouseButton::LeftButton)
1774 flags = PTR_FLAGS_BUTTON1;
1776 else if (button & Qt::MouseButton::MiddleButton)
1778 flags = PTR_FLAGS_BUTTON3;
1780 else if (button & Qt::MouseButton::RightButton)
1782 flags = PTR_FLAGS_BUTTON2;
1784 else if (button & Qt::MouseButton::ForwardButton)
1786 flags = PTR_XFLAGS_BUTTON2;
1789 else if (button & Qt::MouseButton::BackButton)
1791 flags = PTR_XFLAGS_BUTTON1;
1796 SendMouseEvent(flags, event->pos(), isExtended);
1800void CConnectFreeRDP::keyPressEvent(QKeyEvent *event)
1803 if(!m_pContext)
return;
1804 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1807 if(RDP_SCANCODE_UNKNOWN != k)
1808#if FreeRDP_VERSION_MAJOR >= 3
1809 freerdp_input_send_keyboard_event_ex(
1810 m_pContext->Context.context.input,
true,
true, k);
1812 freerdp_input_send_keyboard_event_ex(
1813 m_pContext->Context.input,
true, k);
1817void CConnectFreeRDP::keyReleaseEvent(QKeyEvent *event)
1820 if(!m_pContext)
return;
1821 if(m_pParameter && m_pParameter->GetOnlyView())
return;
1823 if(RDP_SCANCODE_UNKNOWN != k)
1824#if FreeRDP_VERSION_MAJOR >= 3
1825 freerdp_input_send_keyboard_event_ex(
1826 m_pContext->Context.context.input,
false,
false, k);
1828 freerdp_input_send_keyboard_event_ex(
1829 m_pContext->Context.input,
false, k);
1833int CConnectFreeRDP::RedirectionSound()
1835 rdpContext* pRdpContext = (rdpContext*)m_pContext;
1836 freerdp* instance = freerdp_client_get_instance(pRdpContext);
1837 rdpSettings* settings = instance->context->settings;
1840 if(m_pParameter->GetRedirectionSound()
1841 == CParameterFreeRDP::RedirecionSoundType::Disable)
1844 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE);
1845 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE);
1847 }
else if(m_pParameter->GetRedirectionSound()
1848 == CParameterFreeRDP::RedirecionSoundType::Local)
1850 freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, TRUE);
1851 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
1852 }
else if(m_pParameter->GetRedirectionSound()
1853 == CParameterFreeRDP::RedirecionSoundType::Remote)
1855 freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, TRUE);
1870 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"rdpsnd",
1871 m_pParameter->GetRedirectionSoundParameters().toStdString().c_str(),
1873 BOOL status = freerdp_client_add_static_channel(settings, count,
1874 #
if FreeRDP_VERSION_MAJOR < 3
1882 status = freerdp_client_add_dynamic_channel(settings, count,
1883 #
if FreeRDP_VERSION_MAJOR < 3
1893 qCritical(log) <<
"Load rdpsnd fail";
1900int CConnectFreeRDP::RedirectionMicrophone()
1902 if(m_pParameter->GetRedirectionSound()
1903 == CParameterFreeRDP::RedirecionSoundType::Remote)
1905 if(!m_pParameter->GetRedirectionMicrophone())
1908 rdpContext* pRdpContext = (rdpContext*)m_pContext;
1909 freerdp* instance = freerdp_client_get_instance(pRdpContext);
1911 rdpSettings* settings = instance->context->settings;
1914 freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
1925 ptr.p = CommandLineParseCommaSeparatedValuesEx(
"audin",
1926 m_pParameter->GetRedirectionMicrophoneParameters().toStdString().c_str(),
1928 BOOL status = freerdp_client_add_dynamic_channel(settings, count,
1929 #
if FreeRDP_VERSION_MAJOR < 3
1938 qCritical(log) <<
"Load audin fail";
1945int CConnectFreeRDP::RedirectionDriver()
1947 QStringList lstDrives = m_pParameter->GetRedirectionDrives();
1948 if(lstDrives.isEmpty())
1951 rdpContext* pRdpContext = (rdpContext*)m_pContext;
1952 freerdp* instance = freerdp_client_get_instance(pRdpContext);
1953 rdpSettings* settings = instance->context->settings;
1956 foreach (
auto drive, lstDrives) {
1958 char* pDrive = _strdup(drive.toStdString().c_str());
1959 const char* argvDrive[] = {
"drive", pDrive};
1960 int count =
sizeof(argvDrive) /
sizeof(
const char*);
1961 BOOL status = freerdp_client_add_device_channel(settings, count,
1962 #
if FreeRDP_VERSION_MAJOR < 3
1966 if(pDrive) free(pDrive);
1969 qCritical(log) <<
"Load drive fail";
1977int CConnectFreeRDP::RedirectionPrinter()
1979 if(!m_pParameter->GetRedirectionPrinter())
1982 rdpContext* pRdpContext = (rdpContext*)m_pContext;
1983 freerdp* instance = freerdp_client_get_instance(pRdpContext);
1984 rdpSettings* settings = instance->context->settings;
1987 QStringList printerList = QPrinterInfo::availablePrinterNames();
1988 if(printerList.isEmpty())
1990 qCritical(log) <<
"The printer is empty";
1993 qDebug(log) << printerList;
1996 const char* argvPrinter[] = {
"printer",
nullptr,
nullptr};
1997 int count =
sizeof(argvPrinter) /
sizeof(
const char*);
1998 BOOL status = freerdp_client_add_device_channel(settings, count,
1999 #
if FreeRDP_VERSION_MAJOR < 3
2004 qCritical(log) <<
"Load printer fail";
2011int CConnectFreeRDP::RedirectionSerial()
2015 rdpContext* pRdpContext = (rdpContext*)m_pContext;
2016 freerdp* instance = freerdp_client_get_instance(pRdpContext);
2017 rdpSettings* settings = instance->context->settings;
2020 QList<QSerialPortInfo> lstSerial = QSerialPortInfo::availablePorts();
2023 foreach (
auto serial, lstSerial) {
2026 qDebug(log) <<
"systemLocation:" << serial.systemLocation()
2027 <<
"portName:" << serial.portName()
2028 <<
"serialNumber:" << serial.serialNumber();
2029 char* pSerial = _strdup(serial.systemLocation().toStdString().c_str());
2030 char* pName = _strdup(serial.portName().toStdString().c_str());
2031 const char* argvSerial[] = {
"serial", pName, pSerial};
2032 int count =
sizeof(argvSerial) /
sizeof(
const char*);
2033 BOOL status = freerdp_client_add_device_channel(settings, count,
2034 #
if FreeRDP_VERSION_MAJOR < 3
2038 if(pSerial) free(pSerial);
2039 if(pName) free(pName);
2043 qCritical(log) <<
"Load drive fail";
2051void CConnectFreeRDP::slotConnectProxyServer(QString szHost, quint16 nPort)
2053 qDebug(log) <<
"CConnectFreeRDP::slotConnectProxyServer" << nPort;
2054 rdpContext* pContext = (rdpContext*)m_pContext;
2055 rdpSettings* settings = pContext->settings;
2057 qCritical(log) <<
"settings is null";
2060 freerdp_settings_set_string(
2061 settings, FreeRDP_ServerHostname,
2062 szHost.toStdString().c_str());
2063 freerdp_settings_set_uint32(
2064 settings, FreeRDP_ServerPort,
2067 int nRet = freerdp_client_start(pContext);
2070 qCritical(log) <<
"freerdp_client_start fail";
2072 qDebug(log) <<
"CConnectFreeRDP::slotConnectProxyServer end";
Remote desktop connect interface.
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
virtual OnInitReturnValue OnInit() override
Specific plug-in realizes connection initialization.
virtual int OnClean() override
Clean.
static int cb_verify_x509_certificate(freerdp *instance, const BYTE *data, size_t length, const char *hostname, UINT16 port, DWORD flags)
Callback used if user interaction is required to accept a certificate.
static DWORD cb_verify_changed_certificate_ex(freerdp *instance, const char *host, UINT16 port, const char *common_name, const char *subject, const char *issuer, const char *fingerprint, const char *old_subject, const char *old_issuer, const char *old_fingerprint, DWORD flags)
Callback set in the rdp_freerdp structure, and used to make a certificate validation when a stored ce...
virtual int WakeUp() override
Wake up Connect thread(background thread)
static DWORD cb_verify_certificate_ex(freerdp *instance, const char *host, UINT16 port, const char *common_name, const char *subject, const char *issuer, const char *fingerprint, DWORD flags)
Callback set in the rdp_freerdp structure, and used to make a certificate validation when the connect...
virtual int OnProcess() override
Specific operation processing of plug-in connection.
static BOOL cb_post_connect(freerdp *instance)
Callback given to freerdp_connect() to perform post-connection operations.
static BOOL cb_pre_connect(freerdp *instance)
Callback given to freerdp_connect() to process the pre-connect operations.
void sigError(const int nError, const QString &szError=QString())
Triggered when an error is generated.
void sigInformation(const QString &szInfo)
Triggering from a background thread displays information in the main thread without blocking the back...
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 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 sigBlockInputDialog(const QString &szTitle, const QString &szLable, const QString &szMessage, QString &szText)
Block background threads and display input dialogs in foreground threads (QInputDialog)
void sigConnected()
Emitted when the plugin is successfully connected.
void sigDisconnect()
Notify the user to call disconnect.
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
Blocks the background thread and displays the window in the foreground thread.
static UINT32 QtToScanCode(int key, Qt::KeyboardModifiers modifiers)
CConvertKeyCode::QtToScanCode.
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.