windows-nt/Source/XPSP1/NT/termsrv/remdsk/client/rdhost/remotedesktopclient.h
2020-09-26 16:20:57 +08:00

593 lines
16 KiB
C++

/*++
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 <atlctl.h>
#include <RemoteDesktopTopLevelObject.h>
#include <ClientDataChannelMgr.h>
#include "RDCHostCP.h"
#pragma warning (disable: 4786)
#include <vector>
#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<IDC_EVENT_SOURCE_OBJ, CRemoteDesktopClientEventSink,
&DIID__ISAFRemoteDesktopClientEvents>,
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<CComSingleThreadModel>,
public IDispatchImpl<ISAFRemoteDesktopClient, &IID_ISAFRemoteDesktopClient, &LIBID_RDCCLIENTHOSTLib>,
public IDispatchImpl<ISAFRemoteDesktopTestExtension, &IID_ISAFRemoteDesktopTestExtension, &LIBID_RDCCLIENTHOSTLib>,
public CComControl<CRemoteDesktopClient>,
public IPersistStreamInitImpl<CRemoteDesktopClient>,
public IOleControlImpl<CRemoteDesktopClient>,
public IOleObjectImpl<CRemoteDesktopClient>,
public IOleInPlaceActiveObjectImpl<CRemoteDesktopClient>,
public IViewObjectExImpl<CRemoteDesktopClient>,
public IOleInPlaceObjectWindowlessImpl<CRemoteDesktopClient>,
public IConnectionPointContainerImpl<CRemoteDesktopClient>,
public IPersistStorageImpl<CRemoteDesktopClient>,
public ISpecifyPropertyPagesImpl<CRemoteDesktopClient>,
public IQuickActivateImpl<CRemoteDesktopClient>,
public IDataObjectImpl<CRemoteDesktopClient>,
public IProvideClassInfo2Impl<&CLSID_SAFRemoteDesktopClient, &DIID__ISAFRemoteDesktopClientEvents, &LIBID_RDCCLIENTHOSTLib>,
public IPropertyNotifySinkCP<CRemoteDesktopClient>,
public CComCoClass<CRemoteDesktopClient, &CLSID_SAFRemoteDesktopClient>,
public CProxy_ISAFRemoteDesktopClientEvents< CRemoteDesktopClient >
{
private:
typedef std::vector<LONG, CRemoteDesktopAllocator<LONG> > ChannelsType;
ChannelsType m_Channels;
CComPtr<ISAFRemoteDesktopClient> 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<IDispatch> m_OnConnected;
CComPtr<IDispatch> m_OnDisconnected;
CComPtr<IDispatch> m_OnConnectRemoteDesktopComplete;
CComPtr<IDispatch> m_OnListenConnect;
CComPtr<IDispatch> m_OnBeginConnect;
//
// Data Channel Manager Interface
//
CComObject<CClientDataChannelMgr> *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<CRemoteDesktopClient>)
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_