6#undef PEN_FLAG_INVERTED 
    7#include "freerdp/client.h" 
    8#include "freerdp/client/channels.h" 
    9#include "freerdp/channels/rdpei.h" 
   10#include "freerdp/channels/rdpdr.h" 
   11#include "freerdp/channels/disp.h" 
   12#include "freerdp/channels/tsmf.h" 
   13#include "freerdp/channels/rdpsnd.h" 
   14#include "freerdp/client/encomsp.h" 
   15#include "freerdp/gdi/gfx.h" 
   16#include "freerdp/settings.h" 
   17#include "freerdp/locale/keyboard.h" 
   18#include "freerdp/channels/rdpgfx.h" 
   19#include "freerdp/channels/cliprdr.h" 
   20#include "freerdp/client/cmdline.h" 
   21#include "freerdp/gdi/video.h" 
   22#include "winpr/winsock.h" 
   24#include "BackendFreeRDP.h" 
   25#include "RabbitCommonTools.h" 
   26#include "ConvertKeyCode.h" 
   30#include <QApplication> 
   32#include <QSslCertificate> 
   33#include <QInputDialog> 
   34#include <QMutexLocker> 
   36#include <QPrinterInfo> 
   38#include <QSerialPortInfo> 
   39#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 
   40    #include <QSoundEffect> 
   45#ifdef WINPR_HAVE_POLL_H 
   52#include <sys/select.h> 
   56#if FREERDP_VERSION_MAJOR >= 3 
   57#include "ConnectLayerQTcpSocket.h" 
   59#include "ConnectLayerSSHTunnel.h" 
   64static Q_LOGGING_CATEGORY(log, 
"FreeRDP.Connect")
 
   65static Q_LOGGING_CATEGORY(logKey, "FreeRDP.Connect.Key")
 
   66static Q_LOGGING_CATEGORY(logMouse, "FreeRDP.Connect.Mouse")
 
   70    , m_pOperate(pOperate)
 
   72    , m_pParameter(
nullptr)
 
   75    , m_writeEvent(
nullptr)
 
   76#if FREERDP_VERSION_MAJOR >= 3 
   77    , m_pConnectLayer(
nullptr)
 
   80    , m_pThreadSSH(
nullptr)
 
   83    qDebug(log) << Q_FUNC_INFO;
 
   84    m_pParameter = qobject_cast<CParameterFreeRDP*>(pOperate->GetParameter());
 
   85    Q_ASSERT(m_pParameter);
 
   88CBackendFreeRDP::~CBackendFreeRDP()
 
   90    qDebug(log) << Q_FUNC_INFO;
 
  101    qDebug(log) << Q_FUNC_INFO;
 
  104    m_writeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 
  106        qCritical(log) << 
"CreateEvent failed";
 
  107        return OnInitReturnValue::Fail;
 
  109    ZeroMemory(&m_ClientEntryPoints, 
sizeof(RDP_CLIENT_ENTRY_POINTS));
 
  110    m_ClientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
 
  111    m_ClientEntryPoints.Size = 
sizeof(RDP_CLIENT_ENTRY_POINTS);
 
  113    m_ClientEntryPoints.GlobalInit = cbGlobalInit;
 
  114    m_ClientEntryPoints.GlobalUninit = cbGlobalUninit;
 
  115    m_ClientEntryPoints.ClientNew = cbClientNew;
 
  116    m_ClientEntryPoints.ClientFree = cbClientFree;
 
  117    m_ClientEntryPoints.ClientStart = cbClientStart;
 
  118    m_ClientEntryPoints.ClientStop = cbClientStop;
 
  121    auto pRdpContext = freerdp_client_context_new(&m_ClientEntryPoints);
 
  125        m_pContext->pThis = 
this;
 
  127        qCritical(log) << 
"freerdp_client_context_new fail";
 
  128        return OnInitReturnValue::Fail;
 
  131    rdpSettings* settings = pRdpContext->settings;
 
  133        qCritical(log) << 
"settings is null";
 
  134        return OnInitReturnValue::Fail;
 
  147    char* argv[]= {(
char*)QApplication::applicationFilePath().toStdString().c_str()};
 
  148    int argc = 
sizeof(argv) / 
sizeof(
char*);
 
  149    nRet = freerdp_client_settings_parse_command_line(settings, argc, argv, TRUE);
 
  152        nRet = freerdp_client_settings_command_line_status_print(settings, nRet, argc, argv);
 
  153        return OnInitReturnValue::Fail;
 
  156#if FREERDP_VERSION_MAJOR >= 3 
  157    if (!stream_dump_register_handlers(pRdpContext,
 
  158                                       CONNECTION_STATE_MCS_CREATE_REQUEST,
 
  160        return OnInitReturnValue::Fail;
 
  163    auto &user = m_pParameter->m_Net.
m_User;
 
  164    if(!user.GetUser().isEmpty())
 
  165        freerdp_settings_set_string(
 
  166            settings, FreeRDP_Username,
 
  167            user.GetUser().toStdString().c_str());
 
  168    if(!user.GetPassword().isEmpty())
 
  169        freerdp_settings_set_string(
 
  170            settings, FreeRDP_Password,
 
  171            user.GetPassword().toStdString().c_str());
 
  173    freerdp_settings_set_bool(
 
  174        settings, FreeRDP_RedirectClipboard, m_pParameter->GetClipboard());
 
  176#if FREERDP_VERSION_MAJOR >= 3 
  177    bool bOnlyView = m_pParameter->GetOnlyView();
 
  178    freerdp_settings_set_bool(
 
  179        settings, FreeRDP_SuspendInput, bOnlyView);
 
  182    freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
 
  183                                m_pParameter->GetDesktopWidth());
 
  184    freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
 
  185                                m_pParameter->GetDesktopHeight());
 
  186    freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth,
 
  187                                m_pParameter->GetColorDepth());
 
  189    freerdp_settings_set_bool(settings, FreeRDP_UseMultimon,
 
  190                              m_pParameter->GetUseMultimon());
 
  192    if(m_pParameter->GetReconnectInterval()) {
 
  193        freerdp_settings_set_bool(
 
  194            settings, FreeRDP_AutoReconnectionEnabled, 
true);
 
  195        freerdp_settings_set_uint32(
 
  197            FreeRDP_AutoReconnectMaxRetries,
 
  198            m_pParameter->GetReconnectInterval());
 
  201        freerdp_settings_set_bool(
 
  202            settings, FreeRDP_AutoReconnectionEnabled, 
false);
 
  206    RedirectionMicrophone();
 
  208    RedirectionPrinter();
 
  213    switch(m_pParameter->m_Proxy.GetUsedType())
 
  215    case CParameterProxy::TYPE::System:
 
  217    case CParameterProxy::TYPE::Http:
 
  218    case CParameterProxy::TYPE::SockesV5:
 
  221        if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_SOCKS))
 
  222            return OnInitReturnValue::Fail;
 
  223        if(CParameterProxy::TYPE::Http == m_pParameter->m_Proxy.GetUsedType()) {
 
  224            net = &m_pParameter->m_Proxy.m_Http;
 
  225            if (!freerdp_settings_set_uint32(settings, FreeRDP_ProxyType, PROXY_TYPE_HTTP))
 
  226                return OnInitReturnValue::Fail;
 
  229        if (!freerdp_settings_set_string(settings, FreeRDP_ProxyHostname,
 
  230                                         net->GetHost().toStdString().c_str()))
 
  231            return OnInitReturnValue::Fail;
 
  232        if (!freerdp_settings_set_uint16(settings, FreeRDP_ProxyPort, net->GetPort()))
 
  233            return OnInitReturnValue::Fail;
 
  235        if(((user.GetUsedType() == CParameterUser::TYPE::UserPassword)
 
  236             && (user.GetPassword().isEmpty() || user.GetUser().isEmpty()))
 
  237            || ((user.GetUsedType() == CParameterUser::TYPE::PublicKey)
 
  238                && user.GetPassphrase().isEmpty())) {
 
  239            int nRet = QDialog::Rejected;
 
  241            if(QDialog::Accepted != nRet)
 
  243                return OnInitReturnValue::Fail;
 
  246        if (!freerdp_settings_set_string(settings, FreeRDP_ProxyUsername,
 
  247                                         user.GetUser().toStdString().c_str()))
 
  248            return OnInitReturnValue::Fail;
 
  249        if (!freerdp_settings_set_string(settings, FreeRDP_ProxyPassword,
 
  250                                         user.GetPassword().toStdString().c_str()))
 
  251            return OnInitReturnValue::Fail;
 
  262    case CParameterProxy::TYPE::None:
 
  264        if(!m_pParameter->GetDomain().isEmpty())
 
  265            freerdp_settings_set_string(
 
  266                settings, FreeRDP_Domain,
 
  267                m_pParameter->GetDomain().toStdString().c_str());
 
  268        if(m_pParameter->m_Net.GetHost().isEmpty())
 
  271            szErr = tr(
"The server is empty, please input it");
 
  272            qCritical(log) << szErr;
 
  274            emit 
sigError(-1, szErr.toStdString().c_str());
 
  275            return OnInitReturnValue::Fail;
 
  277        auto &net = m_pParameter->m_Net;
 
  278        freerdp_settings_set_string(
 
  279            settings, FreeRDP_ServerHostname,
 
  280            net.GetHost().toStdString().c_str());
 
  281        freerdp_settings_set_uint32(
 
  282            settings, FreeRDP_ServerPort,
 
  285        nRet = freerdp_client_start(pRdpContext);
 
  288            qCritical(log) << 
"freerdp_client_start fail";
 
  289            return OnInitReturnValue::Fail;
 
  294    case CParameterProxy::TYPE::SSHTunnel:
 
  296#if FREERDP_VERSION_MAJOR >= 3 
  298        if(!m_pConnectLayer) 
return OnInitReturnValue::Fail;
 
  299        nRet = m_pConnectLayer->Initialize(pRdpContext);
 
  300        if(nRet) 
return OnInitReturnValue::Fail;
 
  303        return InitSSHTunnelPipe();
 
  308        qCritical(log) << 
"Don't support proxy type:" << m_pParameter->m_Proxy.GetUsedType();
 
  312    return OnInitReturnValue::UseOnProcess;
 
 
  317    qDebug(log) << Q_FUNC_INFO;
 
  321        CloseHandle(m_writeEvent);
 
  322        m_writeEvent = 
nullptr;
 
  326        rdpContext* pRdpContext = (rdpContext*)m_pContext;
 
  327        if(!freerdp_disconnect(pRdpContext->instance))
 
  328            qCritical(log) << 
"freerdp_disconnect fail";
 
  330        if(freerdp_client_stop(pRdpContext))
 
  331            qCritical(log) << 
"freerdp_client_stop fail";
 
  333        freerdp_client_context_free(pRdpContext);
 
  334        m_pContext = 
nullptr;
 
  337#if FREERDP_VERSION_MAJOR >= 3 
  338    if(m_pConnectLayer) {
 
  339        m_pConnectLayer->Clean();
 
  340        m_pConnectLayer->deleteLater();
 
  341        m_pConnectLayer = 
nullptr;
 
  346    CleanSSHTunnelPipe();
 
 
  388    rdpContext* pRdpContext = (rdpContext*)m_pContext;
 
  390    if(
nullptr == freerdp_settings_get_string(pRdpContext->settings, FreeRDP_ServerHostname))
 
  398        nCount += freerdp_get_event_handles(pRdpContext, &handles[nCount],
 
  399                                           ARRAYSIZE(handles) - nCount);
 
  402            qCritical(log) << 
"freerdp_get_event_handles failed";
 
  408            handles[nCount++] = m_writeEvent;
 
  410        DWORD waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, nTimeout);
 
  413            ResetEvent(m_writeEvent);
 
  415        if (waitStatus == WAIT_FAILED)
 
  417            qCritical(log) << 
"WaitForMultipleObjects: WAIT_FAILED";
 
  422        if(waitStatus == WAIT_TIMEOUT)
 
  429        if (!freerdp_check_event_handles(pRdpContext))
 
  433            UINT32 err = freerdp_get_last_error(pRdpContext);
 
  435            szErr = 
"freerdp_check_event_handles fail.";
 
  437            szErr += QString::number(err);
 
  439            szErr += freerdp_get_last_error_category(err);
 
  441            szErr += freerdp_get_last_error_name(err);
 
  443            szErr += freerdp_get_last_error_string(err);
 
  444            qCritical(log) << szErr;
 
  468#if FREERDP_VERSION_MAJOR >= 3 
  469        if(freerdp_shall_disconnect_context(pRdpContext))
 
  471        if(freerdp_shall_disconnect(pRdpContext->instance))
 
  474            qCritical(log) << 
"freerdp_shall_disconnect false";
 
 
  482void CBackendFreeRDP::slotClipBoardChanged()
 
  484    qDebug(log) << Q_FUNC_INFO;
 
  485    if(m_pParameter && m_pParameter->GetOnlyView()) 
return;
 
  486    if(m_pParameter->GetClipboard())
 
  487        m_ClipBoard.slotClipBoardChanged();
 
  490BOOL CBackendFreeRDP::cbGlobalInit()
 
  492    qDebug(log) << Q_FUNC_INFO;
 
  496void CBackendFreeRDP::cbGlobalUninit()
 
  498    qDebug(log) << Q_FUNC_INFO;
 
  501BOOL CBackendFreeRDP::cbClientNew(freerdp *instance, rdpContext *context)
 
  503    qDebug(log) << Q_FUNC_INFO;
 
  506    instance->PostDisconnect = cb_post_disconnect;
 
  509#if FREERDP_VERSION_MAJOR < 3 
  510    instance->Authenticate = cb_authenticate;
 
  511    instance->GatewayAuthenticate = cb_GatewayAuthenticate;
 
  513    instance->AuthenticateEx = cb_authenticate_ex;
 
  514    instance->ChooseSmartcard = cb_choose_smartcard;
 
  519    instance->PresentGatewayMessage = cb_present_gateway_message;
 
  521    instance->LogonErrorInfo = cb_logon_error_info;
 
  526void CBackendFreeRDP::cbClientFree(freerdp *instance, rdpContext *context)
 
  528    qDebug(log) << Q_FUNC_INFO;
 
  531int CBackendFreeRDP::cbClientStart(rdpContext *context)
 
  533    qDebug(log) << Q_FUNC_INFO;
 
  536    if (!context || !context->settings)
 
  538    freerdp* instance = freerdp_client_get_instance(context);
 
  542    auto settings = context->settings;
 
  544    QString szDomainHost;
 
  546    szDomainHost = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
 
  547    nPort = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
 
  549    auto &net = pThis->m_pParameter->m_Net;
 
  550    szServer = net.GetHost() + 
":" + QString::number(net.GetPort());
 
  551    auto &proxy = pThis->m_pParameter->m_Proxy;
 
  552    switch(proxy.GetUsedType()) {
 
  553    case CParameterProxy::TYPE::SockesV5:
 
  555        auto &sockesV5 = proxy.m_SockesV5;
 
  556        szServer = sockesV5.GetHost() + 
":" + QString::number(sockesV5.GetPort())
 
  560    case CParameterProxy::TYPE::Http:
 
  562        auto &http = proxy.m_Http;
 
  563        szServer = http.GetHost() + 
":" + QString::number(http.GetPort())
 
  567    case CParameterProxy::TYPE::SSHTunnel:
 
  569        auto &sshNet = proxy.m_SSH.m_Net;
 
  570#if FREERDP_VERSION_MAJOR < 3 
  571        szServer = szDomainHost + 
":" + QString::number(nPort)
 
  572                   + 
" -> " + sshNet.GetHost() + 
":" + QString::number(sshNet.GetPort())
 
  575        szServer = sshNet.GetHost() + 
":" + QString::number(sshNet.GetPort())
 
  584    BOOL status = freerdp_connect(instance);
 
  586        QString szInfo = tr(
"Connected to ") + szServer;
 
  587        qInfo(log) << szInfo;
 
  591        UINT32 nRet = freerdp_get_last_error(context);
 
  594        szErr = tr(
"Connect to ") + szServer + tr(
" fail.");
 
  596        szErr += QString::number(nRet) + 
" - ";
 
  597        szErr += freerdp_get_last_error_name(nRet);
 
  602        szErr += freerdp_get_last_error_string(nRet);
 
  606        case FREERDP_ERROR_CONNECT_LOGON_FAILURE:
 
  608            szErr = tr(
"Logon to ") + szServer;
 
  609            szErr += tr(
" fail. Please check that the username and password are correct.") + 
"\n";
 
  612        case FREERDP_ERROR_CONNECT_WRONG_PASSWORD:
 
  614            szErr = tr(
"Logon to ") + szServer;
 
  615            szErr += tr(
" fail. Please check password are correct.") + 
"\n";
 
  618        case FREERDP_ERROR_AUTHENTICATION_FAILED:
 
  620            szErr = tr(
"Logon to ") + szServer;
 
  621            szErr += tr(
" authentication fail. please add a CA certificate to the store.") + 
"\n";
 
  624        case FREERDP_ERROR_CONNECT_TRANSPORT_FAILED:
 
  626            szErr = tr(
"Logon to ") + szServer;
 
  627            szErr += tr(
" connect transport layer fail.") + 
"\n\n";
 
  628            szErr += tr(
"Please:") + 
"\n";
 
  629            szErr += tr(
"1. Check for any network related issues") + 
"\n";
 
  630            szErr += tr(
"2. Check you have proper security settings ('NLA' enabled is required for most connections nowadays)") + 
"\n";
 
  631            szErr += 
"    " + tr(
"If you do not know the server security settings, contact your server administrator.") + 
"\n";
 
  632            szErr += tr(
"3. Check the certificate is proper (and guacd properly checks that)") + 
"\n";
 
  635        case FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED:
 
  637            szErr += tr(
"Please check you have proper security settings.") + 
"\n";
 
  638            szErr += tr(
"If you do not know the server security settings, contact your server administrator.");
 
  640        case FREERDP_ERROR_CONNECT_CANCELLED:
 
  641            szErr = tr(
"The connect was canceled.") + 
"\n\n" + szErr;
 
  648        qCritical(log) << szErr;
 
  649        emit pThis->
sigError(nRet, szErr.toStdString().c_str());
 
  655int CBackendFreeRDP::cbClientStop(rdpContext *context)
 
  658    qDebug(log) << Q_FUNC_INFO;
 
  659#if FREERDP_VERSION_MAJOR >= 3 
  660    nRet = freerdp_client_common_stop(context);
 
  662    BOOL bRet = freerdp_abort_connect(context->instance);
 
  664    {   qCritical(log) << 
"freerdp_abort_connect fail";
 
  691    qDebug(log) << Q_FUNC_INFO;
 
  692    rdpChannels* channels = 
nullptr;
 
  693    rdpSettings* settings = 
nullptr;
 
  694    rdpContext* context = instance->context;
 
  696    if (!instance || !instance->context || !instance->context->settings)
 
  700    if(!pThis) 
return FALSE;
 
  701    settings = instance->context->settings;
 
  702    channels = context->channels;
 
  704    if(!channels || !pParameter)
 
  708#if defined (Q_OS_WIN) 
  709    if (!freerdp_settings_set_uint32(
 
  710            settings, FreeRDP_OsMajorType, OSMAJORTYPE_WINDOWS))
 
  712    if (!freerdp_settings_set_uint32(
 
  713            settings, FreeRDP_OsMinorType, OSMINORTYPE_WINDOWS_NT))
 
  715#elif defined(Q_OS_ANDROID) 
  716    if (!freerdp_settings_set_uint32(
 
  717            settings, FreeRDP_OsMajorType, OSMAJORTYPE_ANDROID))
 
  719    if (!freerdp_settings_set_uint32(
 
  720            settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
 
  722#elif defined(Q_OS_IOS) 
  723    if (!freerdp_settings_set_uint32(
 
  724            settings, FreeRDP_OsMajorType, OSMAJORTYPE_IOS))
 
  726    if (!freerdp_settings_set_uint32(
 
  727            settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
 
  729#elif defined (Q_OS_UNIX) 
  730    if (!freerdp_settings_set_uint32(
 
  731            settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX))
 
  733    if (!freerdp_settings_set_uint32(
 
  734            settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_XSERVER))
 
  737    if (!freerdp_settings_set_uint32(
 
  738            settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNSPECIFIED))
 
  740    if (!freerdp_settings_set_uint32(
 
  741            settings, FreeRDP_OsMinorType, OSMINORTYPE_UNSPECIFIED))
 
  746    PubSub_SubscribeChannelConnected(instance->context->pubSub,
 
  747                                     OnChannelConnectedEventHandler);
 
  748    PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
 
  749                                        OnChannelDisconnectedEventHandler);
 
  751#if FREERDP_VERSION_MAJOR < 3 
  752    if (!freerdp_client_load_addins(channels, instance->context->settings))
 
  755    #if defined(Q_OS_LINUX) || (defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE)) 
  756        if (!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, TRUE))
 
  761    if(!freerdp_settings_set_bool(
 
  762            settings, FreeRDP_NegotiateSecurityLayer,
 
  763            pParameter->GetNegotiateSecurityLayer()))
 
  765    CParameterFreeRDP::Security security = pParameter->GetSecurity();
 
  767    if(!freerdp_settings_set_bool(
 
  768            settings, FreeRDP_RdpSecurity,
 
  769            CParameterFreeRDP::Security::RDP & security))
 
  771    if (!freerdp_settings_set_bool(
 
  772            settings, FreeRDP_UseRdpSecurityLayer,
 
  773            CParameterFreeRDP::Security::RDP & security))
 
  776    if(!freerdp_settings_set_bool(
 
  777            settings, FreeRDP_TlsSecurity,
 
  778            CParameterFreeRDP::Security::TLS & security))
 
  780    if(!freerdp_settings_set_bool(
 
  781            settings, FreeRDP_NlaSecurity,
 
  782            CParameterFreeRDP::Security::NLA & security))
 
  784    if(!freerdp_settings_set_bool(
 
  785            settings, FreeRDP_ExtSecurity,
 
  786            CParameterFreeRDP::Security::NLA_Ext & security))
 
  788#if FREERDP_VERSION_MAJOR >= 3 
  789    if(!freerdp_settings_set_bool(
 
  790            settings, FreeRDP_AadSecurity,
 
  791            CParameterFreeRDP::Security::RDSAAD & security))
 
  793    if(!freerdp_settings_set_bool(
 
  794            settings, FreeRDP_RdstlsSecurity,
 
  795            CParameterFreeRDP::Security::RDSTLS & security))
 
  797    freerdp_settings_set_uint16(settings, FreeRDP_TLSMinVersion,
 
  798                                pParameter->GetTlsVersion());
 
  802    if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly))
 
  805        auto &user = pParameter->m_Net.
m_User;
 
  806        if(!freerdp_settings_get_string(settings, FreeRDP_Username)) {
 
  807            if(user.GetUser().isEmpty()) {
 
  809                qWarning(log) << 
"Auth-only, but no user name set. Will be call instance->Authenticate.";
 
  811                freerdp_settings_set_string(
 
  812                    settings, FreeRDP_Username,
 
  813                    user.GetUser().toStdString().c_str());
 
  815        if (!freerdp_settings_get_string(settings, FreeRDP_Password)) {
 
  816            if (user.GetPassword().isEmpty()) {
 
  818                qWarning(log) << 
"auth-only, but no password set. Will be call instance->Authenticate";
 
  820                freerdp_settings_set_string(
 
  821                    settings, FreeRDP_Password,
 
  822                    user.GetPassword().toStdString().c_str());
 
  824#if FREERDP_VERSION_MAJOR >= 3 
  825        if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE))
 
  828    } 
else if(freerdp_settings_get_bool(settings, FreeRDP_CredentialsFromStdin)){
 
  830    } 
else if(freerdp_settings_get_bool(settings, FreeRDP_SmartcardLogon)) {
 
  841    UINT32 width = pParameter->GetDesktopWidth();
 
  842    UINT32 height = pParameter->GetDesktopHeight();
 
  843    if ((width < 64) || (height < 64) ||
 
  844            (width > 4096) || (height > 4096))
 
  846        QString szErr = tr(
"Invalid dimensions:")
 
  847                        + QString::number(width)
 
  848                        + 
"*" + QString::number(height);
 
  849        qCritical(log) << szErr;
 
  853        qInfo(log) << 
"Init desktop size " <<  width << 
"*" << height;
 
  857        << 
"width:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth)
 
  858        << 
"height:" << freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight)
 
  859        << 
"ColorDepth:" << freerdp_settings_get_uint32(settings, FreeRDP_ColorDepth);
 
  870    if(!freerdp_set_connection_type(settings, pParameter->GetConnectType()))
 
  872    freerdp_settings_set_uint32(
 
  873        settings, FreeRDP_PerformanceFlags, pParameter->GetPerformanceFlags());
 
  874    freerdp_performance_flags_split(settings);
 
  876    freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, pParameter->GetEnableLocalInputMethod());
 
 
  880const char* CBackendFreeRDP::GetTitle(freerdp* instance)
 
  882    const char* windowTitle;
 
  885    const char* name = 
nullptr;
 
  888    rdpSettings* settings = instance->context->settings;
 
  893    windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
 
  897#if FREERDP_VERSION_MAJOR >= 3 
  898    name = freerdp_settings_get_server_name(settings);
 
  900    name = pThis->m_pParameter->m_Net.GetHost().toStdString().c_str();
 
  902    port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
 
  904    addPort = (port != 3389);
 
  906    char buffer[MAX_PATH + 64] = { 0 };
 
  909        sprintf_s(buffer, 
sizeof(buffer), 
"%s", name);
 
  911        sprintf_s(buffer, 
sizeof(buffer), 
"%s:%" PRIu32, name, port);
 
  913    freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer);
 
  914    return freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
 
  924    qDebug(log) << Q_FUNC_INFO;
 
  926    rdpContext* context = instance->context;
 
  927    rdpSettings* settings = instance->context->settings;
 
  928    rdpUpdate* update = instance->context->update;
 
  931    const char* pWindowTitle = GetTitle(instance);
 
  934        WCHAR* windowTitle = NULL;
 
  935#if FREERDP_VERSION_MAJOR >= 3 
  936        windowTitle = ConvertUtf8ToWCharAlloc(pWindowTitle, NULL);
 
  938        ConvertToUnicode(CP_UTF8, 0, pWindowTitle, -1, &windowTitle, 0);
 
  942            QString title = QString::fromUtf16((
const char16_t*)windowTitle);
 
  944            if(pThis->m_pParameter->GetServerName().isEmpty())
 
  945                emit pThis->sigServerName(title);
 
  949    int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
 
  950    int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
 
  951    emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
 
  953    if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
 
  956    if(!pThis->CreateImage(instance->context))
 
  959    Q_ASSERT(instance->context->cache);
 
  962    if(pThis->m_Cursor.RegisterPointer(context->graphics))
 
  965    update->BeginPaint = cb_begin_paint;
 
  966    update->EndPaint = cb_end_paint;
 
  967    update->DesktopResize = cb_desktop_resize;
 
  969    update->PlaySound = cb_play_bell_sound;
 
  971    update->SetKeyboardIndicators = cb_keyboard_set_indicators;
 
  972    update->SetKeyboardImeStatus = cb_keyboard_set_ime_status;
 
 
  978void CBackendFreeRDP::cb_post_disconnect(freerdp* instance)
 
  980    qDebug(log) << Q_FUNC_INFO;
 
  981    rdpContext* context = 
nullptr;
 
  983    if (!instance || !instance->context)
 
  986    context = instance->context;
 
  988    PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
 
  989                                       OnChannelConnectedEventHandler);
 
  990    PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
 
  991                                          OnChannelDisconnectedEventHandler);
 
  995int CBackendFreeRDP::cb_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
 
  998    const char* str_data = freerdp_get_logon_error_info_data(data);
 
  999    const char* str_type = freerdp_get_logon_error_info_type(type);
 
 1000    QString szErr = tr(
"FreeRDP logon info: [");
 
 1004    qDebug(log) << szErr;
 
 1010void CBackendFreeRDP::OnChannelConnectedEventHandler(
void *context,
 
 1011                                                     #
if FREERDP_VERSION_MAJOR >= 3
 
 1014                                                     ChannelConnectedEventArgs *e)
 
 1016    rdpContext* pContext = (rdpContext*)context;
 
 1018    if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
 
 1019        qDebug(log) << 
"channel" << e->name << 
"connected";
 
 1020        pThis->m_ClipBoard.Init((CliprdrClientContext*)e->pInterface,
 
 1021                                pThis->m_pParameter->GetClipboard());
 
 1023#if FREERDP_VERSION_MAJOR >= 3 
 1025        freerdp_client_OnChannelConnectedEventHandler(pContext, e);
 
 1027    else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
 
 1029        if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
 
 1030            rdpGdi* gdi = pContext->gdi;
 
 1032            gdi_graphics_pipeline_init(gdi, (RdpgfxClientContext*) e->pInterface);
 
 1035            qDebug(log, 
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
 
 1037    else if (strcmp(e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0)
 
 1039        gdi_video_geometry_init(pContext->gdi, (GeometryClientContext*)e->pInterface);
 
 1041    else if (strcmp(e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0)
 
 1043        gdi_video_data_init(pContext->gdi, (VideoClientContext*)e->pInterface);
 
 1045        qDebug(log) << 
"Unimplemented: channel" << e->name << 
"connected but we can’t use it";
 
 1049void CBackendFreeRDP::OnChannelDisconnectedEventHandler(
void *context,
 
 1050                                                        #
if FREERDP_VERSION_MAJOR >= 3
 
 1053                                                        ChannelDisconnectedEventArgs *e)
 
 1055    rdpContext* pContext = (rdpContext*)context;
 
 1058    if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) {
 
 1059        qDebug(log) << 
"channel" << e->name << 
"disconnected";
 
 1060        pThis->m_ClipBoard.UnInit((CliprdrClientContext*)e->pInterface,
 
 1061                                  pThis->m_pParameter->GetClipboard());
 
 1063#if FREERDP_VERSION_MAJOR >= 3 
 1065        freerdp_client_OnChannelDisconnectedEventHandler(pContext, e);
 
 1067    else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
 
 1069        if (freerdp_settings_get_bool(pContext->settings, FreeRDP_SoftwareGdi)) {
 
 1070            rdpGdi* gdi = pContext->gdi;
 
 1071            gdi_graphics_pipeline_uninit(gdi, (RdpgfxClientContext*) e->pInterface);
 
 1074            qDebug(log, 
"Unimplemented: channel %s connected but libfreerdp is in HardwareGdi mode\n", e->name);
 
 1077        qDebug(log) << 
"Unimplemented: channel" << e->name << 
"disconnected but we can’t use it";
 
 1082UINT32 CBackendFreeRDP::GetImageFormat(QImage::Format format)
 
 1085#if (QT_VERSION >= QT_VERSION_CHECK(5,2,0)) 
 1086    case QImage::Format_RGBA8888:
 
 1087        return PIXEL_FORMAT_RGBA32;
 
 1088    case QImage::Format_RGBX8888:
 
 1089        return PIXEL_FORMAT_RGBX32;
 
 1091    case QImage::Format_RGB16:
 
 1092        return PIXEL_FORMAT_RGB16;
 
 1093    case QImage::Format_ARGB32:
 
 1094        return PIXEL_FORMAT_BGRA32;
 
 1095    case QImage::Format_RGB32:
 
 1096        return PIXEL_FORMAT_BGRA32;
 
 1103UINT32 CBackendFreeRDP::GetImageFormat()
 
 1105    return GetImageFormat(m_Image.format());
 
 1108BOOL CBackendFreeRDP::CreateImage(rdpContext *context)
 
 1111    ClientContext* pContext = (ClientContext*)context;
 
 1113    rdpGdi* gdi = context->gdi;
 
 1114    Q_ASSERT(pThis && gdi);
 
 1115    pThis->m_Image = QImage(gdi->primary_buffer,
 
 1116                            static_cast<int>(gdi->width),
 
 1117                            static_cast<int>(gdi->height),
 
 1118                            QImage::Format_ARGB32);
 
 1122#if FREERDP_VERSION_MAJOR >= 3 
 1124static CREDUI_INFOW wfUiInfo = { 
sizeof(CREDUI_INFOW), NULL, L
"Enter your credentials",
 
 1125                                L
"Remote Desktop Security", NULL };
 
 1128BOOL CBackendFreeRDP::cb_authenticate_ex(freerdp* instance,
 
 1129                               char** username, 
char** password,
 
 1130                               char** domain, rdp_auth_reason reason)
 
 1132    qDebug(log) << Q_FUNC_INFO << 
"reason:" << reason;
 
 1136    if(!username || !password || !domain) 
return FALSE;
 
 1138    rdpContext* pContext = (rdpContext*)instance->context;
 
 1143    WCHAR UserNameW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
 
 1144    WCHAR UserW[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
 
 1145    WCHAR DomainW[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
 
 1146    WCHAR PasswordW[CREDUI_MAX_PASSWORD_LENGTH + 1] = { 0 };
 
 1148    WINPR_ASSERT(instance);
 
 1149    WINPR_ASSERT(instance->context);
 
 1150    WINPR_ASSERT(instance->context->settings);
 
 1152    WINPR_ASSERT(username);
 
 1153    WINPR_ASSERT(domain);
 
 1154    WINPR_ASSERT(password);
 
 1156    const WCHAR auth[] = L
"Target credentials requested";
 
 1157    const WCHAR authPin[] = L
"PIN requested";
 
 1158    const WCHAR gwAuth[] = L
"Gateway credentials requested";
 
 1159    const WCHAR* titleW = auth;
 
 1162    dwFlags = CREDUI_FLAGS_DO_NOT_PERSIST | CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
 
 1163              CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
 
 1170        if ((*username) && (*password))
 
 1173    case AUTH_SMARTCARD_PIN:
 
 1174        dwFlags &= ~CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS;
 
 1175        dwFlags |= CREDUI_FLAGS_PASSWORD_ONLY_OK | CREDUI_FLAGS_KEEP_USERNAME;
 
 1180            *username = _strdup(
"PIN");
 
 1193        ConvertUtf8ToWChar(*username, UserNameW, ARRAYSIZE(UserNameW));
 
 1194        ConvertUtf8ToWChar(*username, UserW, ARRAYSIZE(UserW));
 
 1198        ConvertUtf8ToWChar(*password, PasswordW, ARRAYSIZE(PasswordW));
 
 1201        ConvertUtf8ToWChar(*domain, DomainW, ARRAYSIZE(DomainW));
 
 1203    if (_wcsnlen(PasswordW, ARRAYSIZE(PasswordW)) == 0)
 
 1205        status = CredUIPromptForCredentialsW(&wfUiInfo, titleW, NULL, 0, UserNameW,
 
 1206                                             ARRAYSIZE(UserNameW), PasswordW,
 
 1207                                             ARRAYSIZE(PasswordW), &fSave, dwFlags);
 
 1208        if (status != NO_ERROR)
 
 1211                      "CredUIPromptForCredentials unexpected status: 0x%08lX",
 
 1216        if ((dwFlags & CREDUI_FLAGS_KEEP_USERNAME) == 0)
 
 1218            status = CredUIParseUserNameW(UserNameW, UserW, ARRAYSIZE(UserW), DomainW,
 
 1219                                          ARRAYSIZE(DomainW));
 
 1220            if (status != NO_ERROR)
 
 1222                CHAR User[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
 
 1223                CHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1] = { 0 };
 
 1224                CHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1] = { 0 };
 
 1226                ConvertWCharNToUtf8(UserNameW, ARRAYSIZE(UserNameW), UserName, ARRAYSIZE(UserName));
 
 1227                ConvertWCharNToUtf8(UserW, ARRAYSIZE(UserW), User, ARRAYSIZE(User));
 
 1228                ConvertWCharNToUtf8(DomainW, ARRAYSIZE(DomainW), Domain, ARRAYSIZE(Domain));
 
 1230                          "Failed to parse UserName: %s into User: %s Domain: %s",
 
 1231                          UserName, User, Domain);
 
 1237    *username = ConvertWCharNToUtf8Alloc(UserW, ARRAYSIZE(UserW), NULL);
 
 1240        qCritical(log) << 
"ConvertWCharNToUtf8Alloc failed" << status;
 
 1244    if (_wcsnlen(DomainW, ARRAYSIZE(DomainW)) > 0)
 
 1245        *domain = ConvertWCharNToUtf8Alloc(DomainW, ARRAYSIZE(DomainW), NULL);
 
 1247        *domain = _strdup(
"\0");
 
 1252        qCritical(log) << 
"strdup failed" << status;
 
 1256    *password = ConvertWCharNToUtf8Alloc(PasswordW, ARRAYSIZE(PasswordW), NULL);
 
 1265    return cb_authenticate(instance, username, password, domain);
 
 1270BOOL CBackendFreeRDP::cb_choose_smartcard(freerdp* instance,
 
 1271                         SmartcardCertInfo** cert_list,
 
 1273                         DWORD* choice, BOOL gateway)
 
 1275    rdpContext* pContext = (rdpContext*)instance->context;
 
 1277    QString msg(
"Multiple smartcards are available for use:\n");
 
 1278    for (DWORD i = 0; i < count; i++)
 
 1280        const SmartcardCertInfo* cert = cert_list[i];
 
 1281        char* reader = ConvertWCharToUtf8Alloc(cert->reader, NULL);
 
 1282        char* container_name = ConvertWCharToUtf8Alloc(cert->containerName, NULL);
 
 1284        msg += QString::number(i) + 
" ";
 
 1285        msg += QString(container_name) + 
"\n\t";
 
 1286        msg += 
"Reader: " + QString(reader) + 
"\n\t";
 
 1287        msg += 
"User: " + QString(cert->userHint) + + 
"@" + QString(cert->domainHint) + 
"\n\t";
 
 1288        msg += 
"Subject: " + QString(cert->subject) + 
"\n\t";
 
 1289        msg += 
"Issuer: " + QString(cert->issuer) + 
"\n\t";
 
 1290        msg += 
"UPN: " + QString(cert->upn) + 
"\n";
 
 1293        free(container_name);
 
 1296    msg += 
"\nChoose a smartcard to use for ";
 
 1298        msg += 
"gateway authentication";
 
 1302    msg += 
"(0 - " + QString::number(count - 1) + 
")";
 
 1310        int n = num.toInt(&ok);
 
 1320#ifdef WITH_WINDOWS_CERT_STORE 
 1328static void wf_report_error(
char* wszMessage, DWORD dwErrCode)
 
 1330    LPSTR pwszMsgBuf = NULL;
 
 1332    if (NULL != wszMessage && 0 != *wszMessage)
 
 1334        WLog_ERR(TAG, 
"%s", wszMessage);
 
 1337    FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
 
 1342                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
 
 1352    if (NULL != pwszMsgBuf)
 
 1354        WLog_ERR(TAG, 
"Error: 0x%08x (%d) %s", dwErrCode, dwErrCode, pwszMsgBuf);
 
 1355        LocalFree(pwszMsgBuf);
 
 1359        WLog_ERR(TAG, 
"Error: 0x%08x (%d)", dwErrCode, dwErrCode);
 
 1363static DWORD wf_is_x509_certificate_trusted(
const char* common_name, 
const char* subject,
 
 1364                                            const char* issuer, 
const char* fingerprint)
 
 1366    HRESULT hr = CRYPT_E_NOT_FOUND;
 
 1368    DWORD dwChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
 
 1369    PCCERT_CONTEXT pCert = NULL;
 
 1370    HCERTCHAINENGINE hChainEngine = NULL;
 
 1371    PCCERT_CHAIN_CONTEXT pChainContext = NULL;
 
 1373    CERT_ENHKEY_USAGE EnhkeyUsage = { 0 };
 
 1374    CERT_USAGE_MATCH CertUsage = { 0 };
 
 1375    CERT_CHAIN_PARA ChainPara = { 0 };
 
 1376    CERT_CHAIN_POLICY_PARA ChainPolicy = { 0 };
 
 1377    CERT_CHAIN_POLICY_STATUS PolicyStatus = { 0 };
 
 1378    CERT_CHAIN_ENGINE_CONFIG EngineConfig = { 0 };
 
 1380    DWORD derPubKeyLen = WINPR_ASSERTING_INT_CAST(uint32_t, strlen(fingerprint));
 
 1381    char* derPubKey = calloc(derPubKeyLen, 
sizeof(
char));
 
 1382    if (NULL == derPubKey)
 
 1384        WLog_ERR(TAG, 
"Could not allocate derPubKey");
 
 1391    if (!CryptStringToBinaryA(fingerprint, 0, CRYPT_STRING_BASE64HEADER, derPubKey, &derPubKeyLen,
 
 1394        WLog_ERR(TAG, 
"CryptStringToBinary failed. Err: %d", GetLastError());
 
 1401    EnhkeyUsage.cUsageIdentifier = 0;
 
 1402    EnhkeyUsage.rgpszUsageIdentifier = NULL;
 
 1404    CertUsage.dwType = USAGE_MATCH_TYPE_AND;
 
 1405    CertUsage.Usage = EnhkeyUsage;
 
 1407    ChainPara.cbSize = 
sizeof(ChainPara);
 
 1408    ChainPara.RequestedUsage = CertUsage;
 
 1410    ChainPolicy.cbSize = 
sizeof(ChainPolicy);
 
 1412    PolicyStatus.cbSize = 
sizeof(PolicyStatus);
 
 1414    EngineConfig.cbSize = 
sizeof(EngineConfig);
 
 1415    EngineConfig.dwUrlRetrievalTimeout = 0;
 
 1417    pCert = CertCreateCertificateContext(X509_ASN_ENCODING, derPubKey, derPubKeyLen);
 
 1420        WLog_ERR(TAG, 
"FAILED: Certificate could not be parsed.");
 
 1424    dwChainFlags |= CERT_CHAIN_ENABLE_PEER_TRUST;
 
 1433    if (!CertCreateCertificateChainEngine(&EngineConfig, &hChainEngine))
 
 1435        hr = HRESULT_FROM_WIN32(GetLastError());
 
 1442    if (!CertGetCertificateChain(hChainEngine, 
 
 1453        hr = HRESULT_FROM_WIN32(GetLastError());
 
 1460    if (!CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE, 
 
 1465        hr = HRESULT_FROM_WIN32(GetLastError());
 
 1469    if (PolicyStatus.dwError != S_OK)
 
 1471        wf_report_error(
"CertVerifyCertificateChainPolicy: Chain Status", PolicyStatus.dwError);
 
 1472        hr = PolicyStatus.dwError;
 
 1478        if (PolicyStatus.dwError == CRYPT_E_NO_REVOCATION_CHECK ||
 
 1479            PolicyStatus.dwError == CRYPT_E_REVOCATION_OFFLINE)
 
 1487    WLog_INFO(TAG, 
"CertVerifyCertificateChainPolicy succeeded for %s (%s) issued by %s",
 
 1488              common_name, subject, issuer);
 
 1495        WLog_INFO(TAG, 
"CertVerifyCertificateChainPolicy failed for %s (%s) issued by %s",
 
 1496                  common_name, subject, issuer);
 
 1497        wf_report_error(NULL, hr);
 
 1502    if (NULL != pChainContext)
 
 1504        CertFreeCertificateChain(pChainContext);
 
 1507    if (NULL != hChainEngine)
 
 1509        CertFreeCertificateChainEngine(hChainEngine);
 
 1514        CertFreeCertificateContext(pCert);
 
 1523BOOL CBackendFreeRDP::cb_authenticate(freerdp* instance, 
char** username,
 
 1524                                      char** password, 
char** domain)
 
 1526    qDebug(log) << Q_FUNC_INFO;
 
 1529    rdpContext* pContext = (rdpContext*)instance->context;
 
 1531    if(!username || !password || !domain) 
return FALSE;
 
 1532    if(*username && *password ) 
return TRUE;
 
 1534    int nRet = QDialog::Rejected;
 
 1536                                   nRet, pThis->m_pParameter);
 
 1537    if(QDialog::Accepted == nRet)
 
 1539        QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
 
 1540        QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
 
 1541        QString szDomain = pThis->m_pParameter->GetDomain();
 
 1542        if(!szDomain.isEmpty() && domain)
 
 1543            *domain = _strdup(szDomain.toStdString().c_str());
 
 1544        if(!szName.isEmpty() && username)
 
 1545            *username = _strdup(szName.toStdString().c_str());
 
 1547            *password = _strdup(szPassword.toStdString().c_str());
 
 1554BOOL CBackendFreeRDP::cb_GatewayAuthenticate(freerdp *instance,
 
 1555                                char **username, 
char **password, 
char **domain)
 
 1557    qDebug(log) << Q_FUNC_INFO;
 
 1561    rdpContext* pContext = (rdpContext*)instance->context;
 
 1563    if(!username || !password || !domain) 
return FALSE;
 
 1564    if(*username && *password ) 
return TRUE;
 
 1566    int nRet = QDialog::Rejected;
 
 1567    emit pThis->
sigBlockShowWidget(
"CDlgGetUserPasswordFreeRDP", nRet, pThis->m_pParameter);
 
 1568    if(QDialog::Accepted == nRet)
 
 1570        QString szPassword = pThis->m_pParameter->m_Net.
m_User.GetPassword();
 
 1571        QString szName = pThis->m_pParameter->m_Net.
m_User.GetUser();
 
 1572        QString szDomain = pThis->m_pParameter->GetDomain();
 
 1573        if(!szDomain.isEmpty() && domain)
 
 1574            *domain = _strdup(szDomain.toStdString().c_str());
 
 1575        if(!szName.isEmpty() && username)
 
 1576            *username = _strdup(szName.toStdString().c_str());
 
 1578            *password = _strdup(szPassword.toStdString().c_str());
 
 1586                                               const BYTE* data, 
size_t length,
 
 1587                                 const char* hostname, UINT16 port, DWORD flags)
 
 1589    qDebug(log) << Q_FUNC_INFO;
 
 1590    rdpContext* pContext = (rdpContext*)instance->context;
 
 1591    QSslCertificate cert(QByteArray((
const char*)data, length));
 
 1592#if FREERDP_VERSION_MAJOR >= 3 
 1596    if (flags & VERIFY_CERT_FLAG_FP_IS_PEM) {
 
 1598            instance, hostname, port,
 
 1599            cert.issuerDisplayName().toStdString().c_str(),
 
 1600            cert.subjectDisplayName().toStdString().c_str(),
 
 1601            cert.issuerDisplayName().toStdString().c_str(),
 
 1607        instance, hostname, port,
 
 1608        cert.issuerDisplayName().toStdString().c_str(),
 
 1609        cert.subjectDisplayName().toStdString().c_str(),
 
 1610        cert.issuerDisplayName().toStdString().c_str(),
 
 1611        cert.serialNumber().toStdString().c_str(),
 
 
 1615static QString pem_cert_fingerprint(
const char* pem, DWORD flags)
 
 1617    QString szFingerPrint;
 
 1618#if FREERDP_VERSION_MAJOR >= 3 
 1622    if (flags & VERIFY_CERT_FLAG_FP_IS_PEM)
 
 1624        rdpCertificate* cert = freerdp_certificate_new_from_pem(pem);
 
 1628        char* fp = freerdp_certificate_get_fingerprint(cert);
 
 1629        char* start = freerdp_certificate_get_validity(cert, TRUE);
 
 1630        char* end = freerdp_certificate_get_validity(cert, FALSE);
 
 1631        freerdp_certificate_free(cert);
 
 1633        szFingerPrint = QObject::tr(
"Valid from: ") + QString(start) + 
"\n";
 
 1634        szFingerPrint += QObject::tr(
"Valid to: ") + QString(end) + 
"\n";
 
 1635        szFingerPrint += QObject::tr(
"Fingerprint: ") + QString(fp) + 
"\n";
 
 1642        szFingerPrint = QObject::tr(
"Fingerprint: ") + QString(pem) + 
"\n";
 
 1643    return szFingerPrint;
 
 1662                       const char *host, UINT16 port,
 
 1663                       const char *common_name, 
const char *subject,
 
 1664                       const char *issuer, 
const char *fingerprint, DWORD flags)
 
 1666    qDebug(log) << Q_FUNC_INFO;
 
 1668    rdpContext* pContext = (rdpContext*)instance->context;
 
 1675        emit pThis->sigServerName(common_name);
 
 1678    if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
 
 1684#if FREERDP_VERSION_MAJOR >= 3 
 1685#if defined(Q_OS_WIN) && defined(WITH_WINDOWS_CERT_STORE) 
 1686    if (flags & VERIFY_CERT_FLAG_FP_IS_PEM && !(flags & VERIFY_CERT_FLAG_MISMATCH))
 
 1688        if (wf_is_x509_certificate_trusted(common_name, subject, issuer, fingerprint) == S_OK)
 
 1696    QString szType = tr(
"RDP-Server");
 
 1697    if (flags & VERIFY_CERT_FLAG_GATEWAY)
 
 1698        szType = tr(
"RDP-Gateway");
 
 1699    if (flags & VERIFY_CERT_FLAG_REDIRECT)
 
 1700        szType = tr(
"RDP-Redirect");
 
 1702    QString title(tr(
"Verify certificate"));
 
 1705    message += szType + tr(
": %1:%2").arg(host, QString::number(port)) + 
"\n";
 
 1706    message += tr(
"Common name: ") + common_name + 
"\n";
 
 1707    message += tr(
"Subject: ") + subject + 
"\n";
 
 1708    message += tr(
"Issuer: ") + issuer + 
"\n";
 
 1709    message += pem_cert_fingerprint(fingerprint, flags);
 
 1711    if(VERIFY_CERT_FLAG_CHANGED & flags) {
 
 1712        message += tr(
"The above X.509 certificate is changed.\n" 
 1713                  "It is possible that the server has changed its certificate, " 
 1714                  "or Maybe it was attacked." 
 1715                  "Please look at the OpenSSL documentation on " 
 1716                  "how to add a private CA to the store.");
 
 1718        message += tr(
"The above X.509 certificate could not be verified.\n" 
 1719                  "Possibly because you do not have the CA certificate " 
 1720                  "in your certificate store, or the certificate has expired.\n" 
 1721                  "Please look at the OpenSSL documentation on " 
 1722                  "how to add a private CA to the store.");
 
 1726    message += tr(
"Yes - trusted") + 
"\n";
 
 1727    message += tr(
"Ignore - temporary trusted") + 
"\n";
 
 1728    message += tr(
"No - no trusted") + 
"\n";
 
 1730    QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
 
 1731    QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
 
 1732    bool bCheckBox = 
false;
 
 1734                                    tr(
"Don't show again"));
 
 1735    pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
 
 1741    case QMessageBox::StandardButton::Yes:
 
 1743    case QMessageBox::StandardButton::Ignore:
 
 
 1771                      const char *host, UINT16 port,
 
 1772                      const char *common_name, 
const char *subject,
 
 1773                      const char *issuer, 
const char *fingerprint,
 
 1774                      const char *old_subject, 
const char *old_issuer,
 
 1775                      const char *old_fingerprint, DWORD flags)
 
 1777    qDebug(log) << Q_FUNC_INFO;
 
 1778    rdpContext* pContext = (rdpContext*)instance->context;
 
 1781        emit pThis->sigServerName(common_name);
 
 1783    if(!pThis->m_pParameter->GetShowVerifyDiaglog()) {
 
 1789    QString szType = tr(
"RDP-Server");
 
 1790    if (flags & VERIFY_CERT_FLAG_GATEWAY)
 
 1791        szType = tr(
"RDP-Gateway");
 
 1792    if (flags & VERIFY_CERT_FLAG_REDIRECT)
 
 1793        szType = tr(
"RDP-Redirect");
 
 1795    QString title(tr(
"Verify changed certificate"));
 
 1797    message += szType + tr(
": %1:%2").arg(host, QString::number(port)) + 
"\n";
 
 1798    message += tr(
"New Certificate details:") + 
"\n";
 
 1799    message += 
"  " + tr(
"name: ") + common_name + 
"\n";
 
 1800    message += 
"  " + tr(
"subject: ") + subject + 
"\n";
 
 1801    message += 
"  " + tr(
"issuer: ") + issuer + 
"\n";
 
 1802    message += 
"  " + pem_cert_fingerprint(fingerprint, flags) + 
"\n";
 
 1803    message += tr(
"Old Certificate details:") + 
"\n";
 
 1804    message += 
"  " + tr(
"subject: ") + old_subject + 
"\n";
 
 1805    message += 
"  " + tr(
"issuer: ") + old_issuer + 
"\n";
 
 1806    message += 
"  " + pem_cert_fingerprint(old_fingerprint, flags) + 
"\n";
 
 1808    message += tr(
"The above X.509 certificate could not be verified, " 
 1809                  "possibly because you do not have the CA certificate " 
 1810                  "in your certificate store, or the certificate has expired. " 
 1811                  "Please look at the OpenSSL documentation on " 
 1812                  "how to add a private CA to the store.");
 
 1815    message += tr(
"Yes - trusted") + 
"\n";
 
 1816    message += tr(
"Ignore - temporary trusted") + 
"\n";
 
 1817    message += tr(
"No - no trusted") + 
"\n";
 
 1819    bool bCheckBox = 
false;
 
 1820    QMessageBox::StandardButton nRet = QMessageBox::StandardButton::No;
 
 1821    QMessageBox::StandardButtons buttons = QMessageBox::Yes | QMessageBox::Ignore | QMessageBox::No;
 
 1823                                    tr(
"Don't show again"));
 
 1824    pThis->m_pParameter->SetShowVerifyDiaglog(!bCheckBox);
 
 1831    case QMessageBox::StandardButton::Yes:
 
 1833    case QMessageBox::StandardButton::Ignore:
 
 
 1844BOOL CBackendFreeRDP::cb_present_gateway_message(
 
 1845        freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
 
 1846        BOOL isConsentMandatory, 
size_t length, 
const WCHAR* message)
 
 1848    qDebug(log) << Q_FUNC_INFO;
 
 1850    if (!isDisplayMandatory && !isConsentMandatory)
 
 1854    if (type == GATEWAY_MESSAGE_CONSENT && isConsentMandatory)
 
 1856        QString msgType = (type == GATEWAY_MESSAGE_CONSENT)
 
 1857                              ? tr(
"Consent message") : tr(
"Service message");
 
 1859#if FREERDP_VERSION_MAJOR >= 3 
 1860        char* pMsg = ConvertWCharToUtf8Alloc(message, NULL);
 
 1866        msgType += QString::fromStdWString((
wchar_t*)message);
 
 1869        msgType += tr(
"I understand and agree to the terms of this policy (Y/N)");
 
 1871        rdpContext* pContext = (rdpContext*)instance->context;
 
 1873        QMessageBox::StandardButton nRet = QMessageBox::No;
 
 1874        bool bCheckBox = 
false;
 
 1876                                        QMessageBox::Yes|QMessageBox::No,
 
 1879        case QMessageBox::Yes:
 
 1887        return client_cli_present_gateway_message(
 
 1888            instance, type, isDisplayMandatory,
 
 1889            isConsentMandatory, length, message);
 
 1894BOOL CBackendFreeRDP::cb_begin_paint(rdpContext *context)
 
 1898    if (!context || !context->gdi || !context->gdi->primary
 
 1899            || !context->gdi->primary->hdc)
 
 1902    hdc = context->gdi->primary->hdc;
 
 1904    if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
 
 1907    hdc->hwnd->invalid->null = TRUE;
 
 1908    hdc->hwnd->ninvalid = 0;
 
 1912BOOL CBackendFreeRDP::UpdateBuffer(INT32 x, INT32 y, INT32 w, INT32 h)
 
 1914    if(x > m_Image.width() || y > m_Image.height()) {
 
 1915        qCritical(log) << 
"The width and height out of range." 
 1916                       << 
"Image width:" << m_Image.width()
 
 1917                       << 
"Image height:" << m_Image.height()
 
 1918                       << 
"w:" << w << 
"h:" << h;
 
 1922    QRect rect(x, y, w, h);
 
 1923    QImage img = m_Image.copy(rect);
 
 1929BOOL CBackendFreeRDP::cb_end_paint(rdpContext *context)
 
 1932    ClientContext* pContext = (ClientContext*)context;
 
 1936    REGION16 invalidRegion;
 
 1937    RECTANGLE_16 invalidRect;
 
 1938    const RECTANGLE_16* extents;
 
 1942    if (!context || !context->gdi || !context->gdi->primary
 
 1943            || !context->gdi->primary->hdc)
 
 1946    hdc = context->gdi->primary->hdc;
 
 1948    if (!hdc || !hdc->hwnd || !hdc->hwnd->invalid)
 
 1951    rdpGdi* gdi = context->gdi;
 
 1952    if (gdi->suppressOutput)
 
 1955    HGDI_WND hwnd = context->gdi->primary->hdc->hwnd;
 
 1956    ninvalid = hwnd->ninvalid; 
 
 1957    cinvalid = hwnd->cinvalid; 
 
 1961    region16_init(&invalidRegion);
 
 1963    for (i = 0; i < ninvalid; i++)
 
 1965        if(cinvalid[i].null)
 
 1967            qWarning(log) << 
"is null region" << cinvalid[i].x << cinvalid[i].y
 
 1968                          << cinvalid[i].w << cinvalid[i].h;
 
 1971        invalidRect.left = cinvalid[i].x;
 
 1972        invalidRect.top = cinvalid[i].y;
 
 1973        invalidRect.right = cinvalid[i].x + cinvalid[i].w;
 
 1974        invalidRect.bottom = cinvalid[i].y + cinvalid[i].h;
 
 1975        region16_union_rect(&invalidRegion, &invalidRegion, &invalidRect);
 
 1978    if (!region16_is_empty(&invalidRegion))
 
 1980        extents = region16_extents(&invalidRegion);
 
 1982        pThis->UpdateBuffer(extents->left,
 
 1984                            extents->right - extents->left,
 
 1985                            extents->bottom - extents->top);
 
 1988    region16_uninit(&invalidRegion);
 
 1993BOOL CBackendFreeRDP::cb_desktop_resize(rdpContext* context)
 
 1995    qDebug(log) << Q_FUNC_INFO;
 
 1996    ClientContext* pContext = (ClientContext*)context;
 
 1998    rdpSettings* settings;
 
 1999    if (!context || !context->settings)
 
 2001    settings = context->settings;
 
 2002    int desktopWidth = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth);
 
 2003    int desktopHeight = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight);
 
 2005    if(!gdi_resize(context->gdi, desktopWidth, desktopHeight))
 
 2007    if(!pThis->CreateImage(context))
 
 2010    emit pThis->sigSetDesktopSize(desktopWidth, desktopHeight);
 
 2011    pThis->UpdateBuffer(0, 0, desktopWidth, desktopHeight);
 
 2015BOOL CBackendFreeRDP::cb_play_bell_sound(rdpContext *context, 
const PLAY_SOUND_UPDATE *play_sound)
 
 2017    qDebug(log) << Q_FUNC_INFO;
 
 2018    ClientContext* pContext = (ClientContext*)context;
 
 2020    WINPR_UNUSED(play_sound);
 
 2021    QApplication::beep();
 
 2025#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 
 2026    QSoundEffect effect;
 
 2027    effect.setSource(QUrl::fromLocalFile(szFile));
 
 2032    QSound::play(szFile);
 
 2038BOOL CBackendFreeRDP::cb_keyboard_set_indicators(rdpContext *context, UINT16 led_flags)
 
 2040    qDebug(log) << Q_FUNC_INFO;
 
 2041    ClientContext* pContext = (ClientContext*)context;
 
 2044    int state = CFrmViewer::LED_STATE::Unknown;
 
 2046    if (led_flags & KBD_SYNC_NUM_LOCK)
 
 2047        state |= CFrmViewer::LED_STATE::NumLock;
 
 2048    if (led_flags & KBD_SYNC_CAPS_LOCK)
 
 2049        state |= CFrmViewer::LED_STATE::CapsLock;
 
 2050    if (led_flags & KBD_SYNC_SCROLL_LOCK)
 
 2051        state |= CFrmViewer::LED_STATE::ScrollLock;
 
 2053    emit pThis->sigUpdateLedState(state);
 
 2059BOOL CBackendFreeRDP::cb_keyboard_set_ime_status(
 
 2060    rdpContext* context, UINT16 imeId, UINT32 imeState, UINT32 imeConvMode)
 
 2066              "KeyboardSetImeStatus(unitId=%04" PRIx16 
", imeState=%08" PRIx32
 
 2067              ", imeConvMode=%08" PRIx32 
") ignored",
 
 2068              imeId, imeState, imeConvMode);
 
 2076        SetEvent(m_writeEvent);
 
 
 2081bool CBackendFreeRDP::SendMouseEvent(UINT16 flags, QPoint pos, 
bool isExtended)
 
 2083    if(m_pParameter && m_pParameter->GetOnlyView()) 
return true;
 
 2084    if(!m_pContext) 
return false;
 
 2086#if FREERDP_VERSION_MAJOR >= 3 
 2088        freerdp_client_send_extended_button_event(
 
 2089            &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
 
 2091        freerdp_client_send_button_event(
 
 2092            &m_pContext->Context, FALSE, flags, pos.x(), pos.y());
 
 2094    if(!m_pContext->Context.input) 
return false;
 
 2095    return freerdp_input_send_mouse_event(
 
 2096        m_pContext->Context.input, flags, pos.x(), pos.y());
 
 2101void CBackendFreeRDP::wheelEvent(QWheelEvent *event)
 
 2103    qDebug(logMouse) << Q_FUNC_INFO << event;
 
 2104    if(!m_pContext) 
return;
 
 2105    if(m_pParameter && m_pParameter->GetOnlyView()) 
return;
 
 2109#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 
 2110    pos = 
event->position();
 
 2114    QPoint p = 
event->angleDelta();
 
 2117        flags |= PTR_FLAGS_WHEEL | p.y();
 
 2121        flags |= PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.y();
 
 2126        flags |= PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | -p.x();  
 
 2130        flags |= PTR_FLAGS_HWHEEL | p.x();
 
 2132#if FREERDP_VERSION_MAJOR >= 3 
 2133    freerdp_client_send_wheel_event(&m_pContext->Context, flags);
 
 2138    freerdp_input_send_mouse_event(
 
 2139        m_pContext->Context.input, flags, pos.x(), pos.y());
 
 2144void CBackendFreeRDP::mouseMoveEvent(QMouseEvent *event)
 
 2146    qDebug(logMouse) << Q_FUNC_INFO << 
event << 
event->buttons() << 
event->button();
 
 2147    if(!m_pContext) 
return;
 
 2148    if(m_pParameter && m_pParameter->GetOnlyView()) 
return;
 
 2149    UINT16 flags = PTR_FLAGS_MOVE;
 
 2150    SendMouseEvent(flags, event->pos(), 
false);
 
 2153void CBackendFreeRDP::mousePressEvent(QMouseEvent *event)
 
 2155    qDebug(logMouse) << Q_FUNC_INFO << 
event << 
event->buttons() << 
event->button();
 
 2156    if(!m_pContext) 
return;
 
 2157    if(m_pParameter && m_pParameter->GetOnlyView()) 
return;
 
 2160    bool isExtended = 
false;
 
 2161    Qt::MouseButton button = 
event->button();
 
 2162    if (button & Qt::MouseButton::LeftButton)
 
 2164        flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1;
 
 2166    else if (button & Qt::MouseButton::RightButton)
 
 2168        flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2;
 
 2170    else if (button & Qt::MouseButton::MiddleButton)
 
 2172        flags = PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON3;
 
 2174    else if (button & Qt::MouseButton::ForwardButton)
 
 2176        flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
 
 2179    else if (button & Qt::MouseButton::BackButton)
 
 2181        flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
 
 2186        SendMouseEvent(flags, event->pos(), isExtended);
 
 2190void CBackendFreeRDP::mouseReleaseEvent(QMouseEvent *event)
 
 2192    qDebug(logMouse) << Q_FUNC_INFO << 
event << 
event->buttons() << 
event->button();
 
 2193    if(!m_pContext) 
return;
 
 2194    if(m_pParameter && m_pParameter->GetOnlyView()) 
return;
 
 2197    bool isExtended = 
false;
 
 2198    Qt::MouseButton button = 
event->button();
 
 2199    if (button & Qt::MouseButton::LeftButton)
 
 2201        flags = PTR_FLAGS_BUTTON1;
 
 2203    else if (button & Qt::MouseButton::MiddleButton)
 
 2205        flags = PTR_FLAGS_BUTTON3;
 
 2207    else if (button & Qt::MouseButton::RightButton)
 
 2209        flags = PTR_FLAGS_BUTTON2;
 
 2211    else if (button & Qt::MouseButton::ForwardButton)
 
 2213        flags = PTR_XFLAGS_BUTTON2;
 
 2216    else if (button & Qt::MouseButton::BackButton)
 
 2218        flags = PTR_XFLAGS_BUTTON1;
 
 2223        SendMouseEvent(flags, event->pos(), isExtended);
 
 2227void CBackendFreeRDP::keyPressEvent(QKeyEvent *event)
 
 2229    qDebug(logKey) << Q_FUNC_INFO << event;
 
 2230    if(!m_pContext) 
return;
 
 2231    if(m_pParameter && m_pParameter->GetOnlyView()) 
return;
 
 2234    if(RDP_SCANCODE_UNKNOWN != k)
 
 2235#if FREERDP_VERSION_MAJOR >= 3 
 2236        freerdp_input_send_keyboard_event_ex(
 
 2237            m_pContext->Context.context.input, 
true, 
true, k);
 
 2239        freerdp_input_send_keyboard_event_ex(
 
 2240            m_pContext->Context.input, 
true, k);
 
 2244void CBackendFreeRDP::keyReleaseEvent(QKeyEvent *event)
 
 2246    qDebug(logKey) << Q_FUNC_INFO << event;
 
 2247    if(!m_pContext) 
return;
 
 2248    if(m_pParameter && m_pParameter->GetOnlyView()) 
return;
 
 2250    if(RDP_SCANCODE_UNKNOWN != k)
 
 2251#if FREERDP_VERSION_MAJOR >= 3 
 2252        freerdp_input_send_keyboard_event_ex(
 
 2253            m_pContext->Context.context.input, 
false, 
false, k);
 
 2255        freerdp_input_send_keyboard_event_ex(
 
 2256            m_pContext->Context.input, 
false, k);
 
 2260void CBackendFreeRDP::InputMethodEvent(QInputMethodEvent *event)
 
 2262    qDebug(logKey) << Q_FUNC_INFO << event;
 
 2263    if(!m_pContext) 
return;
 
 2264    if(m_pParameter && m_pParameter->GetOnlyView()) 
return;
 
 2265    QString szText = 
event->commitString();
 
 2266    if(szText.isEmpty())
 
 2268    for(
int i = 0; i < szText.length(); i++) {
 
 2269        QChar c = szText.at(i);
 
 2270#if FREERDP_VERSION_MAJOR >= 3 
 2271        freerdp_input_send_unicode_keyboard_event(m_pContext->Context.context.input, 0, (UINT16)c.unicode());
 
 2273        freerdp_input_send_unicode_keyboard_event(m_pContext->Context.input, 0, (UINT16)c.unicode());
 
 2278int CBackendFreeRDP::RedirectionSound()
 
 2280    rdpContext* pRdpContext = (rdpContext*)m_pContext;
 
 2281    freerdp* instance = freerdp_client_get_instance(pRdpContext);
 
 2282    rdpSettings* settings = instance->context->settings;
 
 2285    if(m_pParameter->GetRedirectionSound()
 
 2286        == CParameterFreeRDP::RedirecionSoundType::Disable)
 
 2289        freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, FALSE);
 
 2290        freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, FALSE);
 
 2292    } 
else if(m_pParameter->GetRedirectionSound()
 
 2293               == CParameterFreeRDP::RedirecionSoundType::Local)
 
 2295        freerdp_settings_set_bool(settings, FreeRDP_AudioPlayback, TRUE);
 
 2296        freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
 
 2297    } 
else if(m_pParameter->GetRedirectionSound()
 
 2298               == CParameterFreeRDP::RedirecionSoundType::Remote)
 
 2300        freerdp_settings_set_bool(settings, FreeRDP_RemoteConsoleAudio, TRUE);
 
 2315    ptr.p = CommandLineParseCommaSeparatedValuesEx(
"rdpsnd",
 
 2316              m_pParameter->GetRedirectionSoundParameters().toStdString().c_str(),
 
 2318    BOOL status = freerdp_client_add_static_channel(settings, count,
 
 2319                                                #
if FREERDP_VERSION_MAJOR < 3
 
 2327        status = freerdp_client_add_dynamic_channel(settings, count,
 
 2328                                            #
if FREERDP_VERSION_MAJOR < 3
 
 2338        qCritical(log) << 
"Load rdpsnd fail";
 
 2345int CBackendFreeRDP::RedirectionMicrophone()
 
 2347    if(m_pParameter->GetRedirectionSound()
 
 2348        == CParameterFreeRDP::RedirecionSoundType::Remote)
 
 2350    if(!m_pParameter->GetRedirectionMicrophone())
 
 2353    rdpContext* pRdpContext = (rdpContext*)m_pContext;
 
 2354    freerdp* instance = freerdp_client_get_instance(pRdpContext);
 
 2356    rdpSettings* settings = instance->context->settings;
 
 2359    freerdp_settings_set_bool(settings, FreeRDP_AudioCapture, TRUE);
 
 2370    ptr.p = CommandLineParseCommaSeparatedValuesEx(
"audin",
 
 2371         m_pParameter->GetRedirectionMicrophoneParameters().toStdString().c_str(),
 
 2373    BOOL status = freerdp_client_add_dynamic_channel(settings, count,
 
 2374                                                 #
if FREERDP_VERSION_MAJOR < 3
 
 2383        qCritical(log) << 
"Load audin fail";
 
 2390int CBackendFreeRDP::RedirectionDriver()
 
 2392    QStringList lstDrives = m_pParameter->GetRedirectionDrives();
 
 2393    if(lstDrives.isEmpty())
 
 2396    rdpContext* pRdpContext = (rdpContext*)m_pContext;
 
 2397    freerdp* instance = freerdp_client_get_instance(pRdpContext);
 
 2398    rdpSettings* settings = instance->context->settings;
 
 2401    foreach (
auto drive, lstDrives) {
 
 2403        char* pDrive = _strdup(drive.toStdString().c_str());
 
 2404        const char* argvDrive[] = {
"drive", pDrive};
 
 2405        int count = 
sizeof(argvDrive) / 
sizeof(
const char*);
 
 2406        BOOL status = freerdp_client_add_device_channel(settings, count,
 
 2407                                                #
if FREERDP_VERSION_MAJOR < 3
 
 2411        if(pDrive) free(pDrive);
 
 2414            qCritical(log) << 
"Load drive fail";
 
 2422int CBackendFreeRDP::RedirectionPrinter()
 
 2424    if(!m_pParameter->GetRedirectionPrinter())
 
 2427    rdpContext* pRdpContext = (rdpContext*)m_pContext;
 
 2428    freerdp* instance = freerdp_client_get_instance(pRdpContext);
 
 2429    rdpSettings* settings = instance->context->settings;
 
 2432    QStringList printerList = QPrinterInfo::availablePrinterNames();
 
 2433    if(printerList.isEmpty())
 
 2435        qCritical(log) << 
"The printer is empty";
 
 2438    qDebug(log) << printerList;
 
 2441    const char* argvPrinter[] = {
"printer",  
nullptr, 
nullptr};
 
 2442    int count = 
sizeof(argvPrinter) / 
sizeof(
const char*);
 
 2443    BOOL status = freerdp_client_add_device_channel(settings, count,
 
 2444                                                #
if FREERDP_VERSION_MAJOR < 3
 
 2449        qCritical(log) << 
"Load printer fail";
 
 2456int CBackendFreeRDP::RedirectionSerial()
 
 2460    rdpContext* pRdpContext = (rdpContext*)m_pContext;
 
 2461    freerdp* instance = freerdp_client_get_instance(pRdpContext);
 
 2462    rdpSettings* settings = instance->context->settings;
 
 2465    QList<QSerialPortInfo> lstSerial = QSerialPortInfo::availablePorts();
 
 2468    foreach (
auto serial, lstSerial) {
 
 2471        qDebug(log) << 
"systemLocation:" << serial.systemLocation()
 
 2472                        << 
"portName:" << serial.portName()
 
 2473                        << 
"serialNumber:" << serial.serialNumber();
 
 2474        char* pSerial = _strdup(serial.systemLocation().toStdString().c_str());
 
 2475        char* pName = _strdup(serial.portName().toStdString().c_str());
 
 2476        const char* argvSerial[] = {
"serial", pName, pSerial};
 
 2477        int count = 
sizeof(argvSerial) / 
sizeof(
const char*);
 
 2478        BOOL status = freerdp_client_add_device_channel(settings, count,
 
 2479                                                    #
if FREERDP_VERSION_MAJOR < 3
 
 2483        if(pSerial) free(pSerial);
 
 2484        if(pName) free(pName);
 
 2488            qCritical(log) << 
"Load drive fail";
 
 2496void CBackendFreeRDP::slotConnectProxyServer(QString szHost, quint16 nPort)
 
 2498    qDebug(log) << 
"Connect proxy server:" << szHost + 
":" + QString::number(nPort);
 
 2499    rdpContext* pContext = (rdpContext*)m_pContext;
 
 2500    rdpSettings* settings = pContext->settings;
 
 2502        qCritical(log) << 
"settings is null";
 
 2505    freerdp_settings_set_string(
 
 2506        settings, FreeRDP_ServerHostname,
 
 2507        szHost.toStdString().c_str());
 
 2508    freerdp_settings_set_uint32(
 
 2509        settings, FreeRDP_ServerPort,
 
 2512    int nRet = freerdp_client_start(pContext);
 
 2515        qCritical(log) << 
"freerdp_client_start fail";
 
 2517    qDebug(log) << 
"Connect proxy server:" << szHost + 
":" + QString::number(nPort) << 
"end";
 
 2521CBackendFreeRDP::OnInitReturnValue CBackendFreeRDP::InitSSHTunnelPipe()
 
 2526            &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net, 
this);
 
 2528        return OnInitReturnValue::Fail;
 
 2529    bool check = connect(m_pThreadSSH, SIGNAL(sigServer(QString, quint16)),
 
 2530                         this, SLOT(slotConnectProxyServer(QString, quint16)));
 
 2532    check = connect(m_pThreadSSH, SIGNAL(
sigError(
int,QString)),
 
 2533                    this, SIGNAL(
sigError(
int,QString)));
 
 2535    check = connect(m_pThreadSSH, SIGNAL(
sigStop()),
 
 2538    m_pThreadSSH->start();
 
 2539    return OnInitReturnValue::UseOnProcess;
 
 2542int CBackendFreeRDP::CleanSSHTunnelPipe()
 
 2546        m_pThreadSSH->Exit();
 
 2547        m_pThreadSSH = 
nullptr;
 
Remote desktop interface.
 
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
 
static DWORD cb_verify_certificate_ex(freerdp *instance, const char *host, UINT16 port, const char *common_name, const char *subject, const char *issuer, const char *fingerprint, DWORD flags)
Callback set in the rdp_freerdp structure, and used to make a certificate validation when the connect...
 
static BOOL cb_pre_connect(freerdp *instance)
Callback given to freerdp_connect() to process the pre-connect operations.
 
static int cb_verify_x509_certificate(freerdp *instance, const BYTE *data, size_t length, const char *hostname, UINT16 port, DWORD flags)
Callback used if user interaction is required to accept a certificate.
 
virtual OnInitReturnValue OnInit() override
Initialization.
 
static BOOL cb_post_connect(freerdp *instance)
Callback given to freerdp_connect() to perform post-connection operations.
 
virtual int OnClean() override
Clean.
 
virtual int OnProcess() override
Specific operation processing of plug-in connection.
 
static DWORD cb_verify_changed_certificate_ex(freerdp *instance, const char *host, UINT16 port, const char *common_name, const char *subject, const char *issuer, const char *fingerprint, const char *old_subject, const char *old_issuer, const char *old_fingerprint, DWORD flags)
Callback set in the rdp_freerdp structure, and used to make a certificate validation when a stored ce...
 
virtual int WakeUp() override
Wake up Backend thread(background thread)
 
void sigInformation(const QString &szInfo)
Triggering from a background thread displays information in the main thread without blocking the back...
 
void sigStop()
Notify the user to stop.
 
void sigShowMessageBox(const QString &szTitle, const QString &szMessage, const QMessageBox::Icon &icon=QMessageBox::Information)
Trigger the display of a message dialog (QMessageBox) in the main thread from a background thread wit...
 
void sigError(const int nError, const QString &szError=QString())
Triggered when an error is generated.
 
void sigBlockShowMessageBox(const QString &szTitle, const QString &szMessage, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton &nRet, bool &checkBox, QString checkBoxContext=QString())
Block background threads and display message dialogs in foreground threads (QMessageBox)
 
void sigRunning()
Emitted when the plugin is successfully started.
 
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
Blocks the background thread and displays the window in the foreground thread.
 
void sigBlockInputDialog(const QString &szTitle, const QString &szLable, const QString &szMessage, QString &szText)
Block background threads and display input dialogs in foreground threads (QInputDialog)
 
static UINT32 QtToScanCode(int key, Qt::KeyboardModifiers modifiers)
CConvertKeyCode::QtToScanCode.
 
[Declare CParameterFreeRDP]
 
Basic network parameters.
 
CParameterUser m_User
[Instance user]
 
void sigChanged()
emit when the parameter changes Usually if required, the corresponding parameter corresponds to a cha...
 
Data is forwarded over a local socket and SSH tunnel.