/*++ Copyright (c) 1999-2000 Microsoft Corporation Module Name: RemoteDesktopClient Abstract: The CRemoteDesktopClient class is the parent class for the Remote Desktop class hierarchy on the client-side. It helps the CRemoteDesktopClientHost class to implement the ISAFRemoteDesktopClient interface. The Remote Desktop class hierarchy provides a pluggable C++ interface for remote desktop access, by abstracting the implementation specific details of remote desktop access for the client-side of . Author: Tad Brockway 02/00 Revision History: --*/ #ifndef __REMOTEDESKTOPCLIENT_H_ #define __REMOTEDESKTOPCLIENT_H_ #include "resource.h" #include #include #include #include "RDCHostCP.h" #pragma warning (disable: 4786) #include #define IDC_EVENT_SOURCE_OBJ 1 // // Info for all the event functions is entered here // there is a way to have ATL do this automatically using typelib's // but it is slower. // static _ATL_FUNC_INFO EventFuncNoParamsInfo = { CC_STDCALL, // Calling convention. VT_EMPTY, // Return type. 0, // Number of arguments. {VT_EMPTY} // Argument types. }; static _ATL_FUNC_INFO EventFuncLongParamInfo = { CC_STDCALL, // Calling convention. VT_EMPTY, // Return type. 1, // Number of arguments. {VT_I4} // Argument types. }; typedef enum { CONNECTION_STATE_NOTCONNECTED, // not connected CONNECTION_STATE_CONNECTPENDINGCONNECT, // Initiate connection and still waiting for connection to succeed CONNECTION_STATE_LISTENPENDINGCONNECT, // Listening for incoming connection. CONNECTION_STATE_CONNECTED // we are connected. } CONNECTION_STATE; /////////////////////////////////////////////////////// // // CRemoteDesktopClientEventSink // class CRemoteDesktopClient; class CRemoteDesktopClientEventSink : public IDispEventSimpleImpl, public CRemoteDesktopTopLevelObject { public: CRemoteDesktopClient *m_Obj; public: BEGIN_SINK_MAP(CRemoteDesktopClientEventSink) SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents, DISPID_RDSCLIENTEVENTS_CONNECTED, OnConnected, &EventFuncNoParamsInfo) SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents, DISPID_RDSCLIENTEVENTS_DISCONNECTED, OnDisconnected, &EventFuncLongParamInfo) SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents, DISPID_RDSCLIENTEVENTS_REMOTECONTROLREQUESTCOMPLETE, OnConnectRemoteDesktopComplete, &EventFuncLongParamInfo) SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents, DISPID_RDSCLIENTEVENTS_LISTENCONNECT, OnListenConnect, &EventFuncLongParamInfo) SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents, DISPID_RDSCLIENTEVENTS_BEGINCONNECT, OnBeginConnect, &EventFuncNoParamsInfo) END_SINK_MAP() CRemoteDesktopClientEventSink() { m_Obj = NULL; } // // Event Sinks // void __stdcall OnConnected(); void __stdcall OnDisconnected(long reason); void __stdcall OnConnectRemoteDesktopComplete(long status); void __stdcall OnListenConnect(long status); void __stdcall OnBeginConnect(); // // Return the name of this class. // virtual const LPTSTR ClassName() { return TEXT("CRemoteDesktopClientEventSink"); } }; /////////////////////////////////////////////////////// // // CRemoteDesktopClient // class ATL_NO_VTABLE CRemoteDesktopClient : public CRemoteDesktopTopLevelObject, public CComObjectRootEx, public IDispatchImpl, public IDispatchImpl, public CComControl, public IPersistStreamInitImpl, public IOleControlImpl, public IOleObjectImpl, public IOleInPlaceActiveObjectImpl, public IViewObjectExImpl, public IOleInPlaceObjectWindowlessImpl, public IConnectionPointContainerImpl, public IPersistStorageImpl, public ISpecifyPropertyPagesImpl, public IQuickActivateImpl, public IDataObjectImpl, public IProvideClassInfo2Impl<&CLSID_SAFRemoteDesktopClient, &DIID__ISAFRemoteDesktopClientEvents, &LIBID_RDCCLIENTHOSTLib>, public IPropertyNotifySinkCP, public CComCoClass, public CProxy_ISAFRemoteDesktopClientEvents< CRemoteDesktopClient > { private: typedef std::vector > ChannelsType; ChannelsType m_Channels; CComPtr m_Client; BSTR m_ExtDllName; BSTR m_ExtParams; HWND m_ClientWnd; CAxWindow m_ClientAxView; BOOL m_RemoteControlEnabled; BOOL m_EnableSmartSizing; LONG m_ColorDepth; CONNECTION_STATE m_ConnectingState; // // Event sink receives events fired by the client control.. // CRemoteDesktopClientEventSink m_ClientEventSink; // // IDispatch Pointers for Scriptable Event Object Registrations // CComPtr m_OnConnected; CComPtr m_OnDisconnected; CComPtr m_OnConnectRemoteDesktopComplete; CComPtr m_OnListenConnect; CComPtr m_OnBeginConnect; // // Data Channel Manager Interface // CComObject *m_ChannelMgr; // // Connect Parameters // CComBSTR m_ConnectParms; HRESULT _PutExtParams( VOID ); HRESULT InitializeRemoteDesktopClientObject(); public: CRemoteDesktopClient() { DC_BEGIN_FN("CRemoteDesktopClient::CRemoteDesktopClient"); m_RemoteControlEnabled = FALSE; // // We are window'd, even if our parent supports Windowless // controls. // m_bWindowOnly = TRUE; m_ClientWnd = NULL; m_EnableSmartSizing = FALSE; m_ExtDllName = m_ExtParams = NULL; m_ColorDepth = 8; DC_END_FN(); } virtual ~CRemoteDesktopClient(); HRESULT FinalConstruct(); // // Event Sinks // void OnConnected(); void OnDisconnected(long reason); void OnConnectRemoteDesktopComplete(long status); void OnListenConnect(long status); void OnBeginConnect(); DECLARE_REGISTRY_RESOURCEID(IDR_REMOTEDESKTOPCLIENT) DECLARE_PROTECT_FINAL_CONSTRUCT() // // COM Interface Map // BEGIN_COM_MAP(CRemoteDesktopClient) COM_INTERFACE_ENTRY(ISAFRemoteDesktopClient) COM_INTERFACE_ENTRY(ISAFRemoteDesktopTestExtension) COM_INTERFACE_ENTRY2(IDispatch, ISAFRemoteDesktopClient) COM_INTERFACE_ENTRY(IViewObjectEx) COM_INTERFACE_ENTRY(IViewObject2) COM_INTERFACE_ENTRY(IViewObject) COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY(IOleInPlaceObject) COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless) COM_INTERFACE_ENTRY(IOleInPlaceActiveObject) COM_INTERFACE_ENTRY(IOleControl) COM_INTERFACE_ENTRY(IOleObject) COM_INTERFACE_ENTRY(IPersistStreamInit) COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) COM_INTERFACE_ENTRY(IConnectionPointContainer) COM_INTERFACE_ENTRY(ISpecifyPropertyPages) COM_INTERFACE_ENTRY(IQuickActivate) COM_INTERFACE_ENTRY(IPersistStorage) COM_INTERFACE_ENTRY(IDataObject) COM_INTERFACE_ENTRY(IProvideClassInfo) COM_INTERFACE_ENTRY(IProvideClassInfo2) COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer) END_COM_MAP() // // Property Map // BEGIN_PROP_MAP(CRemoteDesktopClient) PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4) PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4) // Example entries // PROP_ENTRY("Property Description", dispid, clsid) // PROP_PAGE(CLSID_StockColorPage) END_PROP_MAP() // // Connection Point Map // BEGIN_CONNECTION_POINT_MAP(CRemoteDesktopClient) CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink) CONNECTION_POINT_ENTRY(DIID__ISAFRemoteDesktopClientEvents) END_CONNECTION_POINT_MAP() // // Message Map // BEGIN_MSG_MAP(CRemoteDesktopClient) CHAIN_MSG_MAP(CComControl) DEFAULT_REFLECTION_HANDLER() MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) MESSAGE_HANDLER(WM_CREATE, OnCreate) MESSAGE_HANDLER(WM_SIZE, OnSize) END_MSG_MAP() // // Handler prototypes: // // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled); // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled); // // IViewObjectEx Methods // DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE) public: STDMETHOD(CreateListenEndpoint)( /*[in]*/ LONG port, /*[out, retval]*/ BSTR* pConnectParm ); STDMETHOD(StartListen)( /*[in]*/ LONG timeout ); STDMETHOD(AcceptListenConnection)( /*[in]*/BSTR expertBlob ); STDMETHOD(StopListen)(); STDMETHOD(get_IsRemoteDesktopConnected)(/*[out, retval]*/ BOOL *pVal); STDMETHOD(get_IsServerConnected)(/*[out, retval]*/BOOL *pVal); STDMETHOD(DisconnectRemoteDesktop)(); STDMETHOD(ConnectRemoteDesktop)(); STDMETHOD(ConnectToServer)(BSTR bstrServer); STDMETHOD(DisconnectFromServer)(); STDMETHOD(get_ExtendedErrorInfo)(/*[out, retval]*/LONG *error); STDMETHOD(get_ChannelManager)(ISAFRemoteDesktopChannelMgr **mgr) { m_ChannelMgr->AddRef(); *mgr = m_ChannelMgr; return S_OK; } STDMETHOD(put_ConnectParms)(/*[in]*/BSTR parms) { m_ConnectParms = parms; return S_OK; } STDMETHOD(get_ConnectParms)(/*[out, retval]*/BSTR *parms) { CComBSTR tmp; tmp = m_ConnectParms; *parms = tmp.Detach(); return S_OK; } STDMETHOD(put_OnBeginConnect)(/*[in]*/IDispatch *iDisp) { m_OnBeginConnect = iDisp; return S_OK; } STDMETHOD(put_OnConnected)(/*[in]*/IDispatch *iDisp) { m_OnConnected = iDisp; return S_OK; } STDMETHOD(put_OnDisconnected)(/*[in]*/IDispatch *iDisp) { m_OnDisconnected = iDisp; return S_OK; } STDMETHOD(put_OnConnectRemoteDesktopComplete)(/*[in]*/IDispatch *iDisp) { m_OnConnectRemoteDesktopComplete = iDisp; return S_OK; } STDMETHOD(put_OnListenConnect)(/*[in]*/IDispatch *iDisp) { m_OnListenConnect = iDisp; return S_OK; } STDMETHOD(put_EnableSmartSizing)(/*[in]*/BOOL val) { HRESULT hr; if (m_Client != NULL) { hr = m_Client->put_EnableSmartSizing(val); if (hr == S_OK) { m_EnableSmartSizing = val; } } else { m_EnableSmartSizing = val; hr = S_OK; } return hr; } STDMETHOD(get_EnableSmartSizing)(/*[in]*/BOOL *pVal) { if (pVal != NULL) { *pVal = m_EnableSmartSizing; return S_OK; } else { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } } STDMETHOD(get_ConnectedServer)(/*[in]*/BSTR* Val) { HRESULT hr; if( NULL == Val ) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } else if( m_Client != NULL ) { hr = m_Client->get_ConnectedServer( Val ); } else { hr = E_FAIL; } return hr; } STDMETHOD(get_ConnectedPort)(/*[in]*/LONG* Val) { HRESULT hr; if( NULL == Val ) { hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } else if( m_Client != NULL ) { hr = m_Client->get_ConnectedPort( Val ); } else { hr = E_FAIL; } return hr; } STDMETHOD(put_ColorDepth)(/*[in]*/LONG Val) { HRESULT hr; if (m_Client != NULL) { hr = m_Client->put_ColorDepth(Val); if (hr == S_OK) { m_ColorDepth = Val; } } else { m_ColorDepth = Val; hr = S_OK; } return hr; } STDMETHOD(get_ColorDepth)(/*[out,retval]*/LONG* pVal) { if (pVal != NULL) { *pVal = m_ColorDepth; return S_OK; } else { return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER); } } // // OnCreate // LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // // Hide our window, by default. // //ShowWindow(SW_HIDE); return 0; } // // OnSetFocus // LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { // // Set focus back to the client window, if it exists. // if (m_ClientWnd != NULL) { ::PostMessage(m_ClientWnd, uMsg, wParam, lParam); } return 0; } // // OnSize // LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { DC_BEGIN_FN("CRemoteDesktopClient::OnSize"); if (m_ClientWnd != NULL) { RECT rect; GetClientRect(&rect); ::MoveWindow(m_ClientWnd, rect.left, rect.top, rect.right, rect.bottom, TRUE); } DC_END_FN(); return 0; } // // OnDraw // HRESULT OnDraw(ATL_DRAWINFO& di) { // // Make sure our window is hidden, if remote control is not // active. // if (!m_RemoteControlEnabled) { //ShowWindow(SW_HIDE); } return S_OK; } // // Return the name of this class. // virtual const LPTSTR ClassName() { return TEXT("CRemoteDesktopClient"); } // // ISAFRemoteDesktopTestExtension // STDMETHOD(put_TestExtDllName)(/*[in]*/BSTR newVal) { if ( NULL != m_ExtDllName ) SysFreeString( m_ExtDllName ); m_ExtDllName = SysAllocString( newVal ); return ( NULL != m_ExtDllName )?S_OK:E_OUTOFMEMORY; } STDMETHOD(put_TestExtParams)(/*[in]*/BSTR newVal) { if ( NULL != m_ExtParams ) SysFreeString( m_ExtDllName ); m_ExtParams = SysAllocString( newVal ); return ( NULL != m_ExtDllName )?S_OK:E_OUTOFMEMORY; } }; /////////////////////////////////////////////////////// // // CRemoteDesktopClient Inline Methods // inline void CRemoteDesktopClient::OnConnected() { Fire_Connected(m_OnConnected); } inline void CRemoteDesktopClient::OnDisconnected(long reason) { // // Hide our window. // m_RemoteControlEnabled = FALSE; //ShowWindow(SW_HIDE); Fire_Disconnected(reason, m_OnDisconnected); } inline void CRemoteDesktopClient::OnConnectRemoteDesktopComplete(long status) { // // Show our window, if the request succeeded. // if (status == ERROR_SUCCESS) { m_RemoteControlEnabled = TRUE; ShowWindow(SW_SHOW); } Fire_RemoteControlRequestComplete(status, m_OnConnectRemoteDesktopComplete); } inline void CRemoteDesktopClient::OnListenConnect(long status) { Fire_ListenConnect(status, m_OnListenConnect); } inline void CRemoteDesktopClient::OnBeginConnect() { ShowWindow(SW_SHOW); Fire_BeginConnect(m_OnBeginConnect); } #endif //__REMOTEDESKTOPCLIENT_H_