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

843 lines
23 KiB
C++

/*++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
TSRDPRemoteDesktopClient
Abstract:
This is the TS/RDP implementation of the Remote Desktop Client class.
The Remote Desktop Client 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
The TSRDPRemoteDesktopClass implements remote-desktopping
with the help of an instance of the MSTSC ActiveX client control.
Author:
Tad Brockway 02/00
Revision History:
--*/
#ifndef __TSRDPREMOTEDESKTOPCLIENT_H_
#define __TSRDPREMOTEDESKTOPCLIENT_H_
#include "resource.h"
#include <atlctl.h>
#include "RDCHostCP.h"
#include <mstsax.h>
#include <rdchost.h>
#include <RemoteDesktopTopLevelObject.h>
#include <RemoteDesktopUtils.h>
#include "parseaddr.h"
#pragma warning (disable: 4786)
#include <list>
#include "icshelpapi.h"
#define IDC_MSTSCEVENT_SOURCE_OBJ 1
#define IDC_CHANNELEVENT_SOURCE_OBJ 2
#define WM_STARTLISTEN (0xBFFE)
#define WM_TSCONNECT (0xBFFF)
#define WM_LISTENTIMEOUT_TIMER 1
#define WM_CONNECTCHECK_TIMER 2
#define MAX_FETCHIPADDRESSRETRY 5
//
// MSTSC ActiveX GUID
//
#define MSTSCAX_TEXTGUID _T("{7cacbd7b-0d99-468f-ac33-22e495c0afe5}")
#define RDC_CHECKCONN_TIMEOUT (30 * 1000) //millisec. default value to ping is 30 seconds
#define RDC_CONNCHECK_ENTRY L"ConnectionCheck"
//
// 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 TSRDPClientEventFuncNoParamsInfo =
{
CC_STDCALL, // Calling convention.
VT_EMPTY, // Return type.
0, // Number of arguments.
{VT_EMPTY} // Argument types.
};
static _ATL_FUNC_INFO TSRDPClientEventFuncLongParamInfo =
{
CC_STDCALL, // Calling convention.
VT_EMPTY, // Return type.
1, // Number of arguments.
{VT_I4} // Argument types.
};
static _ATL_FUNC_INFO TSRDPClientEventFuncTwoStringParamInfo =
{
CC_STDCALL, // Calling convention.
VT_EMPTY, // Return type.
2, // Number of arguments.
{VT_BSTR, // Argument types
VT_BSTR}
};
static _ATL_FUNC_INFO TSRDPClientEventFuncReceivePublicKeyParamInfo =
{
CC_STDCALL, // Calling convention.
VT_EMPTY, // Return type.
2, // Number of arguments.
{VT_BSTR, // Argument types
VT_BYREF | VT_BOOL }
};
static _ATL_FUNC_INFO TSRDPClientEventFuncOneStringParamInfo =
{
CC_STDCALL, // Calling convention.
VT_EMPTY, // Return type.
1, // Number of arguments.
{VT_BSTR} // Argument types
};
///////////////////////////////////////////////////////
//
// CMSTSCClientEventSink
//
class CTSRDPRemoteDesktopClient;
class CMSTSCClientEventSink :
public IDispEventSimpleImpl<IDC_MSTSCEVENT_SOURCE_OBJ, CMSTSCClientEventSink,
&DIID_IMsTscAxEvents>,
public CRemoteDesktopTopLevelObject
{
public:
CTSRDPRemoteDesktopClient *m_Obj;
public:
BEGIN_SINK_MAP(CMSTSCClientEventSink)
SINK_ENTRY_INFO(IDC_MSTSCEVENT_SOURCE_OBJ, DIID_IMsTscAxEvents,
DISPID_CONNECTED, OnRDPConnected,
&TSRDPClientEventFuncNoParamsInfo)
SINK_ENTRY_INFO(IDC_MSTSCEVENT_SOURCE_OBJ, DIID_IMsTscAxEvents,
DISPID_DISCONNECTED, OnDisconnected,
&TSRDPClientEventFuncLongParamInfo)
SINK_ENTRY_INFO(IDC_MSTSCEVENT_SOURCE_OBJ, DIID_IMsTscAxEvents,
DISPID_LOGINCOMPLETE, OnLoginComplete,
&TSRDPClientEventFuncNoParamsInfo)
SINK_ENTRY_INFO(IDC_MSTSCEVENT_SOURCE_OBJ, DIID_IMsTscAxEvents,
DISPID_RECEVIEDTSPUBLICKEY, OnReceivedTSPublicKey,
&TSRDPClientEventFuncReceivePublicKeyParamInfo)
SINK_ENTRY_INFO(IDC_MSTSCEVENT_SOURCE_OBJ, DIID_IMsTscAxEvents,
DISPID_CHANNELRECEIVEDDATA, OnReceiveData,
&TSRDPClientEventFuncTwoStringParamInfo)
END_SINK_MAP()
CMSTSCClientEventSink()
{
m_Obj = NULL;
}
~CMSTSCClientEventSink();
//
// Event Sinks
//
void __stdcall OnReceivedTSPublicKey(BSTR publicKey, VARIANT_BOOL* pfContinue);
HRESULT __stdcall OnRDPConnected();
HRESULT __stdcall OnLoginComplete();
HRESULT __stdcall OnDisconnected(long disconReason);
void __stdcall OnReceiveData(BSTR chanName, BSTR data);
//
// Return the name of this class.
//
virtual const LPTSTR ClassName() {
return TEXT("CMSTSCClientEventSink");
}
};
///////////////////////////////////////////////////////
//
// CCtlChannelEventSink
//
// Control Channel Event Sink
//
class CCtlChannelEventSink :
public IDispEventSimpleImpl<IDC_CHANNELEVENT_SOURCE_OBJ, CCtlChannelEventSink,
&DIID__ISAFRemoteDesktopDataChannelEvents>,
public CRemoteDesktopTopLevelObject
{
public:
CTSRDPRemoteDesktopClient *m_Obj;
public:
BEGIN_SINK_MAP(CCtlChannelEventSink)
SINK_ENTRY_INFO(IDC_CHANNELEVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopDataChannelEvents,
DISPID_RDSCHANNELEVENTS_CHANNELDATAREADY, DataReady,
&TSRDPClientEventFuncOneStringParamInfo)
END_SINK_MAP()
CCtlChannelEventSink()
{
m_Obj = NULL;
}
~CCtlChannelEventSink();
//
// Event Sinks
//
void __stdcall DataReady(BSTR channelName);
//
// Return the name of this class.
//
virtual const LPTSTR ClassName() {
return TEXT("CCtlChannelEventSink");
}
};
///////////////////////////////////////////////////////
//
// CTSRDPRemoteDesktopClient
//
class CMSTSCClientEventSink;
class ATL_NO_VTABLE CTSRDPRemoteDesktopClient :
public CComObjectRootEx<CComSingleThreadModel>,
public CComControl<CTSRDPRemoteDesktopClient>,
public IPersistStreamInitImpl<CTSRDPRemoteDesktopClient>,
public IOleControlImpl<CTSRDPRemoteDesktopClient>,
public IOleObjectImpl<CTSRDPRemoteDesktopClient>,
public IOleInPlaceActiveObjectImpl<CTSRDPRemoteDesktopClient>,
public IViewObjectExImpl<CTSRDPRemoteDesktopClient>,
public IOleInPlaceObjectWindowlessImpl<CTSRDPRemoteDesktopClient>,
public IPersistStorageImpl<CTSRDPRemoteDesktopClient>,
public ISpecifyPropertyPagesImpl<CTSRDPRemoteDesktopClient>,
public IQuickActivateImpl<CTSRDPRemoteDesktopClient>,
public IDataObjectImpl<CTSRDPRemoteDesktopClient>,
public IProvideClassInfo2Impl<&CLSID_TSRDPRemoteDesktopClient, &DIID__ISAFRemoteDesktopClientEvents, &LIBID_RDCCLIENTHOSTLib>,
public CComCoClass<CTSRDPRemoteDesktopClient, &CLSID_TSRDPRemoteDesktopClient>,
public IDispatchImpl<ISAFRemoteDesktopClient, &IID_ISAFRemoteDesktopClient, &LIBID_RDCCLIENTHOSTLib>,
public IDispatchImpl<ISAFRemoteDesktopTestExtension, &IID_ISAFRemoteDesktopTestExtension, &LIBID_RDCCLIENTHOSTLib>,
public IDataChannelIO,
public CProxy_ISAFRemoteDesktopClientEvents< CTSRDPRemoteDesktopClient>,
public CProxy_IDataChannelIOEvents< CTSRDPRemoteDesktopClient>,
public IConnectionPointContainerImpl<CTSRDPRemoteDesktopClient>,
public CRemoteDesktopTopLevelObject
{
friend CCtlChannelEventSink;
private:
IMsRdpClient2 *m_TSClient;
HWND m_TSClientWnd;
CAxWindow m_TSClientAxView;
BOOL m_ConnectionInProgress;
BOOL m_RemoteControlRequestInProgress;
BOOL m_ConnectedToServer;
BOOL m_Initialized;
LONG m_LastExtendedErrorInfo;
//
// Event sink receives events fired by the TS client control..
//
CMSTSCClientEventSink m_TSClientEventSink;
//
// Control Channel Event Sink
//
CCtlChannelEventSink m_CtlChannelEventSink;
//
// Multiplexes Channel Data
//
CComPtr<ISAFRemoteDesktopChannelMgr> m_ChannelMgr;
CComPtr<ISAFRemoteDesktopDataChannel> m_CtlChannel;
//
// The parsed connection parameters.
//
DWORD m_ConnectParmVersion;
CComBSTR m_AssistantAccount;
CComBSTR m_AssistantAccountPwd;
CComBSTR m_HelpSessionName;
CComBSTR m_HelpSessionID;
CComBSTR m_HelpSessionPwd;
CComBSTR m_TSSecurityBlob;
ServerAddressList m_ServerAddressList;
CComBSTR m_ConnectedServer;
LONG m_ConnectedPort;
//
// The complete connection string.
//
CComBSTR m_ConnectParms;
//
// Expert side to be transmitted over to user
//
CComBSTR m_ExpertBlob;
//
// Search for a child window of the specified parent window.
//
typedef struct _WinSearch
{
HWND foundWindow;
LPTSTR srchCaption;
LPTSTR srchClass;
} WINSEARCH, *PWINSEARCH;
HWND SearchForWindow(HWND hwndParent, LPTSTR srchCaption, LPTSTR srchClass);
static BOOL CALLBACK _WindowSrchProc(HWND hwnd, PWINSEARCH srch);
//timer related members
DWORD m_PrevTimer;
UINT m_TimerId;
DWORD m_RdcConnCheckTimeInterval;
BOOL m_ListenConnectInProgress; // duration of StartListen() until mstscax connected.
SOCKET m_ListenSocket; // listen() socket
SOCKET m_TSConnectSocket; // accept() scoket
DWORD m_ICSPort; // port that ICS library punch on ICS server
BOOL m_InitListeningLibrary; // Instance of object initialize WinSock/ICS library.
UINT_PTR m_ListenTimeoutTimerID; // Timer ID for listen timeout.
void
ListenConnectCleanup()
{
m_ListenConnectInProgress = FALSE;
if( INVALID_SOCKET != m_ListenSocket ) {
closesocket( m_ListenSocket );
}
if( (UINT_PTR)0 != m_ListenTimeoutTimerID ) {
KillTimer( m_ListenTimeoutTimerID );
}
if( INVALID_SOCKET != m_TSConnectSocket ) {
closesocket( m_TSConnectSocket );
}
if( 0 != m_ICSPort ) {
ClosePort( m_ICSPort );
}
m_ListenSocket = INVALID_SOCKET;
m_TSConnectSocket = INVALID_SOCKET;
m_ICSPort = 0;
}
//
// Variable to manage WinSock and ICS library startup/shutdown, WinSock/ICS library
// is RDP specific so not declare in parent class.
//
static LONG gm_ListeningLibraryRefCount; // Number of time we reference WinSock and ICS library
//
// accessing only global variable, no need for per-instance.
//
static HRESULT
InitListeningLibrary();
static HRESULT
TerminateListeningLibrary();
//
// Listen socket already in progress
//
inline BOOL
ListenConnectInProgress() {
return m_ListenConnectInProgress;
}
protected:
//
// Final Initialization.
//
virtual HRESULT Initialize(LPCREATESTRUCT pCreateStruct);
//
// Generate a remote control request message for the
// server.
//
HRESULT GenerateRCRequest(BSTR *rcRequest);
//
// Generate a 'client authenticate' request.
//
HRESULT GenerateClientAuthenticateRequest(BSTR *authenticateReq);
//
// Generate a version information packet.
//
HRESULT GenerateVersionInfoPacket(BSTR *versionInfoPacket);
//
// Send the terminate shadowing key sequence to the server.
//
HRESULT SendTerminateRCKeysToServer();
//
// Handle Remote Control 'Control' Channel messages.
//
VOID HandleControlChannelMsg();
//
// Translate an MSTSC disconnect code into a Salem disconnect
// code.
//
LONG TranslateMSTSCDisconnectCode(DisconnectReasonCode disconReason,
ExtendedDisconnectReasonCode extendedReasonCode);
//
// Disconnects the client from the server.
//
STDMETHOD(DisconnectFromServerInternal)(
LONG disconnectCode
);
HRESULT
SetupConnectionInfo(BOOL bListen, BSTR expertBlob);
//
// Connect to server with port
//
HRESULT
ConnectServerPort(
BSTR ServerName,
LONG portNumber
);
//
// Connect to server with established socket
//
HRESULT
ConnectServerWithOpenedSocket();
//generate a simple message for checking if the connection is alive
HRESULT GenerateNullData(BSTR *bstrMsg);
//
// Retrieve connect parm
//
HRESULT
RetrieveUserConnectParm( BSTR* pConnectParm );
void
FireListenConnect( DWORD ErrCode )
{
return;
}
public:
//
// Constructor/Destructor
//
CTSRDPRemoteDesktopClient() {
//
// We are window'd, even if our parent supports Windowless
// controls.
//
m_bWindowOnly = TRUE;
m_ConnectedToServer = FALSE;
m_Initialized = FALSE;
m_TSClient = NULL;
m_TSClientWnd = NULL;
m_ConnectionInProgress = FALSE;
m_RemoteControlRequestInProgress = FALSE;
m_LastExtendedErrorInfo = 0;
m_TimerId = 0; //used for pinging
m_RdcConnCheckTimeInterval = RDC_CHECKCONN_TIMEOUT;
//
// No reference to listening library.
//
m_InitListeningLibrary = FALSE;
m_ListenConnectInProgress = FALSE;
m_ListenSocket = INVALID_SOCKET;
m_TSConnectSocket = INVALID_SOCKET;
m_ListenTimeoutTimerID = (UINT_PTR) 0;
m_ICSPort = 0;
//
// Not valid until unitialized.
//
SetValid(FALSE);
}
~CTSRDPRemoteDesktopClient();
HRESULT FinalConstruct();
DECLARE_REGISTRY_RESOURCEID(IDR_TSRDPREMOTEDESKTOPCLIENT)
DECLARE_PROTECT_FINAL_CONSTRUCT()
//
// Event Sinks
//
VOID OnRDPConnected();
VOID OnLoginComplete();
VOID OnDisconnected(long disconReason);
VOID OnMSTSCReceiveData(BSTR data);
VOID OnReceivedTSPublicKey(BSTR tsPublicKey, VARIANT_BOOL* bContinue);
//
// Interface Map
//
BEGIN_COM_MAP(CTSRDPRemoteDesktopClient)
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(ISpecifyPropertyPages)
COM_INTERFACE_ENTRY(IQuickActivate)
COM_INTERFACE_ENTRY(IPersistStorage)
COM_INTERFACE_ENTRY(IDataObject)
COM_INTERFACE_ENTRY(IProvideClassInfo)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
COM_INTERFACE_ENTRY(ISAFRemoteDesktopClient)
COM_INTERFACE_ENTRY(ISAFRemoteDesktopTestExtension)
COM_INTERFACE_ENTRY2(IDispatch, ISAFRemoteDesktopClient)
COM_INTERFACE_ENTRY(IDataChannelIO)
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()
//
// Property Map
//
BEGIN_PROP_MAP(CTSRDPRemoteDesktopClient)
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(CTSRDPRemoteDesktopClient)
CONNECTION_POINT_ENTRY(DIID__ISAFRemoteDesktopClientEvents)
CONNECTION_POINT_ENTRY(DIID__IDataChannelIOEvents)
END_CONNECTION_POINT_MAP()
//
// Message Map
//
BEGIN_MSG_MAP(CTSRDPRemoteDesktopClient)
CHAIN_MSG_MAP(CComControl<CTSRDPRemoteDesktopClient>)
DEFAULT_REFLECTION_HANDLER()
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_TSCONNECT, OnTSConnect)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
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:
LRESULT OnTSConnect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnStartListen(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
//
// OnDraw
//
HRESULT OnDraw(ATL_DRAWINFO& di)
{
RECT& rc = *(RECT*)di.prcBounds;
Rectangle(di.hdcDraw, rc.left, rc.top, rc.right, rc.bottom);
HRESULT hr;
if (!m_Initialized) {
hr = S_OK;
SetTextAlign(di.hdcDraw, TA_CENTER|TA_BASELINE);
LPCTSTR pszText = _T("TSRDP Remote Desktop Client");
TextOut(di.hdcDraw,
(rc.left + rc.right) / 2,
(rc.top + rc.bottom) / 2,
pszText,
lstrlen(pszText));
}
return hr;
}
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
//
// Hide our window, by default.
//
//ShowWindow(SW_HIDE);
if (!m_Initialized) {
LPCREATESTRUCT pCreateStruct = (LPCREATESTRUCT)lParam;
Initialize(pCreateStruct);
}
return 0;
}
LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DC_BEGIN_FN("CTSRDPRemoteDesktopClient::OnSetFocus");
//
// Set focus back to the client window, if it exists.
//
if (m_TSClientWnd != NULL) {
::PostMessage(m_TSClientWnd, uMsg, wParam, lParam);
}
DC_END_FN();
return 0;
}
//
// OnSize
//
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DC_BEGIN_FN("CTSRDPRemoteDesktopClient::OnSize");
if (m_TSClientWnd != NULL) {
RECT rect;
GetClientRect(&rect);
::MoveWindow(m_TSClientWnd, rect.left, rect.top,
rect.right, rect.bottom, TRUE);
}
DC_END_FN();
return 0;
}
LRESULT OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
bHandled = TRUE;
return 0;
//return DefWindowProc(uMsg, wParam, lParam);
}
//
// ISAFRemoteDesktopClient Methods
//
STDMETHOD(ConnectToServer)(BSTR Server);
STDMETHOD(DisconnectFromServer)();
STDMETHOD(ConnectRemoteDesktop)();
STDMETHOD(DisconnectRemoteDesktop)();
STDMETHOD(get_IsRemoteDesktopConnected)(BOOL * pVal);
STDMETHOD(get_IsServerConnected)(BOOL * pVal);
STDMETHOD(put_EnableSmartSizing)(BOOL val);
STDMETHOD(get_EnableSmartSizing)(BOOL *pVal);
STDMETHOD(put_ColorDepth)(LONG Val);
STDMETHOD(get_ColorDepth)(LONG* pVal);
STDMETHOD(get_ExtendedErrorInfo)(LONG *error) {
*error = m_LastExtendedErrorInfo;
return S_OK;
}
STDMETHOD(get_ChannelManager)(ISAFRemoteDesktopChannelMgr **mgr) {
*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;
}
//
// Scriptable Event Object Registration Properties (not supported)
//
STDMETHOD(put_OnConnected)(/*[in]*/IDispatch *iDisp) { return E_FAIL; }
STDMETHOD(put_OnDisconnected)(/*[in]*/IDispatch *iDisp) { return E_FAIL; }
STDMETHOD(put_OnConnectRemoteDesktopComplete)(/*[in]*/IDispatch *iDisp) { return E_FAIL; }
STDMETHOD(put_OnListenConnect)(/*[in]*/IDispatch *iDisp) { return E_FAIL; }
STDMETHOD(put_OnBeginConnect)(/*[in]*/IDispatch *iDisp) { return E_FAIL; }
//
// IDataChannelIO Methods
//
STDMETHOD(SendData)(/*[in]*/BSTR data);
STDMETHOD(put_ChannelMgr)(/*[in]*/ISAFRemoteDesktopChannelMgr *newVal);
//
// Return the name of this class.
//
virtual const LPTSTR ClassName() {
return TEXT("CTSRDPRemoteDesktopServer");
}
//
// ISAFRemoteDesktopTestExtension
//
STDMETHOD(put_TestExtDllName)(/*[in]*/BSTR newVal);
STDMETHOD(put_TestExtParams)(/*[in]*/BSTR newVal);
STDMETHOD(get_ConnectedServer)(/*[in]*/BSTR* Val) {
HRESULT hr = S_OK;
if( m_ConnectedToServer ) {
*Val = m_ConnectedServer.Copy();
}
else {
hr = E_FAIL;
}
return hr;
}
STDMETHOD(get_ConnectedPort)(/*[in]*/LONG* Val) {
HRESULT hr = S_OK;
if( m_ConnectedToServer ) {
*Val = m_ConnectedPort;
}
else {
hr = E_FAIL;
}
return hr;
}
STDMETHOD(CreateListenEndpoint)(
/*[in]*/ LONG port,
/*[out, retval]*/ BSTR* pConnectParm
);
STDMETHOD(StartListen)(
/*[in]*/ LONG timeout
);
STDMETHOD(AcceptListenConnection)(
/*[in]*/BSTR expertBlob
);
STDMETHOD(StopListen)();
};
///////////////////////////////////////////////////////
//
// CTSRDPRemoteDesktopClient Inline Methods
//
inline STDMETHODIMP
CTSRDPRemoteDesktopClient::get_IsServerConnected(
BOOL *pVal
)
/*++
Routine Description:
Indicates whether the client is connected to the server, excluding
control over the remote user's desktop.
Arguments:
pVal - Set to TRUE if the client is connected to the server.
Return Value:
S_OK on success. Otherwise, an error code is returned.
--*/
{
DC_BEGIN_FN("CTSRDPRemoteDesktopClient::get_IsServerConnected");
HRESULT hr = S_OK;
if (IsValid()) {
*pVal = m_ConnectedToServer;
}
else {
ASSERT(FALSE);
hr = E_FAIL;
}
DC_END_FN();
return hr;
}
inline STDMETHODIMP
CTSRDPRemoteDesktopClient::get_IsRemoteDesktopConnected(
BOOL *pVal
)
/*++
Routine Description:
Indicates whether the control is currently controlling the remote user's
desktop.
Arguments:
pVal - Sets to TRUE if the control is currently connected to the server.
Return Value:
S_OK on success. Otherwise, an error code is returned.
--*/
{
DC_BEGIN_FN("CTSRDPRemoteDesktopClient::get_IsRemoteDesktopConnected");
HRESULT hr = S_OK;
if (IsValid()) {
*pVal = m_RemoteControlRequestInProgress;
}
else {
ASSERT(FALSE);
hr = E_FAIL;
}
DC_END_FN();
return hr;
}
#endif //__TSRDPREMOTEDESKTOPCLIENT_H_