Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

592 lines
16 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. RemoteDesktopClient
  5. Abstract:
  6. The CRemoteDesktopClient class is the parent
  7. class for the Remote Desktop class hierarchy on the client-side.
  8. It helps the CRemoteDesktopClientHost class to implement
  9. the ISAFRemoteDesktopClient interface.
  10. The Remote Desktop class hierarchy provides a pluggable C++ interface
  11. for remote desktop access, by abstracting the implementation
  12. specific details of remote desktop access for the client-side of
  13. .
  14. Author:
  15. Tad Brockway 02/00
  16. Revision History:
  17. --*/
  18. #ifndef __REMOTEDESKTOPCLIENT_H_
  19. #define __REMOTEDESKTOPCLIENT_H_
  20. #include "resource.h"
  21. #include <atlctl.h>
  22. #include <RemoteDesktopTopLevelObject.h>
  23. #include <ClientDataChannelMgr.h>
  24. #include "RDCHostCP.h"
  25. #pragma warning (disable: 4786)
  26. #include <vector>
  27. #define IDC_EVENT_SOURCE_OBJ 1
  28. //
  29. // Info for all the event functions is entered here
  30. // there is a way to have ATL do this automatically using typelib's
  31. // but it is slower.
  32. //
  33. static _ATL_FUNC_INFO EventFuncNoParamsInfo =
  34. {
  35. CC_STDCALL, // Calling convention.
  36. VT_EMPTY, // Return type.
  37. 0, // Number of arguments.
  38. {VT_EMPTY} // Argument types.
  39. };
  40. static _ATL_FUNC_INFO EventFuncLongParamInfo =
  41. {
  42. CC_STDCALL, // Calling convention.
  43. VT_EMPTY, // Return type.
  44. 1, // Number of arguments.
  45. {VT_I4} // Argument types.
  46. };
  47. typedef enum {
  48. CONNECTION_STATE_NOTCONNECTED, // not connected
  49. CONNECTION_STATE_CONNECTPENDINGCONNECT, // Initiate connection and still waiting for connection to succeed
  50. CONNECTION_STATE_LISTENPENDINGCONNECT, // Listening for incoming connection.
  51. CONNECTION_STATE_CONNECTED // we are connected.
  52. } CONNECTION_STATE;
  53. ///////////////////////////////////////////////////////
  54. //
  55. // CRemoteDesktopClientEventSink
  56. //
  57. class CRemoteDesktopClient;
  58. class CRemoteDesktopClientEventSink :
  59. public IDispEventSimpleImpl<IDC_EVENT_SOURCE_OBJ, CRemoteDesktopClientEventSink,
  60. &DIID__ISAFRemoteDesktopClientEvents>,
  61. public CRemoteDesktopTopLevelObject
  62. {
  63. public:
  64. CRemoteDesktopClient *m_Obj;
  65. public:
  66. BEGIN_SINK_MAP(CRemoteDesktopClientEventSink)
  67. SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents,
  68. DISPID_RDSCLIENTEVENTS_CONNECTED, OnConnected,
  69. &EventFuncNoParamsInfo)
  70. SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents,
  71. DISPID_RDSCLIENTEVENTS_DISCONNECTED, OnDisconnected,
  72. &EventFuncLongParamInfo)
  73. SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents,
  74. DISPID_RDSCLIENTEVENTS_REMOTECONTROLREQUESTCOMPLETE,
  75. OnConnectRemoteDesktopComplete,
  76. &EventFuncLongParamInfo)
  77. SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents,
  78. DISPID_RDSCLIENTEVENTS_LISTENCONNECT,
  79. OnListenConnect,
  80. &EventFuncLongParamInfo)
  81. SINK_ENTRY_INFO(IDC_EVENT_SOURCE_OBJ, DIID__ISAFRemoteDesktopClientEvents,
  82. DISPID_RDSCLIENTEVENTS_BEGINCONNECT,
  83. OnBeginConnect,
  84. &EventFuncNoParamsInfo)
  85. END_SINK_MAP()
  86. CRemoteDesktopClientEventSink()
  87. {
  88. m_Obj = NULL;
  89. }
  90. //
  91. // Event Sinks
  92. //
  93. void __stdcall OnConnected();
  94. void __stdcall OnDisconnected(long reason);
  95. void __stdcall OnConnectRemoteDesktopComplete(long status);
  96. void __stdcall OnListenConnect(long status);
  97. void __stdcall OnBeginConnect();
  98. //
  99. // Return the name of this class.
  100. //
  101. virtual const LPTSTR ClassName() {
  102. return TEXT("CRemoteDesktopClientEventSink");
  103. }
  104. };
  105. ///////////////////////////////////////////////////////
  106. //
  107. // CRemoteDesktopClient
  108. //
  109. class ATL_NO_VTABLE CRemoteDesktopClient :
  110. public CRemoteDesktopTopLevelObject,
  111. public CComObjectRootEx<CComSingleThreadModel>,
  112. public IDispatchImpl<ISAFRemoteDesktopClient, &IID_ISAFRemoteDesktopClient, &LIBID_RDCCLIENTHOSTLib>,
  113. public IDispatchImpl<ISAFRemoteDesktopTestExtension, &IID_ISAFRemoteDesktopTestExtension, &LIBID_RDCCLIENTHOSTLib>,
  114. public CComControl<CRemoteDesktopClient>,
  115. public IPersistStreamInitImpl<CRemoteDesktopClient>,
  116. public IOleControlImpl<CRemoteDesktopClient>,
  117. public IOleObjectImpl<CRemoteDesktopClient>,
  118. public IOleInPlaceActiveObjectImpl<CRemoteDesktopClient>,
  119. public IViewObjectExImpl<CRemoteDesktopClient>,
  120. public IOleInPlaceObjectWindowlessImpl<CRemoteDesktopClient>,
  121. public IConnectionPointContainerImpl<CRemoteDesktopClient>,
  122. public IPersistStorageImpl<CRemoteDesktopClient>,
  123. public ISpecifyPropertyPagesImpl<CRemoteDesktopClient>,
  124. public IQuickActivateImpl<CRemoteDesktopClient>,
  125. public IDataObjectImpl<CRemoteDesktopClient>,
  126. public IProvideClassInfo2Impl<&CLSID_SAFRemoteDesktopClient, &DIID__ISAFRemoteDesktopClientEvents, &LIBID_RDCCLIENTHOSTLib>,
  127. public IPropertyNotifySinkCP<CRemoteDesktopClient>,
  128. public CComCoClass<CRemoteDesktopClient, &CLSID_SAFRemoteDesktopClient>,
  129. public CProxy_ISAFRemoteDesktopClientEvents< CRemoteDesktopClient >
  130. {
  131. private:
  132. typedef std::vector<LONG, CRemoteDesktopAllocator<LONG> > ChannelsType;
  133. ChannelsType m_Channels;
  134. CComPtr<ISAFRemoteDesktopClient> m_Client;
  135. BSTR m_ExtDllName;
  136. BSTR m_ExtParams;
  137. HWND m_ClientWnd;
  138. CAxWindow m_ClientAxView;
  139. BOOL m_RemoteControlEnabled;
  140. BOOL m_EnableSmartSizing;
  141. LONG m_ColorDepth;
  142. CONNECTION_STATE m_ConnectingState;
  143. //
  144. // Event sink receives events fired by the client control..
  145. //
  146. CRemoteDesktopClientEventSink m_ClientEventSink;
  147. //
  148. // IDispatch Pointers for Scriptable Event Object Registrations
  149. //
  150. CComPtr<IDispatch> m_OnConnected;
  151. CComPtr<IDispatch> m_OnDisconnected;
  152. CComPtr<IDispatch> m_OnConnectRemoteDesktopComplete;
  153. CComPtr<IDispatch> m_OnListenConnect;
  154. CComPtr<IDispatch> m_OnBeginConnect;
  155. //
  156. // Data Channel Manager Interface
  157. //
  158. CComObject<CClientDataChannelMgr> *m_ChannelMgr;
  159. //
  160. // Connect Parameters
  161. //
  162. CComBSTR m_ConnectParms;
  163. HRESULT _PutExtParams( VOID );
  164. HRESULT
  165. InitializeRemoteDesktopClientObject();
  166. public:
  167. CRemoteDesktopClient()
  168. {
  169. DC_BEGIN_FN("CRemoteDesktopClient::CRemoteDesktopClient");
  170. m_RemoteControlEnabled = FALSE;
  171. //
  172. // We are window'd, even if our parent supports Windowless
  173. // controls.
  174. //
  175. m_bWindowOnly = TRUE;
  176. m_ClientWnd = NULL;
  177. m_EnableSmartSizing = FALSE;
  178. m_ExtDllName = m_ExtParams = NULL;
  179. m_ColorDepth = 8;
  180. DC_END_FN();
  181. }
  182. virtual ~CRemoteDesktopClient();
  183. HRESULT FinalConstruct();
  184. //
  185. // Event Sinks
  186. //
  187. void OnConnected();
  188. void OnDisconnected(long reason);
  189. void OnConnectRemoteDesktopComplete(long status);
  190. void OnListenConnect(long status);
  191. void OnBeginConnect();
  192. DECLARE_REGISTRY_RESOURCEID(IDR_REMOTEDESKTOPCLIENT)
  193. DECLARE_PROTECT_FINAL_CONSTRUCT()
  194. //
  195. // COM Interface Map
  196. //
  197. BEGIN_COM_MAP(CRemoteDesktopClient)
  198. COM_INTERFACE_ENTRY(ISAFRemoteDesktopClient)
  199. COM_INTERFACE_ENTRY(ISAFRemoteDesktopTestExtension)
  200. COM_INTERFACE_ENTRY2(IDispatch, ISAFRemoteDesktopClient)
  201. COM_INTERFACE_ENTRY(IViewObjectEx)
  202. COM_INTERFACE_ENTRY(IViewObject2)
  203. COM_INTERFACE_ENTRY(IViewObject)
  204. COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)
  205. COM_INTERFACE_ENTRY(IOleInPlaceObject)
  206. COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)
  207. COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)
  208. COM_INTERFACE_ENTRY(IOleControl)
  209. COM_INTERFACE_ENTRY(IOleObject)
  210. COM_INTERFACE_ENTRY(IPersistStreamInit)
  211. COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
  212. COM_INTERFACE_ENTRY(IConnectionPointContainer)
  213. COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
  214. COM_INTERFACE_ENTRY(IQuickActivate)
  215. COM_INTERFACE_ENTRY(IPersistStorage)
  216. COM_INTERFACE_ENTRY(IDataObject)
  217. COM_INTERFACE_ENTRY(IProvideClassInfo)
  218. COM_INTERFACE_ENTRY(IProvideClassInfo2)
  219. COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
  220. END_COM_MAP()
  221. //
  222. // Property Map
  223. //
  224. BEGIN_PROP_MAP(CRemoteDesktopClient)
  225. PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
  226. PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
  227. // Example entries
  228. // PROP_ENTRY("Property Description", dispid, clsid)
  229. // PROP_PAGE(CLSID_StockColorPage)
  230. END_PROP_MAP()
  231. //
  232. // Connection Point Map
  233. //
  234. BEGIN_CONNECTION_POINT_MAP(CRemoteDesktopClient)
  235. CONNECTION_POINT_ENTRY(IID_IPropertyNotifySink)
  236. CONNECTION_POINT_ENTRY(DIID__ISAFRemoteDesktopClientEvents)
  237. END_CONNECTION_POINT_MAP()
  238. //
  239. // Message Map
  240. //
  241. BEGIN_MSG_MAP(CRemoteDesktopClient)
  242. CHAIN_MSG_MAP(CComControl<CRemoteDesktopClient>)
  243. DEFAULT_REFLECTION_HANDLER()
  244. MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
  245. MESSAGE_HANDLER(WM_CREATE, OnCreate)
  246. MESSAGE_HANDLER(WM_SIZE, OnSize)
  247. END_MSG_MAP()
  248. //
  249. // Handler prototypes:
  250. //
  251. // LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
  252. // LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
  253. // LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);
  254. //
  255. // IViewObjectEx Methods
  256. //
  257. DECLARE_VIEW_STATUS(VIEWSTATUS_SOLIDBKGND | VIEWSTATUS_OPAQUE)
  258. public:
  259. STDMETHOD(CreateListenEndpoint)(
  260. /*[in]*/ LONG port,
  261. /*[out, retval]*/ BSTR* pConnectParm
  262. );
  263. STDMETHOD(StartListen)(
  264. /*[in]*/ LONG timeout
  265. );
  266. STDMETHOD(AcceptListenConnection)(
  267. /*[in]*/BSTR expertBlob
  268. );
  269. STDMETHOD(StopListen)();
  270. STDMETHOD(get_IsRemoteDesktopConnected)(/*[out, retval]*/ BOOL *pVal);
  271. STDMETHOD(get_IsServerConnected)(/*[out, retval]*/BOOL *pVal);
  272. STDMETHOD(DisconnectRemoteDesktop)();
  273. STDMETHOD(ConnectRemoteDesktop)();
  274. STDMETHOD(ConnectToServer)(BSTR bstrServer);
  275. STDMETHOD(DisconnectFromServer)();
  276. STDMETHOD(get_ExtendedErrorInfo)(/*[out, retval]*/LONG *error);
  277. STDMETHOD(get_ChannelManager)(ISAFRemoteDesktopChannelMgr **mgr) {
  278. m_ChannelMgr->AddRef();
  279. *mgr = m_ChannelMgr;
  280. return S_OK;
  281. }
  282. STDMETHOD(put_ConnectParms)(/*[in]*/BSTR parms) {
  283. m_ConnectParms = parms;
  284. return S_OK;
  285. }
  286. STDMETHOD(get_ConnectParms)(/*[out, retval]*/BSTR *parms) {
  287. CComBSTR tmp;
  288. tmp = m_ConnectParms;
  289. *parms = tmp.Detach();
  290. return S_OK;
  291. }
  292. STDMETHOD(put_OnBeginConnect)(/*[in]*/IDispatch *iDisp) {
  293. m_OnBeginConnect = iDisp;
  294. return S_OK;
  295. }
  296. STDMETHOD(put_OnConnected)(/*[in]*/IDispatch *iDisp) {
  297. m_OnConnected = iDisp;
  298. return S_OK;
  299. }
  300. STDMETHOD(put_OnDisconnected)(/*[in]*/IDispatch *iDisp) {
  301. m_OnDisconnected = iDisp;
  302. return S_OK;
  303. }
  304. STDMETHOD(put_OnConnectRemoteDesktopComplete)(/*[in]*/IDispatch *iDisp) {
  305. m_OnConnectRemoteDesktopComplete = iDisp;
  306. return S_OK;
  307. }
  308. STDMETHOD(put_OnListenConnect)(/*[in]*/IDispatch *iDisp) {
  309. m_OnListenConnect = iDisp;
  310. return S_OK;
  311. }
  312. STDMETHOD(put_EnableSmartSizing)(/*[in]*/BOOL val) {
  313. HRESULT hr;
  314. if (m_Client != NULL) {
  315. hr = m_Client->put_EnableSmartSizing(val);
  316. if (hr == S_OK) {
  317. m_EnableSmartSizing = val;
  318. }
  319. }
  320. else {
  321. m_EnableSmartSizing = val;
  322. hr = S_OK;
  323. }
  324. return hr;
  325. }
  326. STDMETHOD(get_EnableSmartSizing)(/*[in]*/BOOL *pVal) {
  327. if (pVal != NULL) {
  328. *pVal = m_EnableSmartSizing;
  329. return S_OK;
  330. }
  331. else {
  332. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  333. }
  334. }
  335. STDMETHOD(get_ConnectedServer)(/*[in]*/BSTR* Val) {
  336. HRESULT hr;
  337. if( NULL == Val ) {
  338. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  339. }
  340. else if( m_Client != NULL ) {
  341. hr = m_Client->get_ConnectedServer( Val );
  342. }
  343. else {
  344. hr = E_FAIL;
  345. }
  346. return hr;
  347. }
  348. STDMETHOD(get_ConnectedPort)(/*[in]*/LONG* Val) {
  349. HRESULT hr;
  350. if( NULL == Val ) {
  351. hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  352. }
  353. else if( m_Client != NULL ) {
  354. hr = m_Client->get_ConnectedPort( Val );
  355. }
  356. else {
  357. hr = E_FAIL;
  358. }
  359. return hr;
  360. }
  361. STDMETHOD(put_ColorDepth)(/*[in]*/LONG Val) {
  362. HRESULT hr;
  363. if (m_Client != NULL) {
  364. hr = m_Client->put_ColorDepth(Val);
  365. if (hr == S_OK) {
  366. m_ColorDepth = Val;
  367. }
  368. }
  369. else {
  370. m_ColorDepth = Val;
  371. hr = S_OK;
  372. }
  373. return hr;
  374. }
  375. STDMETHOD(get_ColorDepth)(/*[out,retval]*/LONG* pVal) {
  376. if (pVal != NULL) {
  377. *pVal = m_ColorDepth;
  378. return S_OK;
  379. }
  380. else {
  381. return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
  382. }
  383. }
  384. //
  385. // OnCreate
  386. //
  387. LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  388. {
  389. //
  390. // Hide our window, by default.
  391. //
  392. //ShowWindow(SW_HIDE);
  393. return 0;
  394. }
  395. //
  396. // OnSetFocus
  397. //
  398. LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  399. {
  400. //
  401. // Set focus back to the client window, if it exists.
  402. //
  403. if (m_ClientWnd != NULL) {
  404. ::PostMessage(m_ClientWnd, uMsg, wParam, lParam);
  405. }
  406. return 0;
  407. }
  408. //
  409. // OnSize
  410. //
  411. LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  412. {
  413. DC_BEGIN_FN("CRemoteDesktopClient::OnSize");
  414. if (m_ClientWnd != NULL) {
  415. RECT rect;
  416. GetClientRect(&rect);
  417. ::MoveWindow(m_ClientWnd, rect.left, rect.top,
  418. rect.right, rect.bottom, TRUE);
  419. }
  420. DC_END_FN();
  421. return 0;
  422. }
  423. //
  424. // OnDraw
  425. //
  426. HRESULT OnDraw(ATL_DRAWINFO& di)
  427. {
  428. //
  429. // Make sure our window is hidden, if remote control is not
  430. // active.
  431. //
  432. if (!m_RemoteControlEnabled) {
  433. //ShowWindow(SW_HIDE);
  434. }
  435. return S_OK;
  436. }
  437. //
  438. // Return the name of this class.
  439. //
  440. virtual const LPTSTR ClassName() {
  441. return TEXT("CRemoteDesktopClient");
  442. }
  443. //
  444. // ISAFRemoteDesktopTestExtension
  445. //
  446. STDMETHOD(put_TestExtDllName)(/*[in]*/BSTR newVal)
  447. {
  448. if ( NULL != m_ExtDllName )
  449. SysFreeString( m_ExtDllName );
  450. m_ExtDllName = SysAllocString( newVal );
  451. return ( NULL != m_ExtDllName )?S_OK:E_OUTOFMEMORY;
  452. }
  453. STDMETHOD(put_TestExtParams)(/*[in]*/BSTR newVal)
  454. {
  455. if ( NULL != m_ExtParams )
  456. SysFreeString( m_ExtDllName );
  457. m_ExtParams = SysAllocString( newVal );
  458. return ( NULL != m_ExtDllName )?S_OK:E_OUTOFMEMORY;
  459. }
  460. };
  461. ///////////////////////////////////////////////////////
  462. //
  463. // CRemoteDesktopClient Inline Methods
  464. //
  465. inline void CRemoteDesktopClient::OnConnected()
  466. {
  467. Fire_Connected(m_OnConnected);
  468. }
  469. inline void CRemoteDesktopClient::OnDisconnected(long reason)
  470. {
  471. //
  472. // Hide our window.
  473. //
  474. m_RemoteControlEnabled = FALSE;
  475. //ShowWindow(SW_HIDE);
  476. Fire_Disconnected(reason, m_OnDisconnected);
  477. }
  478. inline void CRemoteDesktopClient::OnConnectRemoteDesktopComplete(long status)
  479. {
  480. //
  481. // Show our window, if the request succeeded.
  482. //
  483. if (status == ERROR_SUCCESS) {
  484. m_RemoteControlEnabled = TRUE;
  485. ShowWindow(SW_SHOW);
  486. }
  487. Fire_RemoteControlRequestComplete(status, m_OnConnectRemoteDesktopComplete);
  488. }
  489. inline void CRemoteDesktopClient::OnListenConnect(long status)
  490. {
  491. Fire_ListenConnect(status, m_OnListenConnect);
  492. }
  493. inline void CRemoteDesktopClient::OnBeginConnect()
  494. {
  495. ShowWindow(SW_SHOW);
  496. Fire_BeginConnect(m_OnBeginConnect);
  497. }
  498. #endif //__REMOTEDESKTOPCLIENT_H_