ACL.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / clr / src / BCL / System / Security / AccessControl / ACL.cs / 1 / ACL.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Classes:  Access Control List (ACL) family of classes 
**
** 
===========================================================*/

using System;
using System.Collections; 
using System.Security.Principal;
 
namespace System.Security.AccessControl 
{
 
    public sealed class AceEnumerator : IEnumerator
    {
        #region Private Members
 
        //
        // Current enumeration index 
        // 

        private int _current; 

        //
        // Parent collection
        // 

        private readonly GenericAcl _acl; 
 
        #endregion
 
        #region Constructors

        internal AceEnumerator( GenericAcl collection )
        { 
            if ( collection == null )
            { 
                throw new ArgumentNullException( "collection" ); 
            }
 
            _acl = collection;
            Reset();
        }
 
        #endregion
 
        #region IEnumerator Interface 

        object IEnumerator.Current 
        {
            get
            {
                if ( _current == -1 || 
                    _current >= _acl.Count )
                { 
                    throw new InvalidOperationException( Environment.GetResourceString( "Arg_InvalidOperationException" )); 
                }
 
                return _acl[_current];
            }
        }
 
        public GenericAce Current
        { 
            get { return (( IEnumerator )this ).Current as GenericAce; } 
        }
 
        public bool MoveNext()
        {
            _current++;
 
            return ( _current < _acl.Count );
        } 
 
        public void Reset()
        { 
            _current = -1;
        }

        #endregion 
    }
 
 
    public abstract class GenericAcl : ICollection
    { 
        #region Constructors

        protected GenericAcl()
        { } 

        #endregion 
 
        #region Public Constants
 
        //
        // ACL revisions
        //
 
        public static readonly byte AclRevision = 2;
        public static readonly byte AclRevisionDS = 4; 
 
        //
        // Maximum length of a binary representation of the ACL 
        //

        public static readonly int MaxBinaryLength = ushort.MaxValue;
 
        #endregion
 
        #region Protected Members 

        // 
        //  Define an ACL and the ACE format.  The structure of an ACL header
        //  followed by one or more ACEs.  Pictorally the structure of an ACL header
        //  is as follows:
        // 
        //       3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
        //       1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 
        //      +-------------------------------+---------------+---------------+ 
        //      |            AclSize            |      Sbz1     |  AclRevision  |
        //      +-------------------------------+---------------+---------------+ 
        //      |              Sbz2             |           AceCount            |
        //      +-------------------------------+-------------------------------+
        //
 
        internal const int HeaderLength = 8;
 
        #endregion 

        #region Public Properties 

        //
        // Returns the revision of the ACL
        // 

        public abstract byte Revision { get; } 
 
        //
        // Returns the length of the binary representation of the ACL 
        //

        public abstract int BinaryLength { get; }
 
        //
        // Retrieves the ACE at a specified index 
        // 

        public abstract GenericAce this[int index] { get; set; } 

        #endregion

        #region Public Methods 

        // 
        // Returns the binary representation of the ACL 
        //
 
        public abstract void GetBinaryForm( byte[] binaryForm, int offset );

        #endregion
 
        #region ICollection Implementation
 
        void ICollection.CopyTo( Array array, int index ) 
        {
            if ( array == null ) 
            {
                throw new ArgumentNullException( "array" );
            }
 
            if ( array.Rank != 1 )
            { 
                throw new RankException( Environment.GetResourceString( "Rank_MultiDimNotSupported" )); 
            }
 
            if ( index < 0 )
            {
                throw new ArgumentOutOfRangeException(
                    "index", 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
            } 
            else if ( array.Length - index < Count ) 
            {
                throw new ArgumentOutOfRangeException( 
                    "array",
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
            }
 
            for ( int i = 0; i < Count; i++ )
            { 
                array.SetValue( this[i], index + i ); 
            }
        } 

        public void CopyTo( GenericAce[] array, int index )
        {
            (( ICollection )this ).CopyTo( array, index ); 
        }
 
        public abstract int Count { get; } 

        public bool IsSynchronized 
        {
            get { return false; }
        }
 
        public object SyncRoot
        { 
            get { return null; } 
        }
 
        #endregion

        #region IEnumerable Implementation
 
        IEnumerator IEnumerable.GetEnumerator()
        { 
            return new AceEnumerator( this ); 
        }
 
        public AceEnumerator GetEnumerator()
        {
            return (( IEnumerable )this ).GetEnumerator() as AceEnumerator;
        } 

        #endregion 
    } 

 
    public sealed class RawAcl : GenericAcl
    {
        #region Private Members
 
        private byte _revision;
        private ArrayList _aces; 
        private int _binaryLength = HeaderLength; 

        #endregion 

        #region Private Methods

        private static void VerifyHeader( byte[] binaryForm, int offset, out byte revision, out int count, out int length ) 
        {
            if ( binaryForm == null ) 
            { 
                throw new ArgumentNullException( "binaryForm" );
            } 

            if ( offset < 0 )
            {
                // 
                // Offset must not be negative
                // 
 
                throw new ArgumentOutOfRangeException(
                    "offset", 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
            }

            if ( binaryForm.Length - offset < HeaderLength ) 
            {
                // 
                // We expect at least the ACL header 
                //
 
                goto InvalidParameter;
            }

            revision = binaryForm[offset + 0]; 
            length = ( binaryForm[offset + 2] << 0 ) + ( binaryForm[offset + 3] << 8 );
            count = ( binaryForm[offset + 4] << 0 ) + ( binaryForm[offset + 5] << 8 ); 
 
            if ( length > binaryForm.Length - offset )
            { 
                //
                // Reported length of ACL ought to be no longer than the
                // length of the buffer passed in
                // 

                goto InvalidParameter; 
            } 

            return; 

        InvalidParameter:

            throw new ArgumentOutOfRangeException( 
                "binaryForm",
                Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" )); 
        } 

        private void MarshalHeader( byte[] binaryForm, int offset ) 
        {
            if ( binaryForm == null )
            {
                throw new ArgumentNullException( "binaryForm" ); 
            }
            else if ( offset < 0 ) 
            { 
                throw new ArgumentOutOfRangeException(
                    "offset", 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
            }
            else if ( BinaryLength > MaxBinaryLength )
            { 
                throw new InvalidOperationException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
            } 
            else if ( binaryForm.Length - offset < BinaryLength ) 
            {
                throw new ArgumentOutOfRangeException( 
                    "binaryForm",
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
            }
 
            binaryForm[offset + 0] = Revision;
            binaryForm[offset + 1] = 0; 
            binaryForm[offset + 2] = ( byte )( BinaryLength >> 0 ); 
            binaryForm[offset + 3] = ( byte )( BinaryLength >> 8 );
            binaryForm[offset + 4] = ( byte )( Count >> 0 ); 
            binaryForm[offset + 5] = ( byte )( Count >> 8 );
            binaryForm[offset + 6] = 0;
            binaryForm[offset + 7] = 0;
        } 

        internal void SetBinaryForm( byte[] binaryForm, int offset ) 
        { 
            int count, length;
 
            //
            // Verify the header and extract interesting header info
            //
 
            VerifyHeader( binaryForm, offset, out _revision, out count, out length );
 
            // 
            // Remember how far ahead the binary form should end (for later verification)
            // 

            length += offset;

            offset += HeaderLength; 

            _aces = new ArrayList( count ); 
            _binaryLength = HeaderLength; 

            for ( int i = 0; i < count; i++ ) 
            {
                GenericAce ace = GenericAce.CreateFromBinaryForm( binaryForm, offset );

                int aceLength = ace.BinaryLength; 

                if ( _binaryLength + aceLength > MaxBinaryLength ) 
                { 
                    //
                    // The ACE was too long - it would overflow the ACL maximum length 
                    //

                    throw new ArgumentException(
                        Environment.GetResourceString( "ArgumentException_InvalidAclBinaryForm" ), 
                        "binaryForm" );
                } 
 
                _aces.Add( ace );
 
                if ( aceLength % 4 != 0 )
                {
                    //
                    // This indicates a bug in one of the ACE classes. 
                    // Binary length of an ace must ALWAYS be divisible by 4.
                    // 
 
                    BCLDebug.Assert( false, "aceLength % 4 != 0" );
                    throw new SystemException(); 
                }

                _binaryLength += aceLength;
 
                if ( _revision == AclRevisionDS )
                { 
                    // 
                    // Increment the offset by the advertised length rather than the
                    // actual binary length. (Ideally these two should match, but for 
                    // object aces created through ADSI, the actual length is 32 bytes
                    // less than the allocated size of the ACE. This is a bug in ADSI.)
                    //
                    offset += (binaryForm[offset + 2] << 0) + (binaryForm[offset + 3] << 8); 
                }
                else 
                { 
                    offset += aceLength;
                } 

                //
                // Verify that no more than the advertised length of the ACL was consumed
                // 

                if ( offset > length ) 
                { 
                    goto InvalidParameter;
                } 
            }

            return;
 
        InvalidParameter:
 
            throw new ArgumentException( 
                Environment.GetResourceString( "ArgumentException_InvalidAclBinaryForm" ),
                "binaryForm" ); 
        }

        #endregion
 
        #region Constructors
 
        // 
        // Creates an empty ACL
        // 

        public RawAcl( byte revision, int capacity )
            : base()
        { 
            _revision = revision;
            _aces = new ArrayList( capacity ); 
        } 

        // 
        // Creates an ACL from its binary representation
        //

        public RawAcl( byte[] binaryForm, int offset ) 
            : base()
        { 
            SetBinaryForm( binaryForm, offset ); 
        }
 
        #endregion

        #region Public Properties
 
        //
        // Returns the revision of the ACL 
        // 

        public override byte Revision 
        {
            get { return _revision; }
        }
 
        //
        // Returns the number of ACEs in the ACL 
        // 

        public override int Count 
        {
            get { return _aces.Count; }
        }
 
        //
        // Returns the length of the binary representation of the ACL 
        // 

        public override int BinaryLength 
        {
            get { return _binaryLength; }
        }
 
        #endregion
 
        #region Public Methods 

        // 
        // Returns the binary representation of the ACL
        //

        public override void GetBinaryForm( byte[] binaryForm, int offset ) 
        {
            // 
            // Populate the header 
            //
 
            MarshalHeader( binaryForm, offset );
            offset += HeaderLength;

            for ( int i = 0; i < Count; i++ ) 
            {
                GenericAce ace = _aces[i] as GenericAce; 
 
                ace.GetBinaryForm( binaryForm, offset );
 
                int aceLength = ace.BinaryLength;

                if ( aceLength % 4 != 0 )
                { 
                    //
                    // This indicates a bug in one of the ACE classes. 
                    // Binary length of an ace must ALWAYS be divisible by 4. 
                    //
 
                    BCLDebug.Assert( false, "aceLength % 4 != 0" );
                    throw new SystemException();
                }
 
                offset += aceLength;
            } 
        } 

        // 
        // Return an ACE at a particular index
        // The ACE is not cloned prior to returning, enabling the caller
        // to modify the ACE in place (a potentially dangerous operation)
        // 

        public override GenericAce this[int index] 
        { 
            get
            { 
                return _aces[index] as GenericAce;
            }

            set 
            {
                if ( value == null ) 
                { 
                    throw new ArgumentNullException( "value" );
                } 

                if ( value.BinaryLength % 4 != 0 )
                {
                    // 
                    // This indicates a bug in one of the ACE classes.
                    // Binary length of an ace must ALWAYS be divisible by 4. 
                    // 

                    BCLDebug.Assert( false, "aceLength % 4 != 0" ); 
                    throw new SystemException();
                }

                int newBinaryLength = BinaryLength - ( index < _aces.Count ? ( _aces[index] as GenericAce ).BinaryLength : 0 ) + value.BinaryLength; 

                if ( newBinaryLength > MaxBinaryLength ) 
                { 
                    throw new OverflowException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
                } 

                _aces[index] = value;

                _binaryLength = newBinaryLength; 
            }
        } 
 
        //
        // Adds an ACE at the specified index 
        //

        public void InsertAce( int index, GenericAce ace )
        { 
            if ( ace == null )
            { 
                throw new ArgumentNullException( "ace" ); 
            }
 
            if ( _binaryLength + ace.BinaryLength > MaxBinaryLength )
            {
                throw new OverflowException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
            } 

            _aces.Insert( index, ace ); 
            _binaryLength += ace.BinaryLength; 
        }
 
        //
        // Removes an ACE at the specified index
        //
 
        public void RemoveAce( int index )
        { 
            GenericAce ace = _aces[index] as GenericAce; 
            _aces.RemoveAt( index );
            _binaryLength -= ace.BinaryLength; 
        }

        #endregion
    } 

 
    public abstract class CommonAcl : GenericAcl 
    {
        #region Add/Remove Logic Support 

        [Flags]
        private enum AF    // ACE flags
        { 
            CI        = 0x8,    // container inherit
            OI        = 0x4,    // object inherit 
            IO        = 0x2,    // inherit only 
            NP        = 0x1,    // no propagate inherit
            Invalid   = NP,     // not a valid combination of flags 
        }

        [Flags]
        private enum PM    // Propagation matrix 
        {
            F         = 0x10,    // folder 
            CF        = 0x08,    // child folder 
            CO        = 0x04,    // child object
            GF        = 0x02,    // grandchild folder 
            GO        = 0x01,    // grandchild object
            Invalid   = GO,      // not a valid combination of flags
        }
 
        private static PM[] AFtoPM;    // AceFlags-to-Propagation conversion matrix
        private static AF[] PMtoAF;    // Propagation-to-AceFlags conversion matrix 
 
        static CommonAcl()
        { 
            AFtoPM = new PM[16];

            for ( int i = 0; i < AFtoPM.Length; i++ )
            { 
                AFtoPM[i] = PM.Invalid;
            } 
 
            //
            // This table specifies what effect various combinations of inheritance bits 
            // have on how ACEs are inherited onto child objects
            // Important: Not all combinations of inheritance bits are valid
            //
 
            AFtoPM[( int )(   0   |   0   |   0   |   0   )] = PM.F |   0   |   0   |   0   |   0   ;
            AFtoPM[( int )(   0   | AF.OI |   0   |   0   )] = PM.F |   0   | PM.CO |   0   | PM.GO ; 
            AFtoPM[( int )(   0   | AF.OI |   0   | AF.NP )] = PM.F |   0   | PM.CO |   0   |   0   ; 
            AFtoPM[( int )(   0   | AF.OI | AF.IO |   0   )] =   0  |   0   | PM.CO |   0   | PM.GO ;
            AFtoPM[( int )(   0   | AF.OI | AF.IO | AF.NP )] =   0  |   0   | PM.CO |   0   |   0   ; 
            AFtoPM[( int )( AF.CI |   0   |   0   |   0   )] = PM.F | PM.CF |   0   | PM.GF |   0   ;
            AFtoPM[( int )( AF.CI |   0   |   0   | AF.NP )] = PM.F | PM.CF |   0   |   0   |   0   ;
            AFtoPM[( int )( AF.CI |   0   | AF.IO |   0   )] =   0  | PM.CF |   0   | PM.GF |   0   ;
            AFtoPM[( int )( AF.CI |   0   | AF.IO | AF.NP )] =   0  | PM.CF |   0   |   0   |   0   ; 
            AFtoPM[( int )( AF.CI | AF.OI |   0   |   0   )] = PM.F | PM.CF | PM.CO | PM.GF | PM.GO ;
            AFtoPM[( int )( AF.CI | AF.OI |   0   | AF.NP )] = PM.F | PM.CF | PM.CO |   0   |   0   ; 
            AFtoPM[( int )( AF.CI | AF.OI | AF.IO |   0   )] =   0  | PM.CF | PM.CO | PM.GF | PM.GO ; 
            AFtoPM[( int )( AF.CI | AF.OI | AF.IO | AF.NP )] =   0  | PM.CF | PM.CO |   0   |   0   ;
 
            PMtoAF = new AF[32];

            for ( int i = 0; i < PMtoAF.Length; i++ )
            { 
                PMtoAF[i] = AF.Invalid;
            } 
 
            //
            // This table is a reverse lookup table of the AFtoPM table 
            // Given how inheritance is applied to child objects and containers,
            // it helps figure out whether that pattern is expressible using
            // the four ACE inheritance bits
            // 

            PMtoAF[( int )( PM.F |   0   |   0   |   0   |   0   )] =    0   |   0   |   0   |   0   ; 
            PMtoAF[( int )( PM.F |   0   | PM.CO |   0   | PM.GO )] =    0   | AF.OI |   0   |   0   ; 
            PMtoAF[( int )( PM.F |   0   | PM.CO |   0   |   0   )] =    0   | AF.OI |   0   | AF.NP ;
            PMtoAF[( int )(   0  |   0   | PM.CO |   0   | PM.GO )] =    0   | AF.OI | AF.IO |   0   ; 
            PMtoAF[( int )(   0  |   0   | PM.CO |   0   |   0   )] =    0   | AF.OI | AF.IO | AF.NP ;
            PMtoAF[( int )( PM.F | PM.CF |   0   | PM.GF |   0   )] =  AF.CI |   0   |   0   |   0   ;
            PMtoAF[( int )( PM.F | PM.CF |   0   |   0   |   0   )] =  AF.CI |   0   |   0   | AF.NP ;
            PMtoAF[( int )(   0  | PM.CF |   0   | PM.GF |   0   )] =  AF.CI |   0   | AF.IO |   0   ; 
            PMtoAF[( int )(   0  | PM.CF |   0   |   0   |   0   )] =  AF.CI |   0   | AF.IO | AF.NP ;
            PMtoAF[( int )( PM.F | PM.CF | PM.CO | PM.GF | PM.GO )] =  AF.CI | AF.OI |   0   |   0   ; 
            PMtoAF[( int )( PM.F | PM.CF | PM.CO |   0   |   0   )] =  AF.CI | AF.OI |   0   | AF.NP ; 
            PMtoAF[( int )(   0  | PM.CF | PM.CO | PM.GF | PM.GO )] =  AF.CI | AF.OI | AF.IO |   0   ;
            PMtoAF[( int )(   0  | PM.CF | PM.CO |   0   |   0   )] =  AF.CI | AF.OI | AF.IO | AF.NP ; 
        }

        //
        // Canonicalizes AceFlags into a form that the mapping tables understand 
        //
 
        private static AF AFFromAceFlags( AceFlags aceFlags, bool isDS ) 
        {
            AF af = 0; 

            if (( aceFlags & AceFlags.ContainerInherit ) != 0)
            {
                af |= AF.CI; 
            }
 
            // 
            // ObjectInherit applies only to regular aces not object aces
            // so it can be ignored in the object aces case 
            //
            if (( !isDS ) && (( aceFlags & AceFlags.ObjectInherit ) != 0 ))
            {
                af |= AF.OI; 
            }
 
            if (( aceFlags & AceFlags.InheritOnly ) != 0 ) 
            {
                af |= AF.IO; 
            }

            if (( aceFlags & AceFlags.NoPropagateInherit ) != 0 )
            { 
                af |= AF.NP;
            } 
 
            return af;
        } 

        //
        // Converts lookup table representation of AceFlags into the "public" form
        // 

        private static AceFlags AceFlagsFromAF( AF af, bool isDS ) 
        { 
            AceFlags aceFlags = 0;
 
            if (( af & AF.CI ) != 0 )
            {
                aceFlags |= AceFlags.ContainerInherit;
            } 

            // 
            // ObjectInherit applies only to regular aces not object aces 
            // so it can be ignored in the object aces case
            // 
            if (( !isDS ) && (( af & AF.OI ) != 0 ))
            {
                aceFlags |= AceFlags.ObjectInherit;
            } 

            if (( af & AF.IO ) != 0 ) 
            { 
                aceFlags |= AceFlags.InheritOnly;
            } 

            if (( af & AF.NP ) != 0 )
            {
                aceFlags |= AceFlags.NoPropagateInherit; 
            }
 
            return aceFlags; 
        }
 
        //
        // Implements the merge of inheritance bits during the 'ADD' operation
        //
 
        private static bool MergeInheritanceBits( AceFlags left, AceFlags right, bool isDS, out AceFlags result )
        { 
            result = 0; 

            AF leftAF = AFFromAceFlags( left, isDS ); 
            AF rightAF = AFFromAceFlags( right, isDS );

            PM leftPM = AFtoPM[(int)leftAF];
            PM rightPM = AFtoPM[(int)rightAF]; 

            if ( leftPM == PM.Invalid || rightPM == PM.Invalid ) 
            { 
                return false; // incorrect ACE flags?
            } 

            PM resultPM = leftPM | rightPM;
            AF resultAF = PMtoAF[( int )resultPM];
 
            if ( resultAF == AF.Invalid )
            { 
                return false; 
            }
            else 
            {
                result = AceFlagsFromAF( resultAF, isDS );
                return true;
            } 
        }
 
        private static bool RemoveInheritanceBits( AceFlags existing, AceFlags remove, bool isDS, out AceFlags result, out bool total ) 
        {
            result = 0; 
            total = false;

            AF leftAF = AFFromAceFlags( existing, isDS );
            AF rightAF = AFFromAceFlags( remove, isDS ); 

            PM leftPM = AFtoPM[( int )leftAF]; 
            PM rightPM = AFtoPM[( int )rightAF]; 

            if ( leftPM == PM.Invalid || rightPM == PM.Invalid ) 
            {
                return false; // incorrect ACE flags?
            }
 
            PM resultPM;
            unchecked { resultPM = leftPM & ~rightPM; } 
 
            //
            // If the resulting propagation matrix is zero, 
            // communicate back the fact that removal is "total"
            //

            if ( resultPM == 0 ) 
            {
                total = true; 
                return true; 
            }
 
            AF resultAF = PMtoAF[( int )resultPM];

            if ( resultAF == AF.Invalid )
            { 
                return false;
            } 
            else 
            {
                result = AceFlagsFromAF( resultAF, isDS ); 
                return true;
            }
        }
 
        #endregion
 
        #region Private Members 

        private RawAcl _acl; 
        private bool _isDirty = false;
        private readonly bool _isCanonical;
        private readonly bool _isContainer;
 
        //
        // To distinguish between a directory object acl and other common acls. 
        // 

        private readonly bool _isDS; 

        #endregion

        #region Private Methods 

        private void CanonicalizeIfNecessary() 
        { 
            if ( _isDirty )
            { 
                Canonicalize( false, this is DiscretionaryAcl );
                _isDirty = false;
            }
        } 

        private enum ComparisonResult 
        { 
            LessThan,
            EqualTo, 
            GreaterThan,
        }

        // 
        // Compares two discretionary ACEs and returns
        //    LessThan if ace1 < ace2 
        //    EqualTo if ace1 == ace2 
        //    GreaterThan if ace1 > ace2
        // 
        // The order is:
        //        - explicit Access Denied ACEs
        //          [regular aces first, then object aces]
        //        - explicit Access Allowed ACEs 
        //          [regular aces first, then object aces]
        //        - inherited ACEs (in the original order ) 
        //        - user-defined ACEs (in the original order ) 
        //
 
        private static int DaclAcePriority( GenericAce ace)
        {
            int result;
            AceType type = ace.AceType; 

            if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
            { 
                //
                // inherited aces are at the end as a group 
                //

                result = 2 * ushort.MaxValue + ace._indexInAcl;
            } 
            else if ( type == AceType.AccessDenied ||
                type == AceType.AccessDeniedCallback ) 
            { 
                result = 0;
            } 
            else if ( type == AceType.AccessDeniedObject ||
                type == AceType.AccessDeniedCallbackObject )
            {
                result = 1; 
            }
            else if ( type == AceType.AccessAllowed || 
                type == AceType.AccessAllowedCallback ) 
            {
                result = 2; 
            }
            else if ( type == AceType.AccessAllowedObject ||
                type == AceType.AccessAllowedCallbackObject )
            { 
                result = 3;
            } 
            else 
            {
                // 
                // custom aces are at the second group
                //
                result = ushort.MaxValue + ace._indexInAcl;
            } 

            return result; 
        } 

        // 
        // Compares two system ACEs and returns
        //    LessThan if ace1 < ace2
        //    EqualTo if ace1 == ace2
        //    GreaterThan if ace1 > ace2 
        //
        // The order is: 
        //        - explicit audit or alarm ACEs 
        //        - explicit audit or alarm object ACEs
        //        - inherited ACEs (in the original order ) 
        //        - user-defined ACEs (in the original order )
        //

        private static int SaclAcePriority( GenericAce ace ) 
        {
            int result; 
            AceType type = ace.AceType; 

            if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
            {
                result = 2 * ushort.MaxValue + ace._indexInAcl;
            }
            else if ( type == AceType.SystemAudit || 
                type == AceType.SystemAlarm ||
                type == AceType.SystemAuditCallback || 
                type == AceType.SystemAlarmCallback ) 
            {
                result = 0; 
            }
            else if ( type == AceType.SystemAuditObject ||
                type == AceType.SystemAlarmObject ||
                type == AceType.SystemAuditCallbackObject || 
                type == AceType.SystemAlarmCallbackObject )
            { 
                result = 1; 
            }
            else 
            {
                result = ushort.MaxValue + ace._indexInAcl;
            }
 
            return result;
        } 
 
        private static ComparisonResult CompareAces( GenericAce ace1, GenericAce ace2, bool isDacl )
        { 
            int ace1Priority = isDacl ? DaclAcePriority( ace1 ) : SaclAcePriority( ace1 );
            int ace2Priority = isDacl ? DaclAcePriority( ace2 ) : SaclAcePriority( ace2 );

            if ( ace1Priority < ace2Priority ) 
            {
                return ComparisonResult.LessThan; 
            } 
            else if ( ace1Priority > ace2Priority )
            { 
                return ComparisonResult.GreaterThan;
            }
            else
            { 
                KnownAce k_ace1 = ace1 as KnownAce;
                KnownAce k_ace2 = ace2 as KnownAce; 
 
                if ( k_ace1 != null && k_ace2 != null )
                { 
                    int result = k_ace1.SecurityIdentifier.CompareTo( k_ace2.SecurityIdentifier );

                    if ( result < 0 )
                    { 
                        return ComparisonResult.LessThan;
                    } 
                    else if ( result > 0 ) 
                    {
                        return ComparisonResult.GreaterThan; 
                    }
                }

                return ComparisonResult.EqualTo; 
            }
        } 
 
        private void QuickSort( int left, int right, bool isDacl )
        { 
            GenericAce pivot;
            int leftHold, rightHold;
            int pivotIndex;
 
            if ( left >= right )
            { 
                return; 
            }
 
            leftHold = left;
            rightHold = right;

            pivot = _acl[left]; 
            pivotIndex = left;
 
            while ( left < right ) 
            {
//              while (( _acl[right] >= pivot ) && ( left < right )) 
                while (( ComparisonResult.LessThan != CompareAces( _acl[right], pivot, isDacl ) ) && ( left < right ))
                {
                    right--;
                } 

                if ( left != right ) 
                { 
                    _acl[left] = _acl[right];
                    left++; 
                }

//              while (( _acl[left] <= pivot ) && ( left < right ))
                while (( ComparisonResult.GreaterThan != CompareAces( _acl[left], pivot, isDacl ) ) && ( left < right )) 
                {
                    left++; 
                } 

                if ( left != right ) 
                {
                    _acl[right] = _acl[left];
                    right--;
                } 
            }
 
            _acl[left] = pivot; 
            pivotIndex = left;
            left = leftHold; 
            right = rightHold;

            if ( left < pivotIndex )
            { 
                QuickSort( left, pivotIndex - 1, isDacl );
            } 
 
            if ( right > pivotIndex )
            { 
                QuickSort( pivotIndex + 1, right, isDacl );
            }
        }
 
        //
        // Inspects the ACE, modifies it by stripping away unnecessary or 
        // meaningless flags. 
        // Returns 'true' if the ACE should remain in the ACL, 'false' otherwise
        // 

        private bool InspectAce( ref GenericAce ace, bool isDacl )
        {
            const AceFlags AuditFlags = 
                AceFlags.SuccessfulAccess |
                AceFlags.FailedAccess; 
 
            const AceFlags InheritFlags =
                AceFlags.ObjectInherit | 
                AceFlags.ContainerInherit |
                AceFlags.NoPropagateInherit |
                AceFlags.InheritOnly;
 
            //
            // Any ACE without at least one bit set in the access mask can be removed 
            // 

            KnownAce knownAce = ace as KnownAce; 

            if ( knownAce != null )
            {
                if ( knownAce.AccessMask == 0 ) 
                {
                    return false; 
                } 
            }
 
            if ( !IsContainer )
            {
                //
                // On a leaf object ACL, inheritance bits are meaningless. 
                // Specifically, an ACE marked "inherit-only" will never participate
                // in access control and can be removed. 
                // Similarly, an ACE marked "container-inherit", "no-propagate-inherit" 
                // or "object-inherit" can have those bits cleared since they carry
                // no meaning. 
                //

                if (( ace.AceFlags & AceFlags.InheritOnly ) != 0 )
                { 
                    return false;
                } 
 
                if (( ace.AceFlags & InheritFlags ) != 0 )
                { 
                    unchecked { ace.AceFlags &= ~InheritFlags; }
                }
            }
            else 
            {
                // 
                // Without either "container inherit" or "object inherit" to go with it, 
                // the InheritOnly bit is meaningless and the entire ACE can be removed.
                // 

                if ((( ace.AceFlags & AceFlags.InheritOnly ) != 0 ) &&
                    (( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) &&
                    (( ace.AceFlags & AceFlags.ObjectInherit ) == 0 )) 
                {
                    return false; 
                } 

                // 
                // Without either "container inherit" or "object inherit" to go with it,
                // the NoPropagateInherit bit is meaningless and can be turned off.
                //
                if ((( ace.AceFlags & AceFlags.NoPropagateInherit ) != 0 ) && 
                    (( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) &&
                    (( ace.AceFlags & AceFlags.ObjectInherit ) == 0 )) 
                { 
                    unchecked { ace.AceFlags &= ~AceFlags.NoPropagateInherit; }
                } 
            }

            QualifiedAce qualifiedAce = knownAce as QualifiedAce;
 
            if ( isDacl )
            { 
                // 
                // There is no place for audit flags on a DACL
                // 

                unchecked { ace.AceFlags &= ~AuditFlags; }

                if ( qualifiedAce != null ) 
                {
                    // 
                    // Qualified ACEs in a DACL must be allow or deny ACEs 
                    //
 
                    if ( qualifiedAce.AceQualifier != AceQualifier.AccessAllowed &&
                        qualifiedAce.AceQualifier != AceQualifier.AccessDenied )
                    {
                        return false; 
                    }
                } 
            } 
            else
            { 
                //
                // On a SACL, any ACE that does not specify Success or Failure
                // flags can be removed
                // 

                if (( ace.AceFlags & AuditFlags ) == 0 ) 
                { 
                    return false;
                } 

                //
                // Qualified ACEs in a SACL must be audit ACEs
                // 

                if ( qualifiedAce != null ) 
                { 
                    if ( qualifiedAce.AceQualifier != AceQualifier.SystemAudit )
                    { 
                        return false;
                    }
                }
            } 
            return true;
        } 
 
        //
        // Strips meaningless flags from ACEs, removes meaningless ACEs 
        //

        private void RemoveMeaninglessAcesAndFlags( bool isDacl )
        { 
            //
            // Be warned: do NOT use the Count property because it has 
            // side-effect of calling canonicalization. 
            //
 
            for ( int i = _acl.Count - 1; i >= 0; i-- )
            {
                GenericAce ace = _acl[i];
 
                if ( false == InspectAce( ref ace, isDacl ))
                { 
                    _acl.RemoveAce( i ); 
                }
            } 
        }

        //
        // Converts the ACL to its canonical form 
        //
 
        private void Canonicalize( bool compact, bool isDacl ) 
        {
            // 
            // for quick sort to work, we must not allow the ace's indexes - which are constantly
            // changing during sorting - to influence our element's sorting order value. For
            // that purpose, we fix the ace's _indexInAcl here and use it for creating the
            // ace's sorting order value. 
            //
 
            for (ushort aclIndex = 0; aclIndex < _acl.Count; aclIndex++) 
            {
                _acl[aclIndex]._indexInAcl = aclIndex; 
            }

            QuickSort( 0, _acl.Count - 1, isDacl );
 
            if ( compact )
            { 
                for ( int i = 0; i < Count - 1; i++ ) 
                {
                    QualifiedAce thisAce = _acl[i] as QualifiedAce; 

                    if ( thisAce == null )
                    {
                        continue; 
                    }
 
                    QualifiedAce nextAce = _acl[i + 1] as QualifiedAce; 

                    if ( nextAce == null ) 
                    {
                        continue;
                    }
 
                    if ( true == MergeAces( ref thisAce, nextAce ))
                    { 
                        _acl.RemoveAce(i + 1); 
                    }
                } 
            }
        }

        // 
        // This method determines whether the object type and inherited object type from the original ace
        // should be retained or not based on access mask and aceflags for a given split 
        // 
        private void GetObjectTypesForSplit( ObjectAce originalAce, int accessMask, AceFlags aceFlags, out ObjectAceFlags objectFlags, out Guid objectType, out Guid inheritedObjectType )
        { 

            objectFlags = 0;
            objectType = Guid.Empty;
            inheritedObjectType = Guid.Empty; 

            // 
            // We should retain the object type if the access mask for this split contains any bits that refer to object type 
            //
            if (( accessMask & ObjectAce.AccessMaskWithObjectType ) != 0 ) 
            {
                // keep the original ace's object flags and object type
                objectType = originalAce.ObjectAceType;
                objectFlags |= originalAce.ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent; 
            }
 
            // 
            // We should retain the inherited object type if the aceflags for this contains inheritance (ContainerInherit)
            // 
            if (( aceFlags & AceFlags.ContainerInherit ) != 0 )
            {
                // keep the original ace's object flags and object type
                inheritedObjectType = originalAce.InheritedObjectAceType; 
                objectFlags |= originalAce.ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent;
            } 
        } 

        private bool ObjectTypesMatch( QualifiedAce ace, QualifiedAce newAce ) 
        {
            Guid objectType = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceType : Guid.Empty;
            Guid newObjectType = ( newAce is ObjectAce ) ? (( ObjectAce ) newAce ).ObjectAceType : Guid.Empty;
 
            return objectType.Equals( newObjectType );
        } 
 
        private bool InheritedObjectTypesMatch( QualifiedAce ace, QualifiedAce newAce )
        { 
            Guid inheritedObjectType = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).InheritedObjectAceType : Guid.Empty;
            Guid newInheritedObjectType = ( newAce is ObjectAce ) ? (( ObjectAce ) newAce ).InheritedObjectAceType : Guid.Empty;

            return inheritedObjectType.Equals( newInheritedObjectType ); 
        }
 
        private bool AccessMasksAreMergeable( QualifiedAce ace, QualifiedAce newAce ) 
        {
            // 
            // The access masks are mergeable in any of the following conditions
            // 1. Object types match
            // 2. (Object types do not match) The existing ace does not have an object type and
            //     already contains all the bits of the new ace which refer to the object type 
            //
 
            if ( ObjectTypesMatch( ace, newAce )) 
            {
                // case 1 
                return true;
            }

            ObjectAceFlags objectFlags = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceFlags : ObjectAceFlags.None; 
            if ((( ace.AccessMask & newAce.AccessMask & ObjectAce.AccessMaskWithObjectType ) ==  ( newAce.AccessMask & ObjectAce.AccessMaskWithObjectType )) &&
                 (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 )) 
            { 
                // case 2
                return true; 
            }

            return false;
        } 

        private bool AceFlagsAreMergeable( QualifiedAce ace, QualifiedAce newAce ) 
        { 
            //
            // The ace flags can be considered for merge in any of the following conditions 
            // 1. Inherited object types match
            // 2. (Inherited object types do not match) The existing ace does not have an inherited object type and
            //     already contains all the bits of the new ace
            // 

            if ( InheritedObjectTypesMatch( ace, newAce )) 
            { 
                // case 1
                return true; 
            }

            ObjectAceFlags objectFlags = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceFlags : ObjectAceFlags.None;
            if (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 ) 
            {
                // case 2 
 
                //
                // This method is called only when the access masks of the two aces are already confirmed to be exact matches 
                // therefore the second condition of case 2 is already verified
                //
                BCLDebug.Assert(( ace.AccessMask & newAce.AccessMask) ==  newAce.AccessMask, "AceFlagsAreMergeable:: AccessMask of existing ace does not contain all access bits of new ace.");
                return true; 
            }
 
            return false; 
        }
 
        private bool GetAccessMaskForRemoval( QualifiedAce ace, ObjectAceFlags objectFlags, Guid objectType, ref int accessMask )
        {
            if (( ace.AccessMask & accessMask & ObjectAce.AccessMaskWithObjectType ) != 0 )
            { 

                // 
                // If the aces have access bits in common which refer to object types 
                // then we follow these rules:
                // 
                //       Remove    No OT    OT = A        OT = B
                // Existing
                //
                //   No OT          Remove   Invalid        Invalid 
                //
                //   OT = A        Remove   Remove      Nothing Common 
                // 

 
                if ( ace is ObjectAce )
                {
                    bool commonAccessBitsWithObjectTypeExist = true;
                    ObjectAce objectAce = ace as ObjectAce; 

                    // 
                    // if what we are trying to remove has an object type 
                    // but the existing ace does not then this is an invalid case
                    // 
                    if ((( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 ) &&
                        (( objectAce.ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 ))
                    {
                        return false; 
                    }
 
                    // 
                    // if what we are trying to remove has no object type or
                    // if object types match (since at this point we have ensured that both have object types present) 
                    // then we have common access bits with object type
                    //
                    commonAccessBitsWithObjectTypeExist = (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 ) ||
                                                                                    objectAce.ObjectTypesMatch( objectFlags, objectType ); 
                    if ( !commonAccessBitsWithObjectTypeExist )
                    { 
                        accessMask &= ~ObjectAce.AccessMaskWithObjectType; 
                    }
                } 
                else if (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 )
                {
                    // the existing ace is a common ace and the one we're removing
                    // refers to a specific object type so this is invalid 
                    return false;
                } 
            } 

            return true; 

        }

        private bool GetInheritanceFlagsForRemoval( QualifiedAce ace, ObjectAceFlags objectFlags, Guid inheritedObjectType, ref AceFlags aceFlags ) 
        {
            if ((( ace.AceFlags & AceFlags.ContainerInherit ) != 0 )  && (( aceFlags & AceFlags.ContainerInherit ) != 0 )) 
            { 

                // 
                // If the aces have inheritance bits in common
                // then we follow these rules:
                //
                //       Remove    No IOT    IOT = A        IOT = B 
                // Existing
                // 
                //   No IOT          Remove   Invalid        Invalid 
                //
                //   IOT = A        Remove   Remove      Nothing Common 
                //


                if ( ace is ObjectAce ) 
                {
                    bool commonInheritanceFlagsExist = true; 
                    ObjectAce objectAce = ace as ObjectAce; 

                    // 
                    // if what we are trying to remove has an inherited object type
                    // but the existing ace does not then this is an invalid case
                    //
                    if ((( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) != 0 ) && 
                        (( objectAce.ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 ))
                    { 
                        return false; 
                    }
 
                    //
                    // if what we are trying to remove has no inherited object type or
                    // if inherited object types match then we have common inheritance flags
                    // 
                    commonInheritanceFlagsExist = (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 ) ||
                                                                       objectAce.InheritedObjectTypesMatch( objectFlags, inheritedObjectType ); 
                    if ( !commonInheritanceFlagsExist ) 
                    {
                        aceFlags &= ~AceFlags.InheritanceFlags; 
                    }
                }
                else if (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) != 0 )
                { 
                    // the existing ace is a common ace and the one we're removing
                    // refers to a specific child type so this is invalid 
                    return false; 
                }
            } 

            return true;

        } 

        // 
        // Merge routine for qualified ACEs 
        //
 
        private bool MergeAces( ref QualifiedAce ace, QualifiedAce newAce )
        {
            //
            // Only interested in explicit (non-inherited) ACEs 
            //
 
            if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
            {
                return false; 
            }

            if (( newAce.AceFlags & AceFlags.Inherited ) != 0 )
            { 
                return false;
            } 
 
            //
            // Only interested in ACEs with the specified qualifier 
            //

            if ( ace.AceQualifier != newAce.AceQualifier )
            { 
                return false;
            } 
 
            //
            // Only interested in ACEs with the specified SID 
            //

            if ( ace.SecurityIdentifier != newAce.SecurityIdentifier )
            { 
                return false;
            } 
 
            //
            // The modification algorithm proceeds in stages 
            //
            // Stage 1: if flags match, add to the access mask
            //
 
            if ( ace.AceFlags == newAce.AceFlags )
            { 
                if ( ace is ObjectAce  || newAce is ObjectAce ) 
                {
                    // for object aces we need to match the inherited object types (for ace flags equality) 
                    if ( InheritedObjectTypesMatch( ace, newAce ))
                    {
                        // also since access mask bits are further qualified by object type, they cannot always be added on
                        if ( AccessMasksAreMergeable( ace, newAce )) 
                        {
                            ace.AccessMask |= newAce.AccessMask; 
                            return true; 
                        }
                    } 
                }
                else
                {
                    ace.AccessMask |= newAce.AccessMask; 
                    return true;
                } 
            } 

 

            //
            // Stage 2: Audit flags can be combined if the rest of the
            //          flags (both access mask and inheritance) match 
            //
 
            if ((( ace.AceFlags & AceFlags.InheritanceFlags ) == ( newAce.AceFlags & AceFlags.InheritanceFlags )) && 
                ( ace.AccessMask == newAce.AccessMask ))
            { 
                if (( ace is ObjectAce ) || ( newAce is ObjectAce ))
                {
                    // for object aces we need to match the inherited object types (for inheritance flags equality) and object type (for access mask equality) as well
                    if ( InheritedObjectTypesMatch( ace, newAce ) && 
                        ( ObjectTypesMatch( ace, newAce )))
                    { 
                        ace.AceFlags |= ( newAce.AceFlags & AceFlags.AuditFlags ); 
                        return true;
                    } 
                }
                else
                {
                    ace.AceFlags |= ( newAce.AceFlags & AceFlags.AuditFlags ); 
                    return true;
                } 
 
            }
 
            //
            // Stage 3: Inheritance flags can be combined in some cases
            //          provided access mask and audit bits are the same
            // 

            if ((( ace.AceFlags & AceFlags.AuditFlags ) == ( newAce.AceFlags & AceFlags.AuditFlags )) && 
                ( ace.AccessMask == newAce.AccessMask )) 
            {
                AceFlags merged; 

                //
                // See whether the inheritance bits can be merged
                // 

                if (( ace is ObjectAce ) || ( newAce is ObjectAce )) 
                { 
                    // object types need to match (for access mask equality) and inheritance flags need additional DS specific logic
                    // to check whether they can be merged 
                    if (( ObjectTypesMatch( ace, newAce )) &&
                         ( AceFlagsAreMergeable( ace, newAce )))
                    {
                        if ( true == MergeInheritanceBits( ace.AceFlags, newAce.AceFlags, IsDS, out merged )) 
                        {
                            ace.AceFlags = ( merged | ( ace.AceFlags & AceFlags.AuditFlags )); 
                            return true; 
                        }
                    } 
                }
                else
                {
                    if ( true == MergeInheritanceBits( ace.AceFlags, newAce.AceFlags, IsDS, out merged )) 
                    {
                        ace.AceFlags = ( merged | ( ace.AceFlags & AceFlags.AuditFlags )); 
                        return true; 
                    }
                } 

            }

            return false; 
        }
 
        // 
        // Returns 'true' if the ACL is in canonical order; 'false' otherwise
        // 

        private bool CanonicalCheck( bool isDacl )
        {
            if ( isDacl ) 
            {
                // 
                // DACL canonical order: 
                //   Explicit Deny - Explicit Allow - Inherited
                // 

                const int AccessDenied = 0;
                const int AccessAllowed = 1;
                const int Inherited = 2; 
                const int Unknown = 3;
 
                int currentStage = AccessDenied; 

                // 
                // In this loop, do NOT use 'Count' as upper bound of the loop,
                // since doing so will canonicalize the ACL invalidating the result
                // of this check!
                // 

                for ( int i = 0; i < _acl.Count; i++ ) 
                { 
                    int aceStage = Unknown;
 
                    GenericAce ace = _acl[i];

                    if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
                    { 
                        aceStage = Inherited;
                    } 
                    else 
                    {
                        QualifiedAce qualifiedAce = ace as QualifiedAce; 

                        if ( qualifiedAce == null )
                        {
                            // 
                            // Explicit ACE is not recognized - this is not a canonical ACL
                            // 
 
                            return false;
                        } 

                        if ( qualifiedAce.AceQualifier == AceQualifier.AccessAllowed )
                        {
                            aceStage = AccessAllowed; 
                        }
                        else if ( qualifiedAce.AceQualifier == AceQualifier.AccessDenied ) 
                        { 
                            aceStage = AccessDenied;
                        } 
                        else
                        {
                            //
                            // Only allow and deny ACEs are allowed here 
                            //
 
                            BCLDebug.Assert( false, "Audit and alarm ACEs must have been stripped by remove-meaningless logic" ); 
                            return false;
                        } 
                    }

                    if ( aceStage == Unknown )
                    { 
                        continue;
                    } 
 
                    if ( aceStage > currentStage )
                    { 
                        currentStage = aceStage;
                    }
                    else if ( aceStage < currentStage )
                    { 
                        return false;
                    } 
                } 
            }
            else 
            {
                //
                // SACL canonical order:
                //   Explicit - Inherited 
                //
 
                const int Explicit = 0; 
                const int Inherited = 1;
                const int Unknown = 2; 

                int currentStage = Explicit;

                // 
                // In this loop, do NOT use 'Count' as upper bound of the loop,
                // since doing so will canonicalize the ACL invalidating the result 
                // of this check! 
                //
 
                for ( int i = 0; i < _acl.Count; i++ )
                {
                    int aceStage = Unknown;
 
                    GenericAce ace = _acl[i];
 
                    if ( ace == null ) 
                    {
                        // 
                        // <[....]-9/19/2004> Afraid to yank this statement now
                        // for fear of destabilization, so adding an assert instead
                        //
 
                        BCLDebug.Assert( ace != null, "How did a null ACE end up in a SACL?" );
                        continue; 
                    } 

                    if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
                    {
                        aceStage = Inherited;
                    }
                    else 
                    {
                        QualifiedAce qualifiedAce = ace as QualifiedAce; 
 
                        if ( qualifiedAce == null )
                        { 
                            //
                            // Explicit ACE is not recognized - this is not a canonical ACL
                            //
 
                            return false;
                        } 
 
                        if ( qualifiedAce.AceQualifier == AceQualifier.SystemAudit ||
                            qualifiedAce.AceQualifier == AceQualifier.SystemAlarm ) 
                        {
                            aceStage = Explicit;
                        }
                        else 
                        {
                            // 
                            // Only audit and alarm ACEs are allowed here 
                            //
 
                            BCLDebug.Assert( false, "Allow and deny ACEs must have been stripped by remove-meaningless logic" );
                            return false;
                        }
                    } 

                    if ( aceStage > currentStage ) 
                    { 
                        currentStage = aceStage;
                    } 
                    else if ( aceStage < currentStage )
                    {
                        return false;
                    } 
                }
            } 
 
            return true;
        } 

        private void ThrowIfNotCanonical()
        {
            if ( !_isCanonical ) 
            {
                throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_ModificationOfNonCanonicalAcl" )); 
            } 
        }
 
        #endregion

        #region Constructors
 
        //
        // Creates an empty ACL 
        // 

        internal CommonAcl( bool isContainer, bool isDS, byte revision, int capacity ) 
            : base()
        {
            _isContainer = isContainer;
            _isDS = isDS; 
            _acl = new RawAcl( revision, capacity );
            _isCanonical = true; // since it is empty 
        } 

        // 
        // Creates an ACL from a raw ACL
        // - 'trusted' (internal) callers get to pass the raw ACL
        //   that this object will take ownership of
        // - 'untrusted' callers are handled by creating a local 
        //   copy of the ACL passed in
        // 
 
        internal CommonAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted, bool isDacl )
            : base() 
        {
            _isContainer = isContainer;
            _isDS = isDS;
 
            if ( rawAcl == null )
            { 
                throw new ArgumentNullException( "rawAcl" ); 
            }
 
            if ( trusted )
            {
                //
                // In the trusted case, we take over ownership of the ACL passed in 
                //
 
                _acl = rawAcl; 

                RemoveMeaninglessAcesAndFlags( isDacl ); 
            }
            else
            {
                // 
                // In the untrusted case, we create our own raw ACL to keep the ACEs in
                // 
 
                _acl = new RawAcl( rawAcl.Revision, rawAcl.Count );
 
                for ( int i = 0; i < rawAcl.Count; i++ )
                {
                    //
                    // Clone each ACE prior to putting it in 
                    //
 
                    GenericAce ace = rawAcl[i].Copy(); 

                    // 
                    // Avoid inserting meaningless ACEs
                    //

                    if ( true == InspectAce( ref ace, isDacl )) 
                    {
                        _acl.InsertAce( _acl.Count, ace ); 
                    } 
                }
            } 

            //
            // See whether the ACL is canonical to begin with
            // 

            if ( true == CanonicalCheck( isDacl )) 
            { 
                //
                // Sort and compact the array 
                //

                Canonicalize( true, isDacl );
 
                _isCanonical = true;
            } 
            else 
            {
                _isCanonical = false; 
            }
        }

        #endregion 

        #region Internal Properties 
 
        internal RawAcl RawAcl
        { 
            get { return _acl; }
        }

        #endregion 

        #region Protected Methods 
 
        internal void CheckAccessType( AccessControlType accessType )
        { 
            if ( accessType != AccessControlType.Allow &&
                accessType != AccessControlType.Deny )
            {
                throw new ArgumentOutOfRangeException( 
                    "accessType",
                    Environment.GetResourceString( "ArgumentOutOfRange_Enum" )); 
            } 
        }
 
        internal void CheckFlags( InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        {
            if ( IsContainer )
            { 
                //
                // Supplying propagation flags without inheritance flags is illegal 
                // 

                if ( inheritanceFlags == InheritanceFlags.None && 
                    propagationFlags != PropagationFlags.None )
                {
                    throw new ArgumentException(
                        Environment.GetResourceString( "Argument_InvalidAnyFlag" ), 
                        "propagationFlags" );
                } 
            } 
            else if ( inheritanceFlags != InheritanceFlags.None )
            { 
                throw new ArgumentException(
                    Environment.GetResourceString("Argument_InvalidAnyFlag"),
                    "inheritanceFlags" );
            } 
            else if ( propagationFlags != PropagationFlags.None )
            { 
                throw new ArgumentException( 
                    Environment.GetResourceString( "Argument_InvalidAnyFlag" ),
                    "propagationFlags" ); 
            }

            return;
        } 

        // 
        // Helper function behind all the AddXXX methods for qualified aces 
        //
 
        internal void AddQualifiedAce( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        {
            ThrowIfNotCanonical();
 
            bool aceMerged = false; // if still false after all attempts to merge, create new entry
 
            if ( sid == null ) 
            {
                throw new ArgumentNullException( "sid" ); 
            }

            if ( qualifier == AceQualifier.SystemAudit &&
                (( flags & AceFlags.AuditFlags ) == 0 )) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ), 
                    "flags" );
            } 

            if ( accessMask == 0 )
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Argument_ArgumentZero" ),
                    "accessMask" ); 
            } 

            GenericAce newAce; 

            if (( !IsDS ) || ( objectFlags == ObjectAceFlags.None ))
            {
                newAce = new CommonAce( flags, qualifier, accessMask, sid, false, null ); 
            }
            else 
            { 
                newAce = new ObjectAce( flags, qualifier, accessMask, sid, objectFlags, objectType, inheritedObjectType, false, null );
            } 

            //
            // Make sure the new ACE wouldn't be meaningless before proceeding
            // 

            if ( false == InspectAce( ref newAce, ( this is DiscretionaryAcl ))) 
            { 
                return;
            } 

            //
            // See if the new ACE can be merged with any of the existing ones
            // 

            for ( int i = 0; i < Count; i++ ) 
            { 
                QualifiedAce ace = _acl[i] as QualifiedAce;
 
                if ( ace == null )
                {
                    continue;
                } 

                if ( true == MergeAces( ref ace, newAce as QualifiedAce )) 
                { 
                    aceMerged = true;
                    break; 
                }
            }

            // 
            // Couldn't modify any existing entry, so add a new one
            // 
 
            if ( !aceMerged )
            { 
                _acl.InsertAce( _acl.Count, newAce );

                _isDirty = true;
            } 
            OnAclModificationTried();
        } 
 
        //
        // Helper function behind all the SetXXX methods 
        //

        internal void SetQualifiedAce( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        { 
            ThrowIfNotCanonical();
 
            if ( sid == null ) 
            {
                throw new ArgumentNullException( "sid" ); 
            }

            if ( qualifier == AceQualifier.SystemAudit &&
                (( flags & AceFlags.AuditFlags ) == 0 )) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ), 
                    "flags" );
            } 

            if ( accessMask == 0 )
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Argument_ArgumentZero" ),
                    "accessMask" ); 
            } 

            GenericAce newAce; 

            if (( !IsDS ) || ( objectFlags == ObjectAceFlags.None ))
            {
                newAce = new CommonAce( flags, qualifier, accessMask, sid, false, null ); 
            }
            else 
            { 
                newAce = new ObjectAce( flags, qualifier, accessMask, sid, objectFlags, objectType, inheritedObjectType, false, null );
            } 

            //
            // Make sure the new ACE wouldn't be meaningless before proceeding
            // 

            if ( false == InspectAce( ref newAce, ( this is DiscretionaryAcl ))) 
            { 
                return;
            } 

            for ( int i = 0; i < Count; i++ )
            {
                QualifiedAce ace = _acl[i] as QualifiedAce; 

                // 
                // Not a qualified ACE - keep going 
                //
 
                if ( ace == null )
                {
                    continue;
                } 

                // 
                // Only interested in explicit (non-inherited) ACEs 
                //
 
                if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
                {
                    continue;
                } 

                // 
                // Only interested in ACEs with the specified qualifier 
                //
 
                if ( ace.AceQualifier != qualifier )
                {
                    continue;
                } 

                // 
                // Only interested in ACEs with the specified SID 
                //
 
                if ( ace.SecurityIdentifier != sid )
                {
                    continue;
                } 

                // 
                // This ACE corresponds to the SID and qualifier in question - ---- it 
                //
 
                _acl.RemoveAce( i );
                i--;
            }
 
            //
            // As a final step, add the ACE we want. 
            // Add it at the end - we'll re-canonicalize later. 
            //
 
            _acl.InsertAce( _acl.Count, newAce );

            //
            // To aid the efficiency of batch operations, recanonicalize this later 
            //
 
            _isDirty = true; 
            OnAclModificationTried();
        } 

        //
        // Helper function behind all the RemoveXXX methods
        // 

        internal bool RemoveQualifiedAces( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, bool saclSemantics, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        { 
            ThrowIfNotCanonical();
 
            if ( accessMask == 0 )
            {
                throw new ArgumentException(
                    Environment.GetResourceString( "Argument_ArgumentZero" ), 
                    "accessMask" );
            } 
 
            if ( qualifier == AceQualifier.SystemAudit &&
                (( flags & AceFlags.AuditFlags ) == 0 )) 
            {
                throw new ArgumentException(
                    Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ),
                    "flags" ); 
            }
 
            if ( sid == null ) 
            {
                throw new ArgumentNullException( "sid" ); 
            }

            //
            // Two passes are made. 
            // During the first pass, no changes are made to the ACL,
            // the ACEs are simply evaluated to ascertain that the operation 
            // can succeed. 
            // If everything is kosher, the second pass is the one that makes changes.
            // 

            bool evaluationPass = true;
            bool removePossible = true; // unless proven otherwise
 
            //
            // Needed for DS acls to keep track of the original access mask specified for removal 
            // 
            int originalAccessMask = accessMask;
            AceFlags originalFlags = flags; 

            //
            // It is possible that the removal will result in an overflow exception
            // because more ACEs get inserted. 
            // Save the current state of the object and revert to it later if
            // and exception is thrown. 
            // 

            byte[] recovery = new byte[BinaryLength]; 
            GetBinaryForm( recovery, 0 );

        MakeAnotherPass:
 
            try
            { 
                for ( int i = 0; i < Count; i++ ) 
                {
                    QualifiedAce ace = _acl[i] as QualifiedAce; 

                    //
                    // Not a qualified ACE - keep going
                    // 

                    if ( ace == null ) 
                    { 
                        continue;
                    } 

                    //
                    // Only interested in explicit (non-inherited) ACEs
                    // 

                    if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
                    { 
                        continue;
                    } 

                    //
                    // Only interested in ACEs with the specified qualifier
                    // 

                    if ( ace.AceQualifier != qualifier ) 
                    { 
                        continue;
                    } 

                    //
                    // Only interested in ACEs with the specified SID
                    // 

                    if ( ace.SecurityIdentifier != sid ) 
                    { 
                        continue;
                    } 

                    //
                    // If access masks have nothing in common, skip the whole exercise
                    // 

                    if ( IsDS ) 
                    { 
                        //
                        // incase of directory aces, if the access mask of the 
                        // existing and new ace have any bits in common that need
                        // an object type, then we need to perform some checks on the
                        // object types in the two aces. Since certain bits are further qualified
                        // by the object type they cannot be determined to be common without 
                        // inspecting the object type. It is possible that the same bits may be set but
                        // the object types are different in which case they are really not common bits. 
                        // 
                        accessMask = originalAccessMask;
                        bool objectTypesConflict = !GetAccessMaskForRemoval( ace, objectFlags, objectType, ref accessMask ); 

                        // if the access masks have nothing in common, skip
                        if (( ace.AccessMask & accessMask ) == 0 )
                        { 
                            continue;
                        } 
 
                        //
                        // incase of directory aces, if the existing and new ace are being inherited, 
                        // then we need to perform some checks on the
                        // inherited object types in the two aces. Since inheritance is further qualified
                        // by the inherited object type the inheritance flags cannot be determined to be common without
                        // inspecting the inherited object type. It is possible that both aces may be further inherited but if 
                        // the inherited object types are different the inheritance may not be common.
                        // 
                        flags = originalFlags; 
                        bool inheritedObjectTypesConflict = !GetInheritanceFlagsForRemoval( ace, objectFlags, inheritedObjectType, ref flags );
 
                        if (((( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) && (( flags & AceFlags.ContainerInherit ) != 0 )  && (( flags & AceFlags.InheritOnly ) != 0 )) ||
                             ((( flags & AceFlags.ContainerInherit ) == 0 ) && (( ace.AceFlags & AceFlags.ContainerInherit ) != 0 )  && (( ace.AceFlags & AceFlags.InheritOnly ) != 0)))
                        {
                            // if one ace applies only to self and the other only to children/descendents we have nothing in common 
                            continue;
                        } 
 
                        //
                        // if the ace being removed referred only to child types and child types among existing ace and 
                        // ace being removed are not common then there is nothing in common between these aces (skip)
                        //
                        if ((( originalFlags & AceFlags.ContainerInherit ) != 0 ) && (( originalFlags & AceFlags.InheritOnly ) != 0 ) && (( flags & AceFlags.ContainerInherit ) == 0 ))
                        { 
                            continue;
                        } 
 
                        if ( objectTypesConflict || inheritedObjectTypesConflict )
                        { 
                            //
                            // if we reached this stage, then we've found something common between the two aces.
                            // But since there is a conflict between the object types (or inherited object types), the remove is not possible
                            // 
                            removePossible = false;
                            break; 
                        } 
                    }
                    else 
                    {
                        if (( ace.AccessMask & accessMask ) == 0 )
                        {
                            continue; 
                        }
                    } 
 
                    //
                    // If audit flags on a SACL have nothing in common, 
                    // skip the whole exercise
                    //

                    if ( saclSemantics && 
                        (( ace.AceFlags & flags & AceFlags.AuditFlags ) == 0 ))
                    { 
                        continue; 
                    }
 
                    //
                    // See if the ACE needs to be split into several
                    // To illustrate with an example, consider this equation:
                    //            From: CI OI    NP SA FA R W 
                    //          Remove:    OI IO NP SA    R
                    // 
                    // PermissionSplit: CI OI    NP SA FA   W   // remove R 
                    //   AuditingSplit: CI OI    NP    FA R     // remove SA
                    //      MergeSplit: CI OI    NP SA    R     // ready for merge 
                    //          Remove:    OI IO NP SA    R     // same audit and perm flags as merge split
                    //
                    //          Result: CI OI    NP SA FA   W   // PermissionSplit
                    //                  CI OI    NP    FA R     // AuditingSplit 
                    //                  CI       NP SA    R     // Result of perm removal
                    // 
 
                    //
                    // Example for DS acls (when removal is possible) 
                    //
                    // From: CI(Guid) LC CC(Guid)
                    // Remove: CI IO LC
                    // 
                    // PermissionSplit: CI(Guid) CC(Guid) // Remove GR
                    //        MergeSplit: CI(Guid) LC // Ready for merge 
                    //           Remove: CI IO LC // Removal is possible since we are trying to remove inheritance for 
                    //                                            all child types when it exists for one specific child type
                    // 
                    //              Result: CI(Guid) CC(Guid) // PermissionSplit
                    //                         LC // Result of perm removal
                    //
                    // 
                    // Example for DS acls (when removal is NOT possible)
                    // 
                    // From: CI GR CC(Guid) 
                    // Remove: CI(Guid) IO LC
                    // 
                    // PermissionSplit: CI CC(Guid) // Remove GR
                    //        MergeSplit: CI LC // Ready for merge
                    //           Remove: CI(Guid) IO CC // Removal is not possible since we are trying to remove
                    //                                                     inheritance for a specific child type when it exists for all child types 
                    //
 
                    // Permission split settings 
                    AceFlags ps_AceFlags = 0;
                    int ps_AccessMask = 0; 
                    ObjectAceFlags ps_ObjectAceFlags = 0;
                    Guid ps_ObjectAceType = Guid.Empty;
                    Guid ps_InheritedObjectAceType = Guid.Empty;
 
                    // Auditing split makes sense if this is a SACL
                    AceFlags as_AceFlags = 0; 
                    int as_AccessMask = 0; 
                    ObjectAceFlags as_ObjectAceFlags = 0;
                    Guid as_ObjectAceType = Guid.Empty; 
                    Guid as_InheritedObjectAceType = Guid.Empty;

                    // Merge split settings
                    AceFlags ms_AceFlags = 0; 
                    int ms_AccessMask = 0;
                    ObjectAceFlags ms_ObjectAceFlags = 0; 
                    Guid ms_ObjectAceType = Guid.Empty; 
                    Guid ms_InheritedObjectAceType = Guid.Empty;
 
                    // Merge result settings
                    AceFlags mergeResultFlags = 0;
                    bool mergeRemoveTotal = false;
 
                    //
                    // First compute the permission split 
                    // 

                    ps_AceFlags = ace.AceFlags; 
                    unchecked { ps_AccessMask = ace.AccessMask & ~accessMask; }

                    if ( ace is ObjectAce )
                    { 
                        //
                        // determine what should be the object/inherited object types on the permission split 
                        // 
                        GetObjectTypesForSplit( ace as ObjectAce, ps_AccessMask /* access mask for this split */, ps_AceFlags /* flags remain the same */, out ps_ObjectAceFlags, out ps_ObjectAceType, out ps_InheritedObjectAceType );
                    } 

                    //
                    // Next, for SACLs only, compute the auditing split
                    // 

                    if ( saclSemantics ) 
                    { 
                        //
                        // This operation can set the audit bits region 
                        // of ACE flags to zero;
                        // This case will be handled later
                        //
 
                        unchecked { as_AceFlags = ace.AceFlags & ~( flags & AceFlags.AuditFlags ); }
 
                        // 
                        // The result of this evaluation is guaranteed
                        // not to be zero by now 
                        //

                        as_AccessMask = ( ace.AccessMask & accessMask );
 
                        if ( ace is ObjectAce )
                        { 
                            // 
                            // determine what should be the object/inherited object types on the audit split
                            // 
                            GetObjectTypesForSplit( ace as ObjectAce, as_AccessMask /* access mask for this split */, as_AceFlags /* flags remain the same for inheritance */, out as_ObjectAceFlags, out as_ObjectAceType, out as_InheritedObjectAceType );
                        }
                    }
 
                    //
                    // Finally, compute the merge split 
                    // 

                    ms_AceFlags = ( ace.AceFlags & AceFlags.InheritanceFlags ) | ( flags & ace.AceFlags & AceFlags.AuditFlags ); 
                    ms_AccessMask = ( ace.AccessMask & accessMask );


                    // 
                    // Now is the time to obtain the result of applying the remove
                    // operation to the merge split 
                    // Skipping this step for SACLs where the merge split step 
                    // produced no auditing flags
                    // 

                    if ( !saclSemantics ||
                        (( ms_AceFlags & AceFlags.AuditFlags ) != 0 ))
                    { 
                        if ( false == RemoveInheritanceBits( ms_AceFlags, flags, IsDS, out mergeResultFlags, out mergeRemoveTotal ))
                        { 
                            removePossible = false; 
                            break;
                        } 

                        if ( !mergeRemoveTotal )
                        {
                            mergeResultFlags |= ( ms_AceFlags & AceFlags.AuditFlags ); 

                            if ( ace is ObjectAce ) 
                            { 
                                //
                                // determine what should be the object/inherited object types on the merge split 
                                //
                                GetObjectTypesForSplit( ace as ObjectAce, ms_AccessMask /* access mask for this split */, mergeResultFlags /* flags for this split */, out ms_ObjectAceFlags, out ms_ObjectAceType, out ms_InheritedObjectAceType );
                            }
                        } 
                    }
 
                    // 
                    // If this is no longer an evaluation, go ahead and make the changes
                    // 

                    if ( !evaluationPass )
                    {
                        QualifiedAce newAce; 

                        // 
                        // Modify the existing ACE in-place if it has any access 
                        // mask bits left, otherwise simply remove it
                        // However, if for an object ace we are removing the object type 
                        // then we should really remove this ace and add a new one since
                        // we would be changing the size of this ace
                        //
 
                        if ( ps_AccessMask != 0 )
                        { 
                            if (( ace is ObjectAce ) && 
                                (((( ObjectAce) ace ).ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 ) &&
                                     (( ps_ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 )) 
                            {
                                ObjectAce newObjectAce;

                                _acl.RemoveAce(i); 
                                newObjectAce = new ObjectAce( ps_AceFlags, qualifier, ps_AccessMask, ace.SecurityIdentifier, ps_ObjectAceFlags, ps_ObjectAceType, ps_InheritedObjectAceType, false, null );
                                _acl.InsertAce( i, newObjectAce ); 
                            } 
                            else
                            { 
                                ace.AceFlags = ps_AceFlags;
                                ace.AccessMask = ps_AccessMask;

                                if ( ace is ObjectAce ) 
                                {
                                    ObjectAce objectAce = ace as ObjectAce; 
 
                                    objectAce.ObjectAceFlags = ps_ObjectAceFlags;
                                    objectAce.ObjectAceType = ps_ObjectAceType; 
                                    objectAce.InheritedObjectAceType = ps_InheritedObjectAceType;
                                }
                            }
                        } 
                        else
                        { 
                            _acl.RemoveAce(i); 
                            i--; // keep the array index honest
                        } 

                        //
                        // On a SACL, the result of the auditing split must be recorded
                        // 

                        if ( saclSemantics && (( as_AceFlags & AceFlags.AuditFlags ) != 0 )) 
                        { 
                            if ( ace is CommonAce )
                            { 
                                newAce = new CommonAce( as_AceFlags, qualifier, as_AccessMask, ace.SecurityIdentifier, false, null );
                            }
                            else
                            { 
                                // object ace
                                newAce = new ObjectAce( as_AceFlags, qualifier, as_AccessMask, ace.SecurityIdentifier, as_ObjectAceFlags, as_ObjectAceType, as_InheritedObjectAceType, false, null ); 
                            } 

                            i++; // so it's not considered again 
                            _acl.InsertAce( i, newAce );
                        }

                        // 
                        // If there are interesting bits left over from a remove, store them
                        // as a separate ACE 
                        // 

                        if ( !mergeRemoveTotal ) 
                        {
                            if ( ace is CommonAce )
                            {
                                newAce = new CommonAce( mergeResultFlags, qualifier, ms_AccessMask, ace.SecurityIdentifier, false, null ); 
                            }
                            else 
                            { 
                                // object ace
                                newAce = new ObjectAce( mergeResultFlags, qualifier, ms_AccessMask, ace.SecurityIdentifier, ms_ObjectAceFlags, ms_ObjectAceType, ms_InheritedObjectAceType, false, null ); 
                            }

                            i++; // so it's not considered again
                            _acl.InsertAce( i, newAce ); 
                        }
                    } 
                } 
            }
            catch( OverflowException ) 
            {
                //
                // Oops, overflow means that the ACL became too big.
                // Inform the caller that the remove was not possible. 
                //
 
                _acl.SetBinaryForm( recovery, 0 ); 
                return false;
            } 

            //
            // Finished evaluating the possibility of a remove.
            // If it looks like it's doable, go ahead and do it. 
            //
 
            if ( evaluationPass && removePossible ) 
            {
                evaluationPass = false; 
                goto MakeAnotherPass;
            }

            OnAclModificationTried(); 

            return removePossible; 
        } 

        internal void RemoveQualifiedAcesSpecific( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            ThrowIfNotCanonical();

            if ( accessMask == 0 ) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Argument_ArgumentZero" ), 
                    "accessMask" );
            } 

            if ( qualifier == AceQualifier.SystemAudit &&
                (( flags & AceFlags.AuditFlags ) == 0 ))
            { 
                throw new ArgumentException(
                    Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ), 
                    "flags" ); 
            }
 
            if ( sid == null )
            {
                throw new ArgumentNullException( "sid" );
            } 

            for ( int i = 0; i < Count; i++ ) 
            { 
                QualifiedAce ace = _acl[i] as QualifiedAce;
 
                //
                // Not a qualified ACE - keep going
                //
 
                if ( ace == null )
                { 
                    continue; 
                }
 
                //
                // Only interested in explicit (non-inherited) ACEs
                //
 
                if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
                { 
                    continue; 
                }
 
                //
                // Only interested in ACEs with the specified qualifier
                //
 
                if ( ace.AceQualifier != qualifier )
                { 
                    continue; 
                }
 
                //
                // Only interested in ACEs with the specified SID
                //
 
                if ( ace.SecurityIdentifier != sid )
                { 
                    continue; 
                }
 
                //
                // Only interested in exact ACE flag matches
                //
 
                if ( ace.AceFlags != flags )
                { 
                    continue; 
                }
 
                //
                // Only interested in exact access mask matches
                //
 
                if ( ace.AccessMask != accessMask )
                { 
                    continue; 
                }
 
                if ( IsDS )
                {
                    //
                    // Incase of object aces, only interested in ACEs which match in their 
                    // objectType and inheritedObjectType
                    // 
 
                    if (( ace is ObjectAce ) && ( objectFlags != ObjectAceFlags.None ))
                    { 
                        //
                        // both are object aces, so must match in object type and inherited object type
                        //
                        ObjectAce objectAce = ace as ObjectAce; 

                        if (( !objectAce.ObjectTypesMatch( objectFlags, objectType )) 
                            || ( !objectAce.InheritedObjectTypesMatch( objectFlags, inheritedObjectType ))) 
                        {
                            continue; 
                        }
                    }
                    else if (( ace is ObjectAce ) || ( objectFlags != ObjectAceFlags.None ))
                    { 
                        // one is object ace and the other is not, so no match
                        continue; 
                    } 
                }
 
                //
                // Got our exact match; now remove it
                //
 
                _acl.RemoveAce(i);
                i--; // keep the array index honest 
            } 
            OnAclModificationTried();
        } 

        internal virtual void OnAclModificationTried()
        {
        } 
        #endregion
 
        #region Public Properties 

        // 
        // Returns the revision of the ACL
        //

        public sealed override byte Revision 
        {
            get { return _acl.Revision; } 
        } 

        // 
        // Returns the number of ACEs in the ACL
        //

        public sealed override int Count 
        {
            get 
            { 
                CanonicalizeIfNecessary();
                return _acl.Count; 
            }
        }

        // 
        // Returns the length of the binary representation of the ACL
        // 
 
        public sealed override int BinaryLength
        { 
            get
            {
                CanonicalizeIfNecessary();
                return _acl.BinaryLength; 
            }
        } 
 
        //
        // Returns 'true' if the ACL was canonical at creation time 
        //

        public bool IsCanonical
        { 
            get { return _isCanonical; }
        } 
 
        public bool IsContainer
        { 
            get { return _isContainer; }
        }

        public bool IsDS 
        {
            get { return _isDS; } 
        } 

        #endregion 

        #region Public Methods

        // 
        // Returns the binary representation of the ACL
        // 
 
        public sealed override void GetBinaryForm( byte[] binaryForm, int offset )
        { 
            CanonicalizeIfNecessary();
            _acl.GetBinaryForm( binaryForm, offset );
        }
 
        //
        // Retrieves the ACE at a given index inside the ACL 
        // Since the caller can modify the ACE it receives, 
        // clone the ACE prior to returning it to the caller
        // 

        public sealed override GenericAce this[int index]
        {
            get 
            {
                CanonicalizeIfNecessary(); 
                return _acl[index].Copy(); 
            }
 
            set
            {
                throw new NotSupportedException( Environment.GetResourceString( "NotSupported_SetMethod" ));
            } 
        }
 
        public void RemoveInheritedAces() 
        {
            ThrowIfNotCanonical(); 

            //
            // Iterating backwards as an optimization - all inherited ACEs
            // are usually in the back of the ACL 
            //
 
            for ( int i = _acl.Count - 1; i >= 0; i-- ) 
            {
                GenericAce ace = _acl[i]; 

                if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
                {
                    _acl.RemoveAce( i ); 
                }
            } 
            OnAclModificationTried(); 
        }
 
        public void Purge( SecurityIdentifier sid )
        {
            ThrowIfNotCanonical();
 
            if ( sid == null )
            { 
                throw new ArgumentNullException( "sid" ); 
            }
 
            for ( int i = Count - 1; i >= 0; i-- )
            {
                KnownAce ace = _acl[i] as KnownAce;
 
                //
                // Skip over unknown ACEs 
                // 

                if ( ace == null ) 
                {
                    continue;
                }
 
                //
                // Skip over inherited ACEs 
                // 

                if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
                {
                    continue;
                }
 
                //
                // SID matches - ACE is out 
                // 

                if ( ace.SecurityIdentifier == sid ) 
                {
                    _acl.RemoveAce( i );
                }
            } 
            OnAclModificationTried();
        } 
 
        #endregion
    } 


    public sealed class SystemAcl : CommonAcl
    { 
        #region Constructors
 
        // 
        // Creates an emtpy ACL
        // 

        public SystemAcl( bool isContainer, bool isDS, int capacity )
            : this( isContainer, isDS, isDS ? AclRevisionDS : AclRevision, capacity )
        { 
        }
 
        public SystemAcl( bool isContainer, bool isDS, byte revision, int capacity ) 
            : base( isContainer, isDS, revision, capacity )
        { 
        }

        //
        // Creates an ACL from a given raw ACL 
        // after canonicalizing it
        // 
 
        public SystemAcl( bool isContainer, bool isDS, RawAcl rawAcl )
            : this( isContainer, isDS, rawAcl, false ) 
        {
        }

        // 
        // Internal version - if 'trusted' is true,
        // takes ownership of the given raw ACL 
        // 

        internal SystemAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted ) 
            : base( isContainer, isDS, rawAcl, trusted, false )
        {
        }
 
        #endregion
 
        #region Public Methods 

        public void AddAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags ) 
        {
            CheckFlags( inheritanceFlags, propagationFlags );
            AddQualifiedAce( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        } 

        public void SetAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags ) 
        { 
            CheckFlags( inheritanceFlags, propagationFlags );
            SetQualifiedAce( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty ); 
        }

        public bool RemoveAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        { 
            return RemoveQualifiedAces(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), true, ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        } 
 
        public void RemoveAuditSpecific( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        { 
            RemoveQualifiedAcesSpecific( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        }

        public void AddAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            // 
            // This is valid only for DS Acls 
            //
            if ( !IsDS ) 
            {
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
            } 

            CheckFlags( inheritanceFlags, propagationFlags ); 
            AddQualifiedAce(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType); 
        }
 
        public void SetAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        {
            //
            // This is valid only for DS Acls 
            //
            if ( !IsDS ) 
            { 
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" )); 
            }

            CheckFlags( inheritanceFlags, propagationFlags );
            SetQualifiedAce(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType); 
        }
 
        public bool RemoveAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            // 
            // This is valid only for DS Acls
            //
            if ( !IsDS )
            { 
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" )); 
            } 

            return RemoveQualifiedAces(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), true, objectFlags, objectType, inheritedObjectType); 
        }

        public void RemoveAuditSpecific( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        { 
            //
            // This is valid only for DS Acls 
            // 
            if ( !IsDS )
            { 
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
            }
 
            RemoveQualifiedAcesSpecific(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType);
        } 
 
        #endregion
    } 


    public sealed class DiscretionaryAcl : CommonAcl
    { 
        #region
        static private SecurityIdentifier _sidEveryone = new SecurityIdentifier( WellKnownSidType.WorldSid, null ); 
        private bool everyOneFullAccessForNullDacl = false; 
        #endregion
 
        #region Constructors

        //
        // Creates an emtpy ACL 
        //
 
        public DiscretionaryAcl( bool isContainer, bool isDS, int capacity ) 
            : this( isContainer, isDS, isDS ? AclRevisionDS : AclRevision, capacity )
        { 
        }

        public DiscretionaryAcl( bool isContainer, bool isDS, byte revision, int capacity )
            : base( isContainer, isDS, revision, capacity ) 
        {
        } 
 
        //
        // Creates an ACL from a given raw ACL 
        // after canonicalizing it
        //

        public DiscretionaryAcl( bool isContainer, bool isDS, RawAcl rawAcl ) 
            : this( isContainer, isDS, rawAcl, false )
        { 
        } 

        // 
        // Internal version - if 'trusted' is true,
        // takes ownership of the given raw ACL
        //
 
        internal DiscretionaryAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted )
            : base( isContainer, isDS, rawAcl == null ? new RawAcl( isDS ? AclRevisionDS : AclRevision, 0 ) : rawAcl, trusted, true ) 
        { 
        }
 
        #endregion

        #region Public Methods
 
        public void AddAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        { 
            CheckAccessType( accessType ); 
            CheckFlags( inheritanceFlags, propagationFlags );
            everyOneFullAccessForNullDacl = false; 
            AddQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        }

        public void SetAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags ) 
        {
            CheckAccessType( accessType ); 
            CheckFlags( inheritanceFlags, propagationFlags ); 
            everyOneFullAccessForNullDacl = false;
            SetQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty ); 
        }

        public bool RemoveAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        { 
            CheckAccessType( accessType );
            everyOneFullAccessForNullDacl = false; 
            return RemoveQualifiedAces( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), false, ObjectAceFlags.None, Guid.Empty, Guid.Empty ); 
        }
 
        public void RemoveAccessSpecific( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        {
            CheckAccessType( accessType );
            everyOneFullAccessForNullDacl = false; 
            RemoveQualifiedAcesSpecific(sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        } 
 
        public void AddAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        { 
            //
            // This is valid only for DS Acls
            //
            if ( !IsDS ) 
            {
                throw new InvalidOperationException( 
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" )); 
            }
 
            CheckAccessType( accessType );
            CheckFlags( inheritanceFlags, propagationFlags );
            everyOneFullAccessForNullDacl = false;
            AddQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType ); 
        }
 
        public void SetAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            // 
            // This is valid only for DS Acls
            //
            if ( !IsDS )
            { 
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" )); 
            } 

            CheckAccessType( accessType ); 
            CheckFlags( inheritanceFlags, propagationFlags );
            everyOneFullAccessForNullDacl = false;
            SetQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType);
        } 

        public bool RemoveAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        { 
            //
            // This is valid only for DS Acls 
            //
            if ( !IsDS )
            {
                throw new InvalidOperationException( 
                    Environment.GetResourceString(" InvalidOperation_OnlyValidForDS "));
            } 
 
            CheckAccessType( accessType );
            everyOneFullAccessForNullDacl = false; 
            return RemoveQualifiedAces(sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), false, objectFlags, objectType, inheritedObjectType );
        }

        public void RemoveAccessSpecific( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            // 
            // This is valid only for DS Acls 
            //
            if ( !IsDS ) 
            {
                throw new InvalidOperationException(
                    Environment.GetResourceString(" InvalidOperation_OnlyValidForDS "));
            } 

            CheckAccessType( accessType ); 
            everyOneFullAccessForNullDacl = false; 
            RemoveQualifiedAcesSpecific( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType );
        } 

        #endregion

        #region internals and privates 

        // 
        // DACL's "allow everyone full access may be created to replace a null DACL because managed 
        // access control does not want to leave null DACLs around. But we need to remember this MACL
        // created ACE when the DACL is modified, we can remove it to match the same native semantics of 
        // a null DACL.
        //
        internal bool EveryOneFullAccessForNullDacl
        { 
            get { return everyOneFullAccessForNullDacl; }
            set { everyOneFullAccessForNullDacl = value; } 
        } 

        // 
        // As soon as you tried successfully to modified the ACL, the internally created allow every one full access ACL is materialized
        // because in native world, a NULL dacl can't be operated on.
        //
        internal override void OnAclModificationTried() 
        {
            everyOneFullAccessForNullDacl = false; 
        } 

        ///  
        /// This static method will create an "allow everyone full control" single ACE DACL.
        /// 
        /// whether it is a DS DACL
        /// whether it is a container 
        /// The single ACE DACL
        /// Note: This method is created to get the best behavior for using "allow everyone full access" 
        /// single ACE DACL to replace null DACL from CommonSecurityObject. 
        static internal DiscretionaryAcl CreateAllowEveryoneFullAccess(bool isDS, bool isContainer)
        { 
            DiscretionaryAcl dcl = new DiscretionaryAcl( isContainer, isDS, 1 );
            dcl.AddAccess(
                AccessControlType.Allow,
                _sidEveryone, 
                -1,
                isContainer ? ( InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit ) : InheritanceFlags.None, 
                PropagationFlags.None ); 

            dcl.everyOneFullAccessForNullDacl = true; 
            return dcl;
        }
        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Classes:  Access Control List (ACL) family of classes 
**
** 
===========================================================*/

using System;
using System.Collections; 
using System.Security.Principal;
 
namespace System.Security.AccessControl 
{
 
    public sealed class AceEnumerator : IEnumerator
    {
        #region Private Members
 
        //
        // Current enumeration index 
        // 

        private int _current; 

        //
        // Parent collection
        // 

        private readonly GenericAcl _acl; 
 
        #endregion
 
        #region Constructors

        internal AceEnumerator( GenericAcl collection )
        { 
            if ( collection == null )
            { 
                throw new ArgumentNullException( "collection" ); 
            }
 
            _acl = collection;
            Reset();
        }
 
        #endregion
 
        #region IEnumerator Interface 

        object IEnumerator.Current 
        {
            get
            {
                if ( _current == -1 || 
                    _current >= _acl.Count )
                { 
                    throw new InvalidOperationException( Environment.GetResourceString( "Arg_InvalidOperationException" )); 
                }
 
                return _acl[_current];
            }
        }
 
        public GenericAce Current
        { 
            get { return (( IEnumerator )this ).Current as GenericAce; } 
        }
 
        public bool MoveNext()
        {
            _current++;
 
            return ( _current < _acl.Count );
        } 
 
        public void Reset()
        { 
            _current = -1;
        }

        #endregion 
    }
 
 
    public abstract class GenericAcl : ICollection
    { 
        #region Constructors

        protected GenericAcl()
        { } 

        #endregion 
 
        #region Public Constants
 
        //
        // ACL revisions
        //
 
        public static readonly byte AclRevision = 2;
        public static readonly byte AclRevisionDS = 4; 
 
        //
        // Maximum length of a binary representation of the ACL 
        //

        public static readonly int MaxBinaryLength = ushort.MaxValue;
 
        #endregion
 
        #region Protected Members 

        // 
        //  Define an ACL and the ACE format.  The structure of an ACL header
        //  followed by one or more ACEs.  Pictorally the structure of an ACL header
        //  is as follows:
        // 
        //       3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
        //       1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 
        //      +-------------------------------+---------------+---------------+ 
        //      |            AclSize            |      Sbz1     |  AclRevision  |
        //      +-------------------------------+---------------+---------------+ 
        //      |              Sbz2             |           AceCount            |
        //      +-------------------------------+-------------------------------+
        //
 
        internal const int HeaderLength = 8;
 
        #endregion 

        #region Public Properties 

        //
        // Returns the revision of the ACL
        // 

        public abstract byte Revision { get; } 
 
        //
        // Returns the length of the binary representation of the ACL 
        //

        public abstract int BinaryLength { get; }
 
        //
        // Retrieves the ACE at a specified index 
        // 

        public abstract GenericAce this[int index] { get; set; } 

        #endregion

        #region Public Methods 

        // 
        // Returns the binary representation of the ACL 
        //
 
        public abstract void GetBinaryForm( byte[] binaryForm, int offset );

        #endregion
 
        #region ICollection Implementation
 
        void ICollection.CopyTo( Array array, int index ) 
        {
            if ( array == null ) 
            {
                throw new ArgumentNullException( "array" );
            }
 
            if ( array.Rank != 1 )
            { 
                throw new RankException( Environment.GetResourceString( "Rank_MultiDimNotSupported" )); 
            }
 
            if ( index < 0 )
            {
                throw new ArgumentOutOfRangeException(
                    "index", 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
            } 
            else if ( array.Length - index < Count ) 
            {
                throw new ArgumentOutOfRangeException( 
                    "array",
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
            }
 
            for ( int i = 0; i < Count; i++ )
            { 
                array.SetValue( this[i], index + i ); 
            }
        } 

        public void CopyTo( GenericAce[] array, int index )
        {
            (( ICollection )this ).CopyTo( array, index ); 
        }
 
        public abstract int Count { get; } 

        public bool IsSynchronized 
        {
            get { return false; }
        }
 
        public object SyncRoot
        { 
            get { return null; } 
        }
 
        #endregion

        #region IEnumerable Implementation
 
        IEnumerator IEnumerable.GetEnumerator()
        { 
            return new AceEnumerator( this ); 
        }
 
        public AceEnumerator GetEnumerator()
        {
            return (( IEnumerable )this ).GetEnumerator() as AceEnumerator;
        } 

        #endregion 
    } 

 
    public sealed class RawAcl : GenericAcl
    {
        #region Private Members
 
        private byte _revision;
        private ArrayList _aces; 
        private int _binaryLength = HeaderLength; 

        #endregion 

        #region Private Methods

        private static void VerifyHeader( byte[] binaryForm, int offset, out byte revision, out int count, out int length ) 
        {
            if ( binaryForm == null ) 
            { 
                throw new ArgumentNullException( "binaryForm" );
            } 

            if ( offset < 0 )
            {
                // 
                // Offset must not be negative
                // 
 
                throw new ArgumentOutOfRangeException(
                    "offset", 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
            }

            if ( binaryForm.Length - offset < HeaderLength ) 
            {
                // 
                // We expect at least the ACL header 
                //
 
                goto InvalidParameter;
            }

            revision = binaryForm[offset + 0]; 
            length = ( binaryForm[offset + 2] << 0 ) + ( binaryForm[offset + 3] << 8 );
            count = ( binaryForm[offset + 4] << 0 ) + ( binaryForm[offset + 5] << 8 ); 
 
            if ( length > binaryForm.Length - offset )
            { 
                //
                // Reported length of ACL ought to be no longer than the
                // length of the buffer passed in
                // 

                goto InvalidParameter; 
            } 

            return; 

        InvalidParameter:

            throw new ArgumentOutOfRangeException( 
                "binaryForm",
                Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" )); 
        } 

        private void MarshalHeader( byte[] binaryForm, int offset ) 
        {
            if ( binaryForm == null )
            {
                throw new ArgumentNullException( "binaryForm" ); 
            }
            else if ( offset < 0 ) 
            { 
                throw new ArgumentOutOfRangeException(
                    "offset", 
                    Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
            }
            else if ( BinaryLength > MaxBinaryLength )
            { 
                throw new InvalidOperationException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
            } 
            else if ( binaryForm.Length - offset < BinaryLength ) 
            {
                throw new ArgumentOutOfRangeException( 
                    "binaryForm",
                    Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
            }
 
            binaryForm[offset + 0] = Revision;
            binaryForm[offset + 1] = 0; 
            binaryForm[offset + 2] = ( byte )( BinaryLength >> 0 ); 
            binaryForm[offset + 3] = ( byte )( BinaryLength >> 8 );
            binaryForm[offset + 4] = ( byte )( Count >> 0 ); 
            binaryForm[offset + 5] = ( byte )( Count >> 8 );
            binaryForm[offset + 6] = 0;
            binaryForm[offset + 7] = 0;
        } 

        internal void SetBinaryForm( byte[] binaryForm, int offset ) 
        { 
            int count, length;
 
            //
            // Verify the header and extract interesting header info
            //
 
            VerifyHeader( binaryForm, offset, out _revision, out count, out length );
 
            // 
            // Remember how far ahead the binary form should end (for later verification)
            // 

            length += offset;

            offset += HeaderLength; 

            _aces = new ArrayList( count ); 
            _binaryLength = HeaderLength; 

            for ( int i = 0; i < count; i++ ) 
            {
                GenericAce ace = GenericAce.CreateFromBinaryForm( binaryForm, offset );

                int aceLength = ace.BinaryLength; 

                if ( _binaryLength + aceLength > MaxBinaryLength ) 
                { 
                    //
                    // The ACE was too long - it would overflow the ACL maximum length 
                    //

                    throw new ArgumentException(
                        Environment.GetResourceString( "ArgumentException_InvalidAclBinaryForm" ), 
                        "binaryForm" );
                } 
 
                _aces.Add( ace );
 
                if ( aceLength % 4 != 0 )
                {
                    //
                    // This indicates a bug in one of the ACE classes. 
                    // Binary length of an ace must ALWAYS be divisible by 4.
                    // 
 
                    BCLDebug.Assert( false, "aceLength % 4 != 0" );
                    throw new SystemException(); 
                }

                _binaryLength += aceLength;
 
                if ( _revision == AclRevisionDS )
                { 
                    // 
                    // Increment the offset by the advertised length rather than the
                    // actual binary length. (Ideally these two should match, but for 
                    // object aces created through ADSI, the actual length is 32 bytes
                    // less than the allocated size of the ACE. This is a bug in ADSI.)
                    //
                    offset += (binaryForm[offset + 2] << 0) + (binaryForm[offset + 3] << 8); 
                }
                else 
                { 
                    offset += aceLength;
                } 

                //
                // Verify that no more than the advertised length of the ACL was consumed
                // 

                if ( offset > length ) 
                { 
                    goto InvalidParameter;
                } 
            }

            return;
 
        InvalidParameter:
 
            throw new ArgumentException( 
                Environment.GetResourceString( "ArgumentException_InvalidAclBinaryForm" ),
                "binaryForm" ); 
        }

        #endregion
 
        #region Constructors
 
        // 
        // Creates an empty ACL
        // 

        public RawAcl( byte revision, int capacity )
            : base()
        { 
            _revision = revision;
            _aces = new ArrayList( capacity ); 
        } 

        // 
        // Creates an ACL from its binary representation
        //

        public RawAcl( byte[] binaryForm, int offset ) 
            : base()
        { 
            SetBinaryForm( binaryForm, offset ); 
        }
 
        #endregion

        #region Public Properties
 
        //
        // Returns the revision of the ACL 
        // 

        public override byte Revision 
        {
            get { return _revision; }
        }
 
        //
        // Returns the number of ACEs in the ACL 
        // 

        public override int Count 
        {
            get { return _aces.Count; }
        }
 
        //
        // Returns the length of the binary representation of the ACL 
        // 

        public override int BinaryLength 
        {
            get { return _binaryLength; }
        }
 
        #endregion
 
        #region Public Methods 

        // 
        // Returns the binary representation of the ACL
        //

        public override void GetBinaryForm( byte[] binaryForm, int offset ) 
        {
            // 
            // Populate the header 
            //
 
            MarshalHeader( binaryForm, offset );
            offset += HeaderLength;

            for ( int i = 0; i < Count; i++ ) 
            {
                GenericAce ace = _aces[i] as GenericAce; 
 
                ace.GetBinaryForm( binaryForm, offset );
 
                int aceLength = ace.BinaryLength;

                if ( aceLength % 4 != 0 )
                { 
                    //
                    // This indicates a bug in one of the ACE classes. 
                    // Binary length of an ace must ALWAYS be divisible by 4. 
                    //
 
                    BCLDebug.Assert( false, "aceLength % 4 != 0" );
                    throw new SystemException();
                }
 
                offset += aceLength;
            } 
        } 

        // 
        // Return an ACE at a particular index
        // The ACE is not cloned prior to returning, enabling the caller
        // to modify the ACE in place (a potentially dangerous operation)
        // 

        public override GenericAce this[int index] 
        { 
            get
            { 
                return _aces[index] as GenericAce;
            }

            set 
            {
                if ( value == null ) 
                { 
                    throw new ArgumentNullException( "value" );
                } 

                if ( value.BinaryLength % 4 != 0 )
                {
                    // 
                    // This indicates a bug in one of the ACE classes.
                    // Binary length of an ace must ALWAYS be divisible by 4. 
                    // 

                    BCLDebug.Assert( false, "aceLength % 4 != 0" ); 
                    throw new SystemException();
                }

                int newBinaryLength = BinaryLength - ( index < _aces.Count ? ( _aces[index] as GenericAce ).BinaryLength : 0 ) + value.BinaryLength; 

                if ( newBinaryLength > MaxBinaryLength ) 
                { 
                    throw new OverflowException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
                } 

                _aces[index] = value;

                _binaryLength = newBinaryLength; 
            }
        } 
 
        //
        // Adds an ACE at the specified index 
        //

        public void InsertAce( int index, GenericAce ace )
        { 
            if ( ace == null )
            { 
                throw new ArgumentNullException( "ace" ); 
            }
 
            if ( _binaryLength + ace.BinaryLength > MaxBinaryLength )
            {
                throw new OverflowException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
            } 

            _aces.Insert( index, ace ); 
            _binaryLength += ace.BinaryLength; 
        }
 
        //
        // Removes an ACE at the specified index
        //
 
        public void RemoveAce( int index )
        { 
            GenericAce ace = _aces[index] as GenericAce; 
            _aces.RemoveAt( index );
            _binaryLength -= ace.BinaryLength; 
        }

        #endregion
    } 

 
    public abstract class CommonAcl : GenericAcl 
    {
        #region Add/Remove Logic Support 

        [Flags]
        private enum AF    // ACE flags
        { 
            CI        = 0x8,    // container inherit
            OI        = 0x4,    // object inherit 
            IO        = 0x2,    // inherit only 
            NP        = 0x1,    // no propagate inherit
            Invalid   = NP,     // not a valid combination of flags 
        }

        [Flags]
        private enum PM    // Propagation matrix 
        {
            F         = 0x10,    // folder 
            CF        = 0x08,    // child folder 
            CO        = 0x04,    // child object
            GF        = 0x02,    // grandchild folder 
            GO        = 0x01,    // grandchild object
            Invalid   = GO,      // not a valid combination of flags
        }
 
        private static PM[] AFtoPM;    // AceFlags-to-Propagation conversion matrix
        private static AF[] PMtoAF;    // Propagation-to-AceFlags conversion matrix 
 
        static CommonAcl()
        { 
            AFtoPM = new PM[16];

            for ( int i = 0; i < AFtoPM.Length; i++ )
            { 
                AFtoPM[i] = PM.Invalid;
            } 
 
            //
            // This table specifies what effect various combinations of inheritance bits 
            // have on how ACEs are inherited onto child objects
            // Important: Not all combinations of inheritance bits are valid
            //
 
            AFtoPM[( int )(   0   |   0   |   0   |   0   )] = PM.F |   0   |   0   |   0   |   0   ;
            AFtoPM[( int )(   0   | AF.OI |   0   |   0   )] = PM.F |   0   | PM.CO |   0   | PM.GO ; 
            AFtoPM[( int )(   0   | AF.OI |   0   | AF.NP )] = PM.F |   0   | PM.CO |   0   |   0   ; 
            AFtoPM[( int )(   0   | AF.OI | AF.IO |   0   )] =   0  |   0   | PM.CO |   0   | PM.GO ;
            AFtoPM[( int )(   0   | AF.OI | AF.IO | AF.NP )] =   0  |   0   | PM.CO |   0   |   0   ; 
            AFtoPM[( int )( AF.CI |   0   |   0   |   0   )] = PM.F | PM.CF |   0   | PM.GF |   0   ;
            AFtoPM[( int )( AF.CI |   0   |   0   | AF.NP )] = PM.F | PM.CF |   0   |   0   |   0   ;
            AFtoPM[( int )( AF.CI |   0   | AF.IO |   0   )] =   0  | PM.CF |   0   | PM.GF |   0   ;
            AFtoPM[( int )( AF.CI |   0   | AF.IO | AF.NP )] =   0  | PM.CF |   0   |   0   |   0   ; 
            AFtoPM[( int )( AF.CI | AF.OI |   0   |   0   )] = PM.F | PM.CF | PM.CO | PM.GF | PM.GO ;
            AFtoPM[( int )( AF.CI | AF.OI |   0   | AF.NP )] = PM.F | PM.CF | PM.CO |   0   |   0   ; 
            AFtoPM[( int )( AF.CI | AF.OI | AF.IO |   0   )] =   0  | PM.CF | PM.CO | PM.GF | PM.GO ; 
            AFtoPM[( int )( AF.CI | AF.OI | AF.IO | AF.NP )] =   0  | PM.CF | PM.CO |   0   |   0   ;
 
            PMtoAF = new AF[32];

            for ( int i = 0; i < PMtoAF.Length; i++ )
            { 
                PMtoAF[i] = AF.Invalid;
            } 
 
            //
            // This table is a reverse lookup table of the AFtoPM table 
            // Given how inheritance is applied to child objects and containers,
            // it helps figure out whether that pattern is expressible using
            // the four ACE inheritance bits
            // 

            PMtoAF[( int )( PM.F |   0   |   0   |   0   |   0   )] =    0   |   0   |   0   |   0   ; 
            PMtoAF[( int )( PM.F |   0   | PM.CO |   0   | PM.GO )] =    0   | AF.OI |   0   |   0   ; 
            PMtoAF[( int )( PM.F |   0   | PM.CO |   0   |   0   )] =    0   | AF.OI |   0   | AF.NP ;
            PMtoAF[( int )(   0  |   0   | PM.CO |   0   | PM.GO )] =    0   | AF.OI | AF.IO |   0   ; 
            PMtoAF[( int )(   0  |   0   | PM.CO |   0   |   0   )] =    0   | AF.OI | AF.IO | AF.NP ;
            PMtoAF[( int )( PM.F | PM.CF |   0   | PM.GF |   0   )] =  AF.CI |   0   |   0   |   0   ;
            PMtoAF[( int )( PM.F | PM.CF |   0   |   0   |   0   )] =  AF.CI |   0   |   0   | AF.NP ;
            PMtoAF[( int )(   0  | PM.CF |   0   | PM.GF |   0   )] =  AF.CI |   0   | AF.IO |   0   ; 
            PMtoAF[( int )(   0  | PM.CF |   0   |   0   |   0   )] =  AF.CI |   0   | AF.IO | AF.NP ;
            PMtoAF[( int )( PM.F | PM.CF | PM.CO | PM.GF | PM.GO )] =  AF.CI | AF.OI |   0   |   0   ; 
            PMtoAF[( int )( PM.F | PM.CF | PM.CO |   0   |   0   )] =  AF.CI | AF.OI |   0   | AF.NP ; 
            PMtoAF[( int )(   0  | PM.CF | PM.CO | PM.GF | PM.GO )] =  AF.CI | AF.OI | AF.IO |   0   ;
            PMtoAF[( int )(   0  | PM.CF | PM.CO |   0   |   0   )] =  AF.CI | AF.OI | AF.IO | AF.NP ; 
        }

        //
        // Canonicalizes AceFlags into a form that the mapping tables understand 
        //
 
        private static AF AFFromAceFlags( AceFlags aceFlags, bool isDS ) 
        {
            AF af = 0; 

            if (( aceFlags & AceFlags.ContainerInherit ) != 0)
            {
                af |= AF.CI; 
            }
 
            // 
            // ObjectInherit applies only to regular aces not object aces
            // so it can be ignored in the object aces case 
            //
            if (( !isDS ) && (( aceFlags & AceFlags.ObjectInherit ) != 0 ))
            {
                af |= AF.OI; 
            }
 
            if (( aceFlags & AceFlags.InheritOnly ) != 0 ) 
            {
                af |= AF.IO; 
            }

            if (( aceFlags & AceFlags.NoPropagateInherit ) != 0 )
            { 
                af |= AF.NP;
            } 
 
            return af;
        } 

        //
        // Converts lookup table representation of AceFlags into the "public" form
        // 

        private static AceFlags AceFlagsFromAF( AF af, bool isDS ) 
        { 
            AceFlags aceFlags = 0;
 
            if (( af & AF.CI ) != 0 )
            {
                aceFlags |= AceFlags.ContainerInherit;
            } 

            // 
            // ObjectInherit applies only to regular aces not object aces 
            // so it can be ignored in the object aces case
            // 
            if (( !isDS ) && (( af & AF.OI ) != 0 ))
            {
                aceFlags |= AceFlags.ObjectInherit;
            } 

            if (( af & AF.IO ) != 0 ) 
            { 
                aceFlags |= AceFlags.InheritOnly;
            } 

            if (( af & AF.NP ) != 0 )
            {
                aceFlags |= AceFlags.NoPropagateInherit; 
            }
 
            return aceFlags; 
        }
 
        //
        // Implements the merge of inheritance bits during the 'ADD' operation
        //
 
        private static bool MergeInheritanceBits( AceFlags left, AceFlags right, bool isDS, out AceFlags result )
        { 
            result = 0; 

            AF leftAF = AFFromAceFlags( left, isDS ); 
            AF rightAF = AFFromAceFlags( right, isDS );

            PM leftPM = AFtoPM[(int)leftAF];
            PM rightPM = AFtoPM[(int)rightAF]; 

            if ( leftPM == PM.Invalid || rightPM == PM.Invalid ) 
            { 
                return false; // incorrect ACE flags?
            } 

            PM resultPM = leftPM | rightPM;
            AF resultAF = PMtoAF[( int )resultPM];
 
            if ( resultAF == AF.Invalid )
            { 
                return false; 
            }
            else 
            {
                result = AceFlagsFromAF( resultAF, isDS );
                return true;
            } 
        }
 
        private static bool RemoveInheritanceBits( AceFlags existing, AceFlags remove, bool isDS, out AceFlags result, out bool total ) 
        {
            result = 0; 
            total = false;

            AF leftAF = AFFromAceFlags( existing, isDS );
            AF rightAF = AFFromAceFlags( remove, isDS ); 

            PM leftPM = AFtoPM[( int )leftAF]; 
            PM rightPM = AFtoPM[( int )rightAF]; 

            if ( leftPM == PM.Invalid || rightPM == PM.Invalid ) 
            {
                return false; // incorrect ACE flags?
            }
 
            PM resultPM;
            unchecked { resultPM = leftPM & ~rightPM; } 
 
            //
            // If the resulting propagation matrix is zero, 
            // communicate back the fact that removal is "total"
            //

            if ( resultPM == 0 ) 
            {
                total = true; 
                return true; 
            }
 
            AF resultAF = PMtoAF[( int )resultPM];

            if ( resultAF == AF.Invalid )
            { 
                return false;
            } 
            else 
            {
                result = AceFlagsFromAF( resultAF, isDS ); 
                return true;
            }
        }
 
        #endregion
 
        #region Private Members 

        private RawAcl _acl; 
        private bool _isDirty = false;
        private readonly bool _isCanonical;
        private readonly bool _isContainer;
 
        //
        // To distinguish between a directory object acl and other common acls. 
        // 

        private readonly bool _isDS; 

        #endregion

        #region Private Methods 

        private void CanonicalizeIfNecessary() 
        { 
            if ( _isDirty )
            { 
                Canonicalize( false, this is DiscretionaryAcl );
                _isDirty = false;
            }
        } 

        private enum ComparisonResult 
        { 
            LessThan,
            EqualTo, 
            GreaterThan,
        }

        // 
        // Compares two discretionary ACEs and returns
        //    LessThan if ace1 < ace2 
        //    EqualTo if ace1 == ace2 
        //    GreaterThan if ace1 > ace2
        // 
        // The order is:
        //        - explicit Access Denied ACEs
        //          [regular aces first, then object aces]
        //        - explicit Access Allowed ACEs 
        //          [regular aces first, then object aces]
        //        - inherited ACEs (in the original order ) 
        //        - user-defined ACEs (in the original order ) 
        //
 
        private static int DaclAcePriority( GenericAce ace)
        {
            int result;
            AceType type = ace.AceType; 

            if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
            { 
                //
                // inherited aces are at the end as a group 
                //

                result = 2 * ushort.MaxValue + ace._indexInAcl;
            } 
            else if ( type == AceType.AccessDenied ||
                type == AceType.AccessDeniedCallback ) 
            { 
                result = 0;
            } 
            else if ( type == AceType.AccessDeniedObject ||
                type == AceType.AccessDeniedCallbackObject )
            {
                result = 1; 
            }
            else if ( type == AceType.AccessAllowed || 
                type == AceType.AccessAllowedCallback ) 
            {
                result = 2; 
            }
            else if ( type == AceType.AccessAllowedObject ||
                type == AceType.AccessAllowedCallbackObject )
            { 
                result = 3;
            } 
            else 
            {
                // 
                // custom aces are at the second group
                //
                result = ushort.MaxValue + ace._indexInAcl;
            } 

            return result; 
        } 

        // 
        // Compares two system ACEs and returns
        //    LessThan if ace1 < ace2
        //    EqualTo if ace1 == ace2
        //    GreaterThan if ace1 > ace2 
        //
        // The order is: 
        //        - explicit audit or alarm ACEs 
        //        - explicit audit or alarm object ACEs
        //        - inherited ACEs (in the original order ) 
        //        - user-defined ACEs (in the original order )
        //

        private static int SaclAcePriority( GenericAce ace ) 
        {
            int result; 
            AceType type = ace.AceType; 

            if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
            {
                result = 2 * ushort.MaxValue + ace._indexInAcl;
            }
            else if ( type == AceType.SystemAudit || 
                type == AceType.SystemAlarm ||
                type == AceType.SystemAuditCallback || 
                type == AceType.SystemAlarmCallback ) 
            {
                result = 0; 
            }
            else if ( type == AceType.SystemAuditObject ||
                type == AceType.SystemAlarmObject ||
                type == AceType.SystemAuditCallbackObject || 
                type == AceType.SystemAlarmCallbackObject )
            { 
                result = 1; 
            }
            else 
            {
                result = ushort.MaxValue + ace._indexInAcl;
            }
 
            return result;
        } 
 
        private static ComparisonResult CompareAces( GenericAce ace1, GenericAce ace2, bool isDacl )
        { 
            int ace1Priority = isDacl ? DaclAcePriority( ace1 ) : SaclAcePriority( ace1 );
            int ace2Priority = isDacl ? DaclAcePriority( ace2 ) : SaclAcePriority( ace2 );

            if ( ace1Priority < ace2Priority ) 
            {
                return ComparisonResult.LessThan; 
            } 
            else if ( ace1Priority > ace2Priority )
            { 
                return ComparisonResult.GreaterThan;
            }
            else
            { 
                KnownAce k_ace1 = ace1 as KnownAce;
                KnownAce k_ace2 = ace2 as KnownAce; 
 
                if ( k_ace1 != null && k_ace2 != null )
                { 
                    int result = k_ace1.SecurityIdentifier.CompareTo( k_ace2.SecurityIdentifier );

                    if ( result < 0 )
                    { 
                        return ComparisonResult.LessThan;
                    } 
                    else if ( result > 0 ) 
                    {
                        return ComparisonResult.GreaterThan; 
                    }
                }

                return ComparisonResult.EqualTo; 
            }
        } 
 
        private void QuickSort( int left, int right, bool isDacl )
        { 
            GenericAce pivot;
            int leftHold, rightHold;
            int pivotIndex;
 
            if ( left >= right )
            { 
                return; 
            }
 
            leftHold = left;
            rightHold = right;

            pivot = _acl[left]; 
            pivotIndex = left;
 
            while ( left < right ) 
            {
//              while (( _acl[right] >= pivot ) && ( left < right )) 
                while (( ComparisonResult.LessThan != CompareAces( _acl[right], pivot, isDacl ) ) && ( left < right ))
                {
                    right--;
                } 

                if ( left != right ) 
                { 
                    _acl[left] = _acl[right];
                    left++; 
                }

//              while (( _acl[left] <= pivot ) && ( left < right ))
                while (( ComparisonResult.GreaterThan != CompareAces( _acl[left], pivot, isDacl ) ) && ( left < right )) 
                {
                    left++; 
                } 

                if ( left != right ) 
                {
                    _acl[right] = _acl[left];
                    right--;
                } 
            }
 
            _acl[left] = pivot; 
            pivotIndex = left;
            left = leftHold; 
            right = rightHold;

            if ( left < pivotIndex )
            { 
                QuickSort( left, pivotIndex - 1, isDacl );
            } 
 
            if ( right > pivotIndex )
            { 
                QuickSort( pivotIndex + 1, right, isDacl );
            }
        }
 
        //
        // Inspects the ACE, modifies it by stripping away unnecessary or 
        // meaningless flags. 
        // Returns 'true' if the ACE should remain in the ACL, 'false' otherwise
        // 

        private bool InspectAce( ref GenericAce ace, bool isDacl )
        {
            const AceFlags AuditFlags = 
                AceFlags.SuccessfulAccess |
                AceFlags.FailedAccess; 
 
            const AceFlags InheritFlags =
                AceFlags.ObjectInherit | 
                AceFlags.ContainerInherit |
                AceFlags.NoPropagateInherit |
                AceFlags.InheritOnly;
 
            //
            // Any ACE without at least one bit set in the access mask can be removed 
            // 

            KnownAce knownAce = ace as KnownAce; 

            if ( knownAce != null )
            {
                if ( knownAce.AccessMask == 0 ) 
                {
                    return false; 
                } 
            }
 
            if ( !IsContainer )
            {
                //
                // On a leaf object ACL, inheritance bits are meaningless. 
                // Specifically, an ACE marked "inherit-only" will never participate
                // in access control and can be removed. 
                // Similarly, an ACE marked "container-inherit", "no-propagate-inherit" 
                // or "object-inherit" can have those bits cleared since they carry
                // no meaning. 
                //

                if (( ace.AceFlags & AceFlags.InheritOnly ) != 0 )
                { 
                    return false;
                } 
 
                if (( ace.AceFlags & InheritFlags ) != 0 )
                { 
                    unchecked { ace.AceFlags &= ~InheritFlags; }
                }
            }
            else 
            {
                // 
                // Without either "container inherit" or "object inherit" to go with it, 
                // the InheritOnly bit is meaningless and the entire ACE can be removed.
                // 

                if ((( ace.AceFlags & AceFlags.InheritOnly ) != 0 ) &&
                    (( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) &&
                    (( ace.AceFlags & AceFlags.ObjectInherit ) == 0 )) 
                {
                    return false; 
                } 

                // 
                // Without either "container inherit" or "object inherit" to go with it,
                // the NoPropagateInherit bit is meaningless and can be turned off.
                //
                if ((( ace.AceFlags & AceFlags.NoPropagateInherit ) != 0 ) && 
                    (( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) &&
                    (( ace.AceFlags & AceFlags.ObjectInherit ) == 0 )) 
                { 
                    unchecked { ace.AceFlags &= ~AceFlags.NoPropagateInherit; }
                } 
            }

            QualifiedAce qualifiedAce = knownAce as QualifiedAce;
 
            if ( isDacl )
            { 
                // 
                // There is no place for audit flags on a DACL
                // 

                unchecked { ace.AceFlags &= ~AuditFlags; }

                if ( qualifiedAce != null ) 
                {
                    // 
                    // Qualified ACEs in a DACL must be allow or deny ACEs 
                    //
 
                    if ( qualifiedAce.AceQualifier != AceQualifier.AccessAllowed &&
                        qualifiedAce.AceQualifier != AceQualifier.AccessDenied )
                    {
                        return false; 
                    }
                } 
            } 
            else
            { 
                //
                // On a SACL, any ACE that does not specify Success or Failure
                // flags can be removed
                // 

                if (( ace.AceFlags & AuditFlags ) == 0 ) 
                { 
                    return false;
                } 

                //
                // Qualified ACEs in a SACL must be audit ACEs
                // 

                if ( qualifiedAce != null ) 
                { 
                    if ( qualifiedAce.AceQualifier != AceQualifier.SystemAudit )
                    { 
                        return false;
                    }
                }
            } 
            return true;
        } 
 
        //
        // Strips meaningless flags from ACEs, removes meaningless ACEs 
        //

        private void RemoveMeaninglessAcesAndFlags( bool isDacl )
        { 
            //
            // Be warned: do NOT use the Count property because it has 
            // side-effect of calling canonicalization. 
            //
 
            for ( int i = _acl.Count - 1; i >= 0; i-- )
            {
                GenericAce ace = _acl[i];
 
                if ( false == InspectAce( ref ace, isDacl ))
                { 
                    _acl.RemoveAce( i ); 
                }
            } 
        }

        //
        // Converts the ACL to its canonical form 
        //
 
        private void Canonicalize( bool compact, bool isDacl ) 
        {
            // 
            // for quick sort to work, we must not allow the ace's indexes - which are constantly
            // changing during sorting - to influence our element's sorting order value. For
            // that purpose, we fix the ace's _indexInAcl here and use it for creating the
            // ace's sorting order value. 
            //
 
            for (ushort aclIndex = 0; aclIndex < _acl.Count; aclIndex++) 
            {
                _acl[aclIndex]._indexInAcl = aclIndex; 
            }

            QuickSort( 0, _acl.Count - 1, isDacl );
 
            if ( compact )
            { 
                for ( int i = 0; i < Count - 1; i++ ) 
                {
                    QualifiedAce thisAce = _acl[i] as QualifiedAce; 

                    if ( thisAce == null )
                    {
                        continue; 
                    }
 
                    QualifiedAce nextAce = _acl[i + 1] as QualifiedAce; 

                    if ( nextAce == null ) 
                    {
                        continue;
                    }
 
                    if ( true == MergeAces( ref thisAce, nextAce ))
                    { 
                        _acl.RemoveAce(i + 1); 
                    }
                } 
            }
        }

        // 
        // This method determines whether the object type and inherited object type from the original ace
        // should be retained or not based on access mask and aceflags for a given split 
        // 
        private void GetObjectTypesForSplit( ObjectAce originalAce, int accessMask, AceFlags aceFlags, out ObjectAceFlags objectFlags, out Guid objectType, out Guid inheritedObjectType )
        { 

            objectFlags = 0;
            objectType = Guid.Empty;
            inheritedObjectType = Guid.Empty; 

            // 
            // We should retain the object type if the access mask for this split contains any bits that refer to object type 
            //
            if (( accessMask & ObjectAce.AccessMaskWithObjectType ) != 0 ) 
            {
                // keep the original ace's object flags and object type
                objectType = originalAce.ObjectAceType;
                objectFlags |= originalAce.ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent; 
            }
 
            // 
            // We should retain the inherited object type if the aceflags for this contains inheritance (ContainerInherit)
            // 
            if (( aceFlags & AceFlags.ContainerInherit ) != 0 )
            {
                // keep the original ace's object flags and object type
                inheritedObjectType = originalAce.InheritedObjectAceType; 
                objectFlags |= originalAce.ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent;
            } 
        } 

        private bool ObjectTypesMatch( QualifiedAce ace, QualifiedAce newAce ) 
        {
            Guid objectType = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceType : Guid.Empty;
            Guid newObjectType = ( newAce is ObjectAce ) ? (( ObjectAce ) newAce ).ObjectAceType : Guid.Empty;
 
            return objectType.Equals( newObjectType );
        } 
 
        private bool InheritedObjectTypesMatch( QualifiedAce ace, QualifiedAce newAce )
        { 
            Guid inheritedObjectType = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).InheritedObjectAceType : Guid.Empty;
            Guid newInheritedObjectType = ( newAce is ObjectAce ) ? (( ObjectAce ) newAce ).InheritedObjectAceType : Guid.Empty;

            return inheritedObjectType.Equals( newInheritedObjectType ); 
        }
 
        private bool AccessMasksAreMergeable( QualifiedAce ace, QualifiedAce newAce ) 
        {
            // 
            // The access masks are mergeable in any of the following conditions
            // 1. Object types match
            // 2. (Object types do not match) The existing ace does not have an object type and
            //     already contains all the bits of the new ace which refer to the object type 
            //
 
            if ( ObjectTypesMatch( ace, newAce )) 
            {
                // case 1 
                return true;
            }

            ObjectAceFlags objectFlags = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceFlags : ObjectAceFlags.None; 
            if ((( ace.AccessMask & newAce.AccessMask & ObjectAce.AccessMaskWithObjectType ) ==  ( newAce.AccessMask & ObjectAce.AccessMaskWithObjectType )) &&
                 (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 )) 
            { 
                // case 2
                return true; 
            }

            return false;
        } 

        private bool AceFlagsAreMergeable( QualifiedAce ace, QualifiedAce newAce ) 
        { 
            //
            // The ace flags can be considered for merge in any of the following conditions 
            // 1. Inherited object types match
            // 2. (Inherited object types do not match) The existing ace does not have an inherited object type and
            //     already contains all the bits of the new ace
            // 

            if ( InheritedObjectTypesMatch( ace, newAce )) 
            { 
                // case 1
                return true; 
            }

            ObjectAceFlags objectFlags = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceFlags : ObjectAceFlags.None;
            if (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 ) 
            {
                // case 2 
 
                //
                // This method is called only when the access masks of the two aces are already confirmed to be exact matches 
                // therefore the second condition of case 2 is already verified
                //
                BCLDebug.Assert(( ace.AccessMask & newAce.AccessMask) ==  newAce.AccessMask, "AceFlagsAreMergeable:: AccessMask of existing ace does not contain all access bits of new ace.");
                return true; 
            }
 
            return false; 
        }
 
        private bool GetAccessMaskForRemoval( QualifiedAce ace, ObjectAceFlags objectFlags, Guid objectType, ref int accessMask )
        {
            if (( ace.AccessMask & accessMask & ObjectAce.AccessMaskWithObjectType ) != 0 )
            { 

                // 
                // If the aces have access bits in common which refer to object types 
                // then we follow these rules:
                // 
                //       Remove    No OT    OT = A        OT = B
                // Existing
                //
                //   No OT          Remove   Invalid        Invalid 
                //
                //   OT = A        Remove   Remove      Nothing Common 
                // 

 
                if ( ace is ObjectAce )
                {
                    bool commonAccessBitsWithObjectTypeExist = true;
                    ObjectAce objectAce = ace as ObjectAce; 

                    // 
                    // if what we are trying to remove has an object type 
                    // but the existing ace does not then this is an invalid case
                    // 
                    if ((( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 ) &&
                        (( objectAce.ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 ))
                    {
                        return false; 
                    }
 
                    // 
                    // if what we are trying to remove has no object type or
                    // if object types match (since at this point we have ensured that both have object types present) 
                    // then we have common access bits with object type
                    //
                    commonAccessBitsWithObjectTypeExist = (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 ) ||
                                                                                    objectAce.ObjectTypesMatch( objectFlags, objectType ); 
                    if ( !commonAccessBitsWithObjectTypeExist )
                    { 
                        accessMask &= ~ObjectAce.AccessMaskWithObjectType; 
                    }
                } 
                else if (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 )
                {
                    // the existing ace is a common ace and the one we're removing
                    // refers to a specific object type so this is invalid 
                    return false;
                } 
            } 

            return true; 

        }

        private bool GetInheritanceFlagsForRemoval( QualifiedAce ace, ObjectAceFlags objectFlags, Guid inheritedObjectType, ref AceFlags aceFlags ) 
        {
            if ((( ace.AceFlags & AceFlags.ContainerInherit ) != 0 )  && (( aceFlags & AceFlags.ContainerInherit ) != 0 )) 
            { 

                // 
                // If the aces have inheritance bits in common
                // then we follow these rules:
                //
                //       Remove    No IOT    IOT = A        IOT = B 
                // Existing
                // 
                //   No IOT          Remove   Invalid        Invalid 
                //
                //   IOT = A        Remove   Remove      Nothing Common 
                //


                if ( ace is ObjectAce ) 
                {
                    bool commonInheritanceFlagsExist = true; 
                    ObjectAce objectAce = ace as ObjectAce; 

                    // 
                    // if what we are trying to remove has an inherited object type
                    // but the existing ace does not then this is an invalid case
                    //
                    if ((( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) != 0 ) && 
                        (( objectAce.ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 ))
                    { 
                        return false; 
                    }
 
                    //
                    // if what we are trying to remove has no inherited object type or
                    // if inherited object types match then we have common inheritance flags
                    // 
                    commonInheritanceFlagsExist = (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 ) ||
                                                                       objectAce.InheritedObjectTypesMatch( objectFlags, inheritedObjectType ); 
                    if ( !commonInheritanceFlagsExist ) 
                    {
                        aceFlags &= ~AceFlags.InheritanceFlags; 
                    }
                }
                else if (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) != 0 )
                { 
                    // the existing ace is a common ace and the one we're removing
                    // refers to a specific child type so this is invalid 
                    return false; 
                }
            } 

            return true;

        } 

        // 
        // Merge routine for qualified ACEs 
        //
 
        private bool MergeAces( ref QualifiedAce ace, QualifiedAce newAce )
        {
            //
            // Only interested in explicit (non-inherited) ACEs 
            //
 
            if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
            {
                return false; 
            }

            if (( newAce.AceFlags & AceFlags.Inherited ) != 0 )
            { 
                return false;
            } 
 
            //
            // Only interested in ACEs with the specified qualifier 
            //

            if ( ace.AceQualifier != newAce.AceQualifier )
            { 
                return false;
            } 
 
            //
            // Only interested in ACEs with the specified SID 
            //

            if ( ace.SecurityIdentifier != newAce.SecurityIdentifier )
            { 
                return false;
            } 
 
            //
            // The modification algorithm proceeds in stages 
            //
            // Stage 1: if flags match, add to the access mask
            //
 
            if ( ace.AceFlags == newAce.AceFlags )
            { 
                if ( ace is ObjectAce  || newAce is ObjectAce ) 
                {
                    // for object aces we need to match the inherited object types (for ace flags equality) 
                    if ( InheritedObjectTypesMatch( ace, newAce ))
                    {
                        // also since access mask bits are further qualified by object type, they cannot always be added on
                        if ( AccessMasksAreMergeable( ace, newAce )) 
                        {
                            ace.AccessMask |= newAce.AccessMask; 
                            return true; 
                        }
                    } 
                }
                else
                {
                    ace.AccessMask |= newAce.AccessMask; 
                    return true;
                } 
            } 

 

            //
            // Stage 2: Audit flags can be combined if the rest of the
            //          flags (both access mask and inheritance) match 
            //
 
            if ((( ace.AceFlags & AceFlags.InheritanceFlags ) == ( newAce.AceFlags & AceFlags.InheritanceFlags )) && 
                ( ace.AccessMask == newAce.AccessMask ))
            { 
                if (( ace is ObjectAce ) || ( newAce is ObjectAce ))
                {
                    // for object aces we need to match the inherited object types (for inheritance flags equality) and object type (for access mask equality) as well
                    if ( InheritedObjectTypesMatch( ace, newAce ) && 
                        ( ObjectTypesMatch( ace, newAce )))
                    { 
                        ace.AceFlags |= ( newAce.AceFlags & AceFlags.AuditFlags ); 
                        return true;
                    } 
                }
                else
                {
                    ace.AceFlags |= ( newAce.AceFlags & AceFlags.AuditFlags ); 
                    return true;
                } 
 
            }
 
            //
            // Stage 3: Inheritance flags can be combined in some cases
            //          provided access mask and audit bits are the same
            // 

            if ((( ace.AceFlags & AceFlags.AuditFlags ) == ( newAce.AceFlags & AceFlags.AuditFlags )) && 
                ( ace.AccessMask == newAce.AccessMask )) 
            {
                AceFlags merged; 

                //
                // See whether the inheritance bits can be merged
                // 

                if (( ace is ObjectAce ) || ( newAce is ObjectAce )) 
                { 
                    // object types need to match (for access mask equality) and inheritance flags need additional DS specific logic
                    // to check whether they can be merged 
                    if (( ObjectTypesMatch( ace, newAce )) &&
                         ( AceFlagsAreMergeable( ace, newAce )))
                    {
                        if ( true == MergeInheritanceBits( ace.AceFlags, newAce.AceFlags, IsDS, out merged )) 
                        {
                            ace.AceFlags = ( merged | ( ace.AceFlags & AceFlags.AuditFlags )); 
                            return true; 
                        }
                    } 
                }
                else
                {
                    if ( true == MergeInheritanceBits( ace.AceFlags, newAce.AceFlags, IsDS, out merged )) 
                    {
                        ace.AceFlags = ( merged | ( ace.AceFlags & AceFlags.AuditFlags )); 
                        return true; 
                    }
                } 

            }

            return false; 
        }
 
        // 
        // Returns 'true' if the ACL is in canonical order; 'false' otherwise
        // 

        private bool CanonicalCheck( bool isDacl )
        {
            if ( isDacl ) 
            {
                // 
                // DACL canonical order: 
                //   Explicit Deny - Explicit Allow - Inherited
                // 

                const int AccessDenied = 0;
                const int AccessAllowed = 1;
                const int Inherited = 2; 
                const int Unknown = 3;
 
                int currentStage = AccessDenied; 

                // 
                // In this loop, do NOT use 'Count' as upper bound of the loop,
                // since doing so will canonicalize the ACL invalidating the result
                // of this check!
                // 

                for ( int i = 0; i < _acl.Count; i++ ) 
                { 
                    int aceStage = Unknown;
 
                    GenericAce ace = _acl[i];

                    if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
                    { 
                        aceStage = Inherited;
                    } 
                    else 
                    {
                        QualifiedAce qualifiedAce = ace as QualifiedAce; 

                        if ( qualifiedAce == null )
                        {
                            // 
                            // Explicit ACE is not recognized - this is not a canonical ACL
                            // 
 
                            return false;
                        } 

                        if ( qualifiedAce.AceQualifier == AceQualifier.AccessAllowed )
                        {
                            aceStage = AccessAllowed; 
                        }
                        else if ( qualifiedAce.AceQualifier == AceQualifier.AccessDenied ) 
                        { 
                            aceStage = AccessDenied;
                        } 
                        else
                        {
                            //
                            // Only allow and deny ACEs are allowed here 
                            //
 
                            BCLDebug.Assert( false, "Audit and alarm ACEs must have been stripped by remove-meaningless logic" ); 
                            return false;
                        } 
                    }

                    if ( aceStage == Unknown )
                    { 
                        continue;
                    } 
 
                    if ( aceStage > currentStage )
                    { 
                        currentStage = aceStage;
                    }
                    else if ( aceStage < currentStage )
                    { 
                        return false;
                    } 
                } 
            }
            else 
            {
                //
                // SACL canonical order:
                //   Explicit - Inherited 
                //
 
                const int Explicit = 0; 
                const int Inherited = 1;
                const int Unknown = 2; 

                int currentStage = Explicit;

                // 
                // In this loop, do NOT use 'Count' as upper bound of the loop,
                // since doing so will canonicalize the ACL invalidating the result 
                // of this check! 
                //
 
                for ( int i = 0; i < _acl.Count; i++ )
                {
                    int aceStage = Unknown;
 
                    GenericAce ace = _acl[i];
 
                    if ( ace == null ) 
                    {
                        // 
                        // <[....]-9/19/2004> Afraid to yank this statement now
                        // for fear of destabilization, so adding an assert instead
                        //
 
                        BCLDebug.Assert( ace != null, "How did a null ACE end up in a SACL?" );
                        continue; 
                    } 

                    if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
                    {
                        aceStage = Inherited;
                    }
                    else 
                    {
                        QualifiedAce qualifiedAce = ace as QualifiedAce; 
 
                        if ( qualifiedAce == null )
                        { 
                            //
                            // Explicit ACE is not recognized - this is not a canonical ACL
                            //
 
                            return false;
                        } 
 
                        if ( qualifiedAce.AceQualifier == AceQualifier.SystemAudit ||
                            qualifiedAce.AceQualifier == AceQualifier.SystemAlarm ) 
                        {
                            aceStage = Explicit;
                        }
                        else 
                        {
                            // 
                            // Only audit and alarm ACEs are allowed here 
                            //
 
                            BCLDebug.Assert( false, "Allow and deny ACEs must have been stripped by remove-meaningless logic" );
                            return false;
                        }
                    } 

                    if ( aceStage > currentStage ) 
                    { 
                        currentStage = aceStage;
                    } 
                    else if ( aceStage < currentStage )
                    {
                        return false;
                    } 
                }
            } 
 
            return true;
        } 

        private void ThrowIfNotCanonical()
        {
            if ( !_isCanonical ) 
            {
                throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_ModificationOfNonCanonicalAcl" )); 
            } 
        }
 
        #endregion

        #region Constructors
 
        //
        // Creates an empty ACL 
        // 

        internal CommonAcl( bool isContainer, bool isDS, byte revision, int capacity ) 
            : base()
        {
            _isContainer = isContainer;
            _isDS = isDS; 
            _acl = new RawAcl( revision, capacity );
            _isCanonical = true; // since it is empty 
        } 

        // 
        // Creates an ACL from a raw ACL
        // - 'trusted' (internal) callers get to pass the raw ACL
        //   that this object will take ownership of
        // - 'untrusted' callers are handled by creating a local 
        //   copy of the ACL passed in
        // 
 
        internal CommonAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted, bool isDacl )
            : base() 
        {
            _isContainer = isContainer;
            _isDS = isDS;
 
            if ( rawAcl == null )
            { 
                throw new ArgumentNullException( "rawAcl" ); 
            }
 
            if ( trusted )
            {
                //
                // In the trusted case, we take over ownership of the ACL passed in 
                //
 
                _acl = rawAcl; 

                RemoveMeaninglessAcesAndFlags( isDacl ); 
            }
            else
            {
                // 
                // In the untrusted case, we create our own raw ACL to keep the ACEs in
                // 
 
                _acl = new RawAcl( rawAcl.Revision, rawAcl.Count );
 
                for ( int i = 0; i < rawAcl.Count; i++ )
                {
                    //
                    // Clone each ACE prior to putting it in 
                    //
 
                    GenericAce ace = rawAcl[i].Copy(); 

                    // 
                    // Avoid inserting meaningless ACEs
                    //

                    if ( true == InspectAce( ref ace, isDacl )) 
                    {
                        _acl.InsertAce( _acl.Count, ace ); 
                    } 
                }
            } 

            //
            // See whether the ACL is canonical to begin with
            // 

            if ( true == CanonicalCheck( isDacl )) 
            { 
                //
                // Sort and compact the array 
                //

                Canonicalize( true, isDacl );
 
                _isCanonical = true;
            } 
            else 
            {
                _isCanonical = false; 
            }
        }

        #endregion 

        #region Internal Properties 
 
        internal RawAcl RawAcl
        { 
            get { return _acl; }
        }

        #endregion 

        #region Protected Methods 
 
        internal void CheckAccessType( AccessControlType accessType )
        { 
            if ( accessType != AccessControlType.Allow &&
                accessType != AccessControlType.Deny )
            {
                throw new ArgumentOutOfRangeException( 
                    "accessType",
                    Environment.GetResourceString( "ArgumentOutOfRange_Enum" )); 
            } 
        }
 
        internal void CheckFlags( InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        {
            if ( IsContainer )
            { 
                //
                // Supplying propagation flags without inheritance flags is illegal 
                // 

                if ( inheritanceFlags == InheritanceFlags.None && 
                    propagationFlags != PropagationFlags.None )
                {
                    throw new ArgumentException(
                        Environment.GetResourceString( "Argument_InvalidAnyFlag" ), 
                        "propagationFlags" );
                } 
            } 
            else if ( inheritanceFlags != InheritanceFlags.None )
            { 
                throw new ArgumentException(
                    Environment.GetResourceString("Argument_InvalidAnyFlag"),
                    "inheritanceFlags" );
            } 
            else if ( propagationFlags != PropagationFlags.None )
            { 
                throw new ArgumentException( 
                    Environment.GetResourceString( "Argument_InvalidAnyFlag" ),
                    "propagationFlags" ); 
            }

            return;
        } 

        // 
        // Helper function behind all the AddXXX methods for qualified aces 
        //
 
        internal void AddQualifiedAce( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        {
            ThrowIfNotCanonical();
 
            bool aceMerged = false; // if still false after all attempts to merge, create new entry
 
            if ( sid == null ) 
            {
                throw new ArgumentNullException( "sid" ); 
            }

            if ( qualifier == AceQualifier.SystemAudit &&
                (( flags & AceFlags.AuditFlags ) == 0 )) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ), 
                    "flags" );
            } 

            if ( accessMask == 0 )
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Argument_ArgumentZero" ),
                    "accessMask" ); 
            } 

            GenericAce newAce; 

            if (( !IsDS ) || ( objectFlags == ObjectAceFlags.None ))
            {
                newAce = new CommonAce( flags, qualifier, accessMask, sid, false, null ); 
            }
            else 
            { 
                newAce = new ObjectAce( flags, qualifier, accessMask, sid, objectFlags, objectType, inheritedObjectType, false, null );
            } 

            //
            // Make sure the new ACE wouldn't be meaningless before proceeding
            // 

            if ( false == InspectAce( ref newAce, ( this is DiscretionaryAcl ))) 
            { 
                return;
            } 

            //
            // See if the new ACE can be merged with any of the existing ones
            // 

            for ( int i = 0; i < Count; i++ ) 
            { 
                QualifiedAce ace = _acl[i] as QualifiedAce;
 
                if ( ace == null )
                {
                    continue;
                } 

                if ( true == MergeAces( ref ace, newAce as QualifiedAce )) 
                { 
                    aceMerged = true;
                    break; 
                }
            }

            // 
            // Couldn't modify any existing entry, so add a new one
            // 
 
            if ( !aceMerged )
            { 
                _acl.InsertAce( _acl.Count, newAce );

                _isDirty = true;
            } 
            OnAclModificationTried();
        } 
 
        //
        // Helper function behind all the SetXXX methods 
        //

        internal void SetQualifiedAce( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        { 
            ThrowIfNotCanonical();
 
            if ( sid == null ) 
            {
                throw new ArgumentNullException( "sid" ); 
            }

            if ( qualifier == AceQualifier.SystemAudit &&
                (( flags & AceFlags.AuditFlags ) == 0 )) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ), 
                    "flags" );
            } 

            if ( accessMask == 0 )
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Argument_ArgumentZero" ),
                    "accessMask" ); 
            } 

            GenericAce newAce; 

            if (( !IsDS ) || ( objectFlags == ObjectAceFlags.None ))
            {
                newAce = new CommonAce( flags, qualifier, accessMask, sid, false, null ); 
            }
            else 
            { 
                newAce = new ObjectAce( flags, qualifier, accessMask, sid, objectFlags, objectType, inheritedObjectType, false, null );
            } 

            //
            // Make sure the new ACE wouldn't be meaningless before proceeding
            // 

            if ( false == InspectAce( ref newAce, ( this is DiscretionaryAcl ))) 
            { 
                return;
            } 

            for ( int i = 0; i < Count; i++ )
            {
                QualifiedAce ace = _acl[i] as QualifiedAce; 

                // 
                // Not a qualified ACE - keep going 
                //
 
                if ( ace == null )
                {
                    continue;
                } 

                // 
                // Only interested in explicit (non-inherited) ACEs 
                //
 
                if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
                {
                    continue;
                } 

                // 
                // Only interested in ACEs with the specified qualifier 
                //
 
                if ( ace.AceQualifier != qualifier )
                {
                    continue;
                } 

                // 
                // Only interested in ACEs with the specified SID 
                //
 
                if ( ace.SecurityIdentifier != sid )
                {
                    continue;
                } 

                // 
                // This ACE corresponds to the SID and qualifier in question - ---- it 
                //
 
                _acl.RemoveAce( i );
                i--;
            }
 
            //
            // As a final step, add the ACE we want. 
            // Add it at the end - we'll re-canonicalize later. 
            //
 
            _acl.InsertAce( _acl.Count, newAce );

            //
            // To aid the efficiency of batch operations, recanonicalize this later 
            //
 
            _isDirty = true; 
            OnAclModificationTried();
        } 

        //
        // Helper function behind all the RemoveXXX methods
        // 

        internal bool RemoveQualifiedAces( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, bool saclSemantics, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        { 
            ThrowIfNotCanonical();
 
            if ( accessMask == 0 )
            {
                throw new ArgumentException(
                    Environment.GetResourceString( "Argument_ArgumentZero" ), 
                    "accessMask" );
            } 
 
            if ( qualifier == AceQualifier.SystemAudit &&
                (( flags & AceFlags.AuditFlags ) == 0 )) 
            {
                throw new ArgumentException(
                    Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ),
                    "flags" ); 
            }
 
            if ( sid == null ) 
            {
                throw new ArgumentNullException( "sid" ); 
            }

            //
            // Two passes are made. 
            // During the first pass, no changes are made to the ACL,
            // the ACEs are simply evaluated to ascertain that the operation 
            // can succeed. 
            // If everything is kosher, the second pass is the one that makes changes.
            // 

            bool evaluationPass = true;
            bool removePossible = true; // unless proven otherwise
 
            //
            // Needed for DS acls to keep track of the original access mask specified for removal 
            // 
            int originalAccessMask = accessMask;
            AceFlags originalFlags = flags; 

            //
            // It is possible that the removal will result in an overflow exception
            // because more ACEs get inserted. 
            // Save the current state of the object and revert to it later if
            // and exception is thrown. 
            // 

            byte[] recovery = new byte[BinaryLength]; 
            GetBinaryForm( recovery, 0 );

        MakeAnotherPass:
 
            try
            { 
                for ( int i = 0; i < Count; i++ ) 
                {
                    QualifiedAce ace = _acl[i] as QualifiedAce; 

                    //
                    // Not a qualified ACE - keep going
                    // 

                    if ( ace == null ) 
                    { 
                        continue;
                    } 

                    //
                    // Only interested in explicit (non-inherited) ACEs
                    // 

                    if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
                    { 
                        continue;
                    } 

                    //
                    // Only interested in ACEs with the specified qualifier
                    // 

                    if ( ace.AceQualifier != qualifier ) 
                    { 
                        continue;
                    } 

                    //
                    // Only interested in ACEs with the specified SID
                    // 

                    if ( ace.SecurityIdentifier != sid ) 
                    { 
                        continue;
                    } 

                    //
                    // If access masks have nothing in common, skip the whole exercise
                    // 

                    if ( IsDS ) 
                    { 
                        //
                        // incase of directory aces, if the access mask of the 
                        // existing and new ace have any bits in common that need
                        // an object type, then we need to perform some checks on the
                        // object types in the two aces. Since certain bits are further qualified
                        // by the object type they cannot be determined to be common without 
                        // inspecting the object type. It is possible that the same bits may be set but
                        // the object types are different in which case they are really not common bits. 
                        // 
                        accessMask = originalAccessMask;
                        bool objectTypesConflict = !GetAccessMaskForRemoval( ace, objectFlags, objectType, ref accessMask ); 

                        // if the access masks have nothing in common, skip
                        if (( ace.AccessMask & accessMask ) == 0 )
                        { 
                            continue;
                        } 
 
                        //
                        // incase of directory aces, if the existing and new ace are being inherited, 
                        // then we need to perform some checks on the
                        // inherited object types in the two aces. Since inheritance is further qualified
                        // by the inherited object type the inheritance flags cannot be determined to be common without
                        // inspecting the inherited object type. It is possible that both aces may be further inherited but if 
                        // the inherited object types are different the inheritance may not be common.
                        // 
                        flags = originalFlags; 
                        bool inheritedObjectTypesConflict = !GetInheritanceFlagsForRemoval( ace, objectFlags, inheritedObjectType, ref flags );
 
                        if (((( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) && (( flags & AceFlags.ContainerInherit ) != 0 )  && (( flags & AceFlags.InheritOnly ) != 0 )) ||
                             ((( flags & AceFlags.ContainerInherit ) == 0 ) && (( ace.AceFlags & AceFlags.ContainerInherit ) != 0 )  && (( ace.AceFlags & AceFlags.InheritOnly ) != 0)))
                        {
                            // if one ace applies only to self and the other only to children/descendents we have nothing in common 
                            continue;
                        } 
 
                        //
                        // if the ace being removed referred only to child types and child types among existing ace and 
                        // ace being removed are not common then there is nothing in common between these aces (skip)
                        //
                        if ((( originalFlags & AceFlags.ContainerInherit ) != 0 ) && (( originalFlags & AceFlags.InheritOnly ) != 0 ) && (( flags & AceFlags.ContainerInherit ) == 0 ))
                        { 
                            continue;
                        } 
 
                        if ( objectTypesConflict || inheritedObjectTypesConflict )
                        { 
                            //
                            // if we reached this stage, then we've found something common between the two aces.
                            // But since there is a conflict between the object types (or inherited object types), the remove is not possible
                            // 
                            removePossible = false;
                            break; 
                        } 
                    }
                    else 
                    {
                        if (( ace.AccessMask & accessMask ) == 0 )
                        {
                            continue; 
                        }
                    } 
 
                    //
                    // If audit flags on a SACL have nothing in common, 
                    // skip the whole exercise
                    //

                    if ( saclSemantics && 
                        (( ace.AceFlags & flags & AceFlags.AuditFlags ) == 0 ))
                    { 
                        continue; 
                    }
 
                    //
                    // See if the ACE needs to be split into several
                    // To illustrate with an example, consider this equation:
                    //            From: CI OI    NP SA FA R W 
                    //          Remove:    OI IO NP SA    R
                    // 
                    // PermissionSplit: CI OI    NP SA FA   W   // remove R 
                    //   AuditingSplit: CI OI    NP    FA R     // remove SA
                    //      MergeSplit: CI OI    NP SA    R     // ready for merge 
                    //          Remove:    OI IO NP SA    R     // same audit and perm flags as merge split
                    //
                    //          Result: CI OI    NP SA FA   W   // PermissionSplit
                    //                  CI OI    NP    FA R     // AuditingSplit 
                    //                  CI       NP SA    R     // Result of perm removal
                    // 
 
                    //
                    // Example for DS acls (when removal is possible) 
                    //
                    // From: CI(Guid) LC CC(Guid)
                    // Remove: CI IO LC
                    // 
                    // PermissionSplit: CI(Guid) CC(Guid) // Remove GR
                    //        MergeSplit: CI(Guid) LC // Ready for merge 
                    //           Remove: CI IO LC // Removal is possible since we are trying to remove inheritance for 
                    //                                            all child types when it exists for one specific child type
                    // 
                    //              Result: CI(Guid) CC(Guid) // PermissionSplit
                    //                         LC // Result of perm removal
                    //
                    // 
                    // Example for DS acls (when removal is NOT possible)
                    // 
                    // From: CI GR CC(Guid) 
                    // Remove: CI(Guid) IO LC
                    // 
                    // PermissionSplit: CI CC(Guid) // Remove GR
                    //        MergeSplit: CI LC // Ready for merge
                    //           Remove: CI(Guid) IO CC // Removal is not possible since we are trying to remove
                    //                                                     inheritance for a specific child type when it exists for all child types 
                    //
 
                    // Permission split settings 
                    AceFlags ps_AceFlags = 0;
                    int ps_AccessMask = 0; 
                    ObjectAceFlags ps_ObjectAceFlags = 0;
                    Guid ps_ObjectAceType = Guid.Empty;
                    Guid ps_InheritedObjectAceType = Guid.Empty;
 
                    // Auditing split makes sense if this is a SACL
                    AceFlags as_AceFlags = 0; 
                    int as_AccessMask = 0; 
                    ObjectAceFlags as_ObjectAceFlags = 0;
                    Guid as_ObjectAceType = Guid.Empty; 
                    Guid as_InheritedObjectAceType = Guid.Empty;

                    // Merge split settings
                    AceFlags ms_AceFlags = 0; 
                    int ms_AccessMask = 0;
                    ObjectAceFlags ms_ObjectAceFlags = 0; 
                    Guid ms_ObjectAceType = Guid.Empty; 
                    Guid ms_InheritedObjectAceType = Guid.Empty;
 
                    // Merge result settings
                    AceFlags mergeResultFlags = 0;
                    bool mergeRemoveTotal = false;
 
                    //
                    // First compute the permission split 
                    // 

                    ps_AceFlags = ace.AceFlags; 
                    unchecked { ps_AccessMask = ace.AccessMask & ~accessMask; }

                    if ( ace is ObjectAce )
                    { 
                        //
                        // determine what should be the object/inherited object types on the permission split 
                        // 
                        GetObjectTypesForSplit( ace as ObjectAce, ps_AccessMask /* access mask for this split */, ps_AceFlags /* flags remain the same */, out ps_ObjectAceFlags, out ps_ObjectAceType, out ps_InheritedObjectAceType );
                    } 

                    //
                    // Next, for SACLs only, compute the auditing split
                    // 

                    if ( saclSemantics ) 
                    { 
                        //
                        // This operation can set the audit bits region 
                        // of ACE flags to zero;
                        // This case will be handled later
                        //
 
                        unchecked { as_AceFlags = ace.AceFlags & ~( flags & AceFlags.AuditFlags ); }
 
                        // 
                        // The result of this evaluation is guaranteed
                        // not to be zero by now 
                        //

                        as_AccessMask = ( ace.AccessMask & accessMask );
 
                        if ( ace is ObjectAce )
                        { 
                            // 
                            // determine what should be the object/inherited object types on the audit split
                            // 
                            GetObjectTypesForSplit( ace as ObjectAce, as_AccessMask /* access mask for this split */, as_AceFlags /* flags remain the same for inheritance */, out as_ObjectAceFlags, out as_ObjectAceType, out as_InheritedObjectAceType );
                        }
                    }
 
                    //
                    // Finally, compute the merge split 
                    // 

                    ms_AceFlags = ( ace.AceFlags & AceFlags.InheritanceFlags ) | ( flags & ace.AceFlags & AceFlags.AuditFlags ); 
                    ms_AccessMask = ( ace.AccessMask & accessMask );


                    // 
                    // Now is the time to obtain the result of applying the remove
                    // operation to the merge split 
                    // Skipping this step for SACLs where the merge split step 
                    // produced no auditing flags
                    // 

                    if ( !saclSemantics ||
                        (( ms_AceFlags & AceFlags.AuditFlags ) != 0 ))
                    { 
                        if ( false == RemoveInheritanceBits( ms_AceFlags, flags, IsDS, out mergeResultFlags, out mergeRemoveTotal ))
                        { 
                            removePossible = false; 
                            break;
                        } 

                        if ( !mergeRemoveTotal )
                        {
                            mergeResultFlags |= ( ms_AceFlags & AceFlags.AuditFlags ); 

                            if ( ace is ObjectAce ) 
                            { 
                                //
                                // determine what should be the object/inherited object types on the merge split 
                                //
                                GetObjectTypesForSplit( ace as ObjectAce, ms_AccessMask /* access mask for this split */, mergeResultFlags /* flags for this split */, out ms_ObjectAceFlags, out ms_ObjectAceType, out ms_InheritedObjectAceType );
                            }
                        } 
                    }
 
                    // 
                    // If this is no longer an evaluation, go ahead and make the changes
                    // 

                    if ( !evaluationPass )
                    {
                        QualifiedAce newAce; 

                        // 
                        // Modify the existing ACE in-place if it has any access 
                        // mask bits left, otherwise simply remove it
                        // However, if for an object ace we are removing the object type 
                        // then we should really remove this ace and add a new one since
                        // we would be changing the size of this ace
                        //
 
                        if ( ps_AccessMask != 0 )
                        { 
                            if (( ace is ObjectAce ) && 
                                (((( ObjectAce) ace ).ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 ) &&
                                     (( ps_ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 )) 
                            {
                                ObjectAce newObjectAce;

                                _acl.RemoveAce(i); 
                                newObjectAce = new ObjectAce( ps_AceFlags, qualifier, ps_AccessMask, ace.SecurityIdentifier, ps_ObjectAceFlags, ps_ObjectAceType, ps_InheritedObjectAceType, false, null );
                                _acl.InsertAce( i, newObjectAce ); 
                            } 
                            else
                            { 
                                ace.AceFlags = ps_AceFlags;
                                ace.AccessMask = ps_AccessMask;

                                if ( ace is ObjectAce ) 
                                {
                                    ObjectAce objectAce = ace as ObjectAce; 
 
                                    objectAce.ObjectAceFlags = ps_ObjectAceFlags;
                                    objectAce.ObjectAceType = ps_ObjectAceType; 
                                    objectAce.InheritedObjectAceType = ps_InheritedObjectAceType;
                                }
                            }
                        } 
                        else
                        { 
                            _acl.RemoveAce(i); 
                            i--; // keep the array index honest
                        } 

                        //
                        // On a SACL, the result of the auditing split must be recorded
                        // 

                        if ( saclSemantics && (( as_AceFlags & AceFlags.AuditFlags ) != 0 )) 
                        { 
                            if ( ace is CommonAce )
                            { 
                                newAce = new CommonAce( as_AceFlags, qualifier, as_AccessMask, ace.SecurityIdentifier, false, null );
                            }
                            else
                            { 
                                // object ace
                                newAce = new ObjectAce( as_AceFlags, qualifier, as_AccessMask, ace.SecurityIdentifier, as_ObjectAceFlags, as_ObjectAceType, as_InheritedObjectAceType, false, null ); 
                            } 

                            i++; // so it's not considered again 
                            _acl.InsertAce( i, newAce );
                        }

                        // 
                        // If there are interesting bits left over from a remove, store them
                        // as a separate ACE 
                        // 

                        if ( !mergeRemoveTotal ) 
                        {
                            if ( ace is CommonAce )
                            {
                                newAce = new CommonAce( mergeResultFlags, qualifier, ms_AccessMask, ace.SecurityIdentifier, false, null ); 
                            }
                            else 
                            { 
                                // object ace
                                newAce = new ObjectAce( mergeResultFlags, qualifier, ms_AccessMask, ace.SecurityIdentifier, ms_ObjectAceFlags, ms_ObjectAceType, ms_InheritedObjectAceType, false, null ); 
                            }

                            i++; // so it's not considered again
                            _acl.InsertAce( i, newAce ); 
                        }
                    } 
                } 
            }
            catch( OverflowException ) 
            {
                //
                // Oops, overflow means that the ACL became too big.
                // Inform the caller that the remove was not possible. 
                //
 
                _acl.SetBinaryForm( recovery, 0 ); 
                return false;
            } 

            //
            // Finished evaluating the possibility of a remove.
            // If it looks like it's doable, go ahead and do it. 
            //
 
            if ( evaluationPass && removePossible ) 
            {
                evaluationPass = false; 
                goto MakeAnotherPass;
            }

            OnAclModificationTried(); 

            return removePossible; 
        } 

        internal void RemoveQualifiedAcesSpecific( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            ThrowIfNotCanonical();

            if ( accessMask == 0 ) 
            {
                throw new ArgumentException( 
                    Environment.GetResourceString( "Argument_ArgumentZero" ), 
                    "accessMask" );
            } 

            if ( qualifier == AceQualifier.SystemAudit &&
                (( flags & AceFlags.AuditFlags ) == 0 ))
            { 
                throw new ArgumentException(
                    Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ), 
                    "flags" ); 
            }
 
            if ( sid == null )
            {
                throw new ArgumentNullException( "sid" );
            } 

            for ( int i = 0; i < Count; i++ ) 
            { 
                QualifiedAce ace = _acl[i] as QualifiedAce;
 
                //
                // Not a qualified ACE - keep going
                //
 
                if ( ace == null )
                { 
                    continue; 
                }
 
                //
                // Only interested in explicit (non-inherited) ACEs
                //
 
                if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
                { 
                    continue; 
                }
 
                //
                // Only interested in ACEs with the specified qualifier
                //
 
                if ( ace.AceQualifier != qualifier )
                { 
                    continue; 
                }
 
                //
                // Only interested in ACEs with the specified SID
                //
 
                if ( ace.SecurityIdentifier != sid )
                { 
                    continue; 
                }
 
                //
                // Only interested in exact ACE flag matches
                //
 
                if ( ace.AceFlags != flags )
                { 
                    continue; 
                }
 
                //
                // Only interested in exact access mask matches
                //
 
                if ( ace.AccessMask != accessMask )
                { 
                    continue; 
                }
 
                if ( IsDS )
                {
                    //
                    // Incase of object aces, only interested in ACEs which match in their 
                    // objectType and inheritedObjectType
                    // 
 
                    if (( ace is ObjectAce ) && ( objectFlags != ObjectAceFlags.None ))
                    { 
                        //
                        // both are object aces, so must match in object type and inherited object type
                        //
                        ObjectAce objectAce = ace as ObjectAce; 

                        if (( !objectAce.ObjectTypesMatch( objectFlags, objectType )) 
                            || ( !objectAce.InheritedObjectTypesMatch( objectFlags, inheritedObjectType ))) 
                        {
                            continue; 
                        }
                    }
                    else if (( ace is ObjectAce ) || ( objectFlags != ObjectAceFlags.None ))
                    { 
                        // one is object ace and the other is not, so no match
                        continue; 
                    } 
                }
 
                //
                // Got our exact match; now remove it
                //
 
                _acl.RemoveAce(i);
                i--; // keep the array index honest 
            } 
            OnAclModificationTried();
        } 

        internal virtual void OnAclModificationTried()
        {
        } 
        #endregion
 
        #region Public Properties 

        // 
        // Returns the revision of the ACL
        //

        public sealed override byte Revision 
        {
            get { return _acl.Revision; } 
        } 

        // 
        // Returns the number of ACEs in the ACL
        //

        public sealed override int Count 
        {
            get 
            { 
                CanonicalizeIfNecessary();
                return _acl.Count; 
            }
        }

        // 
        // Returns the length of the binary representation of the ACL
        // 
 
        public sealed override int BinaryLength
        { 
            get
            {
                CanonicalizeIfNecessary();
                return _acl.BinaryLength; 
            }
        } 
 
        //
        // Returns 'true' if the ACL was canonical at creation time 
        //

        public bool IsCanonical
        { 
            get { return _isCanonical; }
        } 
 
        public bool IsContainer
        { 
            get { return _isContainer; }
        }

        public bool IsDS 
        {
            get { return _isDS; } 
        } 

        #endregion 

        #region Public Methods

        // 
        // Returns the binary representation of the ACL
        // 
 
        public sealed override void GetBinaryForm( byte[] binaryForm, int offset )
        { 
            CanonicalizeIfNecessary();
            _acl.GetBinaryForm( binaryForm, offset );
        }
 
        //
        // Retrieves the ACE at a given index inside the ACL 
        // Since the caller can modify the ACE it receives, 
        // clone the ACE prior to returning it to the caller
        // 

        public sealed override GenericAce this[int index]
        {
            get 
            {
                CanonicalizeIfNecessary(); 
                return _acl[index].Copy(); 
            }
 
            set
            {
                throw new NotSupportedException( Environment.GetResourceString( "NotSupported_SetMethod" ));
            } 
        }
 
        public void RemoveInheritedAces() 
        {
            ThrowIfNotCanonical(); 

            //
            // Iterating backwards as an optimization - all inherited ACEs
            // are usually in the back of the ACL 
            //
 
            for ( int i = _acl.Count - 1; i >= 0; i-- ) 
            {
                GenericAce ace = _acl[i]; 

                if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
                {
                    _acl.RemoveAce( i ); 
                }
            } 
            OnAclModificationTried(); 
        }
 
        public void Purge( SecurityIdentifier sid )
        {
            ThrowIfNotCanonical();
 
            if ( sid == null )
            { 
                throw new ArgumentNullException( "sid" ); 
            }
 
            for ( int i = Count - 1; i >= 0; i-- )
            {
                KnownAce ace = _acl[i] as KnownAce;
 
                //
                // Skip over unknown ACEs 
                // 

                if ( ace == null ) 
                {
                    continue;
                }
 
                //
                // Skip over inherited ACEs 
                // 

                if (( ace.AceFlags & AceFlags.Inherited ) != 0 ) 
                {
                    continue;
                }
 
                //
                // SID matches - ACE is out 
                // 

                if ( ace.SecurityIdentifier == sid ) 
                {
                    _acl.RemoveAce( i );
                }
            } 
            OnAclModificationTried();
        } 
 
        #endregion
    } 


    public sealed class SystemAcl : CommonAcl
    { 
        #region Constructors
 
        // 
        // Creates an emtpy ACL
        // 

        public SystemAcl( bool isContainer, bool isDS, int capacity )
            : this( isContainer, isDS, isDS ? AclRevisionDS : AclRevision, capacity )
        { 
        }
 
        public SystemAcl( bool isContainer, bool isDS, byte revision, int capacity ) 
            : base( isContainer, isDS, revision, capacity )
        { 
        }

        //
        // Creates an ACL from a given raw ACL 
        // after canonicalizing it
        // 
 
        public SystemAcl( bool isContainer, bool isDS, RawAcl rawAcl )
            : this( isContainer, isDS, rawAcl, false ) 
        {
        }

        // 
        // Internal version - if 'trusted' is true,
        // takes ownership of the given raw ACL 
        // 

        internal SystemAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted ) 
            : base( isContainer, isDS, rawAcl, trusted, false )
        {
        }
 
        #endregion
 
        #region Public Methods 

        public void AddAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags ) 
        {
            CheckFlags( inheritanceFlags, propagationFlags );
            AddQualifiedAce( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        } 

        public void SetAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags ) 
        { 
            CheckFlags( inheritanceFlags, propagationFlags );
            SetQualifiedAce( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty ); 
        }

        public bool RemoveAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        { 
            return RemoveQualifiedAces(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), true, ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        } 
 
        public void RemoveAuditSpecific( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        { 
            RemoveQualifiedAcesSpecific( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        }

        public void AddAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            // 
            // This is valid only for DS Acls 
            //
            if ( !IsDS ) 
            {
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
            } 

            CheckFlags( inheritanceFlags, propagationFlags ); 
            AddQualifiedAce(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType); 
        }
 
        public void SetAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        {
            //
            // This is valid only for DS Acls 
            //
            if ( !IsDS ) 
            { 
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" )); 
            }

            CheckFlags( inheritanceFlags, propagationFlags );
            SetQualifiedAce(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType); 
        }
 
        public bool RemoveAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            // 
            // This is valid only for DS Acls
            //
            if ( !IsDS )
            { 
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" )); 
            } 

            return RemoveQualifiedAces(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), true, objectFlags, objectType, inheritedObjectType); 
        }

        public void RemoveAuditSpecific( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        { 
            //
            // This is valid only for DS Acls 
            // 
            if ( !IsDS )
            { 
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
            }
 
            RemoveQualifiedAcesSpecific(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType);
        } 
 
        #endregion
    } 


    public sealed class DiscretionaryAcl : CommonAcl
    { 
        #region
        static private SecurityIdentifier _sidEveryone = new SecurityIdentifier( WellKnownSidType.WorldSid, null ); 
        private bool everyOneFullAccessForNullDacl = false; 
        #endregion
 
        #region Constructors

        //
        // Creates an emtpy ACL 
        //
 
        public DiscretionaryAcl( bool isContainer, bool isDS, int capacity ) 
            : this( isContainer, isDS, isDS ? AclRevisionDS : AclRevision, capacity )
        { 
        }

        public DiscretionaryAcl( bool isContainer, bool isDS, byte revision, int capacity )
            : base( isContainer, isDS, revision, capacity ) 
        {
        } 
 
        //
        // Creates an ACL from a given raw ACL 
        // after canonicalizing it
        //

        public DiscretionaryAcl( bool isContainer, bool isDS, RawAcl rawAcl ) 
            : this( isContainer, isDS, rawAcl, false )
        { 
        } 

        // 
        // Internal version - if 'trusted' is true,
        // takes ownership of the given raw ACL
        //
 
        internal DiscretionaryAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted )
            : base( isContainer, isDS, rawAcl == null ? new RawAcl( isDS ? AclRevisionDS : AclRevision, 0 ) : rawAcl, trusted, true ) 
        { 
        }
 
        #endregion

        #region Public Methods
 
        public void AddAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        { 
            CheckAccessType( accessType ); 
            CheckFlags( inheritanceFlags, propagationFlags );
            everyOneFullAccessForNullDacl = false; 
            AddQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        }

        public void SetAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags ) 
        {
            CheckAccessType( accessType ); 
            CheckFlags( inheritanceFlags, propagationFlags ); 
            everyOneFullAccessForNullDacl = false;
            SetQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty ); 
        }

        public bool RemoveAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        { 
            CheckAccessType( accessType );
            everyOneFullAccessForNullDacl = false; 
            return RemoveQualifiedAces( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), false, ObjectAceFlags.None, Guid.Empty, Guid.Empty ); 
        }
 
        public void RemoveAccessSpecific( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
        {
            CheckAccessType( accessType );
            everyOneFullAccessForNullDacl = false; 
            RemoveQualifiedAcesSpecific(sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
        } 
 
        public void AddAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
        { 
            //
            // This is valid only for DS Acls
            //
            if ( !IsDS ) 
            {
                throw new InvalidOperationException( 
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" )); 
            }
 
            CheckAccessType( accessType );
            CheckFlags( inheritanceFlags, propagationFlags );
            everyOneFullAccessForNullDacl = false;
            AddQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType ); 
        }
 
        public void SetAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            // 
            // This is valid only for DS Acls
            //
            if ( !IsDS )
            { 
                throw new InvalidOperationException(
                    Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" )); 
            } 

            CheckAccessType( accessType ); 
            CheckFlags( inheritanceFlags, propagationFlags );
            everyOneFullAccessForNullDacl = false;
            SetQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType);
        } 

        public bool RemoveAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        { 
            //
            // This is valid only for DS Acls 
            //
            if ( !IsDS )
            {
                throw new InvalidOperationException( 
                    Environment.GetResourceString(" InvalidOperation_OnlyValidForDS "));
            } 
 
            CheckAccessType( accessType );
            everyOneFullAccessForNullDacl = false; 
            return RemoveQualifiedAces(sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), false, objectFlags, objectType, inheritedObjectType );
        }

        public void RemoveAccessSpecific( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
        {
            // 
            // This is valid only for DS Acls 
            //
            if ( !IsDS ) 
            {
                throw new InvalidOperationException(
                    Environment.GetResourceString(" InvalidOperation_OnlyValidForDS "));
            } 

            CheckAccessType( accessType ); 
            everyOneFullAccessForNullDacl = false; 
            RemoveQualifiedAcesSpecific( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType );
        } 

        #endregion

        #region internals and privates 

        // 
        // DACL's "allow everyone full access may be created to replace a null DACL because managed 
        // access control does not want to leave null DACLs around. But we need to remember this MACL
        // created ACE when the DACL is modified, we can remove it to match the same native semantics of 
        // a null DACL.
        //
        internal bool EveryOneFullAccessForNullDacl
        { 
            get { return everyOneFullAccessForNullDacl; }
            set { everyOneFullAccessForNullDacl = value; } 
        } 

        // 
        // As soon as you tried successfully to modified the ACL, the internally created allow every one full access ACL is materialized
        // because in native world, a NULL dacl can't be operated on.
        //
        internal override void OnAclModificationTried() 
        {
            everyOneFullAccessForNullDacl = false; 
        } 

        ///  
        /// This static method will create an "allow everyone full control" single ACE DACL.
        /// 
        /// whether it is a DS DACL
        /// whether it is a container 
        /// The single ACE DACL
        /// Note: This method is created to get the best behavior for using "allow everyone full access" 
        /// single ACE DACL to replace null DACL from CommonSecurityObject. 
        static internal DiscretionaryAcl CreateAllowEveryoneFullAccess(bool isDS, bool isContainer)
        { 
            DiscretionaryAcl dcl = new DiscretionaryAcl( isContainer, isDS, 1 );
            dcl.AddAccess(
                AccessControlType.Allow,
                _sidEveryone, 
                -1,
                isContainer ? ( InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit ) : InheritanceFlags.None, 
                PropagationFlags.None ); 

            dcl.everyOneFullAccessForNullDacl = true; 
            return dcl;
        }
        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK