MSTSCLib :: MsRdpClient некорректное поведение - PullRequest
0 голосов
/ 05 декабря 2018

Я пытаюсь использовать MsRdpClient для подключения к серверу rdp и получения некоторых основных уведомлений.Теперь у меня та же проблема, что и у людей около 8 лет, я не нашел ответа, поэтому я снова поднимаю эту тему.У меня есть такой код, собранный из различных примеров того, как использовать rdp с winapi:

#include <Windows.h>
#include <CommCtrl.h>
#include <tchar.h>
#include "resource.h"
#include <atlbase.h>
#include <exdisp.h>

#include "mstscax.tlh"
#include "mstscax.tli"
using namespace MSTSCLib;


class CTscEventSink : public IMsTscAxEvents
{
public:
    CTscEventSink()
    {
        _ulRefs = 1;
        m_dwEvtCookie = 0;
    }
    ~CTscEventSink()
    {
    }
    BOOL Attach(IMsTscAx* pTscAx)
    {
        CComPtr<IConnectionPointContainer> cpCPCont;
        HRESULT hr;
        hr = pTscAx->QueryInterface(IID_IConnectionPointContainer, (LPVOID *)&cpCPCont);
        if (FAILED(hr))
            return FALSE;
        hr = cpCPCont->FindConnectionPoint(__uuidof(IMsTscAxEvents), &m_cpConnect);
        if (FAILED(hr))
        {
            return FALSE;
        }
        hr = m_cpConnect->Advise(this, &m_dwEvtCookie);
        if (FAILED(hr))
        {
            m_dwEvtCookie = 0;
            return FALSE;
        }
        return TRUE;
    }
    void Detach()
    {
        if ((m_dwEvtCookie) && (m_cpConnect))
            m_cpConnect->Unadvise(m_dwEvtCookie);
        if (m_cpConnect)
            m_cpConnect = NULL;
    }
    //IUnknown Methods
    STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppv)
    {
        if (riid == __uuidof(IMsTscAxEvents))
        {
            *ppv = (IMsTscAxEvents *)this;
        }
        else
        {
            *ppv = NULL;
            return E_NOINTERFACE;
        }
        AddRef();
        return S_OK;
    }
    STDMETHOD_(ULONG, AddRef) (void)
    {
        InterlockedIncrement((LONG*)&_ulRefs);
        return _ulRefs;
    }
    STDMETHOD_(ULONG, Release) (void)
    {
        ULONG ulRefs = _ulRefs;
        if (InterlockedDecrement((LONG*)&_ulRefs) == 0)
        {
            delete this;
            return 0;
        }
        return _ulRefs;
    }
    HRESULT OnConnecting()
    {
        DebugBreak();
        ::MessageBoxA(NULL, "Connecting", "", 0);
    }
    HRESULT OnConnected()
    {
        DebugBreak();
        ::MessageBoxA(NULL, "Connected", "", 0);
    }
    HRESULT OnFatalError()
    {
        DebugBreak();
        ::MessageBoxA(NULL, "Fatal Error", "", 0);
    }
    HRESULT OnLoginComplete()
    {
        DebugBreak();
        ::MessageBoxA(NULL, "Login complete", "", 0);
    }
    HRESULT OnLogonError(
        long lError)
    {
        DebugBreak();
        ::MessageBoxA(NULL, "OnLogonError", "", 0);
    }
    HRESULT OnDisconnected(
        long discReason)
    {
        DebugBreak();
        ::MessageBoxA(NULL, "OnDisconnected", "", 0);
    }
    //IDispatch Methods
    STDMETHOD(GetTypeInfoCount)(UINT FAR* pctinfo)
    {
        return E_NOTIMPL;
    }
    STDMETHOD(GetTypeInfo)(UINT itinfo, LCID lcid, ITypeInfo FAR* FAR* pptinfo)
    {
        return E_NOTIMPL;
    }
    STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR FAR* FAR* rgszNames, UINT cNames,
        LCID lcid, DISPID FAR* rgdispid)
    {
        return E_NOTIMPL;
    }
    STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
        DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult,
        EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr)
    {

        return S_OK;
    }
protected:
    ULONG _ulRefs;
    DWORD m_dwEvtCookie;
    CComPtr<IConnectionPoint> m_cpConnect;
};


CTscEventSink * pCTscEventSink;
MSTSCLib::IMsRdpClient2* pInterface = NULL;


LRESULT CALLBACK WindowProc(HWND hWnd, UINT messg, WPARAM wParam, LPARAM lParam)
{
    switch (messg)
    {
    case WM_SIZE:

        break;
    case WM_CLOSE:

        DestroyWindow(hWnd);
        break;
    case WM_DESTROY:

        PostQuitMessage(0);
        break;
    default:

        return(DefWindowProc(hWnd, messg, wParam, lParam));
    }
    return 0;
}

int CALLBACK wWinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPWSTR lpCmdLine,
    int nCmdShow)
{

    WNDCLASS wndclass;
    wndclass.style = CS_VREDRAW | CS_HREDRAW;
    wndclass.lpfnWndProc = &WindowProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = NULL;
    wndclass.hCursor = NULL;
    wndclass.hbrBackground = reinterpret_cast <HBRUSH> (COLOR_BTNFACE + 1);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = L"RdpTest1";
    ::RegisterClass(&wndclass);

    HWND mainWindow = ::CreateWindow(
        L"RdpTest1",
        L"Rdp!",
        0,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        800,
        800,
        NULL,
        NULL,
        hInstance,
        0);
    ::ShowWindow(mainWindow, nCmdShow);
    ::UpdateWindow(mainWindow);

    //ocx

    typedef HRESULT(WINAPI *PFonc)(IUnknown*, HWND, IUnknown**);
    HINSTANCE hDLL2 = ::LoadLibrary(TEXT("atl.dll"));
    if (!hDLL2)
        return 1;

    PFonc AtlAxAttachControl = (PFonc) ::GetProcAddress(hDLL2, "AtlAxAttachControl");

    HRESULT hr = ::CoInitialize(0);

    HRESULT hrInit = CoInitialize(NULL);
    if (FAILED(hrInit)) return 0;
    CLSID clsid = __uuidof(MSTSCLib::MsRdpClient2);
    IID iid = __uuidof(MSTSCLib::IMsRdpClient2);
    HRESULT hrInterface = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, (void**)&pInterface);
    if (SUCCEEDED(hrInterface))
    {

        pCTscEventSink = new CTscEventSink();

        BOOL b = pCTscEventSink->Attach(pInterface);
        pInterface->PutServer(L"non_existing_server.lol");
        pInterface->PutFullScreen(VARIANT_TRUE);
        pInterface->PutDesktopWidth(GetSystemMetrics(SM_CXSCREEN));
        pInterface->PutDesktopHeight(GetSystemMetrics(SM_CYSCREEN));
        pInterface->PutUserName(L"some_incorrect_user");
        pInterface->AdvancedSettings2->PutClearTextPassword(L"some_incorrect_pass");

        pInterface->AdvancedSettings2->PutRDPPort(3389);

        IMsRdpExtendedSettings *pExtendedSetting = NULL;
        IID interface_MsRdpClient8NotSafeForScripting = __uuidof(MSTSCLib::MsRdpClient2NotSafeForScripting);
        HRESULT hr = pInterface->QueryInterface(interface_MsRdpClient8NotSafeForScripting, (void**)&pExtendedSetting);
        if (hr == S_OK)
        {
            VARIANT index;
            VariantInit(&index);
            V_VT(&index) = VT_BOOL;
            index.boolVal = VARIANT_TRUE;
            pExtendedSetting->put_Property((BSTR)L"DisableCredentialsDelegation", &index);
        }
        hr = AtlAxAttachControl(pInterface, mainWindow, 0);
        if (FAILED(hr)) {
            MessageBox(0, L"FAILED(AtlAxAttachControl(pitd, container, NULL))", L"Error", MB_ICONERROR | MB_OK);
        }
        HRESULT hrConnect = pInterface->Connect();
        if (FAILED(hrConnect))
        {
            MessageBoxW(NULL, L"pInterface->Connect()", L"Error", 0);
        }
        else MessageBoxW(NULL, L"pInterface->Connect() Success!!!", L"Success", 0);
    }
    else
    {
        wchar_t buf[16] = { 0 };
        _ltow(hrInterface, buf, 16);
        MessageBoxW(NULL, buf, L"CoCreateInstance failed", 0);
    }

    ::MSG message;
    while (::GetMessageA(&message, 0, 0, 0)) {
        switch (message.message) {
        case WM_QUIT:
            break;
        default:
            ::TranslateMessage(&message);
            ::DispatchMessage(&message);
            break;
        }
    }
    CoUninitialize();
    FreeLibrary(hDLL2);
    return 0;
}

Хорошо, так что я делаю в этом коде.Я создаю окно, создаю объект MSTSCLib::IMsRdpClient2* pInterface, присоединяю класс приемника событий, чтобы перехватывать события, к этому объекту и передаю ему недопустимые данные.Но никакие события не запускаются, OnFatalError, OnConnecting и т. Д. Никогда не вызывались, и HRESULT hrConnect = pInterface->Connect(); всегда возвращает S_OK, независимо от того, какой сервер / пользователь / пароль.Из того, что я понял, это поведение связано с реализацией Invoke в CTscEventSink Мне нужно сделать что-то внутри:

STDMETHOD(Invoke)(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
    DISPPARAMS FAR* pdispparams, VARIANT FAR* pvarResult,
    EXCEPINFO FAR* pexcepinfo, UINT FAR* puArgErr)
{

    return S_OK;
}

Вместо того, чтобы просто возвращать S_OK, мне нужно что-то сделать, чтобына самом деле передать команду подключения дальше.Может кто-нибудь помочь, что мне здесь делать ??Как то, что позвонить из Invoke ??Это загадка, и я не знаю примеров, и ни одна страница MSDN не говорит об этом.

...