Leaked source code of windows server 2003
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.

757 lines
16 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. // client might still be connected to our interface, fire
  68. // disconnect event.
  69. ClientDisconnected();
  70. m_OnDisconnected->Release();
  71. }
  72. }
  73. catch (...) {
  74. TRC_ALT((TB, L"Exception caught in outgoing interface release."));
  75. }
  76. DC_END_FN();
  77. }
  78. HRESULT
  79. CRemoteDesktopSession::Initialize(
  80. BSTR connectParms,
  81. CRemoteDesktopServerHost *hostObject,
  82. REMOTE_DESKTOP_SHARING_CLASS sharingClass,
  83. BOOL bEnableCallback,
  84. DWORD timeOut,
  85. BSTR userHelpCreateBlob,
  86. LONG tsSessionID,
  87. BSTR userSid
  88. )
  89. /*++
  90. Routine Description:
  91. The Initialize method prepares the COM object for connection by
  92. the client-side Remote Desktop Host ActiveX Control.
  93. Arguments:
  94. connectParms - If parms are non-NULL, then the session already exists.
  95. Otherwise, a new session should be created.
  96. hostObject - Back pointer to containing RDS Host object.
  97. sharingClass - Level of desktop sharing for a new session.
  98. bEnableCallback - TRUE to instruct sessmgr to call session resolver, FALSE otherwise.
  99. timeOut - Help session timeout value. 0, if not specified.
  100. userHelpCreateBlob - user specified help session creation blob.
  101. tsSessionID - Terminal Services Session ID or -1 if
  102. undefined.
  103. userSid - User SID or "" if undefined.
  104. Return Value:
  105. S_OK on success. Otherwise, an error code is returned.
  106. --*/
  107. {
  108. DC_BEGIN_FN("CRemoteDesktopSession::Initialize");
  109. HRESULT hr;
  110. DWORD ret;
  111. DWORD protocolType;
  112. CComBSTR parmsMachineName;
  113. CComBSTR parmsAssistantAccount;
  114. CComBSTR parmsAssistantAccountPwd;
  115. CComBSTR parmsHelpSessionName;
  116. CComBSTR parmsHelpSessionPwd;
  117. CComBSTR parmsProtocolSpecificParms;
  118. CComBSTR helpSessionName;
  119. CComBSTR sessionDescr;
  120. DWORD dwVersion;
  121. ASSERT(IsValid());
  122. if (!IsValid()) {
  123. return E_FAIL;
  124. }
  125. TRC_NRM((TB, L"***Ref count is: %ld", m_dwRef));
  126. //
  127. // Keep a back pointer to the RDS host object.
  128. //
  129. m_RDSHost = hostObject;
  130. //
  131. // Open an instance of the Remote Desktop Help Session Manager service.
  132. //
  133. ASSERT(m_HelpSessionManager == NULL);
  134. hr = m_HelpSessionManager.CoCreateInstance(CLSID_RemoteDesktopHelpSessionMgr, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_DISABLE_AAA);
  135. if (!SUCCEEDED(hr)) {
  136. TRC_ERR((TB, TEXT("Can't create help session manager: %08X"), hr));
  137. goto CLEANUPANDEXIT;
  138. }
  139. //
  140. // Set the security level to impersonate. This is required by
  141. // the session manager.
  142. //
  143. hr = CoSetProxyBlanket(
  144. (IUnknown *)m_HelpSessionManager,
  145. RPC_C_AUTHN_DEFAULT,
  146. RPC_C_AUTHZ_DEFAULT,
  147. NULL,
  148. RPC_C_AUTHN_LEVEL_DEFAULT,
  149. RPC_C_IMP_LEVEL_IDENTIFY,
  150. NULL,
  151. EOAC_NONE
  152. );
  153. if (!SUCCEEDED(hr)) {
  154. TRC_ERR((TB, TEXT("CoSetProxyBlanket: %08X"), hr));
  155. goto CLEANUPANDEXIT;
  156. }
  157. //
  158. // Create a new help session if we don't already have connection
  159. // parms.
  160. //
  161. if (connectParms == NULL) {
  162. TRC_NRM((TB, L"Creating new help session."));
  163. GetSessionName(helpSessionName);
  164. GetSessionDescription(sessionDescr);
  165. hr = m_HelpSessionManager->CreateHelpSessionEx(
  166. sharingClass,
  167. bEnableCallback,
  168. timeOut,
  169. tsSessionID,
  170. userSid,
  171. userHelpCreateBlob,
  172. &m_HelpSession
  173. );
  174. if (!SUCCEEDED(hr)) {
  175. TRC_ERR((TB, L"CreateHelpSession: %08X", hr));
  176. goto CLEANUPANDEXIT;
  177. }
  178. hr = m_HelpSession->get_HelpSessionId(&m_HelpSessionID);
  179. if (!SUCCEEDED(hr)) {
  180. TRC_ERR((TB, L"get_HelpSessionId: %08X", hr));
  181. goto CLEANUPANDEXIT;
  182. }
  183. }
  184. else {
  185. //
  186. // Parse the connection parms to get the help
  187. // session ID.
  188. //
  189. ret = ParseConnectParmsString(
  190. connectParms,
  191. &dwVersion,
  192. &protocolType,
  193. parmsMachineName,
  194. parmsAssistantAccount,
  195. parmsAssistantAccountPwd,
  196. m_HelpSessionID,
  197. parmsHelpSessionName,
  198. parmsHelpSessionPwd,
  199. parmsProtocolSpecificParms
  200. );
  201. if (ret != ERROR_SUCCESS) {
  202. hr = HRESULT_FROM_WIN32(ret);
  203. goto CLEANUPANDEXIT;
  204. }
  205. //
  206. // Open the help session interface.
  207. //
  208. hr = m_HelpSessionManager->RetrieveHelpSession(
  209. m_HelpSessionID,
  210. &m_HelpSession
  211. );
  212. if (!SUCCEEDED(hr)) {
  213. TRC_ERR((TB, L"Failed to open existing help session %s: %08X.",
  214. m_HelpSessionID, hr));
  215. goto CLEANUPANDEXIT;
  216. }
  217. if( CheckAccessRight( userSid ) == FALSE ) {
  218. TRC_ERR((TB, L"CheckAccessRight on %s return FALSE",
  219. m_HelpSessionID));
  220. hr = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  221. goto CLEANUPANDEXIT;
  222. }
  223. }
  224. //
  225. // Get the ticket expiration time
  226. //
  227. hr = m_HelpSession->get_TimeOut(&m_ExpirationTime);
  228. if( FAILED(hr) ) {
  229. TRC_ERR((TB, L"get_ExpireTime: %08X", hr));
  230. }
  231. CLEANUPANDEXIT:
  232. DC_END_FN();
  233. return hr;
  234. }
  235. void
  236. CRemoteDesktopSession::Shutdown()
  237. /*++
  238. Routine Description:
  239. The Shutdown method causes the COM object to no longer be
  240. prepared for connection by the client-side Remote Desktop Host
  241. ActiveX Control.
  242. Arguments:
  243. Return Value:
  244. S_OK on success. Otherwise, an error code is returned.
  245. --*/
  246. {
  247. DC_BEGIN_FN("CRemoteDesktopSession::Shutdown");
  248. if (m_HelpSessionManager != NULL) {
  249. //
  250. // Shutdown might be result of RA policy change so we can't
  251. // delete the ticket.
  252. //
  253. m_HelpSession = NULL;
  254. m_HelpSessionManager = NULL;
  255. }
  256. CLEANUPANDEXIT:
  257. DC_END_FN();
  258. }
  259. STDMETHODIMP
  260. CRemoteDesktopSession::get_HelpSessionId(
  261. /*[out, retval]*/ BSTR* HelpSessionId
  262. )
  263. /*
  264. Routine Description:
  265. Return Help Session ID.
  266. Arguments:
  267. HelpSessionId :
  268. Returns:
  269. S_OK or error code.
  270. --*/
  271. {
  272. HRESULT hRes;
  273. if( NULL == HelpSessionId ) {
  274. hRes = E_INVALIDARG;
  275. goto CLEANUPANDEXIT;
  276. }
  277. // Ticket object might got expired but client still
  278. // holding reference counter.
  279. if( !m_HelpSessionID ) {
  280. hRes = E_HANDLE;
  281. goto CLEANUPANDEXIT;
  282. }
  283. *HelpSessionId = m_HelpSessionID.Copy();
  284. if( NULL == *HelpSessionId ) {
  285. hRes = E_OUTOFMEMORY;
  286. }
  287. else {
  288. hRes = S_OK;
  289. }
  290. CLEANUPANDEXIT:
  291. return hRes;
  292. }
  293. STDMETHODIMP
  294. CRemoteDesktopSession::put_SharingClass(
  295. REMOTE_DESKTOP_SHARING_CLASS sharingClass
  296. )
  297. /*++
  298. Routine Description:
  299. Set the desktop sharing level.
  300. Arguments:
  301. Return Value:
  302. --*/
  303. {
  304. DC_BEGIN_FN("CRemoteDesktopSession::put_SharingClass");
  305. HRESULT hr;
  306. if( !m_HelpSession ) {
  307. hr = E_HANDLE;
  308. }
  309. else {
  310. hr = m_HelpSession->put_UserHelpSessionRemoteDesktopSharingSetting(
  311. sharingClass
  312. );
  313. }
  314. DC_END_FN();
  315. return hr;
  316. }
  317. STDMETHODIMP
  318. CRemoteDesktopSession::get_SharingClass(
  319. REMOTE_DESKTOP_SHARING_CLASS *sharingClass
  320. )
  321. /*++
  322. Routine Description:
  323. Get the desktop sharing level.
  324. Arguments:
  325. Return Value:
  326. --*/
  327. {
  328. DC_BEGIN_FN("CRemoteDesktopSession::get_SharingClass");
  329. HRESULT hr;
  330. if( !m_HelpSession ) {
  331. hr = E_HANDLE;
  332. ASSERT(FALSE);
  333. }
  334. else {
  335. hr = m_HelpSession->get_UserHelpSessionRemoteDesktopSharingSetting(
  336. sharingClass
  337. );
  338. }
  339. DC_END_FN();
  340. return hr;
  341. }
  342. STDMETHODIMP
  343. CRemoteDesktopSession::put_UserBlob(
  344. BSTR UserBlob
  345. )
  346. /*++
  347. Routine Description:
  348. Set the desktop sharing level.
  349. Arguments:
  350. Return Value:
  351. --*/
  352. {
  353. DC_BEGIN_FN("CRemoteDesktopSession::put_UserBlob");
  354. HRESULT hr;
  355. if( !m_HelpSession ) {
  356. hr = E_HANDLE;
  357. ASSERT(FALSE);
  358. }
  359. else {
  360. hr = m_HelpSession->put_HelpSessionCreateBlob(UserBlob);
  361. }
  362. DC_END_FN();
  363. return hr;
  364. }
  365. STDMETHODIMP
  366. CRemoteDesktopSession::get_UserBlob(
  367. BSTR* UserBlob
  368. )
  369. /*++
  370. Routine Description:
  371. Set the desktop sharing level.
  372. Arguments:
  373. Return Value:
  374. --*/
  375. {
  376. DC_BEGIN_FN("CRemoteDesktopSession::get_UserBlob");
  377. HRESULT hr;
  378. if( !m_HelpSession ) {
  379. hr = E_HANDLE;
  380. ASSERT(FALSE);
  381. }
  382. else {
  383. hr = m_HelpSession->get_HelpSessionCreateBlob(UserBlob);
  384. }
  385. DC_END_FN();
  386. return hr;
  387. }
  388. STDMETHODIMP
  389. CRemoteDesktopSession::get_ExpireTime(
  390. DWORD* pExpireTime
  391. )
  392. /*++
  393. Routine Description:
  394. Get ticket expiration time, time return is standard C
  395. library time - number of seconds elapsed since midnight
  396. (00:00:00), January 1, 1970, coordinated universal time,
  397. according to the system clock.
  398. Arguments:
  399. Return Value:
  400. --*/
  401. {
  402. DC_BEGIN_FN("CRemoteDesktopSession::get_ExpireTime");
  403. HRESULT hr = S_OK;
  404. //
  405. // m_HelpSession must have initialized so check on
  406. // m_HelpSession
  407. //
  408. if( !m_HelpSession ) {
  409. hr = E_HANDLE;
  410. ASSERT(FALSE);
  411. }
  412. else {
  413. *pExpireTime = m_ExpirationTime;
  414. }
  415. DC_END_FN();
  416. return hr;
  417. }
  418. STDMETHODIMP
  419. CRemoteDesktopSession::put_OnConnected(
  420. IDispatch *iDisp
  421. )
  422. /*++
  423. Routine Description:
  424. Assign the outgoing interface for 'connected' events.
  425. Only one interface can be assigned at a time.
  426. Arguments:
  427. Return Value:
  428. --*/
  429. {
  430. DC_BEGIN_FN("CRemoteDesktopSession::put_OnConnected");
  431. HRESULT hr = S_OK;
  432. if (m_OnConnected != NULL) {
  433. //
  434. // The client proc may have gone away, so we need
  435. // to catch exceptions on the release.
  436. //
  437. try {
  438. m_OnConnected->Release();
  439. }
  440. catch (...) {
  441. }
  442. }
  443. m_OnConnected = iDisp;
  444. if (m_OnConnected != NULL) {
  445. try {
  446. m_OnConnected->AddRef();
  447. }
  448. catch (...) {
  449. m_OnConnected = NULL;
  450. TRC_ERR((TB, L"Exception caught in AddRef"));
  451. hr = E_FAIL;
  452. }
  453. }
  454. DC_END_FN();
  455. return hr;
  456. }
  457. STDMETHODIMP
  458. CRemoteDesktopSession::put_OnDisconnected(
  459. IDispatch *iDisp
  460. )
  461. /*++
  462. Routine Description:
  463. Assign the outgoing interface for 'disconnected' events.
  464. Only one interface can be assigned at a time.
  465. Arguments:
  466. Return Value:
  467. --*/
  468. {
  469. DC_BEGIN_FN("CRemoteDesktopSession::put_OnDisconnected(");
  470. HRESULT hr = S_OK;
  471. if (m_OnDisconnected != NULL) {
  472. //
  473. // The client proc may have gone away, so we need
  474. // to catch exceptions on the release.
  475. //
  476. try {
  477. m_OnDisconnected->Release();
  478. }
  479. catch (...) {
  480. }
  481. }
  482. m_OnDisconnected = iDisp;
  483. if (m_OnDisconnected != NULL) {
  484. try {
  485. m_OnDisconnected->AddRef();
  486. }
  487. catch (...) {
  488. m_OnDisconnected = NULL;
  489. TRC_ERR((TB, L"Exception caught in AddRef"));
  490. hr = E_FAIL;
  491. }
  492. }
  493. DC_END_FN();
  494. return hr;
  495. }
  496. STDMETHODIMP
  497. CRemoteDesktopSession::CloseRemoteDesktopSession()
  498. /*++
  499. Routine Description:
  500. Remove RDS session from the containing host object. Note that
  501. this function does not dereference the ISAFRemoteDesktopSession
  502. interface.
  503. Arguments:
  504. Return Value:
  505. --*/
  506. {
  507. DC_BEGIN_FN("CRemoteDesktopSession::CloseRemoteDesktopSession");
  508. HRESULT hr = m_RDSHost->CloseRemoteDesktopSession(this);
  509. DC_END_FN();
  510. return hr;
  511. }
  512. VOID
  513. CRemoteDesktopSession::ClientConnected()
  514. /*++
  515. Routine Description:
  516. Called when a connection to the client has been established.
  517. Arguments:
  518. Return Value:
  519. --*/
  520. {
  521. DC_BEGIN_FN("CRemoteDesktopSession::Connected");
  522. ASSERT(IsValid());
  523. //
  524. // We will catch and ignore exceptions here. The interface may
  525. // have been implemented in a client application that has 'gone
  526. // away.'
  527. //
  528. try {
  529. Fire_ClientConnected(m_OnConnected);
  530. }
  531. catch (...) {
  532. TRC_ALT((TB, L"Exception caught."));
  533. }
  534. DC_END_FN();
  535. }
  536. VOID
  537. CRemoteDesktopSession::ClientDisconnected()
  538. /*++
  539. Routine Description:
  540. Called when a connection to the client has been terminated.
  541. Arguments:
  542. Return Value:
  543. --*/
  544. {
  545. DC_BEGIN_FN("CRemoteDesktopSession::Disconnected");
  546. ASSERT(IsValid());
  547. //
  548. // We will catch and ignore exceptions here. The interface may
  549. // have been implemented in a client application that has 'gone
  550. // away.'
  551. //
  552. try {
  553. Fire_ClientDisconnected(m_OnDisconnected);
  554. }
  555. catch (...) {
  556. TRC_ALT((TB, L"Exception caught."));
  557. }
  558. DC_END_FN();
  559. }
  560. BOOL
  561. CRemoteDesktopSession::CheckAccessRight( BSTR userSID )
  562. {
  563. DC_BEGIN_FN("CRemoteDesktopSession::CheckAccessRight");
  564. HRESULT hr;
  565. VARIANT_BOOL userOwnerOfTicket = VARIANT_FALSE;
  566. if( !m_HelpSession ) {
  567. ASSERT(FALSE);
  568. goto CLEANUPANDEXIT;
  569. }
  570. // no need to check userSID, sessmgr check it.
  571. hr = m_HelpSession->IsUserOwnerOfTicket(userSID, &userOwnerOfTicket);
  572. if( FAILED(hr) ) {
  573. // Just to make sure we return FALSE in this case.
  574. userOwnerOfTicket = VARIANT_FALSE;
  575. }
  576. CLEANUPANDEXIT:
  577. DC_END_FN();
  578. // return if ticket is owned by userSID, FALSE in error condition
  579. return (userOwnerOfTicket == VARIANT_TRUE)? TRUE : FALSE;
  580. }