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.

571 lines
12 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. RDPRemoteDesktopSession
  5. Abstract:
  6. The CRemoteDesktopSession class is the parent
  7. class for the Remote Desktop class hierarchy on the server-side.
  8. It helps the CRemoteDesktopServerHost class to implement
  9. the ISAFRemoteDesktopSession 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 server-side.
  13. Author:
  14. Tad Brockway 02/00
  15. Revision History:
  16. --*/
  17. #include <RemoteDesktop.h>
  18. #include "stdafx.h"
  19. #ifdef TRC_FILE
  20. #undef TRC_FILE
  21. #endif
  22. #define TRC_FILE "_srdses"
  23. #include "RDSHost.h"
  24. #include "RemoteDesktopSession.h"
  25. #include "RemoteDesktopServerHost.h"
  26. #include <sessmgr_i.c>
  27. #include <objidl.h>
  28. #include <objbase.h>
  29. ///////////////////////////////////////////////////////
  30. //
  31. // CRemoteDesktopSession Methods
  32. //
  33. HRESULT
  34. CRemoteDesktopSession::FinalConstruct()
  35. /*++
  36. Routine Description:
  37. Final Constructor
  38. Arguments:
  39. Return Value:
  40. S_OK on success. Otherwise, an error code is returned.
  41. --*/
  42. {
  43. DC_BEGIN_FN("CRemoteDesktopSession::FinalConstruct");
  44. DC_END_FN();
  45. return S_OK;
  46. }
  47. CRemoteDesktopSession::~CRemoteDesktopSession()
  48. /*++
  49. Routine Description:
  50. Destructor
  51. Arguments:
  52. Return Value:
  53. --*/
  54. {
  55. DC_BEGIN_FN("CRemoteDesktopSession::~CRemoteDesktopSession");
  56. Shutdown();
  57. //
  58. // Release any lingering outgoing interfaces. Need to catch
  59. // exceptions here in case the outgoing interface application
  60. // has already gone away.
  61. //
  62. try {
  63. if (m_OnConnected != NULL) {
  64. m_OnConnected->Release();
  65. }
  66. if (m_OnDisconnected != NULL) {
  67. m_OnDisconnected->Release();
  68. }
  69. }
  70. catch (...) {
  71. TRC_ALT((TB, L"Exception caught in outgoing interface release."));
  72. }
  73. DC_END_FN();
  74. }
  75. HRESULT
  76. CRemoteDesktopSession::Initialize(
  77. BSTR connectParms,
  78. CRemoteDesktopServerHost *hostObject,
  79. REMOTE_DESKTOP_SHARING_CLASS sharingClass,
  80. BOOL bEnableCallback,
  81. DWORD timeOut,
  82. BSTR userHelpCreateBlob,
  83. LONG tsSessionID,
  84. BSTR userSid
  85. )
  86. /*++
  87. Routine Description:
  88. The Initialize method prepares the COM object for connection by
  89. the client-side Remote Desktop Host ActiveX Control.
  90. Arguments:
  91. connectParms - If parms are non-NULL, then the session already exists.
  92. Otherwise, a new session should be created.
  93. hostObject - Back pointer to containing RDS Host object.
  94. sharingClass - Level of desktop sharing for a new session.
  95. bEnableCallback - TRUE to instruct sessmgr to call session resolver, FALSE otherwise.
  96. timeOut - Help session timeout value. 0, if not specified.
  97. userHelpCreateBlob - user specified help session creation blob.
  98. tsSessionID - Terminal Services Session ID or -1 if
  99. undefined.
  100. userSid - User SID or "" if undefined.
  101. Return Value:
  102. S_OK on success. Otherwise, an error code is returned.
  103. --*/
  104. {
  105. DC_BEGIN_FN("CRemoteDesktopSession::Initialize");
  106. HRESULT hr;
  107. DWORD ret;
  108. DWORD protocolType;
  109. CComBSTR parmsMachineName;
  110. CComBSTR parmsAssistantAccount;
  111. CComBSTR parmsAssistantAccountPwd;
  112. CComBSTR parmsHelpSessionName;
  113. CComBSTR parmsHelpSessionPwd;
  114. CComBSTR parmsProtocolSpecificParms;
  115. CComBSTR helpSessionName;
  116. CComBSTR sessionDescr;
  117. DWORD dwVersion;
  118. ASSERT(IsValid());
  119. if (!IsValid()) {
  120. return E_FAIL;
  121. }
  122. TRC_NRM((TB, L"***Ref count is: %ld", m_dwRef));
  123. //
  124. // Keep a back pointer to the RDS host object.
  125. //
  126. m_RDSHost = hostObject;
  127. //
  128. // Open an instance of the Remote Desktop Help Session Manager service.
  129. //
  130. ASSERT(m_HelpSessionManager == NULL);
  131. hr = m_HelpSessionManager.CoCreateInstance(CLSID_RemoteDesktopHelpSessionMgr);
  132. if (!SUCCEEDED(hr)) {
  133. TRC_ERR((TB, TEXT("Can't create help session manager: %08X"), hr));
  134. goto CLEANUPANDEXIT;
  135. }
  136. //
  137. // Set the security level to impersonate. This is required by
  138. // the session manager.
  139. //
  140. hr = CoSetProxyBlanket(
  141. (IUnknown *)m_HelpSessionManager,
  142. RPC_C_AUTHN_DEFAULT,
  143. RPC_C_AUTHZ_DEFAULT,
  144. NULL,
  145. RPC_C_AUTHN_LEVEL_DEFAULT,
  146. RPC_C_IMP_LEVEL_IMPERSONATE,
  147. NULL,
  148. EOAC_NONE
  149. );
  150. if (!SUCCEEDED(hr)) {
  151. TRC_ERR((TB, TEXT("CoSetProxyBlanket: %08X"), hr));
  152. goto CLEANUPANDEXIT;
  153. }
  154. //
  155. // Create a new help session if we don't already have connection
  156. // parms.
  157. //
  158. if (connectParms == NULL) {
  159. TRC_NRM((TB, L"Creating new help session."));
  160. GetSessionName(helpSessionName);
  161. GetSessionDescription(sessionDescr);
  162. hr = m_HelpSessionManager->CreateHelpSessionEx(
  163. sharingClass,
  164. bEnableCallback,
  165. timeOut,
  166. tsSessionID,
  167. userSid,
  168. userHelpCreateBlob,
  169. &m_HelpSession
  170. );
  171. if (!SUCCEEDED(hr)) {
  172. TRC_ERR((TB, L"CreateHelpSession: %08X", hr));
  173. goto CLEANUPANDEXIT;
  174. }
  175. hr = m_HelpSession->get_HelpSessionId(&m_HelpSessionID);
  176. if (!SUCCEEDED(hr)) {
  177. TRC_ERR((TB, L"get_HelpSessionId: %08X", hr));
  178. goto CLEANUPANDEXIT;
  179. }
  180. }
  181. else {
  182. //
  183. // Parse the connection parms to get the help
  184. // session ID.
  185. //
  186. ret = ParseConnectParmsString(
  187. connectParms,
  188. &dwVersion,
  189. &protocolType,
  190. parmsMachineName,
  191. parmsAssistantAccount,
  192. parmsAssistantAccountPwd,
  193. m_HelpSessionID,
  194. parmsHelpSessionName,
  195. parmsHelpSessionPwd,
  196. parmsProtocolSpecificParms
  197. );
  198. if (ret != ERROR_SUCCESS) {
  199. hr = HRESULT_FROM_WIN32(ret);
  200. goto CLEANUPANDEXIT;
  201. }
  202. //
  203. // Open the help session interface.
  204. //
  205. hr = m_HelpSessionManager->RetrieveHelpSession(
  206. m_HelpSessionID,
  207. &m_HelpSession
  208. );
  209. if (!SUCCEEDED(hr)) {
  210. TRC_ERR((TB, L"Failed to open existing help session %s: %08X.",
  211. m_HelpSessionID, hr));
  212. goto CLEANUPANDEXIT;
  213. }
  214. else {
  215. TRC_NRM((TB, L"Opened existing help session %s.", m_HelpSessionID));
  216. }
  217. }
  218. CLEANUPANDEXIT:
  219. DC_END_FN();
  220. return hr;
  221. }
  222. void
  223. CRemoteDesktopSession::Shutdown()
  224. /*++
  225. Routine Description:
  226. The Shutdown method causes the COM object to no longer be
  227. prepared for connection by the client-side Remote Desktop Host
  228. ActiveX Control.
  229. Arguments:
  230. Return Value:
  231. S_OK on success. Otherwise, an error code is returned.
  232. --*/
  233. {
  234. DC_BEGIN_FN("CRemoteDesktopSession::Shutdown");
  235. //
  236. // Delete the help session created via the call to StartListening
  237. // and delete the instance of the Remote Desktop Help Session Manager
  238. // service.
  239. //
  240. if (m_HelpSessionManager != NULL) {
  241. m_HelpSessionManager->DeleteHelpSession(m_HelpSessionID);
  242. m_HelpSessionManager = NULL;
  243. }
  244. CLEANUPANDEXIT:
  245. DC_END_FN();
  246. }
  247. STDMETHODIMP
  248. CRemoteDesktopSession::put_SharingClass(
  249. REMOTE_DESKTOP_SHARING_CLASS sharingClass
  250. )
  251. /*++
  252. Routine Description:
  253. Set the desktop sharing level.
  254. Arguments:
  255. Return Value:
  256. --*/
  257. {
  258. DC_BEGIN_FN("CRemoteDesktopSession::put_SharingClass");
  259. HRESULT hr = m_HelpSession->put_UserHelpSessionRemoteDesktopSharingSetting(
  260. sharingClass
  261. );
  262. DC_END_FN();
  263. return hr;
  264. }
  265. STDMETHODIMP
  266. CRemoteDesktopSession::get_SharingClass(
  267. REMOTE_DESKTOP_SHARING_CLASS *sharingClass
  268. )
  269. /*++
  270. Routine Description:
  271. Get the desktop sharing level.
  272. Arguments:
  273. Return Value:
  274. --*/
  275. {
  276. DC_BEGIN_FN("CRemoteDesktopSession::get_SharingClass");
  277. HRESULT hr = m_HelpSession->get_UserHelpSessionRemoteDesktopSharingSetting(
  278. sharingClass
  279. );
  280. DC_END_FN();
  281. return hr;
  282. }
  283. STDMETHODIMP
  284. CRemoteDesktopSession::put_OnConnected(
  285. IDispatch *iDisp
  286. )
  287. /*++
  288. Routine Description:
  289. Assign the outgoing interface for 'connected' events.
  290. Only one interface can be assigned at a time.
  291. Arguments:
  292. Return Value:
  293. --*/
  294. {
  295. DC_BEGIN_FN("CRemoteDesktopSession::put_OnConnected");
  296. HRESULT hr = S_OK;
  297. if (m_OnConnected != NULL) {
  298. //
  299. // The client proc may have gone away, so we need
  300. // to catch exceptions on the release.
  301. //
  302. try {
  303. m_OnConnected->Release();
  304. }
  305. catch (...) {
  306. }
  307. }
  308. m_OnConnected = iDisp;
  309. if (m_OnConnected != NULL) {
  310. try {
  311. m_OnConnected->AddRef();
  312. }
  313. catch (...) {
  314. m_OnConnected = NULL;
  315. TRC_ERR((TB, L"Exception caught in AddRef"));
  316. hr = E_FAIL;
  317. }
  318. }
  319. DC_END_FN();
  320. return hr;
  321. }
  322. STDMETHODIMP
  323. CRemoteDesktopSession::put_OnDisconnected(
  324. IDispatch *iDisp
  325. )
  326. /*++
  327. Routine Description:
  328. Assign the outgoing interface for 'disconnected' events.
  329. Only one interface can be assigned at a time.
  330. Arguments:
  331. Return Value:
  332. --*/
  333. {
  334. DC_BEGIN_FN("CRemoteDesktopSession::put_OnDisconnected(");
  335. HRESULT hr = S_OK;
  336. if (m_OnDisconnected != NULL) {
  337. //
  338. // The client proc may have gone away, so we need
  339. // to catch exceptions on the release.
  340. //
  341. try {
  342. m_OnDisconnected->Release();
  343. }
  344. catch (...) {
  345. }
  346. }
  347. m_OnDisconnected = iDisp;
  348. if (m_OnDisconnected != NULL) {
  349. try {
  350. m_OnDisconnected->AddRef();
  351. }
  352. catch (...) {
  353. m_OnDisconnected = NULL;
  354. TRC_ERR((TB, L"Exception caught in AddRef"));
  355. hr = E_FAIL;
  356. }
  357. }
  358. DC_END_FN();
  359. return hr;
  360. }
  361. STDMETHODIMP
  362. CRemoteDesktopSession::CloseRemoteDesktopSession()
  363. /*++
  364. Routine Description:
  365. Remove RDS session from the containing host object. Note that
  366. this function does not dereference the ISAFRemoteDesktopSession
  367. interface.
  368. Arguments:
  369. Return Value:
  370. --*/
  371. {
  372. DC_BEGIN_FN("CRemoteDesktopSession::CloseRemoteDesktopSession");
  373. HRESULT hr = m_RDSHost->CloseRemoteDesktopSession(this);
  374. DC_END_FN();
  375. return hr;
  376. }
  377. VOID
  378. CRemoteDesktopSession::ClientConnected()
  379. /*++
  380. Routine Description:
  381. Called when a connection to the client has been established.
  382. Arguments:
  383. Return Value:
  384. --*/
  385. {
  386. DC_BEGIN_FN("CRemoteDesktopSession::Connected");
  387. ASSERT(IsValid());
  388. //
  389. // We will catch and ignore exceptions here. The interface may
  390. // have been implemented in a client application that has 'gone
  391. // away.'
  392. //
  393. try {
  394. Fire_ClientConnected(m_OnConnected);
  395. }
  396. catch (...) {
  397. TRC_ALT((TB, L"Exception caught."));
  398. }
  399. DC_END_FN();
  400. }
  401. VOID
  402. CRemoteDesktopSession::ClientDisconnected()
  403. /*++
  404. Routine Description:
  405. Called when a connection to the client has been terminated.
  406. cd
  407. Arguments:
  408. Return Value:
  409. --*/
  410. {
  411. DC_BEGIN_FN("CRemoteDesktopSession::Disconnected");
  412. ASSERT(IsValid());
  413. //
  414. // We will catch and ignore exceptions here. The interface may
  415. // have been implemented in a client application that has 'gone
  416. // away.'
  417. //
  418. try {
  419. Fire_ClientDisconnected(m_OnDisconnected);
  420. }
  421. catch (...) {
  422. TRC_ALT((TB, L"Exception caught."));
  423. }
  424. DC_END_FN();
  425. }