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.

1064 lines
26 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: RegKeySecurity.cpp
  7. //
  8. // Contents: Provides code for changes to Regkey Security
  9. //
  10. //
  11. // Notes:
  12. //
  13. // Author: ckotze 4 July 2000
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include <ncreg.h>
  19. #include <regkysec.h>
  20. #include <ncutil.h>
  21. #include <ncdebug.h>
  22. //+---------------------------------------------------------------------------
  23. //
  24. // Function: CRegKeySecurity constructor
  25. //
  26. // Purpose:
  27. //
  28. // Arguments:
  29. //
  30. // Returns:
  31. //
  32. // Author: ckotze 4 July 2000
  33. //
  34. // Notes:
  35. //
  36. CRegKeySecurity::CRegKeySecurity() : m_psdRegKey(NULL), m_bDaclDefaulted(FALSE), m_hkeyCurrent(0),
  37. m_paclDacl(NULL), m_bHasDacl(FALSE), m_psidGroup(NULL), m_psidOwner(NULL), m_paclSacl(NULL), m_bHasSacl(FALSE)
  38. {
  39. }
  40. //+---------------------------------------------------------------------------
  41. //
  42. // Function: CRegKeySecurity destructor
  43. //
  44. // Purpose:
  45. //
  46. // Arguments:
  47. //
  48. // Returns:
  49. //
  50. // Author: ckotze 4 July 2000
  51. //
  52. // Notes:
  53. //
  54. CRegKeySecurity::~CRegKeySecurity()
  55. {
  56. if (m_psdRegKey)
  57. {
  58. delete[] m_psdRegKey;
  59. }
  60. RegCloseKey();
  61. m_listAllAce.clear();
  62. }
  63. //+---------------------------------------------------------------------------
  64. //
  65. // Function: RegOpenKey
  66. //
  67. // Purpose: Opens the Registry Key with enough privileges to set the
  68. // permission on the Key.
  69. //
  70. // Arguments:
  71. // hkeyRoot - the root key from which to open the subkey
  72. //
  73. // strKeyName - the subkey to open.
  74. //
  75. // Returns: An S_OK if the key was successfully opened, and error code
  76. // otherwise
  77. //
  78. // Author: ckotze 4 July 2000
  79. //
  80. // Notes:
  81. //
  82. HRESULT CRegKeySecurity::RegOpenKey(const HKEY hkeyRoot, LPCTSTR strKeyName)
  83. {
  84. LONG lResult = 0;
  85. DWORD dwRightsRequired = KEY_ALL_ACCESS;
  86. if (m_hkeyCurrent)
  87. {
  88. RegCloseKey();
  89. }
  90. if ((lResult = HrRegOpenKeyEx(hkeyRoot, strKeyName, dwRightsRequired, &m_hkeyCurrent)) != ERROR_SUCCESS)
  91. {
  92. return HRESULT_FROM_WIN32(lResult);
  93. }
  94. return S_OK;
  95. }
  96. //+---------------------------------------------------------------------------
  97. //
  98. // Function: GetKeySecurity
  99. //
  100. // Purpose: Retrieves the Security Descriptor for the currently open
  101. // Registry key.
  102. //
  103. // Arguments: None
  104. //
  105. //
  106. //
  107. // Returns: An S_OK if the key was successfully opened, and error code
  108. // otherwise
  109. //
  110. // Author: ckotze 4 July 2000
  111. //
  112. // Notes:
  113. //
  114. HRESULT CRegKeySecurity::GetKeySecurity()
  115. {
  116. HRESULT hr = S_OK;
  117. DWORD cbSD = 1; // try a size that won't be large enough
  118. LONG lResult;
  119. if (!m_hkeyCurrent)
  120. {
  121. TraceError("CRegKeySecurity::GetKeySecurity", E_UNEXPECTED);
  122. return E_UNEXPECTED;
  123. }
  124. // First call should get the correct size.
  125. if ((hr = HrRegGetKeySecurity(m_hkeyCurrent, OWNER_SECURITY_INFORMATION |
  126. GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  127. &m_psdRegKey, &cbSD)) != S_OK)
  128. {
  129. if (m_psdRegKey)
  130. {
  131. delete[] m_psdRegKey;
  132. }
  133. if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
  134. {
  135. m_psdRegKey = reinterpret_cast<PSECURITY_DESCRIPTOR>(new BYTE[cbSD]);
  136. hr = HrRegGetKeySecurity(m_hkeyCurrent, OWNER_SECURITY_INFORMATION |
  137. GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
  138. m_psdRegKey, &cbSD);
  139. }
  140. }
  141. return hr;
  142. }
  143. //+---------------------------------------------------------------------------
  144. //
  145. // Function: SetKeySecurity
  146. //
  147. // Purpose: Updates the Security Descriptor of the currently open key.
  148. //
  149. //
  150. // Arguments: None
  151. //
  152. //
  153. // Returns: An S_OK if the key was successfully opened, and error code
  154. // otherwise
  155. //
  156. // Author: ckotze 4 July 2000
  157. //
  158. // Notes:
  159. //
  160. HRESULT CRegKeySecurity::SetKeySecurity()
  161. {
  162. HRESULT hr = S_OK;
  163. if ((hr = HrRegSetKeySecurity(m_hkeyCurrent, OWNER_SECURITY_INFORMATION
  164. | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, m_psdRegKey)) != S_OK)
  165. {
  166. TraceError("CRegKeySecurity::SetKeySecurity", hr);
  167. }
  168. return hr;
  169. }
  170. //+---------------------------------------------------------------------------
  171. //
  172. // Function: RegCloseKey
  173. //
  174. // Purpose: Closes the currently open registry key.
  175. //
  176. //
  177. // Arguments: None
  178. //
  179. //
  180. //
  181. // Returns: An S_OK if the key was successfully opened, and error code
  182. // otherwise
  183. //
  184. // Author: ckotze 4 July 2000
  185. //
  186. // Notes:
  187. //
  188. HRESULT CRegKeySecurity::RegCloseKey()
  189. {
  190. HRESULT hr = S_OK;
  191. if (m_hkeyCurrent)
  192. {
  193. LONG err;
  194. err = ::RegCloseKey(m_hkeyCurrent);
  195. hr = HRESULT_FROM_WIN32(err);
  196. m_hkeyCurrent = 0;
  197. }
  198. return hr;
  199. }
  200. //+---------------------------------------------------------------------------
  201. //
  202. // Function: GetSecurityDescriptorDacl
  203. //
  204. // Purpose: Retrieve the Discretionary Access Control List from the SD
  205. //
  206. //
  207. // Arguments:
  208. //
  209. //
  210. // Returns: An S_OK if the key was successfully opened, and error code
  211. // otherwise
  212. //
  213. // Author: ckotze 4 July 2000
  214. //
  215. // Notes:
  216. //
  217. HRESULT CRegKeySecurity::GetSecurityDescriptorDacl()
  218. {
  219. HRESULT hr = S_OK;
  220. if (!m_psdRegKey)
  221. {
  222. return E_UNEXPECTED;
  223. }
  224. if (!::GetSecurityDescriptorDacl(m_psdRegKey,
  225. (LPBOOL)&m_bHasDacl,
  226. (PACL *)&m_paclDacl,
  227. (LPBOOL)&m_bDaclDefaulted))
  228. {
  229. DWORD dwErr;
  230. dwErr = GetLastError();
  231. hr = HRESULT_FROM_WIN32(dwErr);
  232. }
  233. return hr;
  234. }
  235. //+---------------------------------------------------------------------------
  236. //
  237. // Function: SetSecurityDescriptorDacl
  238. //
  239. // Purpose: Update the Discretionary Access Control List in the SD
  240. //
  241. //
  242. // Arguments:
  243. //
  244. //
  245. // Returns: An S_OK if the key was successfully opened, and error code
  246. // otherwise
  247. //
  248. // Author: ckotze 4 July 2000
  249. //
  250. // Notes:
  251. //
  252. HRESULT CRegKeySecurity::SetSecurityDescriptorDacl(PACL paclDacl, DWORD dwNumEntries)
  253. {
  254. HRESULT hr = E_FAIL;
  255. DWORD dwErr = 0;
  256. SECURITY_DESCRIPTOR psdSD = {0};
  257. SECURITY_DESCRIPTOR_CONTROL pSDCControl;
  258. PACL pDacl = NULL;
  259. PACL pSacl = NULL;
  260. PSID psidOwner = NULL;
  261. PSID psidGroup = NULL;
  262. DWORD dwSDSize = sizeof(psdSD);
  263. DWORD dwOwnerSIDSize = 0;
  264. DWORD dwGroupSIDSize = 0;
  265. DWORD cbDacl = 0;
  266. DWORD cbSacl = 0;
  267. DWORD dwRevision = 0;
  268. if (!paclDacl)
  269. {
  270. return E_INVALIDARG;
  271. }
  272. if (GetSecurityDescriptorControl(m_psdRegKey, &pSDCControl, &dwRevision))
  273. {
  274. if (SE_SELF_RELATIVE & pSDCControl)
  275. {
  276. if (!MakeAbsoluteSD(m_psdRegKey, &psdSD, &dwSDSize, pDacl, &cbDacl, pSacl, &cbSacl, psidOwner, &dwOwnerSIDSize, psidGroup, &dwGroupSIDSize))
  277. {
  278. pDacl = reinterpret_cast<PACL>(new BYTE[cbDacl]);
  279. if (!pDacl)
  280. {
  281. return E_OUTOFMEMORY;
  282. }
  283. psidOwner = new BYTE[dwOwnerSIDSize];
  284. if (!psidOwner)
  285. {
  286. delete[] pDacl;
  287. return E_OUTOFMEMORY;
  288. }
  289. psidGroup = new BYTE[dwGroupSIDSize];
  290. if (!psidGroup)
  291. {
  292. delete[] pDacl;
  293. delete[] psidOwner;
  294. return E_OUTOFMEMORY;
  295. }
  296. else if (MakeAbsoluteSD(m_psdRegKey, &psdSD, &dwSDSize, pDacl, &cbDacl, pSacl, &cbSacl, psidOwner, &dwOwnerSIDSize, psidGroup, &dwGroupSIDSize))
  297. {
  298. if (!::SetSecurityDescriptorDacl(&psdSD, m_bHasDacl, paclDacl, m_bDaclDefaulted))
  299. {
  300. dwErr = GetLastError();
  301. }
  302. if (!MakeSelfRelativeSD(&psdSD, m_psdRegKey, &dwSDSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  303. {
  304. if (m_psdRegKey)
  305. {
  306. delete[] m_psdRegKey;
  307. }
  308. m_psdRegKey = reinterpret_cast<PSECURITY_DESCRIPTOR>(new BYTE[dwSDSize]);
  309. if (MakeSelfRelativeSD(&psdSD, m_psdRegKey, &dwSDSize))
  310. {
  311. hr = S_OK;
  312. SetLastError(0);
  313. m_paclDacl = NULL;
  314. }
  315. }
  316. }
  317. delete[] pDacl;
  318. delete[] psidOwner;
  319. delete[] psidGroup;
  320. }
  321. }
  322. }
  323. else
  324. {
  325. DWORD dwErr;
  326. dwErr = GetLastError();
  327. hr = HRESULT_FROM_WIN32(dwErr);
  328. }
  329. return hr;
  330. }
  331. //+---------------------------------------------------------------------------
  332. //
  333. // Function: GrantRightsOnRegKey
  334. //
  335. // Purpose: Add the specified account to the ACL with the permissions
  336. // required and the inheritance information.
  337. //
  338. // Arguments:
  339. // psidUserOrGroup - The sid (Security Identifier) of the user to
  340. // be added.
  341. // amPermissionMask - The permissions to be granted.
  342. //
  343. // kamMask - Applies to this key or child keys or both?
  344. //
  345. //
  346. // Returns: An S_OK if the key was successfully opened, and error code
  347. // otherwise
  348. //
  349. // Author: ckotze 4 July 2000
  350. //
  351. // Notes:
  352. //
  353. HRESULT CRegKeySecurity::GrantRightsOnRegKey(PCSID psidUserOrGroup, ACCESS_MASK amPermissionsMask, KEY_APPLY_MASK kamMask)
  354. {
  355. HRESULT hr = E_FAIL;
  356. PACCESS_ALLOWED_ACE paaAllowedAce = NULL;
  357. PACCESS_DENIED_ACE paaDeniedAce = NULL;
  358. BOOL bAceMatch = FALSE;
  359. BYTE cAceFlags = 0;
  360. DWORD cbAcl = 0;
  361. DWORD cbAce = 0;
  362. if (!IsValidSid(const_cast<PSID>(psidUserOrGroup)))
  363. {
  364. return HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  365. }
  366. hr = GetAccessControlEntriesFromAcl();
  367. if (FAILED(hr))
  368. {
  369. return hr;
  370. }
  371. cbAcl = sizeof(ACL);
  372. for (ACEITER i = m_listAllAce.begin(); i != m_listAllAce.end() ; i++)
  373. {
  374. CAccessControlEntry paEntry(*i);
  375. cbAcl += sizeof(ACCESS_ALLOWED_ACE) + 8 +
  376. paEntry.GetLengthSid()- sizeof(DWORD);
  377. // Assert(kamMask)
  378. switch (kamMask)
  379. {
  380. case KEY_CURRENT:
  381. {
  382. cAceFlags = 0; // Do not allow this to be inherited by children.
  383. break;
  384. }
  385. case KEY_CHILDREN:
  386. {
  387. cAceFlags = CONTAINER_INHERIT_ACE;
  388. cAceFlags |= INHERIT_ONLY_ACE;
  389. break;
  390. }
  391. case KEY_ALL:
  392. {
  393. cAceFlags = CONTAINER_INHERIT_ACE;
  394. break;
  395. }
  396. default:
  397. return E_INVALIDARG;
  398. }
  399. if (paEntry.HasExactRights(amPermissionsMask) && paEntry.HasExactInheritFlags(cAceFlags) && paEntry.IsEqualSid(psidUserOrGroup))
  400. {
  401. bAceMatch = TRUE;
  402. }
  403. }
  404. if (!bAceMatch)
  405. {
  406. ACCESS_ALLOWED_ACE paEntry = {NULL};
  407. ACL_REVISION_INFORMATION AclRevisionInfo;
  408. PACL pNewDACL = NULL;
  409. CAccessControlEntry AccessControlEntry(ACCESS_ALLOWED_ACE_TYPE, amPermissionsMask, cAceFlags, psidUserOrGroup);
  410. // subtract ACE.SidStart from the size
  411. cbAce = sizeof (paEntry) - sizeof (DWORD);
  412. // add this ACE's SID length
  413. cbAce += 8 + GetLengthSid(const_cast<PSID>(psidUserOrGroup));
  414. // add the length of each ACE to the total ACL length
  415. cbAcl += cbAce;
  416. m_listAllAce.insert(m_listAllAce.end(), AccessControlEntry);
  417. AclRevisionInfo.AclRevision = ACL_REVISION;
  418. hr = BuildAndApplyACLFromList(cbAcl, AclRevisionInfo);
  419. if (SUCCEEDED(hr))
  420. {
  421. hr = SetKeySecurity();
  422. }
  423. }
  424. else
  425. {
  426. hr = S_FALSE;
  427. }
  428. return hr;
  429. }
  430. //+---------------------------------------------------------------------------
  431. //
  432. // Function: RevokeRightsOnRegKey
  433. //
  434. // Purpose: Remove the specified account to the ACL with the permissions
  435. // required and the inheritance information.
  436. //
  437. // Arguments:
  438. // psidUserOrGroup - The sid (Security Identifier) of the user to
  439. // be added.
  440. // amPermissionMask - The permissions to be granted.
  441. //
  442. // kamMask - Applies to this key or child keys or both?
  443. //
  444. // Returns: An S_OK if the key was successfully opened, and error code
  445. // otherwise
  446. //
  447. // Author: ckotze 4 July 2000
  448. //
  449. // Notes: This is designed to only remove the exact combination of user
  450. // rights and sid and key apply mask. This is to stop us from
  451. // accidentally deleting a key that was put there for the user/group
  452. // by an administrator.
  453. //
  454. HRESULT CRegKeySecurity::RevokeRightsOnRegKey(PCSID psidUserOrGroup, ACCESS_MASK amPermissionsMask, KEY_APPLY_MASK kamMask)
  455. {
  456. HRESULT hr = S_OK;
  457. PACCESS_ALLOWED_ACE paaAllowedAce = NULL;
  458. PACCESS_DENIED_ACE paaDeniedAce = NULL;
  459. BOOL bAceMatch = FALSE;
  460. BYTE cAceFlags = 0;
  461. DWORD cbAcl = 0;
  462. DWORD cbAce = 0;
  463. if (!IsValidSid(const_cast<PSID>(psidUserOrGroup)))
  464. {
  465. return HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  466. }
  467. hr = GetAccessControlEntriesFromAcl();
  468. if (FAILED(hr))
  469. {
  470. return hr;
  471. }
  472. cbAcl = sizeof(ACL);
  473. for (ACEITER i = m_listAllAce.begin(); i != m_listAllAce.end() ; i++)
  474. {
  475. CAccessControlEntry paEntry(*i);
  476. // Assert(kamMask)
  477. switch (kamMask)
  478. {
  479. case KEY_CURRENT:
  480. {
  481. cAceFlags = 0; // Do not allow this to be inherited by children.
  482. break;
  483. }
  484. case KEY_CHILDREN:
  485. {
  486. cAceFlags = CONTAINER_INHERIT_ACE;
  487. cAceFlags |= INHERIT_ONLY_ACE;
  488. break;
  489. }
  490. case KEY_ALL:
  491. {
  492. cAceFlags = CONTAINER_INHERIT_ACE;
  493. break;
  494. }
  495. default:
  496. return E_INVALIDARG;
  497. }
  498. if (paEntry.HasExactRights(amPermissionsMask) && paEntry.HasExactInheritFlags(cAceFlags) && paEntry.IsEqualSid(psidUserOrGroup))
  499. {
  500. ACEITER j = i;
  501. i = m_listAllAce.erase(j);
  502. bAceMatch = TRUE;
  503. }
  504. else
  505. {
  506. cbAcl += sizeof(ACCESS_ALLOWED_ACE) + 8 +
  507. paEntry.GetLengthSid()- sizeof(DWORD);
  508. }
  509. }
  510. if (bAceMatch)
  511. {
  512. ACCESS_ALLOWED_ACE paEntry = {NULL};
  513. ACL_REVISION_INFORMATION AclRevisionInfo;
  514. PACL pNewDACL = NULL;
  515. // subtract ACE.SidStart from the size
  516. cbAce = sizeof (paEntry) - sizeof (DWORD);
  517. // add this ACE's SID length
  518. cbAce += 8 + GetLengthSid(const_cast<PSID>(psidUserOrGroup));
  519. // add the length of each ACE to the total ACL length
  520. cbAcl += cbAce;
  521. AclRevisionInfo.AclRevision = ACL_REVISION;
  522. hr = BuildAndApplyACLFromList(cbAcl, AclRevisionInfo);
  523. if (SUCCEEDED(hr))
  524. {
  525. hr = SetKeySecurity();
  526. }
  527. }
  528. else
  529. {
  530. hr = S_FALSE;
  531. }
  532. return hr;
  533. }
  534. //+---------------------------------------------------------------------------
  535. //
  536. // Function: GetAccessControlEntriesFromAcl
  537. //
  538. // Purpose: Retrieves all the ACE's from the ACL and stores them in an
  539. // STL list for easier manipulation.
  540. //
  541. // Arguments:
  542. //
  543. //
  544. //
  545. // Returns: An S_OK if the key was successfully opened, and error code
  546. // otherwise
  547. //
  548. // Author: ckotze 4 July 2000
  549. //
  550. // Notes:
  551. //
  552. HRESULT CRegKeySecurity::GetAccessControlEntriesFromAcl()
  553. {
  554. ACL_SIZE_INFORMATION asiAclSize;
  555. ACL_REVISION_INFORMATION ariAclRevision;
  556. DWORD dwBufLength;
  557. DWORD dwAcl;
  558. DWORD dwTotalEntries = 0;
  559. HRESULT hr = S_OK;
  560. PACCESS_ALLOWED_ACE paaAllowedAce = NULL;
  561. PACCESS_DENIED_ACE paaDeniedAce = NULL;
  562. ACCESS_MASK amAccessAllowedMask = 0;
  563. ACCESS_MASK amAccessDeniedMask = 0;
  564. if (!m_paclDacl)
  565. {
  566. hr = GetSecurityDescriptorDacl();
  567. if (FAILED(hr))
  568. {
  569. return hr;
  570. }
  571. }
  572. if (!IsValidAcl(m_paclDacl))
  573. {
  574. return HRESULT_FROM_WIN32(ERROR_INVALID_ACL);
  575. }
  576. dwBufLength = sizeof(asiAclSize);
  577. if (!GetAclInformation(m_paclDacl,
  578. &asiAclSize,
  579. dwBufLength,
  580. AclSizeInformation))
  581. {
  582. return(FALSE);
  583. }
  584. dwBufLength = sizeof(ariAclRevision);
  585. if (!GetAclInformation(m_paclDacl,
  586. &ariAclRevision,
  587. dwBufLength,
  588. AclRevisionInformation))
  589. {
  590. return(FALSE);
  591. }
  592. switch (ariAclRevision.AclRevision)
  593. {
  594. case ACL_REVISION1 :
  595. {
  596. break;
  597. }
  598. case ACL_REVISION2 :
  599. {
  600. break;
  601. }
  602. default :
  603. {
  604. return(FALSE);
  605. }
  606. }
  607. if (asiAclSize.AceCount <= 0)
  608. {
  609. return E_INVALIDARG;
  610. }
  611. m_listAllAce.clear();
  612. for (dwAcl = 0;dwAcl < asiAclSize.AceCount; dwAcl++)
  613. {
  614. if (!GetAce(m_paclDacl,
  615. dwAcl,
  616. reinterpret_cast<LPVOID *>(&paaAllowedAce)))
  617. {
  618. return HRESULT_FROM_WIN32(ERROR_INVALID_ACL);
  619. }
  620. if (paaAllowedAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  621. {
  622. CAccessControlEntry pEntry(*paaAllowedAce);
  623. m_listAllAce.insert(m_listAllAce.end(), pEntry);
  624. }
  625. else
  626. {
  627. CAccessControlEntry pEntry(*paaAllowedAce);
  628. m_listAllAce.insert(m_listAllAce.begin(), pEntry);
  629. }
  630. }
  631. return S_OK;
  632. }
  633. HRESULT CRegKeySecurity::BuildAndApplyACLFromList(DWORD cbAcl, ACL_REVISION_INFORMATION AclRevisionInfo)
  634. {
  635. HRESULT hr = S_OK;
  636. DWORD cbAce = 0;
  637. PACL pNewDACL = NULL;
  638. pNewDACL = reinterpret_cast<PACL>(new BYTE[cbAcl]);
  639. if (!pNewDACL)
  640. {
  641. return E_OUTOFMEMORY;
  642. }
  643. ZeroMemory(pNewDACL, cbAcl);
  644. if (InitializeAcl(pNewDACL, cbAcl, AclRevisionInfo.AclRevision))
  645. {
  646. for (ACEITER i = m_listAllAce.begin(); i != m_listAllAce.end(); i++)
  647. {
  648. CAccessControlEntry Ace = *i;
  649. if (IsValidAcl(pNewDACL))
  650. {
  651. hr = Ace.AddToACL(&pNewDACL, AclRevisionInfo);
  652. if (FAILED(hr))
  653. {
  654. break;
  655. }
  656. }
  657. else
  658. {
  659. hr = HRESULT_FROM_WIN32(ERROR_INVALID_ACL);
  660. break;
  661. }
  662. }
  663. if (SUCCEEDED(hr))
  664. {
  665. hr = SetSecurityDescriptorDacl(pNewDACL, m_listAllAce.size());
  666. }
  667. delete[] pNewDACL;
  668. }
  669. return hr;
  670. }
  671. //+---------------------------------------------------------------------------
  672. //
  673. // Function: CAccessControlEntry constructor
  674. //
  675. // Purpose:
  676. //
  677. //
  678. // Arguments:
  679. //
  680. //
  681. //
  682. //
  683. // Returns: An S_OK if the key was successfully opened, and error code
  684. // otherwise
  685. //
  686. // Author: ckotze 4 July 2000
  687. //
  688. // Notes:
  689. //
  690. CAccessControlEntry::CAccessControlEntry()
  691. {
  692. }
  693. //+---------------------------------------------------------------------------
  694. //
  695. // Function: CAccessControlEntry copy constructor
  696. //
  697. // Purpose: To contruct a new CAccessControEntry based on the supplied
  698. // Access Control Entry for storage in an STL list.
  699. //
  700. // Arguments:
  701. // aaAllowed - An ACCESS_ALLOWED_ACE or ACCESS_DENIED_ACE
  702. //
  703. //
  704. // Returns: An S_OK if the key was successfully opened, and error code
  705. // otherwise
  706. //
  707. // Author: ckotze 4 July 2000
  708. //
  709. // Notes: Since STL doesn't know how to work with Sids we get the string
  710. // representation of the sid and then store that inside the list.
  711. //
  712. CAccessControlEntry::CAccessControlEntry(const ACCESS_ALLOWED_ACE& aaAllowed)
  713. {
  714. m_cAceType = aaAllowed.Header.AceType;
  715. m_amMask = aaAllowed.Mask;
  716. m_cAceFlags = aaAllowed.Header.AceFlags;
  717. CNCUtility::SidToString(&aaAllowed.SidStart, m_strSid);
  718. m_dwLengthSid = ::GetLengthSid(reinterpret_cast<PSID>(const_cast<LPDWORD>(&aaAllowed.SidStart)));
  719. }
  720. //+---------------------------------------------------------------------------
  721. //
  722. // Function: CAccessControlEntry copy constructor
  723. //
  724. // Purpose: To contruct a new CAccessControEntry based on the supplied
  725. // Access Control Entry fields for storage in an STL list.
  726. //
  727. //
  728. // Arguments:
  729. // AceType - The type of ACE (allowed or denied or audit etc)
  730. //
  731. // amMask - Permissions Mask
  732. //
  733. // AceFlags - AceFlags
  734. //
  735. // psidUserOrGroup - The User or Group we're interested in
  736. //
  737. //
  738. //
  739. // Returns: An S_OK if the key was successfully opened, and error code
  740. // otherwise
  741. //
  742. // Author: ckotze 4 July 2000
  743. //
  744. // Notes: Since STL doesn't know how to work with Sids we get the string
  745. // representation of the sid and then store that inside the list.
  746. //
  747. CAccessControlEntry::CAccessControlEntry(const BYTE AceType, const ACCESS_MASK amMask, const BYTE AceFlags, PCSID psidUserOrGroup)
  748. {
  749. m_cAceType = AceType;
  750. m_amMask = amMask;
  751. m_cAceFlags = AceFlags;
  752. CNCUtility::SidToString(psidUserOrGroup, m_strSid);
  753. m_dwLengthSid = ::GetLengthSid(const_cast<PSID>(psidUserOrGroup));
  754. }
  755. //+---------------------------------------------------------------------------
  756. //
  757. // Function: CAccessControlEntry destructor
  758. //
  759. // Purpose:
  760. //
  761. //
  762. // Arguments:
  763. //
  764. //
  765. //
  766. // Returns: An S_OK if the key was successfully opened, and error code
  767. // otherwise
  768. //
  769. // Author: ckotze 4 July 2000
  770. //
  771. // Notes:
  772. //
  773. CAccessControlEntry::~CAccessControlEntry()
  774. {
  775. }
  776. //+---------------------------------------------------------------------------
  777. //
  778. // Function: AddToACL
  779. //
  780. // Purpose: Adds this current AccessControlEntry to the specified ACL
  781. //
  782. //
  783. // Arguments:
  784. // pAcl - Access Control List to Add to
  785. //
  786. // AclRevisionInfo - Version of ACL
  787. //
  788. // Returns: An S_OK if the key was successfully opened, and error code
  789. // otherwise
  790. //
  791. // Author: ckotze 4 July 2000
  792. //
  793. // Notes:
  794. //
  795. HRESULT CAccessControlEntry::AddToACL(PACL* pAcl, ACL_REVISION_INFORMATION AclRevisionInfo)
  796. {
  797. HRESULT hr;
  798. PSID pSid = NULL;
  799. hr = CNCUtility::StringToSid(m_strSid, pSid);
  800. if (FAILED(hr))
  801. {
  802. return hr;
  803. }
  804. if (m_cAceType == ACCESS_ALLOWED_ACE_TYPE)
  805. {
  806. if (!::AddAccessAllowedAceEx(*pAcl, AclRevisionInfo.AclRevision, m_cAceFlags, m_amMask, pSid))
  807. {
  808. DWORD dwErr;
  809. dwErr = GetLastError();
  810. hr = HRESULT_FROM_WIN32(dwErr);
  811. }
  812. }
  813. else
  814. {
  815. if (!::AddAccessDeniedAceEx(*pAcl, AclRevisionInfo.AclRevision, m_cAceFlags, m_amMask, pSid))
  816. {
  817. DWORD dwErr;
  818. dwErr = GetLastError();
  819. hr = HRESULT_FROM_WIN32(dwErr);
  820. }
  821. }
  822. if (pSid)
  823. {
  824. FreeSid(pSid);
  825. }
  826. return S_OK;
  827. }
  828. //+---------------------------------------------------------------------------
  829. //
  830. // Function: HasExactRights
  831. //
  832. // Purpose: Checks to see if this ACE has the exact same rights that we
  833. // are looking for
  834. //
  835. //
  836. // Arguments:
  837. // amRightsRequired - The AccessMask in question
  838. //
  839. //
  840. // Returns: An S_OK if the key was successfully opened, and error code
  841. // otherwise
  842. //
  843. // Author: ckotze 4 July 2000
  844. //
  845. // Notes:
  846. //
  847. BOOL CAccessControlEntry::HasExactRights(ACCESS_MASK amRightsRequired) const
  848. {
  849. return (amRightsRequired == m_amMask);
  850. }
  851. //+---------------------------------------------------------------------------
  852. //
  853. // Function: GetLengthSid
  854. //
  855. // Purpose: returns the length of the sid in this AccessControlEntry
  856. //
  857. // Arguments:
  858. //
  859. //
  860. //
  861. //
  862. // Returns: An S_OK if the key was successfully opened, and error code
  863. // otherwise
  864. //
  865. // Author: ckotze 4 July 2000
  866. //
  867. // Notes:
  868. //
  869. DWORD CAccessControlEntry::GetLengthSid() const
  870. {
  871. return m_dwLengthSid;
  872. }
  873. //+---------------------------------------------------------------------------
  874. //
  875. // Function: HasExactRights
  876. //
  877. // Purpose: Checks to see if this ACE has the exact same inherit flags
  878. // that we are looking for
  879. //
  880. //
  881. // Arguments:
  882. // amRightsRequired - The AccessMask in question
  883. //
  884. //
  885. // Returns: An S_OK if the key was successfully opened, and error code
  886. // otherwise
  887. //
  888. // Author: ckotze 4 July 2000
  889. //
  890. // Notes:
  891. //
  892. BOOL CAccessControlEntry::HasExactInheritFlags(BYTE AceFlags)
  893. {
  894. return (m_cAceFlags == AceFlags);
  895. }
  896. //+---------------------------------------------------------------------------
  897. //
  898. // Function: IsEqualSid
  899. //
  900. // Purpose: Is this the same Sid as the one we're looking for?
  901. //
  902. //
  903. // Arguments:
  904. // psidUserOrGroup - Sid in question
  905. //
  906. //
  907. //
  908. // Returns: An S_OK if the key was successfully opened, and error code
  909. // otherwise
  910. //
  911. // Author: ckotze 4 July 2000
  912. //
  913. // Notes:
  914. //
  915. BOOL CAccessControlEntry::IsEqualSid(PCSID psidUserOrGroup) const
  916. {
  917. HRESULT hr;
  918. BOOL bEqualSid = FALSE;
  919. PSID pSid = NULL;
  920. hr = CNCUtility::StringToSid(m_strSid, pSid);
  921. if (SUCCEEDED(hr))
  922. {
  923. bEqualSid = ::EqualSid(pSid, const_cast<PSID>(psidUserOrGroup));
  924. }
  925. if (pSid)
  926. {
  927. FreeSid(pSid);
  928. }
  929. return bEqualSid;
  930. }