MSTSCLib :: MsRdpClient错误行为

时间:2018-12-04 23:33:39

标签: c++ winapi activex rdp mstsc

我正在尝试使用MsRdpClient连接到rdp服务器,并收到一些基本通知。现在,我遇到了同样的问题,人们已经有大约8年的时间了,但没有找到任何答案,因此我再次提出了这个话题。我所拥有的就是这样的代码,这些代码来自有关如何在Winapi中使用rdp的各种示例:

#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来进一步传递connect命令。有人可以帮忙吗,我需要在这里做什么?喜欢从Invoke打电话来吗?这太麻烦了,我不知道任何示例,也没有msdn页对此有所说明。

0 个答案:

没有答案