home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / cacls / daclwrap.cxx < prev    next >
C/C++ Source or Header  |  1995-07-20  |  22KB  |  643 lines

  1. //+-------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1995, Microsoft Corporation.
  4. //
  5. //  File:        daclwrap.cxx
  6. //
  7. //  Contents:    class encapsulating file security.
  8. //
  9. //  Classes:     CDaclWrap
  10. //
  11. //  History:     Nov-93        Created         DaveMont
  12. //
  13. //--------------------------------------------------------------------
  14. #include <t2.hxx>
  15. #include <daclwrap.hxx>
  16.  
  17. #if DBG
  18. extern ULONG Debug;
  19. #endif
  20. //+---------------------------------------------------------------------------
  21. //
  22. //  Member:     CDaclWrap::CDaclWrap, public
  23. //
  24. //  Synopsis:   initialize data members, constructor will not throw
  25. //
  26. //  Arguments:  none
  27. //
  28. //----------------------------------------------------------------------------
  29. CDaclWrap::CDaclWrap()
  30.       : _ccaa(0)
  31. {
  32. }
  33. //+---------------------------------------------------------------------------
  34. //
  35. //  Member:     Dtor, public
  36. //
  37. //  Synopsis:   cleanup allocated data
  38. //
  39. //  Arguments:  none
  40. //
  41. //----------------------------------------------------------------------------
  42. CDaclWrap::~CDaclWrap()
  43. {
  44.     for (ULONG j = 0; j < _ccaa; j++)
  45.         delete _aaa[j].pcaa;
  46. }
  47. //+---------------------------------------------------------------------------
  48. //
  49. //  Member:     CDaclWrap::SetAccess, public
  50. //
  51. //  Synopsis:   caches data for a new ACE
  52. //
  53. //  Arguments:  IN [option] - rePlace, Revoke, Grant, Deny
  54. //              IN [Name] - principal (username)
  55. //              IN [System] - server/machine where Name is defined
  56. //              IN [access] - access mode (Read Change None All)
  57. //
  58. //----------------------------------------------------------------------------
  59. ULONG CDaclWrap::SetAccess(ULONG option, WCHAR *Name, WCHAR *System, ULONG access)
  60. {
  61.     ULONG ret;
  62.  
  63.     // sorry, static number of ACCESSes can be set at one time
  64.  
  65.     if (_ccaa >= CMAXACES)
  66.         return(ERROR_BUFFER_OVERFLOW);
  67.  
  68.     // allocate a new account access class
  69.  
  70.     if (NULL == (_aaa[_ccaa].pcaa = new CAccountAccess(Name, System)))
  71.     {
  72.         return(ERROR_NOT_ENOUGH_MEMORY);
  73.     }
  74.  
  75.     // to fix the bug where someone asks to both grant and deny under
  76.     // the /p option (the deny is thru access = N)
  77.  
  78.     if ((GENERIC_NONE == access) && (OPTION_REPLACE == option))
  79.     {
  80.     _aaa[_ccaa].option = OPTION_DENY;
  81.     } else
  82.     {
  83.     _aaa[_ccaa].option = option;
  84.     }
  85.  
  86.     SID *psid;
  87.  
  88.     if (ERROR_SUCCESS == ( ret = _aaa[_ccaa].pcaa->Init(access)))
  89.     {
  90.         // get the sid to make sure the username is valid
  91.  
  92.         if (ERROR_SUCCESS == ( ret =_aaa[_ccaa].pcaa->Sid(&psid)))
  93.         {
  94.             // loop thru the existing sids, making sure the new one is not a duplicate
  95.  
  96.             SID *poldsid;
  97.             for (ULONG check = 0;check < _ccaa ; check++)
  98.             {
  99.                 if (ERROR_SUCCESS == ( ret =_aaa[check].pcaa->Sid(&poldsid)))
  100.                 {
  101.                     if (EqualSid(psid,poldsid))
  102.                     {
  103.                         VERBOSE((stderr, "SetAccess found matching new sids\n"))
  104.                         return(ERROR_BAD_ARGUMENTS);
  105.                     }
  106.                 }
  107.             }
  108.             _ccaa++;
  109.         }
  110.     }
  111.     return(ret);
  112. }
  113.  
  114. //+---------------------------------------------------------------------------
  115. //
  116. //  Member:     CDaclWrap:BuildAcl, public
  117. //
  118. //  Synopsis:   merges cached new aces with the input ACL
  119. //
  120. //  Arguments:  OUT [pnewdacl] - Address of new ACL to build
  121. //              IN  [poldacl]  - (OPTIONAL) old ACL that is to be merged
  122. //              IN  [revision] - ACL revision
  123. //              IN  [fdir]     - True = directory
  124. //
  125. //----------------------------------------------------------------------------
  126. ULONG CDaclWrap::BuildAcl(ACL **pnewdacl, ACL *poldacl, UCHAR revision, BOOL fdir)
  127. {
  128.     ULONG ret, caclsize;
  129.  
  130.     // get the size of the new ACL we are going to create
  131.  
  132.     if (ERROR_SUCCESS == (ret =  _GetNewAclSize(&caclsize, poldacl, fdir)))
  133.     {
  134.         // allocate the new ACL
  135.  
  136.         if (ERROR_SUCCESS == (ret =  _AllocateNewAcl(pnewdacl, caclsize, revision)))
  137.         {
  138.             // and fill it up
  139.  
  140.             if (ERROR_SUCCESS != (ret =  _FillNewAcl(*pnewdacl, poldacl, fdir)))
  141.             {
  142.                 // free the buffer if we failed
  143.  
  144.                 LocalFree(*pnewdacl);
  145.             }
  146.  
  147.         }
  148.     }
  149.     return(ret);
  150. }
  151.  
  152. //+---------------------------------------------------------------------------
  153. //
  154. //  Member:     CDaclWrap:_GetNewAclSize, private
  155. //
  156. //  Synopsis:   returns the size need to merge the new ACEs with the old ACL,
  157. //              this is an ugly algorithm:
  158. //
  159. //if (old aces exist)
  160. //   for (new aces)
  161. //      if (new ace option == GRANT)
  162. //         for (old aces)
  163. //            if (new ace SID == old ace SID)
  164. //               do inheritance check
  165. //               found = true
  166. //               if (old ace type == ALLOWED)
  167. //                  old ace mask |= new ace mask
  168. //               else
  169. //                  old ace mask &= ~new ace mask
  170. //         if (!found)
  171. //            add size of new ace
  172. //         else
  173. //            new ace mask = 0
  174. //      else
  175. //         add size of new ace
  176. //
  177. //   for (old aces)
  178. //      for (new aces)
  179. //         if (new ace option == DENY, REPLACE, REVOKE)
  180. //            if (new ace SID == old ace SID)
  181. //               found = true
  182. //               break
  183. //      if (!found)
  184. //         add size of old ace
  185. //      else
  186. //         old ace mask = 0
  187. //else
  188. //   for (new aces)
  189. //      add size of new ace
  190. //
  191. //
  192. //  Arguments:  OUT [caclsize] - returns size
  193. //              IN  [poldacl]  - (OPTIONAL) old ACL that is to be merged
  194. //              IN  [fdir]     - True = directory
  195. //
  196. //----------------------------------------------------------------------------
  197. ULONG CDaclWrap::_GetNewAclSize(ULONG *caclsize, ACL *poldacl, BOOL fdir)
  198. {
  199.     ULONG ret;
  200.  
  201.     // the size for the ACL header
  202.  
  203.     *caclsize = sizeof(ACL);
  204.  
  205.     // initialize the access requests
  206.     for (ULONG j = 0; j < _ccaa; j++)
  207.        _aaa[j].pcaa->ReInit();
  208.  
  209.     // if we are merging, calculate the merge size
  210.  
  211.     if (poldacl)
  212.     {
  213.         // first the grant options
  214.  
  215.         for (j = 0; j < _ccaa; j++)
  216.         {
  217.             SID *psid;
  218.             if (OPTION_GRANT == _aaa[j].option)
  219.             {
  220.                 BOOL ffound = FALSE;
  221.                 ACE_HEADER *pah = (ACE_HEADER *)Add2Ptr(poldacl, sizeof(ACL));
  222.  
  223.                 for (ULONG cace = 0; cace < poldacl->AceCount;
  224.                      cace++, pah = (ACE_HEADER *)Add2Ptr(pah, pah->AceSize))
  225.                 {
  226.                     if (ERROR_SUCCESS == (ret = _aaa[j].pcaa->Sid(&psid)))
  227.                     {
  228.                         if (EqualSid(psid,
  229.                                      (SID *)&((ACCESS_ALLOWED_ACE *)
  230.                                      pah)->SidStart) )
  231.                         {
  232.                             // if old and new types are the same, just and with the old
  233.  
  234.                             if (fdir && (pah->AceType == _aaa[j].pcaa->AceType()))
  235.                             {
  236.                                 // make sure that we can handle the inheritance
  237.                                 _aaa[j].pcaa->AddInheritance(pah->AceFlags);
  238.  
  239.                                 ffound = TRUE;
  240.                             } else if (pah->AceType == _aaa[j].pcaa->AceType())
  241.                             {
  242.                                 ffound = TRUE;
  243.                             }
  244.                             
  245.                             if (ACCESS_ALLOWED_ACE_TYPE == pah->AceType)
  246.                             {
  247.                                 (ACCESS_MASK) ((ACCESS_ALLOWED_ACE *)
  248.                                 pah)->Mask |= _aaa[j].pcaa->AccessMask();
  249.                             } else if (ACCESS_DENIED_ACE_TYPE == pah->AceType)
  250.                             {
  251.                                 (ACCESS_MASK) ((ACCESS_ALLOWED_ACE *)
  252.                                 pah)->Mask &= ~_aaa[j].pcaa->AccessMask();
  253.                             } else
  254.                             {
  255.                                 VERBOSE((stderr, "_GetNewAclSize found an ace that was not allowed or denied\n"))
  256.                                 return(ERROR_INVALID_DATA);
  257.                             }
  258.                         }
  259.                     } else
  260.                     {
  261.                         return(ret);
  262.                     }
  263.                 }
  264.                 if (!ffound)
  265.                 {
  266.                     // bugbug allowed/denied sizes currently the same
  267.                     
  268.                     *caclsize += sizeof(ACCESS_ALLOWED_ACE) -
  269.                                  sizeof(DWORD) +
  270.                                  GetLengthSid(psid);
  271.                     
  272.                     SIZE((stderr, "adding on size of an new ACE (to the new ACL) = %d\n",*caclsize))
  273.                 } else
  274.                 {
  275.                     if (fdir && (ERROR_SUCCESS != (ret = _aaa[j].pcaa->TestInheritance())))
  276.                         return(ret);
  277.                     _aaa[j].pcaa->ClearAccessMask();
  278.                 }
  279.             } else if ( (OPTION_REPLACE == _aaa[j].option) ||
  280.                         (OPTION_DENY == _aaa[j].option) )
  281.             {
  282.                 if (ERROR_SUCCESS == (ret = _aaa[j].pcaa->Sid(&psid)))
  283.                 {
  284.                     // bugbug allowed/denied sizes currently the same
  285.                 
  286.                     *caclsize += sizeof(ACCESS_ALLOWED_ACE) -
  287.                                  sizeof(DWORD) +
  288.                                  GetLengthSid(psid);
  289.                 
  290.                     SIZE((stderr, "adding on size of an new ACE (to the new ACL) = %d\n",*caclsize))
  291.                 } else
  292.                     return(ret);
  293.             }
  294.         }
  295.         // now for the deny, replace & revoke options
  296.  
  297.         ACE_HEADER *pah = (ACE_HEADER *)Add2Ptr(poldacl, sizeof(ACL));
  298.         SID *psid;
  299.  
  300.         // loop thru the old ACL
  301.  
  302.         for (ULONG cace = 0; cace < poldacl->AceCount;
  303.             cace++, pah = (ACE_HEADER *)Add2Ptr(pah, pah->AceSize))
  304.         {
  305.             BOOL ffound = FALSE;
  306.  
  307.             // and thru the new ACEs looking for matching SIDs
  308.  
  309.             for (ULONG j = 0; j < _ccaa; j++)
  310.             {
  311.                 if ( (_aaa[j].option & OPTION_DENY ) ||
  312.                      (_aaa[j].option & OPTION_REPLACE ) ||
  313.                      (_aaa[j].option & OPTION_REVOKE ) )
  314.                 {
  315.                     if (ERROR_SUCCESS == (ret = _aaa[j].pcaa->Sid(&psid)))
  316.                     {
  317.                         if (EqualSid(psid,
  318.                                      (SID *)&((ACCESS_ALLOWED_ACE *)
  319.                                      pah)->SidStart) )
  320.                         {
  321.                             ffound = TRUE;
  322.                         }
  323.                     } else
  324.                         return(ret);
  325.                 }
  326.             }
  327.             if (!ffound)
  328.             {
  329.                 // if we did not find a match, add the size of the old ACE
  330.  
  331.                 *caclsize += ((ACE_HEADER *)pah)->AceSize;
  332.  
  333.                 SIZE((stderr, "adding on size of an old ACE (to the new ACL) = %d\n",*caclsize))
  334.             } else
  335.             {
  336.                 (ACCESS_MASK) ((ACCESS_ALLOWED_ACE *)pah)->Mask = 0;
  337.             }
  338.         }
  339.         SIZE((stderr, "final size for new ACL = %d\n",*caclsize))
  340.     } else
  341.     {
  342.         // no old ACL, just add up the sizes of the new aces
  343.  
  344.         for (j = 0; j < _ccaa; j++)
  345.         {
  346.             // need to know the size of the sid
  347.     
  348.             SID *psid;
  349.             if (ERROR_SUCCESS == (ret = _aaa[j].pcaa->Sid(&psid)))
  350.             {
  351.                 // bugbug allowed/denied sizes currently the same
  352.     
  353.                 *caclsize += sizeof(ACCESS_ALLOWED_ACE) -
  354.                              sizeof(DWORD) +
  355.                              GetLengthSid(psid);
  356.     
  357.                 SIZE((stderr, "adding on size of an new ACE (to the new ACL) = %d\n",*caclsize))
  358.             } else
  359.             {
  360.                 return(ret);
  361.             }
  362.         }
  363.         SIZE((stderr, "final size for new ACL = %d\n",*caclsize))
  364.     }
  365.     return(ERROR_SUCCESS);
  366. }
  367. //+---------------------------------------------------------------------------
  368. //
  369. //  Member:     CDaclWrap:_AllocateNewAcl, private
  370. //
  371. //  Synopsis:   allocates and initializes the new ACL
  372. //
  373. //  Arguments:  OUT [pnewdacl] - address of new ACL to allocate
  374. //              IN  [caclsize] - size to allocate for the new ACL
  375. //              IN  [revision] - revision of the new ACL
  376. //
  377. //----------------------------------------------------------------------------
  378. ULONG CDaclWrap::_AllocateNewAcl(ACL **pnewdacl, ULONG caclsize, ULONG revision)
  379. {
  380.     if (NULL == (*pnewdacl = (ACL *) LocalAlloc(LMEM_FIXED, caclsize)))
  381.     {
  382.         return(ERROR_NOT_ENOUGH_MEMORY);
  383.     }
  384.  
  385.     if (!InitializeAcl(*pnewdacl,caclsize, revision))
  386.     {
  387.         ULONG ret = GetLastError();
  388.         LocalFree(*pnewdacl);
  389.         return(ret);
  390.  
  391.     }
  392.  
  393.     return(ERROR_SUCCESS);
  394. }
  395. //+---------------------------------------------------------------------------
  396. //
  397. //  Member:     CDaclWrap:_SetAllowedAce, private
  398. //
  399. //  Synopsis:   appends an allowed ACE to the input ACL
  400. //
  401. //  Arguments:  IN [dacl] - ACL to add the ACE to
  402. //              IN [mask] - access mask to add
  403. //              IN [psid] - SID to add
  404. //              IN [fdir] - if a Dir add inherit ACE as well
  405. //
  406. //----------------------------------------------------------------------------
  407. ULONG CDaclWrap::_SetAllowedAce(ACL *dacl, ACCESS_MASK mask, SID *psid, BOOL fdir)
  408. {
  409.     ULONG ret = ERROR_SUCCESS;
  410.  
  411.     // compute the size of the ACE we are making
  412.  
  413.     USHORT acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(psid);
  414.  
  415.     SIZE((stderr, "adding allowed ace, size = %d\n",fdir ? acesize*2 : acesize))
  416.  
  417.     // static buffer in the hopes we won't have to allocate memory
  418.  
  419.     BYTE buf[1024];
  420.  
  421.     // allocator either uses buf or allocates a new buffer if size is not enough
  422.  
  423.     FastAllocator fa(buf, 1024);
  424.  
  425.     // get the buffer for the ACE
  426.  
  427.     ACCESS_ALLOWED_ACE *paaa = (ACCESS_ALLOWED_ACE *)fa.GetBuf(acesize);
  428.  
  429.     // fill in the ACE
  430.  
  431.     memcpy(&paaa->SidStart,psid,GetLengthSid(psid));
  432.     paaa->Mask = mask;
  433.  
  434.     paaa->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  435.     paaa->Header.AceFlags = fdir ? CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE : 0;
  436.     paaa->Header.AceSize = acesize;
  437.  
  438.     // put the ACE into the ACL
  439.  
  440.     if (!AddAce(dacl,
  441.                 dacl->AclRevision,
  442.                 0xffffffff,
  443.                 paaa,
  444.                 paaa->Header.AceSize))
  445.         ret = GetLastError();
  446.     return(ret);
  447. }
  448. //+---------------------------------------------------------------------------
  449. //
  450. //  Member:     CDaclWrap:_SetDeniedAce, private
  451. //
  452. //  Synopsis:   appends a denied ACE to the input ACL
  453. //
  454. //  Arguments:  IN [dacl] - ACL to add the ACE to
  455. //              IN [mask] - access mask to add
  456. //              IN [psid] - SID to add
  457. //              IN [fdir] - if a Dir add inherit ACE as well
  458. //
  459. //----------------------------------------------------------------------------
  460. ULONG CDaclWrap::_SetDeniedAce(ACL *dacl, ACCESS_MASK mask, SID *psid, BOOL fdir)
  461. {
  462.     ULONG ret = ERROR_SUCCESS;
  463.  
  464.     // compute the size of the ACE we are making
  465.  
  466.     USHORT acesize = sizeof(ACCESS_DENIED_ACE) -
  467.                    sizeof(DWORD) +
  468.                    GetLengthSid(psid);
  469.  
  470.     SIZE((stderr, "adding denied ace, size = %d\n",acesize))
  471.  
  472.     // static buffer in the hopes we won't have to allocate memory
  473.  
  474.     BYTE buf[1024];
  475.  
  476.     // allocator either uses buf or allocates a new buffer if size is not enough
  477.  
  478.     FastAllocator fa(buf, 1024);
  479.  
  480.     // get the buffer for the ACE
  481.  
  482.     ACCESS_DENIED_ACE *paaa = (ACCESS_DENIED_ACE *)fa.GetBuf(acesize);
  483.  
  484.     // fill in the ACE
  485.  
  486.     memcpy(&paaa->SidStart,psid,GetLengthSid(psid));
  487.     paaa->Mask = mask;
  488.  
  489.     paaa->Header.AceType = ACCESS_DENIED_ACE_TYPE;
  490.     paaa->Header.AceFlags = fdir ? CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE : 0;
  491.     paaa->Header.AceSize = acesize;
  492.  
  493.     // put the ACE into the ACL
  494.  
  495.     if (!AddAce(dacl,
  496.                 dacl->AclRevision,
  497.                 0xffffffff,
  498.                 paaa,
  499.                 paaa->Header.AceSize))
  500.         ret = GetLastError();
  501.     return(ret);
  502. }
  503. //+---------------------------------------------------------------------------
  504. //
  505. //  Member:     CDaclWrap:_FillNewAcl, private
  506. //
  507. //  Synopsis:   The worker routine that actually fills the ACL, it adds the
  508. //              new denied ACEs, then if the new ACEs are being merged with
  509. //              an existing ACL, the existing ACL's ACE's (that don't
  510. //              conflict) are added, finally the new allowed ACEs are added.
  511. //              another ugly algorithm:
  512. //
  513. //for (new aces)
  514. //   if (new ace option == DENY)
  515. //      add new ace
  516. //
  517. //if (old aces)
  518. //   for (old aces)
  519. //      if (old ace mask != 0)
  520. //         add old ace
  521. //
  522. //   for (new aces)
  523. //      if (new ace option != DENY)
  524. //         if ( new ace option != REVOKE)
  525. //            if (new ace mask != 0
  526. //                add new ace
  527. //
  528. //else
  529. //   for (new aces)
  530. //      if (new ace option != DENY)
  531. //         add new ace
  532. //
  533. //  Arguments:  IN [pnewdacl] - the new ACL to be filled
  534. //              IN [poldacl]  - (OPTIONAL) old ACL that is to be merged
  535. //              IN [fdir]     - TRUE = directory
  536. //
  537. //----------------------------------------------------------------------------
  538. ULONG CDaclWrap::_FillNewAcl(ACL *pnewdacl, ACL *poldacl, BOOL fdir)
  539. {
  540.     SID *psid;
  541.     ULONG ret;
  542.  
  543.     // set new denied aces
  544.  
  545.     VERBOSE((stderr, "start addr of new ACL %0lx\n",pnewdacl))
  546.  
  547.     for (ULONG j = 0; j < _ccaa; j++)
  548.     {
  549.         if (_aaa[j].option & OPTION_DENY)
  550.         {
  551.             if (ERROR_SUCCESS == (ret = _aaa[j].pcaa->Sid(&psid)))
  552.             {
  553.                 if (ERROR_SUCCESS != (ret = _SetDeniedAce(pnewdacl,
  554.                                                            _aaa[j].pcaa->AccessMask(),
  555.                                                            psid,
  556.                                                            fdir )))
  557.                     return(ret);
  558.             } else
  559.                 return(ret);
  560.         }
  561.     }
  562.  
  563.     // check and see if the ACL from from the file is in correct format
  564.  
  565.     if (poldacl)
  566.     {
  567.         SIZE((stderr, "old ACL size = %d, acecount = %d\n",poldacl->AclSize,
  568.               poldacl->AceCount))
  569.  
  570.         ACE_HEADER *pah = (ACE_HEADER *)Add2Ptr(poldacl, sizeof(ACL));
  571.  
  572.         // loop thru the old ACL, looking for matches with the new ACEs
  573.  
  574.         BOOL fallowedacefound = FALSE;
  575.         for (ULONG cace = 0; cace < poldacl->AceCount;
  576.             cace++, pah = (ACE_HEADER *)Add2Ptr(pah, pah->AceSize))
  577.         {
  578.             // error exit if the old ACL is incorrectly formated
  579.  
  580.             if (pah->AceType == ACCESS_DENIED_ACE_TYPE && fallowedacefound)
  581.             {
  582.                 VERBOSE((stderr, "_FillNewAcl found an denied ACE after an allowed ACE\n"))
  583.                 return(ERROR_INVALID_DATA);
  584.             }
  585.             else if (pah->AceType == ACCESS_ALLOWED_ACE_TYPE)
  586.                 fallowedacefound = TRUE;
  587.  
  588.             // add the old ace to the new ACL if the old ace's mask is not zero
  589.  
  590.             if ( 0 != (ACCESS_MASK)((ACCESS_ALLOWED_ACE *)pah)->Mask)
  591.             {
  592.                 // add the old ace
  593.                 if (!AddAce(pnewdacl,
  594.                             pnewdacl->AclRevision,
  595.                             0xffffffff,
  596.                             pah,
  597.                             pah->AceSize))
  598.                     return(GetLastError());
  599.             }
  600.         }
  601.         // now for the new aces
  602.  
  603.         for (ULONG j = 0; j < _ccaa; j++)
  604.         {
  605.             if ( (_aaa[j].option != OPTION_DENY) && 
  606.                  (_aaa[j].option != OPTION_REVOKE) &&
  607.                  (_aaa[j].pcaa->AccessMask() != 0) )
  608.             {
  609.                 if (ERROR_SUCCESS == (ret = _aaa[j].pcaa->Sid(&psid)))
  610.                 {
  611.                     if (ERROR_SUCCESS != (ret = _SetAllowedAce(pnewdacl,
  612.                                                                _aaa[j].pcaa->AccessMask(),
  613.                                                                psid,
  614.                                                                fdir )))
  615.                         return(ret);
  616.                 } else
  617.                     return(ret);
  618.             }
  619.             
  620.         }
  621.     } else
  622.     {
  623.         // no old acl, just add the (rest) of the new aces
  624.         for (ULONG j = 0; j < _ccaa; j++)
  625.         {
  626.             if (_aaa[j].option != OPTION_DENY)
  627.             {
  628.                 if (ERROR_SUCCESS == (ret = _aaa[j].pcaa->Sid(&psid)))
  629.                 {
  630.                     if (ERROR_SUCCESS != (ret = _SetAllowedAce(pnewdacl,
  631.                                                                _aaa[j].pcaa->AccessMask(),
  632.                                                                psid,
  633.                                                                fdir )))
  634.                         return(ret);
  635.                 } else
  636.                     return(ret);
  637.             }
  638.         }
  639.     }
  640.  
  641.     return(ERROR_SUCCESS);
  642. }
  643.