/// <summary>
 /// Constructor from a token default DACL and ownership values.
 /// </summary>
 /// <param name="token">The token to use for its default DACL</param>
 public SecurityDescriptor(NtToken token) : this()
 {
     Owner = new SecurityDescriptorSid(token.Owner, true);
     Group = new SecurityDescriptorSid(token.PrimaryGroup, true);
     Dacl  = token.DefaultDacl;
     if (token.IntegrityLevel < TokenIntegrityLevel.Medium)
     {
         Sacl = new Acl();
         Sacl.Add(new Ace(AceType.MandatoryLabel, AceFlags.None, 1, token.IntegrityLevelSid.Sid));
     }
 }
        /// <summary>
        /// Gets an indication if this ACL is canonical.
        /// </summary>
        /// <remarks>Canonical basically means that deny ACEs are before allow ACEs.</remarks>
        /// <returns>True if the ACL is canonical.</returns>
        public bool IsCanonical()
        {
            Acl acl = Canonicalize();

            if (acl.Count != Count)
            {
                return(false);
            }

            for (int i = 0; i < acl.Count; ++i)
            {
                if (this[i] != acl[i])
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// Gets an indication if this ACL is canonical.
        /// </summary>
        /// <remarks>Canonical means that deny ACEs are before allow ACEs.</remarks>
        /// <param name="dacl">True to canonicalize a DACL, otherwise a SACL.</param>
        /// <returns>True if the ACL is canonical.</returns>
        public bool IsCanonical(bool dacl)
        {
            Acl acl = Clone();

            acl.Canonicalize(dacl);
            if (acl.Count != Count)
            {
                return(false);
            }

            for (int i = 0; i < acl.Count; ++i)
            {
                if (!ReferenceEquals(this[i], acl[i]))
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// Gets an indication if this ACL is canonical.
        /// </summary>
        /// <remarks>Canonical means that deny ACEs are before allow ACEs.</remarks>
        /// <param name="dacl">True to canonicalize a DACL, otherwise a SACL.</param>
        /// <returns>True if the ACL is canonical.</returns>
        public bool IsCanonical(bool dacl)
        {
            Acl acl       = Clone();
            var ace_order = acl.ToArray();

            acl.Canonicalize(dacl);
            if (acl.Count != ace_order.Length)
            {
                return(false);
            }

            for (int i = 0; i < acl.Count; ++i)
            {
                if (!ReferenceEquals(ace_order[i], acl[i]))
                {
                    return(false);
                }
            }
            return(true);
        }
        /// <summary>
        /// Canonicalize the ACL (for use on DACLs only).
        /// </summary>
        /// <remarks>This isn't a general purpose algorithm, for example it doesn't worry much about object ordering.
        /// Also it can be lossy, if it doesn't understand an ACE type it will drop it.</remarks>
        /// <returns>The canonical ACL.</returns>
        public Acl Canonicalize()
        {
            List <Ace> access_denied  = new List <Ace>();
            List <Ace> access_allowed = new List <Ace>();
            List <Ace> inherited      = new List <Ace>();

            foreach (Ace ace in this)
            {
                if ((ace.Flags & AceFlags.Inherited) == AceFlags.Inherited)
                {
                    inherited.Add(ace);
                }
                else
                {
                    switch (ace.Type)
                    {
                    case AceType.Allowed:
                    case AceType.AllowedObject:
                        access_allowed.Add(ace);
                        break;

                    case AceType.Denied:
                    case AceType.DeniedObject:
                        access_denied.Add(ace);
                        break;
                    }
                }
            }

            Acl ret = new Acl();

            ret.AddRange(access_denied);
            ret.AddRange(access_allowed);
            ret.AddRange(inherited);
            return(ret);
        }