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.

4681 lines
112 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-2001 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. #ifndef __ATLSECURITY_H__
  11. #define __ATLSECURITY_H__
  12. #pragma once
  13. #include <sddl.h>
  14. #include <userenv.h>
  15. #include <aclapi.h>
  16. #include <atlcoll.h>
  17. #include <atlstr.h>
  18. namespace ATL
  19. {
  20. #pragma comment(lib, "userenv.lib")
  21. class CSid
  22. {
  23. public:
  24. CSid();
  25. explicit CSid(LPCTSTR pszAccountName, LPCTSTR pszSystem = NULL);
  26. explicit CSid(const SID *pSid, LPCTSTR pszSystem = NULL);
  27. CSid(const SID_IDENTIFIER_AUTHORITY &IdentifierAuthority, BYTE nSubAuthorityCount, ...);
  28. virtual ~CSid(){free(m_pSid);}
  29. CSid(const CSid &rhs);
  30. CSid &operator=(const CSid &rhs);
  31. CSid(const SID &rhs);
  32. CSid &operator=(const SID &rhs);
  33. typedef CSimpleArray<CSid> CSidArray;
  34. bool LoadAccount(LPCTSTR pszAccountName, LPCTSTR pszSystem = NULL);
  35. bool LoadAccount(const SID *pSid, LPCTSTR pszSystem = NULL);
  36. LPCTSTR AccountName() const;
  37. LPCTSTR Domain() const;
  38. LPCTSTR Sid() const;
  39. const SID *GetPSID() const {return m_pSid;}
  40. operator const SID *() const {return GetPSID();}
  41. SID_NAME_USE SidNameUse() const {return m_SidNameUse;}
  42. UINT GetLength() const
  43. {ATLASSERT(IsValid()); return ::GetLengthSid(m_pSid);}
  44. // SID functions
  45. bool operator==(const CSid &rhs) const
  46. {return 0 != ::EqualSid(m_pSid, rhs.m_pSid);}
  47. bool operator==(const SID &rhs) const
  48. {return 0 != ::EqualSid(m_pSid, const_cast<SID *>(&rhs));}
  49. bool EqualPrefix(const CSid &rhs) const
  50. {return 0 != ::EqualPrefixSid(m_pSid, rhs.m_pSid);}
  51. bool EqualPrefix(const SID &rhs) const
  52. {return 0 != ::EqualPrefixSid(m_pSid, const_cast<SID *>(&rhs));}
  53. const SID_IDENTIFIER_AUTHORITY *GetPSID_IDENTIFIER_AUTHORITY() const
  54. {ATLASSERT(IsValid()); return ::GetSidIdentifierAuthority(m_pSid);}
  55. DWORD GetSubAuthority(DWORD nSubAuthority) const
  56. {ATLASSERT(IsValid()); return *::GetSidSubAuthority(m_pSid, nSubAuthority);}
  57. UCHAR GetSubAuthorityCount() const
  58. {ATLASSERT(IsValid()); return *::GetSidSubAuthorityCount(m_pSid);}
  59. bool IsValid() const {return 0 != ::IsValidSid(m_pSid);}
  60. private:
  61. void Copy(const SID &rhs);
  62. void Clear();
  63. void GetAccountNameAndDomain() const;
  64. SID *m_pSid;
  65. mutable SID_NAME_USE m_SidNameUse;
  66. mutable CString m_strAccountName;
  67. mutable CString m_strDomain;
  68. mutable CString m_strSid;
  69. CString m_strSystem;
  70. };
  71. // Well-known sids
  72. namespace Sids
  73. {
  74. __declspec(selectany) extern const SID_IDENTIFIER_AUTHORITY
  75. SecurityNullSidAuthority = SECURITY_NULL_SID_AUTHORITY,
  76. SecurityWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY,
  77. SecurityLocalSidAuthority = SECURITY_LOCAL_SID_AUTHORITY,
  78. SecurityCreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY,
  79. SecurityNonUniqueAuthority = SECURITY_NON_UNIQUE_AUTHORITY,
  80. SecurityNTAuthority = SECURITY_NT_AUTHORITY;
  81. // Universal
  82. inline const CSid &Null()
  83. {
  84. static const CSid sid(SecurityNullSidAuthority, 1, SECURITY_NULL_RID);
  85. return sid;
  86. }
  87. inline const CSid &World()
  88. {
  89. static const CSid sid(SecurityWorldSidAuthority, 1, SECURITY_WORLD_RID);
  90. return sid;
  91. }
  92. inline const CSid &Local()
  93. {
  94. static const CSid sid(SecurityLocalSidAuthority, 1, SECURITY_LOCAL_RID);
  95. return sid;
  96. }
  97. inline const CSid &CreatorOwner()
  98. {
  99. static const CSid sid(SecurityCreatorSidAuthority, 1, SECURITY_CREATOR_OWNER_RID);
  100. return sid;
  101. }
  102. inline const CSid &CreatorGroup()
  103. {
  104. static const CSid sid(SecurityCreatorSidAuthority, 1, SECURITY_CREATOR_GROUP_RID);
  105. return sid;
  106. }
  107. inline const CSid &CreatorOwnerServer()
  108. {
  109. static const CSid sid(SecurityCreatorSidAuthority, 1, SECURITY_CREATOR_OWNER_SERVER_RID);
  110. return sid;
  111. }
  112. inline const CSid &CreatorGroupServer()
  113. {
  114. static const CSid sid(SecurityCreatorSidAuthority, 1, SECURITY_CREATOR_GROUP_SERVER_RID);
  115. return sid;
  116. }
  117. // NT Authority
  118. inline const CSid &Dialup()
  119. {
  120. static const CSid sid(SecurityNTAuthority, 1, SECURITY_DIALUP_RID);
  121. return sid;
  122. }
  123. inline const CSid &Network()
  124. {
  125. static const CSid sid(SecurityNTAuthority, 1, SECURITY_NETWORK_RID);
  126. return sid;
  127. }
  128. inline const CSid &Batch()
  129. {
  130. static const CSid sid(SecurityNTAuthority, 1, SECURITY_BATCH_RID);
  131. return sid;
  132. }
  133. inline const CSid &Interactive()
  134. {
  135. static const CSid sid(SecurityNTAuthority, 1, SECURITY_INTERACTIVE_RID);
  136. return sid;
  137. }
  138. inline const CSid &Service()
  139. {
  140. static const CSid sid(SecurityNTAuthority, 1, SECURITY_SERVICE_RID);
  141. return sid;
  142. }
  143. inline const CSid &AnonymousLogon()
  144. {
  145. static const CSid sid(SecurityNTAuthority, 1, SECURITY_ANONYMOUS_LOGON_RID);
  146. return sid;
  147. }
  148. inline const CSid &Proxy()
  149. {
  150. static const CSid sid(SecurityNTAuthority, 1, SECURITY_PROXY_RID);
  151. return sid;
  152. }
  153. inline const CSid &ServerLogon()
  154. {
  155. static const CSid sid(SecurityNTAuthority, 1, SECURITY_SERVER_LOGON_RID);
  156. return sid;
  157. }
  158. inline const CSid &Self()
  159. {
  160. static const CSid sid(SecurityNTAuthority, 1, SECURITY_PRINCIPAL_SELF_RID);
  161. return sid;
  162. }
  163. inline const CSid &AuthenticatedUser()
  164. {
  165. static const CSid sid(SecurityNTAuthority, 1, SECURITY_AUTHENTICATED_USER_RID);
  166. return sid;
  167. }
  168. inline const CSid &RestrictedCode()
  169. {
  170. static const CSid sid(SecurityNTAuthority, 1, SECURITY_RESTRICTED_CODE_RID);
  171. return sid;
  172. }
  173. inline const CSid &TerminalServer()
  174. {
  175. static const CSid sid(SecurityNTAuthority, 1, SECURITY_TERMINAL_SERVER_RID);
  176. return sid;
  177. }
  178. inline const CSid &System()
  179. {
  180. static const CSid sid(SecurityNTAuthority, 1, SECURITY_LOCAL_SYSTEM_RID);
  181. return sid;
  182. }
  183. // NT Authority\BUILTIN
  184. inline const CSid &Admins()
  185. {
  186. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS);
  187. return sid;
  188. }
  189. inline const CSid &Users()
  190. {
  191. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS);
  192. return sid;
  193. }
  194. inline const CSid &Guests()
  195. {
  196. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS);
  197. return sid;
  198. }
  199. inline const CSid &PowerUsers()
  200. {
  201. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS);
  202. return sid;
  203. }
  204. inline const CSid &AccountOps()
  205. {
  206. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS);
  207. return sid;
  208. }
  209. inline const CSid &SystemOps()
  210. {
  211. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS);
  212. return sid;
  213. }
  214. inline const CSid &PrintOps()
  215. {
  216. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS);
  217. return sid;
  218. }
  219. inline const CSid &BackupOps()
  220. {
  221. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS);
  222. return sid;
  223. }
  224. inline const CSid &Replicator()
  225. {
  226. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR);
  227. return sid;
  228. }
  229. inline const CSid &RasServers()
  230. {
  231. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_RAS_SERVERS);
  232. return sid;
  233. }
  234. inline const CSid &PreW2KAccess()
  235. {
  236. static const CSid sid(SecurityNTAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS);
  237. return sid;
  238. }
  239. } // namespace Sids
  240. inline CSid::CSid()
  241. : m_pSid(NULL), m_SidNameUse(SidTypeInvalid)
  242. {
  243. }
  244. inline CSid::CSid(LPCTSTR pszAccountName, LPCTSTR pszSystem)
  245. : m_pSid(NULL), m_SidNameUse(SidTypeInvalid)
  246. {
  247. if(!LoadAccount(pszAccountName, pszSystem))
  248. AtlThrowLastWin32();
  249. }
  250. inline CSid::CSid(const SID *pSid, LPCTSTR pszSystem)
  251. : m_pSid(NULL), m_SidNameUse(SidTypeInvalid)
  252. {
  253. if(!LoadAccount(pSid, pszSystem))
  254. AtlThrowLastWin32();
  255. }
  256. inline CSid::CSid(const SID_IDENTIFIER_AUTHORITY &IdentifierAuthority,
  257. BYTE nSubAuthorityCount, ...)
  258. : m_pSid(NULL), m_SidNameUse(SidTypeInvalid)
  259. {
  260. SID *pSid;
  261. ATLASSERT(nSubAuthorityCount);
  262. if(!nSubAuthorityCount)
  263. AtlThrow(E_INVALIDARG);
  264. pSid = static_cast<SID *>(_alloca(::GetSidLengthRequired(nSubAuthorityCount)));
  265. if(!::InitializeSid(pSid,
  266. const_cast<SID_IDENTIFIER_AUTHORITY *>(&IdentifierAuthority),
  267. nSubAuthorityCount))
  268. {
  269. AtlThrowLastWin32();
  270. }
  271. va_list args;
  272. va_start(args, nSubAuthorityCount);
  273. for(UINT i = 0; i < nSubAuthorityCount; i++)
  274. *::GetSidSubAuthority(pSid, i) = va_arg(args, DWORD);
  275. va_end(args);
  276. Copy(*pSid);
  277. m_SidNameUse = SidTypeUnknown;
  278. }
  279. inline CSid::CSid(const CSid &rhs)
  280. : m_SidNameUse(rhs.m_SidNameUse), m_pSid(NULL),
  281. m_strAccountName(rhs.m_strAccountName), m_strDomain(rhs.m_strDomain),
  282. m_strSid(rhs.m_strSid)
  283. {
  284. if(!rhs.IsValid())
  285. AtlThrow(E_INVALIDARG);
  286. DWORD dwLengthSid = ::GetLengthSid(rhs.m_pSid);
  287. m_pSid = static_cast<SID *>(malloc(dwLengthSid));
  288. if(!m_pSid)
  289. AtlThrow(E_OUTOFMEMORY);
  290. if(!::CopySid(dwLengthSid, m_pSid, rhs.m_pSid))
  291. {
  292. HRESULT hr = AtlHresultFromLastError();
  293. free(m_pSid);
  294. AtlThrow(hr);
  295. }
  296. }
  297. inline CSid &CSid::operator=(const CSid &rhs)
  298. {
  299. if(this != &rhs)
  300. {
  301. if(!rhs.IsValid())
  302. AtlThrow(E_INVALIDARG);
  303. m_SidNameUse = rhs.m_SidNameUse;
  304. m_strAccountName = rhs.m_strAccountName;
  305. m_strDomain = rhs.m_strDomain;
  306. m_strSid = rhs.m_strSid;
  307. free(m_pSid);
  308. DWORD dwLengthSid = ::GetLengthSid(rhs.m_pSid);
  309. m_pSid = static_cast<SID *>(malloc(dwLengthSid));
  310. if(!m_pSid)
  311. AtlThrow(E_OUTOFMEMORY);
  312. if(!::CopySid(dwLengthSid, m_pSid, rhs.m_pSid))
  313. {
  314. HRESULT hr = AtlHresultFromLastError();
  315. free(m_pSid);
  316. m_pSid = NULL;
  317. AtlThrow(hr);
  318. }
  319. }
  320. return *this;
  321. }
  322. inline CSid::CSid(const SID &rhs)
  323. : m_pSid(NULL), m_SidNameUse(SidTypeInvalid)
  324. {
  325. Copy(rhs);
  326. }
  327. inline CSid &CSid::operator=(const SID &rhs)
  328. {
  329. if(m_pSid != &rhs)
  330. {
  331. Clear();
  332. Copy(rhs);
  333. m_SidNameUse = SidTypeUnknown;
  334. }
  335. return *this;
  336. }
  337. inline bool CSid::LoadAccount(LPCTSTR pszAccountName, LPCTSTR pszSystem)
  338. {
  339. // REVIEW
  340. static const DWORD dwSidSize = offsetof(SID, SubAuthority) + SID_MAX_SUB_AUTHORITIES * sizeof(DWORD);
  341. static const DWORD dwDomainSize = 128; // seems reasonable
  342. BYTE byTmp[dwSidSize];
  343. SID *pSid = reinterpret_cast<SID *>(byTmp);
  344. TCHAR szDomain[dwDomainSize];
  345. DWORD cbSid = dwSidSize, cbDomain = dwDomainSize;
  346. BOOL bSuccess = ::LookupAccountName(pszSystem, pszAccountName, pSid, &cbSid, szDomain, &cbDomain, &m_SidNameUse);
  347. if(bSuccess || ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
  348. {
  349. // LookupAccountName doesn't change cbSid on success (although it changes cbDomain)
  350. if(bSuccess)
  351. cbSid = ::GetLengthSid(pSid);
  352. free(m_pSid);
  353. m_pSid = static_cast<SID *>(malloc(cbSid));
  354. if (m_pSid)
  355. {
  356. if(bSuccess)
  357. {
  358. if(::CopySid(cbSid, m_pSid, pSid))
  359. {
  360. m_strDomain = szDomain;
  361. m_strAccountName = pszAccountName;
  362. m_strSystem = pszSystem;
  363. return true;
  364. }
  365. }
  366. else
  367. {
  368. LPTSTR pszDomain = m_strDomain.GetBuffer(cbDomain);
  369. bSuccess = ::LookupAccountName(pszSystem, pszAccountName, m_pSid, &cbSid,
  370. pszDomain ,&cbDomain, &m_SidNameUse);
  371. m_strDomain.ReleaseBuffer();
  372. if(bSuccess)
  373. {
  374. m_strAccountName = pszAccountName;
  375. m_strSystem = pszSystem;
  376. return true;
  377. }
  378. }
  379. }
  380. }
  381. Clear();
  382. return false;
  383. }
  384. inline bool CSid::LoadAccount(const SID *pSid, LPCTSTR pszSystem)
  385. {
  386. ATLASSERT(pSid);
  387. if(pSid)
  388. _ATLTRY
  389. {
  390. m_strSystem = pszSystem;
  391. Copy(*pSid);
  392. return true;
  393. }
  394. _ATLCATCHALL()
  395. {
  396. Clear();
  397. }
  398. return false;
  399. }
  400. inline LPCTSTR CSid::AccountName() const
  401. {
  402. if(m_strAccountName.IsEmpty())
  403. GetAccountNameAndDomain();
  404. return m_strAccountName;
  405. }
  406. inline LPCTSTR CSid::Domain() const
  407. {
  408. if(m_strDomain.IsEmpty())
  409. GetAccountNameAndDomain();
  410. return m_strDomain;
  411. }
  412. inline LPCTSTR CSid::Sid() const
  413. {
  414. if(m_strSid.IsEmpty())
  415. {
  416. #if(_WIN32_WINNT >= 0x0500)
  417. LPTSTR pszSid;
  418. if(::ConvertSidToStringSid(m_pSid, &pszSid))
  419. {
  420. m_strSid = pszSid;
  421. ::LocalFree(pszSid);
  422. }
  423. #else
  424. SID_IDENTIFIER_AUTHORITY *psia = ::GetSidIdentifierAuthority(m_pSid);
  425. UINT i;
  426. if(psia->Value[0] || psia->Value[1])
  427. {
  428. unsigned __int64 nAuthority = 0;
  429. for(i = 0; i < 6; i++)
  430. {
  431. nAuthority <<= 8;
  432. nAuthority |= psia->Value[i];
  433. }
  434. m_strSid.Format(_T("S-%d-%I64u"), SID_REVISION, nAuthority);
  435. }
  436. else
  437. {
  438. ULONG nAuthority = 0;
  439. for(i = 2; i < 6; i++)
  440. {
  441. nAuthority <<= 8;
  442. nAuthority |= psia->Value[i];
  443. }
  444. m_strSid.Format(_T("S-%d-%lu"), SID_REVISION, nAuthority);
  445. }
  446. UINT nSubAuthorityCount = *::GetSidSubAuthorityCount(m_pSid);
  447. CString strTemp;
  448. for(i = 0; i < nSubAuthorityCount; i++)
  449. {
  450. strTemp.Format(_T("-%lu"), *::GetSidSubAuthority(m_pSid, i));
  451. m_strSid += strTemp;
  452. }
  453. #endif
  454. }
  455. return m_strSid;
  456. }
  457. inline void CSid::Clear()
  458. {
  459. m_SidNameUse = SidTypeInvalid;
  460. m_strAccountName.Empty();
  461. m_strDomain.Empty();
  462. m_strSid.Empty();
  463. m_strSystem.Empty();
  464. free(m_pSid);
  465. m_pSid = NULL;
  466. }
  467. inline void CSid::Copy(const SID &rhs)
  468. {
  469. // This function assumes everything is cleaned up/initialized
  470. // (with the exception of m_strSystem).
  471. // It does some sanity checking to prevent memory leaks, but
  472. // you should clean up all members of CSid before calling this
  473. // function. (i.e., results are unpredictable on error)
  474. ATLASSERT(m_SidNameUse == SidTypeInvalid);
  475. ATLASSERT(m_strAccountName.IsEmpty());
  476. ATLASSERT(m_strDomain.IsEmpty());
  477. ATLASSERT(m_strSid.IsEmpty());
  478. SID *p = const_cast<SID *>(&rhs);
  479. if(!::IsValidSid(p))
  480. AtlThrow(E_INVALIDARG);
  481. free(m_pSid);
  482. DWORD dwLengthSid = ::GetLengthSid(p);
  483. m_pSid = (SID *) malloc(dwLengthSid);
  484. if(!m_pSid)
  485. AtlThrow(E_OUTOFMEMORY);
  486. if(!::CopySid(dwLengthSid, m_pSid, p))
  487. {
  488. HRESULT hr = AtlHresultFromLastError();
  489. free(m_pSid);
  490. m_pSid = NULL;
  491. AtlThrow(hr);
  492. }
  493. }
  494. inline void CSid::GetAccountNameAndDomain() const
  495. {
  496. // REVIEW: 32 large enough?
  497. static const DWORD dwMax = 32; // seems reasonable
  498. DWORD cbName = dwMax, cbDomain = dwMax;
  499. TCHAR szName[dwMax], szDomain[dwMax];
  500. if(::LookupAccountSid(m_strSystem, m_pSid, szName, &cbName, szDomain, &cbDomain, &m_SidNameUse))
  501. {
  502. m_strAccountName = szName;
  503. m_strDomain = szDomain;
  504. }
  505. else
  506. {
  507. switch(::GetLastError())
  508. {
  509. case ERROR_INSUFFICIENT_BUFFER:
  510. {
  511. LPTSTR pszName = m_strAccountName.GetBuffer(cbName);
  512. LPTSTR pszDomain = m_strDomain.GetBuffer(cbDomain);
  513. if (!::LookupAccountSid(m_strSystem, m_pSid, pszName, &cbName, pszDomain, &cbDomain, &m_SidNameUse))
  514. {
  515. AtlThrowLastWin32();
  516. }
  517. m_strAccountName.ReleaseBuffer();
  518. m_strDomain.ReleaseBuffer();
  519. break;
  520. }
  521. case ERROR_NONE_MAPPED:
  522. m_strAccountName.Empty();
  523. m_strDomain.Empty();
  524. m_SidNameUse = SidTypeUnknown;
  525. break;
  526. default:
  527. ATLASSERT(FALSE);
  528. }
  529. }
  530. }
  531. template<>
  532. class CElementTraits< CSid > :
  533. public CElementTraitsBase< CSid >
  534. {
  535. public:
  536. static ULONG Hash( INARGTYPE t ) throw()
  537. {
  538. return( ULONG( ULONG_PTR( t.GetPSID() ) ) );
  539. }
  540. static int CompareElements( INARGTYPE element1, INARGTYPE element2 ) throw()
  541. {
  542. return( element1 == element2 );
  543. }
  544. static int CompareElementsOrdered( INARGTYPE element1, INARGTYPE element2 ) throw()
  545. {
  546. #if 0
  547. if( element1 < element2 )
  548. {
  549. return( -1 );
  550. }
  551. else if( element1 == element2 )
  552. {
  553. return( 0 );
  554. }
  555. else
  556. {
  557. ATLASSERT( element1 > element2 );
  558. return( 1 );
  559. }
  560. #else
  561. element1;
  562. element2;
  563. ATLASSERT(false);
  564. return 0;
  565. #endif
  566. }
  567. };
  568. //***************************************
  569. // CAcl
  570. // CAce
  571. //
  572. // CDacl
  573. // CAccessAce
  574. //
  575. // CSacl
  576. // CAuditAce
  577. //***************************************
  578. // **************************************************************
  579. // ACLs
  580. class CAcl
  581. {
  582. public:
  583. CAcl() : m_pAcl(NULL), m_bNull(false), m_dwAclRevision(ACL_REVISION){}
  584. virtual ~CAcl(){free(m_pAcl);}
  585. CAcl(const CAcl &rhs) : m_pAcl(NULL), m_bNull(rhs.m_bNull),
  586. m_dwAclRevision(rhs.m_dwAclRevision){}
  587. CAcl &operator=(const CAcl &rhs)
  588. {
  589. if(this != &rhs)
  590. {
  591. free(m_pAcl);
  592. m_pAcl = NULL;
  593. m_bNull = rhs.m_bNull;
  594. m_dwAclRevision = rhs.m_dwAclRevision;
  595. }
  596. return *this;
  597. }
  598. typedef CSimpleArray<ACCESS_MASK> CAccessMaskArray;
  599. typedef CSimpleArray<BYTE> CAceTypeArray;
  600. typedef CSimpleArray<BYTE> CAceFlagArray;
  601. void GetAclEntries(CSid::CSidArray *pSids, CAccessMaskArray *pAccessMasks = NULL,
  602. CAceTypeArray *pAceTypes = NULL, CAceFlagArray *pAceFlags = NULL) const;
  603. bool RemoveAces(const CSid &rSid);
  604. virtual UINT GetAceCount() const = 0;
  605. virtual void RemoveAllAces() = 0;
  606. const ACL *GetPACL() const;
  607. operator const ACL *() const {return GetPACL();}
  608. UINT GetLength() const;
  609. void SetNull(){Dirty(); m_bNull = true;}
  610. void SetEmpty(){Dirty(); m_bNull = false;}
  611. bool IsNull() const {return m_bNull;}
  612. bool IsEmpty() const {return !m_bNull && 0 == GetAceCount();}
  613. private:
  614. mutable ACL *m_pAcl;
  615. bool m_bNull;
  616. protected:
  617. void Dirty(){free(m_pAcl); m_pAcl = NULL;}
  618. class CAce
  619. {
  620. public:
  621. CAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags)
  622. : m_dwAccessMask(AccessMask), m_Sid(rSid), m_AceFlags(AceFlags), m_pAce(NULL){}
  623. virtual ~CAce(){free(m_pAce);}
  624. CAce(const CAce &rhs) : m_Sid(rhs.m_Sid), m_dwAccessMask(rhs.m_dwAccessMask),
  625. m_AceFlags(rhs.m_AceFlags), m_pAce(NULL){}
  626. CAce &operator=(const CAce &rhs)
  627. {
  628. if(this != &rhs)
  629. {
  630. m_Sid = rhs.m_Sid;
  631. m_dwAccessMask = rhs.m_dwAccessMask;
  632. m_AceFlags = rhs.m_AceFlags;
  633. free(m_pAce);
  634. m_pAce = NULL;
  635. }
  636. return *this;
  637. }
  638. virtual void *GetACE() const = 0;
  639. virtual UINT GetLength() const = 0;
  640. virtual BYTE AceType() const = 0;
  641. virtual bool IsObjectAce() const {return false;}
  642. ACCESS_MASK AccessMask() const
  643. {return m_dwAccessMask;}
  644. BYTE AceFlags() const
  645. {return m_AceFlags;}
  646. const CSid &Sid() const
  647. {return m_Sid;}
  648. void AddAccess(ACCESS_MASK AccessMask)
  649. {m_dwAccessMask |= AccessMask; free(m_pAce); m_pAce = NULL;}
  650. protected:
  651. CSid m_Sid;
  652. ACCESS_MASK m_dwAccessMask;
  653. BYTE m_AceFlags;
  654. mutable void *m_pAce;
  655. };
  656. virtual const CAce *GetAce(UINT nIndex) const = 0;
  657. virtual void RemoveAce(UINT nIndex) = 0;
  658. virtual void PrepareAcesForACL() const {}
  659. DWORD m_dwAclRevision;
  660. };
  661. inline const ACL *CAcl::GetPACL() const
  662. {
  663. if(!m_pAcl && !m_bNull)
  664. {
  665. UINT nAclLength = sizeof(ACL);
  666. const CAce *pAce;
  667. UINT i;
  668. const UINT nCount = GetAceCount();
  669. for(i = 0; i < nCount; i++)
  670. {
  671. pAce = GetAce(i);
  672. ATLASSERT(pAce);
  673. if(pAce)
  674. nAclLength += pAce->GetLength();
  675. }
  676. m_pAcl = static_cast<ACL *>(malloc(nAclLength));
  677. if(!m_pAcl)
  678. return NULL;
  679. if(!::InitializeAcl(m_pAcl, nAclLength, m_dwAclRevision))
  680. {
  681. free(m_pAcl);
  682. m_pAcl = NULL;
  683. }
  684. else
  685. {
  686. PrepareAcesForACL();
  687. for(i = 0; i < nCount; i++)
  688. {
  689. pAce = GetAce(i);
  690. ATLASSERT(pAce);
  691. if(!pAce ||
  692. !::AddAce(m_pAcl, m_dwAclRevision, MAXDWORD, pAce->GetACE(), pAce->GetLength()))
  693. {
  694. free(m_pAcl);
  695. m_pAcl = NULL;
  696. break;
  697. }
  698. }
  699. }
  700. }
  701. return m_pAcl;
  702. }
  703. inline UINT CAcl::GetLength() const
  704. {
  705. ACL *pAcl = const_cast<ACL *>(GetPACL());
  706. ACL_SIZE_INFORMATION AclSize;
  707. ATLASSERT(pAcl);
  708. if(!::GetAclInformation(pAcl, &AclSize, sizeof(AclSize), AclSizeInformation))
  709. {
  710. ATLASSERT(false);
  711. return 0;
  712. }
  713. else
  714. return AclSize.AclBytesInUse;
  715. }
  716. inline void CAcl::GetAclEntries(CSid::CSidArray *pSids, CAccessMaskArray *pAccessMasks,
  717. CAceTypeArray *pAceTypes, CAceFlagArray *pAceFlags) const
  718. {
  719. ATLASSERT(pSids);
  720. if(pSids)
  721. {
  722. pSids->RemoveAll();
  723. if(pAccessMasks)
  724. pAccessMasks->RemoveAll();
  725. if(pAceTypes)
  726. pAceTypes->RemoveAll();
  727. if(pAceFlags)
  728. pAceFlags->RemoveAll();
  729. const CAce *pAce;
  730. const UINT nCount = GetAceCount();
  731. for(UINT i = 0; i < nCount; i++)
  732. {
  733. pAce = GetAce(i);
  734. pSids->Add(pAce->Sid());
  735. if(pAccessMasks)
  736. pAccessMasks->Add(pAce->AccessMask());
  737. if(pAceTypes)
  738. pAceTypes->Add(pAce->AceType());
  739. if(pAceFlags)
  740. pAceFlags->Add(pAce->AceFlags());
  741. }
  742. }
  743. }
  744. inline bool CAcl::RemoveAces(const CSid &rSid)
  745. {
  746. ATLASSERT(rSid.IsValid());
  747. if(IsNull() || !rSid.IsValid())
  748. return false;
  749. bool bRet = false;
  750. const CAce *pAce;
  751. UINT i = 0;
  752. while(i < GetAceCount())
  753. {
  754. pAce = GetAce(i);
  755. if(rSid == pAce->Sid())
  756. {
  757. RemoveAce(i);
  758. bRet = true;
  759. }
  760. else
  761. i++;
  762. }
  763. if(bRet)
  764. Dirty();
  765. return bRet;
  766. }
  767. // ************************************************
  768. // CDacl
  769. class CDacl : public CAcl
  770. {
  771. public:
  772. CDacl(){}
  773. ~CDacl(){CDacl::RemoveAllAces();}
  774. CDacl(const ACL &rhs){Copy(rhs);}
  775. CDacl &operator=(const ACL &rhs);
  776. bool AddAllowedAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags = 0);
  777. bool AddDeniedAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags = 0);
  778. #if(_WIN32_WINNT >= 0x0500)
  779. bool AddAllowedAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags,
  780. const GUID *pObjectType, const GUID *pInheritedObjectType);
  781. bool AddDeniedAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags,
  782. const GUID *pObjectType, const GUID *pInheritedObjectType);
  783. #endif
  784. void RemoveAllAces();
  785. UINT GetAceCount() const
  786. {return m_Acl.GetSize();}
  787. private:
  788. void Copy(const ACL &rhs);
  789. class CAccessAce : public CAcl::CAce
  790. {
  791. public:
  792. CAccessAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags, bool bAllowAccess)
  793. : CAce(rSid, AccessMask, AceFlags), m_bAllow(bAllowAccess){}
  794. void *GetACE() const;
  795. UINT GetLength() const
  796. {return offsetof(ACCESS_ALLOWED_ACE, SidStart) + m_Sid.GetLength();}
  797. BYTE AceType() const
  798. {return (BYTE)(m_bAllow ? ACCESS_ALLOWED_ACE_TYPE : ACCESS_DENIED_ACE_TYPE);}
  799. bool Allow() const {return m_bAllow;}
  800. bool Inherited() const {return 0 != (m_AceFlags & INHERITED_ACE);}
  801. protected:
  802. bool m_bAllow;
  803. };
  804. #if(_WIN32_WINNT >= 0x0500)
  805. class CAccessObjectAce : public CAccessAce
  806. {
  807. public:
  808. CAccessObjectAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags, bool bAllowAccess,
  809. const GUID *pObjectType, const GUID *pInheritedObjectType);
  810. ~CAccessObjectAce();
  811. CAccessObjectAce(const CAccessObjectAce &rhs)
  812. : CAccessAce(rhs), m_pObjectType(NULL), m_pInheritedObjectType(NULL){*this = rhs;}
  813. CAccessObjectAce &operator=(const CAccessObjectAce &rhs);
  814. void *GetACE() const;
  815. UINT GetLength() const;
  816. BYTE AceType() const
  817. {return (BYTE)(m_bAllow ? ACCESS_ALLOWED_OBJECT_ACE_TYPE : ACCESS_DENIED_OBJECT_ACE_TYPE);}
  818. bool IsObjectAce() const {return true;}
  819. protected:
  820. GUID *m_pObjectType, *m_pInheritedObjectType;
  821. };
  822. #endif
  823. const CAcl::CAce *GetAce(UINT nIndex) const
  824. {return m_Acl[nIndex];}
  825. void RemoveAce(UINT nIndex);
  826. void PrepareAcesForACL() const;
  827. mutable CSimpleArray<CAccessAce *> m_Acl;
  828. friend bool operator>(const CAccessAce &lhs, const CAccessAce &rhs)
  829. {
  830. // The order is:
  831. // denied direct aces
  832. // denied direct object aces
  833. // allowed direct aces
  834. // allowed direct object aces
  835. // denied inherit aces
  836. // denied inherit object aces
  837. // allowed inherit aces
  838. // allowed inherit object aces
  839. // inherited aces are always "greater" than non-inherited aces
  840. if(lhs.Inherited() && !rhs.Inherited())
  841. return true;
  842. if(!lhs.Inherited() && rhs.Inherited())
  843. return false;
  844. // if the aces are *both* either inherited or non-inherited, continue...
  845. // allowed aces are always "greater" than denied aces (subject to above)
  846. if(lhs.Allow() && !rhs.Allow())
  847. return true;
  848. if(!lhs.Allow() && rhs.Allow())
  849. return false;
  850. // if the aces are *both* either allowed or denied, continue...
  851. // object aces are always "greater" than non-object aces (subject to above)
  852. if(lhs.IsObjectAce() && !rhs.IsObjectAce())
  853. return true;
  854. if(!lhs.IsObjectAce() && rhs.IsObjectAce())
  855. return false;
  856. // aces are "equal" (e.g., both are access denied inherited object aces)
  857. return false;
  858. }
  859. };
  860. inline CDacl &CDacl::operator=(const ACL &rhs)
  861. {
  862. RemoveAllAces();
  863. Copy(rhs);
  864. return *this;
  865. }
  866. inline void CDacl::PrepareAcesForACL() const
  867. {
  868. // For a dacl, sort the aces
  869. int i, j, h = 1;
  870. const int nCount = m_Acl.GetSize();
  871. CAccessAce *pAce;
  872. while(h * 3 + 1 < nCount)
  873. h = 3 * h + 1;
  874. while(h > 0)
  875. {
  876. for(i = h - 1; i < nCount; i++)
  877. {
  878. pAce = m_Acl[i];
  879. for(j = i; j >= h && *m_Acl[j - h] > *pAce; j -= h)
  880. m_Acl[j] = m_Acl[j - h];
  881. m_Acl[j] = pAce;
  882. }
  883. h /= 3;
  884. }
  885. }
  886. inline void CDacl::Copy(const ACL &rhs)
  887. {
  888. ACL *pAcl = const_cast<ACL *>(&rhs);
  889. ACL_SIZE_INFORMATION AclSizeInfo;
  890. ACE_HEADER *pHeader;
  891. CSid Sid;
  892. ACCESS_MASK AccessMask;
  893. CAccessAce *pAce;
  894. Dirty();
  895. if(!::GetAclInformation(pAcl, &AclSizeInfo, sizeof(AclSizeInfo), AclSizeInformation))
  896. AtlThrowLastWin32();
  897. for(DWORD i = 0; i < AclSizeInfo.AceCount; i++)
  898. {
  899. if(!::GetAce(pAcl, i, reinterpret_cast<void **>(&pHeader)))
  900. AtlThrowLastWin32();
  901. AccessMask = *reinterpret_cast<ACCESS_MASK *>
  902. (reinterpret_cast<BYTE *>(pHeader) + sizeof(ACE_HEADER));
  903. switch(pHeader->AceType)
  904. {
  905. case ACCESS_ALLOWED_ACE_TYPE:
  906. case ACCESS_DENIED_ACE_TYPE:
  907. Sid = *reinterpret_cast<SID *>
  908. (reinterpret_cast<BYTE *>(pHeader) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
  909. ATLTRY(pAce = new CAccessAce(Sid, AccessMask, pHeader->AceFlags,
  910. ACCESS_ALLOWED_ACE_TYPE == pHeader->AceType));
  911. if (!pAce)
  912. AtlThrow(E_OUTOFMEMORY);
  913. if (!m_Acl.Add(pAce))
  914. {
  915. delete pAce;
  916. AtlThrow(E_OUTOFMEMORY);
  917. }
  918. break;
  919. #if(_WIN32_WINNT >= 0x0500)
  920. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  921. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  922. {
  923. GUID *pObjectType = NULL, *pInheritedObjectType = NULL;
  924. BYTE *pb = reinterpret_cast<BYTE *>
  925. (pHeader) + offsetof(ACCESS_ALLOWED_OBJECT_ACE, SidStart);
  926. DWORD dwFlags = reinterpret_cast<ACCESS_ALLOWED_OBJECT_ACE *>(pHeader)->Flags;
  927. if(dwFlags & ACE_OBJECT_TYPE_PRESENT)
  928. {
  929. pObjectType = reinterpret_cast<GUID *>
  930. (reinterpret_cast<BYTE *>(pHeader) +
  931. offsetof(ACCESS_ALLOWED_OBJECT_ACE, ObjectType));
  932. }
  933. else
  934. pb -= sizeof(GUID);
  935. if(dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  936. {
  937. pInheritedObjectType = reinterpret_cast<GUID *>
  938. (reinterpret_cast<BYTE *>(pHeader) +
  939. (pObjectType ?
  940. offsetof(ACCESS_ALLOWED_OBJECT_ACE, InheritedObjectType) :
  941. offsetof(ACCESS_ALLOWED_OBJECT_ACE, ObjectType)));
  942. }
  943. else
  944. pb -= sizeof(GUID);
  945. Sid = *reinterpret_cast<SID *>(pb);
  946. ATLTRY(pAce = new CAccessObjectAce(Sid, AccessMask, pHeader->AceFlags,
  947. ACCESS_ALLOWED_OBJECT_ACE_TYPE == pHeader->AceType,
  948. pObjectType, pInheritedObjectType));
  949. if (!pAce)
  950. AtlThrow(E_OUTOFMEMORY);
  951. if (!m_Acl.Add(pAce))
  952. {
  953. delete pAce;
  954. AtlThrow(E_OUTOFMEMORY);
  955. }
  956. break;
  957. }
  958. #endif
  959. default:
  960. // Wrong ACE type
  961. ATLASSERT(false);
  962. }
  963. }
  964. }
  965. inline bool CDacl::AddAllowedAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags)
  966. {
  967. ATLASSERT(rSid.IsValid());
  968. if(IsNull() || !rSid.IsValid())
  969. return false;
  970. CAccessAce *pAce = NULL;
  971. ATLTRY(pAce = new CAccessAce(rSid, AccessMask, AceFlags, true));
  972. if(!pAce)
  973. return false;
  974. if (!m_Acl.Add(pAce))
  975. {
  976. delete pAce;
  977. return false;
  978. }
  979. Dirty();
  980. return true;
  981. }
  982. #if(_WIN32_WINNT >= 0x0500)
  983. inline bool CDacl::AddAllowedAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags,
  984. const GUID *pObjectType, const GUID *pInheritedObjectType)
  985. {
  986. if(!pObjectType && !pInheritedObjectType)
  987. return AddAllowedAce(rSid, AccessMask, AceFlags);
  988. ATLASSERT(rSid.IsValid());
  989. if(IsNull() || !rSid.IsValid())
  990. return false;
  991. CAccessAce *pAce;
  992. ATLTRY(pAce = new CAccessObjectAce(rSid, AccessMask, AceFlags, true,
  993. pObjectType, pInheritedObjectType));
  994. if(!pAce)
  995. return false;
  996. if (!m_Acl.Add(pAce))
  997. {
  998. delete pAce;
  999. return false;
  1000. }
  1001. m_dwAclRevision = ACL_REVISION_DS;
  1002. Dirty();
  1003. return true;
  1004. }
  1005. #endif
  1006. inline bool CDacl::AddDeniedAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags)
  1007. {
  1008. ATLASSERT(rSid.IsValid());
  1009. if(IsNull() || !rSid.IsValid())
  1010. return false;
  1011. CAccessAce *pAce = NULL;
  1012. ATLTRY(pAce = new CAccessAce(rSid, AccessMask, AceFlags, false));
  1013. if(!pAce)
  1014. return false;
  1015. if (!m_Acl.Add(pAce))
  1016. {
  1017. delete pAce;
  1018. return false;
  1019. }
  1020. Dirty();
  1021. return true;
  1022. }
  1023. #if(_WIN32_WINNT >= 0x0500)
  1024. inline bool CDacl::AddDeniedAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags,
  1025. const GUID *pObjectType, const GUID *pInheritedObjectType)
  1026. {
  1027. if(!pObjectType && !pInheritedObjectType)
  1028. return AddDeniedAce(rSid, AccessMask, AceFlags);
  1029. ATLASSERT(rSid.IsValid());
  1030. if(IsNull() || !rSid.IsValid())
  1031. return false;
  1032. CAccessAce *pAce;
  1033. ATLTRY(pAce = new CAccessObjectAce(rSid, AccessMask, AceFlags, false,
  1034. pObjectType, pInheritedObjectType));
  1035. if(!pAce)
  1036. return false;
  1037. if (!m_Acl.Add(pAce))
  1038. {
  1039. delete pAce;
  1040. return false;
  1041. }
  1042. m_dwAclRevision = ACL_REVISION_DS;
  1043. Dirty();
  1044. return true;
  1045. }
  1046. #endif
  1047. inline void CDacl::RemoveAllAces()
  1048. {
  1049. const UINT nCount = GetAceCount();
  1050. for(UINT i = 0; i < nCount; i++)
  1051. delete GetAce(i);
  1052. m_Acl.RemoveAll();
  1053. Dirty();
  1054. }
  1055. inline void CDacl::RemoveAce(UINT nIndex)
  1056. {
  1057. delete GetAce(nIndex);
  1058. m_Acl.RemoveAt(nIndex);
  1059. }
  1060. inline void *CDacl::CAccessAce::GetACE() const
  1061. {
  1062. C_ASSERT(sizeof(ACCESS_ALLOWED_ACE) == sizeof(ACCESS_DENIED_ACE));
  1063. C_ASSERT(offsetof(ACCESS_ALLOWED_ACE, Header)==offsetof(ACCESS_DENIED_ACE, Header));
  1064. C_ASSERT(offsetof(ACCESS_ALLOWED_ACE, Mask)==offsetof(ACCESS_DENIED_ACE, Mask));
  1065. C_ASSERT(offsetof(ACCESS_ALLOWED_ACE, SidStart)==offsetof(ACCESS_DENIED_ACE, SidStart));
  1066. if(!m_pAce)
  1067. {
  1068. UINT nLength = GetLength();
  1069. ACCESS_ALLOWED_ACE *pAce = static_cast<ACCESS_ALLOWED_ACE *>(malloc(nLength));
  1070. if(!pAce)
  1071. return NULL;
  1072. memset(pAce, 0x00, nLength);
  1073. pAce->Header.AceSize = static_cast<WORD>(nLength);
  1074. pAce->Header.AceFlags = m_AceFlags;
  1075. pAce->Header.AceType = AceType();
  1076. pAce->Mask = m_dwAccessMask;
  1077. ATLASSERT(nLength-offsetof(ACCESS_ALLOWED_ACE, SidStart) >= m_Sid.GetLength());
  1078. memcpy(&pAce->SidStart, m_Sid.GetPSID(), m_Sid.GetLength());
  1079. m_pAce = pAce;
  1080. }
  1081. return m_pAce;
  1082. }
  1083. #if(_WIN32_WINNT >= 0x0500)
  1084. inline CDacl::CAccessObjectAce::CAccessObjectAce(const CSid &rSid, ACCESS_MASK AccessMask,
  1085. BYTE AceFlags, bool bAllowAccess,
  1086. const GUID *pObjectType,
  1087. const GUID *pInheritedObjectType) :
  1088. CAccessAce(rSid, AccessMask, AceFlags, bAllowAccess),
  1089. m_pObjectType(NULL),
  1090. m_pInheritedObjectType(NULL)
  1091. {
  1092. if(pObjectType)
  1093. {
  1094. ATLTRY(m_pObjectType = new GUID(*pObjectType));
  1095. if(!m_pObjectType)
  1096. AtlThrow(E_OUTOFMEMORY);
  1097. }
  1098. if(pInheritedObjectType)
  1099. {
  1100. ATLTRY(m_pInheritedObjectType = new GUID(*pInheritedObjectType));
  1101. if(!m_pInheritedObjectType)
  1102. {
  1103. delete m_pObjectType;
  1104. m_pObjectType = NULL;
  1105. AtlThrow(E_OUTOFMEMORY);
  1106. }
  1107. }
  1108. }
  1109. inline CDacl::CAccessObjectAce::~CAccessObjectAce()
  1110. {
  1111. delete m_pObjectType;
  1112. delete m_pInheritedObjectType;
  1113. }
  1114. inline CDacl::CAccessObjectAce &CDacl::CAccessObjectAce::operator=(const CAccessObjectAce &rhs)
  1115. {
  1116. if(this != &rhs)
  1117. {
  1118. CAccessAce::operator=(rhs);
  1119. if(rhs.m_pObjectType)
  1120. {
  1121. if(!m_pObjectType)
  1122. {
  1123. ATLTRY(m_pObjectType = new GUID);
  1124. if(!m_pObjectType)
  1125. AtlThrow(E_OUTOFMEMORY);
  1126. }
  1127. *m_pObjectType = *rhs.m_pObjectType;
  1128. }
  1129. else
  1130. {
  1131. delete m_pObjectType;
  1132. m_pObjectType = NULL;
  1133. }
  1134. if(rhs.m_pInheritedObjectType)
  1135. {
  1136. if(!m_pInheritedObjectType)
  1137. {
  1138. ATLTRY(m_pInheritedObjectType = new GUID);
  1139. if(!m_pInheritedObjectType)
  1140. {
  1141. delete m_pObjectType;
  1142. m_pObjectType = NULL;
  1143. AtlThrow(E_OUTOFMEMORY);
  1144. }
  1145. }
  1146. *m_pInheritedObjectType = *rhs.m_pInheritedObjectType;
  1147. }
  1148. else
  1149. {
  1150. delete m_pInheritedObjectType;
  1151. m_pInheritedObjectType = NULL;
  1152. }
  1153. }
  1154. return *this;
  1155. }
  1156. inline UINT CDacl::CAccessObjectAce::GetLength() const
  1157. {
  1158. UINT nLength = offsetof(ACCESS_ALLOWED_OBJECT_ACE, SidStart);
  1159. if(!m_pObjectType)
  1160. nLength -= sizeof(GUID);
  1161. if(!m_pInheritedObjectType)
  1162. nLength -= sizeof(GUID);
  1163. nLength += m_Sid.GetLength();
  1164. return nLength;
  1165. }
  1166. inline void *CDacl::CAccessObjectAce::GetACE() const
  1167. {
  1168. C_ASSERT(sizeof(ACCESS_ALLOWED_OBJECT_ACE) == sizeof(ACCESS_DENIED_OBJECT_ACE));
  1169. C_ASSERT(offsetof(ACCESS_ALLOWED_OBJECT_ACE, Header)==offsetof(ACCESS_DENIED_OBJECT_ACE, Header));
  1170. C_ASSERT(offsetof(ACCESS_ALLOWED_OBJECT_ACE, Mask)==offsetof(ACCESS_DENIED_OBJECT_ACE, Mask));
  1171. C_ASSERT(offsetof(ACCESS_ALLOWED_OBJECT_ACE, Flags)==offsetof(ACCESS_DENIED_OBJECT_ACE, Flags));
  1172. C_ASSERT(offsetof(ACCESS_ALLOWED_OBJECT_ACE, ObjectType)==offsetof(ACCESS_DENIED_OBJECT_ACE, ObjectType));
  1173. C_ASSERT(offsetof(ACCESS_ALLOWED_OBJECT_ACE, InheritedObjectType)==offsetof(ACCESS_DENIED_OBJECT_ACE, InheritedObjectType));
  1174. C_ASSERT(offsetof(ACCESS_ALLOWED_OBJECT_ACE, SidStart)==offsetof(ACCESS_DENIED_OBJECT_ACE, SidStart));
  1175. if(!m_pAce)
  1176. {
  1177. UINT nLength = GetLength();
  1178. ACCESS_ALLOWED_OBJECT_ACE *pAce = static_cast<ACCESS_ALLOWED_OBJECT_ACE *>(malloc(nLength));
  1179. if(!pAce)
  1180. return NULL;
  1181. memset(pAce, 0x00, nLength);
  1182. pAce->Header.AceSize = static_cast<WORD>(nLength);
  1183. pAce->Header.AceFlags = m_AceFlags;
  1184. pAce->Header.AceType = AceType();
  1185. pAce->Mask = m_dwAccessMask;
  1186. pAce->Flags = 0;
  1187. BYTE *pb = (reinterpret_cast<BYTE *>(pAce)) + offsetof(ACCESS_ALLOWED_OBJECT_ACE, SidStart);
  1188. if(!m_pObjectType)
  1189. pb -= sizeof(GUID);
  1190. else
  1191. {
  1192. pAce->ObjectType = *m_pObjectType;
  1193. pAce->Flags |= ACE_OBJECT_TYPE_PRESENT;
  1194. }
  1195. if(!m_pInheritedObjectType)
  1196. pb -= sizeof(GUID);
  1197. else
  1198. {
  1199. if(m_pObjectType)
  1200. pAce->InheritedObjectType = *m_pInheritedObjectType;
  1201. else
  1202. pAce->ObjectType = *m_pInheritedObjectType;
  1203. pAce->Flags |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
  1204. }
  1205. ATLASSERT(size_t(pb - reinterpret_cast<BYTE *>(pAce)) >= m_Sid.GetLength());
  1206. memcpy(pb, m_Sid.GetPSID(), m_Sid.GetLength());
  1207. m_pAce = pAce;
  1208. }
  1209. return m_pAce;
  1210. }
  1211. #endif // _WIN32_WINNT
  1212. //******************************************
  1213. // CSacl
  1214. class CSacl : public CAcl
  1215. {
  1216. public:
  1217. CSacl(){}
  1218. ~CSacl(){CSacl::RemoveAllAces();}
  1219. CSacl(const ACL &rhs) {Copy(rhs);}
  1220. CSacl &operator=(const ACL &rhs);
  1221. bool AddAuditAce(const CSid &rSid, ACCESS_MASK AccessMask,
  1222. bool bSuccess, bool bFailure, BYTE AceFlags = 0);
  1223. #if(_WIN32_WINNT >= 0x0500)
  1224. bool AddAuditAce(const CSid &rSid, ACCESS_MASK AccessMask,
  1225. bool bSuccess, bool bFailure, BYTE AceFlags,
  1226. const GUID *pObjectType, const GUID *pInheritedObjectType);
  1227. #endif
  1228. void RemoveAllAces();
  1229. UINT GetAceCount() const
  1230. {return m_Acl.GetSize();}
  1231. private:
  1232. void Copy(const ACL &rhs);
  1233. class CAuditAce : public CAcl::CAce
  1234. {
  1235. public:
  1236. CAuditAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags,
  1237. bool bAuditSuccess, bool bAuditFailure)
  1238. : CAce(rSid, AccessMask, AceFlags),
  1239. m_bSuccess(bAuditSuccess), m_bFailure(bAuditFailure){}
  1240. void *GetACE() const;
  1241. UINT GetLength() const
  1242. {return offsetof(SYSTEM_AUDIT_ACE, SidStart) + m_Sid.GetLength();}
  1243. BYTE AceType() const
  1244. {return SYSTEM_AUDIT_ACE_TYPE;}
  1245. protected:
  1246. bool m_bSuccess, m_bFailure;
  1247. };
  1248. #if(_WIN32_WINNT >= 0x0500)
  1249. class CAuditObjectAce : public CAuditAce
  1250. {
  1251. public:
  1252. CAuditObjectAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags,
  1253. bool bAuditSuccess, bool bAuditFailure,
  1254. const GUID *pObjectType, const GUID *pInheritedObjectType);
  1255. ~CAuditObjectAce();
  1256. CAuditObjectAce(const CAuditObjectAce &rhs)
  1257. : CAuditAce(rhs), m_pObjectType(NULL), m_pInheritedObjectType(NULL){*this = rhs;}
  1258. CAuditObjectAce &operator=(const CAuditObjectAce &rhs);
  1259. void *GetACE() const;
  1260. UINT GetLength() const;
  1261. BYTE AceType() const
  1262. {return SYSTEM_AUDIT_OBJECT_ACE_TYPE;}
  1263. bool IsObjectAce() const {return true;}
  1264. protected:
  1265. GUID *m_pObjectType, *m_pInheritedObjectType;
  1266. };
  1267. #endif
  1268. POSITION GetHeadAce() const;
  1269. const CAce *GetAce(UINT nIndex) const
  1270. {return m_Acl[nIndex];}
  1271. void RemoveAce(UINT nIndex);
  1272. CSimpleArray<CAuditAce *> m_Acl;
  1273. };
  1274. inline CSacl &CSacl::operator=(const ACL &rhs)
  1275. {
  1276. RemoveAllAces();
  1277. Copy(rhs);
  1278. return *this;
  1279. }
  1280. inline void CSacl::Copy(const ACL &rhs)
  1281. {
  1282. ACL *pAcl = const_cast<ACL *>(&rhs);
  1283. ACL_SIZE_INFORMATION AclSizeInfo;
  1284. ACE_HEADER *pHeader;
  1285. CSid Sid;
  1286. ACCESS_MASK AccessMask;
  1287. bool bSuccess, bFailure;
  1288. CAuditAce *pAce;
  1289. Dirty();
  1290. if(!::GetAclInformation(pAcl, &AclSizeInfo, sizeof(AclSizeInfo), AclSizeInformation))
  1291. AtlThrowLastWin32();
  1292. for(DWORD i = 0; i < AclSizeInfo.AceCount; i++)
  1293. {
  1294. if(!::GetAce(pAcl, i, reinterpret_cast<void **>(&pHeader)))
  1295. AtlThrowLastWin32();
  1296. AccessMask = *reinterpret_cast<ACCESS_MASK *>
  1297. (reinterpret_cast<BYTE *>(pHeader) + sizeof(ACE_HEADER));
  1298. bSuccess = 0 != (pHeader->AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG);
  1299. bFailure = 0 != (pHeader->AceFlags & FAILED_ACCESS_ACE_FLAG);
  1300. switch(pHeader->AceType)
  1301. {
  1302. case SYSTEM_AUDIT_ACE_TYPE:
  1303. Sid = *reinterpret_cast<SID *>
  1304. (reinterpret_cast<BYTE *>(pHeader) + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK));
  1305. ATLTRY(pAce = new CAuditAce(Sid, AccessMask, pHeader->AceFlags, bSuccess, bFailure));
  1306. if (!pAce)
  1307. AtlThrow(E_OUTOFMEMORY);
  1308. if (!m_Acl.Add(pAce))
  1309. {
  1310. delete pAce;
  1311. AtlThrow(E_OUTOFMEMORY);
  1312. }
  1313. break;
  1314. #if(_WIN32_WINNT >= 0x0500)
  1315. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  1316. {
  1317. GUID *pObjectType = NULL, *pInheritedObjectType = NULL;
  1318. BYTE *pb = reinterpret_cast<BYTE *>
  1319. (pHeader) + offsetof(SYSTEM_AUDIT_OBJECT_ACE, SidStart);
  1320. DWORD dwFlags = reinterpret_cast<SYSTEM_AUDIT_OBJECT_ACE *>(pHeader)->Flags;
  1321. if(dwFlags & ACE_OBJECT_TYPE_PRESENT)
  1322. {
  1323. pObjectType = reinterpret_cast<GUID *>
  1324. (reinterpret_cast<BYTE *>(pHeader) +
  1325. offsetof(SYSTEM_AUDIT_OBJECT_ACE, ObjectType));
  1326. }
  1327. else
  1328. pb -= sizeof(GUID);
  1329. if(dwFlags & ACE_INHERITED_OBJECT_TYPE_PRESENT)
  1330. {
  1331. pInheritedObjectType = reinterpret_cast<GUID *>
  1332. (reinterpret_cast<BYTE *>(pHeader) +
  1333. (pObjectType ?
  1334. offsetof(SYSTEM_AUDIT_OBJECT_ACE, InheritedObjectType) :
  1335. offsetof(SYSTEM_AUDIT_OBJECT_ACE, ObjectType)));
  1336. }
  1337. else
  1338. pb -= sizeof(GUID);
  1339. Sid = *reinterpret_cast<SID *>(pb);
  1340. ATLTRY(pAce = new CAuditObjectAce(Sid, AccessMask, pHeader->AceFlags,
  1341. bSuccess, bFailure, pObjectType, pInheritedObjectType));
  1342. if(!pAce)
  1343. AtlThrow(E_OUTOFMEMORY);
  1344. if (!m_Acl.Add(pAce))
  1345. {
  1346. delete pAce;
  1347. AtlThrow(E_OUTOFMEMORY);
  1348. }
  1349. break;
  1350. }
  1351. #endif
  1352. default:
  1353. // Wrong ACE type
  1354. ATLASSERT(false);
  1355. }
  1356. }
  1357. }
  1358. inline bool CSacl::AddAuditAce(const CSid &rSid, ACCESS_MASK AccessMask,
  1359. bool bSuccess, bool bFailure, BYTE AceFlags)
  1360. {
  1361. ATLASSERT(rSid.IsValid());
  1362. if(IsNull() || !rSid.IsValid())
  1363. return false;
  1364. CAuditAce *pAce;
  1365. ATLTRY(pAce = new CAuditAce(rSid, AccessMask, AceFlags, bSuccess, bFailure));
  1366. if(!pAce)
  1367. return false;
  1368. if (!m_Acl.Add(pAce))
  1369. {
  1370. delete pAce;
  1371. return false;
  1372. }
  1373. Dirty();
  1374. return true;
  1375. }
  1376. #if(_WIN32_WINNT >= 0x0500)
  1377. inline bool CSacl::AddAuditAce(const CSid &rSid, ACCESS_MASK AccessMask,
  1378. bool bSuccess, bool bFailure, BYTE AceFlags,
  1379. const GUID *pObjectType, const GUID *pInheritedObjectType)
  1380. {
  1381. if(!pObjectType && !pInheritedObjectType)
  1382. return AddAuditAce(rSid, AccessMask, bSuccess, bFailure, AceFlags);
  1383. ATLASSERT(rSid.IsValid());
  1384. if(IsNull() || !rSid.IsValid())
  1385. return false;
  1386. CAuditAce *pAce;
  1387. ATLTRY(pAce = new CAuditObjectAce(rSid, AccessMask, AceFlags, bSuccess,
  1388. bFailure, pObjectType, pInheritedObjectType));
  1389. if(!pAce)
  1390. return false;
  1391. if (!m_Acl.Add(pAce))
  1392. {
  1393. delete pAce;
  1394. return false;
  1395. }
  1396. m_dwAclRevision = ACL_REVISION_DS;
  1397. Dirty();
  1398. return true;
  1399. }
  1400. #endif
  1401. inline void CSacl::RemoveAllAces()
  1402. {
  1403. const UINT nCount = GetAceCount();
  1404. for(UINT i = 0; i < nCount; i++)
  1405. delete GetAce(i);
  1406. m_Acl.RemoveAll();
  1407. Dirty();
  1408. }
  1409. inline void CSacl::RemoveAce(UINT nIndex)
  1410. {
  1411. delete GetAce(nIndex);
  1412. m_Acl.RemoveAt(nIndex);
  1413. }
  1414. inline void *CSacl::CAuditAce::GetACE() const
  1415. {
  1416. if(!m_pAce)
  1417. {
  1418. UINT nLength = GetLength();
  1419. SYSTEM_AUDIT_ACE *pAce = static_cast<SYSTEM_AUDIT_ACE *>(malloc(nLength));
  1420. if(!pAce)
  1421. return NULL;
  1422. memset(pAce, 0x00, nLength);
  1423. pAce->Header.AceSize = static_cast<WORD>(nLength);
  1424. pAce->Header.AceFlags = m_AceFlags;
  1425. pAce->Header.AceType = AceType();;
  1426. pAce->Mask = m_dwAccessMask;
  1427. ATLASSERT(nLength-offsetof(SYSTEM_AUDIT_ACE, SidStart) >= m_Sid.GetLength());
  1428. memcpy(&pAce->SidStart, m_Sid.GetPSID(), m_Sid.GetLength());
  1429. if(m_bSuccess)
  1430. pAce->Header.AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
  1431. else
  1432. pAce->Header.AceFlags &= ~SUCCESSFUL_ACCESS_ACE_FLAG;
  1433. if(m_bFailure)
  1434. pAce->Header.AceFlags |= FAILED_ACCESS_ACE_FLAG;
  1435. else
  1436. pAce->Header.AceFlags &= ~FAILED_ACCESS_ACE_FLAG;
  1437. m_pAce = pAce;
  1438. }
  1439. return m_pAce;
  1440. }
  1441. #if(_WIN32_WINNT >= 0x0500)
  1442. inline CSacl::CAuditObjectAce::CAuditObjectAce(const CSid &rSid, ACCESS_MASK AccessMask, BYTE AceFlags,
  1443. bool bAuditSuccess, bool bAuditFailure, const GUID *pObjectType, const GUID *pInheritedObjectType)
  1444. : CAuditAce(rSid, AccessMask, AceFlags, bAuditSuccess, bAuditFailure)
  1445. {
  1446. if(pObjectType)
  1447. {
  1448. ATLTRY(m_pObjectType = new GUID(*pObjectType));
  1449. if(!m_pObjectType)
  1450. AtlThrow(E_OUTOFMEMORY);
  1451. }
  1452. if(pInheritedObjectType)
  1453. {
  1454. ATLTRY(m_pInheritedObjectType = new GUID(*pInheritedObjectType));
  1455. if(!m_pInheritedObjectType)
  1456. {
  1457. delete m_pObjectType;
  1458. m_pObjectType = NULL;
  1459. AtlThrow(E_OUTOFMEMORY);
  1460. }
  1461. }
  1462. }
  1463. inline CSacl::CAuditObjectAce::~CAuditObjectAce()
  1464. {
  1465. delete m_pObjectType;
  1466. delete m_pInheritedObjectType;
  1467. }
  1468. inline CSacl::CAuditObjectAce &CSacl::CAuditObjectAce::operator=(const CAuditObjectAce &rhs)
  1469. {
  1470. if(this != &rhs)
  1471. {
  1472. CAuditAce::operator=(rhs);
  1473. if(rhs.m_pObjectType)
  1474. {
  1475. if(!m_pObjectType)
  1476. {
  1477. ATLTRY(m_pObjectType = new GUID);
  1478. if(!m_pObjectType)
  1479. AtlThrow(E_OUTOFMEMORY);
  1480. }
  1481. *m_pObjectType = *rhs.m_pObjectType;
  1482. }
  1483. else
  1484. {
  1485. delete m_pObjectType;
  1486. m_pObjectType = NULL;
  1487. }
  1488. if(rhs.m_pInheritedObjectType)
  1489. {
  1490. if(!m_pInheritedObjectType)
  1491. {
  1492. ATLTRY(m_pInheritedObjectType = new GUID);
  1493. if(!m_pInheritedObjectType)
  1494. {
  1495. delete m_pObjectType;
  1496. m_pObjectType = NULL;
  1497. AtlThrow(E_OUTOFMEMORY);
  1498. }
  1499. }
  1500. *m_pInheritedObjectType = *rhs.m_pInheritedObjectType;
  1501. }
  1502. else
  1503. {
  1504. delete m_pInheritedObjectType;
  1505. m_pInheritedObjectType = NULL;
  1506. }
  1507. }
  1508. return *this;
  1509. }
  1510. inline UINT CSacl::CAuditObjectAce::GetLength() const
  1511. {
  1512. UINT nLength = offsetof(SYSTEM_AUDIT_OBJECT_ACE, SidStart);
  1513. if(!m_pObjectType)
  1514. nLength -= sizeof(GUID);
  1515. if(!m_pInheritedObjectType)
  1516. nLength -= sizeof(GUID);
  1517. nLength += m_Sid.GetLength();
  1518. return nLength;
  1519. }
  1520. inline void *CSacl::CAuditObjectAce::GetACE() const
  1521. {
  1522. if(!m_pAce)
  1523. {
  1524. UINT nLength = GetLength();
  1525. SYSTEM_AUDIT_OBJECT_ACE *pAce = static_cast<SYSTEM_AUDIT_OBJECT_ACE *>(malloc(nLength));
  1526. if(!pAce)
  1527. return NULL;
  1528. memset(pAce, 0x00, nLength);
  1529. pAce->Header.AceType = SYSTEM_AUDIT_OBJECT_ACE_TYPE;
  1530. pAce->Header.AceSize = static_cast<WORD>(nLength);
  1531. pAce->Header.AceFlags = m_AceFlags;
  1532. pAce->Mask = m_dwAccessMask;
  1533. pAce->Flags = 0;
  1534. if(m_bSuccess)
  1535. pAce->Header.AceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
  1536. else
  1537. pAce->Header.AceFlags &= ~SUCCESSFUL_ACCESS_ACE_FLAG;
  1538. if(m_bFailure)
  1539. pAce->Header.AceFlags |= FAILED_ACCESS_ACE_FLAG;
  1540. else
  1541. pAce->Header.AceFlags &= ~FAILED_ACCESS_ACE_FLAG;
  1542. BYTE *pb = ((BYTE *) pAce) + offsetof(SYSTEM_AUDIT_OBJECT_ACE, SidStart);
  1543. if(!m_pObjectType)
  1544. pb -= sizeof(GUID);
  1545. else
  1546. {
  1547. pAce->ObjectType = *m_pObjectType;
  1548. pAce->Flags |= ACE_OBJECT_TYPE_PRESENT;
  1549. }
  1550. if(!m_pInheritedObjectType)
  1551. pb -= sizeof(GUID);
  1552. else
  1553. {
  1554. if(m_pObjectType)
  1555. pAce->InheritedObjectType = *m_pInheritedObjectType;
  1556. else
  1557. pAce->ObjectType = *m_pInheritedObjectType;
  1558. pAce->Flags |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
  1559. }
  1560. ATLASSERT(size_t(pb - reinterpret_cast<BYTE*>(pAce)) >= m_Sid.GetLength());
  1561. memcpy(pb, m_Sid.GetPSID(), m_Sid.GetLength());
  1562. m_pAce = pAce;
  1563. }
  1564. return m_pAce;
  1565. }
  1566. #endif
  1567. //******************************************
  1568. // CSecurityDesc
  1569. class CSecurityDesc
  1570. {
  1571. public:
  1572. CSecurityDesc() : m_pSecurityDescriptor(NULL){}
  1573. virtual ~CSecurityDesc() {Clear();}
  1574. CSecurityDesc(const CSecurityDesc &rhs);
  1575. CSecurityDesc &operator=(const CSecurityDesc &rhs);
  1576. CSecurityDesc(const SECURITY_DESCRIPTOR &rhs);
  1577. CSecurityDesc &operator=(const SECURITY_DESCRIPTOR &rhs);
  1578. #if(_WIN32_WINNT >= 0x0500)
  1579. bool FromString(LPCTSTR pstr);
  1580. bool ToString(CString *pstr,
  1581. SECURITY_INFORMATION si =
  1582. OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
  1583. DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION) const;
  1584. #endif
  1585. bool SetOwner(const CSid &Sid, bool bDefaulted = false);
  1586. bool SetGroup(const CSid &Sid, bool bDefaulted = false);
  1587. bool SetDacl(const CDacl &Dacl, bool bDefaulted = false);
  1588. bool SetDacl(bool bPresent, bool bDefaulted = false);
  1589. bool SetSacl(const CSacl &Sacl, bool bDefaulted = false);
  1590. bool GetOwner(CSid *pSid, bool *pbDefaulted = NULL) const;
  1591. bool GetGroup(CSid *pSid, bool *pbDefaulted = NULL) const;
  1592. bool GetDacl(CDacl *pDacl, bool *pbPresent = NULL, bool *pbDefaulted = NULL) const;
  1593. bool GetSacl(CSacl *pSacl, bool *pbPresent = NULL, bool *pbDefaulted = NULL) const;
  1594. bool IsDaclDefaulted() const;
  1595. bool IsDaclPresent() const;
  1596. bool IsGroupDefaulted() const;
  1597. bool IsOwnerDefaulted() const;
  1598. bool IsSaclDefaulted() const;
  1599. bool IsSaclPresent() const;
  1600. bool IsSelfRelative() const;
  1601. // Only meaningful on Win2k or better
  1602. bool IsDaclAutoInherited() const;
  1603. bool IsDaclProtected() const;
  1604. bool IsSaclAutoInherited() const;
  1605. bool IsSaclProtected() const;
  1606. const SECURITY_DESCRIPTOR *GetPSECURITY_DESCRIPTOR() const
  1607. {return m_pSecurityDescriptor;}
  1608. operator const SECURITY_DESCRIPTOR *() const {return GetPSECURITY_DESCRIPTOR();}
  1609. bool GetSECURITY_DESCRIPTOR(SECURITY_DESCRIPTOR *pSD, LPDWORD lpdwBufferLength);
  1610. bool GetControl(SECURITY_DESCRIPTOR_CONTROL *psdc) const;
  1611. #if(_WIN32_WINNT >= 0x0500)
  1612. bool SetControl(SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
  1613. SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet);
  1614. #endif
  1615. bool MakeSelfRelative();
  1616. bool MakeAbsolute();
  1617. protected:
  1618. virtual void Clear();
  1619. bool AllocateAndInitializeSecurityDescriptor();
  1620. void Init(const SECURITY_DESCRIPTOR &rhs);
  1621. SECURITY_DESCRIPTOR *m_pSecurityDescriptor;
  1622. };
  1623. class CSecurityAttributes : public SECURITY_ATTRIBUTES
  1624. {
  1625. public:
  1626. CSecurityAttributes()
  1627. {nLength = 0; lpSecurityDescriptor = NULL; bInheritHandle = FALSE;}
  1628. explicit CSecurityAttributes(const CSecurityDesc &rSecurityDescriptor, bool bInheritHandle = false) :
  1629. m_SecurityDescriptor(rSecurityDescriptor)
  1630. {
  1631. Set(m_SecurityDescriptor, bInheritHandle);
  1632. }
  1633. void Set(const CSecurityDesc &rSecurityDescriptor, bool bInheritHandle = false)
  1634. {
  1635. m_SecurityDescriptor = rSecurityDescriptor;
  1636. nLength = sizeof(SECURITY_ATTRIBUTES);
  1637. lpSecurityDescriptor = const_cast<SECURITY_DESCRIPTOR *>
  1638. (m_SecurityDescriptor.GetPSECURITY_DESCRIPTOR());
  1639. this->bInheritHandle = bInheritHandle;
  1640. }
  1641. protected:
  1642. CSecurityDesc m_SecurityDescriptor;
  1643. };
  1644. inline CSecurityDesc::CSecurityDesc(const CSecurityDesc &rhs)
  1645. : m_pSecurityDescriptor(NULL)
  1646. {
  1647. if(rhs.m_pSecurityDescriptor)
  1648. Init(*rhs.m_pSecurityDescriptor);
  1649. }
  1650. inline CSecurityDesc &CSecurityDesc::operator=(const CSecurityDesc &rhs)
  1651. {
  1652. if(this != &rhs)
  1653. {
  1654. Clear();
  1655. if(rhs.m_pSecurityDescriptor)
  1656. Init(*rhs.m_pSecurityDescriptor);
  1657. }
  1658. return *this;
  1659. }
  1660. inline CSecurityDesc::CSecurityDesc(const SECURITY_DESCRIPTOR &rhs)
  1661. : m_pSecurityDescriptor(NULL)
  1662. {
  1663. Init(rhs);
  1664. }
  1665. inline CSecurityDesc &CSecurityDesc::operator=(const SECURITY_DESCRIPTOR &rhs)
  1666. {
  1667. if(m_pSecurityDescriptor != &rhs)
  1668. {
  1669. Clear();
  1670. Init(rhs);
  1671. }
  1672. return *this;
  1673. }
  1674. inline void CSecurityDesc::Init(const SECURITY_DESCRIPTOR &rhs)
  1675. {
  1676. SECURITY_DESCRIPTOR *pSD = const_cast<SECURITY_DESCRIPTOR *>(&rhs);
  1677. DWORD dwRev, dwLen = ::GetSecurityDescriptorLength(pSD);
  1678. m_pSecurityDescriptor = static_cast<SECURITY_DESCRIPTOR *>(malloc(dwLen));
  1679. if(!m_pSecurityDescriptor)
  1680. AtlThrow(E_OUTOFMEMORY);
  1681. SECURITY_DESCRIPTOR_CONTROL sdc;
  1682. if(!::GetSecurityDescriptorControl(pSD, &sdc, &dwRev))
  1683. {
  1684. HRESULT hr = AtlHresultFromLastError();
  1685. free(m_pSecurityDescriptor);
  1686. m_pSecurityDescriptor = NULL;
  1687. AtlThrow(hr);
  1688. }
  1689. if(sdc & SE_SELF_RELATIVE)
  1690. memcpy(m_pSecurityDescriptor, pSD, dwLen);
  1691. else
  1692. {
  1693. if(!::MakeSelfRelativeSD(pSD, m_pSecurityDescriptor, &dwLen))
  1694. {
  1695. HRESULT hr = AtlHresultFromLastError();
  1696. free(m_pSecurityDescriptor);
  1697. m_pSecurityDescriptor = NULL;
  1698. AtlThrow(hr);
  1699. }
  1700. }
  1701. }
  1702. inline void CSecurityDesc::Clear()
  1703. {
  1704. if(m_pSecurityDescriptor)
  1705. {
  1706. SECURITY_DESCRIPTOR_CONTROL sdc;
  1707. if(GetControl(&sdc) && !(sdc & SE_SELF_RELATIVE))
  1708. {
  1709. PSID pOwner, pGroup;
  1710. ACL *pDacl, *pSacl;
  1711. BOOL bDefaulted, bPresent;
  1712. ::GetSecurityDescriptorOwner(m_pSecurityDescriptor, &pOwner, &bDefaulted);
  1713. free(pOwner);
  1714. ::GetSecurityDescriptorGroup(m_pSecurityDescriptor, &pGroup, &bDefaulted);
  1715. free(pGroup);
  1716. ::GetSecurityDescriptorDacl(m_pSecurityDescriptor, &bPresent, &pDacl, &bDefaulted);
  1717. if(bPresent)
  1718. free(pDacl);
  1719. ::GetSecurityDescriptorSacl(m_pSecurityDescriptor, &bPresent, &pSacl, &bDefaulted);
  1720. if(bPresent)
  1721. free(pSacl);
  1722. }
  1723. free(m_pSecurityDescriptor);
  1724. m_pSecurityDescriptor = NULL;
  1725. }
  1726. }
  1727. inline bool CSecurityDesc::MakeSelfRelative()
  1728. {
  1729. SECURITY_DESCRIPTOR_CONTROL sdc;
  1730. if(!m_pSecurityDescriptor || !GetControl(&sdc))
  1731. return false;
  1732. if(sdc & SE_SELF_RELATIVE)
  1733. return true;
  1734. SECURITY_DESCRIPTOR *pSD;
  1735. DWORD dwLen = 0;
  1736. ::MakeSelfRelativeSD(m_pSecurityDescriptor, NULL, &dwLen);
  1737. if(::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  1738. return false;
  1739. pSD = static_cast<SECURITY_DESCRIPTOR *>(malloc(dwLen));
  1740. if(!pSD)
  1741. return false;
  1742. if(!::MakeSelfRelativeSD(m_pSecurityDescriptor, pSD, &dwLen))
  1743. {
  1744. free(pSD);
  1745. return false;
  1746. }
  1747. Clear();
  1748. m_pSecurityDescriptor = pSD;
  1749. return true;
  1750. }
  1751. inline bool CSecurityDesc::MakeAbsolute()
  1752. {
  1753. SECURITY_DESCRIPTOR_CONTROL sdc;
  1754. if(!m_pSecurityDescriptor || !GetControl(&sdc))
  1755. return false;
  1756. if(!(sdc & SE_SELF_RELATIVE))
  1757. return true;
  1758. SECURITY_DESCRIPTOR *pSD;
  1759. SID *pOwner, *pGroup;
  1760. ACL *pDacl, *pSacl;
  1761. DWORD dwSD, dwOwner, dwGroup, dwDacl, dwSacl;
  1762. dwSD = dwOwner = dwGroup = dwDacl = dwSacl = 0;
  1763. ::MakeAbsoluteSD(m_pSecurityDescriptor, NULL, &dwSD, NULL, &dwDacl,
  1764. NULL, &dwSacl, NULL, &dwOwner, NULL, &dwGroup);
  1765. if(::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  1766. return false;
  1767. pSD = static_cast<SECURITY_DESCRIPTOR *>(malloc(dwSD));
  1768. pOwner = static_cast<SID *>(dwOwner ? malloc(dwOwner) : NULL);
  1769. pGroup = static_cast<SID *>(dwGroup ? malloc(dwGroup) : NULL);
  1770. pDacl = static_cast<ACL *>(dwDacl ? malloc(dwDacl) : NULL);
  1771. pSacl = static_cast<ACL *>(dwSacl ? malloc(dwSacl) : NULL);
  1772. if(!::MakeAbsoluteSD(m_pSecurityDescriptor,
  1773. pSD, &dwSD,
  1774. pDacl, &dwDacl,
  1775. pSacl, &dwSacl,
  1776. pOwner, &dwOwner,
  1777. pGroup, &dwGroup))
  1778. {
  1779. free(pSD);
  1780. free(pOwner);
  1781. free(pGroup);
  1782. free(pDacl);
  1783. free(pSacl);
  1784. return false;
  1785. }
  1786. Clear();
  1787. m_pSecurityDescriptor = pSD;
  1788. return true;
  1789. }
  1790. inline bool CSecurityDesc::AllocateAndInitializeSecurityDescriptor()
  1791. {
  1792. // m_pSecurityDescriptor should be NULL.
  1793. ATLASSERT(!m_pSecurityDescriptor);
  1794. m_pSecurityDescriptor = static_cast<SECURITY_DESCRIPTOR *>(malloc(sizeof(SECURITY_DESCRIPTOR)));
  1795. if(!m_pSecurityDescriptor)
  1796. return false;
  1797. if(!::InitializeSecurityDescriptor(m_pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
  1798. {
  1799. free(m_pSecurityDescriptor);
  1800. m_pSecurityDescriptor = NULL;
  1801. return false;
  1802. }
  1803. return true;
  1804. }
  1805. #if(_WIN32_WINNT >= 0x0500)
  1806. inline bool CSecurityDesc::FromString(LPCTSTR pstr)
  1807. {
  1808. SECURITY_DESCRIPTOR *pSD;
  1809. if(!::ConvertStringSecurityDescriptorToSecurityDescriptor(pstr, SDDL_REVISION_1,
  1810. (PSECURITY_DESCRIPTOR *) &pSD, NULL))
  1811. {
  1812. return false;
  1813. }
  1814. *this = *pSD;
  1815. ::LocalFree(pSD);
  1816. return true;
  1817. }
  1818. inline bool CSecurityDesc::ToString(CString *pstr, SECURITY_INFORMATION si) const
  1819. {
  1820. ATLASSERT(pstr);
  1821. if(!pstr || !m_pSecurityDescriptor)
  1822. return false;
  1823. LPTSTR pszStringSecurityDescriptor;
  1824. if(!::ConvertSecurityDescriptorToStringSecurityDescriptor(m_pSecurityDescriptor,
  1825. SDDL_REVISION_1,
  1826. si,
  1827. &pszStringSecurityDescriptor,
  1828. NULL))
  1829. {
  1830. return false;
  1831. }
  1832. *pstr = pszStringSecurityDescriptor;
  1833. ::LocalFree(pszStringSecurityDescriptor);
  1834. return true;
  1835. }
  1836. #endif
  1837. inline bool CSecurityDesc::GetSECURITY_DESCRIPTOR(SECURITY_DESCRIPTOR *pSD, LPDWORD lpdwBufferLength)
  1838. {
  1839. ATLASSERT(lpdwBufferLength);
  1840. if(!lpdwBufferLength)
  1841. return false;
  1842. if(!MakeAbsolute())
  1843. return false;
  1844. return 0 != ::MakeSelfRelativeSD(m_pSecurityDescriptor, pSD, lpdwBufferLength);
  1845. }
  1846. inline bool CSecurityDesc::SetOwner(const CSid &Sid, bool bDefaulted)
  1847. {
  1848. if(m_pSecurityDescriptor && !MakeAbsolute())
  1849. return false;
  1850. PSID pNewOwner, pOldOwner;
  1851. if(m_pSecurityDescriptor)
  1852. {
  1853. BOOL bDefaulted;
  1854. if(!::GetSecurityDescriptorOwner(m_pSecurityDescriptor, &pOldOwner, &bDefaulted))
  1855. return false;
  1856. }
  1857. else
  1858. {
  1859. if(!AllocateAndInitializeSecurityDescriptor())
  1860. return false;
  1861. pOldOwner = NULL;
  1862. }
  1863. if(!Sid.IsValid())
  1864. return false;
  1865. UINT nSidLength = Sid.GetLength();
  1866. pNewOwner = malloc(nSidLength);
  1867. if(!pNewOwner)
  1868. return false;
  1869. if(!::CopySid(nSidLength, pNewOwner, const_cast<SID *>(Sid.GetPSID())) ||
  1870. !::SetSecurityDescriptorOwner(m_pSecurityDescriptor, pNewOwner, bDefaulted))
  1871. {
  1872. free(pNewOwner);
  1873. return false;
  1874. }
  1875. free(pOldOwner);
  1876. return true;
  1877. }
  1878. inline bool CSecurityDesc::SetGroup(const CSid &Sid, bool bDefaulted)
  1879. {
  1880. if(m_pSecurityDescriptor && !MakeAbsolute())
  1881. return false;
  1882. PSID pNewGroup, pOldGroup;
  1883. if(m_pSecurityDescriptor)
  1884. {
  1885. BOOL bDefaulted;
  1886. if(!::GetSecurityDescriptorGroup(m_pSecurityDescriptor, &pOldGroup, &bDefaulted))
  1887. return false;
  1888. }
  1889. else
  1890. {
  1891. if(!AllocateAndInitializeSecurityDescriptor())
  1892. return false;
  1893. pOldGroup = NULL;
  1894. }
  1895. if(!Sid.IsValid())
  1896. return false;
  1897. UINT nSidLength = Sid.GetLength();
  1898. pNewGroup = malloc(nSidLength);
  1899. if(!pNewGroup)
  1900. return false;
  1901. if(!::CopySid(nSidLength, pNewGroup, const_cast<SID *>(Sid.GetPSID())) ||
  1902. !::SetSecurityDescriptorGroup(m_pSecurityDescriptor, pNewGroup, bDefaulted))
  1903. {
  1904. free(pNewGroup);
  1905. return false;
  1906. }
  1907. free(pOldGroup);
  1908. return true;
  1909. }
  1910. inline bool CSecurityDesc::SetDacl(bool bPresent, bool bDefaulted)
  1911. {
  1912. if(m_pSecurityDescriptor && !MakeAbsolute())
  1913. return false;
  1914. PACL pOldDacl = NULL;
  1915. if(m_pSecurityDescriptor)
  1916. {
  1917. BOOL bDefaulted, bPresent;
  1918. if(!::GetSecurityDescriptorDacl(m_pSecurityDescriptor, &bPresent, &pOldDacl, &bDefaulted))
  1919. return false;
  1920. }
  1921. else
  1922. if(!AllocateAndInitializeSecurityDescriptor())
  1923. return false;
  1924. #ifdef _DEBUG
  1925. if(bPresent)
  1926. ATLTRACE(atlTraceSecurity, 2, _T("Caution: Setting Dacl to Null\n"));
  1927. #endif
  1928. if(!::SetSecurityDescriptorDacl(m_pSecurityDescriptor, bPresent, NULL, bDefaulted))
  1929. return false;
  1930. free(pOldDacl);
  1931. return true;
  1932. }
  1933. inline bool CSecurityDesc::SetDacl(const CDacl &Dacl, bool bDefaulted)
  1934. {
  1935. if(m_pSecurityDescriptor && !MakeAbsolute())
  1936. return false;
  1937. PACL pNewDacl, pOldDacl = NULL;
  1938. if(m_pSecurityDescriptor)
  1939. {
  1940. BOOL bDefaulted, bPresent;
  1941. if(!::GetSecurityDescriptorDacl(m_pSecurityDescriptor, &bPresent, &pOldDacl, &bDefaulted))
  1942. return false;
  1943. }
  1944. else if(!AllocateAndInitializeSecurityDescriptor())
  1945. return false;
  1946. if(Dacl.IsNull() || Dacl.IsEmpty())
  1947. pNewDacl = NULL;
  1948. else
  1949. {
  1950. UINT nAclLength = Dacl.GetLength();
  1951. if(!nAclLength)
  1952. return false;
  1953. pNewDacl = static_cast<ACL *>(malloc(nAclLength));
  1954. if(!pNewDacl)
  1955. return false;
  1956. memcpy(pNewDacl, Dacl.GetPACL(), nAclLength);
  1957. }
  1958. #ifdef _DEBUG
  1959. if(Dacl.IsNull())
  1960. ATLTRACE(atlTraceSecurity, 2, _T("Caution: Setting Dacl to Null\n"));
  1961. #endif
  1962. if(!::SetSecurityDescriptorDacl(m_pSecurityDescriptor, Dacl.IsNull() || pNewDacl, pNewDacl, bDefaulted))
  1963. {
  1964. free(pNewDacl);
  1965. return false;
  1966. }
  1967. free(pOldDacl);
  1968. return true;
  1969. }
  1970. inline bool CSecurityDesc::SetSacl(const CSacl &Sacl, bool bDefaulted)
  1971. {
  1972. if(m_pSecurityDescriptor && !MakeAbsolute())
  1973. return false;
  1974. PACL pNewSacl, pOldSacl = NULL;
  1975. if(m_pSecurityDescriptor)
  1976. {
  1977. BOOL bDefaulted, bPresent;
  1978. if(!::GetSecurityDescriptorSacl(m_pSecurityDescriptor, &bPresent, &pOldSacl, &bDefaulted))
  1979. return false;
  1980. }
  1981. else if(!AllocateAndInitializeSecurityDescriptor())
  1982. return false;
  1983. if(Sacl.IsNull() || Sacl.IsEmpty())
  1984. pNewSacl = NULL;
  1985. else
  1986. {
  1987. UINT nAclLength = Sacl.GetLength();
  1988. if(!nAclLength)
  1989. return false;
  1990. pNewSacl = static_cast<ACL *>(malloc(nAclLength));
  1991. if(!pNewSacl)
  1992. return false;
  1993. memcpy(pNewSacl, Sacl.GetPACL(), nAclLength);
  1994. }
  1995. if(!::SetSecurityDescriptorSacl(m_pSecurityDescriptor, Sacl.IsNull() || pNewSacl, pNewSacl, bDefaulted))
  1996. {
  1997. free(pNewSacl);
  1998. return false;
  1999. }
  2000. free(pOldSacl);
  2001. return true;
  2002. }
  2003. inline bool CSecurityDesc::GetOwner(CSid *pSid, bool *pbDefaulted) const
  2004. {
  2005. ATLASSERT(pSid);
  2006. SID *pOwner;
  2007. BOOL bDefaulted;
  2008. if(!pSid || !m_pSecurityDescriptor ||
  2009. !::GetSecurityDescriptorOwner(m_pSecurityDescriptor, (PSID *) &pOwner, &bDefaulted))
  2010. {
  2011. return false;
  2012. }
  2013. *pSid = *pOwner;
  2014. if(pbDefaulted)
  2015. *pbDefaulted = 0 != bDefaulted;
  2016. return true;
  2017. }
  2018. inline bool CSecurityDesc::GetGroup(CSid *pSid, bool *pbDefaulted) const
  2019. {
  2020. ATLASSERT(pSid);
  2021. SID *pGroup;
  2022. BOOL bDefaulted;
  2023. if(!pSid || !m_pSecurityDescriptor ||
  2024. !::GetSecurityDescriptorGroup(m_pSecurityDescriptor, (PSID *) &pGroup, &bDefaulted))
  2025. {
  2026. return false;
  2027. }
  2028. *pSid = *pGroup;
  2029. if(pbDefaulted)
  2030. *pbDefaulted = 0 != bDefaulted;
  2031. return true;
  2032. }
  2033. inline bool CSecurityDesc::GetDacl(CDacl *pDacl, bool *pbPresent, bool *pbDefaulted) const
  2034. {
  2035. ACL *pAcl;
  2036. BOOL bPresent, bDefaulted;
  2037. if(!m_pSecurityDescriptor ||
  2038. !::GetSecurityDescriptorDacl(m_pSecurityDescriptor, &bPresent, &pAcl, &bDefaulted) ||
  2039. !bPresent)
  2040. {
  2041. return false;
  2042. }
  2043. if(pDacl)
  2044. {
  2045. if(bPresent)
  2046. {
  2047. if(pAcl)
  2048. *pDacl = *pAcl;
  2049. else
  2050. pDacl->SetNull();
  2051. }
  2052. else
  2053. pDacl->SetEmpty();
  2054. }
  2055. if(pbPresent)
  2056. *pbPresent = 0 != bPresent;
  2057. if(pbDefaulted)
  2058. *pbDefaulted = 0 != bDefaulted;
  2059. return true;
  2060. }
  2061. inline bool CSecurityDesc::GetSacl(CSacl *pSacl, bool *pbPresent, bool *pbDefaulted) const
  2062. {
  2063. ACL *pAcl;
  2064. BOOL bPresent, bDefaulted;
  2065. if(!m_pSecurityDescriptor ||
  2066. !::GetSecurityDescriptorSacl(m_pSecurityDescriptor, &bPresent, &pAcl, &bDefaulted) ||
  2067. !bPresent)
  2068. {
  2069. return false;
  2070. }
  2071. if(pSacl)
  2072. {
  2073. if(bPresent)
  2074. {
  2075. if(pAcl)
  2076. *pSacl = *pAcl;
  2077. else
  2078. pSacl->SetNull();
  2079. }
  2080. else
  2081. pSacl->SetEmpty();
  2082. }
  2083. if(pbPresent)
  2084. *pbPresent = 0 != bPresent;
  2085. if(pbDefaulted)
  2086. *pbDefaulted = 0 != bDefaulted;
  2087. return true;
  2088. }
  2089. inline bool CSecurityDesc::IsDaclDefaulted() const
  2090. {
  2091. SECURITY_DESCRIPTOR_CONTROL sdc;
  2092. if(!GetControl(&sdc))
  2093. return false;
  2094. return (sdc & SE_DACL_PRESENT) &&
  2095. (sdc & SE_DACL_DEFAULTED);
  2096. }
  2097. inline bool CSecurityDesc::IsDaclPresent() const
  2098. {
  2099. SECURITY_DESCRIPTOR_CONTROL sdc;
  2100. if(!GetControl(&sdc))
  2101. return false;
  2102. return 0 != (sdc & SE_DACL_PRESENT);
  2103. }
  2104. inline bool CSecurityDesc::IsGroupDefaulted() const
  2105. {
  2106. SECURITY_DESCRIPTOR_CONTROL sdc;
  2107. if(!GetControl(&sdc))
  2108. return false;
  2109. return 0 != (sdc & SE_GROUP_DEFAULTED);
  2110. }
  2111. inline bool CSecurityDesc::IsOwnerDefaulted() const
  2112. {
  2113. SECURITY_DESCRIPTOR_CONTROL sdc;
  2114. if(!GetControl(&sdc))
  2115. return false;
  2116. return (sdc & SE_OWNER_DEFAULTED);
  2117. }
  2118. inline bool CSecurityDesc::IsSaclDefaulted() const
  2119. {
  2120. SECURITY_DESCRIPTOR_CONTROL sdc;
  2121. if(!GetControl(&sdc))
  2122. return false;
  2123. return (sdc & SE_SACL_PRESENT) &&
  2124. (sdc & SE_SACL_DEFAULTED);
  2125. }
  2126. inline bool CSecurityDesc::IsSaclPresent() const
  2127. {
  2128. SECURITY_DESCRIPTOR_CONTROL sdc;
  2129. if(!GetControl(&sdc))
  2130. return false;
  2131. return 0 != (sdc & SE_SACL_PRESENT);
  2132. }
  2133. inline bool CSecurityDesc::IsSelfRelative() const
  2134. {
  2135. SECURITY_DESCRIPTOR_CONTROL sdc;
  2136. if(!GetControl(&sdc))
  2137. return false;
  2138. return 0 != (sdc & SE_SELF_RELATIVE);
  2139. }
  2140. inline bool CSecurityDesc::IsDaclAutoInherited() const
  2141. {
  2142. SECURITY_DESCRIPTOR_CONTROL sdc;
  2143. if(!GetControl(&sdc))
  2144. return false;
  2145. return 0 != (sdc & SE_DACL_AUTO_INHERITED);
  2146. }
  2147. inline bool CSecurityDesc::IsDaclProtected() const
  2148. {
  2149. SECURITY_DESCRIPTOR_CONTROL sdc;
  2150. if(!GetControl(&sdc))
  2151. return false;
  2152. return 0 != (sdc & SE_DACL_PROTECTED);
  2153. }
  2154. inline bool CSecurityDesc::IsSaclAutoInherited() const
  2155. {
  2156. SECURITY_DESCRIPTOR_CONTROL sdc;
  2157. if(!GetControl(&sdc))
  2158. return false;
  2159. return 0 != (sdc & SE_SACL_AUTO_INHERITED);
  2160. }
  2161. inline bool CSecurityDesc::IsSaclProtected() const
  2162. {
  2163. SECURITY_DESCRIPTOR_CONTROL sdc;
  2164. if(!GetControl(&sdc))
  2165. return false;
  2166. return 0 != (sdc & SE_SACL_PROTECTED);
  2167. }
  2168. inline bool CSecurityDesc::GetControl(SECURITY_DESCRIPTOR_CONTROL *psdc) const
  2169. {
  2170. ATLASSERT(psdc);
  2171. if(!psdc)
  2172. return false;
  2173. DWORD dwRev;
  2174. *psdc = 0;
  2175. if(!m_pSecurityDescriptor ||
  2176. !::GetSecurityDescriptorControl(m_pSecurityDescriptor, psdc, &dwRev))
  2177. {
  2178. return false;
  2179. }
  2180. return true;
  2181. }
  2182. #if(_WIN32_WINNT >= 0x0500)
  2183. inline bool CSecurityDesc::SetControl(SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
  2184. SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
  2185. {
  2186. return 0 != ::SetSecurityDescriptorControl(m_pSecurityDescriptor,
  2187. ControlBitsOfInterest, ControlBitsToSet);
  2188. }
  2189. #endif
  2190. template<>
  2191. class CSimpleArrayEqualHelper<LUID>
  2192. {
  2193. public:
  2194. static bool IsEqual(const LUID& l1, const LUID& l2)
  2195. {
  2196. return l1.HighPart == l2.HighPart && l1.LowPart == l2.LowPart;
  2197. }
  2198. };
  2199. template<>
  2200. class CElementTraits< LUID > :
  2201. public CElementTraitsBase< LUID >
  2202. {
  2203. public:
  2204. typedef const LUID& INARGTYPE;
  2205. typedef LUID& OUTARGTYPE;
  2206. static ULONG Hash( INARGTYPE luid )
  2207. {
  2208. return luid.HighPart ^ luid.LowPart;
  2209. }
  2210. static BOOL CompareElements( INARGTYPE element1, INARGTYPE element2 )
  2211. {
  2212. return CSimpleArrayEqualHelper<LUID>::IsEqual(element1, element2);
  2213. }
  2214. static int CompareElementsOrdered( INARGTYPE element1, INARGTYPE element2 )
  2215. {
  2216. _LARGE_INTEGER li1, li2;
  2217. li1.LowPart = element1.LowPart;
  2218. li1.HighPart = element1.HighPart;
  2219. li2.LowPart = element2.LowPart;
  2220. li2.HighPart = element2.HighPart;
  2221. if( li1.QuadPart > li2.QuadPart )
  2222. return( 1 );
  2223. else if( li1.QuadPart < li2.QuadPart )
  2224. return( -1 );
  2225. return( 0 );
  2226. }
  2227. };
  2228. typedef CSimpleArray<LUID> CLUIDArray;
  2229. //******************************************************
  2230. // CTokenPrivileges
  2231. class CTokenPrivileges
  2232. {
  2233. public:
  2234. CTokenPrivileges() : m_bDirty(true), m_pTokenPrivileges(NULL){}
  2235. virtual ~CTokenPrivileges() {free(m_pTokenPrivileges);}
  2236. CTokenPrivileges(const CTokenPrivileges &rhs);
  2237. CTokenPrivileges &operator=(const CTokenPrivileges &rhs);
  2238. CTokenPrivileges(const TOKEN_PRIVILEGES &rPrivileges) :
  2239. m_pTokenPrivileges(NULL) {AddPrivileges(rPrivileges);}
  2240. CTokenPrivileges &operator=(const TOKEN_PRIVILEGES &rPrivileges)
  2241. {m_TokenPrivileges.RemoveAll(); AddPrivileges(rPrivileges); return *this;}
  2242. void Add(const TOKEN_PRIVILEGES &rPrivileges)
  2243. {AddPrivileges(rPrivileges);}
  2244. bool Add(LPCTSTR pszPrivilege, bool bEnable);
  2245. typedef CSimpleArray<CString> CNames;
  2246. typedef CSimpleArray<DWORD> CAttributes;
  2247. bool LookupPrivilege(LPCTSTR pszPrivilege, DWORD *pdwAttributes = NULL) const;
  2248. void GetNamesAndAttributes(CNames *pNames, CAttributes *pAttributes = NULL) const;
  2249. void GetDisplayNames(CNames *pDisplayNames) const;
  2250. void GetLuidsAndAttributes(CLUIDArray *pPrivileges, CAttributes *pAttributes = NULL) const;
  2251. bool Delete(LPCTSTR pszPrivilege);
  2252. void DeleteAll(){m_TokenPrivileges.RemoveAll(); m_bDirty = true;}
  2253. UINT GetCount() const {return (UINT) m_TokenPrivileges.GetCount();}
  2254. UINT GetLength() const
  2255. {return offsetof(TOKEN_PRIVILEGES, Privileges) + sizeof(LUID_AND_ATTRIBUTES) * GetCount();}
  2256. const TOKEN_PRIVILEGES *GetPTOKEN_PRIVILEGES() const;
  2257. operator const TOKEN_PRIVILEGES *() const {return GetPTOKEN_PRIVILEGES();}
  2258. private:
  2259. typedef CAtlMap<LUID, DWORD> Map;
  2260. Map m_TokenPrivileges;
  2261. mutable TOKEN_PRIVILEGES *m_pTokenPrivileges;
  2262. bool m_bDirty;
  2263. void AddPrivileges(const TOKEN_PRIVILEGES &rPrivileges);
  2264. };
  2265. inline CTokenPrivileges::CTokenPrivileges(const CTokenPrivileges &rhs)
  2266. : m_pTokenPrivileges(NULL), m_bDirty(true)
  2267. {
  2268. const Map::CPair *pPair;
  2269. POSITION pos = rhs.m_TokenPrivileges.GetStartPosition();
  2270. while(pos)
  2271. {
  2272. pPair = rhs.m_TokenPrivileges.GetNext(pos);
  2273. m_TokenPrivileges.SetAt(pPair->m_key, pPair->m_value);
  2274. }
  2275. }
  2276. inline CTokenPrivileges &CTokenPrivileges::operator=(const CTokenPrivileges &rhs)
  2277. {
  2278. if(this != &rhs)
  2279. {
  2280. m_TokenPrivileges.RemoveAll();
  2281. const Map::CPair *pPair;
  2282. POSITION pos = rhs.m_TokenPrivileges.GetStartPosition();
  2283. while(pos)
  2284. {
  2285. pPair = rhs.m_TokenPrivileges.GetNext(pos);
  2286. m_TokenPrivileges.SetAt(pPair->m_key, pPair->m_value);
  2287. }
  2288. m_bDirty = true;
  2289. }
  2290. return *this;
  2291. }
  2292. inline bool CTokenPrivileges::Add(LPCTSTR pszPrivilege, bool bEnable)
  2293. {
  2294. LUID_AND_ATTRIBUTES la;
  2295. if(!::LookupPrivilegeValue(NULL, pszPrivilege, &la.Luid))
  2296. return false;
  2297. la.Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0;
  2298. m_TokenPrivileges.SetAt(la.Luid, la.Attributes);
  2299. m_bDirty = true;
  2300. return true;
  2301. }
  2302. inline bool CTokenPrivileges::Delete(LPCTSTR pszPrivilege)
  2303. {
  2304. LUID Luid;
  2305. if(!::LookupPrivilegeValue(NULL, pszPrivilege, &Luid))
  2306. return false;
  2307. if(!m_TokenPrivileges.RemoveKey(Luid))
  2308. return false;
  2309. m_bDirty = true;
  2310. return true;
  2311. }
  2312. inline const TOKEN_PRIVILEGES *CTokenPrivileges::GetPTOKEN_PRIVILEGES() const
  2313. {
  2314. if(m_bDirty)
  2315. {
  2316. free(m_pTokenPrivileges);
  2317. m_pTokenPrivileges = NULL;
  2318. if(m_TokenPrivileges.GetCount())
  2319. {
  2320. m_pTokenPrivileges = static_cast<TOKEN_PRIVILEGES *>(malloc(GetLength()));
  2321. if(!m_pTokenPrivileges)
  2322. return NULL;
  2323. m_pTokenPrivileges->PrivilegeCount = (DWORD) GetCount();
  2324. UINT i = 0;
  2325. POSITION pos = m_TokenPrivileges.GetStartPosition();
  2326. const Map::CPair *pPair;
  2327. while(pos)
  2328. {
  2329. pPair = m_TokenPrivileges.GetNext(pos);
  2330. m_pTokenPrivileges->Privileges[i].Luid = pPair->m_key;
  2331. m_pTokenPrivileges->Privileges[i].Attributes = pPair->m_value;
  2332. i++;
  2333. }
  2334. }
  2335. }
  2336. return m_pTokenPrivileges;
  2337. }
  2338. inline void CTokenPrivileges::AddPrivileges(const TOKEN_PRIVILEGES &rPrivileges)
  2339. {
  2340. m_bDirty = true;
  2341. for(UINT i = 0; i < rPrivileges.PrivilegeCount; i++)
  2342. m_TokenPrivileges.SetAt(
  2343. rPrivileges.Privileges[i].Luid, rPrivileges.Privileges[i].Attributes);
  2344. }
  2345. inline bool CTokenPrivileges::LookupPrivilege(LPCTSTR pszPrivilege,
  2346. DWORD *pdwAttributes) const
  2347. {
  2348. DWORD dwAttributes;
  2349. LUID luid;
  2350. if(!::LookupPrivilegeValue(NULL, pszPrivilege, &luid))
  2351. return false;
  2352. if(m_TokenPrivileges.Lookup(luid, dwAttributes))
  2353. {
  2354. if(pdwAttributes)
  2355. *pdwAttributes = dwAttributes;
  2356. return true;
  2357. }
  2358. return false;
  2359. }
  2360. inline void CTokenPrivileges::GetNamesAndAttributes(CNames *pNames,
  2361. CAttributes *pAttributes) const
  2362. {
  2363. ATLASSERT(pNames);
  2364. if(pNames)
  2365. {
  2366. LPTSTR psz = NULL;
  2367. DWORD cbName = 0, cbTmp;
  2368. const Map::CPair *pPair;
  2369. pNames->RemoveAll();
  2370. if(pAttributes)
  2371. pAttributes->RemoveAll();
  2372. POSITION pos = m_TokenPrivileges.GetStartPosition();
  2373. while(pos)
  2374. {
  2375. pPair = m_TokenPrivileges.GetNext(pos);
  2376. cbTmp = cbName;
  2377. if(!::LookupPrivilegeName(NULL, const_cast<LUID *>(&pPair->m_key), psz, &cbTmp))
  2378. if(::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  2379. {
  2380. delete[] psz;
  2381. ATLTRY(psz = new TCHAR[cbTmp + 1]);
  2382. if(!psz)
  2383. {
  2384. pNames->RemoveAll();
  2385. if(pAttributes)
  2386. pAttributes->RemoveAll();
  2387. AtlThrow(E_OUTOFMEMORY);
  2388. }
  2389. cbName = cbTmp;
  2390. if(!::LookupPrivilegeName(NULL, const_cast<LUID *>(&pPair->m_key), psz, &cbTmp))
  2391. break;
  2392. }
  2393. else
  2394. break;
  2395. pNames->Add(psz);
  2396. if(pAttributes)
  2397. pAttributes->Add(pPair->m_value);
  2398. }
  2399. delete[] psz;
  2400. if(pos)
  2401. {
  2402. pNames->RemoveAll();
  2403. if(pAttributes)
  2404. pAttributes->RemoveAll();
  2405. }
  2406. }
  2407. }
  2408. inline void CTokenPrivileges::GetDisplayNames(CNames *pDisplayNames) const
  2409. {
  2410. ATLASSERT(pDisplayNames);
  2411. if(pDisplayNames)
  2412. {
  2413. DWORD dwLang, cbTmp, cbDisplayName = 0;
  2414. LPTSTR psz = NULL;
  2415. CNames Names;
  2416. int i;
  2417. GetNamesAndAttributes(&Names);
  2418. pDisplayNames->RemoveAll();
  2419. for(i = 0; i < Names.GetSize(); i++)
  2420. {
  2421. cbTmp = cbDisplayName;
  2422. if(!::LookupPrivilegeDisplayName(NULL, Names[i], psz, &cbTmp, &dwLang))
  2423. {
  2424. if(::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  2425. {
  2426. delete[] psz;
  2427. ATLTRY(psz = new TCHAR[cbTmp + 1]);
  2428. if(!psz)
  2429. {
  2430. pDisplayNames->RemoveAll();
  2431. AtlThrow(E_OUTOFMEMORY);
  2432. }
  2433. cbDisplayName = cbTmp;
  2434. if(!::LookupPrivilegeDisplayName(NULL, Names[i], psz, &cbTmp, &dwLang))
  2435. break;
  2436. }
  2437. else
  2438. break;
  2439. }
  2440. pDisplayNames->Add(psz);
  2441. }
  2442. delete[] psz;
  2443. if(i != Names.GetSize())
  2444. pDisplayNames->RemoveAll();
  2445. }
  2446. }
  2447. inline void CTokenPrivileges::GetLuidsAndAttributes(CLUIDArray *pLuids,
  2448. CAttributes *pAttributes) const
  2449. {
  2450. ATLASSERT(pLuids);
  2451. if(pLuids)
  2452. {
  2453. const Map::CPair *pPair;
  2454. pLuids->RemoveAll();
  2455. if(pAttributes)
  2456. pAttributes->RemoveAll();
  2457. POSITION pos = m_TokenPrivileges.GetStartPosition();
  2458. while(pos)
  2459. {
  2460. pPair = m_TokenPrivileges.GetNext(pos);
  2461. pLuids->Add(pPair->m_key);
  2462. if(pAttributes)
  2463. pAttributes->Add(pPair->m_value);
  2464. }
  2465. }
  2466. }
  2467. //******************************************************
  2468. // CTokenGroups
  2469. class CTokenGroups
  2470. {
  2471. public:
  2472. CTokenGroups() : m_pTokenGroups(NULL), m_bDirty(true){}
  2473. virtual ~CTokenGroups() {free(m_pTokenGroups);}
  2474. CTokenGroups(const CTokenGroups &rhs);
  2475. CTokenGroups &operator=(const CTokenGroups &rhs);
  2476. CTokenGroups(const TOKEN_GROUPS &rhs) :
  2477. m_pTokenGroups(NULL) {AddTokenGroups(rhs);}
  2478. CTokenGroups &operator=(const TOKEN_GROUPS &rhs)
  2479. {m_TokenGroups.RemoveAll(); AddTokenGroups(rhs); return *this;}
  2480. void Add(const TOKEN_GROUPS &rTokenGroups)
  2481. {AddTokenGroups(rTokenGroups);}
  2482. void Add(const CSid &rSid, DWORD dwAttributes)
  2483. {m_TokenGroups.SetAt(rSid, dwAttributes); m_bDirty = true;}
  2484. bool LookupSid(const CSid &rSid, DWORD *pdwAttributes = NULL) const;
  2485. void GetSidsAndAttributes(CSid::CSidArray *pSids,
  2486. CSimpleArray<DWORD> *pAttributes = NULL) const;
  2487. bool Delete(const CSid &rSid) {return m_TokenGroups.RemoveKey(rSid);}
  2488. void DeleteAll(){m_TokenGroups.RemoveAll(); m_bDirty = true;}
  2489. UINT GetCount() const {return (UINT) m_TokenGroups.GetCount();}
  2490. UINT GetLength() const
  2491. {return UINT(offsetof(TOKEN_GROUPS, Groups) +
  2492. sizeof(SID_AND_ATTRIBUTES) * m_TokenGroups.GetCount());}
  2493. const TOKEN_GROUPS *GetPTOKEN_GROUPS() const;
  2494. operator const TOKEN_GROUPS *() const {return GetPTOKEN_GROUPS();}
  2495. private:
  2496. class CTGElementTraits :
  2497. public CElementTraitsBase< CSid >
  2498. {
  2499. public:
  2500. static UINT Hash(const CSid &sid)
  2501. {return sid.GetSubAuthority(sid.GetSubAuthorityCount() - 1);}
  2502. static bool CompareElements( INARGTYPE element1, INARGTYPE element2 ) throw()
  2503. {
  2504. return( element1 == element2 );
  2505. }
  2506. };
  2507. typedef CAtlMap<CSid, DWORD, CTGElementTraits> Map;
  2508. Map m_TokenGroups;
  2509. mutable TOKEN_GROUPS *m_pTokenGroups;
  2510. mutable bool m_bDirty;
  2511. void AddTokenGroups(const TOKEN_GROUPS &rTokenGroups);
  2512. };
  2513. inline CTokenGroups::CTokenGroups(const CTokenGroups &rhs)
  2514. : m_pTokenGroups(NULL), m_bDirty(true)
  2515. {
  2516. const Map::CPair *pPair;
  2517. POSITION pos = rhs.m_TokenGroups.GetStartPosition();
  2518. while(pos)
  2519. {
  2520. pPair = rhs.m_TokenGroups.GetNext(pos);
  2521. m_TokenGroups.SetAt(pPair->m_key, pPair->m_value);
  2522. }
  2523. }
  2524. inline CTokenGroups &CTokenGroups::operator=(const CTokenGroups &rhs)
  2525. {
  2526. if(this != &rhs)
  2527. {
  2528. m_TokenGroups.RemoveAll();
  2529. const Map::CPair *pPair;
  2530. POSITION pos = rhs.m_TokenGroups.GetStartPosition();
  2531. while(pos)
  2532. {
  2533. pPair = rhs.m_TokenGroups.GetNext(pos);
  2534. m_TokenGroups.SetAt(pPair->m_key, pPair->m_value);
  2535. }
  2536. m_bDirty = true;
  2537. }
  2538. return *this;
  2539. }
  2540. inline const TOKEN_GROUPS *CTokenGroups::GetPTOKEN_GROUPS() const
  2541. {
  2542. if(m_bDirty)
  2543. {
  2544. free(m_pTokenGroups);
  2545. m_pTokenGroups = NULL;
  2546. if(m_TokenGroups.GetCount())
  2547. {
  2548. m_pTokenGroups = static_cast<TOKEN_GROUPS *>(malloc(GetLength()));
  2549. if(!m_pTokenGroups)
  2550. return NULL;
  2551. m_pTokenGroups->GroupCount = (DWORD) m_TokenGroups.GetCount();
  2552. UINT i = 0;
  2553. POSITION pos = m_TokenGroups.GetStartPosition();
  2554. const Map::CPair *pPair;
  2555. while(pos)
  2556. {
  2557. // REVIEW: see if there's a way to make sure that no one mucks with this
  2558. // sid... (unlikely that anyone would, but possible)
  2559. pPair = m_TokenGroups.GetNext(pos);
  2560. m_pTokenGroups->Groups[i].Sid = const_cast<SID *>(pPair->m_key.GetPSID());
  2561. m_pTokenGroups->Groups[i].Attributes = pPair->m_value;
  2562. i++;
  2563. }
  2564. }
  2565. }
  2566. return m_pTokenGroups;
  2567. }
  2568. inline void CTokenGroups::AddTokenGroups(const TOKEN_GROUPS &rTokenGroups)
  2569. {
  2570. m_bDirty = true;
  2571. for(UINT i = 0; i < rTokenGroups.GroupCount; i++)
  2572. m_TokenGroups.SetAt(
  2573. CSid(static_cast<SID *>(rTokenGroups.Groups[i].Sid)),
  2574. rTokenGroups.Groups[i].Attributes);
  2575. }
  2576. inline bool CTokenGroups::LookupSid(const CSid &rSid, DWORD *pdwAttributes) const
  2577. {
  2578. DWORD dwAttributes;
  2579. if(m_TokenGroups.Lookup(rSid, dwAttributes))
  2580. {
  2581. if(pdwAttributes)
  2582. *pdwAttributes = dwAttributes;
  2583. return true;
  2584. }
  2585. return false;
  2586. }
  2587. inline void CTokenGroups::GetSidsAndAttributes(CSid::CSidArray *pSids,
  2588. CSimpleArray<DWORD> *pAttributes) const
  2589. {
  2590. ATLASSERT(pSids);
  2591. if(pSids)
  2592. {
  2593. const Map::CPair *pPair;
  2594. pSids->RemoveAll();
  2595. if(pAttributes)
  2596. pAttributes->RemoveAll();
  2597. POSITION pos = m_TokenGroups.GetStartPosition();
  2598. while(pos)
  2599. {
  2600. pPair = m_TokenGroups.GetNext(pos);
  2601. pSids->Add(pPair->m_key);
  2602. if(pAttributes)
  2603. pAttributes->Add(pPair->m_value);
  2604. }
  2605. }
  2606. }
  2607. // *************************************
  2608. // CAccessToken
  2609. class CAccessToken
  2610. {
  2611. public:
  2612. CAccessToken() : m_hToken(NULL), m_hProfile(NULL), m_pRevert(NULL){}
  2613. // REVIEW: should privileges that have been enabled be automatically
  2614. // disabled in the dtor of CAccessToken?
  2615. virtual ~CAccessToken();
  2616. bool Attach(HANDLE hToken, bool bDuplicate = false,
  2617. HANDLE hSrcProcess = NULL, HANDLE hDestProcess = NULL, bool bInherit = false);
  2618. HANDLE Detach()
  2619. {HANDLE hToken = m_hToken; m_hToken = NULL; Clear(); return hToken;}
  2620. HANDLE GetHandle() const {return m_hToken;}
  2621. HANDLE HKeyCurrentUser() const {return m_hProfile;}
  2622. // Privileges
  2623. bool EnablePrivilege(LPCTSTR pszPrivilege, CTokenPrivileges *pPreviousState = NULL);
  2624. bool EnablePrivileges(const CSimpleArray<LPCTSTR> &rPrivileges,
  2625. CTokenPrivileges *pPreviousState = NULL);
  2626. bool DisablePrivilege(LPCTSTR pszPrivilege, CTokenPrivileges *pPreviousState = NULL);
  2627. bool DisablePrivileges(const CSimpleArray<LPCTSTR> &rPrivileges, CTokenPrivileges *pPreviousState = NULL);
  2628. bool EnableDisablePrivileges(const CTokenPrivileges &rPrivilenges,
  2629. CTokenPrivileges *pPreviousState = NULL);
  2630. bool PrivilegeCheck(PPRIVILEGE_SET RequiredPrivileges, bool *pbResult) const;
  2631. bool GetLogonSid(CSid *pSid) const;
  2632. bool GetTokenId(LUID *pluid) const;
  2633. bool GetLogonSessionId(LUID *pluid) const;
  2634. bool CheckTokenMembership(const CSid &rSid, bool *pbIsMember) const;
  2635. #if(_WIN32_WINNT >= 0x0500)
  2636. bool IsTokenRestricted() const {return 0 != ::IsTokenRestricted(m_hToken);}
  2637. #endif
  2638. // Token Information
  2639. protected:
  2640. template<typename RET_T, typename INFO_T>
  2641. void InfoTypeToRetType(RET_T *pRet, const INFO_T &rWork) const
  2642. {ATLASSERT(pRet); *pRet = rWork;}
  2643. template<>
  2644. void InfoTypeToRetType(CDacl *pRet, const TOKEN_DEFAULT_DACL &rWork) const
  2645. {ATLASSERT(pRet); *pRet = *rWork.DefaultDacl;}
  2646. template<>
  2647. void InfoTypeToRetType(CSid *pRet, const TOKEN_OWNER &rWork) const
  2648. {ATLASSERT(pRet); *pRet = *static_cast<SID *>(rWork.Owner);}
  2649. template<>
  2650. void InfoTypeToRetType(CSid *pRet, const TOKEN_PRIMARY_GROUP &rWork) const
  2651. {ATLASSERT(pRet); *pRet = *static_cast<SID *>(rWork.PrimaryGroup);}
  2652. template<>
  2653. void InfoTypeToRetType(CSid *pRet, const TOKEN_USER &rWork) const
  2654. {ATLASSERT(pRet); *pRet = *static_cast<SID *>(rWork.User.Sid);}
  2655. template<typename RET_T, typename INFO_T>
  2656. bool GetInfoConvert(RET_T *pRet, TOKEN_INFORMATION_CLASS TokenClass, INFO_T *pWork = NULL) const
  2657. {
  2658. ATLASSERT(pRet);
  2659. if(!pRet)
  2660. return false;
  2661. DWORD dwLen;
  2662. ::GetTokenInformation(m_hToken, TokenClass, NULL, 0, &dwLen);
  2663. if(::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  2664. return false;
  2665. pWork = static_cast<INFO_T *>(_alloca(dwLen));
  2666. if(!::GetTokenInformation(m_hToken, TokenClass, pWork, dwLen, &dwLen))
  2667. return false;
  2668. InfoTypeToRetType(pRet, *pWork);
  2669. return true;
  2670. }
  2671. template<typename RET_T>
  2672. bool GetInfo(RET_T *pRet, TOKEN_INFORMATION_CLASS TokenClass) const
  2673. {
  2674. ATLASSERT(pRet);
  2675. if(!pRet)
  2676. return false;
  2677. DWORD dwLen;
  2678. if(!::GetTokenInformation(m_hToken, TokenClass, pRet, sizeof(RET_T), &dwLen))
  2679. return false;
  2680. return true;
  2681. }
  2682. public:
  2683. bool GetDefaultDacl(CDacl *pDacl) const
  2684. {return GetInfoConvert<CDacl, TOKEN_DEFAULT_DACL>(pDacl, TokenDefaultDacl);}
  2685. bool GetGroups(CTokenGroups *pGroups) const
  2686. {return GetInfoConvert<CTokenGroups, TOKEN_GROUPS>(pGroups, TokenGroups);}
  2687. bool GetImpersonationLevel(SECURITY_IMPERSONATION_LEVEL *pImpersonationLevel) const
  2688. {return GetInfo<SECURITY_IMPERSONATION_LEVEL>(pImpersonationLevel, TokenImpersonationLevel);}
  2689. bool GetOwner(CSid *pSid) const
  2690. {return GetInfoConvert<CSid, TOKEN_OWNER>(pSid, TokenOwner);}
  2691. bool GetPrimaryGroup(CSid *pSid) const
  2692. {return GetInfoConvert<CSid, TOKEN_PRIMARY_GROUP>(pSid, TokenPrimaryGroup);}
  2693. bool GetPrivileges(CTokenPrivileges *pPrivileges) const
  2694. {return GetInfoConvert<CTokenPrivileges, TOKEN_PRIVILEGES>(pPrivileges, TokenPrivileges);}
  2695. bool GetTerminalServicesSessionId(DWORD *pdwSessionId) const
  2696. {return GetInfo<DWORD>(pdwSessionId, TokenSessionId);}
  2697. bool GetSource(TOKEN_SOURCE *pSource) const
  2698. {return GetInfo<TOKEN_SOURCE>(pSource, TokenSource);}
  2699. bool GetStatistics(TOKEN_STATISTICS *pStatistics) const
  2700. {return GetInfo<TOKEN_STATISTICS>(pStatistics, TokenStatistics);}
  2701. bool GetType(TOKEN_TYPE *pType) const
  2702. {return GetInfo<TOKEN_TYPE>(pType, TokenType);}
  2703. bool GetUser(CSid *pSid) const
  2704. {return GetInfoConvert<CSid, TOKEN_USER>(pSid, TokenUser);}
  2705. bool SetOwner(const CSid &rSid);
  2706. bool SetPrimaryGroup(const CSid &rSid);
  2707. bool SetDefaultDacl(const CDacl &rDacl);
  2708. bool CreateImpersonationToken(CAccessToken *pImp,
  2709. SECURITY_IMPERSONATION_LEVEL sil = SecurityImpersonation) const;
  2710. bool CreatePrimaryToken(CAccessToken *pPri,
  2711. DWORD dwDesiredAccess = MAXIMUM_ALLOWED,
  2712. const CSecurityAttributes *pTokenAttributes = NULL) const;
  2713. #if(_WIN32_WINNT >= 0x0500)
  2714. bool CreateRestrictedToken(CAccessToken *pRestrictedToken,
  2715. const CTokenGroups &SidsToDisable, const CTokenGroups &SidsToRestrict,
  2716. const CTokenPrivileges &PrivilegesToDelete = CTokenPrivileges()) const;
  2717. #endif
  2718. // Token API type functions
  2719. bool GetProcessToken(DWORD dwDesiredAccess, HANDLE hProcess = NULL);
  2720. bool GetThreadToken(DWORD dwDesiredAccess, HANDLE hThread = NULL, bool bOpenAsSelf = true);
  2721. bool GetEffectiveToken(DWORD dwDesiredAccess);
  2722. bool OpenThreadToken(DWORD dwDesiredAccess,
  2723. bool bImpersonate = false, bool bOpenAsSelf = true,
  2724. SECURITY_IMPERSONATION_LEVEL sil = SecurityImpersonation);
  2725. #if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)
  2726. bool OpenCOMClientToken(DWORD dwDesiredAccess,
  2727. bool bImpersonate = false, bool bOpenAsSelf = true);
  2728. #endif //(_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)
  2729. bool OpenNamedPipeClientToken(HANDLE hPipe, DWORD dwDesiredAccess,
  2730. bool bImpersonate = false, bool bOpenAsSelf = true);
  2731. bool OpenRPCClientToken(RPC_BINDING_HANDLE BindingHandle, DWORD dwDesiredAccess,
  2732. bool bImpersonate = false, bool bOpenAsSelf = true);
  2733. bool ImpersonateLoggedOnUser() const;
  2734. bool Impersonate(HANDLE hThread = NULL) const;
  2735. bool Revert(HANDLE hThread = NULL) const;
  2736. bool LoadUserProfile();
  2737. HANDLE GetProfile() const {return m_hProfile;}
  2738. // Must hold Tcb privilege
  2739. bool LogonUser(
  2740. LPCTSTR pszUserName, LPCTSTR pszDomain, LPCTSTR pszPassword,
  2741. DWORD dwLogonType = LOGON32_LOGON_INTERACTIVE,
  2742. DWORD dwLogonProvider = LOGON32_PROVIDER_DEFAULT);
  2743. // Must hold AssignPrimaryToken (unless restricted token) and
  2744. // IncreaseQuota privileges
  2745. bool CreateProcessAsUser(
  2746. LPCTSTR pApplicationName, LPTSTR pCommandLine,
  2747. LPPROCESS_INFORMATION pProcessInformation,
  2748. LPSTARTUPINFO pStartupInfo,
  2749. DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS,
  2750. bool bLoadProfile = false,
  2751. const CSecurityAttributes *pProcessAttributes = NULL,
  2752. const CSecurityAttributes *pThreadAttributes = NULL,
  2753. bool bInherit = false,
  2754. LPCTSTR pCurrentDirectory = NULL);
  2755. protected:
  2756. bool EnableDisablePrivileges(const CSimpleArray<LPCTSTR> &rPrivileges,
  2757. bool bEnable, CTokenPrivileges *pPreviousState);
  2758. void CheckImpersonation() const;
  2759. virtual void Clear();
  2760. HANDLE m_hToken, m_hProfile;
  2761. private:
  2762. // REVIEW: need copy?
  2763. CAccessToken(const CAccessToken &rhs);
  2764. CAccessToken &operator=(const CAccessToken &rhs);
  2765. class CRevert
  2766. {
  2767. public:
  2768. virtual bool Revert() = 0;
  2769. };
  2770. class CRevertToSelf : public CRevert
  2771. {
  2772. public:
  2773. bool Revert(){return 0 != ::RevertToSelf();}
  2774. };
  2775. #if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)
  2776. class CCoRevertToSelf : public CRevert
  2777. {
  2778. public:
  2779. bool Revert(){return SUCCEEDED(::CoRevertToSelf());}
  2780. };
  2781. #endif //(_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)
  2782. class CRpcRevertToSelfEx : public CRevert
  2783. {
  2784. public:
  2785. CRpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
  2786. : m_BindingHandle(BindingHandle){}
  2787. bool Revert(){return RPC_S_OK == ::RpcRevertToSelfEx(m_BindingHandle);}
  2788. private:
  2789. RPC_BINDING_HANDLE m_BindingHandle;
  2790. };
  2791. mutable CRevert *m_pRevert;
  2792. };
  2793. // *************************************
  2794. // CAccessToken implementation
  2795. inline CAccessToken::~CAccessToken()
  2796. {
  2797. Clear();
  2798. }
  2799. inline bool CAccessToken::Attach(HANDLE hToken, bool bDuplicate,
  2800. HANDLE hSrcProcess, HANDLE hDestProcess, bool bInherit)
  2801. {
  2802. ATLASSERT(hToken && hToken != m_hToken);
  2803. if(hToken && hToken != m_hToken)
  2804. {
  2805. Clear();
  2806. if(!bDuplicate)
  2807. {
  2808. m_hToken = hToken;
  2809. return true;
  2810. }
  2811. else
  2812. {
  2813. if(!hSrcProcess)
  2814. hSrcProcess = ::GetCurrentProcess();
  2815. if(!hDestProcess)
  2816. hDestProcess = ::GetCurrentProcess();
  2817. return 0 != ::DuplicateHandle(hSrcProcess, hToken, hDestProcess, &m_hToken,
  2818. 0, bInherit, DUPLICATE_SAME_ACCESS);
  2819. }
  2820. }
  2821. return false;
  2822. }
  2823. inline void CAccessToken::Clear()
  2824. {
  2825. if(m_hProfile)
  2826. {
  2827. ATLASSERT(m_hToken);
  2828. if(m_hToken)
  2829. ::UnloadUserProfile(m_hToken, m_hProfile);
  2830. m_hProfile = NULL;
  2831. }
  2832. if(m_hToken)
  2833. {
  2834. ::CloseHandle(m_hToken);
  2835. m_hToken = NULL;
  2836. }
  2837. delete m_pRevert;
  2838. m_pRevert = NULL;
  2839. }
  2840. inline bool CAccessToken::EnablePrivilege(LPCTSTR pszPrivilege,
  2841. CTokenPrivileges *pPreviousState)
  2842. {
  2843. CTokenPrivileges NewState;
  2844. return NewState.Add(pszPrivilege, true) &&
  2845. EnableDisablePrivileges(NewState, pPreviousState);
  2846. }
  2847. inline bool CAccessToken::EnablePrivileges(const CSimpleArray<LPCTSTR> &rPrivileges,
  2848. CTokenPrivileges *pPreviousState)
  2849. {
  2850. return EnableDisablePrivileges(rPrivileges, true, pPreviousState);
  2851. }
  2852. inline bool CAccessToken::DisablePrivilege(LPCTSTR pszPrivilege,
  2853. CTokenPrivileges *pPreviousState)
  2854. {
  2855. CTokenPrivileges NewState;
  2856. return NewState.Add(pszPrivilege, false) &&
  2857. EnableDisablePrivileges(NewState, pPreviousState);
  2858. }
  2859. inline bool CAccessToken::DisablePrivileges(const CSimpleArray<LPCTSTR> &rPrivileges,
  2860. CTokenPrivileges *pPreviousState)
  2861. {
  2862. return EnableDisablePrivileges(rPrivileges, false, pPreviousState);
  2863. }
  2864. inline bool CAccessToken::EnableDisablePrivileges(const CSimpleArray<LPCTSTR> &rPrivileges,
  2865. bool bEnable, CTokenPrivileges *pPreviousState)
  2866. {
  2867. CTokenPrivileges NewState;
  2868. for(int i = 0; i < rPrivileges.GetSize(); i++)
  2869. if(!NewState.Add(rPrivileges[i], bEnable))
  2870. return false;
  2871. return EnableDisablePrivileges(NewState, pPreviousState);
  2872. }
  2873. inline bool CAccessToken::EnableDisablePrivileges(const CTokenPrivileges &rNewState,
  2874. CTokenPrivileges *pPreviousState)
  2875. {
  2876. if(!rNewState.GetCount())
  2877. return true;
  2878. TOKEN_PRIVILEGES *pNewState = const_cast<TOKEN_PRIVILEGES *>(rNewState.GetPTOKEN_PRIVILEGES());
  2879. if(pPreviousState)
  2880. {
  2881. DWORD dwLength = offsetof(TOKEN_PRIVILEGES, Privileges) +
  2882. rNewState.GetCount() * sizeof(LUID_AND_ATTRIBUTES);
  2883. TOKEN_PRIVILEGES *pPrevState = static_cast<TOKEN_PRIVILEGES *>(_alloca(dwLength));
  2884. if(!::AdjustTokenPrivileges(m_hToken, FALSE, pNewState, dwLength, pPrevState, &dwLength))
  2885. return false;
  2886. pPreviousState->Add(*pPrevState);
  2887. return true;
  2888. }
  2889. else
  2890. return 0 != ::AdjustTokenPrivileges(m_hToken, FALSE, pNewState, 0, NULL, NULL);
  2891. }
  2892. inline bool CAccessToken::PrivilegeCheck(PPRIVILEGE_SET RequiredPrivileges, bool *pbResult) const
  2893. {
  2894. BOOL bResult;
  2895. if(!::PrivilegeCheck(m_hToken, RequiredPrivileges, &bResult))
  2896. return false;
  2897. *pbResult = 0 != bResult;
  2898. return true;
  2899. }
  2900. inline bool CAccessToken::GetProcessToken(DWORD dwDesiredAccess, HANDLE hProcess)
  2901. {
  2902. if(!hProcess)
  2903. hProcess = ::GetCurrentProcess();
  2904. HANDLE hToken;
  2905. if(!::OpenProcessToken(hProcess, dwDesiredAccess, &hToken))
  2906. return false;
  2907. Clear();
  2908. m_hToken = hToken;
  2909. return true;
  2910. }
  2911. inline bool CAccessToken::GetThreadToken(DWORD dwDesiredAccess,
  2912. HANDLE hThread, bool bOpenAsSelf)
  2913. {
  2914. if(!hThread)
  2915. hThread = ::GetCurrentThread();
  2916. HANDLE hToken;
  2917. if(!::OpenThreadToken(hThread, dwDesiredAccess, bOpenAsSelf, &hToken))
  2918. return false;
  2919. Clear();
  2920. m_hToken = hToken;
  2921. return true;
  2922. }
  2923. inline bool CAccessToken::GetEffectiveToken(DWORD dwDesiredAccess)
  2924. {
  2925. if(!GetThreadToken(dwDesiredAccess))
  2926. return GetProcessToken(dwDesiredAccess);
  2927. return true;
  2928. }
  2929. inline void CAccessToken::CheckImpersonation() const
  2930. {
  2931. #ifdef _DEBUG
  2932. // You should not be impersonating at this point. Use GetThreadToken
  2933. // instead of the OpenXXXToken functions or call Revert before
  2934. // calling Impersonate.
  2935. HANDLE hToken;
  2936. if(!::OpenThreadToken(::GetCurrentThread(), 0, false, &hToken) &&
  2937. ::GetLastError() != ERROR_NO_TOKEN)
  2938. ATLTRACE(atlTraceSecurity, 2, _T("Caution: replacing thread impersonation token.\n"));
  2939. #endif
  2940. }
  2941. inline bool CAccessToken::OpenThreadToken(DWORD dwDesiredAccess,
  2942. bool bImpersonate, bool bOpenAsSelf,
  2943. SECURITY_IMPERSONATION_LEVEL sil)
  2944. {
  2945. CheckImpersonation();
  2946. if(!::ImpersonateSelf(sil))
  2947. return false;
  2948. HANDLE hToken;
  2949. if(!::OpenThreadToken(::GetCurrentThread(), dwDesiredAccess, bOpenAsSelf, &hToken))
  2950. return false;
  2951. Clear();
  2952. m_hToken = hToken;
  2953. if(!bImpersonate)
  2954. ::RevertToSelf();
  2955. else
  2956. {
  2957. ATLTRY(m_pRevert = new CRevertToSelf);
  2958. if(!m_pRevert)
  2959. {
  2960. ::RevertToSelf();
  2961. Clear();
  2962. return false;
  2963. }
  2964. }
  2965. return true;
  2966. }
  2967. #if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)
  2968. inline bool CAccessToken::OpenCOMClientToken(DWORD dwDesiredAccess,
  2969. bool bImpersonate, bool bOpenAsSelf)
  2970. {
  2971. CheckImpersonation();
  2972. if(FAILED(::CoImpersonateClient()))
  2973. return false;
  2974. HANDLE hToken;
  2975. if(!::OpenThreadToken(::GetCurrentThread(), dwDesiredAccess, bOpenAsSelf, &hToken))
  2976. return false;
  2977. Clear();
  2978. m_hToken = hToken;
  2979. if(!bImpersonate)
  2980. ::CoRevertToSelf();
  2981. else
  2982. {
  2983. ATLTRY(m_pRevert = new CCoRevertToSelf);
  2984. if(!m_pRevert)
  2985. {
  2986. ::CoRevertToSelf();
  2987. Clear();
  2988. return false;
  2989. }
  2990. }
  2991. return true;
  2992. }
  2993. #endif //(_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)
  2994. inline bool CAccessToken::OpenNamedPipeClientToken(HANDLE hPipe, DWORD dwDesiredAccess,
  2995. bool bImpersonate, bool bOpenAsSelf)
  2996. {
  2997. CheckImpersonation();
  2998. if(!::ImpersonateNamedPipeClient(hPipe))
  2999. return false;
  3000. HANDLE hToken;
  3001. if(!::OpenThreadToken(::GetCurrentThread(), dwDesiredAccess, bOpenAsSelf, &hToken))
  3002. return false;
  3003. Clear();
  3004. m_hToken = hToken;
  3005. if(!bImpersonate)
  3006. ::RevertToSelf();
  3007. else
  3008. {
  3009. ATLTRY(m_pRevert = new CRevertToSelf);
  3010. if(!m_pRevert)
  3011. {
  3012. ::RevertToSelf();
  3013. Clear();
  3014. return false;
  3015. }
  3016. }
  3017. return true;
  3018. }
  3019. inline bool CAccessToken::OpenRPCClientToken(RPC_BINDING_HANDLE BindingHandle,
  3020. DWORD dwDesiredAccess,
  3021. bool bImpersonate, bool bOpenAsSelf)
  3022. {
  3023. CheckImpersonation();
  3024. if(RPC_S_OK != ::RpcImpersonateClient(BindingHandle))
  3025. return false;
  3026. HANDLE hToken;
  3027. if(!::OpenThreadToken(::GetCurrentThread(), dwDesiredAccess, bOpenAsSelf, &hToken))
  3028. return false;
  3029. Clear();
  3030. m_hToken = hToken;
  3031. if(!bImpersonate)
  3032. ::RpcRevertToSelfEx(BindingHandle);
  3033. else
  3034. {
  3035. ATLTRY(m_pRevert = new CRpcRevertToSelfEx(BindingHandle));
  3036. if(!m_pRevert)
  3037. {
  3038. ::RpcRevertToSelfEx(BindingHandle);
  3039. Clear();
  3040. return false;
  3041. }
  3042. }
  3043. return true;
  3044. }
  3045. inline bool CAccessToken::ImpersonateLoggedOnUser() const
  3046. {
  3047. CheckImpersonation();
  3048. ATLASSERT(m_hToken);
  3049. if(m_hToken && ::ImpersonateLoggedOnUser(m_hToken))
  3050. {
  3051. ATLASSERT(!m_pRevert);
  3052. delete m_pRevert;
  3053. ATLTRY(m_pRevert = new CRevertToSelf);
  3054. if (!m_pRevert)
  3055. {
  3056. ::RevertToSelf();
  3057. return false;
  3058. }
  3059. return true;
  3060. }
  3061. return false;
  3062. }
  3063. inline bool CAccessToken::Impersonate(HANDLE hThread) const
  3064. {
  3065. CheckImpersonation();
  3066. ATLASSERT(m_hToken);
  3067. if(m_hToken)
  3068. return 0 != ::SetThreadToken(hThread ? &hThread : NULL, m_hToken);
  3069. return false;
  3070. }
  3071. inline bool CAccessToken::Revert(HANDLE hThread) const
  3072. {
  3073. // REVIEW: What if *this* access token isn't the one that's currently doing
  3074. // the impersonating?
  3075. if(m_pRevert)
  3076. {
  3077. bool bRet = m_pRevert->Revert();
  3078. delete m_pRevert;
  3079. m_pRevert = NULL;
  3080. return bRet;
  3081. }
  3082. else
  3083. return 0 != ::SetThreadToken(hThread ? &hThread : NULL, NULL);
  3084. }
  3085. inline bool CAccessToken::LogonUser(LPCTSTR pszUserName,
  3086. LPCTSTR pszDomain,
  3087. LPCTSTR pszPassword,
  3088. DWORD dwLogonType,
  3089. DWORD dwLogonProvider)
  3090. {
  3091. Clear();
  3092. return 0 != ::LogonUser(
  3093. const_cast<LPTSTR>(pszUserName),
  3094. const_cast<LPTSTR>(pszDomain),
  3095. const_cast<LPTSTR>(pszPassword),
  3096. dwLogonType, dwLogonProvider, &m_hToken);
  3097. }
  3098. inline bool CAccessToken::LoadUserProfile()
  3099. {
  3100. ATLASSERT(m_hToken && !m_hProfile);
  3101. if(!m_hToken || m_hProfile)
  3102. return false;
  3103. CSid UserSid;
  3104. PROFILEINFO Profile;
  3105. if(!GetUser(&UserSid))
  3106. return false;
  3107. memset(&Profile, 0x00, sizeof(PROFILEINFO));
  3108. Profile.dwSize = sizeof(PROFILEINFO);
  3109. Profile.lpUserName = const_cast<LPTSTR>(UserSid.AccountName());
  3110. if(!::LoadUserProfile(m_hToken, &Profile))
  3111. return false;
  3112. m_hProfile = Profile.hProfile;
  3113. return true;
  3114. }
  3115. inline bool CAccessToken::SetOwner(const CSid &rSid)
  3116. { TOKEN_OWNER to;
  3117. to.Owner = const_cast<SID *>(rSid.GetPSID());
  3118. return 0 != ::SetTokenInformation(m_hToken, TokenOwner, &to, sizeof(to));
  3119. }
  3120. inline bool CAccessToken::SetPrimaryGroup(const CSid &rSid)
  3121. {
  3122. TOKEN_PRIMARY_GROUP tpg;
  3123. tpg.PrimaryGroup = const_cast<SID *>(rSid.GetPSID());
  3124. return 0 != ::SetTokenInformation(m_hToken, TokenPrimaryGroup, &tpg, sizeof(tpg));
  3125. }
  3126. inline bool CAccessToken::SetDefaultDacl(const CDacl &rDacl)
  3127. {
  3128. TOKEN_DEFAULT_DACL tdd;
  3129. tdd.DefaultDacl = const_cast<ACL *>(rDacl.GetPACL());
  3130. return 0 != ::SetTokenInformation(m_hToken, TokenDefaultDacl, &tdd, sizeof(tdd));
  3131. }
  3132. inline bool CAccessToken::CreateImpersonationToken(CAccessToken *pImp,
  3133. SECURITY_IMPERSONATION_LEVEL sil) const
  3134. {
  3135. ATLASSERT(pImp);
  3136. if(!pImp)
  3137. return false;
  3138. HANDLE hToken;
  3139. if(!::DuplicateToken(m_hToken, sil, &hToken))
  3140. return false;
  3141. pImp->Clear();
  3142. pImp->m_hToken = hToken;
  3143. return true;
  3144. }
  3145. inline bool CAccessToken::CreatePrimaryToken(CAccessToken *pPri, DWORD dwDesiredAccess,
  3146. const CSecurityAttributes *pTokenAttributes) const
  3147. {
  3148. ATLASSERT(pPri);
  3149. if(!pPri)
  3150. return false;
  3151. HANDLE hToken;
  3152. if(!::DuplicateTokenEx(m_hToken, dwDesiredAccess,
  3153. const_cast<CSecurityAttributes *>(pTokenAttributes),
  3154. SecurityAnonymous, TokenPrimary, &hToken))
  3155. {
  3156. return false;
  3157. }
  3158. pPri->Clear();
  3159. pPri->m_hToken = hToken;
  3160. return true;
  3161. }
  3162. #if(_WIN32_WINNT >= 0x0500)
  3163. // REVIEW should this be something like
  3164. /*
  3165. inline bool CAccessToken::CreateRestrictedToken(CAccessToken *pRestrictedToken,
  3166. const CSidArray &SidsToDisable,
  3167. const CLUIDArray &PrivilegesToDelete,
  3168. const CSidArray &SidsToRestrict) const*/
  3169. inline bool CAccessToken::CreateRestrictedToken(CAccessToken *pRestrictedToken,
  3170. const CTokenGroups &SidsToDisable,
  3171. const CTokenGroups &SidsToRestrict,
  3172. const CTokenPrivileges &PrivilegesToDelete) const
  3173. {
  3174. ATLASSERT(pRestrictedToken);
  3175. if(!pRestrictedToken)
  3176. return false;
  3177. HANDLE hToken;
  3178. SID_AND_ATTRIBUTES *pSidsToDisable;
  3179. SID_AND_ATTRIBUTES *pSidsToRestrict;
  3180. LUID_AND_ATTRIBUTES *pPrivilegesToDelete;
  3181. DWORD dwDisableSidCount;
  3182. DWORD dwDeletePrivilegesCount;
  3183. DWORD dwRestrictedSidCount;
  3184. if(dwDisableSidCount = SidsToDisable.GetCount())
  3185. {
  3186. const TOKEN_GROUPS * pTOKEN_GROUPS = SidsToDisable.GetPTOKEN_GROUPS();
  3187. ATLASSERT(pTOKEN_GROUPS != NULL);
  3188. if(pTOKEN_GROUPS != NULL)
  3189. {
  3190. pSidsToDisable = const_cast<SID_AND_ATTRIBUTES *>
  3191. (pTOKEN_GROUPS->Groups);
  3192. }
  3193. else
  3194. {
  3195. return false;
  3196. }
  3197. }
  3198. else
  3199. {
  3200. pSidsToDisable = NULL;
  3201. }
  3202. if(dwRestrictedSidCount = SidsToRestrict.GetCount())
  3203. {
  3204. const TOKEN_GROUPS * pTOKEN_GROUPS = SidsToRestrict.GetPTOKEN_GROUPS();
  3205. ATLASSERT(pTOKEN_GROUPS != NULL);
  3206. if(pTOKEN_GROUPS != NULL)
  3207. {
  3208. pSidsToRestrict = const_cast<SID_AND_ATTRIBUTES *>
  3209. (pTOKEN_GROUPS->Groups);
  3210. }
  3211. else
  3212. {
  3213. return false;
  3214. }
  3215. }
  3216. else
  3217. {
  3218. pSidsToRestrict = NULL;
  3219. }
  3220. if(dwDeletePrivilegesCount = PrivilegesToDelete.GetCount())
  3221. {
  3222. const TOKEN_PRIVILEGES * pTOKEN_PRIVILEGES = PrivilegesToDelete.GetPTOKEN_PRIVILEGES();
  3223. ATLASSERT(pTOKEN_PRIVILEGES != NULL);
  3224. if(pTOKEN_PRIVILEGES != NULL)
  3225. {
  3226. pPrivilegesToDelete = const_cast<LUID_AND_ATTRIBUTES *>
  3227. (pTOKEN_PRIVILEGES->Privileges);
  3228. }
  3229. else
  3230. {
  3231. return false;
  3232. }
  3233. }
  3234. else
  3235. {
  3236. pPrivilegesToDelete = NULL;
  3237. }
  3238. if(!::CreateRestrictedToken(m_hToken, 0,
  3239. dwDisableSidCount, pSidsToDisable,
  3240. dwDeletePrivilegesCount, pPrivilegesToDelete,
  3241. dwRestrictedSidCount, pSidsToRestrict, &hToken))
  3242. {
  3243. return false;
  3244. }
  3245. pRestrictedToken->Clear();
  3246. pRestrictedToken->m_hToken = hToken;
  3247. return true;
  3248. }
  3249. #endif // _WIN32_WINNT >= 0x0500
  3250. inline bool CAccessToken::GetLogonSid(CSid *pSid) const
  3251. {
  3252. ATLASSERT(pSid);
  3253. if(!pSid)
  3254. return false;
  3255. DWORD dwLen;
  3256. ::GetTokenInformation(m_hToken, TokenGroups, NULL, 0, &dwLen);
  3257. if(::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  3258. return false;
  3259. TOKEN_GROUPS *pGroups = static_cast<TOKEN_GROUPS *>(_alloca(dwLen));
  3260. if(::GetTokenInformation(m_hToken, TokenGroups, pGroups, dwLen, &dwLen))
  3261. for(UINT i = 0; i < pGroups->GroupCount; i++)
  3262. if(pGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID)
  3263. {
  3264. *pSid = *static_cast<SID *>(pGroups->Groups[i].Sid);
  3265. return true;
  3266. }
  3267. return false;
  3268. }
  3269. inline bool CAccessToken::GetTokenId(LUID *pluid) const
  3270. {
  3271. ATLASSERT(pluid);
  3272. if(!pluid)
  3273. return false;
  3274. TOKEN_STATISTICS Statistics;
  3275. if(!GetStatistics(&Statistics))
  3276. return false;
  3277. *pluid = Statistics.TokenId;
  3278. return true;
  3279. }
  3280. inline bool CAccessToken::GetLogonSessionId(LUID *pluid) const
  3281. {
  3282. ATLASSERT(pluid);
  3283. if(!pluid)
  3284. return false;
  3285. TOKEN_STATISTICS Statistics;
  3286. if(!GetStatistics(&Statistics))
  3287. return false;
  3288. *pluid = Statistics.AuthenticationId;
  3289. return true;
  3290. }
  3291. inline bool CAccessToken::CheckTokenMembership(const CSid &rSid, bool *pbIsMember) const
  3292. {
  3293. // "this" must be an impersonation token and NOT a primary token
  3294. BOOL bIsMember;
  3295. ATLASSERT(pbIsMember);
  3296. if (!pbIsMember)
  3297. return false;
  3298. #if(_WIN32_WINNT >= 0x0500)
  3299. if(::CheckTokenMembership(m_hToken, const_cast<SID *>(rSid.GetPSID()), &bIsMember))
  3300. #else
  3301. GENERIC_MAPPING gm = {0, 0, 0, 1};
  3302. PRIVILEGE_SET ps;
  3303. DWORD cb = sizeof(PRIVILEGE_SET);
  3304. DWORD ga;
  3305. CSecurityDesc sd;
  3306. CDacl dacl;
  3307. if (!dacl.AddAllowedAce(rSid, 1))
  3308. return false;
  3309. sd.SetOwner(rSid);
  3310. sd.SetGroup(rSid);
  3311. sd.SetDacl(dacl);
  3312. if(::AccessCheck(const_cast<SECURITY_DESCRIPTOR *>(sd.GetPSECURITY_DESCRIPTOR()),
  3313. m_hToken, 1, &gm, &ps, &cb, &ga, &bIsMember))
  3314. #endif
  3315. {
  3316. *pbIsMember = 0 != bIsMember;
  3317. return true;
  3318. }
  3319. return false;
  3320. }
  3321. inline bool CAccessToken::CreateProcessAsUser(
  3322. LPCTSTR pApplicationName, LPTSTR pCommandLine,
  3323. LPPROCESS_INFORMATION pProcessInformation,
  3324. LPSTARTUPINFO pStartupInfo,
  3325. DWORD dwCreationFlags,
  3326. bool bLoadProfile,
  3327. const CSecurityAttributes *pProcessAttributes,
  3328. const CSecurityAttributes *pThreadAttributes,
  3329. bool bInherit,
  3330. LPCTSTR pCurrentDirectory)
  3331. {
  3332. LPVOID pEnvironmentBlock;
  3333. PROFILEINFO Profile;
  3334. CSid UserSid;
  3335. HANDLE hToken = m_hToken;
  3336. // Straighten out impersonation problems...
  3337. TOKEN_TYPE TokenType;
  3338. if(!GetType(&TokenType) &&
  3339. TokenType != TokenPrimary &&
  3340. !::DuplicateTokenEx(m_hToken, TOKEN_ALL_ACCESS, NULL,
  3341. SecurityAnonymous, TokenPrimary, &hToken))
  3342. {
  3343. return false;
  3344. }
  3345. // Profile
  3346. if(bLoadProfile && !m_hProfile)
  3347. {
  3348. if(!GetUser(&UserSid))
  3349. {
  3350. if(TokenType != TokenPrimary)
  3351. ::CloseHandle(hToken);
  3352. return false;
  3353. }
  3354. memset(&Profile, 0x00, sizeof(PROFILEINFO));
  3355. Profile.dwSize = sizeof(PROFILEINFO);
  3356. Profile.lpUserName = const_cast<LPTSTR>(UserSid.AccountName());
  3357. if(::LoadUserProfile(hToken, &Profile))
  3358. m_hProfile = Profile.hProfile;
  3359. }
  3360. // Environment block
  3361. if(!::CreateEnvironmentBlock(&pEnvironmentBlock, hToken, bInherit))
  3362. return false;
  3363. BOOL bRetVal = ::CreateProcessAsUser(
  3364. hToken,
  3365. pApplicationName,
  3366. pCommandLine,
  3367. const_cast<CSecurityAttributes *>(pProcessAttributes),
  3368. const_cast<CSecurityAttributes *>(pThreadAttributes),
  3369. bInherit,
  3370. dwCreationFlags,
  3371. pEnvironmentBlock,
  3372. pCurrentDirectory,
  3373. pStartupInfo,
  3374. pProcessInformation);
  3375. if(TokenType != TokenPrimary)
  3376. ::CloseHandle(hToken);
  3377. ::DestroyEnvironmentBlock(pEnvironmentBlock);
  3378. return bRetVal != 0;
  3379. }
  3380. //*******************************************
  3381. // Private Security
  3382. class CPrivateObjectSecurityDesc : public CSecurityDesc
  3383. {
  3384. public:
  3385. CPrivateObjectSecurityDesc() : m_bPrivate(false), CSecurityDesc(){}
  3386. ~CPrivateObjectSecurityDesc() {Clear();}
  3387. bool Create(const CSecurityDesc *pParent, const CSecurityDesc *pCreator,
  3388. bool bIsDirectoryObject, const CAccessToken &Token, PGENERIC_MAPPING GenericMapping);
  3389. #if(_WIN32_WINNT >= 0x0500)
  3390. bool Create(const CSecurityDesc *pParent, const CSecurityDesc *pCreator,
  3391. GUID *ObjectType, bool bIsContainerObject, ULONG AutoInheritFlags,
  3392. const CAccessToken &Token, PGENERIC_MAPPING GenericMapping);
  3393. #endif
  3394. bool Get(SECURITY_INFORMATION si, CSecurityDesc *pResult) const;
  3395. bool Set(SECURITY_INFORMATION si, const CSecurityDesc &Modification,
  3396. PGENERIC_MAPPING GenericMapping, const CAccessToken &Token);
  3397. #if(_WIN32_WINNT >= 0x0500)
  3398. bool Set(SECURITY_INFORMATION si, const CSecurityDesc &Modification,
  3399. ULONG AutoInheritFlags, PGENERIC_MAPPING GenericMapping,
  3400. const CAccessToken &Token);
  3401. bool ConvertToAutoInherit(const CSecurityDesc *pParent, GUID *ObjectType,
  3402. bool bIsDirectoryObject, PGENERIC_MAPPING GenericMapping);
  3403. #endif
  3404. protected:
  3405. void Clear();
  3406. private:
  3407. bool m_bPrivate;
  3408. CPrivateObjectSecurityDesc(const CPrivateObjectSecurityDesc &rhs);
  3409. CPrivateObjectSecurityDesc &operator=(const CPrivateObjectSecurityDesc &rhs);
  3410. };
  3411. inline void CPrivateObjectSecurityDesc::Clear()
  3412. {
  3413. if(m_bPrivate)
  3414. {
  3415. ATLVERIFY(::DestroyPrivateObjectSecurity(reinterpret_cast<PSECURITY_DESCRIPTOR *>(&m_pSecurityDescriptor)));
  3416. m_bPrivate = false;
  3417. m_pSecurityDescriptor = NULL;
  3418. }
  3419. else
  3420. CSecurityDesc::Clear();
  3421. }
  3422. inline bool CPrivateObjectSecurityDesc::Create(const CSecurityDesc *pParent, const CSecurityDesc *pCreator,
  3423. bool bIsDirectoryObject, const CAccessToken &Token,
  3424. PGENERIC_MAPPING GenericMapping)
  3425. {
  3426. Clear();
  3427. const SECURITY_DESCRIPTOR *pSDParent = pParent ? pParent->GetPSECURITY_DESCRIPTOR() : NULL;
  3428. const SECURITY_DESCRIPTOR *pSDCreator = pCreator ? pCreator->GetPSECURITY_DESCRIPTOR() : NULL;
  3429. if(!::CreatePrivateObjectSecurity(
  3430. const_cast<SECURITY_DESCRIPTOR *>(pSDParent),
  3431. const_cast<SECURITY_DESCRIPTOR *>(pSDCreator),
  3432. reinterpret_cast<PSECURITY_DESCRIPTOR *>(&m_pSecurityDescriptor),
  3433. bIsDirectoryObject, Token.GetHandle(), GenericMapping))
  3434. {
  3435. return false;
  3436. }
  3437. m_bPrivate = true;
  3438. return true;
  3439. }
  3440. #if(_WIN32_WINNT >= 0x0500)
  3441. inline bool CPrivateObjectSecurityDesc::Create(const CSecurityDesc *pParent, const CSecurityDesc *pCreator,
  3442. GUID *ObjectType, bool bIsContainerObject, ULONG AutoInheritFlags,
  3443. const CAccessToken &Token, PGENERIC_MAPPING GenericMapping)
  3444. {
  3445. Clear();
  3446. const SECURITY_DESCRIPTOR *pSDParent = pParent ? pParent->GetPSECURITY_DESCRIPTOR() : NULL;
  3447. const SECURITY_DESCRIPTOR *pSDCreator = pCreator ? pCreator->GetPSECURITY_DESCRIPTOR() : NULL;
  3448. if(!::CreatePrivateObjectSecurityEx(
  3449. const_cast<SECURITY_DESCRIPTOR *>(pSDParent),
  3450. const_cast<SECURITY_DESCRIPTOR *>(pSDCreator),
  3451. reinterpret_cast<PSECURITY_DESCRIPTOR *>(&m_pSecurityDescriptor),
  3452. ObjectType, bIsContainerObject, AutoInheritFlags, Token.GetHandle(), GenericMapping))
  3453. {
  3454. return false;
  3455. }
  3456. m_bPrivate = true;
  3457. return true;
  3458. }
  3459. #endif
  3460. inline bool CPrivateObjectSecurityDesc::Get(SECURITY_INFORMATION si, CSecurityDesc *pResult) const
  3461. {
  3462. ATLASSERT(pResult);
  3463. if(!pResult)
  3464. return false;
  3465. if(!m_bPrivate)
  3466. return false;
  3467. DWORD dwLength = 0;
  3468. SECURITY_DESCRIPTOR *pSDResult = NULL;
  3469. if(!::GetPrivateObjectSecurity(m_pSecurityDescriptor, si, pSDResult, dwLength, &dwLength) &&
  3470. ::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  3471. {
  3472. return false;
  3473. }
  3474. pSDResult = (SECURITY_DESCRIPTOR *) _alloca(dwLength);
  3475. if(!::GetPrivateObjectSecurity(m_pSecurityDescriptor, si, pSDResult, dwLength, &dwLength))
  3476. return false;
  3477. *pResult = *pSDResult;
  3478. return true;
  3479. }
  3480. inline bool CPrivateObjectSecurityDesc::Set(SECURITY_INFORMATION si, const CSecurityDesc &Modification,
  3481. PGENERIC_MAPPING GenericMapping, const CAccessToken &Token)
  3482. {
  3483. if(!m_bPrivate)
  3484. return false;
  3485. const SECURITY_DESCRIPTOR *pSDModification = Modification.GetPSECURITY_DESCRIPTOR();
  3486. return 0 != ::SetPrivateObjectSecurity(si,
  3487. const_cast<SECURITY_DESCRIPTOR *>(pSDModification),
  3488. reinterpret_cast<PSECURITY_DESCRIPTOR *>(&m_pSecurityDescriptor),
  3489. GenericMapping, Token.GetHandle());
  3490. }
  3491. #if(_WIN32_WINNT >= 0x0500)
  3492. inline bool CPrivateObjectSecurityDesc::Set(SECURITY_INFORMATION si, const CSecurityDesc &Modification,
  3493. ULONG AutoInheritFlags, PGENERIC_MAPPING GenericMapping,
  3494. const CAccessToken &Token)
  3495. {
  3496. if(!m_bPrivate)
  3497. return false;
  3498. const SECURITY_DESCRIPTOR *pSDModification = Modification.GetPSECURITY_DESCRIPTOR();
  3499. return 0 != ::SetPrivateObjectSecurityEx(si,
  3500. const_cast<SECURITY_DESCRIPTOR *>(pSDModification),
  3501. reinterpret_cast<PSECURITY_DESCRIPTOR *>(&m_pSecurityDescriptor),
  3502. AutoInheritFlags, GenericMapping, Token.GetHandle());
  3503. }
  3504. inline bool CPrivateObjectSecurityDesc::ConvertToAutoInherit(const CSecurityDesc *pParent, GUID *ObjectType,
  3505. bool bIsDirectoryObject, PGENERIC_MAPPING GenericMapping)
  3506. {
  3507. if(!m_bPrivate)
  3508. return false;
  3509. const SECURITY_DESCRIPTOR *pSDParent = pParent ? pParent->GetPSECURITY_DESCRIPTOR() : NULL;
  3510. SECURITY_DESCRIPTOR *pSD;
  3511. if(!::ConvertToAutoInheritPrivateObjectSecurity(
  3512. const_cast<SECURITY_DESCRIPTOR *>(pSDParent),
  3513. m_pSecurityDescriptor,
  3514. reinterpret_cast<PSECURITY_DESCRIPTOR *>(&pSD),
  3515. ObjectType, bIsDirectoryObject, GenericMapping))
  3516. {
  3517. return false;
  3518. }
  3519. Clear();
  3520. m_bPrivate = true;
  3521. m_pSecurityDescriptor = pSD;
  3522. return true;
  3523. }
  3524. #endif // _WIN32_WINNT >= 0x500
  3525. //*******************************************
  3526. // Globals
  3527. inline bool AtlGetSecurityDescriptor(LPCTSTR pszObjectName,
  3528. SE_OBJECT_TYPE ObjectType,
  3529. CSecurityDesc *pSecurityDescriptor)
  3530. {
  3531. ATLASSERT(pSecurityDescriptor);
  3532. if(!pSecurityDescriptor)
  3533. return false;
  3534. SECURITY_DESCRIPTOR *pSD;
  3535. SECURITY_INFORMATION si =
  3536. OWNER_SECURITY_INFORMATION |
  3537. GROUP_SECURITY_INFORMATION |
  3538. DACL_SECURITY_INFORMATION;
  3539. DWORD dwErr;
  3540. CAccessToken at;
  3541. CTokenPrivileges TokenPrivileges;
  3542. // Try SACL
  3543. if(at.OpenThreadToken(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  3544. false, false, SecurityImpersonation) &&
  3545. at.EnablePrivilege(SE_SECURITY_NAME, &TokenPrivileges))
  3546. {
  3547. si |= SACL_SECURITY_INFORMATION;
  3548. }
  3549. // REVIEW: should *we* impersonate, or should we let the user impersonate?
  3550. if(!at.Impersonate())
  3551. return false;
  3552. dwErr = ::GetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType, si,
  3553. NULL, NULL, NULL, NULL, (PSECURITY_DESCRIPTOR *) &pSD);
  3554. at.EnableDisablePrivileges(TokenPrivileges);
  3555. if(dwErr != ERROR_SUCCESS && (si & SACL_SECURITY_INFORMATION))
  3556. {
  3557. // could be the SACL causing problems... try without
  3558. si &= ~SACL_SECURITY_INFORMATION;
  3559. dwErr = ::GetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType, si,
  3560. NULL, NULL, NULL, NULL, (PSECURITY_DESCRIPTOR *) &pSD);
  3561. }
  3562. at.Revert();
  3563. if(dwErr != ERROR_SUCCESS)
  3564. {
  3565. ::SetLastError(dwErr);
  3566. return false;
  3567. }
  3568. *pSecurityDescriptor = *pSD;
  3569. ::LocalFree(pSD);
  3570. return true;
  3571. }
  3572. inline bool AtlGetSecurityDescriptor(HANDLE hObject,
  3573. SE_OBJECT_TYPE ObjectType,
  3574. CSecurityDesc *pSecurityDescriptor)
  3575. {
  3576. ATLASSERT(pSecurityDescriptor);
  3577. if(!pSecurityDescriptor)
  3578. return false;
  3579. SECURITY_DESCRIPTOR *pSD;
  3580. SECURITY_INFORMATION si =
  3581. OWNER_SECURITY_INFORMATION |
  3582. GROUP_SECURITY_INFORMATION |
  3583. DACL_SECURITY_INFORMATION;
  3584. DWORD dwErr;
  3585. CAccessToken at;
  3586. CTokenPrivileges TokenPrivileges;
  3587. // Try SACL
  3588. if(at.OpenThreadToken(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  3589. false, false, SecurityImpersonation) &&
  3590. at.EnablePrivilege(SE_SECURITY_NAME, &TokenPrivileges))
  3591. {
  3592. si |= SACL_SECURITY_INFORMATION;
  3593. }
  3594. // REVIEW: should *we* impersonate, or should we let the user impersonate?
  3595. if(!at.Impersonate())
  3596. return false;
  3597. dwErr = ::GetSecurityInfo(hObject, ObjectType, si,
  3598. NULL, NULL, NULL, NULL, reinterpret_cast<PSECURITY_DESCRIPTOR *>(&pSD));
  3599. at.EnableDisablePrivileges(TokenPrivileges);
  3600. if(dwErr != ERROR_SUCCESS && (si & SACL_SECURITY_INFORMATION))
  3601. {
  3602. // could be the SACL causing problems... try without
  3603. si &= ~SACL_SECURITY_INFORMATION;
  3604. dwErr = ::GetSecurityInfo(hObject, ObjectType, si,
  3605. NULL, NULL, NULL, NULL, reinterpret_cast<PSECURITY_DESCRIPTOR *>(&pSD));
  3606. }
  3607. at.Revert();
  3608. if(dwErr != ERROR_SUCCESS)
  3609. {
  3610. ::SetLastError(dwErr);
  3611. return false;
  3612. }
  3613. *pSecurityDescriptor = *pSD;
  3614. ::LocalFree(pSD);
  3615. return true;
  3616. }
  3617. inline bool AtlGetOwnerSid(HANDLE hObject, SE_OBJECT_TYPE ObjectType, CSid *pSid)
  3618. {
  3619. ATLASSERT(hObject && pSid);
  3620. if(!hObject || !pSid)
  3621. return false;
  3622. SID *pOwner;
  3623. PSECURITY_DESCRIPTOR pSD;
  3624. DWORD dwErr = ::GetSecurityInfo(hObject, ObjectType, OWNER_SECURITY_INFORMATION,
  3625. (PSID *) &pOwner, NULL, NULL, NULL, &pSD);
  3626. if(dwErr != ERROR_SUCCESS)
  3627. {
  3628. ::SetLastError(dwErr);
  3629. return false;
  3630. }
  3631. *pSid = *pOwner;
  3632. ::LocalFree(pSD);
  3633. return true;
  3634. }
  3635. inline bool AtlSetOwnerSid(HANDLE hObject, SE_OBJECT_TYPE ObjectType, const CSid &rSid)
  3636. {
  3637. ATLASSERT(hObject && rSid.IsValid());
  3638. if(!hObject || !rSid.IsValid())
  3639. return false;
  3640. DWORD dwErr = ::SetSecurityInfo(hObject, ObjectType, OWNER_SECURITY_INFORMATION,
  3641. const_cast<SID *>(rSid.GetPSID()), NULL, NULL, NULL);
  3642. ::SetLastError(dwErr);
  3643. return ERROR_SUCCESS == dwErr;
  3644. }
  3645. inline bool AtlGetOwnerSid(LPCTSTR pszObjectName, SE_OBJECT_TYPE ObjectType, CSid *pSid)
  3646. {
  3647. ATLASSERT(pszObjectName && pSid);
  3648. if(!pszObjectName || !pSid)
  3649. return false;
  3650. SID *pOwner;
  3651. PSECURITY_DESCRIPTOR pSD;
  3652. DWORD dwErr = ::GetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType,
  3653. OWNER_SECURITY_INFORMATION, reinterpret_cast<PSID *>(&pOwner), NULL, NULL, NULL, &pSD);
  3654. if(dwErr != ERROR_SUCCESS)
  3655. {
  3656. ::SetLastError(dwErr);
  3657. return false;
  3658. }
  3659. *pSid = *pOwner;
  3660. ::LocalFree(pSD);
  3661. return true;
  3662. }
  3663. inline bool AtlSetOwnerSid(LPCTSTR pszObjectName, SE_OBJECT_TYPE ObjectType, const CSid &rSid)
  3664. {
  3665. ATLASSERT(pszObjectName && rSid.IsValid());
  3666. if(!pszObjectName || !rSid.IsValid())
  3667. return false;
  3668. DWORD dwErr = ::SetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType,
  3669. OWNER_SECURITY_INFORMATION, const_cast<SID *>(rSid.GetPSID()), NULL, NULL, NULL);
  3670. ::SetLastError(dwErr);
  3671. return ERROR_SUCCESS == dwErr;
  3672. }
  3673. inline bool AtlGetGroupSid(HANDLE hObject, SE_OBJECT_TYPE ObjectType, CSid *pSid)
  3674. {
  3675. ATLASSERT(hObject && pSid);
  3676. if(!hObject || !pSid)
  3677. return false;
  3678. SID *pGroup;
  3679. PSECURITY_DESCRIPTOR pSD;
  3680. DWORD dwErr = ::GetSecurityInfo(hObject, ObjectType, GROUP_SECURITY_INFORMATION,
  3681. NULL, reinterpret_cast<PSID *>(&pGroup), NULL, NULL, &pSD);
  3682. if(dwErr != ERROR_SUCCESS)
  3683. {
  3684. ::SetLastError(dwErr);
  3685. return false;
  3686. }
  3687. *pSid = *pGroup;
  3688. ::LocalFree(pSD);
  3689. return true;
  3690. }
  3691. inline bool AtlSetGroupSid(HANDLE hObject, SE_OBJECT_TYPE ObjectType, const CSid &rSid)
  3692. {
  3693. ATLASSERT(hObject && rSid.IsValid());
  3694. if(!hObject || !rSid.IsValid())
  3695. return false;
  3696. DWORD dwErr = ::SetSecurityInfo(hObject, ObjectType, GROUP_SECURITY_INFORMATION,
  3697. NULL, const_cast<SID *>(rSid.GetPSID()), NULL, NULL);
  3698. ::SetLastError(dwErr);
  3699. return ERROR_SUCCESS == dwErr;
  3700. }
  3701. inline bool AtlGetGroupSid(LPCTSTR pszObjectName, SE_OBJECT_TYPE ObjectType, CSid *pSid)
  3702. {
  3703. ATLASSERT(pszObjectName && pSid);
  3704. if(!pszObjectName || !pSid)
  3705. return false;
  3706. SID *pGroup;
  3707. PSECURITY_DESCRIPTOR pSD;
  3708. DWORD dwErr = ::GetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName),
  3709. ObjectType, GROUP_SECURITY_INFORMATION, NULL,
  3710. reinterpret_cast<PSID *>(&pGroup), NULL, NULL, &pSD);
  3711. if(dwErr != ERROR_SUCCESS)
  3712. {
  3713. ::SetLastError(dwErr);
  3714. return false;
  3715. }
  3716. *pSid = *pGroup;
  3717. ::LocalFree(pSD);
  3718. return true;
  3719. }
  3720. inline bool AtlSetGroupSid(LPCTSTR pszObjectName, SE_OBJECT_TYPE ObjectType, const CSid &rSid)
  3721. {
  3722. ATLASSERT(pszObjectName && rSid.IsValid());
  3723. if(!pszObjectName || !rSid.IsValid())
  3724. return false;
  3725. DWORD dwErr = ::SetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType,
  3726. GROUP_SECURITY_INFORMATION, NULL, const_cast<SID *>(rSid.GetPSID()), NULL, NULL);
  3727. ::SetLastError(dwErr);
  3728. return ERROR_SUCCESS == dwErr;
  3729. }
  3730. inline bool AtlGetDacl(HANDLE hObject, SE_OBJECT_TYPE ObjectType, CDacl *pDacl)
  3731. {
  3732. ATLASSERT(hObject && pDacl);
  3733. if(!hObject || !pDacl)
  3734. return false;
  3735. ACL *pAcl;
  3736. PSECURITY_DESCRIPTOR pSD;
  3737. DWORD dwErr = ::GetSecurityInfo(hObject, ObjectType, DACL_SECURITY_INFORMATION,
  3738. NULL, NULL, &pAcl, NULL, &pSD);
  3739. if(dwErr != ERROR_SUCCESS)
  3740. {
  3741. ::SetLastError(dwErr);
  3742. return false;
  3743. }
  3744. if(pAcl)
  3745. *pDacl = *pAcl;
  3746. ::LocalFree(pSD);
  3747. return NULL != pAcl;
  3748. }
  3749. inline bool AtlSetDacl(HANDLE hObject, SE_OBJECT_TYPE ObjectType, const CDacl &rDacl,
  3750. DWORD dwInheritanceFlowControl = 0)
  3751. {
  3752. ATLASSERT(hObject);
  3753. if(!hObject)
  3754. return false;
  3755. ATLASSERT(
  3756. dwInheritanceFlowControl == 0 ||
  3757. dwInheritanceFlowControl == PROTECTED_DACL_SECURITY_INFORMATION ||
  3758. dwInheritanceFlowControl == UNPROTECTED_DACL_SECURITY_INFORMATION);
  3759. DWORD dwErr = ::SetSecurityInfo(hObject, ObjectType,
  3760. DACL_SECURITY_INFORMATION | dwInheritanceFlowControl,
  3761. NULL, NULL, const_cast<ACL *>(rDacl.GetPACL()), NULL);
  3762. ::SetLastError(dwErr);
  3763. return ERROR_SUCCESS == dwErr;
  3764. }
  3765. inline bool AtlGetDacl(LPCTSTR pszObjectName, SE_OBJECT_TYPE ObjectType, CDacl *pDacl)
  3766. {
  3767. ATLASSERT(pszObjectName && pDacl);
  3768. if(!pszObjectName || !pDacl)
  3769. return false;
  3770. ACL *pAcl;
  3771. PSECURITY_DESCRIPTOR pSD;
  3772. DWORD dwErr = ::GetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType,
  3773. DACL_SECURITY_INFORMATION, NULL, NULL, &pAcl, NULL, &pSD);
  3774. if(dwErr != ERROR_SUCCESS)
  3775. {
  3776. ::SetLastError(dwErr);
  3777. return false;
  3778. }
  3779. if(pAcl)
  3780. *pDacl = *pAcl;
  3781. ::LocalFree(pSD);
  3782. return NULL != pAcl;
  3783. }
  3784. inline bool AtlSetDacl(LPCTSTR pszObjectName, SE_OBJECT_TYPE ObjectType, const CDacl &rDacl,
  3785. DWORD dwInheritanceFlowControl = 0)
  3786. {
  3787. ATLASSERT(pszObjectName);
  3788. if(!pszObjectName)
  3789. return false;
  3790. ATLASSERT(
  3791. dwInheritanceFlowControl == 0 ||
  3792. dwInheritanceFlowControl == PROTECTED_DACL_SECURITY_INFORMATION ||
  3793. dwInheritanceFlowControl == UNPROTECTED_DACL_SECURITY_INFORMATION);
  3794. DWORD dwErr = ::SetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType,
  3795. DACL_SECURITY_INFORMATION | dwInheritanceFlowControl,
  3796. NULL, NULL, const_cast<ACL *>(rDacl.GetPACL()), NULL);
  3797. ::SetLastError(dwErr);
  3798. return ERROR_SUCCESS == dwErr;
  3799. }
  3800. inline bool AtlGetSacl(HANDLE hObject, SE_OBJECT_TYPE ObjectType, CSacl *pSacl)
  3801. {
  3802. ATLASSERT(hObject && pSacl);
  3803. if(!hObject || !pSacl)
  3804. return false;
  3805. ACL *pAcl;
  3806. PSECURITY_DESCRIPTOR pSD;
  3807. CAccessToken at;
  3808. CTokenPrivileges TokenPrivileges;
  3809. // REVIEW: A LOT. I'm wondering whether or not it's absolutely necessary to impersonate
  3810. // the thread token here (rather than let the user do it or something).
  3811. // Furthermore, should SecurityImpersonation be hard-coded? Maybe it should be a param?
  3812. if(!at.OpenThreadToken(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  3813. false, false, SecurityImpersonation) ||
  3814. !at.EnablePrivilege(SE_SECURITY_NAME, &TokenPrivileges) ||
  3815. !at.Impersonate())
  3816. {
  3817. return false;
  3818. }
  3819. DWORD dwErr = ::GetSecurityInfo(hObject, ObjectType, SACL_SECURITY_INFORMATION,
  3820. NULL, NULL, NULL, &pAcl, &pSD);
  3821. at.EnableDisablePrivileges(TokenPrivileges);
  3822. at.Revert();
  3823. if(dwErr != ERROR_SUCCESS)
  3824. {
  3825. ::SetLastError(dwErr);
  3826. return false;
  3827. }
  3828. if(pAcl)
  3829. *pSacl = *pAcl;
  3830. ::LocalFree(pSD);
  3831. return NULL != pAcl;
  3832. }
  3833. inline bool AtlSetSacl(HANDLE hObject, SE_OBJECT_TYPE ObjectType, const CSacl &rSacl,
  3834. DWORD dwInheritanceFlowControl = 0)
  3835. {
  3836. ATLASSERT(hObject);
  3837. CAccessToken at;
  3838. CTokenPrivileges TokenPrivileges;
  3839. ATLASSERT(
  3840. dwInheritanceFlowControl == 0 ||
  3841. dwInheritanceFlowControl == PROTECTED_SACL_SECURITY_INFORMATION ||
  3842. dwInheritanceFlowControl == UNPROTECTED_SACL_SECURITY_INFORMATION);
  3843. // REVIEW: Should we be impersonating?
  3844. if(!hObject ||
  3845. !at.OpenThreadToken(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  3846. false, false, SecurityImpersonation) ||
  3847. !at.EnablePrivilege(SE_SECURITY_NAME, &TokenPrivileges) ||
  3848. !at.Impersonate())
  3849. {
  3850. return false;
  3851. }
  3852. DWORD dwErr = ::SetSecurityInfo(hObject, ObjectType,
  3853. SACL_SECURITY_INFORMATION | dwInheritanceFlowControl,
  3854. NULL, NULL, NULL, const_cast<ACL *>(rSacl.GetPACL()));
  3855. at.EnableDisablePrivileges(TokenPrivileges);
  3856. at.Revert();
  3857. ::SetLastError(dwErr);
  3858. return ERROR_SUCCESS == dwErr;
  3859. }
  3860. inline bool AtlGetSacl(LPCTSTR pszObjectName, SE_OBJECT_TYPE ObjectType, CSacl *pSacl)
  3861. {
  3862. ATLASSERT(pszObjectName && pSacl);
  3863. if(!pszObjectName || !pSacl)
  3864. return false;
  3865. ACL *pAcl;
  3866. PSECURITY_DESCRIPTOR pSD;
  3867. CAccessToken at;
  3868. CTokenPrivileges TokenPrivileges;
  3869. // REVIEW: Should we be impersonating?
  3870. if(!at.OpenThreadToken(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  3871. false, false, SecurityImpersonation) ||
  3872. !at.EnablePrivilege(SE_SECURITY_NAME, &TokenPrivileges) ||
  3873. !at.Impersonate())
  3874. {
  3875. return false;
  3876. }
  3877. DWORD dwErr = ::GetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType,
  3878. SACL_SECURITY_INFORMATION, NULL, NULL, NULL, &pAcl, &pSD);
  3879. at.EnableDisablePrivileges(TokenPrivileges);
  3880. at.Revert();
  3881. ::SetLastError(dwErr);
  3882. if(dwErr != ERROR_SUCCESS)
  3883. return false;
  3884. if(pAcl)
  3885. *pSacl = *pAcl;
  3886. ::LocalFree(pSD);
  3887. return NULL != pAcl;
  3888. }
  3889. inline bool AtlSetSacl(LPCTSTR pszObjectName, SE_OBJECT_TYPE ObjectType, const CSacl &rSacl,
  3890. DWORD dwInheritanceFlowControl = 0)
  3891. {
  3892. ATLASSERT(pszObjectName);
  3893. CAccessToken at;
  3894. CTokenPrivileges TokenPrivileges;
  3895. ATLASSERT(
  3896. dwInheritanceFlowControl == 0 ||
  3897. dwInheritanceFlowControl == PROTECTED_SACL_SECURITY_INFORMATION ||
  3898. dwInheritanceFlowControl == UNPROTECTED_SACL_SECURITY_INFORMATION);
  3899. // REVIEW: Should we be impersonating or should the user take care of this?
  3900. if(!pszObjectName ||
  3901. !at.OpenThreadToken(TOKEN_IMPERSONATE | TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  3902. false, false, SecurityImpersonation) ||
  3903. !at.EnablePrivilege(SE_SECURITY_NAME, &TokenPrivileges) ||
  3904. !at.Impersonate())
  3905. {
  3906. return false;
  3907. }
  3908. DWORD dwErr = ::SetNamedSecurityInfo(const_cast<LPTSTR>(pszObjectName), ObjectType,
  3909. SACL_SECURITY_INFORMATION | dwInheritanceFlowControl,
  3910. NULL, NULL, NULL, const_cast<ACL *>(rSacl.GetPACL()));
  3911. at.EnableDisablePrivileges(TokenPrivileges);
  3912. at.Revert();
  3913. ::SetLastError(dwErr);
  3914. return ERROR_SUCCESS == dwErr;
  3915. }
  3916. } // namespace ATL
  3917. #endif // __ATLSECURITY_H__