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.

1070 lines
24 KiB

  1. /************************************************************************
  2. Copyright (c) 2000 - 2000 Microsoft Corporation
  3. Module Name :
  4. logontable.cpp
  5. Abstract :
  6. Source file for the logon table.
  7. Author :
  8. Revision History :
  9. ***********************************************************************/
  10. #include "stdafx.h"
  11. #include <winsta.h>
  12. #include <wtsapi32.h>
  13. #include <userenv.h>
  14. #if !defined(BITS_V12_ON_NT4)
  15. #include "logontable.tmh"
  16. #endif
  17. HRESULT DetectTerminalServer( bool * pfTS );
  18. HRESULT
  19. GetUserToken(
  20. ULONG LogonId,
  21. PHANDLE pUserToken
  22. );
  23. HRESULT
  24. WaitForUserToken(
  25. DWORD session,
  26. HANDLE * pToken
  27. )
  28. {
  29. const MaxWait = 30 * 1000;
  30. const WaitInterval = 500;
  31. long StartTime = GetTickCount();
  32. HRESULT Hr = E_FAIL;
  33. do
  34. {
  35. Hr = GetUserToken( session, pToken );
  36. if ( SUCCEEDED( Hr ) )
  37. return Hr;
  38. LogError("logon : unable to get token : %!winerr!", Hr );
  39. Sleep( WaitInterval );
  40. }
  41. while ( GetTickCount() - StartTime < MaxWait );
  42. return Hr;
  43. }
  44. CLoggedOnUsers::CLoggedOnUsers(
  45. TaskScheduler & sched
  46. ) : m_TaskScheduler( sched ),
  47. m_SensNotifier( NULL )
  48. {
  49. FILETIME time;
  50. GetSystemTimeAsFileTime( &time );
  51. m_CurrentCookie = time.dwLowDateTime;
  52. if ( WINDOWS2000_PLATFORM == g_PlatformVersion )
  53. {
  54. try
  55. {
  56. bool fTS;
  57. THROW_HRESULT( DetectTerminalServer( &fTS ));
  58. if (fTS)
  59. {
  60. m_SensNotifier = new CTerminalServerLogonNotification;
  61. LogInfo( "TS-enabled SENS notification activated" );
  62. }
  63. else
  64. {
  65. m_SensNotifier = new CLogonNotification;
  66. LogInfo( "regular SENS notification activated" );
  67. }
  68. }
  69. catch( ComError Error )
  70. {
  71. if ( Error.Error() == TYPE_E_CANTLOADLIBRARY ||
  72. Error.Error() == TYPE_E_LIBNOTREGISTERED )
  73. {
  74. LogInfo( "SENS doesn't exist on this platform, skipping" );
  75. return;
  76. }
  77. else
  78. {
  79. LogInfo("SENS object failed with %x", Error.Error() );
  80. throw;
  81. }
  82. }
  83. }
  84. }
  85. CLoggedOnUsers::~CLoggedOnUsers()
  86. {
  87. if (m_SensNotifier)
  88. {
  89. m_SensNotifier->DeRegisterNotification();
  90. m_SensNotifier->Release();
  91. }
  92. }
  93. HRESULT
  94. CLoggedOnUsers::LogonSession(
  95. DWORD session
  96. )
  97. {
  98. CUser * user = NULL;
  99. try
  100. {
  101. HANDLE Token = NULL;
  102. auto_HANDLE<NULL> AutoToken;
  103. //
  104. // Get the user's token and SID, then create a user object.
  105. //
  106. THROW_HRESULT( WaitForUserToken( session, &Token ));
  107. ASSERT( Token ); // Token can't be NULL
  108. AutoToken = Token;
  109. user = new CUser( Token );
  110. //
  111. // Add the user to our by-session and by-SID indexes.
  112. //
  113. HoldWriterLock lock ( m_TaskScheduler );
  114. try
  115. {
  116. // Just in case...delete any previously recorded user.
  117. //
  118. LogoffSession( session );
  119. //
  120. // Subtlety: if the node for m_ActiveSessions[ session ] doesn't exist,
  121. // then the first reference to it will cause a node to be allocated. This may
  122. // throw E_OUTOFMEMORY.
  123. //
  124. m_ActiveSessions[ session ] = user;
  125. m_ActiveUsers.insert( make_pair( user->QuerySid(), user ) );
  126. }
  127. catch( ComError Error )
  128. {
  129. m_ActiveSessions.erase( session );
  130. throw;
  131. }
  132. Dump();
  133. g_Manager->UserLoggedOn( user->QuerySid() );
  134. return S_OK;
  135. }
  136. catch( ComError err )
  137. {
  138. delete user;
  139. LogError("logon : returning error 0x%x", err.Error() );
  140. Dump();
  141. return err.Error();
  142. }
  143. }
  144. HRESULT
  145. CLoggedOnUsers::LogoffSession(
  146. DWORD session
  147. )
  148. {
  149. try
  150. {
  151. HoldWriterLock lock ( m_TaskScheduler );
  152. CUser * user = m_ActiveSessions[ session ];
  153. if (!user)
  154. return S_OK;
  155. bool b = m_ActiveUsers.RemovePair( user->QuerySid(), user );
  156. ASSERT( b );
  157. m_ActiveSessions.erase( session );
  158. Dump();
  159. if (false == g_Manager->IsUserLoggedOn( user->QuerySid() ))
  160. {
  161. g_Manager->UserLoggedOff( user->QuerySid() );
  162. }
  163. user->DecrementRefCount();
  164. return S_OK;
  165. }
  166. catch( ComError err )
  167. {
  168. LogWarning("logoff : exception 0x%x thrown", err.Error());
  169. Dump();
  170. return err.Error();
  171. }
  172. }
  173. CUser *
  174. CLoggedOnUsers::CUserList::FindSid(
  175. SidHandle sid
  176. )
  177. {
  178. iterator iter = find( sid );
  179. if (iter == end())
  180. {
  181. return NULL;
  182. }
  183. return iter->second;
  184. }
  185. bool
  186. CLoggedOnUsers::CUserList::RemovePair(
  187. SidHandle sid,
  188. CUser * user
  189. )
  190. {
  191. //
  192. // Find the user in the user list and delete it.
  193. //
  194. pair<iterator, iterator> b = equal_range( sid );
  195. for (iterator i = b.first; i != b.second; ++i)
  196. {
  197. if (i->second == user)
  198. {
  199. erase( i );
  200. return true;
  201. }
  202. }
  203. return false;
  204. }
  205. CUser *
  206. CLoggedOnUsers::CUserList::RemoveByCookie(
  207. SidHandle sid,
  208. DWORD cookie
  209. )
  210. {
  211. //
  212. // Find the user in the user list and delete it.
  213. //
  214. pair<iterator, iterator> b = equal_range( sid );
  215. for (iterator i = b.first; i != b.second; ++i)
  216. {
  217. CUser * user = i->second;
  218. if (user->GetCookie() == cookie)
  219. {
  220. erase( i );
  221. return user;
  222. }
  223. }
  224. return NULL;
  225. }
  226. HRESULT
  227. CLoggedOnUsers::LogonService(
  228. HANDLE Token,
  229. DWORD * pCookie
  230. )
  231. {
  232. CUser * user = NULL;
  233. try
  234. {
  235. user = new CUser( Token );
  236. *pCookie = InterlockedIncrement( &m_CurrentCookie );
  237. user->SetCookie( *pCookie );
  238. HoldWriterLock lock ( m_TaskScheduler );
  239. m_ActiveServiceAccounts.insert( make_pair( user->QuerySid(), user ));
  240. return S_OK;
  241. }
  242. catch( ComError err )
  243. {
  244. delete user;
  245. LogError("logon service : returning error 0x%x", err.Error() );
  246. return err.Error();
  247. }
  248. }
  249. HRESULT
  250. CLoggedOnUsers::LogoffService(
  251. SidHandle Sid,
  252. DWORD Cookie
  253. )
  254. {
  255. try
  256. {
  257. HoldWriterLock lock ( m_TaskScheduler );
  258. CUser * user = m_ActiveServiceAccounts.RemoveByCookie( Sid, Cookie );
  259. if (!user)
  260. {
  261. LogWarning("logoff : invalid cookie %d", Cookie);
  262. return E_INVALIDARG;
  263. }
  264. user->DecrementRefCount();
  265. return S_OK;
  266. }
  267. catch( ComError err)
  268. {
  269. LogWarning("logoff : exception 0x%x thrown", err.Error());
  270. return err.Error();
  271. }
  272. }
  273. HRESULT
  274. CLoggedOnUsers::AddServiceAccounts()
  275. {
  276. HRESULT hr = S_OK;
  277. DWORD ignore;
  278. HoldWriterLock lock ( m_TaskScheduler );
  279. //
  280. // Add the LOCAL_SYSTEM account.
  281. //
  282. HANDLE Token;
  283. if (OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &Token ))
  284. {
  285. hr = LogonService( Token, &ignore );
  286. CloseHandle( Token );
  287. }
  288. else
  289. {
  290. hr = HRESULT_FROM_WIN32( GetLastError() );
  291. }
  292. if (FAILED(hr))
  293. {
  294. LogWarning( "failed to register LocalSystem : %!winerr!", hr );
  295. return hr;
  296. }
  297. if (g_PlatformVersion >= WINDOWSXP_PLATFORM)
  298. {
  299. //
  300. // Add the LocalService account.
  301. //
  302. if (LogonUser( L"LocalService",
  303. L"NT AUTHORITY",
  304. L"",
  305. LOGON32_LOGON_SERVICE,
  306. LOGON32_PROVIDER_DEFAULT,
  307. &Token))
  308. {
  309. hr = LogonService( Token, &ignore );
  310. CloseHandle( Token );
  311. }
  312. else
  313. {
  314. hr = HRESULT_FROM_WIN32( GetLastError() );
  315. }
  316. if (FAILED(hr))
  317. {
  318. LogWarning( "failed to register LocalService : %!winerr!", hr );
  319. if ( HRESULT_FROM_WIN32( ERROR_LOGON_FAILURE ) == hr )
  320. LogWarning( "LocalService doesn't exist, skip it.\n");
  321. else
  322. return hr;
  323. }
  324. //
  325. // Add the NetworkService account.
  326. //
  327. if (LogonUser( L"NetworkService",
  328. L"NT AUTHORITY",
  329. L"",
  330. LOGON32_LOGON_SERVICE,
  331. LOGON32_PROVIDER_DEFAULT,
  332. &Token))
  333. {
  334. hr = LogonService( Token, &ignore );
  335. CloseHandle( Token );
  336. }
  337. else
  338. {
  339. hr = HRESULT_FROM_WIN32( GetLastError() );
  340. }
  341. if (FAILED(hr))
  342. {
  343. LogWarning( "failed to register NetworkService : %!winerr!", hr );
  344. if ( HRESULT_FROM_WIN32( ERROR_LOGON_FAILURE ) == hr )
  345. LogWarning( "NetworkService doesn't exist, skip it.\n");
  346. else
  347. return hr;
  348. }
  349. }
  350. //
  351. // done
  352. //
  353. return S_OK;
  354. }
  355. HRESULT
  356. CLoggedOnUsers::AddActiveUsers()
  357. {
  358. HRESULT hr = S_OK;
  359. WTS_SESSION_INFO * SessionInfo = 0;
  360. HANDLE Token;
  361. HoldWriterLock lock ( m_TaskScheduler );
  362. //
  363. // Get the console token, if any, without using Terminal Services.
  364. //
  365. if ( SUCCEEDED( GetUserToken( 0, &Token) ) )
  366. {
  367. CloseHandle( Token );
  368. hr = LogonSession( 0 );
  369. if (FAILED(hr))
  370. {
  371. // ignore it and try to carry on...
  372. LogWarning( "service : unable to logon session zero : %!winerr!", hr );
  373. }
  374. }
  375. #if !defined( BITS_V12_ON_NT4 )
  376. //
  377. // The call may return FALSE, because Terminal Services is not always loaded.
  378. //
  379. DWORD SessionCount = 0;
  380. BOOL b = WTSEnumerateSessions( WTS_CURRENT_SERVER_HANDLE,
  381. 0, // reserved
  382. 1, // version 1 is the only supported v.
  383. &SessionInfo,
  384. &SessionCount
  385. );
  386. if (b)
  387. {
  388. int i;
  389. for (i=0; i < SessionCount; ++i)
  390. {
  391. if (SessionInfo[i].SessionId == 0)
  392. {
  393. // console was handled by GetCurrentUserToken.
  394. continue;
  395. }
  396. if (SessionInfo[i].State == WTSActive ||
  397. SessionInfo[i].State == WTSDisconnected)
  398. {
  399. LogInfo("service : logon session %d, state %d",
  400. SessionInfo[i].SessionId,
  401. SessionInfo[i].State );
  402. hr = LogonSession( SessionInfo[i].SessionId );
  403. if (FAILED(hr))
  404. {
  405. // ignore it and try to carry on...
  406. LogWarning( "service : unable to logon session %d : %!winerr!",
  407. SessionInfo[i].SessionId,
  408. hr );
  409. }
  410. }
  411. }
  412. }
  413. if (SessionInfo)
  414. {
  415. WTSFreeMemory( SessionInfo );
  416. }
  417. //
  418. // Now that the current population is recorded, keep abreast of changes.
  419. //
  420. if (m_SensNotifier)
  421. {
  422. m_SensNotifier->SetEnableState( true );
  423. }
  424. #endif
  425. return S_OK;
  426. }
  427. CUser *
  428. CLoggedOnUsers::FindUser(
  429. SidHandle sid,
  430. DWORD session
  431. )
  432. {
  433. HoldReaderLock lock ( m_TaskScheduler );
  434. CUser * user = 0;
  435. //
  436. // Look for a session with the right user.
  437. //
  438. if (session == ANY_SESSION)
  439. {
  440. user = m_ActiveUsers.FindSid( sid );
  441. }
  442. else
  443. {
  444. try
  445. {
  446. user = m_ActiveSessions[ session ];
  447. if (user && user->QuerySid() != sid)
  448. {
  449. user = 0;
  450. }
  451. }
  452. catch( ComError Error )
  453. {
  454. user = 0;
  455. }
  456. }
  457. //
  458. // Look in the service account list, if the session is compatible.
  459. //
  460. if (!user && (session == 0 || session == ANY_SESSION))
  461. {
  462. user = m_ActiveServiceAccounts.FindSid( sid );
  463. }
  464. if (user)
  465. {
  466. user->IncrementRefCount();
  467. }
  468. return user;
  469. }
  470. void CLoggedOnUsers::Dump()
  471. {
  472. HoldReaderLock lock ( m_TaskScheduler );
  473. LogInfo("sessions:");
  474. m_ActiveSessions.Dump();
  475. LogInfo("users:");
  476. m_ActiveUsers.Dump();
  477. LogInfo("service accounts:");
  478. m_ActiveServiceAccounts.Dump();
  479. }
  480. void CLoggedOnUsers::CSessionList::Dump()
  481. {
  482. for (iterator iter = begin(); iter != end(); ++iter)
  483. {
  484. LogInfo(" session %d user %p", iter->first, iter->second);
  485. }
  486. }
  487. void CLoggedOnUsers::CUserList::Dump()
  488. {
  489. for (iterator iter = begin(); iter != end(); ++iter)
  490. {
  491. if (iter->second)
  492. {
  493. (iter->second)->Dump();
  494. }
  495. }
  496. }
  497. CLoggedOnUsers::CUserList::~CUserList()
  498. {
  499. iterator iter;
  500. while ((iter=begin()) != end())
  501. {
  502. delete iter->second;
  503. erase( iter );
  504. }
  505. }
  506. void CUser::Dump()
  507. {
  508. LogInfo( " user at %p:", this);
  509. LogInfo( " %d refs, sid %!sid!", _ReferenceCount, _Sid.get());
  510. }
  511. long CUser::IncrementRefCount()
  512. {
  513. long count = InterlockedIncrement( & _ReferenceCount );
  514. LogRef("refs %d", count);
  515. return count;
  516. }
  517. long CUser::DecrementRefCount()
  518. {
  519. long count = InterlockedDecrement( & _ReferenceCount );
  520. LogRef("refs %d", count);
  521. if (0 == count)
  522. {
  523. delete this;
  524. }
  525. return count;
  526. }
  527. CUser::CUser(
  528. HANDLE Token
  529. )
  530. /*++
  531. Routine Description:
  532. Initializes a new CUser.
  533. At entry:
  534. <Sid> points to the user's SID.
  535. <Token> points to the user's token. It can be an impersonation or primary token.
  536. <phr> points to an error-return variable.
  537. At exit:
  538. The CUser is set up. The caller can delete <Sid> and <Token> if it wants to.
  539. if an error occurs, it is mapped to an HRESULT and written to <phr>.
  540. otherwise <*phr> is untouched and the CUser is ready for use.
  541. --*/
  542. {
  543. _ReferenceCount = 1;
  544. _Sid = CopyTokenSid( Token );
  545. //
  546. // Copy the token. Whether the source is primary or impersonation,
  547. // the result will be a primary token.
  548. //
  549. if (!DuplicateHandle(
  550. GetCurrentProcess(),
  551. Token,
  552. GetCurrentProcess(),
  553. &_Token,
  554. TOKEN_ALL_ACCESS,
  555. FALSE, // not inheritable
  556. 0 // no funny options
  557. ))
  558. {
  559. HRESULT HrError = HRESULT_FROM_WIN32( GetLastError() );
  560. LogError( "CUser: can't duplicate token %!winerr!", HrError );
  561. throw ComError( HrError );
  562. }
  563. }
  564. CUser::~CUser()
  565. {
  566. CloseHandle( _Token );
  567. }
  568. HRESULT
  569. CUser::LaunchProcess(
  570. StringHandle CmdLine
  571. )
  572. {
  573. DWORD s;
  574. PVOID EnvironmentBlock = 0;
  575. PROCESS_INFORMATION ProcessInformation;
  576. memset( &ProcessInformation, 0, sizeof( PROCESS_INFORMATION ));
  577. try
  578. {
  579. STARTUPINFO si;
  580. memset( &si, 0, sizeof( STARTUPINFO ));
  581. si.cb = sizeof(STARTUPINFO);
  582. CAutoString WritableCmdLine ( CopyString( CmdLine ));
  583. LogInfo( "creating process: %S", WritableCmdLine.get() );
  584. if (!CreateEnvironmentBlock( &EnvironmentBlock,
  585. _Token,
  586. FALSE
  587. ))
  588. {
  589. ThrowLastError();
  590. }
  591. if (!CreateProcessAsUser( _Token,
  592. NULL, // CmdLine contains the .exe name as well as the args
  593. WritableCmdLine.get(),
  594. 0, // no special security attributes
  595. 0, // no special thread attributes
  596. false, // don't inherit my handles
  597. NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT,
  598. EnvironmentBlock,
  599. NULL, // default current directory
  600. &si,
  601. &ProcessInformation
  602. ))
  603. {
  604. ThrowLastError();
  605. }
  606. DestroyEnvironmentBlock( EnvironmentBlock );
  607. EnvironmentBlock = 0;
  608. CloseHandle( ProcessInformation.hThread );
  609. ProcessInformation.hThread = 0;
  610. CloseHandle( ProcessInformation.hProcess );
  611. ProcessInformation.hProcess = 0;
  612. LogInfo("success, pid is 0x%x", ProcessInformation.dwProcessId);
  613. //
  614. // We succeeded.
  615. //
  616. return S_OK;
  617. }
  618. catch ( ComError err )
  619. {
  620. LogError("unable to create process, %x", err.Error() );
  621. if (EnvironmentBlock)
  622. {
  623. DestroyEnvironmentBlock( EnvironmentBlock );
  624. }
  625. return err.Error();
  626. }
  627. }
  628. #if ENABLE_STL_LOCK_OVERRIDE
  629. /*
  630. This file implements the STL lockit class to avoid linking to msvcprt.dll.
  631. */
  632. CCritSec CrtLock;
  633. #pragma warning(push)
  634. #pragma warning(disable:4273) // __declspec(dllimport) attribute overridden
  635. std::_Lockit::_Lockit()
  636. {
  637. CrtLock.WriteLock();
  638. }
  639. std::_Lockit::~_Lockit()
  640. {
  641. CrtLock.WriteUnlock();
  642. }
  643. #pragma warning(pop)
  644. #endif
  645. extern "C"
  646. {
  647. HANDLE
  648. GetCurrentUserTokenW(
  649. WCHAR Winsta[],
  650. DWORD DesiredAccess
  651. );
  652. void * __RPC_USER MIDL_user_allocate(size_t size)
  653. {
  654. try
  655. {
  656. return new char[size];
  657. }
  658. catch( ComError Error )
  659. {
  660. return NULL;
  661. }
  662. }
  663. void __RPC_USER MIDL_user_free( void * block)
  664. {
  665. delete block;
  666. }
  667. }
  668. HRESULT
  669. GetUserToken(
  670. ULONG LogonId,
  671. PHANDLE pUserToken
  672. )
  673. {
  674. //
  675. // This gets the token of the user logged onto the WinStation
  676. // if we are an admin caller.
  677. //
  678. if (LogonId == 0)
  679. {
  680. // don't need the TS API.
  681. *pUserToken = GetCurrentUserTokenW( L"WinSta0", TOKEN_ALL_ACCESS );
  682. if (*pUserToken != NULL)
  683. {
  684. return S_OK;
  685. }
  686. // if not, try the TS API.
  687. }
  688. //
  689. // Use Terminal Services for non-console Logon IDs.
  690. //
  691. BOOL Result;
  692. ULONG ReturnLength;
  693. NTSTATUS Status;
  694. OBJECT_ATTRIBUTES ObjA;
  695. HANDLE ImpersonationToken;
  696. WINSTATIONUSERTOKEN Info;
  697. SECURITY_QUALITY_OF_SERVICE SecurityQualityOfService;
  698. static PWINSTATIONQUERYINFORMATIONW pWinstationQueryInformation = 0;
  699. //
  700. // See if the entry point is loaded yet.
  701. //
  702. if (!pWinstationQueryInformation)
  703. {
  704. HMODULE module = LoadLibrary(_T("winsta.dll"));
  705. if (module == NULL)
  706. {
  707. HRESULT HrError = HRESULT_FROM_WIN32( GetLastError() );
  708. ASSERT( S_OK != HrError );
  709. LogInfo( "Load library of winsta failed, error %!winerr!", HrError );
  710. return HrError;
  711. }
  712. pWinstationQueryInformation = (PWINSTATIONQUERYINFORMATIONW) GetProcAddress( module, "WinStationQueryInformationW" );
  713. if (!pWinstationQueryInformation)
  714. {
  715. HRESULT HrError = HRESULT_FROM_WIN32( GetLastError() );
  716. ASSERT( S_OK != HrError );
  717. LogInfo( "GetProcAddress of WinStationQueryInformationW, error %!winerr!", HrError );
  718. FreeLibrary(module);
  719. return HrError;
  720. }
  721. }
  722. //
  723. // Ask for the token.
  724. //
  725. Info.ProcessId = UlongToHandle(GetCurrentProcessId());
  726. Info.ThreadId = UlongToHandle(GetCurrentThreadId());
  727. Result = (*pWinstationQueryInformation)(
  728. SERVERNAME_CURRENT,
  729. LogonId,
  730. WinStationUserToken,
  731. &Info,
  732. sizeof(Info),
  733. &ReturnLength
  734. );
  735. if( !Result )
  736. {
  737. HRESULT HrError = HRESULT_FROM_WIN32( GetLastError() );
  738. ASSERT( S_OK != HrError );
  739. LogError("token : WinstationQueryInfo failed with %!winerr!%", HrError );
  740. return HrError;
  741. }
  742. //
  743. // The token returned is a duplicate of a primary token.
  744. //
  745. *pUserToken = Info.UserToken;
  746. return S_OK;
  747. }
  748. BOOL
  749. SidToString(
  750. PSID sid,
  751. wchar_t buffer[],
  752. USHORT bytes
  753. )
  754. {
  755. UNICODE_STRING UnicodeString;
  756. UnicodeString.Buffer = buffer;
  757. UnicodeString.Length = 0;
  758. UnicodeString.MaximumLength = bytes;
  759. NTSTATUS NtStatus;
  760. NtStatus = RtlConvertSidToUnicodeString( &UnicodeString,
  761. sid,
  762. FALSE
  763. );
  764. if (!NT_SUCCESS(NtStatus))
  765. {
  766. LogWarning( "RtlConvertSid failed %x", NtStatus);
  767. StringCbCopy( buffer, bytes, L"(conversion failed)" );
  768. return FALSE;
  769. }
  770. buffer[ UnicodeString.Length ] = 0;
  771. return TRUE;
  772. }
  773. HRESULT
  774. SetStaticCloaking(
  775. IUnknown *pUnk
  776. )
  777. {
  778. // Sets static cloaking on the current object so that we
  779. // should always impersonate the current context.
  780. // Also sets the impersonation level to identify.
  781. HRESULT Hr = S_OK;
  782. IClientSecurity *pSecurity = NULL;
  783. OLECHAR *ServerPrincName = NULL;
  784. try
  785. {
  786. Hr = pUnk->QueryInterface( __uuidof( IClientSecurity ),
  787. (void**)&pSecurity );
  788. if (Hr == E_NOINTERFACE)
  789. {
  790. //
  791. // This is not a proxy; the client is in the same apartment as we are.
  792. // Identity issn't an issue, because the client already has access to system
  793. // credentials.
  794. //
  795. return S_OK;
  796. }
  797. DWORD AuthnSvc, AuthzSvc;
  798. DWORD AuthnLevel, ImpLevel, Capabilites;
  799. THROW_HRESULT(
  800. pSecurity->QueryBlanket(
  801. pUnk,
  802. &AuthnSvc,
  803. &AuthzSvc,
  804. &ServerPrincName,
  805. &AuthnLevel,
  806. NULL, // Don't need impersonation handle since were setting that
  807. NULL, // don't need indenty handle since were setting that
  808. &Capabilites ) );
  809. THROW_HRESULT(
  810. pSecurity->SetBlanket(
  811. pUnk,
  812. AuthnSvc,
  813. AuthzSvc,
  814. ServerPrincName,
  815. AuthnLevel,
  816. RPC_C_IMP_LEVEL_IDENTIFY,
  817. NULL, // COM use indentity from token
  818. #if !defined( BITS_V12_ON_NT4 )
  819. EOAC_STATIC_CLOAKING // The point of the exercise
  820. #else
  821. 0
  822. #endif
  823. ) );
  824. }
  825. catch( ComError Error )
  826. {
  827. Hr = Error.Error();
  828. }
  829. CoTaskMemFree( ServerPrincName );
  830. SafeRelease( pSecurity );
  831. return Hr;
  832. }
  833. HRESULT DetectTerminalServer( bool * pfTS )
  834. {
  835. //
  836. // Test for Terminal Services.
  837. //
  838. INT * pConnectState;
  839. DWORD size;
  840. if (WTSQuerySessionInformation( WTS_CURRENT_SERVER,
  841. 0,
  842. WTSConnectState,
  843. reinterpret_cast<LPTSTR *>(&pConnectState),
  844. &size))
  845. {
  846. LogInfo("TS test: TS is installed");
  847. *pfTS = true;
  848. WTSFreeMemory( pConnectState );
  849. return S_OK;
  850. }
  851. else if (GetLastError() == ERROR_APP_WRONG_OS)
  852. {
  853. LogInfo("TS test: no TS");
  854. *pfTS = false;
  855. return S_OK;
  856. }
  857. else
  858. {
  859. DWORD s = GetLastError();
  860. LogError("TS test returned %d", s);
  861. return HRESULT_FROM_WIN32( s );
  862. }
  863. }