/// <summary>
 /// Add the specific ACE(s) to the provided ACL. 
 /// DACL would be reordered after being added, ACCESS_DENIED_ACE before ACCESS_ALLOWED_ACE.
 /// </summary>
 /// <param name="isDACL">Whether it is DACL or SACL</param>
 /// <param name="acl">The ACL to be added to.</param>
 /// <param name="aces">The ACE(s) to be added.</param>
 public static void AddAceToAcl(ref _ACL acl, bool isDACL, params object[] aces)
 {
     if (aces == null || aces.Length == 0)
     {
         return;
     }
     acl.AceCount += (ushort)aces.Length;
     object[] newAces = new object[acl.AceCount];
     if (isDACL)
     {
         int i = 0;
         int j = acl.AceCount - 1;
         foreach (object tmp in acl.Aces)
         {
             if (tmp is _ACCESS_ALLOWED_ACE)
             {
                 newAces[j--] = tmp;
             }
             else if (tmp is _ACCESS_DENIED_ACE)
             {
                 newAces[i++] = tmp;
             }
             else
             {
                 throw new ArgumentException("Unsupport type of ACE");
             }
         }
         foreach (object tmp in aces)
         {
             if (tmp is _ACCESS_ALLOWED_ACE)
             {
                 newAces[j--] = tmp;
             }
             else if (tmp is _ACCESS_DENIED_ACE)
             {
                 newAces[i++] = tmp;
             }
             else
             {
                 throw new ArgumentException("Unsupport type of ACE");
             }
         }
         Debug.Assert(i - j == 1, "New ACE array should be filled.");
     }
     else // SACL does not need to be reordered
     {
         acl.Aces.CopyTo(newAces, 0);
         aces.CopyTo(newAces, acl.Aces.Length);
     }
     acl.Aces = newAces;
     acl.AclSize = CalculateAclSize(acl);
 }
        /// <summary>
        /// PreProcessACLfromCreator. MS-DTYP section 2.5.4.8
        /// </summary>
        /// <param name="acl">
        /// ACL to preprocess.
        /// </param>
        /// <returns>
        /// Processed ACL.
        /// </returns>
        public static _ACL PreProcessACLfromCreator(_ACL acl)
        {
            //Initialize NewACL to Empty ACL
            //FOR each ACE in ACL DO
            //IF ACE.Flags does not contain INHERITED_ACE THEN
            //Append ACE to NewACL
            //ENDIF
            //END FOR
            //RETURN NewACL
            _ACL newAcl = new _ACL();
            newAcl.AclRevision = acl.AclRevision;
            List<object> newAces = new List<object>();

            if (acl.Aces != null)
            {
                foreach (object ace in acl.Aces)
                {
                    _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(ace, "Header");
                    if ((header.AceFlags & ACE_FLAGS.INHERITED_ACE) == ACE_FLAGS.None)
                    {
                        //Append ACE to NewACL
                        newAces.Add(ace);
                    }
                }
            }
            newAcl.Aces = newAces.ToArray();
            newAcl.AceCount = (ushort)newAcl.Aces.Length;
            newAcl.AclSize = DtypUtility.CalculateAclSize(newAcl);

            return newAcl;
        }
 /// <summary>
 /// Calculate AclSize of the given ACL, in bytes.
 /// </summary>
 /// <param name="acl">The acl to be retrieved.</param>
 /// <returns>The size of the given acl, in bytes.</returns>
 internal static ushort CalculateAclSize(_ACL acl)
 {
     //The AclSize contains the following parts:
     //byte AclRevision;(1 byte)
     //byte Sbz1;(1 byte)
     //ushort AclSize;(2 bytes)
     //ushort AceCount;(2 bytes)
     //ushort Sbz2;(2 bytes)
     //object[] Aces;(variable length)
     ushort sizeOfAcl = ACL_HEADER_LENGTH;
     for (int i = 0; i < acl.AceCount; i++)
     {
         _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(acl.Aces[i], "Header");
         sizeOfAcl += header.AceSize;
     }
     return sizeOfAcl;
 }
        /// <summary>
        /// Encode the ACL structure into byte array, according to TD specification.
        /// </summary>
        /// <param name="acl">The acl to be retrieved.</param>
        /// <returns>The encoded byte array.</returns>
        /// <exception cref="ArgumentException">
        /// Thrown when The type of ace is invalid.
        /// </exception>
        public static byte[] EncodeAcl(_ACL acl)
        {
            List<byte> byteArray = new List<byte>();
            byteArray.Add(acl.AclRevision);
            byteArray.Add(acl.Sbz1);
            byteArray.AddRange(TypeMarshal.ToBytes<ushort>(acl.AclSize));
            byteArray.AddRange(TypeMarshal.ToBytes<ushort>(acl.AceCount));
            byteArray.AddRange(TypeMarshal.ToBytes<ushort>(acl.Sbz2));

            for (int i = 0; i < acl.AceCount; i++)
            {
                _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(acl.Aces[i], "Header");
                byte[] tmpByteArray = new byte[] { };
                switch (header.AceType)
                {
                    case ACE_TYPE.ACCESS_ALLOWED_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_ACCESS_ALLOWED_ACE>((_ACCESS_ALLOWED_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.ACCESS_DENIED_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_ACCESS_DENIED_ACE>((_ACCESS_DENIED_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.SYSTEM_AUDIT_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_SYSTEM_AUDIT_ACE>((_SYSTEM_AUDIT_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.ACCESS_ALLOWED_OBJECT_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_ACCESS_ALLOWED_OBJECT_ACE>(
                            (_ACCESS_ALLOWED_OBJECT_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.ACCESS_DENIED_OBJECT_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_ACCESS_DENIED_OBJECT_ACE>(
                            (_ACCESS_DENIED_OBJECT_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.SYSTEM_AUDIT_OBJECT_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_SYSTEM_AUDIT_OBJECT_ACE>(
                            (_SYSTEM_AUDIT_OBJECT_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_ACCESS_ALLOWED_CALLBACK_ACE>(
                            (_ACCESS_ALLOWED_CALLBACK_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.ACCESS_DENIED_CALLBACK_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_ACCESS_DENIED_CALLBACK_ACE>(
                            (_ACCESS_DENIED_CALLBACK_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE>(
                            (_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_ACCESS_DENIED_CALLBACK_OBJECT_ACE>(
                            (_ACCESS_DENIED_CALLBACK_OBJECT_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_SYSTEM_AUDIT_CALLBACK_ACE>(
                            (_SYSTEM_AUDIT_CALLBACK_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE>(
                            (_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.SYSTEM_MANDATORY_LABLE_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_SYSTEM_MANDATORY_LABEL_ACE>(
                            (_SYSTEM_MANDATORY_LABEL_ACE)acl.Aces[i]);
                        break;

                    case ACE_TYPE.SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE:
                        tmpByteArray = ((SystemResourceAttributeAce)acl.Aces[i]).BinaryForm;
                        break;

                    case ACE_TYPE.SYSTEM_SCOPED_POLICY_ID_ACE_TYPE:
                        tmpByteArray = TypeMarshal.ToBytes<_SYSTEM_SCOPED_POLICY_ID_ACE>(
                            (_SYSTEM_SCOPED_POLICY_ID_ACE)acl.Aces[i]);
                        break;

                    default:
                        throw new ArgumentException("The type of ace is invalid", "acl");
                }
                byteArray.AddRange(tmpByteArray);
            }
            return byteArray.ToArray();
        }
        /// <summary>
        /// PostProcessACL. MS-DTYP section 2.5.4.9
        /// </summary>
        /// <param name="acl">ACL on which to substitute SIDs.</param>
        /// <param name="copyFilter">The filter for post-processing the ACL.</param>
        /// <param name="owner">Owner to use in substituting the CreatorOwner SID.</param>
        /// <param name="group">Group to use in substituting the CreatorGroup SID.</param>
        /// <param name="genericMapping">
        /// Mapping of generic permissions to resource manager-specific 
        /// permissions supplied by the caller.
        /// </param>
        /// <returns>
        /// The computed ACL with the SID substitutions performed.
        /// </returns>
        public static _ACL PostProcessACL(
            _ACL acl,
            CopyFilter copyFilter,
            _SID owner,
            _SID group,
            GenericMapping genericMapping)
        {
            #region Pseudocode  v20110329

            //// Substitute CreatorOwner and CreatorGroup SIDs and do GenericMapping in ACL

            //Initialize NewACL to Empty ACL

            //FOR each ACE in ACL DO

            //    // Determine if this ACE passes the filter to be copied to the new ACL

            //    SET CopyThisAce = FALSE

            //    CASE CopyFilter OF

            //        CopyAllAces:
            //            BEGIN
            //                SET CopyThisAce = TRUE
            //            END

            //        CopyInheritedAces:
            //            BEGIN
            //                IF (ACE.AceFlags contains INHERITED_ACE) THEN
            //                    SET CopyThisAce = TRUE
            //                ENDIF
            //            END

            //        CopyExplicitAces:
            //            BEGIN
            //                IF (ACE.AceFlags does not contain INHERITED_ACE) THEN
            //                   SET CopyThisAce = TRUE
            //                ENDIF
            //            END

            //    ENDCASE

            //    Set NewACE to ACE

            //    IF (CopyThisAce) THEN

            //        CASE ACE.Sid OF

            //            CREATOR_OWNER:
            //                NewACE.Sid = Owner

            //            CREATOR_GROUP:
            //                NewACE.Sid = Group
            //        ENDCASE

            //        IF (ACE.Mask contains GENERIC_READ) THEN
            //            Add GenericMapping.GenericRead to NewACE.Mask
            //        ENDIF

            //        IF (ACE.Mask contains GENERIC_WRITE) THEN
            //            Add GenericMapping.GenericWrite to NewACE.Mask
            //        ENDIF

            //        IF (ACE.Mask contains GENERIC_EXECUTE) THEN
            //            Add GenericMapping.GenericExecute to NewACE.Mask
            //        ENDIF

            //        Append NewACE to NewACL
            //    ENDIF

            //END FOR

            //RETURN NewACL
            //// END PostProcessACL

            #endregion

            _ACL newAcl = new _ACL();
            newAcl.AclRevision = acl.AclRevision;
            newAcl.Aces = new object[] { };
            List<object> newAces = new List<object>();

            if (acl.Aces != null)
            {
                foreach (object ace in acl.Aces)
                {
                    object newAce = ObjectUtility.DeepClone(ace);
                    _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(newAce, "Header");

                    bool copyThisAce = false;
                    switch (copyFilter)
                    {
                        case CopyFilter.CopyAllAces:
                            copyThisAce = true;
                            break;
                        case CopyFilter.CopyInheritedAces:
                            if ((header.AceFlags & ACE_FLAGS.INHERITED_ACE) == ACE_FLAGS.INHERITED_ACE)
                            {
                                copyThisAce = true;
                            }
                            break;
                        case CopyFilter.CopyExplicitAces:
                            if ((header.AceFlags & ACE_FLAGS.INHERITED_ACE) == ACE_FLAGS.None)
                            {
                                copyThisAce = true;
                            }
                            break;
                    }

                    if (copyThisAce)
                    {
                        #region Substitute CreatorOwner and CreatorGroup SIDs in ACL

                        _SID sid = (_SID)ObjectUtility.GetFieldValue(newAce, "Sid");
                        if (ObjectUtility.DeepCompare(sid, GetWellKnownSid(WellKnownSid.CREATOR_OWNER, null)))
                        {
                            ObjectUtility.SetFieldValue(newAce, "Sid", owner);
                            header.AceSize = (ushort)(header.AceSize
                                - (sid.SubAuthorityCount - owner.SubAuthorityCount) * sizeof(uint));
                            ObjectUtility.SetFieldValue(newAce, "Header", header);

                        }
                        else if (ObjectUtility.DeepCompare(sid, GetWellKnownSid(WellKnownSid.CREATOR_GROUP, null)))
                        {
                            ObjectUtility.SetFieldValue(newAce, "Sid", group);
                            header.AceSize = (ushort)(header.AceSize
                                - (sid.SubAuthorityCount - group.SubAuthorityCount) * sizeof(uint));
                            ObjectUtility.SetFieldValue(newAce, "Header", header);
                        }
                        #endregion

                        #region Do GenericMapping in ACL

                        uint mask = (uint)ObjectUtility.GetFieldValue(newAce, "Mask");

                        if ((mask & ACCESS_MASK_GENERIC_READ) == ACCESS_MASK_GENERIC_READ)
                        {
                            mask = mask | genericMapping.GenericRead;
                            ObjectUtility.SetFieldValue(newAce, "Mask", mask);
                        }
                        if ((mask & ACCESS_MASK_GENERIC_WRITE) == ACCESS_MASK_GENERIC_WRITE)
                        {
                            mask = mask | genericMapping.GenericWrite;
                            ObjectUtility.SetFieldValue(newAce, "Mask", mask);
                        }
                        if ((mask & ACCESS_MASK_GENERIC_EXECUTE) == ACCESS_MASK_GENERIC_EXECUTE)
                        {
                            mask = mask | genericMapping.GenericExecute;
                            ObjectUtility.SetFieldValue(newAce, "Mask", mask);
                        }
                        #endregion

                        //Append NewACE to NewACL
                        newAces.Add(newAce);
                    }
                }
            }
            newAcl.Aces = newAces.ToArray();
            newAcl.AceCount = (ushort)newAcl.Aces.Length;
            newAcl.AclSize = DtypUtility.CalculateAclSize(newAcl);

            return newAcl;
        }
        /// <summary>
        /// Create a _SECURITY_DESCRIPTOR structure in self-relative format.
        /// </summary>
        /// <param name="control">An unsigned 16-bit field that specifies control access bit flags.</param>
        /// <param name="ownerSid">The SID of the owner of the object</param>
        /// <param name="groupSid">The SID of the group of the object.</param>
        /// <param name="sacl">The SACL of the object.</param>
        /// <param name="dacl">The DACL of the object.</param>
        /// <returns> Output security descriptor for the object.</returns>
        public static _SECURITY_DESCRIPTOR CreateSecurityDescriptor(
            SECURITY_DESCRIPTOR_Control control,
            _SID? ownerSid,
            _SID? groupSid,
            _ACL? sacl,
            _ACL? dacl)
        {
            RawAcl sRawAcl = null;
            RawAcl dRawAcl = null;
            SecurityIdentifier rawOwnerSid = null;
            SecurityIdentifier rawGroupSid = null;
            if (ownerSid != null)
            {
                rawOwnerSid = new SecurityIdentifier(TypeMarshal.ToBytes(ownerSid.Value), 0);
            }
            if (groupSid != null)
            {
                rawGroupSid = new SecurityIdentifier(TypeMarshal.ToBytes(groupSid.Value), 0);
            }
            if (sacl != null)
            {
                sRawAcl = new RawAcl(DtypUtility.EncodeAcl(sacl.Value), 0);
            }
            if (dacl != null)
            {
                dRawAcl = new RawAcl(DtypUtility.EncodeAcl(dacl.Value), 0);
            }
            RawSecurityDescriptor rawSecurityDescriptor = new RawSecurityDescriptor(
                (ControlFlags)control,
                rawOwnerSid,
                rawGroupSid,
                sRawAcl,
                dRawAcl);
            byte[] rawSecurityDescriptorBytes = new byte[rawSecurityDescriptor.BinaryLength];
            rawSecurityDescriptor.GetBinaryForm(rawSecurityDescriptorBytes, 0);

            return DtypUtility.DecodeSecurityDescriptor(rawSecurityDescriptorBytes);
        }
        /// <summary>
        /// Decode the specified buffer into the ACL structure.
        /// </summary>
        /// <param name="buffer">The byte array to be decoded.</param>
        /// <returns>The ACL structure.</returns>
        /// <exception cref="FormatException">
        /// Thrown when the format of input parameter is not correct.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Thrown when The type of ace is invalid.
        /// </exception>
        public static _ACL DecodeAcl(byte[] buffer)
        {
            if (buffer == null || buffer.Length < ACL_HEADER_LENGTH)
            {
                throw new FormatException("The token body is incomplete.");
            }

            _ACL acl = new _ACL();
            List<object> aces = new List<object>();
            int index = 0;
            byte[] tokenBody = new byte[] { };

            acl.AclRevision = buffer[0];
            acl.Sbz1 = buffer[1];

            index += sizeof(byte) * 2;
            tokenBody = ArrayUtility.SubArray(buffer, index, sizeof(ushort));
            acl.AclSize = TypeMarshal.ToStruct<ushort>(tokenBody);

            index += sizeof(ushort);
            tokenBody = ArrayUtility.SubArray(buffer, index, sizeof(ushort));
            acl.AceCount = TypeMarshal.ToStruct<ushort>(tokenBody);

            index += sizeof(ushort);
            tokenBody = ArrayUtility.SubArray(buffer, index, sizeof(ushort));
            acl.Sbz2 = TypeMarshal.ToStruct<ushort>(tokenBody);

            index += sizeof(ushort);
            for (int i = 0; i < acl.AceCount; i++)
            {
                tokenBody = ArrayUtility.SubArray(buffer, index, ACE_HEADER_LENGTH);
                _ACE_HEADER header = TypeMarshal.ToStruct<_ACE_HEADER>(tokenBody);
                object ace = null;
                tokenBody = ArrayUtility.SubArray(buffer, index, header.AceSize);
                switch (header.AceType)
                {
                    case ACE_TYPE.ACCESS_ALLOWED_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_ACCESS_ALLOWED_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.ACCESS_DENIED_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_ACCESS_DENIED_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.SYSTEM_AUDIT_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_SYSTEM_AUDIT_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.ACCESS_ALLOWED_OBJECT_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_ACCESS_ALLOWED_OBJECT_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.ACCESS_DENIED_OBJECT_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_ACCESS_DENIED_OBJECT_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.SYSTEM_AUDIT_OBJECT_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_SYSTEM_AUDIT_OBJECT_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_ACCESS_ALLOWED_CALLBACK_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.ACCESS_DENIED_CALLBACK_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_ACCESS_DENIED_CALLBACK_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_ACCESS_ALLOWED_CALLBACK_OBJECT_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_ACCESS_DENIED_CALLBACK_OBJECT_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_SYSTEM_AUDIT_CALLBACK_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_SYSTEM_AUDIT_CALLBACK_OBJECT_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.SYSTEM_MANDATORY_LABLE_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_SYSTEM_MANDATORY_LABEL_ACE>(tokenBody);
                        break;

                    case ACE_TYPE.SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE:
                        ace = SystemResourceAttributeAce.FromBytes(tokenBody);
                        break;

                    case ACE_TYPE.SYSTEM_SCOPED_POLICY_ID_ACE_TYPE:
                        ace = TypeMarshal.ToStruct<_SYSTEM_SCOPED_POLICY_ID_ACE>(tokenBody);
                        break;

                    default:
                        throw new ArgumentException("The type of ace is invalid.", "buffer");
                }
                index += header.AceSize;
                aces.Add(ace);
            }

            acl.Aces = aces.ToArray();
            return acl;
        }
 /// <summary>
 /// Create an ACL with provided ACE(s). 
 /// </summary>
 /// <param name="isDACL">Whether it is DACL or SACL</param>
 /// <param name="aces">The ACE(s) to be put into the ACL.</param>
 /// <returns>The constructed ACL structure.</returns>
 public static _ACL CreateAcl(bool isDACL, params object[] aces)
 {
     _ACL acl = new _ACL
     {
         AceCount = 0,
         Aces = new object[0],
         AclRevision = 0x02,
         // AclRevision (1 byte) + Sbz1 (1 byte) + AclSize (2 bytes)
         // + AceCount (2 bytes) + Sbz2 (2 bytes)
         AclSize = 8,
         Sbz1 = 0,
         Sbz2 = 0
     };
     if (aces != null && aces.Length != 0)
     {
         AddAceToAcl(ref acl, isDACL, aces);
     }
     return acl;
 }
        /// <summary>
        /// ContainsInheritableACEs. MS-DTYP section 2.5.4.5
        /// </summary>
        /// <param name="acl">ACL</param>
        /// <returns>Return TRUE if contains inheritable ACE; otherwise, FALSE.</returns>
        public static bool ContainsInheritableACEs(_ACL acl)
        {
            //FOR each ACE in ACL DO
            //IF(ACE.Flags contains CONTAINER_INHERIT_ACE) OR
            //(ACE.Flags contains OBJECT_INHERIT_ACE)
            //THEN
            //RETURN TRUE
            //ENDIF
            //END FOR
            //RETURN FALSE

            if (acl.Aces != null)
            {
                foreach (object ace in acl.Aces)
                {
                    object newAce = ObjectUtility.DeepClone(ace);
                    _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(newAce, "Header");

                    if ((header.AceFlags & ACE_FLAGS.CONTAINER_INHERIT_ACE) == ACE_FLAGS.CONTAINER_INHERIT_ACE
                        || (header.AceFlags & ACE_FLAGS.OBJECT_INHERIT_ACE) == ACE_FLAGS.OBJECT_INHERIT_ACE)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// ComputeInheritedACLfromParent. MS-DTYP section 2.5.4.6
        /// </summary>
        /// <param name="acl">
        /// An ACL that contains the parent's ACEs from which to compute the inherited ACL.
        /// </param>
        /// <param name="isContainerObject">
        /// TRUE if the object is a container; otherwise, FALSE.
        /// </param>
        /// <param name="objectTypes">
        /// An array of GUIDs for the object type being created.
        /// </param>
        /// <returns>
        /// The computed ACL that also includes the inherited ACEs.
        /// </returns>
        public static _ACL ComputeInheritedACLfromParent(
            _ACL acl,
            bool isContainerObject,
            Guid[] objectTypes)
        {
            //Initialize ExplicitACL to Empty ACL
            //FOR each ACE in ACL DO
            //IF ACE.Flags contains INHERIT_ONLY_ACE
            //THEN
            //CONTINUE
            //ENDIF
            //IF(((ACE.Flags contains CONTAINER_INHERIT_ACE) AND
            //(IsContainerObject = TRUE))OR
            //((ACE.Flags contains OBJECT_INHERIT_ACE) AND
            //(IsContainerObject = FALSE)))
            //THEN
            //    CASE ACE.Type OF
            //    ALLOW:
            //    DENY:
            //    Set NewACE to ACE
            //    Set NewACE.Flags to INHERITED_ACE
            //    Append NewACE to ExplicitACL
            //    OBJECT_ALLOW:
            //    OBJECT_DENY:
            //    IF (ObjectTypes contains ACE.ObjectGUID) THEN
            //    Set NewACE to ACE
            //    Set NewACE.Flags to INHERITED_ACE
            //    Append NewACE to ExplicitACL
            //    ENDIF
            //    ENDCASE
            //ENDIF
            //END FOR
            //Initialize InheritableACL to Empty ACL
            //IF (IsContainerObject = TRUE) THEN
            //FOR each ACE in ACL DO
            //IF ACE.Flags contains NO_PROPAGATE_INHERIT_ACE THEN
            //CONTINUE
            //ENDIF
            //IF((ACE.Flags contains CONTAINER_INHERIT_ACE) OR
            //(ACE.Flags contains OBJECT_INHERIT_ACE))
            //THEN
            //Set NewACE to ACE
            //Add INHERITED_ACE to NewACE.Flags
            //Add INHERIT_ONLY_ACE to NewACE.Flags
            //Append NewACE to InheritableACL
            //ENDIF
            //END FOR
            //ENDIF
            //RETURN concatenation of ExplicitACL and InheritableACL

            _ACL newAcl = new _ACL();
            newAcl.AclRevision = acl.AclRevision;
            List<object> newAces = new List<object>();

            #region Computes the explicit Acl
            if (acl.Aces != null)
            {
                foreach (object ace in acl.Aces)
                {
                    object newAce = ObjectUtility.DeepClone(ace);
                    _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(newAce, "Header");

                    if ((header.AceFlags & ACE_FLAGS.INHERIT_ONLY_ACE) == ACE_FLAGS.INHERIT_ONLY_ACE)
                    {
                        continue;
                    }

                    if (((header.AceFlags & ACE_FLAGS.CONTAINER_INHERIT_ACE)
                            == ACE_FLAGS.CONTAINER_INHERIT_ACE && isContainerObject)
                        || ((header.AceFlags & ACE_FLAGS.OBJECT_INHERIT_ACE)
                            == ACE_FLAGS.OBJECT_INHERIT_ACE && (!isContainerObject)))
                    {
                        bool retVal = DtypUtility.ComputeInheritedAcefromParent(ref newAce, objectTypes);
                        if (retVal)
                        {
                            newAces.Add(newAce);
                        }
                    }
                }
            }
            #endregion

            #region Compute the inheritable ACL
            if (isContainerObject && acl.AceCount >= 0 && acl.Aces != null)
            {
                foreach (object ace in acl.Aces)
                {
                    object newAce = ObjectUtility.DeepClone(ace);
                    _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(newAce, "Header");

                    if ((header.AceFlags & ACE_FLAGS.NO_PROPAGATE_INHERIT_ACE)
                            == ACE_FLAGS.NO_PROPAGATE_INHERIT_ACE)
                    {
                        continue;
                    }

                    if ((header.AceFlags & ACE_FLAGS.CONTAINER_INHERIT_ACE) == ACE_FLAGS.CONTAINER_INHERIT_ACE
                        || (header.AceFlags & ACE_FLAGS.OBJECT_INHERIT_ACE) == ACE_FLAGS.OBJECT_INHERIT_ACE)
                    {
                        header.AceFlags |= (ACE_FLAGS.INHERIT_ONLY_ACE | ACE_FLAGS.INHERITED_ACE);
                        ObjectUtility.SetFieldValue(newAce, "Header", header);
                        //Append NewACE to NewACL
                        newAces.Add(newAce);
                    }
                }
            }
            #endregion

            newAcl.Aces = newAces.ToArray();
            newAcl.AceCount = (ushort)newAcl.Aces.Length;
            newAcl.AclSize = DtypUtility.CalculateAclSize(newAcl);

            return newAcl;
        }
        /// <summary>
        /// ComputeInheritedACLfromCreator. MS-DTYP section 2.5.4.7
        /// </summary>
        /// <param name="acl">
        /// An ACL supplied in the security descriptor by the caller.
        /// </param>
        /// <param name="isContainerObject">
        /// TRUE if the object is a container; otherwise, FALSE.
        /// </param>
        /// <param name="objectTypes">
        /// An array of GUIDs for the object type being created.
        /// </param>
        /// <returns>
        /// The computed ACL that also includes the inherited ACEs.
        /// </returns>
        public static _ACL ComputeInheritedACLfromCreator(
            _ACL acl,
            bool isContainerObject,
            Guid[] objectTypes)
        {
            //Initialize ExplicitACL to Empty ACL
            //FOR each ACE in ACL DO
            //IF((ACE.Flags contains CONTAINER_INHERIT_ACE) AND
            //(IsContainerObject = TRUE))OR
            //((ACE.Flags contains OBJECT_INHERIT_ACE) AND
            //(IsContainerObject = FALSE))
            //THEN
            //    CASE ACE.Type OF
            //    ALLOW:
            //    DENY:
            //    Set NewACE to ACE
            //    Set NewACE.Flags to NULL
            //    Append NewACE to ExplicitACL
            //    OBJECT_ALLOW
            //    OBJECT_DENY:
            //    IF (ObjectTypes contains ACE.ObjectGUID) THEN
            //    Set NewACE to ACE
            //    Set NewACE.Flags to NULL
            //    Append NewACE to ExplicitACL
            //    ENDIF
            //    ENDCASE
            //ENDIF
            //END FOR
            //Initialize InheritableACL to Empty ACL
            //IF (IsContainerObject = TRUE) THEN
            //    FOR each ACE in ACL DO
            //    IF((ACE.Flags contains CONTAINER_INHERIT_ACE) OR
            //        (ACE.Flags contains OBJECT_INHERIT_ACE))
            //    THEN
            //    Set NewACE to ACE
            //    Add INHERIT_ONLY_ACE to NewACE.Flags
            //    Append NewACE to InheritableACL
            //    ENDIF
            //    END FOR
            //ENDIF
            //RETURN concatenation of ExplicitACL and InheritableACL
            _ACL newAcl = new _ACL();
            newAcl.AclRevision = acl.AclRevision;
            List<object> newAces = new List<object>();

            #region Computes the explicit Acl
            if (acl.Aces != null)
            {
                foreach (object ace in acl.Aces)
                {
                    object newAce = ObjectUtility.DeepClone(ace);
                    _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(newAce, "Header");
                    ACCESS_OBJECT_ACE_Flags flags = ACCESS_OBJECT_ACE_Flags.None;
                    ACE_TYPE aceType = header.AceType;

                    if (header.AceType == ACE_TYPE.ACCESS_ALLOWED_OBJECT_ACE_TYPE
                        || header.AceType == ACE_TYPE.ACCESS_DENIED_OBJECT_ACE_TYPE)
                    {
                        flags = (ACCESS_OBJECT_ACE_Flags)ObjectUtility.GetFieldValue(newAce, "Flags");
                        if ((flags & ACCESS_OBJECT_ACE_Flags.ACE_OBJECT_TYPE_PRESENT)
                                         != ACCESS_OBJECT_ACE_Flags.ACE_OBJECT_TYPE_PRESENT)
                        {
                            aceType = (header.AceType == ACE_TYPE.ACCESS_ALLOWED_OBJECT_ACE_TYPE)
                                ? ACE_TYPE.ACCESS_ALLOWED_ACE_TYPE
                                : ACE_TYPE.ACCESS_DENIED_ACE_TYPE;
                        }
                    }

                    if (((header.AceFlags & ACE_FLAGS.CONTAINER_INHERIT_ACE) != 0 && isContainerObject)
                        || ((header.AceFlags & ACE_FLAGS.OBJECT_INHERIT_ACE) != 0 && (!isContainerObject)))
                    {
                        bool retVal = DtypUtility.ComputeInheritedAcefromCreator(ref newAce, objectTypes);
                        if (retVal)
                        {
                            newAces.Add(newAce);
                        }
                    }
                }
            }
            #endregion

            #region Compute the inheritable ACL
            if (isContainerObject)
            {
                if (acl.Aces != null)
                {
                    foreach (object ace in acl.Aces)
                    {
                        object newAce = ObjectUtility.DeepClone(ace);
                        _ACE_HEADER header = (_ACE_HEADER)ObjectUtility.GetFieldValue(newAce, "Header");

                        if ((header.AceFlags & ACE_FLAGS.CONTAINER_INHERIT_ACE) == ACE_FLAGS.CONTAINER_INHERIT_ACE
                            || (header.AceFlags & ACE_FLAGS.OBJECT_INHERIT_ACE) == ACE_FLAGS.OBJECT_INHERIT_ACE)
                        {
                            header.AceFlags |= ACE_FLAGS.INHERIT_ONLY_ACE;
                            ObjectUtility.SetFieldValue(newAce, "Header", header);
                            //Append NewACE to NewACL
                            newAces.Add(newAce);
                        }
                    }
                }
            }
            #endregion

            newAcl.Aces = newAces.ToArray();
            newAcl.AceCount = (ushort)newAcl.Aces.Length;
            newAcl.AclSize = DtypUtility.CalculateAclSize(newAcl);

            return newAcl;
        }
        /// <summary>
        /// ComputeACL. MS-DTYP section 2.5.4.4
        /// </summary>
        /// <param name="computeType">Enumeration of COMPUTE_DACL and COMPUTE_SACL.</param>
        /// <param name="parentAcl">ACL from the parent security descriptor.</param>
        /// <param name="parentControl">Control flags from the parent security descriptor.</param>
        /// <param name="creatorAcl">ACL supplied in the security descriptor by the creator.</param>
        /// <param name="creatorControl">Control flags supplied in the security descriptor by the creator.</param>
        /// <param name="isContainerObject">TRUE if the object is a container; otherwise, FALSE.</param>
        /// <param name="objectTypes">Array of GUIDs for the object type being created.</param>
        /// <param name="autoInheritFlags">
        /// A set of bit flags that control how access control entries (ACEs) are 
        /// inherited from ParentDescriptor.
        /// </param>
        /// <param name="genericMapping">
        /// Mapping of generic permissions to resource manager-specific permissions supplied by the caller.
        /// </param>
        /// <param name="owner">Owner to use in substituting the CreatorOwner SID.</param>
        /// <param name="group">Group to use in substituting the CreatorGroup SID.</param>
        /// <param name="token">Token for default values.</param>
        /// <param name="computedControl">ComputedControl</param>
        /// <returns>Computed ACL</returns>
        public static _ACL? ComputeACL(
            AclComputeType computeType,
            _ACL? parentAcl,
            SECURITY_DESCRIPTOR_Control parentControl,
            _ACL? creatorAcl,
            SECURITY_DESCRIPTOR_Control creatorControl,
            bool isContainerObject,
            Guid[] objectTypes,
            SecurityDescriptorAutoInheritFlags autoInheritFlags,
            GenericMapping genericMapping,
            _SID owner,
            _SID group,
            Token token,
            out SECURITY_DESCRIPTOR_Control computedControl)
        {
            #region Pseudocode  v20110329

            //// The details of the algorithm to merge the parent ACL and the supplied ACL.
            //// The Control flags computed are slightly different based on whether it is the
            //// ACL in the DACL or the SACL field of the descriptor.
            //// The caller specifies whether it is a DACL or a SACL using the parameter,
            //// ComputeType.
            //Set ComputedACL to NULL
            //Set ComputedControl to NULL

            //CALL ContainsInheritableACEs WITH ParentACL RETURNING ParentHasInheritableACEs

            //IF ParentHasInheritableACEs = TRUE THEN

            //    // The Parent ACL has inheritable ACEs. The Parent ACL should be used if no Creator
            //    // ACL is supplied, or if the Creator ACL was supplied AND it is a default ACL based
            //    // on object type information

            //    IF(CreatorACL is not present) OR
            //      ((CreatorACL is present) AND
            //      (AutoInheritFlags contains DEFAULT_DESCRIPTOR_FOR_OBJECT))
            //    THEN
            //        // Use only the inherited ACEs from the parent.  First compute the ACL from the
            //        // parent ACL, then clean it up by resolving the generic mappings etc.

            //        CALL ComputeInheritedACLFromParent WITH
            //          ACL set to ParentACL,
            //          IsContainerObject set to IsContainerObject,
            //          ObjectTypes set to ObjectTypes

            //        RETURNING NextACL
            //        CALL PostProcessACL WITH
            //          ACL set to NextACL,
            //          CopyFilter set to CopyInheritedAces,
            //          Owner set to Owner,
            //          Group set to Group,
            //          GenericMapping set to GenericMapping

            //        RETURNING FinalACL

            //        Set ComputedACL to FinalACL
            //        RETURN
            //    ENDIF

            //IF ((CreatorACL is present) AND
            //  (AutoInheritFlags does not contain DEFAULT_DESCRIPTOR_FOR_OBJECT))
            //THEN
            //    // Since a creator ACL is present, and we’re not defaulting the
            //    // descriptor, determine which ACEs are inherited and compute the new ACL
            //    CALL PreProcessACLFromCreator WITH
            //       ACL set to CreatorACL
            //    RETURNING PreACL

            //    CALL ComputeInheritedACLFromCreator WITH
            //       ACL set to PreACL,
            //       IsContainerObject set to IsContainerObject,
            //       ObjectTypes set to ObjectTypes
            //    RETURNING TmpACL

            //    //  Special handling for DACL types of ACLs

            //    IF (ComputeType = DACL_COMPUTE) THEN

            //        // DACL-specific operations

            //        IF (CreatorControl does not have DACL_PROTECTED flag set) AND
            //           (AutoInheritFlags contains DACL_AUTO_INHERIT)
            //        THEN

            //            //  We’re not working from a protected DACL, and we’re supposed to
            //            //  allow automatic inheritance.  Compute the inherited ACEs from
            //            //  Parent ACL this time, and append that to the ACL that we’re building

            //            CALL ComputeInheritedACLFromParent WITH
            //              ACL set to ParentACL,
            //              IsContainerObject set to IsContainerObject,
            //              ObjectTypes set to ObjectTypes
            //            RETURNING InheritedParentACL

            //            Append InheritedParentACL.ACEs to TmpACL.ACE
            //            Set DACL_AUTO_INHERITED flag in ComputedControl

            //        ENDIF

            //    ENDIF  // DACL-Specific behavior
            //    IF (ComputeType = SACL_COMPUTE) THEN

            //        // Similar to the above, perform SACL-specific operations

            //        IF (CreatorControl does not have SACL_PROTECTED flag set) AND
            //           (AutoInheritFlags contains SACL_AUTO_INHERIT flag)
            //        THEN

            //            //  We’re not working from a protected SACL, and we’re supposed to
            //            //  allow automatic inheritance.  Compute the inherited ACEs from
            //            //  Parent ACL this time, and append that to the ACL that we’re building

            //            CALL ComputeInheritedACLFromParent WITH
            //              ACL set to ParentACL,
            //              IsContainerObject set to IsContainerObject,
            //              ObjectTypes set to ObjectTypes
            //            RETURNING InheritedParentACL

            //            Append InheritedParentACL.ACEs to TmpACL.ACE
            //            Set SACL_AUTO_INHERITED flag in ComputedControl

            //        ENDIF

            //    ENDIF  // SACL-Specific behavior

            //    CALL PostProcessACL WITH
            //      ACL set to TmpACL,
            //      CopyFilter set to CopyInheritedAces,
            //      Owner set to Owner,
            //      Group set to Group,
            //      GenericMapping set to GenericMapping
            //    RETURNING ProcessedACL

            //    Set ComputedACL to ProcessedACL
            //    RETURN
            //ENDIF  // CreatorACL is present

            //ELSE // ParentACL does not contain inheritable ACEs

            //    IF CreatorACL = NULL THEN
            //        // No ACL supplied for the object
            //        IF (ComputeType = DACL_COMPUTE) THEN
            //            Set TmpACL to Token.DefaultDACL
            //        ELSE
            //            // No default for SACL; left as NULL
            //        ENDIF

            //    ELSE
            //        // Explicit ACL was supplied for the object - either default or not.
            //        // In either case, use it for the object, since there are no inherited ACEs.
            //        CALL PreProcessACLFromCreator WITH CreatorACL
            //        RETURNING TmpACL
            //    ENDIF

            //    CALL PostProcessACL WITH
            //      ACL set to TmpACL,
            //      CopyFilter set to CopyAllAces,
            //      Owner set to Owner,
            //      Group set to Group,
            //      GenericMapping set to GenericMapping

            //        RETURNING ProcessedACL
            //        Set ComputedACL to ProcessedACL

            //ENDIF
            //// END ComputeACL

            #endregion

            _ACL? computedACL = null;
            computedControl = SECURITY_DESCRIPTOR_Control.None;
            _ACL tmpAcl = new _ACL();
            _ACL preAcl = new _ACL();

            if (parentAcl != null && ContainsInheritableACEs(parentAcl.Value))
            {
                // ParentACL contains inheritable ACEs
                if ((creatorAcl == null) || ((creatorAcl != null) && (autoInheritFlags
                    & SecurityDescriptorAutoInheritFlags.DEFAULT_DESCRIPTOR_FOR_OBJECT)
                    == SecurityDescriptorAutoInheritFlags.DEFAULT_DESCRIPTOR_FOR_OBJECT))
                {
                    // Use only the inherited ACEs from the parent
                    _ACL nextAcl = ComputeInheritedACLfromParent(parentAcl.Value, isContainerObject, objectTypes);
                    _ACL finalAcl = PostProcessACL(nextAcl, CopyFilter.CopyInheritedAces, owner, group, genericMapping);
                    computedACL = finalAcl;
                }
                else
                {
                    preAcl = PreProcessACLfromCreator(creatorAcl.Value);
                    tmpAcl = ComputeInheritedACLfromCreator(preAcl, isContainerObject, objectTypes);

                    _ACL? inheritedAcl = null;
                    if ((computeType == AclComputeType.COMPUTE_DACL)
                        && (creatorControl & SECURITY_DESCRIPTOR_Control.DACLProtected)
                            == SECURITY_DESCRIPTOR_Control.None
                        && (autoInheritFlags & SecurityDescriptorAutoInheritFlags.DACL_AUTO_INHERIT)
                            == SecurityDescriptorAutoInheritFlags.DACL_AUTO_INHERIT)
                    {
                        // Compute the inherited ACEs from the parent
                        inheritedAcl = ComputeInheritedACLfromParent(
                            parentAcl.Value,
                            isContainerObject,
                            objectTypes);

                        computedControl |= SECURITY_DESCRIPTOR_Control.DACLAutoInherited;
                    }
                    else if ((computeType == AclComputeType.COMPUTE_SACL)
                        && (creatorControl & SECURITY_DESCRIPTOR_Control.SACLProtected)
                            == SECURITY_DESCRIPTOR_Control.None
                        && (autoInheritFlags & SecurityDescriptorAutoInheritFlags.SACL_AUTO_INHERIT)
                            == SecurityDescriptorAutoInheritFlags.SACL_AUTO_INHERIT)
                    {
                        // Compute the inherited ACEs from the parent
                        inheritedAcl = ComputeInheritedACLfromParent(
                            parentAcl.Value,
                            isContainerObject,
                            objectTypes);

                        computedControl |= SECURITY_DESCRIPTOR_Control.SACLAutoInherited;
                    }
                    if (inheritedAcl != null)
                    {
                        List<object> tmpAces = new List<object>();
                        tmpAces.AddRange(tmpAcl.Aces);
                        tmpAces.AddRange(inheritedAcl.Value.Aces);
                        tmpAcl.Aces = tmpAces.ToArray();
                        tmpAcl.AceCount = (ushort)tmpAcl.Aces.Length;
                        tmpAcl.AclSize = DtypUtility.CalculateAclSize(tmpAcl);
                    }

                    computedACL = PostProcessACL(tmpAcl, CopyFilter.CopyInheritedAces, owner, group, genericMapping);
                }
            }
            else
            {
                // ParentACL does not contain inheritable ACEs
                if (creatorAcl == null)
                {
                    if (computeType == AclComputeType.COMPUTE_DACL)
                    {
                        tmpAcl = token.DefaultDACL;
                    }
                    else
                    {
                        //No default for SACL;left as NULL
                        return null;
                    }
                }
                else
                {
                    // Explicit ACL was supplied for the object - either default or not.
                    // In either case, use it for the object, since there are no inherited ACEs.
                    tmpAcl = PreProcessACLfromCreator(creatorAcl.Value);
                }
                computedACL = PostProcessACL(tmpAcl, CopyFilter.CopyAllAces, owner, group, genericMapping);
            }

            if (computedACL != null)
            {
                computedControl |= ((computeType == AclComputeType.COMPUTE_DACL)
                    ? SECURITY_DESCRIPTOR_Control.DACLPresent
                    : SECURITY_DESCRIPTOR_Control.SACLPresent);
            }
            return computedACL;
        }