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.

1080 lines
22 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cAccessControlList.cxx
  7. //
  8. // Contents: AccessControlList object
  9. //
  10. // History: 11-1-95 krishnag Created.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "oleds.hxx"
  14. #pragma hdrstop
  15. // Class CAccessControlList
  16. DEFINE_IDispatch_Implementation(CAccessControlList)
  17. CAccessControlList::CAccessControlList():
  18. _pDispMgr(NULL),
  19. _dwAclRevision(0),
  20. _dwAceCount(0),
  21. _pAccessControlEntry(NULL),
  22. _pCurrentEntry(NULL),
  23. _pACLEnums(NULL)
  24. {
  25. ENLIST_TRACKING(CAccessControlList);
  26. }
  27. HRESULT
  28. CAccessControlList::CreateAccessControlList(
  29. REFIID riid,
  30. void **ppvObj
  31. )
  32. {
  33. CAccessControlList FAR * pAccessControlList = NULL;
  34. HRESULT hr = S_OK;
  35. hr = AllocateAccessControlListObject(&pAccessControlList);
  36. BAIL_ON_FAILURE(hr);
  37. hr = pAccessControlList->QueryInterface(riid, ppvObj);
  38. BAIL_ON_FAILURE(hr);
  39. pAccessControlList->Release();
  40. RRETURN(hr);
  41. error:
  42. delete pAccessControlList;
  43. RRETURN_EXP_IF_ERR(hr);
  44. }
  45. CAccessControlList::~CAccessControlList( )
  46. {
  47. PACCESS_CONTROL_ENTRY pTemp = NULL;
  48. PACCESS_CONTROL_ENTRY pNext = NULL;
  49. PACL_ENUM_ENTRY pACL = _pACLEnums;
  50. delete _pDispMgr;
  51. pTemp = _pAccessControlEntry;
  52. while (pTemp) {
  53. pNext = pTemp->pNext;
  54. if (pTemp->pAccessControlEntry) {
  55. (pTemp->pAccessControlEntry)->Release();
  56. }
  57. FreeADsMem(pTemp);
  58. pTemp = pNext;
  59. }
  60. //
  61. // since each enumerator hold ref count on this ACL, this destructor should
  62. // never be called unless all of its enumerators' destructors have been
  63. // invoked. In the enumerator's destructor, RemoveEnumerator is called
  64. // first before release ref count on this. Thus, by the time, at this
  65. // point, pACL should be empty.
  66. //
  67. ADsAssert(!pACL);
  68. //
  69. // just in case we have bug in codes, e.g enumerators not all destroyed
  70. // before dll detachement. don't want to leak here anyway
  71. //
  72. while (pACL) {
  73. _pACLEnums = pACL->pNext;
  74. //
  75. // free the entry but do not destroy the enumerator since clients
  76. // should release all interface ptrs to enumerator for destruction.
  77. //
  78. FreeADsMem(pACL);
  79. pACL = _pACLEnums;
  80. }
  81. }
  82. STDMETHODIMP
  83. CAccessControlList::QueryInterface(
  84. REFIID iid,
  85. LPVOID FAR* ppv
  86. )
  87. {
  88. if (IsEqualIID(iid, IID_IUnknown))
  89. {
  90. *ppv = (IADsAccessControlList FAR *) this;
  91. }
  92. else if (IsEqualIID(iid, IID_IADsAccessControlList))
  93. {
  94. *ppv = (IADsAccessControlList FAR *) this;
  95. }
  96. else if (IsEqualIID(iid, IID_IDispatch))
  97. {
  98. *ppv = (IADsAccessControlList FAR *) this;
  99. }
  100. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  101. {
  102. *ppv = (ISupportErrorInfo FAR *) this;
  103. }
  104. else if (IsEqualIID(iid, IID_IEnumVARIANT))
  105. {
  106. *ppv = (IEnumVARIANT FAR *) this;
  107. }
  108. else
  109. {
  110. *ppv = NULL;
  111. return E_NOINTERFACE;
  112. }
  113. AddRef();
  114. return NOERROR;
  115. }
  116. HRESULT
  117. CAccessControlList::AllocateAccessControlListObject(
  118. CAccessControlList ** ppAccessControlList
  119. )
  120. {
  121. CAccessControlList FAR * pAccessControlList = NULL;
  122. CDispatchMgr FAR * pDispMgr = NULL;
  123. HRESULT hr = S_OK;
  124. pAccessControlList = new CAccessControlList();
  125. if (pAccessControlList == NULL) {
  126. hr = E_OUTOFMEMORY;
  127. }
  128. BAIL_ON_FAILURE(hr);
  129. pDispMgr = new CDispatchMgr;
  130. if (pDispMgr == NULL) {
  131. hr = E_OUTOFMEMORY;
  132. }
  133. BAIL_ON_FAILURE(hr);
  134. hr = LoadTypeInfoEntry(
  135. pDispMgr,
  136. LIBID_ADs,
  137. IID_IADsAccessControlList,
  138. (IADsAccessControlList *)pAccessControlList,
  139. DISPID_NEWENUM
  140. );
  141. BAIL_ON_FAILURE(hr);
  142. pAccessControlList->_pDispMgr = pDispMgr;
  143. *ppAccessControlList = pAccessControlList;
  144. RRETURN(hr);
  145. error:
  146. delete pDispMgr;
  147. RRETURN_EXP_IF_ERR(hr);
  148. }
  149. //
  150. // ISupportErrorInfo method
  151. //
  152. STDMETHODIMP
  153. CAccessControlList::InterfaceSupportsErrorInfo(THIS_ REFIID riid)
  154. {
  155. if (IsEqualIID(riid, IID_IADsAccessControlList) ||
  156. IsEqualIID(riid, IID_IEnumVARIANT)) {
  157. return S_OK;
  158. } else {
  159. return S_FALSE;
  160. }
  161. }
  162. STDMETHODIMP
  163. CAccessControlList::CopyAccessList(
  164. THIS_ IDispatch FAR * FAR * ppAccessControlList
  165. )
  166. {
  167. HRESULT hr = S_OK;
  168. DWORD dwAceCount = 0;
  169. DWORD dwNewAceCount = 0;
  170. DWORD dwAclRevision = 0;
  171. DWORD i = 0;
  172. VARIANT varAce;
  173. IADsAccessControlEntry * pSourceAce = NULL;
  174. IADsAccessControlEntry * pTargetAce = NULL;
  175. IDispatch * pTargDisp = NULL;
  176. DWORD cElementFetched = 0;
  177. IADsAccessControlList * pAccessControlList = NULL;
  178. hr = CoCreateInstance(
  179. CLSID_AccessControlList,
  180. NULL,
  181. CLSCTX_INPROC_SERVER,
  182. IID_IADsAccessControlList,
  183. (void **)&pAccessControlList
  184. );
  185. BAIL_ON_FAILURE(hr);
  186. dwAceCount = _dwAceCount;
  187. dwAclRevision = _dwAclRevision;
  188. //
  189. // Reset the enumerator
  190. //
  191. _pCurrentEntry = _pAccessControlEntry;
  192. for (i = 0; i < dwAceCount; i++) {
  193. VariantInit(&varAce);
  194. hr = Next(1, &varAce, &cElementFetched);
  195. CONTINUE_ON_FAILURE(hr);
  196. hr = (V_DISPATCH(&varAce))->QueryInterface(
  197. IID_IADsAccessControlEntry,
  198. (void **)&pSourceAce
  199. );
  200. CONTINUE_ON_FAILURE(hr);
  201. hr = CopyAccessControlEntry(
  202. pSourceAce,
  203. &pTargetAce
  204. );
  205. BAIL_ON_FAILURE(hr);
  206. hr = pTargetAce->QueryInterface(
  207. IID_IDispatch,
  208. (void **)&pTargDisp
  209. );
  210. BAIL_ON_FAILURE(hr);
  211. hr = pAccessControlList->AddAce(pTargDisp);
  212. BAIL_ON_FAILURE(hr);
  213. dwNewAceCount++;
  214. if (pTargDisp) {
  215. pTargDisp->Release();
  216. pTargDisp = NULL;
  217. }
  218. if (pTargetAce) {
  219. pTargetAce->Release();
  220. pTargetAce = NULL;
  221. }
  222. if (pSourceAce) {
  223. pSourceAce->Release();
  224. pSourceAce = NULL;
  225. }
  226. VariantClear(&varAce);
  227. }
  228. hr= pAccessControlList->put_AceCount(dwNewAceCount);
  229. BAIL_ON_FAILURE(hr);
  230. hr = pAccessControlList->put_AclRevision((long)dwAclRevision);
  231. BAIL_ON_FAILURE(hr);
  232. *ppAccessControlList = pAccessControlList;
  233. error:
  234. RRETURN_EXP_IF_ERR(hr);
  235. }
  236. STDMETHODIMP
  237. CAccessControlList::AddAce(
  238. THIS_ IDispatch FAR * pAccessControlEntry
  239. )
  240. {
  241. HRESULT hr = S_OK;
  242. PACCESS_CONTROL_ENTRY pAccessEntry = NULL;
  243. PACCESS_CONTROL_ENTRY pTemp = NULL;
  244. IADsAccessControlEntry * pAce = NULL;
  245. hr = pAccessControlEntry->QueryInterface(
  246. IID_IADsAccessControlEntry,
  247. (void **)&pAce
  248. );
  249. BAIL_ON_FAILURE(hr);
  250. pAccessEntry = (PACCESS_CONTROL_ENTRY)AllocADsMem(
  251. sizeof(ACCESS_CONTROL_ENTRY)
  252. );
  253. if (!pAccessEntry) {
  254. pAce->Release();
  255. RRETURN(E_OUTOFMEMORY);
  256. }
  257. pAccessEntry->pAccessControlEntry = pAce;
  258. //
  259. // - Now append this ace to the very end.
  260. // - Since ACE is added to the end, no need to call
  261. // AdjustCurPtrOfEnumerators().
  262. //
  263. if (!_pAccessControlEntry) {
  264. _pAccessControlEntry = pAccessEntry;
  265. }else {
  266. pTemp = _pAccessControlEntry;
  267. while (pTemp->pNext) {
  268. pTemp = pTemp->pNext;
  269. }
  270. pTemp->pNext = pAccessEntry;
  271. }
  272. //
  273. // Now up the ace count
  274. //
  275. _dwAceCount++;
  276. error:
  277. RRETURN_EXP_IF_ERR(hr);
  278. }
  279. STDMETHODIMP
  280. CAccessControlList::RemoveAce(
  281. THIS_ IDispatch FAR * pAccessControlEntry
  282. )
  283. {
  284. HRESULT hr = S_OK;
  285. PACCESS_CONTROL_ENTRY pTemp = NULL;
  286. IADsAccessControlEntry * pAce = NULL;
  287. PACCESS_CONTROL_ENTRY pAccessEntry = NULL;
  288. DWORD dwRemovePos = 1; // one-based indexing since enumerator was
  289. // written that way
  290. if (!_pAccessControlEntry) {
  291. RRETURN(E_FAIL);
  292. }
  293. hr = pAccessControlEntry->QueryInterface(
  294. IID_IADsAccessControlEntry,
  295. (void **)&pAce
  296. );
  297. BAIL_ON_FAILURE(hr);
  298. pAccessEntry = _pAccessControlEntry;
  299. //
  300. // It is the first entry
  301. //
  302. if (EquivalentAces(pAccessEntry->pAccessControlEntry, pAce)) {
  303. //
  304. // Check if we have an enumerator pointed to us
  305. //
  306. if (pAccessEntry == _pCurrentEntry) {
  307. _pCurrentEntry = pAccessEntry->pNext;
  308. }
  309. _pAccessControlEntry = pAccessEntry->pNext;
  310. (pAccessEntry->pAccessControlEntry)->Release();
  311. FreeADsMem(pAccessEntry);
  312. if (pAce) {
  313. pAce->Release();
  314. }
  315. //
  316. // Decrement the Ace count
  317. //
  318. _dwAceCount--;
  319. //
  320. // Adjust "current" ptr of all enumerators if necessary
  321. //
  322. AdjustCurPtrOfEnumerators(dwRemovePos, FALSE);
  323. RRETURN(S_OK);
  324. }
  325. while (pAccessEntry->pNext) {
  326. pTemp = pAccessEntry->pNext;
  327. dwRemovePos++;
  328. if (EquivalentAces(pTemp->pAccessControlEntry, pAce)){
  329. //
  330. // Check if we have an enumerator pointed to us
  331. //
  332. if (pAccessEntry == _pCurrentEntry) {
  333. _pCurrentEntry = pAccessEntry->pNext;
  334. }
  335. pAccessEntry->pNext = pTemp->pNext;
  336. (pTemp->pAccessControlEntry)->Release();
  337. FreeADsMem(pTemp);
  338. if (pAce) {
  339. pAce->Release();
  340. }
  341. //
  342. // Decrement the Ace count
  343. //
  344. _dwAceCount--;
  345. //
  346. // Adjust "current" ptr of all enumerators if necessary
  347. //
  348. AdjustCurPtrOfEnumerators(dwRemovePos, FALSE);
  349. RRETURN(S_OK);
  350. }
  351. pAccessEntry = pAccessEntry->pNext;
  352. }
  353. if (pAce) {
  354. pAce->Release();
  355. }
  356. error:
  357. RRETURN_EXP_IF_ERR(E_FAIL);
  358. }
  359. STDMETHODIMP
  360. CAccessControlList::get_AclRevision(THIS_ long FAR * retval)
  361. {
  362. *retval = _dwAclRevision;
  363. RRETURN(S_OK);
  364. }
  365. STDMETHODIMP
  366. CAccessControlList::put_AclRevision(THIS_ long lnAclRevision)
  367. {
  368. _dwAclRevision = lnAclRevision;
  369. RRETURN(S_OK);
  370. }
  371. STDMETHODIMP
  372. CAccessControlList::get_AceCount(THIS_ long FAR * retval)
  373. {
  374. *retval = _dwAceCount;
  375. RRETURN(S_OK);
  376. }
  377. STDMETHODIMP
  378. CAccessControlList::put_AceCount(THIS_ long lnAceCount)
  379. {
  380. _dwAceCount = lnAceCount;
  381. RRETURN(S_OK);
  382. }
  383. STDMETHODIMP
  384. CAccessControlList::Next(ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched)
  385. {
  386. DWORD i = 0;
  387. DWORD j = 0;
  388. IDispatch * pDispatch = NULL;
  389. IADsAccessControlEntry * pAccessControlEntry = NULL;
  390. PACCESS_CONTROL_ENTRY pTemp = NULL;
  391. PVARIANT pThisVar;
  392. HRESULT hr = S_OK;
  393. pTemp = _pCurrentEntry;
  394. if (!pTemp) {
  395. if (pcElementFetched) {
  396. *pcElementFetched = 0;
  397. }
  398. RRETURN(S_FALSE);
  399. }
  400. while (pTemp && (j < cElements)){
  401. pThisVar = pvar + j;
  402. VariantInit(pThisVar);
  403. pAccessControlEntry = pTemp->pAccessControlEntry;
  404. hr = pAccessControlEntry->QueryInterface(
  405. IID_IDispatch,
  406. (void **)&pDispatch
  407. );
  408. V_DISPATCH(pThisVar) = pDispatch;
  409. V_VT(pThisVar) = VT_DISPATCH;
  410. pTemp = pTemp->pNext;
  411. j++;
  412. }
  413. if (pcElementFetched) {
  414. *pcElementFetched = j;
  415. }
  416. //
  417. // Advance _pCurrentEntry
  418. //
  419. _pCurrentEntry = pTemp;
  420. if (j < cElements) {
  421. RRETURN (S_FALSE);
  422. }
  423. RRETURN(S_OK);
  424. }
  425. //+---------------------------------------------------------------------------
  426. //
  427. // Function: CAccessControlList::GetElement
  428. //
  429. // Synopsis: Get the dwPos'th ACE in the ACL. Note that no
  430. // refCount is added to the ACE, it is the responsibility
  431. // of the caller to handle that.
  432. //
  433. // Arguments: [dwPos] the ACE required
  434. // [pAce] Pointer to ACE returned in this param.
  435. //
  436. // Returns: HRESULT
  437. //
  438. // Modifies: [pAce]
  439. //
  440. //----------------------------------------------------------------------------
  441. HRESULT
  442. CAccessControlList::GetElement(
  443. DWORD dwPos,
  444. IADsAccessControlEntry ** pAce
  445. )
  446. {
  447. HRESULT hr = S_OK;
  448. DWORD j = 1;
  449. PACCESS_CONTROL_ENTRY pTemp = NULL;
  450. *pAce = NULL;
  451. // set to the acl head
  452. pTemp = _pAccessControlEntry;
  453. if (_dwAceCount < dwPos) {
  454. BAIL_ON_FAILURE(hr = E_FAIL);
  455. }
  456. while (pTemp && (j < dwPos)) {
  457. pTemp = pTemp->pNext;
  458. j++;
  459. }
  460. if (!pTemp || pTemp == NULL) {
  461. BAIL_ON_FAILURE(hr = E_FAIL);
  462. }
  463. // we should have the correct ACE here
  464. *pAce = pTemp->pAccessControlEntry;
  465. error:
  466. if (FAILED(hr)) {
  467. hr = S_FALSE;
  468. }
  469. RRETURN(hr);
  470. }
  471. STDMETHODIMP
  472. CAccessControlList::get__NewEnum(THIS_ IUnknown * FAR* retval)
  473. {
  474. HRESULT hr = S_OK;
  475. IEnumVARIANT * penum = NULL;
  476. *retval = NULL;
  477. hr = CAccCtrlListEnum::CreateAclEnum(
  478. (CAccCtrlListEnum **)&penum,
  479. this
  480. );
  481. BAIL_ON_FAILURE(hr);
  482. hr = penum->QueryInterface(
  483. IID_IUnknown,
  484. (VOID FAR* FAR*)retval
  485. );
  486. BAIL_ON_FAILURE(hr);
  487. if (penum) {
  488. penum->Release();
  489. }
  490. //
  491. // keep a linked list of all enumerators that enumerate on this ACL
  492. // But don't hold on to inteface ptr of enumerators; otherwise, cycle
  493. // reference count. Do this only after above succeed.
  494. //
  495. hr = AddEnumerator(
  496. (CAccCtrlListEnum *)penum
  497. );
  498. BAIL_ON_FAILURE(hr);
  499. error:
  500. if (FAILED(hr) && penum) {
  501. delete penum;
  502. }
  503. RRETURN_EXP_IF_ERR(hr);
  504. }
  505. HRESULT
  506. CAccessControlList::
  507. AddEnumerator(
  508. CAccCtrlListEnum *pACLEnum
  509. )
  510. {
  511. PACL_ENUM_ENTRY pNewACLEnum = NULL;
  512. //
  513. // don't want add NULL enumerator as an entry to add complication everywhere
  514. //
  515. ADsAssert(pACLEnum);
  516. pNewACLEnum = (PACL_ENUM_ENTRY) AllocADsMem(sizeof(ACL_ENUM_ENTRY));
  517. if (!pNewACLEnum)
  518. RRETURN(E_OUTOFMEMORY);
  519. //
  520. // We are only adding a ptr to the enumerator.
  521. // Don't hold on to inteface ptr. Otherwise, this has ref count on
  522. // enumerator has ref count on this. Cycle reference count.
  523. //
  524. pNewACLEnum->pACLEnum = pACLEnum;
  525. pNewACLEnum->pNext = _pACLEnums;
  526. _pACLEnums = pNewACLEnum;
  527. RRETURN(S_OK);
  528. }
  529. HRESULT
  530. CAccessControlList::
  531. RemoveEnumerator(
  532. CAccCtrlListEnum *pACLEnum
  533. )
  534. {
  535. PACL_ENUM_ENTRY pCurACLEnum = _pACLEnums;
  536. PACL_ENUM_ENTRY pPrevACLEnum = NULL;
  537. //
  538. // can't think of a case needing to remove a pACLEnum which may be
  539. // NULL now. Don't want to add complication. Probably coding error.
  540. //
  541. ADsAssert(pACLEnum);
  542. //
  543. // optional, but we really shouldn't call this if _pACLEnums is NULL
  544. //
  545. ADsAssert(_pACLEnums);
  546. //
  547. // check the first enumerator
  548. //
  549. if (pCurACLEnum) {
  550. //
  551. // match what we want to remove
  552. //
  553. if (pCurACLEnum->pACLEnum == pACLEnum) {
  554. //
  555. // remove the enumerator from our list but don't destroy
  556. // the enumerator
  557. //
  558. _pACLEnums = pCurACLEnum->pNext;
  559. FreeADsMem(pCurACLEnum);
  560. RRETURN(S_OK);
  561. }
  562. } else {
  563. RRETURN(E_FAIL);
  564. }
  565. //
  566. // start checking from the second element, if any, of the list
  567. //
  568. pPrevACLEnum = pCurACLEnum;
  569. pCurACLEnum = pCurACLEnum->pNext;
  570. while (pCurACLEnum && (pCurACLEnum->pACLEnum!=pACLEnum)) {
  571. pPrevACLEnum = pCurACLEnum;
  572. pCurACLEnum = pCurACLEnum->pNext;
  573. }
  574. if (pCurACLEnum) {
  575. //
  576. // match found
  577. //
  578. pPrevACLEnum->pNext = pCurACLEnum->pNext;
  579. FreeADsMem(pCurACLEnum);
  580. RRETURN(S_OK);
  581. } else {
  582. RRETURN(E_FAIL);
  583. }
  584. }
  585. BOOL
  586. EquivalentStrings(
  587. BSTR bstrSrcString,
  588. BSTR bstrDestString
  589. )
  590. {
  591. if (!bstrSrcString && !bstrDestString) {
  592. return(TRUE);
  593. }
  594. if (!bstrSrcString && bstrDestString) {
  595. return(FALSE);
  596. }
  597. if (!bstrDestString && bstrSrcString) {
  598. return(FALSE);
  599. }
  600. #ifdef WIN95
  601. if (!_wcsicmp(bstrSrcString, bstrDestString)) {
  602. #else
  603. if (CompareStringW(
  604. LOCALE_SYSTEM_DEFAULT,
  605. NORM_IGNORECASE,
  606. bstrSrcString,
  607. -1,
  608. bstrDestString,
  609. -1
  610. )
  611. == CSTR_EQUAL) {
  612. #endif
  613. return(TRUE);
  614. }
  615. return(FALSE);
  616. }
  617. BOOL
  618. EquivalentAces(
  619. IADsAccessControlEntry * pSourceAce,
  620. IADsAccessControlEntry * pDestAce
  621. )
  622. {
  623. HRESULT hr = S_OK;
  624. BSTR bstrSrcTrustee = NULL;
  625. BSTR bstrDestTrustee = NULL;
  626. DWORD dwSrcMask = 0;
  627. DWORD dwDestMask = 0;
  628. DWORD dwSrcAceFlags = 0;
  629. DWORD dwDestAceFlags = 0;
  630. DWORD dwSrcAceType = 0;
  631. DWORD dwDestAceType = 0;
  632. DWORD dwSrcFlags = 0;
  633. DWORD dwDestFlags = 0;
  634. BSTR bstrSrcObjectType = NULL;
  635. BSTR bstrDestObjectType = NULL;
  636. BSTR bstrSrcInherObjType = NULL;
  637. BSTR bstrDestInherObjType = NULL;
  638. BOOL dwRet = FALSE;
  639. hr = pSourceAce->get_Trustee(&bstrSrcTrustee);
  640. BAIL_ON_FAILURE(hr);
  641. hr = pDestAce->get_Trustee(&bstrDestTrustee);
  642. BAIL_ON_FAILURE(hr);
  643. if (!EquivalentStrings(bstrSrcTrustee, bstrDestTrustee)) {
  644. hr = E_FAIL;
  645. BAIL_ON_FAILURE(hr);
  646. }
  647. hr = pSourceAce->get_AccessMask((long *)&dwSrcMask);
  648. BAIL_ON_FAILURE(hr);
  649. hr = pDestAce->get_AccessMask((long *)&dwDestMask);
  650. BAIL_ON_FAILURE(hr);
  651. if (dwSrcMask != dwDestMask) {
  652. hr = E_FAIL;
  653. BAIL_ON_FAILURE(hr);
  654. }
  655. hr = pSourceAce->get_AceFlags((long *)&dwSrcAceFlags);
  656. BAIL_ON_FAILURE(hr);
  657. hr = pDestAce->get_AceFlags((long *)&dwDestAceFlags);
  658. BAIL_ON_FAILURE(hr);
  659. if (dwSrcAceFlags != dwDestAceFlags) {
  660. hr = E_FAIL;
  661. BAIL_ON_FAILURE(hr);
  662. }
  663. hr = pSourceAce->get_AceType((long *)&dwSrcAceType);
  664. BAIL_ON_FAILURE(hr);
  665. hr = pDestAce->get_AceType((long *)&dwDestAceType);
  666. BAIL_ON_FAILURE(hr);
  667. if (dwSrcAceType != dwDestAceType) {
  668. hr = E_FAIL;
  669. BAIL_ON_FAILURE(hr);
  670. }
  671. hr = pSourceAce->get_Flags((long *)&dwSrcFlags);
  672. BAIL_ON_FAILURE(hr);
  673. hr = pDestAce->get_Flags((long *)&dwDestFlags);
  674. BAIL_ON_FAILURE(hr);
  675. if (dwSrcFlags != dwDestFlags) {
  676. hr = E_FAIL;
  677. BAIL_ON_FAILURE(hr);
  678. }
  679. hr = pSourceAce->get_ObjectType(&bstrSrcObjectType);
  680. BAIL_ON_FAILURE(hr);
  681. hr = pDestAce->get_ObjectType(&bstrDestObjectType);
  682. BAIL_ON_FAILURE(hr);
  683. if (!EquivalentStrings(bstrSrcObjectType, bstrDestObjectType)) {
  684. hr = E_FAIL;
  685. BAIL_ON_FAILURE(hr);
  686. }
  687. hr = pSourceAce->get_InheritedObjectType(&bstrSrcInherObjType);
  688. BAIL_ON_FAILURE(hr);
  689. hr = pDestAce->get_InheritedObjectType(&bstrDestInherObjType);
  690. BAIL_ON_FAILURE(hr);
  691. if (!EquivalentStrings(bstrSrcInherObjType, bstrDestInherObjType)) {
  692. hr = E_FAIL;
  693. BAIL_ON_FAILURE(hr);
  694. }
  695. dwRet = TRUE;
  696. cleanup:
  697. if (bstrSrcTrustee) {
  698. ADsFreeString(bstrSrcTrustee);
  699. }
  700. if (bstrDestTrustee) {
  701. ADsFreeString(bstrDestTrustee);
  702. }
  703. if (bstrSrcObjectType) {
  704. ADsFreeString(bstrSrcObjectType);
  705. }
  706. if (bstrDestObjectType) {
  707. ADsFreeString(bstrDestObjectType);
  708. }
  709. if (bstrSrcInherObjType) {
  710. ADsFreeString(bstrSrcInherObjType);
  711. }
  712. if (bstrDestInherObjType) {
  713. ADsFreeString(bstrDestInherObjType);
  714. }
  715. return(dwRet);
  716. error:
  717. dwRet = FALSE;
  718. goto cleanup;
  719. }
  720. void
  721. CAccessControlList::
  722. AdjustCurPtrOfEnumerators(
  723. DWORD dwPosNewOrDeletedACE,
  724. BOOL fACEAdded
  725. )
  726. {
  727. PACL_ENUM_ENTRY pACLEnum = _pACLEnums;
  728. CAccCtrlListEnum * pEnum = NULL;
  729. BOOL fOk = FALSE;
  730. if (fACEAdded) {
  731. while (pACLEnum) {
  732. pEnum = pACLEnum->pACLEnum;
  733. ADsAssert(pEnum);
  734. //
  735. // NOTE: - Problem may occur in multithreaded model (manipulation
  736. // on the enumerator & the actual ACL in two threads).
  737. // - ADSI CLIENTS should use critical section protection, as
  738. // with property cache.
  739. //
  740. if (dwPosNewOrDeletedACE <= pEnum->GetCurElement()) {
  741. //
  742. // the new ACE is added in front of the last ACE enumerated
  743. // so, increment the position of the last enumerated element
  744. // by one
  745. fOk = pEnum->IncrementCurElement();
  746. ADsAssert(fOk); // should be within bound after increment;
  747. // otherwise, coding error
  748. }
  749. // else {
  750. //
  751. // the new ACE is added after the last ACE enumerated, so
  752. // no effect on the position of the last enumerated element
  753. //
  754. // }
  755. pACLEnum=pACLEnum->pNext;
  756. }
  757. } else { // ACE deleted
  758. while (pACLEnum) {
  759. pEnum = pACLEnum->pACLEnum;
  760. ADsAssert(pEnum);
  761. //
  762. // NOTE: - Problem may occur in multithreaded model (manipulation
  763. // on the enumerator & the actual ACL in two threads).
  764. // - ADSI CLIENTS should use critical section protection,
  765. // as with property cache.
  766. //
  767. if ( dwPosNewOrDeletedACE <= pEnum->GetCurElement() ) {
  768. //
  769. // the ACE deleted is in front of, or is, the last ACE
  770. // enumerated, so decrement the position of the last
  771. // enumerated element by one
  772. fOk = pEnum->DecrementCurElement();
  773. ADsAssert(fOk); // should be within bound after decrement;
  774. // otherwise, coding error
  775. }
  776. // else {
  777. //
  778. // the new ACE deleted is after the last ACE enumerated, so
  779. // no effect on the position of the last enumerated element
  780. //
  781. // }
  782. pACLEnum=pACLEnum->pNext;
  783. }
  784. }
  785. }