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.

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