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.

2827 lines
61 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. HelpSess.cpp
  5. Abstract:
  6. HelpSess.cpp : Implementation of CRemoteDesktopHelpSession
  7. Author:
  8. HueiWang 2/17/2000
  9. --*/
  10. #include "stdafx.h"
  11. #include <time.h>
  12. #include <Sddl.h>
  13. #include "global.h"
  14. #include "Sessmgr.h"
  15. #include "rdshost.h"
  16. #include "HelpTab.h"
  17. #include "policy.h"
  18. #include "HelpAcc.h"
  19. #include "HelpMgr.h"
  20. #include "HelpSess.h"
  21. #include <rdshost_i.c>
  22. #include "RemoteDesktopUtils.h"
  23. #include "RemoteDesktop.h"
  24. #include <safsessionresolver_i.c>
  25. /////////////////////////////////////////////////////////////////////////////
  26. HRESULT
  27. ConvertSidToAccountName(
  28. IN CComBSTR& SidString,
  29. IN BSTR* ppszDomain,
  30. IN BSTR* ppszUserAcc
  31. //IN LPTSTR* ppszDomain,
  32. //IN LPTSTR* ppszUserAcc
  33. )
  34. /*++
  35. Description:
  36. Convert a string SID to domain\account.
  37. Parameters:
  38. ownerSidString : SID in string form to be converted.
  39. ppszDomain : Pointer to string pointer to receive domain name
  40. UserAcc : Pointer to string pointer to receive user name
  41. Returns:
  42. S_OK or error code.
  43. Note:
  44. Routine uses LocalAlloc() to allocate memory for ppszDomain
  45. and ppszUserAcc.
  46. --*/
  47. {
  48. DWORD dwStatus = ERROR_SUCCESS;
  49. PSID pOwnerSid = NULL;
  50. //LPTSTR pszAccName = NULL;
  51. BSTR pszAccName = NULL;
  52. DWORD cbAccName = 0;
  53. //LPTSTR pszDomainName = NULL;
  54. BSTR pszDomainName = NULL;
  55. DWORD cbDomainName = 0;
  56. SID_NAME_USE SidType;
  57. BOOL bSuccess;
  58. //
  59. // Convert string form SID to PSID
  60. //
  61. if( FALSE == ConvertStringSidToSid( (LPCTSTR)SidString, &pOwnerSid ) )
  62. {
  63. // this might also fail if system is in shutdown state.
  64. dwStatus = GetLastError();
  65. goto CLEANUPANDEXIT;
  66. }
  67. if( NULL == ppszDomain || NULL == ppszUserAcc )
  68. {
  69. dwStatus = ERROR_INVALID_PARAMETER;
  70. MYASSERT( FALSE );
  71. goto CLEANUPANDEXIT;
  72. }
  73. //
  74. // Lookup user account for this SID
  75. //
  76. bSuccess = LookupAccountSid(
  77. NULL,
  78. pOwnerSid,
  79. pszAccName,
  80. &cbAccName,
  81. pszDomainName,
  82. &cbDomainName,
  83. &SidType
  84. );
  85. if( TRUE == bSuccess || ERROR_INSUFFICIENT_BUFFER == GetLastError() )
  86. {
  87. //pszAccName = (LPWSTR) LocalAlloc( LPTR, (cbAccName + 1) * sizeof(WCHAR) );
  88. //pszDomainName = (LPWSTR) LocalAlloc( LPTR, (cbDomainName + 1)* sizeof(WCHAR) );
  89. pszAccName = ::SysAllocStringLen( NULL, (cbAccName + 1) );
  90. pszDomainName = ::SysAllocStringLen( NULL, (cbDomainName + 1) );
  91. if( NULL != pszAccName && NULL != pszDomainName )
  92. {
  93. bSuccess = LookupAccountSid(
  94. NULL,
  95. pOwnerSid,
  96. pszAccName,
  97. &cbAccName,
  98. pszDomainName,
  99. &cbDomainName,
  100. &SidType
  101. );
  102. }
  103. else
  104. {
  105. SetLastError(ERROR_OUTOFMEMORY);
  106. bSuccess = FALSE;
  107. }
  108. }
  109. if( FALSE == bSuccess )
  110. {
  111. dwStatus = GetLastError();
  112. }
  113. else
  114. {
  115. *ppszDomain = pszDomainName;
  116. *ppszUserAcc = pszAccName;
  117. pszDomainName = NULL;
  118. pszAccName = NULL;
  119. }
  120. CLEANUPANDEXIT:
  121. if( NULL != pOwnerSid )
  122. {
  123. LocalFree( pOwnerSid );
  124. }
  125. if( NULL != pszAccName )
  126. {
  127. //LocalFree( pszAccName );
  128. ::SysFreeString( pszAccName );
  129. }
  130. if( NULL != pszDomainName )
  131. {
  132. // LocalFree( pszDomainName );
  133. ::SysFreeString( pszAccName );
  134. }
  135. return HRESULT_FROM_WIN32(dwStatus);
  136. }
  137. /////////////////////////////////////////////////////////////////////////////
  138. //
  139. // CRemoteDesktopHelpSession
  140. //
  141. //
  142. CRemoteDesktopHelpSession::CRemoteDesktopHelpSession() :
  143. m_ulLogonId(UNKNOWN_LOGONID),
  144. m_ulHelperSessionId(UNKNOWN_LOGONID),
  145. m_ulHelpSessionFlag(0)
  146. {
  147. }
  148. CRemoteDesktopHelpSession::~CRemoteDesktopHelpSession()
  149. {
  150. }
  151. void
  152. CRemoteDesktopHelpSession::FinalRelease()
  153. {
  154. // Releas help entry
  155. if( NULL != m_pHelpSession )
  156. {
  157. DebugPrintf(
  158. _TEXT("FinalRelease %s on %s\n"),
  159. (IsUnsolicitedHelp()) ? L"Unsolicted Help" : L"Solicited Help",
  160. m_bstrHelpSessionId
  161. );
  162. // Notify disconnect will check if session is in help and bail out if necessary.
  163. // there is a timing issue that our SCM notification might came after caller close
  164. // all reference counter to our session object, in this case, SCM notification will
  165. // trigger reload from database which does not have helper session ID and so will
  166. // not notify resolver causing helpee been helped message.
  167. // We also has AddRef() manually in ResolveXXX call and Release() in
  168. // NotifyDisconnect(), this will hold the object in memory until SCM
  169. // notification comes in.
  170. NotifyDisconnect();
  171. CRemoteDesktopHelpSessionMgr::DeleteHelpSessionFromCache( m_bstrHelpSessionId );
  172. m_pHelpSession->Close();
  173. m_pHelpSession = NULL;
  174. }
  175. ULONG count = _Module.Release();
  176. DebugPrintf(
  177. _TEXT("Module Release by CRemoteDesktopHelpSession() %p %d...\n"),
  178. this,
  179. count
  180. );
  181. }
  182. HRESULT
  183. CRemoteDesktopHelpSession::put_ICSPort(
  184. IN DWORD newVal
  185. )
  186. /*++
  187. Description:
  188. Associate ICS port number with this help session.
  189. Parameters:
  190. newVal : ICS port number.
  191. Returns:
  192. --*/
  193. {
  194. HRESULT hRes = S_OK;
  195. CCriticalSectionLocker l(m_HelpSessionLock);
  196. if( FALSE == IsSessionValid() )
  197. {
  198. MYASSERT(FALSE);
  199. hRes = E_UNEXPECTED;
  200. return hRes;
  201. }
  202. //
  203. // Need to immediately update the value...
  204. //
  205. m_pHelpSession->m_ICSPort.EnableImmediateUpdate(TRUE);
  206. m_pHelpSession->m_ICSPort = newVal;
  207. return hRes;
  208. }
  209. STDMETHODIMP
  210. CRemoteDesktopHelpSession::get_ConnectParms(
  211. OUT BSTR* bstrConnectParms
  212. )
  213. /*++
  214. Description:
  215. Retrieve connection parameter for help session.
  216. Parameters:
  217. bstrConnectParms : Pointer to BSTR to receive connect parms.
  218. Returns:
  219. --*/
  220. {
  221. HRESULT hRes = S_OK;
  222. LPTSTR pszAddress = NULL;
  223. int BufSize;
  224. DWORD dwBufferRequire;
  225. DWORD dwNumChars;
  226. DWORD dwRetry;
  227. CComBSTR bstrSessId;
  228. CCriticalSectionLocker l(m_HelpSessionLock);
  229. if( FALSE == IsSessionValid() )
  230. {
  231. hRes = E_HANDLE;
  232. goto CLEANUPANDEXIT;
  233. }
  234. //
  235. // Address might have change which might require bigger buffer, retry
  236. //
  237. //
  238. for(dwRetry=0; dwRetry < MAX_FETCHIPADDRESSRETRY; dwRetry++)
  239. {
  240. if( NULL != pszAddress )
  241. {
  242. LocalFree( pszAddress );
  243. }
  244. //
  245. // Fetch all address on local machine.
  246. //
  247. dwBufferRequire = FetchAllAddresses( NULL, 0 );
  248. if( 0 == dwBufferRequire )
  249. {
  250. hRes = E_UNEXPECTED;
  251. MYASSERT(FALSE);
  252. goto CLEANUPANDEXIT;
  253. }
  254. pszAddress = (LPTSTR) LocalAlloc( LPTR, sizeof(TCHAR)*(dwBufferRequire+1) );
  255. if( NULL == pszAddress )
  256. {
  257. hRes = E_OUTOFMEMORY;
  258. goto CLEANUPANDEXIT;
  259. }
  260. dwNumChars = FetchAllAddresses( pszAddress, dwBufferRequire );
  261. MYASSERT( dwNumChars <= dwBufferRequire );
  262. if( dwNumChars <= dwBufferRequire )
  263. {
  264. break;
  265. }
  266. }
  267. if( NULL == pszAddress )
  268. {
  269. hRes = E_UNEXPECTED;
  270. goto CLEANUPANDEXIT;
  271. }
  272. //
  273. // Store the IP address
  274. //
  275. m_pHelpSession->m_IpAddress = pszAddress;
  276. MYASSERT( ((CComBSTR)m_pHelpSession->m_IpAddress).Length() > 0 );
  277. DebugPrintf(
  278. _TEXT("IP Address %s\n"),
  279. (LPTSTR)(CComBSTR)m_pHelpSession->m_IpAddress
  280. );
  281. //
  282. // Create connection parameters
  283. //
  284. hRes = get_HelpSessionId( &bstrSessId );
  285. if( FAILED(hRes) )
  286. {
  287. MYASSERT(FALSE);
  288. goto CLEANUPANDEXIT;
  289. }
  290. MYASSERT( g_TSSecurityBlob.Length() > 0 );
  291. *bstrConnectParms = CreateConnectParmsString(
  292. REMOTEDESKTOP_TSRDP_PROTOCOL,
  293. CComBSTR(pszAddress),
  294. CComBSTR(SALEM_CONNECTPARM_UNUSEFILED_SUBSTITUTE),
  295. CComBSTR(SALEM_CONNECTPARM_UNUSEFILED_SUBSTITUTE),
  296. bstrSessId,
  297. CComBSTR(SALEM_CONNECTPARM_UNUSEFILED_SUBSTITUTE),
  298. CComBSTR(SALEM_CONNECTPARM_UNUSEFILED_SUBSTITUTE),
  299. g_TSSecurityBlob
  300. );
  301. #if DBG
  302. if( NULL != *bstrConnectParms )
  303. {
  304. DebugPrintf(
  305. _TEXT("Connect Parms %s\n"),
  306. *bstrConnectParms
  307. );
  308. }
  309. #endif
  310. CLEANUPANDEXIT:
  311. if( NULL != pszAddress )
  312. {
  313. LocalFree( pszAddress );
  314. }
  315. return hRes;
  316. }
  317. STDMETHODIMP
  318. CRemoteDesktopHelpSession::get_TimeOut(
  319. /*[out, retval]*/ DWORD* pTimeout
  320. )
  321. /*++
  322. --*/
  323. {
  324. HRESULT hRes = S_OK;
  325. BOOL bSuccess;
  326. CCriticalSectionLocker l(m_HelpSessionLock);
  327. if( NULL == pTimeout )
  328. {
  329. hRes = E_POINTER;
  330. }
  331. else if( FALSE == IsSessionValid() )
  332. {
  333. hRes = E_HANDLE;
  334. }
  335. else if( NULL != m_pHelpSession )
  336. {
  337. FILETIME ft;
  338. SYSTEMTIME sysTime;
  339. ft = m_pHelpSession->m_ExpirationTime;
  340. bSuccess = FileTimeToSystemTime(&ft, &sysTime);
  341. if( TRUE == bSuccess )
  342. {
  343. if( sysTime.wYear >= 2038 )
  344. {
  345. *pTimeout = INT_MAX;
  346. }
  347. else
  348. {
  349. struct tm gmTime;
  350. memset(&gmTime, 0, sizeof(gmTime));
  351. gmTime.tm_sec = sysTime.wSecond;
  352. gmTime.tm_min = sysTime.wMinute;
  353. gmTime.tm_hour = sysTime.wHour;
  354. gmTime.tm_year = sysTime.wYear - 1900;
  355. gmTime.tm_mon = sysTime.wMonth - 1;
  356. gmTime.tm_mday = sysTime.wDay;
  357. if((*pTimeout = mktime(&gmTime)) == (time_t)-1)
  358. {
  359. *pTimeout = INT_MAX;
  360. }
  361. }
  362. }
  363. else
  364. {
  365. hRes = HRESULT_FROM_WIN32( GetLastError() );
  366. }
  367. }
  368. else
  369. {
  370. hRes = E_UNEXPECTED;
  371. MYASSERT( FALSE );
  372. }
  373. return hRes;
  374. }
  375. STDMETHODIMP
  376. CRemoteDesktopHelpSession::put_TimeOut(
  377. /*[in]*/ DWORD Timeout
  378. )
  379. /*++
  380. --*/
  381. {
  382. HRESULT hRes = S_OK;
  383. CCriticalSectionLocker l(m_HelpSessionLock);
  384. LONG MaxTicketExpiry;
  385. //
  386. // Get default timeout value from registry, not a critical
  387. // error, if we failed, we just default to 30 days
  388. //
  389. hRes = PolicyGetMaxTicketExpiry( &MaxTicketExpiry );
  390. if( FAILED(hRes) || 0 == MaxTicketExpiry )
  391. {
  392. MaxTicketExpiry = DEFAULT_MAXTICKET_EXPIRY;
  393. }
  394. if( Timeout > MaxTicketExpiry )
  395. {
  396. hRes = S_FALSE;
  397. Timeout = MaxTicketExpiry;
  398. }
  399. time_t curTime;
  400. FILETIME ftTimeOut;
  401. // Get the current time.
  402. time(&curTime);
  403. // time out in seconds
  404. curTime += Timeout;
  405. // Convert to FILETIME
  406. UnixTimeToFileTime( curTime, &ftTimeOut );
  407. if( FALSE == IsSessionValid() )
  408. {
  409. hRes = E_HANDLE;
  410. }
  411. else if( NULL != m_pHelpSession )
  412. {
  413. if( FALSE == m_pHelpSession->IsEntryExpired() )
  414. {
  415. //
  416. // operator =() update registry immediately
  417. //
  418. m_pHelpSession->m_ExpirationTime = ftTimeOut;
  419. }
  420. }
  421. else
  422. {
  423. hRes = E_UNEXPECTED;
  424. }
  425. return hRes;
  426. }
  427. STDMETHODIMP
  428. CRemoteDesktopHelpSession::get_HelpSessionId(
  429. OUT BSTR *pVal
  430. )
  431. /*++
  432. Routine Description:
  433. Get help session ID.
  434. Parameters:
  435. pVal : return Help session ID of this help session instance.
  436. Returns:
  437. S_OK
  438. E_OUTOFMEMORY
  439. E_UNEXPECTED
  440. --*/
  441. {
  442. HRESULT hRes = S_OK;
  443. CCriticalSectionLocker l(m_HelpSessionLock);
  444. if( NULL == pVal )
  445. {
  446. hRes = E_POINTER;
  447. }
  448. else if( FALSE == IsSessionValid() )
  449. {
  450. hRes = E_HANDLE;
  451. }
  452. else if( NULL != m_pHelpSession )
  453. {
  454. DebugPrintf(
  455. _TEXT("get_HelpSessionId() on %s\n"),
  456. m_bstrHelpSessionId
  457. );
  458. MYASSERT( m_pHelpSession->m_SessionId->Length() > 0 );
  459. if( m_pHelpSession->m_SessionId->Length() > 0 )
  460. {
  461. *pVal = m_pHelpSession->m_SessionId->Copy();
  462. if( NULL == *pVal )
  463. {
  464. hRes = E_OUTOFMEMORY;
  465. }
  466. }
  467. else
  468. {
  469. hRes = E_UNEXPECTED;
  470. }
  471. }
  472. else
  473. {
  474. hRes = E_UNEXPECTED;
  475. MYASSERT( FALSE );
  476. }
  477. return hRes;
  478. }
  479. STDMETHODIMP
  480. CRemoteDesktopHelpSession::get_UserLogonId(
  481. OUT long *pVal
  482. )
  483. /*++
  484. Routine Description:
  485. Get user's TS session ID, note, non-ts session or Win9x always
  486. has 0 as user logon id.
  487. Parameters:
  488. pVal : Return user logon ID.
  489. Returns:
  490. S_OK
  491. --*/
  492. {
  493. HRESULT hRes = S_OK;
  494. CCriticalSectionLocker l(m_HelpSessionLock);
  495. if( NULL == pVal )
  496. {
  497. hRes = E_POINTER;
  498. }
  499. else if(FALSE == IsSessionValid())
  500. {
  501. hRes = E_HANDLE;
  502. }
  503. else if( NULL != m_pHelpSession )
  504. {
  505. *pVal = m_ulLogonId;
  506. if( UNKNOWN_LOGONID == m_ulLogonId )
  507. {
  508. hRes = S_FALSE;
  509. }
  510. }
  511. else
  512. {
  513. MYASSERT( FALSE );
  514. hRes = E_UNEXPECTED;
  515. }
  516. return hRes;
  517. }
  518. STDMETHODIMP
  519. CRemoteDesktopHelpSession::get_AssistantAccountName(
  520. OUT BSTR *pVal
  521. )
  522. /*++
  523. Routine Description:
  524. Get help assistant account name associated with this
  525. help session.
  526. Parameters:
  527. pVal : Return help assistant account name associated
  528. with this help session.
  529. Returns:
  530. S_OK
  531. E_OUTOFMEMORY
  532. --*/
  533. {
  534. HRESULT hRes = S_OK;
  535. // Don't need a lock here.
  536. if( NULL != pVal )
  537. {
  538. CComBSTR accName;
  539. hRes = g_HelpAccount.GetHelpAccountNameEx( accName );
  540. if( SUCCEEDED(hRes) )
  541. {
  542. *pVal = accName.Copy();
  543. if( NULL == *pVal )
  544. {
  545. hRes = E_OUTOFMEMORY;
  546. }
  547. }
  548. }
  549. else
  550. {
  551. hRes = E_POINTER;
  552. }
  553. return hRes;
  554. }
  555. STDMETHODIMP
  556. CRemoteDesktopHelpSession::get_HelpSessionName(
  557. OUT BSTR *pVal
  558. )
  559. /*++
  560. Routine Description:
  561. Get help session name associated with this
  562. help session.
  563. Parameters:
  564. pVal : Return help session name associated
  565. with this help session.
  566. Returns:
  567. S_OK
  568. S_FALSE No Help Session Name
  569. E_OUTOFMEMORY Out of memory
  570. E_POINTER Invalid parameter
  571. HRESULT_FROM_WIN32( ERROR_LOCK_VIOLATION );
  572. --*/
  573. {
  574. HRESULT hRes = S_OK;
  575. CCriticalSectionLocker l(m_HelpSessionLock);
  576. if(FALSE == IsSessionValid())
  577. {
  578. hRes = E_HANDLE;
  579. }
  580. else if( NULL == pVal )
  581. {
  582. hRes = E_POINTER;
  583. }
  584. else if( NULL != m_pHelpSession )
  585. {
  586. if( m_pHelpSession->m_SessionName->Length() > 0 )
  587. {
  588. *pVal = m_pHelpSession->m_SessionName->Copy();
  589. if( NULL == *pVal )
  590. {
  591. hRes = E_OUTOFMEMORY;
  592. }
  593. }
  594. else
  595. {
  596. hRes = S_FALSE;
  597. }
  598. }
  599. else
  600. {
  601. hRes = E_UNEXPECTED;
  602. MYASSERT(FALSE);
  603. }
  604. return hRes;
  605. }
  606. STDMETHODIMP
  607. CRemoteDesktopHelpSession::put_HelpSessionName(
  608. IN BSTR newVal
  609. )
  610. /*++
  611. Routine Description:
  612. Set help session name associated with this
  613. help session.
  614. Parameters:
  615. newVal : New help session name.
  616. Returns:
  617. S_OK
  618. E_OUTOFMEMORY
  619. --*/
  620. {
  621. HRESULT hRes = S_OK;
  622. CCriticalSectionLocker l(m_HelpSessionLock);
  623. if(FALSE == IsSessionValid())
  624. {
  625. hRes = E_HANDLE;
  626. }
  627. else if( FALSE == IsClientSessionCreator() )
  628. {
  629. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  630. }
  631. else if( m_pHelpSession != NULL )
  632. {
  633. //
  634. // NULL will reset help session name
  635. //
  636. //
  637. // operator =() update registry immediately
  638. //
  639. m_pHelpSession->m_SessionName = newVal;
  640. if( !((CComBSTR)m_pHelpSession->m_SessionName == newVal) )
  641. {
  642. hRes = E_OUTOFMEMORY;
  643. }
  644. }
  645. else
  646. {
  647. MYASSERT(FALSE);
  648. hRes = E_UNEXPECTED;
  649. }
  650. return hRes;
  651. }
  652. STDMETHODIMP
  653. CRemoteDesktopHelpSession::put_HelpSessionPassword(
  654. IN BSTR newVal
  655. )
  656. /*++
  657. Routine Description:
  658. Change help session password associated with this
  659. help session.
  660. Parameters:
  661. newVal : New help session password.
  662. Returns:
  663. S_OK
  664. E_OUTOFMEMORY Out of memory
  665. --*/
  666. {
  667. HRESULT hRes = S_OK;
  668. CCriticalSectionLocker l(m_HelpSessionLock);
  669. if( FALSE == IsSessionValid() )
  670. {
  671. hRes = E_HANDLE;
  672. }
  673. else if( FALSE == IsClientSessionCreator() )
  674. {
  675. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  676. }
  677. else if( NULL != m_pHelpSession )
  678. {
  679. //
  680. // NULL will reset password
  681. //
  682. //
  683. // operator =() update registry immediately
  684. //
  685. m_pHelpSession->m_SessionPwd = newVal;
  686. if( !((CComBSTR)m_pHelpSession->m_SessionPwd == newVal) )
  687. {
  688. hRes = E_OUTOFMEMORY;
  689. }
  690. }
  691. else
  692. {
  693. hRes = E_UNEXPECTED;
  694. MYASSERT( FALSE );
  695. }
  696. return hRes;
  697. }
  698. STDMETHODIMP
  699. CRemoteDesktopHelpSession::get_HelpSessionDescription(
  700. OUT BSTR *pVal
  701. )
  702. /*++
  703. Routine Description:
  704. Get help session description associated with this
  705. help session.
  706. Parameters:
  707. pVal : Return help session description associated
  708. with this help session.
  709. Returns:
  710. S_OK
  711. S_FALSE No Description
  712. E_OUTOFMEMORY Out of memory
  713. E_POINTER Invalid argument
  714. --*/
  715. {
  716. HRESULT hRes = S_OK;
  717. CCriticalSectionLocker l(m_HelpSessionLock);
  718. if( NULL == pVal )
  719. {
  720. hRes = E_POINTER;
  721. }
  722. else if( FALSE == IsSessionValid() )
  723. {
  724. hRes = E_HANDLE;
  725. }
  726. else if( m_pHelpSession != NULL )
  727. {
  728. if( m_pHelpSession->m_SessionDesc->Length() > 0 )
  729. {
  730. *pVal = m_pHelpSession->m_SessionDesc->Copy();
  731. if( NULL == *pVal )
  732. {
  733. hRes = E_OUTOFMEMORY;
  734. }
  735. }
  736. else
  737. {
  738. hRes = S_FALSE;
  739. }
  740. }
  741. else
  742. {
  743. hRes = E_UNEXPECTED;
  744. MYASSERT(FALSE);
  745. }
  746. return hRes;
  747. }
  748. STDMETHODIMP
  749. CRemoteDesktopHelpSession::put_HelpSessionDescription(
  750. IN BSTR newVal
  751. )
  752. /*++
  753. Routine Description:
  754. Change help session description associated with this
  755. help session.
  756. Parameters:
  757. newVal : new help session description associated
  758. with this help session.
  759. Returns:
  760. S_OK
  761. Note:
  762. Help Session name and description is reserved for future use
  763. --*/
  764. {
  765. HRESULT hRes = S_OK;
  766. CCriticalSectionLocker l(m_HelpSessionLock);
  767. if( FALSE == IsSessionValid() )
  768. {
  769. hRes = E_HANDLE;
  770. }
  771. else if( FALSE == IsClientSessionCreator() )
  772. {
  773. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  774. }
  775. else if( NULL != m_pHelpSession )
  776. {
  777. //
  778. // NULL will reset description
  779. //
  780. //
  781. // operator =() update registry immediately
  782. //
  783. m_pHelpSession->m_SessionDesc = newVal;
  784. if( !((CComBSTR)m_pHelpSession->m_SessionDesc == newVal) )
  785. {
  786. hRes = E_OUTOFMEMORY;
  787. }
  788. }
  789. else
  790. {
  791. hRes = E_UNEXPECTED;
  792. MYASSERT(FALSE);
  793. }
  794. return hRes;
  795. }
  796. STDMETHODIMP
  797. CRemoteDesktopHelpSession::get_EnableResolver(
  798. OUT BOOL* pVal
  799. )
  800. /*++
  801. Routine Description:
  802. Return Session Resolver's CLSID for this help session.
  803. Parameters:
  804. pVal : Pointer to BSTR to receive pointer to Resolver's CLSID.
  805. Returns:
  806. S_OK
  807. E_POINTER Invalid argument
  808. --*/
  809. {
  810. HRESULT hRes = S_OK;
  811. CCriticalSectionLocker l(m_HelpSessionLock);
  812. if( NULL == pVal )
  813. {
  814. hRes = E_POINTER;
  815. }
  816. else if(FALSE == IsSessionValid())
  817. {
  818. hRes = E_HANDLE;
  819. }
  820. else if( NULL != m_pHelpSession )
  821. {
  822. *pVal = ((long)m_pHelpSession->m_EnableResolver > 0) ? TRUE : FALSE;
  823. }
  824. else
  825. {
  826. hRes = E_UNEXPECTED;
  827. MYASSERT(FALSE);
  828. }
  829. return hRes;
  830. }
  831. STDMETHODIMP
  832. CRemoteDesktopHelpSession::put_EnableResolver(
  833. IN BOOL newVal
  834. )
  835. /*++
  836. Routine Description:
  837. Set Session Resolver's CLSID, if input is NULL or empty
  838. string, Help Session Manager will not invoke resolver.
  839. Parameters:
  840. Val : Resolver's CLSID
  841. Returns:
  842. S_OK
  843. E_OUTOFMEMORY
  844. --*/
  845. {
  846. HRESULT hRes = S_OK;
  847. CCriticalSectionLocker l(m_HelpSessionLock);
  848. if( FALSE == IsSessionValid() )
  849. {
  850. hRes = E_HANDLE;
  851. }
  852. else if( FALSE == IsClientSessionCreator() )
  853. {
  854. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  855. }
  856. else if( NULL != m_pHelpSession )
  857. {
  858. //
  859. // NULL will reset resolver's ID for this session
  860. //
  861. //
  862. // operator =() update registry immediately
  863. //
  864. m_pHelpSession->m_EnableResolver = newVal;
  865. }
  866. else
  867. {
  868. hRes = E_UNEXPECTED;
  869. MYASSERT(FALSE);
  870. }
  871. return hRes;
  872. }
  873. STDMETHODIMP
  874. CRemoteDesktopHelpSession::get_ResolverBlob(
  875. OUT BSTR* pVal
  876. )
  877. /*++
  878. Routine Description:
  879. Return blob for session resolver to map help session
  880. to user session/
  881. Parameters:
  882. pVal : Pointer to BSTR to receive blob.
  883. Returns:
  884. S_OK
  885. S_FALSE No blob
  886. E_OUTOFMEMORY
  887. E_POINTER
  888. --*/
  889. {
  890. HRESULT hRes = S_OK;
  891. CCriticalSectionLocker l(m_HelpSessionLock);
  892. if( NULL == pVal )
  893. {
  894. hRes = E_POINTER;
  895. }
  896. else if(FALSE == IsSessionValid())
  897. {
  898. hRes = E_HANDLE;
  899. }
  900. else if( NULL != m_pHelpSession )
  901. {
  902. if( m_pHelpSession->m_SessResolverBlob->Length() > 0 )
  903. {
  904. *pVal = m_pHelpSession->m_SessResolverBlob->Copy();
  905. if( NULL == *pVal )
  906. {
  907. hRes = E_OUTOFMEMORY;
  908. }
  909. }
  910. else
  911. {
  912. hRes = S_FALSE;
  913. }
  914. }
  915. else
  916. {
  917. hRes = E_UNEXPECTED;
  918. MYASSERT(FALSE);
  919. }
  920. return hRes;
  921. }
  922. STDMETHODIMP
  923. CRemoteDesktopHelpSession::put_ResolverBlob(
  924. IN BSTR newVal
  925. )
  926. /*++
  927. Routine Description:
  928. Add/change blob which will be passed to session
  929. resolver to map/find user session associated with this
  930. help session, Help Session Manager does not interpret this
  931. blob.
  932. Parameters:
  933. newVal : Pointer to new blob.
  934. Returns:
  935. S_OK
  936. E_OUTOFMEMORY Out of memory
  937. --*/
  938. {
  939. HRESULT hRes = S_OK;
  940. CCriticalSectionLocker l(m_HelpSessionLock);
  941. if( FALSE == IsSessionValid() )
  942. {
  943. hRes = E_HANDLE;
  944. }
  945. else if( FALSE == IsClientSessionCreator() )
  946. {
  947. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  948. }
  949. else if( NULL != m_pHelpSession )
  950. {
  951. //
  952. // NULL will reset resolver's ID for this session
  953. //
  954. //
  955. // operator =() update registry immediately
  956. //
  957. m_pHelpSession->m_SessResolverBlob = newVal;
  958. if( !((CComBSTR)m_pHelpSession->m_SessResolverBlob == newVal) )
  959. {
  960. hRes = E_OUTOFMEMORY;
  961. }
  962. }
  963. else
  964. {
  965. hRes = E_UNEXPECTED;
  966. MYASSERT(FALSE);
  967. }
  968. return hRes;
  969. }
  970. STDMETHODIMP
  971. CRemoteDesktopHelpSession::get_HelpSessionCreateBlob(
  972. OUT BSTR* pVal
  973. )
  974. /*++
  975. Routine Description:
  976. Return blob for session resolver to map help session
  977. to user session/
  978. Parameters:
  979. pVal : Pointer to BSTR to receive blob.
  980. Returns:
  981. S_OK
  982. S_FALSE No blob
  983. E_OUTOFMEMORY
  984. E_POINTER
  985. --*/
  986. {
  987. HRESULT hRes = S_OK;
  988. CCriticalSectionLocker l(m_HelpSessionLock);
  989. if( NULL == pVal )
  990. {
  991. hRes = E_POINTER;
  992. }
  993. else if(FALSE == IsSessionValid())
  994. {
  995. hRes = E_HANDLE;
  996. }
  997. else if( NULL != m_pHelpSession )
  998. {
  999. if( m_pHelpSession->m_SessionCreateBlob->Length() > 0 )
  1000. {
  1001. *pVal = m_pHelpSession->m_SessionCreateBlob->Copy();
  1002. if( NULL == *pVal )
  1003. {
  1004. hRes = E_OUTOFMEMORY;
  1005. }
  1006. }
  1007. else
  1008. {
  1009. hRes = S_FALSE;
  1010. }
  1011. }
  1012. else
  1013. {
  1014. hRes = E_UNEXPECTED;
  1015. MYASSERT(FALSE);
  1016. }
  1017. return hRes;
  1018. }
  1019. STDMETHODIMP
  1020. CRemoteDesktopHelpSession::put_HelpSessionCreateBlob(
  1021. IN BSTR newVal
  1022. )
  1023. /*++
  1024. Routine Description:
  1025. Add/change blob which will be passed to session
  1026. resolver to map/find user session associated with this
  1027. help session, Help Session Manager does not interpret this
  1028. blob.
  1029. Parameters:
  1030. newVal : Pointer to new blob.
  1031. Returns:
  1032. S_OK
  1033. E_OUTOFMEMORY Out of memory
  1034. --*/
  1035. {
  1036. HRESULT hRes = S_OK;
  1037. CCriticalSectionLocker l(m_HelpSessionLock);
  1038. if( FALSE == IsSessionValid() )
  1039. {
  1040. hRes = E_HANDLE;
  1041. }
  1042. else if( FALSE == IsClientSessionCreator() )
  1043. {
  1044. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  1045. }
  1046. else if( NULL != m_pHelpSession )
  1047. {
  1048. //
  1049. // operator =() update registry immediately
  1050. //
  1051. m_pHelpSession->m_SessionCreateBlob = newVal;
  1052. if( !((CComBSTR)m_pHelpSession->m_SessionCreateBlob == newVal) )
  1053. {
  1054. hRes = E_OUTOFMEMORY;
  1055. }
  1056. }
  1057. else
  1058. {
  1059. hRes = E_UNEXPECTED;
  1060. MYASSERT(FALSE);
  1061. }
  1062. return hRes;
  1063. }
  1064. STDMETHODIMP
  1065. CRemoteDesktopHelpSession::get_UserHelpSessionRemoteDesktopSharingSetting(
  1066. /*[out, retval]*/ REMOTE_DESKTOP_SHARING_CLASS* pSetting
  1067. )
  1068. /*++
  1069. Routine Description:
  1070. Return help session's RDS setting.
  1071. Parameters:
  1072. pSetting : Pointer to REMOTE_DESKTOP_SHARING_CLASS to
  1073. receive session's RDS setting.
  1074. Returns:
  1075. S_OK
  1076. E_POINTER Invalid argument.
  1077. --*/
  1078. {
  1079. HRESULT hRes = S_OK;
  1080. CCriticalSectionLocker l(m_HelpSessionLock);
  1081. if( NULL == pSetting )
  1082. {
  1083. hRes = E_POINTER;
  1084. }
  1085. else if(FALSE == IsSessionValid())
  1086. {
  1087. hRes = E_HANDLE;
  1088. }
  1089. else if( NULL != m_pHelpSession )
  1090. {
  1091. *pSetting = (REMOTE_DESKTOP_SHARING_CLASS)(long)m_pHelpSession->m_SessionRdsSetting;
  1092. }
  1093. else
  1094. {
  1095. hRes = E_UNEXPECTED;
  1096. MYASSERT(FALSE);
  1097. }
  1098. return hRes;
  1099. }
  1100. STDMETHODIMP
  1101. CRemoteDesktopHelpSession::put_UserHelpSessionRemoteDesktopSharingSetting(
  1102. /*[in]*/ REMOTE_DESKTOP_SHARING_CLASS Setting
  1103. )
  1104. /*++
  1105. Routine Description:
  1106. Set help session's RDS setting.
  1107. Parameters:
  1108. Setting : New RDS setting.
  1109. Returns:
  1110. S_OK
  1111. S_FALSE New setting is overrided with
  1112. policy setting.
  1113. HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) User not allow to get help.
  1114. HRESULT_FROM_WIN32( ERROR_SHARING_VIOLATION ) Other help session already has this set
  1115. HRESULT_FROM_WIN32( ERROR_VC_DISCONNECTED ) Session is not connected
  1116. HRESULT_FROM_WIN32( WinStationQueryInformation() );
  1117. E_OUTOFMEMORY
  1118. Note:
  1119. Only one help session can change the RDS setting, all other help session
  1120. will get HRESULT_FROM_WIN32( ERROR_SHARING_VIOLATION ) error return.
  1121. REMOTE_DESKTOP_SHARING_CLASS also define priviledge
  1122. level, that is user with NO_DESKTOP_SHARING can't
  1123. adjust his/her sharing class, user with CONTROLDESKTOP_PERMISSION_REQUIRE
  1124. can't adjust his/her sharing class to CONTROLDESKTOP_PERMISSION_NOT_REQUIRE
  1125. however, he/she can reset to NO_DESKTOP_SHARING, VIEWDESKTOP_PERMISSION_REQUIRE
  1126. --*/
  1127. {
  1128. HRESULT hRes = S_OK;
  1129. CCriticalSectionLocker l(m_HelpSessionLock);
  1130. if( FALSE == IsSessionValid() )
  1131. {
  1132. hRes = E_HANDLE;
  1133. }
  1134. else if( FALSE == IsClientSessionCreator() )
  1135. {
  1136. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  1137. }
  1138. else if( NULL != m_pHelpSession )
  1139. {
  1140. //
  1141. // operator =() update registry immediately
  1142. //
  1143. m_pHelpSession->m_SessionRdsSetting = Setting;
  1144. }
  1145. else
  1146. {
  1147. hRes = E_UNEXPECTED;
  1148. MYASSERT(FALSE);
  1149. }
  1150. return hRes;
  1151. }
  1152. STDMETHODIMP
  1153. CRemoteDesktopHelpSession::get_AllowToGetHelp(
  1154. /*[out, retval]*/ BOOL* pVal
  1155. )
  1156. /*++
  1157. Routine Description:
  1158. Determine if user created this help session is
  1159. allowed to get help or not, this is possible that policy change
  1160. after user re-logon.
  1161. Parameters:
  1162. pVal : Pointer to BOOL to receive result.
  1163. Returns:
  1164. S_OK
  1165. HRESULT_FROM_WIN32( ERROR_VC_DISCONNECTED ) User is not connected any more.
  1166. E_UNEXPECTED; Internal error.
  1167. --*/
  1168. {
  1169. HRESULT hRes = S_OK;
  1170. CCriticalSectionLocker l(m_HelpSessionLock);
  1171. if( NULL == pVal )
  1172. {
  1173. hRes = E_POINTER;
  1174. }
  1175. else if( FALSE == IsSessionValid() )
  1176. {
  1177. hRes = E_HANDLE;
  1178. }
  1179. else if( NULL != m_pHelpSession )
  1180. {
  1181. if( UNKNOWN_LOGONID == m_ulLogonId )
  1182. {
  1183. hRes = HRESULT_FROM_WIN32( ERROR_VC_DISCONNECTED );
  1184. }
  1185. else if( m_pHelpSession->m_UserSID->Length() == 0 )
  1186. {
  1187. hRes = E_UNEXPECTED;
  1188. MYASSERT(FALSE);
  1189. }
  1190. else
  1191. {
  1192. *pVal = IsUserAllowToGetHelp(
  1193. m_ulLogonId,
  1194. (LPCTSTR) CComBSTRtoLPTSTR( (CComBSTR)m_pHelpSession->m_UserSID )
  1195. );
  1196. }
  1197. }
  1198. else
  1199. {
  1200. hRes = E_UNEXPECTED;
  1201. MYASSERT(FALSE);
  1202. }
  1203. return hRes;
  1204. }
  1205. STDMETHODIMP
  1206. CRemoteDesktopHelpSession::DeleteHelp()
  1207. /*++
  1208. Routine Description:
  1209. Delete this help session
  1210. Parameters:
  1211. None.
  1212. Returns:
  1213. S_OK or error code from
  1214. Help Session Manager's DeleteHelpSession().
  1215. --*/
  1216. {
  1217. HRESULT hRes = S_OK;
  1218. CRemoteDesktopHelpSessionMgr::LockIDToSessionMapCache();
  1219. CCriticalSectionLocker l(m_HelpSessionLock);
  1220. if( FALSE == IsSessionValid() )
  1221. {
  1222. hRes = E_HANDLE;
  1223. }
  1224. else if( NULL != m_pHelpSession )
  1225. {
  1226. DebugPrintf(
  1227. _TEXT("CRemoteDesktopHelpSession::DeleteHelp() %s...\n"),
  1228. m_bstrHelpSessionId
  1229. );
  1230. //
  1231. // BUGBUG : Refer to timing bug, no notification about terminating
  1232. // shadow, and we can't reset session's shadow class. force a
  1233. // reset here for now.
  1234. //
  1235. ResetSessionRDSSetting();
  1236. //
  1237. // if we are not been help, just delete it, if we are in the middle
  1238. // of help, deleting it from cache and database entry will cause
  1239. // Resolver's OnDisconnect() never got call resulting in user
  1240. // lock in resolver never got release so we update the expiration
  1241. // date to current, expiration thread or next load will trigger
  1242. // actual delete.
  1243. //
  1244. if(GetHelperSessionId() == UNKNOWN_LOGONID)
  1245. {
  1246. CRemoteDesktopHelpSessionMgr::DeleteHelpSessionFromCache( (CComBSTR) m_pHelpSession->m_SessionId );
  1247. if( (DWORD)(long)m_pHelpSession->m_ICSPort > 0 )
  1248. {
  1249. //
  1250. // Destructor does not close ICS port, we only close
  1251. // ICS port when help is deleted.
  1252. //
  1253. ClosePort( (DWORD)(long)m_pHelpSession->m_ICSPort );
  1254. }
  1255. // Delete will release the entry ref. count
  1256. hRes = m_pHelpSession->Delete();
  1257. m_pHelpSession = NULL;
  1258. m_bDeleted = TRUE;
  1259. }
  1260. else
  1261. {
  1262. put_TimeOut(0);
  1263. }
  1264. }
  1265. else
  1266. {
  1267. hRes = E_UNEXPECTED;
  1268. MYASSERT(FALSE);
  1269. }
  1270. CRemoteDesktopHelpSessionMgr::UnlockIDToSessionMapCache();
  1271. return hRes;
  1272. }
  1273. void
  1274. CRemoteDesktopHelpSession::ResolveTicketOwner()
  1275. /*++
  1276. Description:
  1277. Convert ticket owner SID to domain\account.
  1278. Parameters:
  1279. None.
  1280. Returns:
  1281. --*/
  1282. {
  1283. //LPTSTR pszNoviceDomain = NULL;
  1284. //LPTSTR pszNoviceName = NULL;
  1285. BSTR pszNoviceDomain = NULL;
  1286. BSTR pszNoviceName = NULL;
  1287. HRESULT hRes = S_OK;
  1288. MYASSERT( IsSessionValid() );
  1289. if( IsSessionValid() )
  1290. {
  1291. hRes = ConvertSidToAccountName(
  1292. (CComBSTR)m_pHelpSession->m_UserSID,
  1293. &pszNoviceDomain,
  1294. &pszNoviceName
  1295. );
  1296. }
  1297. else
  1298. {
  1299. // help session ticket is deleted
  1300. hRes = E_HANDLE;
  1301. }
  1302. //
  1303. // NO ASSERT, ConvertSidToAccountName() already assert.
  1304. //
  1305. if( SUCCEEDED(hRes) )
  1306. {
  1307. //
  1308. // DO NOT FREE the memory, once string is attached to CComBSTR,
  1309. // CComBSTR will free it at destructor
  1310. //
  1311. m_EventLogInfo.bstrNoviceDomain.Attach(pszNoviceDomain);
  1312. m_EventLogInfo.bstrNoviceAccount.Attach(pszNoviceName);
  1313. //m_EventLogInfo.bstrNoviceDomain = pszNoviceDomain;
  1314. //m_EventLogInfo.bstrNoviceAccount = pszNoviceName;
  1315. //LocalFree(pszNoviceDomain);
  1316. //LocalFree(pszNoviceName);
  1317. }
  1318. else
  1319. {
  1320. m_EventLogInfo.bstrNoviceDomain = g_UnknownString;
  1321. m_EventLogInfo.bstrNoviceAccount = (CComBSTR)m_pHelpSession->m_UserSID;
  1322. }
  1323. return;
  1324. }
  1325. void
  1326. CRemoteDesktopHelpSession::ResolveHelperInformation(
  1327. IN ULONG HelperSessionId,
  1328. OUT CComBSTR& bstrExpertIpAddressFromClient,
  1329. OUT CComBSTR& bstrExpertIpAddressFromServer
  1330. )
  1331. /*++
  1332. Description:
  1333. Retrieve from TermSrv regarding HelpAssistant session's IP address send from
  1334. expert (mstscax send this) and IP address of client machine retrive from TCPIP
  1335. Parameters:
  1336. HelperSessionId : TS session ID of help assistant session.
  1337. bstrExpertIpAddressFromClient : IP address send from mstscax.
  1338. bstrExpertIpAddressFromServer : IP address that TS retrieve from tcpip stack.
  1339. Returns:
  1340. --*/
  1341. {
  1342. HRESULT hRes = S_OK;
  1343. WINSTATIONCLIENT winstationClient;
  1344. WINSTATIONREMOTEADDRESS winstationRemoteAddress;
  1345. ULONG winstationInfoLen;
  1346. DWORD dwLength = 0;
  1347. DWORD dwStatus = ERROR_SUCCESS;
  1348. //
  1349. // Retrieve client IP address passed from client
  1350. winstationInfoLen = 0;
  1351. ZeroMemory( &winstationClient, sizeof(winstationClient) );
  1352. if(!WinStationQueryInformation(
  1353. SERVERNAME_CURRENT,
  1354. HelperSessionId,
  1355. WinStationClient,
  1356. (PVOID)&winstationClient,
  1357. sizeof(winstationClient),
  1358. &winstationInfoLen
  1359. ))
  1360. {
  1361. dwStatus = GetLastError();
  1362. DebugPrintf(
  1363. _TEXT("WinStationQueryInformation() query WinStationClient return %d\n"), dwStatus
  1364. );
  1365. // Critical error?, fro now, log as 'unknown'.
  1366. bstrExpertIpAddressFromClient = g_UnknownString;
  1367. }
  1368. else
  1369. {
  1370. bstrExpertIpAddressFromClient = winstationClient.ClientAddress;
  1371. }
  1372. //
  1373. // Retrieve client IP address retrieve from server TCPIP
  1374. winstationInfoLen = 0;
  1375. ZeroMemory( &winstationRemoteAddress, sizeof(winstationRemoteAddress) );
  1376. if(!WinStationQueryInformation(
  1377. SERVERNAME_CURRENT,
  1378. HelperSessionId,
  1379. WinStationRemoteAddress,
  1380. (PVOID)&winstationRemoteAddress,
  1381. sizeof(winstationRemoteAddress),
  1382. &winstationInfoLen
  1383. ))
  1384. {
  1385. dwStatus = GetLastError();
  1386. DebugPrintf(
  1387. _TEXT("WinStationQueryInformation() query WinStationRemoteAddress return %d %d %d\n"),
  1388. dwStatus,
  1389. sizeof(winstationRemoteAddress),
  1390. winstationInfoLen
  1391. );
  1392. // Critical error?, for now, log as 'unknown'.
  1393. bstrExpertIpAddressFromServer = g_UnknownString;
  1394. }
  1395. else
  1396. {
  1397. if( AF_INET == winstationRemoteAddress.sin_family )
  1398. {
  1399. // refer to in_addr structure.
  1400. struct in_addr S;
  1401. S.S_un.S_addr = winstationRemoteAddress.ipv4.in_addr;
  1402. bstrExpertIpAddressFromServer = inet_ntoa(S);
  1403. if(bstrExpertIpAddressFromServer.Length() == 0 )
  1404. {
  1405. MYASSERT(FALSE);
  1406. bstrExpertIpAddressFromServer = g_UnknownString;
  1407. }
  1408. }
  1409. else
  1410. {
  1411. // we are not yet support IPV6 address, calling WSAAddressToString() will fail with error.
  1412. bstrExpertIpAddressFromServer = g_UnknownString;
  1413. }
  1414. }
  1415. CLEANUPANDEXIT:
  1416. return;
  1417. }
  1418. STDMETHODIMP
  1419. CRemoteDesktopHelpSession::ResolveUserSession(
  1420. IN BSTR resolverBlob,
  1421. IN BSTR expertBlob,
  1422. LONG CallerProcessId,
  1423. OUT ULONG_PTR* phHelpCtr,
  1424. OUT LONG* pResolverErrCode,
  1425. OUT long* plUserSession
  1426. )
  1427. /*++
  1428. Routine Description:
  1429. Resolve a user help session to user TS session.
  1430. Parameters:
  1431. plUserSession : Pointer to long to receive user TS session.
  1432. Returns:
  1433. S_OK
  1434. HRESULT_FROM_WIN32( ERROR_NO_ASSOCIATION ) No resolver for this help session
  1435. HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) Can't convert
  1436. result from CoCreateInstance() or IRDSCallback
  1437. -*/
  1438. {
  1439. HRESULT hRes = S_OK;
  1440. UUID ResolverUuid;
  1441. RPC_STATUS rpcStatus;
  1442. ISAFRemoteDesktopCallback* pIResolver;
  1443. long sessionId;
  1444. long HelperSessionId;
  1445. int resolverRetCode;
  1446. WINSTATIONINFORMATION HelperWinstationInfo;
  1447. DWORD dwStatus;
  1448. ULONG winstationInfoLen;
  1449. CComBSTR bstrExpertAddressFromClient;
  1450. CComBSTR bstrExpertAddressFromTSServer;
  1451. CCriticalSectionLocker l(m_HelpSessionLock);
  1452. DWORD dwEventLogCode;
  1453. if( FALSE == IsSessionValid() )
  1454. {
  1455. hRes = E_HANDLE;
  1456. *pResolverErrCode = SAFERROR_HELPSESSIONEXPIRED;
  1457. return hRes;
  1458. }
  1459. if( NULL == m_pHelpSession || NULL == pResolverErrCode )
  1460. {
  1461. hRes = E_POINTER;
  1462. *pResolverErrCode = SAFERROR_INVALIDPARAMETERSTRING;
  1463. MYASSERT(FALSE);
  1464. return hRes;
  1465. }
  1466. if( m_pHelpSession->m_UserSID->Length() == 0 )
  1467. {
  1468. hRes = E_UNEXPECTED;
  1469. *pResolverErrCode = SAFERROR_UNKNOWNSESSMGRERROR;
  1470. goto CLEANUPANDEXIT;
  1471. }
  1472. //
  1473. // must have user logon ID if we are not using resolver,
  1474. // in pure SALEM SDK, multiple expert can connect
  1475. // using same help ticket, only one can shadow.
  1476. //
  1477. *pResolverErrCode = SAFERROR_NOERROR;
  1478. if( (long)m_pHelpSession->m_EnableResolver == 0 )
  1479. {
  1480. if( UNKNOWN_LOGONID != m_ulLogonId )
  1481. {
  1482. *plUserSession = (long) m_ulLogonId;
  1483. }
  1484. else
  1485. {
  1486. // no resolver for this help session
  1487. hRes = HRESULT_FROM_WIN32( ERROR_NO_ASSOCIATION );
  1488. // user already logoff
  1489. *pResolverErrCode = SAFERROR_USERNOTFOUND;
  1490. }
  1491. //
  1492. // We are not using resolver, bail out.
  1493. //
  1494. goto CLEANUPANDEXIT;
  1495. }
  1496. //
  1497. // Retrieve Caller's TS session ID
  1498. //
  1499. hRes = ImpersonateClient();
  1500. if( FAILED(hRes) )
  1501. {
  1502. *pResolverErrCode = SAFERROR_UNKNOWNSESSMGRERROR;
  1503. return hRes;
  1504. }
  1505. HelperSessionId = GetUserTSLogonId();
  1506. EndImpersonateClient();
  1507. ResolveHelperInformation(
  1508. HelperSessionId,
  1509. bstrExpertAddressFromClient,
  1510. bstrExpertAddressFromTSServer
  1511. );
  1512. DebugPrintf(
  1513. _TEXT("Expert Session ID %d, Expert Address %s %s\n"),
  1514. HelperSessionId,
  1515. bstrExpertAddressFromClient,
  1516. bstrExpertAddressFromTSServer
  1517. );
  1518. DebugPrintf(
  1519. _TEXT("Novice %s %s\n"),
  1520. m_EventLogInfo.bstrNoviceDomain,
  1521. m_EventLogInfo.bstrNoviceAccount
  1522. );
  1523. //
  1524. // Check if helper session is still active, under stress, we might
  1525. // get this call after help assistant session is gone.
  1526. //
  1527. ZeroMemory( &HelperWinstationInfo, sizeof(HelperWinstationInfo) );
  1528. winstationInfoLen = 0;
  1529. if(!WinStationQueryInformation(
  1530. SERVERNAME_CURRENT,
  1531. HelperSessionId,
  1532. WinStationInformation,
  1533. (PVOID)&HelperWinstationInfo,
  1534. sizeof(HelperWinstationInfo),
  1535. &winstationInfoLen
  1536. ))
  1537. {
  1538. dwStatus = GetLastError();
  1539. DebugPrintf(
  1540. _TEXT("WinStationQueryInformation() return %d\n"), dwStatus
  1541. );
  1542. hRes = HRESULT_FROM_WIN32( dwStatus );
  1543. *pResolverErrCode = SAFERROR_SESSIONNOTCONNECTED;
  1544. goto CLEANUPANDEXIT;
  1545. }
  1546. if( HelperWinstationInfo.ConnectState != State_Active )
  1547. {
  1548. DebugPrintf(
  1549. _TEXT("Helper session is %d"),
  1550. HelperWinstationInfo.ConnectState
  1551. );
  1552. // Helper Session is not active, can't provide help
  1553. hRes = HRESULT_FROM_WIN32( ERROR_NO_ASSOCIATION );
  1554. *pResolverErrCode = SAFERROR_SESSIONNOTCONNECTED;
  1555. goto CLEANUPANDEXIT;
  1556. }
  1557. //
  1558. // Either resolver is pending or already in progress,
  1559. // we have exclusive lock so we are safe to reference
  1560. // m_hExpertDisconnect.
  1561. //
  1562. if( UNKNOWN_LOGONID != m_ulHelperSessionId )
  1563. {
  1564. //
  1565. // LOGEVENT : SESSMGR_I_REMOTEASSISTANCE_USERALREADYHELP
  1566. //
  1567. _Module.LogSessmgrEventLog(
  1568. EVENTLOG_INFORMATION_TYPE,
  1569. SESSMGR_I_REMOTEASSISTANCE_USERALREADYHELP,
  1570. m_EventLogInfo.bstrNoviceDomain,
  1571. m_EventLogInfo.bstrNoviceAccount,
  1572. (IsUnsolicitedHelp())? g_URAString : g_RAString,
  1573. bstrExpertAddressFromClient,
  1574. bstrExpertAddressFromTSServer,
  1575. SAFERROR_HELPEEALREADYBEINGHELPED
  1576. );
  1577. *pResolverErrCode = SAFERROR_HELPEEALREADYBEINGHELPED;
  1578. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  1579. goto CLEANUPANDEXIT;
  1580. }
  1581. //
  1582. // We assume User is going to accept help
  1583. // 1) When expert disconnect before user accept/deny request,
  1584. // our service logoff notification can find this object and invoke
  1585. // OnDisconnect() into resolver.
  1586. // 2) If another expert connect with same ticket and resolver still
  1587. // pending response from user, we can bail out right away.
  1588. //
  1589. InterlockedExchange( (LPLONG)&m_ulHelperSessionId, (LONG)HelperSessionId );
  1590. //
  1591. // Cache the SID in object
  1592. //
  1593. m_HelpSessionOwnerSid = (CComBSTR)m_pHelpSession->m_UserSID;
  1594. hRes = CoInitialize( NULL );
  1595. if( FAILED(hRes) )
  1596. {
  1597. // failed to coinitialize,
  1598. *pResolverErrCode = SAFERROR_INTERNALERROR;
  1599. goto CLEANUPANDEXIT;
  1600. }
  1601. //
  1602. // Load resolver
  1603. hRes = LoadResolverFromGIT( &pIResolver );
  1604. if( SUCCEEDED(hRes) )
  1605. {
  1606. CComBSTR bstrResolverBlob;
  1607. bstrResolverBlob.Attach(resolverBlob);
  1608. sessionId = (long)m_ulLogonId;
  1609. DebugPrintf(
  1610. _TEXT("User Session ID %d\n"),
  1611. m_ulLogonId
  1612. );
  1613. //
  1614. // keep a copy of blob, we need this to send to resolver on
  1615. // disconnect, note, caller can pass its blob so we need to
  1616. // keep a copy of it.
  1617. //
  1618. if( bstrResolverBlob.Length() == 0 )
  1619. {
  1620. m_ResolverConnectBlob = (CComBSTR)m_pHelpSession->m_SessResolverBlob;
  1621. }
  1622. else
  1623. {
  1624. m_ResolverConnectBlob = bstrResolverBlob;
  1625. }
  1626. hRes = pIResolver->ResolveUserSessionID(
  1627. m_ResolverConnectBlob,
  1628. (CComBSTR)m_pHelpSession->m_UserSID,
  1629. expertBlob,
  1630. (CComBSTR)m_pHelpSession->m_SessionCreateBlob,
  1631. &sessionId,
  1632. CallerProcessId,
  1633. phHelpCtr,
  1634. &resolverRetCode
  1635. );
  1636. *pResolverErrCode = resolverRetCode;
  1637. bstrResolverBlob.Detach();
  1638. pIResolver->Release();
  1639. DebugPrintf(
  1640. _TEXT("Resolver returns 0x%08x\n"),
  1641. hRes
  1642. );
  1643. if( SUCCEEDED(hRes) )
  1644. {
  1645. *plUserSession = sessionId;
  1646. //
  1647. // Update session ID, take the value return from Resolver.
  1648. //
  1649. m_ulLogonId = sessionId;
  1650. //
  1651. // Add this expert to logoff monitor list, when expert session's
  1652. // rdsaddin terminates, we will inform resolver, reason for this
  1653. // is TS might not notify us of expert session disconnect because
  1654. // some system component popup a dialog in help assistant session
  1655. // and termsrv has no other way but to terminate entire session.
  1656. //
  1657. dwStatus = MonitorExpertLogoff(
  1658. CallerProcessId,
  1659. HelperSessionId,
  1660. m_bstrHelpSessionId
  1661. );
  1662. if( ERROR_SUCCESS != dwStatus )
  1663. {
  1664. //
  1665. // If we can't add to resolver list, we immediate notify
  1666. // resolver and return error or we will run into 'helpee
  1667. // already been help problem
  1668. //
  1669. DebugPrintf(
  1670. _TEXT("MonitorExpertLogoff() failed with %d\n"), dwStatus
  1671. );
  1672. // directly invoke resolver here.
  1673. hRes = pIResolver->OnDisconnect(
  1674. m_ResolverConnectBlob,
  1675. m_HelpSessionOwnerSid,
  1676. m_ulLogonId
  1677. );
  1678. MYASSERT( SUCCEEDED(hRes) );
  1679. resolverRetCode = SAFERROR_UNKNOWNSESSMGRERROR;
  1680. }
  1681. else
  1682. {
  1683. //
  1684. // It is possible for caller to close all reference counter to our object
  1685. // and cause a release of our object, if SCM notification comes in after
  1686. // our object is deleted from cache, SCM will reload from database entry
  1687. // and that does not have helper session ID and will not invoke NotifyDisconnect().
  1688. //
  1689. AddRef();
  1690. }
  1691. }
  1692. else
  1693. {
  1694. //
  1695. // User does not accept help from this helpassistant session,
  1696. // reset HelpAssistant session ID
  1697. //
  1698. InterlockedExchange( (LPLONG)&m_ulHelperSessionId, (LONG)UNKNOWN_LOGONID );
  1699. }
  1700. switch( resolverRetCode )
  1701. {
  1702. case SAFERROR_NOERROR :
  1703. // LOGEVENT : SESSMGR_I_REMOTEASSISTANCE_BEGIN
  1704. //
  1705. // Cache event log info so we don't have to retrieve it again.
  1706. //
  1707. m_EventLogInfo.bstrExpertIpAddressFromClient = bstrExpertAddressFromClient;
  1708. m_EventLogInfo.bstrExpertIpAddressFromServer = bstrExpertAddressFromTSServer;
  1709. dwEventLogCode = SESSMGR_I_REMOTEASSISTANCE_BEGIN;
  1710. break;
  1711. case SAFERROR_HELPEECONSIDERINGHELP:
  1712. case SAFERROR_HELPEEALREADYBEINGHELPED:
  1713. // LOGEVENT : SESSMGR_I_REMOTEASSISTANCE_USERALREADYHELP
  1714. dwEventLogCode = SESSMGR_I_REMOTEASSISTANCE_USERALREADYHELP;
  1715. break;
  1716. case SAFERROR_HELPEENOTFOUND:
  1717. // LOGEVENT : SESSMGR_I_REMOTEASSISTANCE_INACTIVEUSER
  1718. dwEventLogCode = SESSMGR_I_REMOTEASSISTANCE_INACTIVEUSER;
  1719. break;
  1720. case SAFERROR_HELPEENEVERRESPONDED:
  1721. // LOGEVENT : SESSMGR_I_REMOTEASSISTANCE_TIMEOUT
  1722. dwEventLogCode = SESSMGR_I_REMOTEASSISTANCE_TIMEOUT;
  1723. break;
  1724. case SAFERROR_HELPEESAIDNO:
  1725. // LOGEVENT : SESSMGR_I_REMOTEASSISTANCE_USERREJECT
  1726. dwEventLogCode = SESSMGR_I_REMOTEASSISTANCE_USERREJECT;
  1727. break;
  1728. default:
  1729. // LOGEVENT : SESSMGR_I_REMOTEASSISTANCE_UNKNOWNRESOLVERERRORCODE
  1730. dwEventLogCode = SESSMGR_I_REMOTEASSISTANCE_UNKNOWNRESOLVERERRORCODE;
  1731. break;
  1732. }
  1733. _Module.LogSessmgrEventLog(
  1734. EVENTLOG_INFORMATION_TYPE,
  1735. dwEventLogCode,
  1736. m_EventLogInfo.bstrNoviceDomain,
  1737. m_EventLogInfo.bstrNoviceAccount,
  1738. (IsUnsolicitedHelp())? g_URAString : g_RAString,
  1739. bstrExpertAddressFromClient,
  1740. bstrExpertAddressFromTSServer,
  1741. resolverRetCode
  1742. );
  1743. }
  1744. else
  1745. {
  1746. *pResolverErrCode = SAFERROR_CANTOPENRESOLVER;
  1747. }
  1748. CoUninitialize();
  1749. CLEANUPANDEXIT:
  1750. DebugPrintf(
  1751. _TEXT("ResolverUserSession returns 0x%08x\n"),
  1752. hRes
  1753. );
  1754. return hRes;
  1755. }
  1756. HRESULT
  1757. CRemoteDesktopHelpSession::NotifyDisconnect()
  1758. /*++
  1759. Routine Description:
  1760. Notify Session Resolver that client is dis-connecting to help session.
  1761. Parameters:
  1762. bstrBlob : Blob to be passed to resolver, NULL if
  1763. use ResolverBlob property.
  1764. Returns:
  1765. E_HANDLE Invalid session, database entry has been deleted but refcount > 0
  1766. E_UNEXPECTED Internal error
  1767. HRESULT_FROM_WIN32( ERROR_VC_DISCONNECTED ) Client disconnected
  1768. HRESULT_FROM_WIN32( ERROR_NO_ASSOCIATION ) No Resolver
  1769. S_FALSE No Resolver
  1770. HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) Invalid Resolver ID
  1771. Error code from CoCreateInstance() and resolver's OnConnect() method.
  1772. --*/
  1773. {
  1774. HRESULT hRes = S_OK;
  1775. ISAFRemoteDesktopCallback* pIResolver;
  1776. DebugPrintf(
  1777. _TEXT("OnDisconnect() - Helper Session ID %d\n"),
  1778. m_ulHelperSessionId
  1779. );
  1780. CCriticalSectionLocker l(m_HelpSessionLock);
  1781. //
  1782. // If we are not been help, just bail out.
  1783. //
  1784. if( UNKNOWN_LOGONID != m_ulHelperSessionId )
  1785. {
  1786. //
  1787. // LOGEVENT : SESSMGR_I_REMOTEASSISTANCE_END
  1788. //
  1789. //
  1790. // always cache help session creator at ResolveUserSession()
  1791. // so this value can't be empty.
  1792. //
  1793. MYASSERT( m_HelpSessionOwnerSid.Length() > 0 );
  1794. MYASSERT( m_ResolverConnectBlob.Length() > 0 );
  1795. if( m_HelpSessionOwnerSid.Length() == 0 ||
  1796. m_ResolverConnectBlob.Length() == 0 )
  1797. {
  1798. MYASSERT(FALSE);
  1799. hRes = E_UNEXPECTED;
  1800. goto CLEANUPANDEXIT;
  1801. }
  1802. hRes = CoInitialize( NULL );
  1803. if( FAILED(hRes) )
  1804. {
  1805. goto CLEANUPANDEXIT;
  1806. }
  1807. //
  1808. // Load resolver
  1809. hRes = LoadResolverFromGIT( &pIResolver );
  1810. MYASSERT( SUCCEEDED(hRes) );
  1811. if( SUCCEEDED(hRes) )
  1812. {
  1813. DebugPrintf(
  1814. _TEXT("OnDisconnect() - Notify Resolver, %s\n%s\n%d\n"),
  1815. m_ResolverConnectBlob,
  1816. m_HelpSessionOwnerSid,
  1817. m_ulLogonId
  1818. );
  1819. hRes = pIResolver->OnDisconnect(
  1820. m_ResolverConnectBlob,
  1821. m_HelpSessionOwnerSid,
  1822. m_ulLogonId
  1823. );
  1824. pIResolver->Release();
  1825. m_ResolverConnectBlob.Empty();
  1826. m_HelpSessionOwnerSid.Empty();
  1827. InterlockedExchange( (LPLONG)&m_ulHelperSessionId, (LONG)UNKNOWN_LOGONID );
  1828. //
  1829. // It is possible for caller to close all reference counter to our object
  1830. // and cause a release of our object, if SCM notification comes in after
  1831. // our object is deleted from cache, SCM will reload from database entry
  1832. // and that does not have helper session ID and will not invoke NotifyDisconnect().
  1833. //
  1834. Release();
  1835. _Module.LogSessmgrEventLog(
  1836. EVENTLOG_INFORMATION_TYPE,
  1837. SESSMGR_I_REMOTEASSISTANCE_END,
  1838. m_EventLogInfo.bstrNoviceDomain,
  1839. m_EventLogInfo.bstrNoviceAccount,
  1840. (IsUnsolicitedHelp())? g_URAString : g_RAString,
  1841. m_EventLogInfo.bstrExpertIpAddressFromClient,
  1842. m_EventLogInfo.bstrExpertIpAddressFromServer,
  1843. ERROR_SUCCESS
  1844. );
  1845. }
  1846. CoUninitialize();
  1847. }
  1848. CLEANUPANDEXIT:
  1849. return hRes;
  1850. }
  1851. STDMETHODIMP
  1852. CRemoteDesktopHelpSession::EnableUserSessionRdsSetting(
  1853. IN BOOL bEnable
  1854. )
  1855. /*++
  1856. Routine Description:
  1857. Enable/restore user session shadow setting.
  1858. --*/
  1859. {
  1860. HRESULT hRes = S_OK;
  1861. CCriticalSectionLocker l(m_HelpSessionLock);
  1862. if( FALSE == IsSessionValid() )
  1863. {
  1864. hRes = E_HANDLE;
  1865. }
  1866. else
  1867. {
  1868. if( TRUE == bEnable )
  1869. {
  1870. hRes = ActivateSessionRDSSetting();
  1871. }
  1872. else
  1873. {
  1874. hRes = ResetSessionRDSSetting();
  1875. }
  1876. }
  1877. return hRes;
  1878. }
  1879. HRESULT
  1880. CRemoteDesktopHelpSession::ActivateSessionRDSSetting()
  1881. {
  1882. HRESULT hRes = S_OK;
  1883. DWORD dwStatus;
  1884. REMOTE_DESKTOP_SHARING_CLASS userRDSDefault;
  1885. BOOL bAllowToGetHelp;
  1886. MYASSERT( TRUE == IsSessionValid() );
  1887. //
  1888. // check if help session user is logon
  1889. //
  1890. if( UNKNOWN_LOGONID == m_ulLogonId )
  1891. {
  1892. hRes = HRESULT_FROM_WIN32( ERROR_VC_DISCONNECTED );
  1893. goto CLEANUPANDEXIT;
  1894. }
  1895. //
  1896. // Make sure user can get help, this is possible since
  1897. // policy might change after user re-logon to help session
  1898. //
  1899. hRes = get_AllowToGetHelp( &bAllowToGetHelp );
  1900. if( FAILED(hRes) )
  1901. {
  1902. goto CLEANUPANDEXIT;
  1903. }
  1904. if( FALSE == bAllowToGetHelp )
  1905. {
  1906. hRes = HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED );
  1907. goto CLEANUPANDEXIT;
  1908. }
  1909. //
  1910. // Retrieve current user session's shadow setting.
  1911. //
  1912. dwStatus = GetUserRDSLevel( m_ulLogonId, &userRDSDefault );
  1913. if( ERROR_SUCCESS != dwStatus )
  1914. {
  1915. hRes = HRESULT_FROM_WIN32( dwStatus );
  1916. goto CLEANUPANDEXIT;
  1917. }
  1918. if( NO_DESKTOP_SHARING != userRDSDefault )
  1919. {
  1920. //
  1921. // Force reset on user session shadow setting only if
  1922. // user session is allowed remote control.
  1923. //
  1924. dwStatus = ConfigUserSessionRDSLevel( m_ulLogonId, m_pHelpSession->m_SessionRdsSetting );
  1925. hRes = HRESULT_FROM_WIN32( dwStatus );
  1926. DebugPrintf(
  1927. _TEXT("ConfigUserSessionRDSLevel to %d returns 0x%08x\n"),
  1928. (DWORD)m_pHelpSession->m_SessionRdsSetting,
  1929. hRes
  1930. );
  1931. }
  1932. else
  1933. {
  1934. // return S_FALSE and let shadow fail
  1935. hRes = S_FALSE;
  1936. DebugPrintf( _TEXT("TS User session does not remote control\n") );
  1937. }
  1938. CLEANUPANDEXIT:
  1939. return hRes;
  1940. }
  1941. HRESULT
  1942. CRemoteDesktopHelpSession::ResetSessionRDSSetting()
  1943. {
  1944. HRESULT hRes = S_OK;
  1945. MYASSERT( TRUE == IsSessionValid() );
  1946. //
  1947. // check if user is log on
  1948. //
  1949. if( UNKNOWN_LOGONID == m_ulLogonId )
  1950. {
  1951. hRes = HRESULT_FROM_WIN32( ERROR_VC_DISCONNECTED );
  1952. }
  1953. //
  1954. // We don't do anything since TermSrv will reset shadow
  1955. // config back to original value if shadower is help
  1956. // assistant.
  1957. //
  1958. CLEANUPANDEXIT:
  1959. return hRes;
  1960. }
  1961. ///////////////////////////////////////////////////////////////
  1962. //
  1963. // Private Function
  1964. //
  1965. HRESULT
  1966. CRemoteDesktopHelpSession::put_UserLogonId(
  1967. IN long newVal
  1968. )
  1969. /*++
  1970. Routine Description:
  1971. Set user TS session for current Help Session
  1972. Parameters:
  1973. newVal : New TS user session
  1974. Returns:
  1975. S_OK
  1976. --*/
  1977. {
  1978. HRESULT hRes = S_OK;
  1979. CCriticalSectionLocker l(m_HelpSessionLock);
  1980. if( FALSE == IsSessionValid() )
  1981. {
  1982. hRes = E_HANDLE;
  1983. }
  1984. else if( NULL != m_pHelpSession )
  1985. {
  1986. //MYASSERT( UNKNOWN_LOGONID == m_ulLogonId );
  1987. //
  1988. // User TS session ID is not persisted to registry
  1989. //
  1990. m_ulLogonId = newVal;
  1991. }
  1992. else
  1993. {
  1994. hRes = E_UNEXPECTED;
  1995. }
  1996. // private routine, assert if failed
  1997. MYASSERT( SUCCEEDED(hRes) );
  1998. return hRes;
  1999. }
  2000. BOOL
  2001. CRemoteDesktopHelpSession::IsEqualSid(
  2002. IN const CComBSTR& bstrSid
  2003. )
  2004. /*++
  2005. Routine Description:
  2006. Compare user's SID.
  2007. Parameters:
  2008. bstrSid : SID to be compared.
  2009. Returns:
  2010. TRUE/FALSE
  2011. --*/
  2012. {
  2013. CCriticalSectionLocker l(m_HelpSessionLock);
  2014. if( NULL == m_pHelpSession )
  2015. {
  2016. MYASSERT(FALSE);
  2017. return FALSE;
  2018. }
  2019. return (TRUE == IsSessionValid()) ? ((CComBSTR)m_pHelpSession->m_UserSID == bstrSid) : FALSE;
  2020. }
  2021. BOOL
  2022. CRemoteDesktopHelpSession::VerifyUserSession(
  2023. IN const CComBSTR& bstrUserSid,
  2024. IN const CComBSTR& bstrSessPwd
  2025. )
  2026. /*++
  2027. Routine Description:
  2028. Verify user help session password.
  2029. Parameters:
  2030. bstrUserSid : calling client's user SID.
  2031. bstrSessName : Help session name, not use currently.
  2032. bstrSessPwd : Help Session Password to be verified.
  2033. Returns:
  2034. TRUE/FALSE
  2035. --*/
  2036. {
  2037. DWORD dwStatus;
  2038. BOOL bReturn = FALSE;
  2039. CCriticalSectionLocker l(m_HelpSessionLock);
  2040. if( NULL == m_pHelpSession )
  2041. {
  2042. MYASSERT(FALSE);
  2043. goto CLEANUPANDEXIT;
  2044. }
  2045. #if DISABLESECURITYCHECKS
  2046. if( (CComBSTR)m_pHelpSession->m_SessionName == HELPSESSION_UNSOLICATED )
  2047. {
  2048. // use console session
  2049. m_ulLogonId = 0;
  2050. }
  2051. #endif
  2052. if( FALSE == IsSessionValid() )
  2053. {
  2054. // Help Session is invalid
  2055. goto CLEANUPANDEXIT;
  2056. }
  2057. bReturn = TRUE;
  2058. CLEANUPANDEXIT:
  2059. return bReturn;
  2060. }
  2061. HRESULT
  2062. CRemoteDesktopHelpSession::InitInstance(
  2063. IN CRemoteDesktopHelpSessionMgr* pMgr,
  2064. IN CComBSTR& bstrClientSid,
  2065. IN PHELPENTRY pHelpEntry
  2066. )
  2067. /*++
  2068. Routine Description:
  2069. Initialize a CRemoteDesktopHelpSession object.
  2070. Parameters:
  2071. Returns:
  2072. S_OK
  2073. --*/
  2074. {
  2075. HRESULT hRes = S_OK;
  2076. if( NULL != pHelpEntry )
  2077. {
  2078. m_pSessMgr = pMgr;
  2079. m_pHelpSession = pHelpEntry;
  2080. m_bstrClientSid = bstrClientSid;
  2081. m_bstrHelpSessionId = pHelpEntry->m_SessionId;
  2082. }
  2083. else
  2084. {
  2085. hRes = HRESULT_FROM_WIN32( ERROR_INTERNAL_ERROR );
  2086. MYASSERT( SUCCEEDED(hRes) );
  2087. }
  2088. return hRes;
  2089. }
  2090. HRESULT
  2091. CRemoteDesktopHelpSession::CreateInstance(
  2092. IN CRemoteDesktopHelpSessionMgr* pMgr,
  2093. IN CComBSTR& bstrClientSid,
  2094. IN PHELPENTRY pHelpEntry,
  2095. OUT RemoteDesktopHelpSessionObj** ppRemoteDesktopHelpSession
  2096. )
  2097. /*++
  2098. Routine Description:
  2099. Create an instance of help session.
  2100. Parameters:
  2101. pMgr : Pointer to help session manager object.
  2102. ppRemoteDesktopHelpSession : Return a pointer to help session instance.
  2103. Returns:
  2104. S_OK
  2105. E_OUTOFMEMORY
  2106. Error code in impersonating client
  2107. --*/
  2108. {
  2109. HRESULT hRes = S_OK;
  2110. RemoteDesktopHelpSessionObj* p = NULL;
  2111. hRes = RemoteDesktopHelpSessionObj::CreateInstance( &p );
  2112. if( SUCCEEDED(hRes) )
  2113. {
  2114. hRes = p->InitInstance(
  2115. pMgr,
  2116. bstrClientSid,
  2117. pHelpEntry
  2118. );
  2119. if( SUCCEEDED(hRes) )
  2120. {
  2121. p->AddRef();
  2122. *ppRemoteDesktopHelpSession = p;
  2123. }
  2124. else
  2125. {
  2126. p->Release();
  2127. }
  2128. }
  2129. return hRes;
  2130. }
  2131. HRESULT
  2132. CRemoteDesktopHelpSession::BeginUpdate()
  2133. {
  2134. HRESULT hRes;
  2135. MYASSERT( NULL != m_pHelpSession );
  2136. if( NULL != m_pHelpSession )
  2137. {
  2138. hRes = m_pHelpSession->BeginUpdate();
  2139. }
  2140. else
  2141. {
  2142. hRes = E_UNEXPECTED;
  2143. }
  2144. return hRes;
  2145. }
  2146. HRESULT
  2147. CRemoteDesktopHelpSession::CommitUpdate()
  2148. {
  2149. HRESULT hRes;
  2150. //
  2151. // Update all entries.
  2152. //
  2153. MYASSERT( NULL != m_pHelpSession );
  2154. if( NULL != m_pHelpSession )
  2155. {
  2156. hRes = m_pHelpSession->CommitUpdate();
  2157. }
  2158. else
  2159. {
  2160. hRes = E_UNEXPECTED;
  2161. }
  2162. return hRes;
  2163. }
  2164. HRESULT
  2165. CRemoteDesktopHelpSession::AbortUpdate()
  2166. {
  2167. HRESULT hRes;
  2168. //
  2169. // Update all entries.
  2170. //
  2171. MYASSERT( NULL != m_pHelpSession );
  2172. if( NULL != m_pHelpSession )
  2173. {
  2174. hRes = m_pHelpSession->AbortUpdate();
  2175. }
  2176. else
  2177. {
  2178. hRes = E_UNEXPECTED;
  2179. }
  2180. return hRes;
  2181. }
  2182. BOOL
  2183. CRemoteDesktopHelpSession::IsHelpSessionExpired()
  2184. {
  2185. MYASSERT( NULL != m_pHelpSession );
  2186. return (NULL != m_pHelpSession) ? m_pHelpSession->IsEntryExpired() : TRUE;
  2187. }
  2188. BOOL
  2189. CRemoteDesktopHelpSession::IsClientSessionCreator()
  2190. {
  2191. BOOL bStatus;
  2192. //
  2193. // NOTE: This function checks to make sure the caller is the user that
  2194. // created the Help Session. For Whistler, we enforce that Help
  2195. // Sessions only be created by apps running as SYSTEM. Once
  2196. // created, the creating app can pass the object to any other app
  2197. // running in any other context. This function will get in the
  2198. // way of this capability so it simply returns TRUE for now.
  2199. //
  2200. return TRUE;
  2201. if( m_pHelpSession )
  2202. {
  2203. bStatus = (/* (CComBSTR) */m_pHelpSession->m_UserSID == m_bstrClientSid);
  2204. if( FALSE == bStatus )
  2205. {
  2206. bStatus = (m_pHelpSession->m_UserSID == g_LocalSystemSID);
  2207. }
  2208. }
  2209. else
  2210. {
  2211. bStatus = FALSE;
  2212. }
  2213. return bStatus;
  2214. }