Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / security / accesscontrol / acl.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** Classes:  Access Control List (ACL) family of classes
9 **
10 **
11 ===========================================================*/
12
13 namespace System.Security.AccessControl
14 {
15     using System;
16     using System.Collections;
17     using System.Security.Principal;
18     using System.Diagnostics.Contracts;
19
20     public sealed class AceEnumerator : IEnumerator
21     {
22         #region Private Members
23
24         //
25         // Current enumeration index
26         //
27         
28         private int _current;
29
30         //
31         // Parent collection
32         //
33
34         private readonly GenericAcl _acl;
35
36         #endregion
37
38         #region Constructors
39
40         internal AceEnumerator( GenericAcl collection )
41         {
42             if ( collection == null )
43             {
44                 throw new ArgumentNullException( "collection" );
45             }
46             Contract.EndContractBlock();
47
48             _acl = collection;
49             Reset();
50         }
51
52         #endregion
53
54         #region IEnumerator Interface
55
56         object IEnumerator.Current
57         {
58             get
59             {
60                 if ( _current == -1 ||
61                     _current >= _acl.Count )
62                 {
63                     throw new InvalidOperationException( Environment.GetResourceString( "Arg_InvalidOperationException" ));
64                 }
65
66                 return _acl[_current];
67             }
68         }
69
70         public GenericAce Current
71         {
72             get { return (( IEnumerator )this ).Current as GenericAce; }
73         }
74
75         public bool MoveNext()
76         {
77             _current++;
78             
79             return ( _current < _acl.Count );
80         }
81
82         public void Reset()
83         {
84             _current = -1;
85         }
86
87         #endregion
88     }
89
90
91     public abstract class GenericAcl : ICollection
92     {
93         #region Constructors
94
95         protected GenericAcl()
96         { }
97
98         #endregion
99
100         #region Public Constants
101
102         //
103         // ACL revisions
104         //
105
106         public static readonly byte AclRevision = 2;
107         public static readonly byte AclRevisionDS = 4;
108
109         //
110         // Maximum length of a binary representation of the ACL
111         //
112
113         public static readonly int MaxBinaryLength = ushort.MaxValue;
114
115         #endregion
116
117         #region Protected Members
118
119         //
120         //  Define an ACL and the ACE format.  The structure of an ACL header
121         //  followed by one or more ACEs.  Pictorally the structure of an ACL header
122         //  is as follows:
123         //
124         //       3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
125         //       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
126         //      +-------------------------------+---------------+---------------+
127         //      |            AclSize            |      Sbz1     |  AclRevision  |
128         //      +-------------------------------+---------------+---------------+
129         //      |              Sbz2             |           AceCount            |
130         //      +-------------------------------+-------------------------------+
131         //
132
133         internal const int HeaderLength = 8;
134         
135         #endregion
136
137         #region Public Properties
138
139         //
140         // Returns the revision of the ACL
141         //
142
143         public abstract byte Revision { get; }
144
145         //
146         // Returns the length of the binary representation of the ACL
147         //
148
149         public abstract int BinaryLength { get; }
150
151         //
152         // Retrieves the ACE at a specified index
153         //
154
155         public abstract GenericAce this[int index] { get; set; }
156
157         #endregion
158
159         #region Public Methods
160
161         //
162         // Returns the binary representation of the ACL
163         //
164
165         public abstract void GetBinaryForm( byte[] binaryForm, int offset );
166
167         #endregion
168
169         #region ICollection Implementation
170
171         void ICollection.CopyTo( Array array, int index )
172         {
173             if ( array == null )
174             {
175                 throw new ArgumentNullException( "array" );
176             }
177
178             if ( array.Rank != 1 )
179             {
180                 throw new RankException( Environment.GetResourceString( "Rank_MultiDimNotSupported" ));
181             }
182             Contract.EndContractBlock();
183
184             if ( index < 0 )
185             {
186                 throw new ArgumentOutOfRangeException(
187                     "index",
188                     Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
189             }
190             else if ( array.Length - index < Count )
191             {
192                 throw new ArgumentOutOfRangeException(
193                     "array",
194                     Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
195             }
196
197             for ( int i = 0; i < Count; i++ )
198             {
199                 array.SetValue( this[i], index + i );
200             }
201         }
202
203         public void CopyTo( GenericAce[] array, int index ) 
204         {
205             (( ICollection )this ).CopyTo( array, index );
206         }
207
208         public abstract int Count { get; }
209
210         public bool IsSynchronized
211         {
212             get { return false; }
213         }
214
215         public virtual object SyncRoot
216         {
217             get { return this; }
218         }
219
220         #endregion
221
222         #region IEnumerable Implementation
223
224         IEnumerator IEnumerable.GetEnumerator()
225         {
226             return new AceEnumerator( this );
227         }
228
229         public AceEnumerator GetEnumerator()
230         {
231             return (( IEnumerable )this ).GetEnumerator() as AceEnumerator;
232         }
233
234         #endregion
235     }
236
237
238     public sealed class RawAcl : GenericAcl
239     {
240         #region Private Members
241
242         private byte _revision;
243         private ArrayList _aces;
244
245         #endregion
246
247         #region Private Methods
248
249         private static void VerifyHeader( byte[] binaryForm, int offset, out byte revision, out int count, out int length )
250         {
251             if ( binaryForm == null )
252             {
253                 throw new ArgumentNullException( "binaryForm" );
254             }
255             Contract.EndContractBlock();
256
257             if ( offset < 0 )
258             {
259                 //
260                 // Offset must not be negative
261                 //
262
263                 throw new ArgumentOutOfRangeException(
264                     "offset",
265                     Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
266             }
267
268             if ( binaryForm.Length - offset < HeaderLength )
269             {
270                 //
271                 // We expect at least the ACL header
272                 //
273
274                 goto InvalidParameter;
275             }
276
277             revision = binaryForm[offset + 0];
278             length = ( binaryForm[offset + 2] << 0 ) + ( binaryForm[offset + 3] << 8 );
279             count = ( binaryForm[offset + 4] << 0 ) + ( binaryForm[offset + 5] << 8 );
280
281             if ( length > binaryForm.Length - offset )
282             {
283                 //
284                 // Reported length of ACL ought to be no longer than the
285                 // length of the buffer passed in
286                 //
287
288                 goto InvalidParameter;
289             }
290
291             return;
292
293         InvalidParameter:
294
295             throw new ArgumentOutOfRangeException(
296                 "binaryForm",
297                 Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
298         }
299
300         private void MarshalHeader( byte[] binaryForm, int offset )
301         {
302             if ( binaryForm == null )
303             {
304                 throw new ArgumentNullException( "binaryForm" );
305             }
306             else if ( offset < 0 )
307             {
308                 throw new ArgumentOutOfRangeException(
309                     "offset",
310                     Environment.GetResourceString( "ArgumentOutOfRange_NeedNonNegNum" ));
311             }
312             else if ( BinaryLength > MaxBinaryLength )
313             {
314                 throw new InvalidOperationException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
315             }
316             else if ( binaryForm.Length - offset < BinaryLength )
317             {
318                 throw new ArgumentOutOfRangeException(
319                     "binaryForm",
320                     Environment.GetResourceString( "ArgumentOutOfRange_ArrayTooSmall" ));
321             }
322
323             binaryForm[offset + 0] = Revision;
324             binaryForm[offset + 1] = 0;
325             binaryForm[offset + 2] = ( byte )( BinaryLength >> 0 );
326             binaryForm[offset + 3] = ( byte )( BinaryLength >> 8 );
327             binaryForm[offset + 4] = ( byte )( Count >> 0 );
328             binaryForm[offset + 5] = ( byte )( Count >> 8 );
329             binaryForm[offset + 6] = 0;
330             binaryForm[offset + 7] = 0;
331         }
332
333         internal void SetBinaryForm( byte[] binaryForm, int offset )
334         {
335             int count, length;
336
337             //
338             // Verify the header and extract interesting header info
339             //
340
341             VerifyHeader( binaryForm, offset, out _revision, out count, out length );
342
343             //
344             // Remember how far ahead the binary form should end (for later verification)
345             //
346
347             length += offset;
348
349             offset += HeaderLength;
350
351             _aces = new ArrayList( count );
352             int binaryLength = HeaderLength;
353
354             for ( int i = 0; i < count; i++ )
355             {
356                 GenericAce ace = GenericAce.CreateFromBinaryForm( binaryForm, offset );
357
358                 int aceLength = ace.BinaryLength;
359
360                 if ( binaryLength + aceLength > MaxBinaryLength )
361                 {
362                     //
363                     // The ACE was too long - it would overflow the ACL maximum length
364                     //
365
366                     throw new ArgumentException(
367                         Environment.GetResourceString( "ArgumentException_InvalidAclBinaryForm" ),
368                         "binaryForm" );
369                 }
370
371                 _aces.Add( ace );
372
373                 if ( aceLength % 4 != 0 )
374                 {
375                     //
376                     // This indicates a bug in one of the ACE classes.
377                     // Binary length of an ace must ALWAYS be divisible by 4.
378                     //
379
380                     Contract.Assert( false, "aceLength % 4 != 0" );
381                     throw new SystemException();
382                 }
383
384                 binaryLength += aceLength;
385
386                 if ( _revision == AclRevisionDS )
387                 {
388                     //
389                     // Increment the offset by the advertised length rather than the 
390                     // actual binary length. (Ideally these two should match, but for
391                     // object aces created through ADSI, the actual length is 32 bytes 
392                     // less than the allocated size of the ACE. This is a bug in ADSI.)
393                     //
394                     offset += (binaryForm[offset + 2] << 0) + (binaryForm[offset + 3] << 8);
395                 }
396                 else
397                 {
398                     offset += aceLength;
399                 }
400
401                 //
402                 // Verify that no more than the advertised length of the ACL was consumed
403                 //
404
405                 if ( offset > length )
406                 {
407                     goto InvalidParameter;
408                 }
409             }
410
411             return;
412
413         InvalidParameter:
414
415             throw new ArgumentException(
416                 Environment.GetResourceString( "ArgumentException_InvalidAclBinaryForm" ),
417                 "binaryForm" );
418         }
419
420         #endregion
421
422         #region Constructors
423
424         //
425         // Creates an empty ACL
426         //
427
428         public RawAcl( byte revision, int capacity )
429             : base()
430         {
431             _revision = revision;
432             _aces = new ArrayList( capacity );
433         }
434
435         //
436         // Creates an ACL from its binary representation
437         //
438
439         public RawAcl( byte[] binaryForm, int offset )
440             : base()
441         {
442             SetBinaryForm( binaryForm, offset );
443         }
444
445         #endregion
446
447         #region Public Properties
448
449         //
450         // Returns the revision of the ACL
451         //
452
453         public override byte Revision
454         {
455             get { return _revision; }
456         }
457
458         //
459         // Returns the number of ACEs in the ACL
460         //
461
462         public override int Count
463         {
464             get { return _aces.Count; }
465         }
466
467         //
468         // Returns the length of the binary representation of the ACL
469         //
470
471         public override int BinaryLength
472         {
473             get
474             {
475                 int binaryLength = HeaderLength;
476
477                 for (int i = 0; i < Count; i++)
478                 {
479                     GenericAce ace = _aces[i] as GenericAce;
480                     binaryLength += ace.BinaryLength;
481                 }
482
483                 return binaryLength;
484             }
485         }
486
487         #endregion
488
489         #region Public Methods
490
491         //
492         // Returns the binary representation of the ACL
493         //
494
495         public override void GetBinaryForm( byte[] binaryForm, int offset )
496         {
497             //
498             // Populate the header
499             //
500
501             MarshalHeader( binaryForm, offset );
502             offset += HeaderLength;
503
504             for ( int i = 0; i < Count; i++ )
505             {
506                 GenericAce ace = _aces[i] as GenericAce;
507
508                 ace.GetBinaryForm( binaryForm, offset );
509
510                 int aceLength = ace.BinaryLength;
511
512                 if ( aceLength % 4 != 0 )
513                 {
514                     //
515                     // This indicates a bug in one of the ACE classes.
516                     // Binary length of an ace must ALWAYS be divisible by 4.
517                     //
518
519                     Contract.Assert( false, "aceLength % 4 != 0" );
520                     throw new SystemException();
521                 }
522
523                 offset += aceLength;
524             }
525         }
526
527         //
528         // Return an ACE at a particular index
529         // The ACE is not cloned prior to returning, enabling the caller
530         // to modify the ACE in place (a potentially dangerous operation)
531         //
532
533         public override GenericAce this[int index]
534         {
535             get
536             {
537                 return _aces[index] as GenericAce;
538             }
539
540             set
541             {
542                 if ( value == null )
543                 {
544                     throw new ArgumentNullException( "value" );
545                 }
546                 Contract.EndContractBlock();
547
548                 if ( value.BinaryLength % 4 != 0 )
549                 {
550                     //
551                     // This indicates a bug in one of the ACE classes.
552                     // Binary length of an ace must ALWAYS be divisible by 4.
553                     //
554
555                     Contract.Assert( false, "aceLength % 4 != 0" );
556                     throw new SystemException();
557                 }
558
559                 int newBinaryLength = BinaryLength - ( index < _aces.Count ? ( _aces[index] as GenericAce ).BinaryLength : 0 ) + value.BinaryLength;
560
561                 if ( newBinaryLength > MaxBinaryLength )
562                 {
563                     throw new OverflowException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
564                 }
565
566                 _aces[index] = value;
567             }
568         }
569
570         //
571         // Adds an ACE at the specified index
572         //
573
574         public void InsertAce( int index, GenericAce ace )
575         {
576             if ( ace == null )
577             {
578                 throw new ArgumentNullException( "ace" );
579             }
580             Contract.EndContractBlock();
581
582             if ( BinaryLength + ace.BinaryLength > MaxBinaryLength )
583             {
584                 throw new OverflowException( Environment.GetResourceString( "AccessControl_AclTooLong" ));
585             }
586
587             _aces.Insert( index, ace );
588         }
589
590         //
591         // Removes an ACE at the specified index
592         //
593
594         public void RemoveAce( int index )
595         {
596             GenericAce ace = _aces[index] as GenericAce;
597             _aces.RemoveAt( index );
598         }
599
600         #endregion
601     }
602
603
604     public abstract class CommonAcl : GenericAcl
605     {
606         #region Add/Remove Logic Support
607
608         [Flags]
609         private enum AF    // ACE flags
610         {
611             CI        = 0x8,    // container inherit
612             OI        = 0x4,    // object inherit
613             IO        = 0x2,    // inherit only
614             NP        = 0x1,    // no propagate inherit
615             Invalid   = NP,     // not a valid combination of flags
616         }
617
618         [Flags]
619         private enum PM    // Propagation matrix
620         {
621             F         = 0x10,    // folder
622             CF        = 0x08,    // child folder
623             CO        = 0x04,    // child object
624             GF        = 0x02,    // grandchild folder
625             GO        = 0x01,    // grandchild object
626             Invalid   = GO,      // not a valid combination of flags
627         }
628
629         private static PM[] AFtoPM;    // AceFlags-to-Propagation conversion matrix
630         private static AF[] PMtoAF;    // Propagation-to-AceFlags conversion matrix
631
632         static CommonAcl()
633         {
634             AFtoPM = new PM[16];
635
636             for ( int i = 0; i < AFtoPM.Length; i++ )
637             {
638                 AFtoPM[i] = PM.Invalid;
639             }
640
641             //
642             // This table specifies what effect various combinations of inheritance bits
643             // have on how ACEs are inherited onto child objects
644             // Important: Not all combinations of inheritance bits are valid
645             //
646
647             AFtoPM[( int )(   0   |   0   |   0   |   0   )] = PM.F |   0   |   0   |   0   |   0   ;
648             AFtoPM[( int )(   0   | AF.OI |   0   |   0   )] = PM.F |   0   | PM.CO |   0   | PM.GO ;
649             AFtoPM[( int )(   0   | AF.OI |   0   | AF.NP )] = PM.F |   0   | PM.CO |   0   |   0   ;
650             AFtoPM[( int )(   0   | AF.OI | AF.IO |   0   )] =   0  |   0   | PM.CO |   0   | PM.GO ;
651             AFtoPM[( int )(   0   | AF.OI | AF.IO | AF.NP )] =   0  |   0   | PM.CO |   0   |   0   ;
652             AFtoPM[( int )( AF.CI |   0   |   0   |   0   )] = PM.F | PM.CF |   0   | PM.GF |   0   ;
653             AFtoPM[( int )( AF.CI |   0   |   0   | AF.NP )] = PM.F | PM.CF |   0   |   0   |   0   ;
654             AFtoPM[( int )( AF.CI |   0   | AF.IO |   0   )] =   0  | PM.CF |   0   | PM.GF |   0   ;
655             AFtoPM[( int )( AF.CI |   0   | AF.IO | AF.NP )] =   0  | PM.CF |   0   |   0   |   0   ;
656             AFtoPM[( int )( AF.CI | AF.OI |   0   |   0   )] = PM.F | PM.CF | PM.CO | PM.GF | PM.GO ;
657             AFtoPM[( int )( AF.CI | AF.OI |   0   | AF.NP )] = PM.F | PM.CF | PM.CO |   0   |   0   ;
658             AFtoPM[( int )( AF.CI | AF.OI | AF.IO |   0   )] =   0  | PM.CF | PM.CO | PM.GF | PM.GO ;
659             AFtoPM[( int )( AF.CI | AF.OI | AF.IO | AF.NP )] =   0  | PM.CF | PM.CO |   0   |   0   ;
660
661             PMtoAF = new AF[32];
662
663             for ( int i = 0; i < PMtoAF.Length; i++ )
664             {
665                 PMtoAF[i] = AF.Invalid;
666             }
667
668             //
669             // This table is a reverse lookup table of the AFtoPM table
670             // Given how inheritance is applied to child objects and containers,
671             // it helps figure out whether that pattern is expressible using
672             // the four ACE inheritance bits
673             //
674
675             PMtoAF[( int )( PM.F |   0   |   0   |   0   |   0   )] =    0   |   0   |   0   |   0   ;
676             PMtoAF[( int )( PM.F |   0   | PM.CO |   0   | PM.GO )] =    0   | AF.OI |   0   |   0   ;
677             PMtoAF[( int )( PM.F |   0   | PM.CO |   0   |   0   )] =    0   | AF.OI |   0   | AF.NP ;
678             PMtoAF[( int )(   0  |   0   | PM.CO |   0   | PM.GO )] =    0   | AF.OI | AF.IO |   0   ;
679             PMtoAF[( int )(   0  |   0   | PM.CO |   0   |   0   )] =    0   | AF.OI | AF.IO | AF.NP ;
680             PMtoAF[( int )( PM.F | PM.CF |   0   | PM.GF |   0   )] =  AF.CI |   0   |   0   |   0   ;
681             PMtoAF[( int )( PM.F | PM.CF |   0   |   0   |   0   )] =  AF.CI |   0   |   0   | AF.NP ;
682             PMtoAF[( int )(   0  | PM.CF |   0   | PM.GF |   0   )] =  AF.CI |   0   | AF.IO |   0   ;
683             PMtoAF[( int )(   0  | PM.CF |   0   |   0   |   0   )] =  AF.CI |   0   | AF.IO | AF.NP ;
684             PMtoAF[( int )( PM.F | PM.CF | PM.CO | PM.GF | PM.GO )] =  AF.CI | AF.OI |   0   |   0   ;
685             PMtoAF[( int )( PM.F | PM.CF | PM.CO |   0   |   0   )] =  AF.CI | AF.OI |   0   | AF.NP ;
686             PMtoAF[( int )(   0  | PM.CF | PM.CO | PM.GF | PM.GO )] =  AF.CI | AF.OI | AF.IO |   0   ;
687             PMtoAF[( int )(   0  | PM.CF | PM.CO |   0   |   0   )] =  AF.CI | AF.OI | AF.IO | AF.NP ;
688         }
689
690         //
691         // Canonicalizes AceFlags into a form that the mapping tables understand
692         //
693
694         private static AF AFFromAceFlags( AceFlags aceFlags, bool isDS )
695         {
696             AF af = 0;
697
698             if (( aceFlags & AceFlags.ContainerInherit ) != 0)
699             {
700                 af |= AF.CI;
701             }
702
703             //
704             // ObjectInherit applies only to regular aces not object aces
705             // so it can be ignored in the object aces case
706             //
707             if (( !isDS ) && (( aceFlags & AceFlags.ObjectInherit ) != 0 ))
708             {
709                 af |= AF.OI;
710             }
711
712             if (( aceFlags & AceFlags.InheritOnly ) != 0 )
713             {
714                 af |= AF.IO;
715             }
716
717             if (( aceFlags & AceFlags.NoPropagateInherit ) != 0 )
718             {
719                 af |= AF.NP;
720             }
721
722             return af;
723         }
724
725         //
726         // Converts lookup table representation of AceFlags into the "public" form
727         //
728
729         private static AceFlags AceFlagsFromAF( AF af, bool isDS )
730         {
731             AceFlags aceFlags = 0;
732
733             if (( af & AF.CI ) != 0 )
734             {
735                 aceFlags |= AceFlags.ContainerInherit;
736             }
737
738             //
739             // ObjectInherit applies only to regular aces not object aces
740             // so it can be ignored in the object aces case
741             //
742             if (( !isDS ) && (( af & AF.OI ) != 0 ))
743             {
744                 aceFlags |= AceFlags.ObjectInherit;
745             }
746
747             if (( af & AF.IO ) != 0 )
748             {
749                 aceFlags |= AceFlags.InheritOnly;
750             }
751
752             if (( af & AF.NP ) != 0 )
753             {
754                 aceFlags |= AceFlags.NoPropagateInherit;
755             }
756
757             return aceFlags;
758         }
759
760         //
761         // Implements the merge of inheritance bits during the 'ADD' operation
762         //
763
764         private static bool MergeInheritanceBits( AceFlags left, AceFlags right, bool isDS, out AceFlags result )
765         {
766             result = 0;
767
768             AF leftAF = AFFromAceFlags( left, isDS );
769             AF rightAF = AFFromAceFlags( right, isDS );
770
771             PM leftPM = AFtoPM[(int)leftAF];
772             PM rightPM = AFtoPM[(int)rightAF];
773
774             if ( leftPM == PM.Invalid || rightPM == PM.Invalid )
775             {
776                 return false; // incorrect ACE flags?
777             }
778
779             PM resultPM = leftPM | rightPM;
780             AF resultAF = PMtoAF[( int )resultPM];
781
782             if ( resultAF == AF.Invalid )
783             {
784                 return false;
785             }
786             else
787             {
788                 result = AceFlagsFromAF( resultAF, isDS );
789                 return true;
790             }
791         }
792
793         private static bool RemoveInheritanceBits( AceFlags existing, AceFlags remove, bool isDS, out AceFlags result, out bool total )
794         {
795             result = 0;
796             total = false;
797
798             AF leftAF = AFFromAceFlags( existing, isDS );
799             AF rightAF = AFFromAceFlags( remove, isDS );
800
801             PM leftPM = AFtoPM[( int )leftAF];
802             PM rightPM = AFtoPM[( int )rightAF];
803
804             if ( leftPM == PM.Invalid || rightPM == PM.Invalid )
805             {
806                 return false; // incorrect ACE flags?
807             }
808
809             PM resultPM;
810             unchecked { resultPM = leftPM & ~rightPM; }
811
812             //
813             // If the resulting propagation matrix is zero,
814             // communicate back the fact that removal is "total"
815             //
816
817             if ( resultPM == 0 )
818             {
819                 total = true;
820                 return true;
821             }
822
823             AF resultAF = PMtoAF[( int )resultPM];
824
825             if ( resultAF == AF.Invalid )
826             {
827                 return false;
828             }
829             else
830             {
831                 result = AceFlagsFromAF( resultAF, isDS );
832                 return true;
833             }
834         }
835
836         #endregion
837
838         #region Private Members
839
840         private RawAcl _acl;
841         private bool _isDirty = false;
842         private readonly bool _isCanonical;
843         private readonly bool _isContainer;
844
845         //
846         // To distinguish between a directory object acl and other common acls.
847         //
848
849         private readonly bool _isDS;
850
851         #endregion
852
853         #region Private Methods
854
855         private void CanonicalizeIfNecessary()
856         {
857             if ( _isDirty )
858             {
859                 Canonicalize( false, this is DiscretionaryAcl );
860                 _isDirty = false;
861             }
862         }
863
864         private enum ComparisonResult
865         {
866             LessThan,
867             EqualTo,
868             GreaterThan,
869         }
870
871         //
872         // Compares two discretionary ACEs and returns
873         //    LessThan if ace1 < ace2
874         //    EqualTo if ace1 == ace2
875         //    GreaterThan if ace1 > ace2
876         //
877         // The order is:
878         //        - explicit Access Denied ACEs
879         //          [regular aces first, then object aces]
880         //        - explicit Access Allowed ACEs
881         //          [regular aces first, then object aces]
882         //        - inherited ACEs (in the original order )
883         //        - user-defined ACEs (in the original order )
884         //
885
886         private static int DaclAcePriority( GenericAce ace)
887         {
888             int result;
889             AceType type = ace.AceType;
890
891             if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
892             {
893                 //
894                 // inherited aces are at the end as a group
895                 //
896
897                 result = 2 * ushort.MaxValue + ace._indexInAcl;
898             }
899             else if ( type == AceType.AccessDenied ||
900                 type == AceType.AccessDeniedCallback )
901             {
902                 result = 0;
903             }
904             else if ( type == AceType.AccessDeniedObject ||
905                 type == AceType.AccessDeniedCallbackObject )
906             {
907                 result = 1;
908             }
909             else if ( type == AceType.AccessAllowed ||
910                 type == AceType.AccessAllowedCallback )
911             {
912                 result = 2;
913             }
914             else if ( type == AceType.AccessAllowedObject ||
915                 type == AceType.AccessAllowedCallbackObject )
916             {
917                 result = 3;
918             }
919             else
920             {
921                 //
922                 // custom aces are at the second group
923                 //
924                 result = ushort.MaxValue + ace._indexInAcl;
925             }
926
927             return result;
928         }
929
930         //
931         // Compares two system ACEs and returns
932         //    LessThan if ace1 < ace2
933         //    EqualTo if ace1 == ace2
934         //    GreaterThan if ace1 > ace2
935         //
936         // The order is:
937         //        - explicit audit or alarm ACEs
938         //        - explicit audit or alarm object ACEs
939         //        - inherited ACEs (in the original order )
940         //        - user-defined ACEs (in the original order )
941         //
942
943         private static int SaclAcePriority( GenericAce ace )
944         {
945             int result;
946             AceType type = ace.AceType;
947
948             if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
949             {
950                 result = 2 * ushort.MaxValue + ace._indexInAcl;
951             }
952             else if ( type == AceType.SystemAudit ||
953                 type == AceType.SystemAlarm ||
954                 type == AceType.SystemAuditCallback ||
955                 type == AceType.SystemAlarmCallback )
956             {
957                 result = 0;
958             }
959             else if ( type == AceType.SystemAuditObject ||
960                 type == AceType.SystemAlarmObject ||
961                 type == AceType.SystemAuditCallbackObject ||
962                 type == AceType.SystemAlarmCallbackObject )
963             {
964                 result = 1;
965             }
966             else
967             {
968                 result = ushort.MaxValue + ace._indexInAcl;
969             }
970
971             return result;
972         }
973
974         private static ComparisonResult CompareAces( GenericAce ace1, GenericAce ace2, bool isDacl )
975         {
976             int ace1Priority = isDacl ? DaclAcePriority( ace1 ) : SaclAcePriority( ace1 );
977             int ace2Priority = isDacl ? DaclAcePriority( ace2 ) : SaclAcePriority( ace2 );
978
979             if ( ace1Priority < ace2Priority )
980             {
981                 return ComparisonResult.LessThan;
982             }
983             else if ( ace1Priority > ace2Priority )
984             {
985                 return ComparisonResult.GreaterThan;
986             }
987             else
988             {
989                 KnownAce k_ace1 = ace1 as KnownAce;
990                 KnownAce k_ace2 = ace2 as KnownAce;
991
992                 if ( k_ace1 != null && k_ace2 != null )
993                 {
994                     int result = k_ace1.SecurityIdentifier.CompareTo( k_ace2.SecurityIdentifier );
995
996                     if ( result < 0 )
997                     {
998                         return ComparisonResult.LessThan;
999                     }
1000                     else if ( result > 0 )
1001                     {
1002                         return ComparisonResult.GreaterThan;
1003                     }
1004                 }
1005
1006                 return ComparisonResult.EqualTo;
1007             }
1008         }
1009
1010         private void QuickSort( int left, int right, bool isDacl )
1011         {
1012             GenericAce pivot;
1013             int leftHold, rightHold;
1014             int pivotIndex;
1015
1016             if ( left >= right )
1017             {
1018                 return;
1019             }
1020
1021             leftHold = left;
1022             rightHold = right;
1023
1024             pivot = _acl[left];
1025             pivotIndex = left;
1026
1027             while ( left < right )
1028             {
1029 //              while (( _acl[right] >= pivot ) && ( left < right ))
1030                 while (( ComparisonResult.LessThan != CompareAces( _acl[right], pivot, isDacl ) ) && ( left < right ))
1031                 {
1032                     right--;
1033                 }
1034                 
1035                 if ( left != right )
1036                 {
1037                     _acl[left] = _acl[right];
1038                     left++;
1039                 }
1040
1041 //              while (( _acl[left] <= pivot ) && ( left < right ))
1042                 while (( ComparisonResult.GreaterThan != CompareAces( _acl[left], pivot, isDacl ) ) && ( left < right ))
1043                 {
1044                     left++;
1045                 }
1046                 
1047                 if ( left != right )
1048                 {
1049                     _acl[right] = _acl[left];
1050                     right--;
1051                 }
1052             }
1053             
1054             _acl[left] = pivot;
1055             pivotIndex = left;
1056             left = leftHold;
1057             right = rightHold;
1058             
1059             if ( left < pivotIndex )
1060             {
1061                 QuickSort( left, pivotIndex - 1, isDacl );
1062             }
1063
1064             if ( right > pivotIndex )
1065             {
1066                 QuickSort( pivotIndex + 1, right, isDacl );
1067             }
1068         }
1069
1070         //
1071         // Inspects the ACE, modifies it by stripping away unnecessary or
1072         // meaningless flags.
1073         // Returns 'true' if the ACE should remain in the ACL, 'false' otherwise
1074         //
1075
1076         private bool InspectAce( ref GenericAce ace, bool isDacl )
1077         {
1078             const AceFlags AuditFlags =
1079                 AceFlags.SuccessfulAccess |
1080                 AceFlags.FailedAccess;
1081
1082             const AceFlags InheritFlags =
1083                 AceFlags.ObjectInherit |
1084                 AceFlags.ContainerInherit |
1085                 AceFlags.NoPropagateInherit |
1086                 AceFlags.InheritOnly;
1087
1088             //
1089             // Any ACE without at least one bit set in the access mask can be removed
1090             //
1091
1092             KnownAce knownAce = ace as KnownAce;
1093
1094             if ( knownAce != null )
1095             {
1096                 if ( knownAce.AccessMask == 0 )
1097                 {
1098                     return false;
1099                 }
1100             }
1101
1102             if ( !IsContainer )
1103             {
1104                 //
1105                 // On a leaf object ACL, inheritance bits are meaningless.
1106                 // Specifically, an ACE marked "inherit-only" will never participate
1107                 // in access control and can be removed.
1108                 // Similarly, an ACE marked "container-inherit", "no-propagate-inherit"
1109                 // or "object-inherit" can have those bits cleared since they carry
1110                 // no meaning.
1111                 //
1112
1113                 if (( ace.AceFlags & AceFlags.InheritOnly ) != 0 )
1114                 {
1115                     return false;
1116                 }
1117
1118                 if (( ace.AceFlags & InheritFlags ) != 0 )
1119                 {
1120                     unchecked { ace.AceFlags &= ~InheritFlags; }
1121                 }
1122             }
1123             else
1124             {
1125                 //
1126                 // Without either "container inherit" or "object inherit" to go with it,
1127                 // the InheritOnly bit is meaningless and the entire ACE can be removed.
1128                 //
1129
1130                 if ((( ace.AceFlags & AceFlags.InheritOnly ) != 0 ) &&
1131                     (( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) &&
1132                     (( ace.AceFlags & AceFlags.ObjectInherit ) == 0 ))
1133                 {
1134                     return false;
1135                 }
1136
1137                 //
1138                 // Without either "container inherit" or "object inherit" to go with it,
1139                 // the NoPropagateInherit bit is meaningless and can be turned off.
1140                 //
1141                 if ((( ace.AceFlags & AceFlags.NoPropagateInherit ) != 0 ) &&
1142                     (( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) &&
1143                     (( ace.AceFlags & AceFlags.ObjectInherit ) == 0 ))
1144                 {
1145                     unchecked { ace.AceFlags &= ~AceFlags.NoPropagateInherit; }
1146                 }
1147             }
1148
1149             QualifiedAce qualifiedAce = knownAce as QualifiedAce;
1150
1151             if ( isDacl )
1152             {
1153                 //
1154                 // There is no place for audit flags on a DACL
1155                 //
1156
1157                 unchecked { ace.AceFlags &= ~AuditFlags; }
1158
1159                 if ( qualifiedAce != null )
1160                 {
1161                     //
1162                     // Qualified ACEs in a DACL must be allow or deny ACEs
1163                     //
1164
1165                     if ( qualifiedAce.AceQualifier != AceQualifier.AccessAllowed &&
1166                         qualifiedAce.AceQualifier != AceQualifier.AccessDenied )
1167                     {
1168                         return false;
1169                     }
1170                 }
1171             }
1172             else
1173             {
1174                 //
1175                 // On a SACL, any ACE that does not specify Success or Failure
1176                 // flags can be removed
1177                 //
1178
1179                 if (( ace.AceFlags & AuditFlags ) == 0 )
1180                 {
1181                     return false;
1182                 }
1183
1184                 //
1185                 // Qualified ACEs in a SACL must be audit ACEs
1186                 //
1187
1188                 if ( qualifiedAce != null )
1189                 {
1190                     if ( qualifiedAce.AceQualifier != AceQualifier.SystemAudit )
1191                     {
1192                         return false;
1193                     }
1194                 }
1195             }
1196             return true;
1197         }
1198
1199         //
1200         // Strips meaningless flags from ACEs, removes meaningless ACEs
1201         //
1202
1203         private void RemoveMeaninglessAcesAndFlags( bool isDacl )
1204         {
1205             //
1206             // Be warned: do NOT use the Count property because it has
1207             // side-effect of calling canonicalization.
1208             //
1209
1210             for ( int i = _acl.Count - 1; i >= 0; i-- )
1211             {
1212                 GenericAce ace = _acl[i];
1213
1214                 if ( false == InspectAce( ref ace, isDacl ))
1215                 {
1216                     _acl.RemoveAce( i );
1217                 }
1218             }
1219         }
1220
1221         //
1222         // Converts the ACL to its canonical form
1223         //
1224
1225         private void Canonicalize( bool compact, bool isDacl )
1226         {
1227             //
1228             // for quick sort to work, we must not allow the ace's indexes - which are constantly
1229             // changing during sorting - to influence our element's sorting order value. For
1230             // that purpose, we fix the ace's _indexInAcl here and use it for creating the
1231             // ace's sorting order value.
1232             //
1233  
1234             for (ushort aclIndex = 0; aclIndex < _acl.Count; aclIndex++)
1235             {
1236                 _acl[aclIndex]._indexInAcl = aclIndex;
1237             }
1238
1239             QuickSort( 0, _acl.Count - 1, isDacl );
1240
1241             if ( compact )
1242             {
1243                 for ( int i = 0; i < Count - 1; i++ )
1244                 {
1245                     QualifiedAce thisAce = _acl[i] as QualifiedAce;
1246
1247                     if ( thisAce == null )
1248                     {
1249                         continue;
1250                     }
1251
1252                     QualifiedAce nextAce = _acl[i + 1] as QualifiedAce;
1253
1254                     if ( nextAce == null )
1255                     {
1256                         continue;
1257                     }
1258
1259                     if ( true == MergeAces( ref thisAce, nextAce ))
1260                     {
1261                         _acl.RemoveAce(i + 1);
1262                     }
1263                 }
1264             }
1265         }
1266
1267         //
1268         // This method determines whether the object type and inherited object type from the original ace
1269         // should be retained or not based on access mask and aceflags for a given split 
1270         //
1271         private void GetObjectTypesForSplit( ObjectAce originalAce, int accessMask, AceFlags aceFlags, out ObjectAceFlags objectFlags, out Guid objectType, out Guid inheritedObjectType ) 
1272         {
1273
1274             objectFlags = 0;
1275             objectType = Guid.Empty;
1276             inheritedObjectType = Guid.Empty;
1277
1278             //
1279             // We should retain the object type if the access mask for this split contains any bits that refer to object type
1280             //
1281             if (( accessMask & ObjectAce.AccessMaskWithObjectType ) != 0 ) 
1282             {
1283                 // keep the original ace's object flags and object type
1284                 objectType = originalAce.ObjectAceType;
1285                 objectFlags |= originalAce.ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent;
1286             }
1287
1288             //
1289             // We should retain the inherited object type if the aceflags for this contains inheritance (ContainerInherit)
1290             //
1291             if (( aceFlags & AceFlags.ContainerInherit ) != 0 ) 
1292             {
1293                 // keep the original ace's object flags and object type
1294                 inheritedObjectType = originalAce.InheritedObjectAceType;
1295                 objectFlags |= originalAce.ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent;
1296             }
1297         }
1298
1299         private bool ObjectTypesMatch( QualifiedAce ace, QualifiedAce newAce )
1300         {
1301             Guid objectType = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceType : Guid.Empty;
1302             Guid newObjectType = ( newAce is ObjectAce ) ? (( ObjectAce ) newAce ).ObjectAceType : Guid.Empty;
1303
1304             return objectType.Equals( newObjectType );
1305         }
1306
1307         private bool InheritedObjectTypesMatch( QualifiedAce ace, QualifiedAce newAce )
1308         {
1309             Guid inheritedObjectType = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).InheritedObjectAceType : Guid.Empty;
1310             Guid newInheritedObjectType = ( newAce is ObjectAce ) ? (( ObjectAce ) newAce ).InheritedObjectAceType : Guid.Empty;
1311
1312             return inheritedObjectType.Equals( newInheritedObjectType );
1313         }
1314
1315         private bool AccessMasksAreMergeable( QualifiedAce ace, QualifiedAce newAce )
1316         {
1317             //
1318             // The access masks are mergeable in any of the following conditions
1319             // 1. Object types match
1320             // 2. (Object types do not match) The existing ace does not have an object type and 
1321             //     already contains all the bits of the new ace which refer to the object type
1322             //
1323
1324             if ( ObjectTypesMatch( ace, newAce ))
1325             {
1326                 // case 1
1327                 return true;
1328             }
1329
1330             ObjectAceFlags objectFlags = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceFlags : ObjectAceFlags.None;
1331             if ((( ace.AccessMask & newAce.AccessMask & ObjectAce.AccessMaskWithObjectType ) ==  ( newAce.AccessMask & ObjectAce.AccessMaskWithObjectType )) &&
1332                  (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 ))
1333             {
1334                 // case 2
1335                 return true;
1336             }
1337
1338             return false;
1339         }
1340
1341         private bool AceFlagsAreMergeable( QualifiedAce ace, QualifiedAce newAce )
1342         {
1343             //
1344             // The ace flags can be considered for merge in any of the following conditions
1345             // 1. Inherited object types match 
1346             // 2. (Inherited object types do not match) The existing ace does not have an inherited object type and 
1347             //     already contains all the bits of the new ace
1348             //
1349
1350             if ( InheritedObjectTypesMatch( ace, newAce ))
1351             {
1352                 // case 1
1353                 return true;
1354             }
1355
1356             ObjectAceFlags objectFlags = ( ace is ObjectAce ) ? (( ObjectAce ) ace ).ObjectAceFlags : ObjectAceFlags.None;
1357             if (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 )
1358             {
1359                 // case 2
1360
1361                 //
1362                 // This method is called only when the access masks of the two aces are already confirmed to be exact matches
1363                 // therefore the second condition of case 2 is already verified
1364                 //
1365                 Contract.Assert(( ace.AccessMask & newAce.AccessMask) ==  newAce.AccessMask, "AceFlagsAreMergeable:: AccessMask of existing ace does not contain all access bits of new ace.");
1366                 return true;
1367             }
1368
1369             return false;
1370         }
1371
1372         private bool GetAccessMaskForRemoval( QualifiedAce ace, ObjectAceFlags objectFlags, Guid objectType, ref int accessMask )
1373         {
1374             if (( ace.AccessMask & accessMask & ObjectAce.AccessMaskWithObjectType ) != 0 ) 
1375             {
1376
1377                 // 
1378                 // If the aces have access bits in common which refer to object types
1379                 // then we follow these rules:
1380                 //
1381                 //       Remove    No OT    OT = A        OT = B
1382                 // Existing
1383                 // 
1384                 //   No OT          Remove   Invalid        Invalid
1385                 //
1386                 //   OT = A        Remove   Remove      Nothing Common
1387                 //
1388             
1389                 
1390                 if ( ace is ObjectAce )
1391                 {
1392                     bool commonAccessBitsWithObjectTypeExist = true;
1393                     ObjectAce objectAce = ace as ObjectAce;
1394
1395                     //
1396                     // if what we are trying to remove has an object type 
1397                     // but the existing ace does not then this is an invalid case
1398                     //
1399                     if ((( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 ) && 
1400                         (( objectAce.ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 ))
1401                     {
1402                         return false;
1403                     }
1404
1405                     //
1406                     // if what we are trying to remove has no object type or
1407                     // if object types match (since at this point we have ensured that both have object types present) 
1408                     // then we have common access bits with object type
1409                     //
1410                     commonAccessBitsWithObjectTypeExist = (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 ) ||
1411                                                                                     objectAce.ObjectTypesMatch( objectFlags, objectType );
1412                     if ( !commonAccessBitsWithObjectTypeExist ) 
1413                     {
1414                         accessMask &= ~ObjectAce.AccessMaskWithObjectType;
1415                     }
1416                 }
1417                 else if (( objectFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 ) 
1418                 {
1419                     // the existing ace is a common ace and the one we're removing 
1420                     // refers to a specific object type so this is invalid
1421                     return false;
1422                 }               
1423             }
1424
1425             return true;
1426
1427         }
1428
1429         private bool GetInheritanceFlagsForRemoval( QualifiedAce ace, ObjectAceFlags objectFlags, Guid inheritedObjectType, ref AceFlags aceFlags )
1430         {
1431             if ((( ace.AceFlags & AceFlags.ContainerInherit ) != 0 )  && (( aceFlags & AceFlags.ContainerInherit ) != 0 ))
1432             {
1433
1434                 // 
1435                 // If the aces have inheritance bits in common 
1436                 // then we follow these rules:
1437                 //
1438                 //       Remove    No IOT    IOT = A        IOT = B
1439                 // Existing
1440                 // 
1441                 //   No IOT          Remove   Invalid        Invalid
1442                 //
1443                 //   IOT = A        Remove   Remove      Nothing Common
1444                 //
1445             
1446                 
1447                 if ( ace is ObjectAce )
1448                 {
1449                     bool commonInheritanceFlagsExist = true;
1450                     ObjectAce objectAce = ace as ObjectAce;
1451
1452                     //
1453                     // if what we are trying to remove has an inherited object type 
1454                     // but the existing ace does not then this is an invalid case
1455                     //
1456                     if ((( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) != 0 ) && 
1457                         (( objectAce.ObjectAceFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 ))
1458                     {
1459                         return false;
1460                     }
1461
1462                     //
1463                     // if what we are trying to remove has no inherited object type or
1464                     // if inherited object types match then we have common inheritance flags                     
1465                     //
1466                     commonInheritanceFlagsExist = (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) == 0 ) ||
1467                                                                        objectAce.InheritedObjectTypesMatch( objectFlags, inheritedObjectType );
1468                     if ( !commonInheritanceFlagsExist ) 
1469                     {
1470                         aceFlags &= ~AceFlags.InheritanceFlags;
1471                     }
1472                 }
1473                 else if (( objectFlags & ObjectAceFlags.InheritedObjectAceTypePresent ) != 0 ) 
1474                 {
1475                     // the existing ace is a common ace and the one we're removing 
1476                     // refers to a specific child type so this is invalid
1477                     return false;
1478                 }               
1479             }
1480
1481             return true;
1482
1483         }
1484
1485         static private bool AceOpaquesMatch( QualifiedAce ace, QualifiedAce newAce )
1486         {
1487             byte[] aceOpaque = ace.GetOpaque();
1488             byte[] newAceOpaque = newAce.GetOpaque();
1489
1490             if ( aceOpaque == null || newAceOpaque == null )
1491             {
1492                 return aceOpaque == newAceOpaque;
1493             }
1494
1495             if ( aceOpaque.Length != newAceOpaque.Length )
1496             {
1497                 return false;
1498             }
1499
1500             for ( int i = 0; i < aceOpaque.Length; ++i )
1501             {
1502                 if ( aceOpaque[i] != newAceOpaque[i] )
1503                 {
1504                     return false;
1505                 }
1506             }
1507
1508             return true;
1509         }
1510
1511         static private bool AcesAreMergeable( QualifiedAce ace, QualifiedAce newAce )
1512         {
1513             //
1514             // Only interested in ACEs with the specified type
1515             //
1516
1517             if ( ace.AceType != newAce.AceType )
1518             {
1519                 return false;
1520             }
1521
1522             //
1523             // Only interested in explicit (non-inherited) ACEs
1524             //
1525
1526             if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
1527             {
1528                 return false;
1529             }
1530
1531             if (( newAce.AceFlags & AceFlags.Inherited ) != 0 )
1532             {
1533                 return false;
1534             }
1535
1536             //
1537             // Only interested in ACEs with the specified qualifier
1538             //
1539
1540             if ( ace.AceQualifier != newAce.AceQualifier )
1541             {
1542                 return false;
1543             }
1544
1545             //
1546             // Only interested in ACEs with the specified SID
1547             //
1548
1549             if ( ace.SecurityIdentifier != newAce.SecurityIdentifier )
1550             {
1551                 return false;
1552             }
1553
1554             //
1555             // Only interested in ACEs with the specified callback data
1556             //
1557
1558             if ( !AceOpaquesMatch( ace, newAce ))
1559             {
1560                 return false;
1561             }
1562
1563             return true;
1564         }
1565
1566         //
1567         // Merge routine for qualified ACEs
1568         //
1569
1570         private bool MergeAces( ref QualifiedAce ace, QualifiedAce newAce )
1571         {
1572             //
1573             // Check whether the ACEs are potentially mergeable
1574             //
1575
1576             if ( !AcesAreMergeable( ace, newAce ))
1577             {
1578                 return false;
1579             }
1580
1581             //
1582             // The modification algorithm proceeds in stages
1583             //
1584             // Stage 1: if flags match, add to the access mask
1585             //
1586
1587             if ( ace.AceFlags == newAce.AceFlags )
1588             {
1589                 if ( ace is ObjectAce  || newAce is ObjectAce ) 
1590                 {
1591                     // for object aces we need to match the inherited object types (for ace flags equality)
1592                     if ( InheritedObjectTypesMatch( ace, newAce ))
1593                     {
1594                         // also since access mask bits are further qualified by object type, they cannot always be added on
1595                         if ( AccessMasksAreMergeable( ace, newAce ))
1596                         {
1597                             ace.AccessMask |= newAce.AccessMask;
1598                             return true;
1599                         }
1600                     }
1601                 }
1602                 else 
1603                 {
1604                     ace.AccessMask |= newAce.AccessMask;
1605                     return true;
1606                 }
1607             }
1608             
1609            
1610             
1611             //
1612             // Stage 2: Audit flags can be combined if the rest of the
1613             //          flags (both access mask and inheritance) match
1614             //
1615             
1616             if ((( ace.AceFlags & AceFlags.InheritanceFlags ) == ( newAce.AceFlags & AceFlags.InheritanceFlags )) &&
1617                 ( ace.AccessMask == newAce.AccessMask ))
1618             {           
1619                 if (( ace is ObjectAce ) || ( newAce is ObjectAce ))
1620                 {
1621                     // for object aces we need to match the inherited object types (for inheritance flags equality) and object type (for access mask equality) as well
1622                     if ( InheritedObjectTypesMatch( ace, newAce ) && 
1623                         ( ObjectTypesMatch( ace, newAce )))
1624                     {
1625                         ace.AceFlags |= ( newAce.AceFlags & AceFlags.AuditFlags );
1626                         return true;
1627                     }
1628                 }
1629                 else 
1630                 {
1631                     ace.AceFlags |= ( newAce.AceFlags & AceFlags.AuditFlags );
1632                     return true;
1633                 }
1634                 
1635             }
1636             
1637             //
1638             // Stage 3: Inheritance flags can be combined in some cases
1639             //          provided access mask and audit bits are the same
1640             //
1641             
1642             if ((( ace.AceFlags & AceFlags.AuditFlags ) == ( newAce.AceFlags & AceFlags.AuditFlags )) &&
1643                 ( ace.AccessMask == newAce.AccessMask ))
1644             {
1645                 AceFlags merged;
1646
1647                 //
1648                 // See whether the inheritance bits can be merged
1649                 //
1650             
1651                 if (( ace is ObjectAce ) || ( newAce is ObjectAce ))
1652                 {
1653                     // object types need to match (for access mask equality) and inheritance flags need additional DS specific logic 
1654                     // to check whether they can be merged                  
1655                     if (( ObjectTypesMatch( ace, newAce )) &&
1656                          ( AceFlagsAreMergeable( ace, newAce )))
1657                     {
1658                         if ( true == MergeInheritanceBits( ace.AceFlags, newAce.AceFlags, IsDS, out merged ))
1659                         {
1660                             ace.AceFlags = ( merged | ( ace.AceFlags & AceFlags.AuditFlags ));
1661                             return true;
1662                         }
1663                     }
1664                 }
1665                 else
1666                 {
1667                     if ( true == MergeInheritanceBits( ace.AceFlags, newAce.AceFlags, IsDS, out merged ))
1668                     {
1669                         ace.AceFlags = ( merged | ( ace.AceFlags & AceFlags.AuditFlags ));
1670                         return true;
1671                     }
1672                 }
1673                 
1674             }
1675
1676             return false;
1677         }
1678
1679         //
1680         // Returns 'true' if the ACL is in canonical order; 'false' otherwise
1681         //
1682
1683         private bool CanonicalCheck( bool isDacl )
1684         {
1685             if ( isDacl )
1686             {
1687                 //
1688                 // DACL canonical order:
1689                 //   Explicit Deny - Explicit Allow - Inherited
1690                 //
1691
1692                 const int AccessDenied = 0;
1693                 const int AccessAllowed = 1;
1694                 const int Inherited = 2;
1695                 const int Unknown = 3;
1696
1697                 int currentStage = AccessDenied;
1698
1699                 //
1700                 // In this loop, do NOT use 'Count' as upper bound of the loop,
1701                 // since doing so will canonicalize the ACL invalidating the result
1702                 // of this check!
1703                 //
1704
1705                 for ( int i = 0; i < _acl.Count; i++ )
1706                 {
1707                     int aceStage = Unknown;
1708
1709                     GenericAce ace = _acl[i];
1710
1711                     if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
1712                     {
1713                         aceStage = Inherited;
1714                     }
1715                     else
1716                     {
1717                         QualifiedAce qualifiedAce = ace as QualifiedAce;
1718
1719                         if ( qualifiedAce == null )
1720                         {
1721                             //
1722                             // Explicit ACE is not recognized - this is not a canonical ACL
1723                             //
1724
1725                             return false;
1726                         }
1727
1728                         if ( qualifiedAce.AceQualifier == AceQualifier.AccessAllowed )
1729                         {
1730                             aceStage = AccessAllowed;
1731                         }
1732                         else if ( qualifiedAce.AceQualifier == AceQualifier.AccessDenied )
1733                         {
1734                             aceStage = AccessDenied;
1735                         }
1736                         else
1737                         {
1738                             //
1739                             // Only allow and deny ACEs are allowed here
1740                             //
1741
1742                             Contract.Assert( false, "Audit and alarm ACEs must have been stripped by remove-meaningless logic" );
1743                             return false;
1744                         }
1745                     }
1746
1747                     if ( aceStage == Unknown )
1748                     {
1749                         continue;
1750                     }
1751
1752                     if ( aceStage > currentStage )
1753                     {
1754                         currentStage = aceStage;
1755                     }
1756                     else if ( aceStage < currentStage )
1757                     {
1758                         return false;
1759                     }
1760                 }
1761             }
1762             else
1763             {
1764                 //
1765                 // SACL canonical order:
1766                 //   Explicit - Inherited                
1767                 //
1768
1769                 const int Explicit = 0;
1770                 const int Inherited = 1;
1771                 const int Unknown = 2;
1772
1773                 int currentStage = Explicit;
1774
1775                 //
1776                 // In this loop, do NOT use 'Count' as upper bound of the loop,
1777                 // since doing so will canonicalize the ACL invalidating the result
1778                 // of this check!
1779                 //
1780
1781                 for ( int i = 0; i < _acl.Count; i++ )
1782                 {
1783                     int aceStage = Unknown;
1784
1785                     GenericAce ace = _acl[i];
1786
1787                     if ( ace == null )
1788                     {
1789                         //
1790                         // <[....]-9/19/2004> Afraid to yank this statement now
1791                         // for fear of destabilization, so adding an assert instead
1792                         //
1793
1794                         Contract.Assert( ace != null, "How did a null ACE end up in a SACL?" );
1795                         continue;
1796                     }
1797
1798                     if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
1799                     {
1800                         aceStage = Inherited;
1801                     }
1802                     else
1803                     {
1804                         QualifiedAce qualifiedAce = ace as QualifiedAce;
1805
1806                         if ( qualifiedAce == null )
1807                         {
1808                             //
1809                             // Explicit ACE is not recognized - this is not a canonical ACL
1810                             //
1811
1812                             return false;
1813                         }
1814
1815                         if ( qualifiedAce.AceQualifier == AceQualifier.SystemAudit ||
1816                             qualifiedAce.AceQualifier == AceQualifier.SystemAlarm )
1817                         {
1818                             aceStage = Explicit;
1819                         }
1820                         else
1821                         {
1822                             //
1823                             // Only audit and alarm ACEs are allowed here
1824                             //
1825
1826                             Contract.Assert( false, "Allow and deny ACEs must have been stripped by remove-meaningless logic" );
1827                             return false;
1828                         }
1829                     }
1830
1831                     if ( aceStage > currentStage )
1832                     {
1833                         currentStage = aceStage;
1834                     }
1835                     else if ( aceStage < currentStage )
1836                     {
1837                         return false;
1838                     }
1839                 }
1840             }
1841
1842             return true;
1843         }
1844
1845         [Pure]
1846         private void ThrowIfNotCanonical()
1847         {
1848             if ( !_isCanonical )
1849             {
1850                 throw new InvalidOperationException( Environment.GetResourceString( "InvalidOperation_ModificationOfNonCanonicalAcl" ));
1851             }
1852         }
1853
1854         #endregion
1855
1856         #region Constructors
1857
1858         //
1859         // Creates an empty ACL
1860         //
1861
1862         internal CommonAcl( bool isContainer, bool isDS, byte revision, int capacity )
1863             : base()
1864         {
1865             _isContainer = isContainer;
1866             _isDS = isDS;
1867             _acl = new RawAcl( revision, capacity );
1868             _isCanonical = true; // since it is empty
1869         }
1870
1871         //
1872         // Creates an ACL from a raw ACL
1873         // - 'trusted' (internal) callers get to pass the raw ACL
1874         //   that this object will take ownership of
1875         // - 'untrusted' callers are handled by creating a local
1876         //   copy of the ACL passed in
1877         //
1878
1879         internal CommonAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted, bool isDacl )
1880             : base()
1881         {
1882             if ( rawAcl == null )
1883             {
1884                 throw new ArgumentNullException( "rawAcl" );
1885             }
1886             Contract.EndContractBlock();
1887
1888             _isContainer = isContainer;
1889             _isDS = isDS;
1890
1891             if (trusted)
1892             {
1893                 //
1894                 // In the trusted case, we take over ownership of the ACL passed in
1895                 //
1896
1897                 _acl = rawAcl;
1898
1899                 RemoveMeaninglessAcesAndFlags( isDacl );
1900             }
1901             else
1902             {
1903                 //
1904                 // In the untrusted case, we create our own raw ACL to keep the ACEs in
1905                 //
1906
1907                 _acl = new RawAcl( rawAcl.Revision, rawAcl.Count );
1908             
1909                 for ( int i = 0; i < rawAcl.Count; i++ )
1910                 {
1911                     //
1912                     // Clone each ACE prior to putting it in
1913                     //
1914
1915                     GenericAce ace = rawAcl[i].Copy();
1916
1917                     //
1918                     // Avoid inserting meaningless ACEs
1919                     //
1920
1921                     if ( true == InspectAce( ref ace, isDacl ))
1922                     {
1923                         _acl.InsertAce( _acl.Count, ace );
1924                     }
1925                 }
1926             }
1927
1928             //
1929             // See whether the ACL is canonical to begin with
1930             //
1931
1932             if ( true == CanonicalCheck( isDacl ))
1933             {
1934                 //
1935                 // Sort and compact the array
1936                 //
1937
1938                 Canonicalize( true, isDacl );
1939
1940                 _isCanonical = true;
1941             }
1942             else
1943             {
1944                 _isCanonical = false;
1945             }
1946         }
1947
1948         #endregion
1949
1950         #region Internal Properties
1951
1952         internal RawAcl RawAcl
1953         {
1954             get { return _acl; }
1955         }
1956
1957         #endregion
1958
1959         #region Protected Methods
1960
1961         internal void CheckAccessType( AccessControlType accessType )
1962         {
1963             if ( accessType != AccessControlType.Allow &&
1964                 accessType != AccessControlType.Deny )
1965             {
1966                 throw new ArgumentOutOfRangeException(
1967                     "accessType",
1968                     Environment.GetResourceString( "ArgumentOutOfRange_Enum" ));
1969             }
1970         }
1971
1972         internal void CheckFlags( InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
1973         {
1974             if ( IsContainer )
1975             {
1976                 //
1977                 // Supplying propagation flags without inheritance flags is illegal
1978                 //
1979
1980                 if ( inheritanceFlags == InheritanceFlags.None &&
1981                     propagationFlags != PropagationFlags.None )
1982                 {
1983                     throw new ArgumentException(
1984                         Environment.GetResourceString( "Argument_InvalidAnyFlag" ),
1985                         "propagationFlags" );
1986                 }
1987             }
1988             else if ( inheritanceFlags != InheritanceFlags.None )
1989             {
1990                 throw new ArgumentException(
1991                     Environment.GetResourceString("Argument_InvalidAnyFlag"),
1992                     "inheritanceFlags" );
1993             }
1994             else if ( propagationFlags != PropagationFlags.None )
1995             {
1996                 throw new ArgumentException(
1997                     Environment.GetResourceString( "Argument_InvalidAnyFlag" ),
1998                     "propagationFlags" );
1999             }
2000
2001             return;
2002         }
2003
2004         //
2005         // Helper function behind all the AddXXX methods for qualified aces
2006         //
2007
2008         internal void AddQualifiedAce( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
2009         {
2010             if ( sid == null )
2011             {
2012                 throw new ArgumentNullException( "sid" );
2013             }
2014             Contract.EndContractBlock();
2015
2016             ThrowIfNotCanonical();
2017
2018             bool aceMerged = false; // if still false after all attempts to merge, create new entry
2019
2020             if ( qualifier == AceQualifier.SystemAudit &&
2021                 (( flags & AceFlags.AuditFlags ) == 0 ))
2022             {
2023                 throw new ArgumentException(
2024                     Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ),
2025                     "flags" );
2026             }
2027
2028             if ( accessMask == 0 )
2029             {
2030                 throw new ArgumentException(
2031                     Environment.GetResourceString( "Argument_ArgumentZero" ),
2032                     "accessMask" );
2033             }
2034
2035             GenericAce newAce;
2036
2037             if (( !IsDS ) || ( objectFlags == ObjectAceFlags.None ))
2038             {
2039                 newAce = new CommonAce( flags, qualifier, accessMask, sid, false, null );
2040             }
2041             else
2042             {
2043                 newAce = new ObjectAce( flags, qualifier, accessMask, sid, objectFlags, objectType, inheritedObjectType, false, null );
2044             }
2045
2046             //
2047             // Make sure the new ACE wouldn't be meaningless before proceeding
2048             //
2049
2050             if ( false == InspectAce( ref newAce, ( this is DiscretionaryAcl )))
2051             {
2052                 return;
2053             }
2054
2055             //
2056             // See if the new ACE can be merged with any of the existing ones
2057             //
2058
2059             for ( int i = 0; i < Count; i++ )
2060             {
2061                 QualifiedAce ace = _acl[i] as QualifiedAce;
2062
2063                 if ( ace == null )
2064                 {
2065                     continue;
2066                 }
2067
2068                 if ( true == MergeAces( ref ace, newAce as QualifiedAce ))
2069                 {
2070                     aceMerged = true;
2071                     break;
2072                 }
2073             }
2074
2075             //
2076             // Couldn't modify any existing entry, so add a new one
2077             //
2078
2079             if ( !aceMerged )
2080             {
2081                 _acl.InsertAce( _acl.Count, newAce );
2082
2083                 _isDirty = true;
2084             }
2085             OnAclModificationTried();
2086         }
2087
2088         //
2089         // Helper function behind all the SetXXX methods
2090         //
2091
2092         internal void SetQualifiedAce( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
2093         {
2094             if ( sid == null )
2095             {
2096                 throw new ArgumentNullException( "sid" );
2097             }
2098
2099             if ( qualifier == AceQualifier.SystemAudit &&
2100                 (( flags & AceFlags.AuditFlags ) == 0 ))
2101             {
2102                 throw new ArgumentException(
2103                     Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ),
2104                     "flags" );
2105             }
2106
2107             if ( accessMask == 0 )
2108             {
2109                 throw new ArgumentException(
2110                     Environment.GetResourceString( "Argument_ArgumentZero" ),
2111                     "accessMask" );
2112             }
2113             Contract.EndContractBlock();
2114             ThrowIfNotCanonical();
2115
2116             GenericAce newAce;
2117
2118             if (( !IsDS ) || ( objectFlags == ObjectAceFlags.None ))
2119             {
2120                 newAce = new CommonAce( flags, qualifier, accessMask, sid, false, null );
2121             }
2122             else
2123             {
2124                 newAce = new ObjectAce( flags, qualifier, accessMask, sid, objectFlags, objectType, inheritedObjectType, false, null );
2125             }
2126
2127             //
2128             // Make sure the new ACE wouldn't be meaningless before proceeding
2129             //
2130
2131             if ( false == InspectAce( ref newAce, ( this is DiscretionaryAcl )))
2132             {
2133                 return;
2134             }
2135
2136             for ( int i = 0; i < Count; i++ )
2137             {
2138                 QualifiedAce ace = _acl[i] as QualifiedAce;
2139
2140                 //
2141                 // Not a qualified ACE - keep going
2142                 //
2143
2144                 if ( ace == null )
2145                 {
2146                     continue;
2147                 }
2148
2149                 //
2150                 // Only interested in explicit (non-inherited) ACEs
2151                 //
2152
2153                 if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
2154                 {
2155                     continue;
2156                 }
2157
2158                 //
2159                 // Only interested in ACEs with the specified qualifier
2160                 //
2161
2162                 if ( ace.AceQualifier != qualifier )
2163                 {
2164                     continue;
2165                 }
2166
2167                 //
2168                 // Only interested in ACEs with the specified SID
2169                 //
2170
2171                 if ( ace.SecurityIdentifier != sid )
2172                 {
2173                     continue;
2174                 }
2175
2176                 //
2177                 // This ACE corresponds to the SID and qualifier in question - remove it
2178                 //
2179
2180                 _acl.RemoveAce( i );
2181                 i--;
2182             }
2183
2184             //
2185             // As a final step, add the ACE we want.
2186             // Add it at the end - we'll re-canonicalize later.
2187             //
2188
2189             _acl.InsertAce( _acl.Count, newAce );
2190
2191             //
2192             // To aid the efficiency of batch operations, recanonicalize this later
2193             //
2194
2195             _isDirty = true;
2196             OnAclModificationTried();
2197         }
2198
2199         //
2200         // Helper function behind all the RemoveXXX methods
2201         //
2202
2203         internal bool RemoveQualifiedAces( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, bool saclSemantics, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
2204         {
2205             if ( accessMask == 0 )
2206             {
2207                 throw new ArgumentException(
2208                     Environment.GetResourceString( "Argument_ArgumentZero" ),
2209                     "accessMask" );
2210             }
2211
2212             if ( qualifier == AceQualifier.SystemAudit &&
2213                 (( flags & AceFlags.AuditFlags ) == 0 ))
2214             {
2215                 throw new ArgumentException(
2216                     Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ),
2217                     "flags" );
2218             }
2219
2220             if ( sid == null )
2221             {
2222                 throw new ArgumentNullException( "sid" );
2223             }
2224             Contract.EndContractBlock();
2225             ThrowIfNotCanonical();
2226
2227
2228             //
2229             // Two passes are made.
2230             // During the first pass, no changes are made to the ACL,
2231             // the ACEs are simply evaluated to ascertain that the operation
2232             // can succeed.
2233             // If everything is kosher, the second pass is the one that makes changes.
2234             //
2235
2236             bool evaluationPass = true;
2237             bool removePossible = true; // unless proven otherwise
2238             
2239             //
2240             // Needed for DS acls to keep track of the original access mask specified for removal
2241             //
2242             int originalAccessMask = accessMask;
2243             AceFlags originalFlags = flags;
2244
2245             //
2246             // It is possible that the removal will result in an overflow exception
2247             // because more ACEs get inserted.
2248             // Save the current state of the object and revert to it later if
2249             // and exception is thrown.
2250             //
2251
2252             byte[] recovery = new byte[BinaryLength];
2253             GetBinaryForm( recovery, 0 );
2254
2255         MakeAnotherPass:
2256
2257             try
2258             {
2259                 for ( int i = 0; i < Count; i++ )
2260                 {
2261                     QualifiedAce ace = _acl[i] as QualifiedAce;
2262
2263                     //
2264                     // Not a qualified ACE - keep going
2265                     //
2266
2267                     if ( ace == null )
2268                     {
2269                         continue;
2270                     }
2271
2272                     //
2273                     // Only interested in explicit (non-inherited) ACEs
2274                     //
2275
2276                     if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
2277                     {
2278                         continue;
2279                     }
2280
2281                     //
2282                     // Only interested in ACEs with the specified qualifier
2283                     //
2284
2285                     if ( ace.AceQualifier != qualifier )
2286                     {
2287                         continue;
2288                     }
2289
2290                     //
2291                     // Only interested in ACEs with the specified SID
2292                     //
2293
2294                     if ( ace.SecurityIdentifier != sid )
2295                     {
2296                         continue;
2297                     }               
2298
2299                     //
2300                     // If access masks have nothing in common, skip the whole exercise
2301                     //
2302
2303                     if ( IsDS ) 
2304                     {
2305                         //
2306                         // incase of directory aces, if the access mask of the 
2307                         // existing and new ace have any bits in common that need 
2308                         // an object type, then we need to perform some checks on the
2309                         // object types in the two aces. Since certain bits are further qualified
2310                         // by the object type they cannot be determined to be common without 
2311                         // inspecting the object type. It is possible that the same bits may be set but
2312                         // the object types are different in which case they are really not common bits.
2313                         //
2314                         accessMask = originalAccessMask;
2315                         bool objectTypesConflict = !GetAccessMaskForRemoval( ace, objectFlags, objectType, ref accessMask );
2316
2317                         // if the access masks have nothing in common, skip
2318                         if (( ace.AccessMask & accessMask ) == 0 )
2319                         {
2320                             continue;
2321                         }
2322
2323                         //
2324                         // incase of directory aces, if the existing and new ace are being inherited, 
2325                         // then we need to perform some checks on the
2326                         // inherited object types in the two aces. Since inheritance is further qualified
2327                         // by the inherited object type the inheritance flags cannot be determined to be common without 
2328                         // inspecting the inherited object type. It is possible that both aces may be further inherited but if
2329                         // the inherited object types are different the inheritance may not be common.
2330                         //
2331                         flags = originalFlags;
2332                         bool inheritedObjectTypesConflict = !GetInheritanceFlagsForRemoval( ace, objectFlags, inheritedObjectType, ref flags );  
2333
2334                         if (((( ace.AceFlags & AceFlags.ContainerInherit ) == 0 ) && (( flags & AceFlags.ContainerInherit ) != 0 )  && (( flags & AceFlags.InheritOnly ) != 0 )) ||
2335                              ((( flags & AceFlags.ContainerInherit ) == 0 ) && (( ace.AceFlags & AceFlags.ContainerInherit ) != 0 )  && (( ace.AceFlags & AceFlags.InheritOnly ) != 0)))
2336                         {
2337                             // if one ace applies only to self and the other only to children/descendents we have nothing in common
2338                             continue;
2339                         }
2340                         
2341                         //
2342                         // if the ace being removed referred only to child types and child types among existing ace and
2343                         // ace being removed are not common then there is nothing in common between these aces (skip)
2344                         //
2345                         if ((( originalFlags & AceFlags.ContainerInherit ) != 0 ) && (( originalFlags & AceFlags.InheritOnly ) != 0 ) && (( flags & AceFlags.ContainerInherit ) == 0 )) 
2346                         {
2347                             continue;
2348                         }
2349
2350                         if ( objectTypesConflict || inheritedObjectTypesConflict )
2351                         {
2352                             //
2353                             // if we reached this stage, then we've found something common between the two aces.
2354                             // But since there is a conflict between the object types (or inherited object types), the remove is not possible
2355                             //
2356                             removePossible = false;
2357                             break;
2358                         }
2359                     }
2360                     else 
2361                     {
2362                         if (( ace.AccessMask & accessMask ) == 0 )
2363                         {
2364                             continue;
2365                         }
2366                     }
2367
2368                     //
2369                     // If audit flags on a SACL have nothing in common,
2370                     // skip the whole exercise
2371                     //
2372
2373                     if ( saclSemantics &&
2374                         (( ace.AceFlags & flags & AceFlags.AuditFlags ) == 0 ))
2375                     {
2376                         continue;
2377                     }
2378
2379                     //
2380                     // See if the ACE needs to be split into several
2381                     // To illustrate with an example, consider this equation:
2382                     //            From: CI OI    NP SA FA R W
2383                     //          Remove:    OI IO NP SA    R
2384                     //
2385                     // PermissionSplit: CI OI    NP SA FA   W   // remove R
2386                     //   AuditingSplit: CI OI    NP    FA R     // remove SA
2387                     //      MergeSplit: CI OI    NP SA    R     // ready for merge
2388                     //          Remove:    OI IO NP SA    R     // same audit and perm flags as merge split
2389                     //
2390                     //          Result: CI OI    NP SA FA   W   // PermissionSplit
2391                     //                  CI OI    NP    FA R     // AuditingSplit
2392                     //                  CI       NP SA    R     // Result of perm removal
2393                     //
2394
2395                     //
2396                     // Example for DS acls (when removal is possible)
2397                     //
2398                     // From: CI(Guid) LC CC(Guid)
2399                     // Remove: CI IO LC
2400                     //
2401                     // PermissionSplit: CI(Guid) CC(Guid) // Remove GR
2402                     //        MergeSplit: CI(Guid) LC // Ready for merge
2403                     //           Remove: CI IO LC // Removal is possible since we are trying to remove inheritance for
2404                     //                                            all child types when it exists for one specific child type
2405                     //
2406                     //              Result: CI(Guid) CC(Guid) // PermissionSplit
2407                     //                         LC // Result of perm removal
2408                     //
2409                     //
2410                     // Example for DS acls (when removal is NOT possible)
2411                     //
2412                     // From: CI GR CC(Guid)
2413                     // Remove: CI(Guid) IO LC
2414                     //
2415                     // PermissionSplit: CI CC(Guid) // Remove GR
2416                     //        MergeSplit: CI LC // Ready for merge
2417                     //           Remove: CI(Guid) IO CC // Removal is not possible since we are trying to remove 
2418                     //                                                     inheritance for a specific child type when it exists for all child types
2419                     //
2420
2421                     // Permission split settings
2422                     AceFlags ps_AceFlags = 0;
2423                     int ps_AccessMask = 0;
2424                     ObjectAceFlags ps_ObjectAceFlags = 0;
2425                     Guid ps_ObjectAceType = Guid.Empty;
2426                     Guid ps_InheritedObjectAceType = Guid.Empty;
2427
2428                     // Auditing split makes sense if this is a SACL
2429                     AceFlags as_AceFlags = 0;
2430                     int as_AccessMask = 0;
2431                     ObjectAceFlags as_ObjectAceFlags = 0;
2432                     Guid as_ObjectAceType = Guid.Empty;
2433                     Guid as_InheritedObjectAceType = Guid.Empty;
2434
2435                     // Merge split settings
2436                     AceFlags ms_AceFlags = 0;
2437                     int ms_AccessMask = 0;
2438                     ObjectAceFlags ms_ObjectAceFlags = 0;
2439                     Guid ms_ObjectAceType = Guid.Empty;
2440                     Guid ms_InheritedObjectAceType = Guid.Empty;
2441
2442                     // Merge result settings
2443                     AceFlags mergeResultFlags = 0;
2444                     bool mergeRemoveTotal = false;
2445
2446                     //
2447                     // First compute the permission split
2448                     //
2449
2450                     ps_AceFlags = ace.AceFlags;
2451                     unchecked { ps_AccessMask = ace.AccessMask & ~accessMask; }
2452
2453                     if ( ace is ObjectAce ) 
2454                     {
2455                         //
2456                         // determine what should be the object/inherited object types on the permission split
2457                         //
2458                         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 );
2459                     }
2460                     
2461                     //
2462                     // Next, for SACLs only, compute the auditing split
2463                     //
2464
2465                     if ( saclSemantics )
2466                     {
2467                         //
2468                         // This operation can set the audit bits region
2469                         // of ACE flags to zero;
2470                         // This case will be handled later
2471                         //
2472
2473                         unchecked { as_AceFlags = ace.AceFlags & ~( flags & AceFlags.AuditFlags ); }
2474
2475                         //
2476                         // The result of this evaluation is guaranteed
2477                         // not to be zero by now
2478                         //
2479
2480                         as_AccessMask = ( ace.AccessMask & accessMask );
2481
2482                         if ( ace is ObjectAce ) 
2483                         {
2484                             //
2485                             // determine what should be the object/inherited object types on the audit split
2486                             //
2487                             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 );
2488                         }
2489                     }
2490
2491                     //
2492                     // Finally, compute the merge split
2493                     //
2494
2495                     ms_AceFlags = ( ace.AceFlags & AceFlags.InheritanceFlags ) | ( flags & ace.AceFlags & AceFlags.AuditFlags );
2496                     ms_AccessMask = ( ace.AccessMask & accessMask );
2497
2498                    
2499                     //
2500                     // Now is the time to obtain the result of applying the remove
2501                     // operation to the merge split
2502                     // Skipping this step for SACLs where the merge split step
2503                     // produced no auditing flags
2504                     //
2505
2506                     if ( !saclSemantics ||
2507                         (( ms_AceFlags & AceFlags.AuditFlags ) != 0 ))
2508                     {         
2509                         if ( false == RemoveInheritanceBits( ms_AceFlags, flags, IsDS, out mergeResultFlags, out mergeRemoveTotal ))
2510                         {
2511                             removePossible = false;
2512                             break;
2513                         }
2514
2515                         if ( !mergeRemoveTotal )
2516                         {
2517                             mergeResultFlags |= ( ms_AceFlags & AceFlags.AuditFlags );
2518                             
2519                             if ( ace is ObjectAce ) 
2520                             {
2521                                 //
2522                                 // determine what should be the object/inherited object types on the merge split
2523                                 //
2524                                 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 );
2525                             }    
2526                         }
2527                     }
2528
2529                     //
2530                     // If this is no longer an evaluation, go ahead and make the changes
2531                     //
2532
2533                     if ( !evaluationPass )
2534                     {
2535                         QualifiedAce newAce;
2536
2537                         //
2538                         // Modify the existing ACE in-place if it has any access
2539                         // mask bits left, otherwise simply remove it
2540                         // However, if for an object ace we are removing the object type 
2541                         // then we should really remove this ace and add a new one since
2542                         // we would be changing the size of this ace
2543                         //
2544
2545                         if ( ps_AccessMask != 0 )
2546                         {
2547                             if (( ace is ObjectAce ) &&
2548                                 (((( ObjectAce) ace ).ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) != 0 ) &&
2549                                      (( ps_ObjectAceFlags & ObjectAceFlags.ObjectAceTypePresent ) == 0 ))
2550                             {
2551                                 ObjectAce newObjectAce;
2552
2553                                 _acl.RemoveAce(i);
2554                                 newObjectAce = new ObjectAce( ps_AceFlags, qualifier, ps_AccessMask, ace.SecurityIdentifier, ps_ObjectAceFlags, ps_ObjectAceType, ps_InheritedObjectAceType, false, null );
2555                                 _acl.InsertAce( i, newObjectAce );
2556                             }
2557                             else 
2558                             {
2559                                 ace.AceFlags = ps_AceFlags;
2560                                 ace.AccessMask = ps_AccessMask;
2561
2562                                 if ( ace is ObjectAce ) 
2563                                 {
2564                                     ObjectAce objectAce = ace as ObjectAce;
2565                                     
2566                                     objectAce.ObjectAceFlags = ps_ObjectAceFlags;
2567                                     objectAce.ObjectAceType = ps_ObjectAceType;
2568                                     objectAce.InheritedObjectAceType = ps_InheritedObjectAceType;
2569                                 }
2570                             }
2571                         }
2572                         else
2573                         {
2574                             _acl.RemoveAce(i);
2575                             i--; // keep the array index honest
2576                         }
2577
2578                         //
2579                         // On a SACL, the result of the auditing split must be recorded
2580                         //
2581
2582                         if ( saclSemantics && (( as_AceFlags & AceFlags.AuditFlags ) != 0 ))
2583                         {
2584                             if ( ace is CommonAce )
2585                             {
2586                                 newAce = new CommonAce( as_AceFlags, qualifier, as_AccessMask, ace.SecurityIdentifier, false, null );
2587                             }
2588                             else
2589                             {
2590                                 // object ace
2591                                 newAce = new ObjectAce( as_AceFlags, qualifier, as_AccessMask, ace.SecurityIdentifier, as_ObjectAceFlags, as_ObjectAceType, as_InheritedObjectAceType, false, null );
2592                             }
2593
2594                             i++; // so it's not considered again
2595                             _acl.InsertAce( i, newAce );
2596                         }
2597
2598                         //
2599                         // If there are interesting bits left over from a remove, store them
2600                         // as a separate ACE
2601                         //
2602
2603                         if ( !mergeRemoveTotal )
2604                         {
2605                             if ( ace is CommonAce )
2606                             {
2607                                 newAce = new CommonAce( mergeResultFlags, qualifier, ms_AccessMask, ace.SecurityIdentifier, false, null );
2608                             }
2609                             else
2610                             {
2611                                 // object ace
2612                                 newAce = new ObjectAce( mergeResultFlags, qualifier, ms_AccessMask, ace.SecurityIdentifier, ms_ObjectAceFlags, ms_ObjectAceType, ms_InheritedObjectAceType, false, null );
2613                             }
2614
2615                             i++; // so it's not considered again
2616                             _acl.InsertAce( i, newAce );
2617                         }
2618                     }
2619                 }
2620             }
2621             catch( OverflowException )
2622             {
2623                 //
2624                 // Oops, overflow means that the ACL became too big.
2625                 // Inform the caller that the remove was not possible.
2626                 //
2627
2628                 _acl.SetBinaryForm( recovery, 0 );
2629                 return false;
2630             }
2631
2632             //
2633             // Finished evaluating the possibility of a remove.
2634             // If it looks like it's doable, go ahead and do it.
2635             //
2636
2637             if ( evaluationPass && removePossible )
2638             {
2639                 evaluationPass = false;
2640                 goto MakeAnotherPass;
2641             }
2642
2643             OnAclModificationTried();
2644
2645             return removePossible;
2646         }
2647
2648         internal void RemoveQualifiedAcesSpecific( SecurityIdentifier sid, AceQualifier qualifier, int accessMask, AceFlags flags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
2649         {
2650             if ( accessMask == 0 )
2651             {
2652                 throw new ArgumentException(
2653                     Environment.GetResourceString( "Argument_ArgumentZero" ),
2654                     "accessMask" );
2655             }
2656
2657             if ( qualifier == AceQualifier.SystemAudit &&
2658                 (( flags & AceFlags.AuditFlags ) == 0 ))
2659             {
2660                 throw new ArgumentException(
2661                     Environment.GetResourceString( "Arg_EnumAtLeastOneFlag" ),
2662                     "flags" );
2663             }
2664         
2665             if ( sid == null )
2666             {
2667                 throw new ArgumentNullException( "sid" );
2668             }
2669             Contract.EndContractBlock();
2670             ThrowIfNotCanonical();
2671
2672             for ( int i = 0; i < Count; i++ )
2673             {
2674                 QualifiedAce ace = _acl[i] as QualifiedAce;
2675
2676                 //
2677                 // Not a qualified ACE - keep going
2678                 //
2679
2680                 if ( ace == null )
2681                 {
2682                     continue;
2683                 }
2684
2685                 //
2686                 // Only interested in explicit (non-inherited) ACEs
2687                 //
2688
2689                 if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
2690                 {
2691                     continue;
2692                 }
2693
2694                 //
2695                 // Only interested in ACEs with the specified qualifier
2696                 //
2697
2698                 if ( ace.AceQualifier != qualifier )
2699                 {
2700                     continue;
2701                 }
2702
2703                 //
2704                 // Only interested in ACEs with the specified SID
2705                 //
2706
2707                 if ( ace.SecurityIdentifier != sid )
2708                 {
2709                     continue;
2710                 }
2711
2712                 //
2713                 // Only interested in exact ACE flag matches
2714                 //
2715
2716                 if ( ace.AceFlags != flags )
2717                 {
2718                     continue;
2719                 }
2720
2721                 //
2722                 // Only interested in exact access mask matches
2723                 //
2724
2725                 if ( ace.AccessMask != accessMask )
2726                 {
2727                     continue;
2728                 }
2729
2730                 if ( IsDS ) 
2731                 {
2732                     //
2733                     // Incase of object aces, only interested in ACEs which match in their 
2734                     // objectType and inheritedObjectType
2735                     //
2736
2737                     if (( ace is ObjectAce ) && ( objectFlags != ObjectAceFlags.None ))
2738                     {                 
2739                         //
2740                         // both are object aces, so must match in object type and inherited object type
2741                         //
2742                         ObjectAce objectAce = ace as ObjectAce;
2743                         
2744                         if (( !objectAce.ObjectTypesMatch( objectFlags, objectType ))
2745                             || ( !objectAce.InheritedObjectTypesMatch( objectFlags, inheritedObjectType ))) 
2746                         {
2747                             continue;
2748                         }
2749                     }
2750                     else if (( ace is ObjectAce ) || ( objectFlags != ObjectAceFlags.None ))
2751                     {
2752                         // one is object ace and the other is not, so no match
2753                         continue;
2754                     }
2755                 }
2756
2757                 //
2758                 // Got our exact match; now remove it
2759                 //
2760
2761                 _acl.RemoveAce(i);
2762                 i--; // keep the array index honest
2763             }
2764             OnAclModificationTried();
2765         }
2766
2767         internal virtual void OnAclModificationTried()
2768         {
2769         }
2770         #endregion
2771
2772         #region Public Properties
2773
2774         //
2775         // Returns the revision of the ACL
2776         //
2777
2778         public sealed override byte Revision
2779         {
2780             get { return _acl.Revision; }
2781         }
2782
2783         //
2784         // Returns the number of ACEs in the ACL
2785         //
2786
2787         public sealed override int Count
2788         {
2789             get
2790             {
2791                 CanonicalizeIfNecessary();
2792                 return _acl.Count;
2793             }
2794         }
2795
2796         //
2797         // Returns the length of the binary representation of the ACL
2798         //
2799
2800         public sealed override int BinaryLength
2801         {
2802             get
2803             {
2804                 CanonicalizeIfNecessary();
2805                 return _acl.BinaryLength;
2806             }
2807         }
2808
2809         //
2810         // Returns 'true' if the ACL was canonical at creation time
2811         //
2812
2813         public bool IsCanonical
2814         {
2815             get { return _isCanonical; }
2816         }
2817
2818         public bool IsContainer
2819         {
2820             get { return _isContainer; }
2821         }
2822
2823         public bool IsDS
2824         {
2825             get { return _isDS; }
2826         }
2827
2828         #endregion
2829
2830         #region Public Methods
2831
2832         //
2833         // Returns the binary representation of the ACL
2834         //
2835
2836         public sealed override void GetBinaryForm( byte[] binaryForm, int offset )
2837         {
2838             CanonicalizeIfNecessary();
2839             _acl.GetBinaryForm( binaryForm, offset );
2840         }
2841
2842         //
2843         // Retrieves the ACE at a given index inside the ACL
2844         // Since the caller can modify the ACE it receives,
2845         // clone the ACE prior to returning it to the caller
2846         //
2847
2848         public sealed override GenericAce this[int index]
2849         {
2850             get
2851             {
2852                 CanonicalizeIfNecessary();
2853                 return _acl[index].Copy();
2854             }
2855
2856             set
2857             {
2858                 throw new NotSupportedException( Environment.GetResourceString( "NotSupported_SetMethod" ));
2859             }
2860         }
2861
2862         public void RemoveInheritedAces()
2863         {
2864             ThrowIfNotCanonical();
2865
2866             //
2867             // Iterating backwards as an optimization - all inherited ACEs
2868             // are usually in the back of the ACL
2869             //
2870
2871             for ( int i = _acl.Count - 1; i >= 0; i-- )
2872             {
2873                 GenericAce ace = _acl[i];
2874
2875                 if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
2876                 {
2877                     _acl.RemoveAce( i );
2878                 }
2879             }
2880             OnAclModificationTried();
2881         }
2882
2883         public void Purge( SecurityIdentifier sid )
2884         {
2885             if ( sid == null )
2886             {
2887                 throw new ArgumentNullException( "sid" );
2888             }
2889             Contract.EndContractBlock();
2890             ThrowIfNotCanonical();
2891             
2892             for ( int i = Count - 1; i >= 0; i-- )
2893             {
2894                 KnownAce ace = _acl[i] as KnownAce;
2895
2896                 //
2897                 // Skip over unknown ACEs
2898                 //
2899
2900                 if ( ace == null )
2901                 {
2902                     continue;
2903                 }
2904
2905                 //
2906                 // Skip over inherited ACEs
2907                 //
2908
2909                 if (( ace.AceFlags & AceFlags.Inherited ) != 0 )
2910                 {
2911                     continue;
2912                 }
2913
2914                 //
2915                 // SID matches - ACE is out
2916                 //
2917
2918                 if ( ace.SecurityIdentifier == sid )
2919                 {
2920                     _acl.RemoveAce( i );
2921                 }
2922             }
2923             OnAclModificationTried();
2924         }
2925
2926         #endregion
2927     }
2928
2929
2930     public sealed class SystemAcl : CommonAcl
2931     {
2932         #region Constructors
2933
2934         //
2935         // Creates an emtpy ACL
2936         //
2937
2938         public SystemAcl( bool isContainer, bool isDS, int capacity )
2939             : this( isContainer, isDS, isDS ? AclRevisionDS : AclRevision, capacity )
2940         {
2941         }
2942
2943         public SystemAcl( bool isContainer, bool isDS, byte revision, int capacity )
2944             : base( isContainer, isDS, revision, capacity )
2945         {
2946         }
2947
2948         //
2949         // Creates an ACL from a given raw ACL
2950         // after canonicalizing it
2951         //
2952
2953         public SystemAcl( bool isContainer, bool isDS, RawAcl rawAcl )
2954             : this( isContainer, isDS, rawAcl, false )
2955         {
2956         }
2957
2958         //
2959         // Internal version - if 'trusted' is true,
2960         // takes ownership of the given raw ACL
2961         //
2962
2963         internal SystemAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted )
2964             : base( isContainer, isDS, rawAcl, trusted, false )
2965         {
2966         }
2967
2968         #endregion
2969
2970         #region Public Methods
2971
2972         public void AddAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
2973         {
2974             CheckFlags( inheritanceFlags, propagationFlags );
2975             AddQualifiedAce( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
2976         }
2977
2978         public void SetAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
2979         {
2980             CheckFlags( inheritanceFlags, propagationFlags );
2981             SetQualifiedAce( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
2982         }
2983
2984         public bool RemoveAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
2985         {
2986             return RemoveQualifiedAces(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), true, ObjectAceFlags.None, Guid.Empty, Guid.Empty );
2987         }
2988
2989         public void RemoveAuditSpecific( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
2990         {
2991             RemoveQualifiedAcesSpecific( sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags( auditFlags ) | GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
2992         }
2993
2994         public void AddAudit(SecurityIdentifier sid, ObjectAuditRule rule)
2995         {
2996             AddAudit(rule.AuditFlags, sid, rule.AccessMask, rule.InheritanceFlags, rule.PropagationFlags, rule.ObjectFlags, rule.ObjectType, rule.InheritedObjectType);
2997         }
2998
2999         public void AddAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
3000         {
3001             //
3002             // This is valid only for DS Acls 
3003             //
3004             if ( !IsDS ) 
3005             {
3006                 throw new InvalidOperationException(
3007                     Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
3008             }
3009             Contract.EndContractBlock();
3010
3011             CheckFlags( inheritanceFlags, propagationFlags );
3012             AddQualifiedAce(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType);
3013         }
3014
3015         public void SetAudit(SecurityIdentifier sid, ObjectAuditRule rule)
3016         {
3017             SetAudit(rule.AuditFlags, sid, rule.AccessMask, rule.InheritanceFlags, rule.PropagationFlags, rule.ObjectFlags, rule.ObjectType, rule.InheritedObjectType);
3018         }
3019
3020         public void SetAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
3021         {
3022             //
3023             // This is valid only for DS Acls 
3024             //
3025             if ( !IsDS )
3026             {
3027                 throw new InvalidOperationException(
3028                     Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
3029             }
3030             Contract.EndContractBlock();
3031
3032             CheckFlags( inheritanceFlags, propagationFlags );
3033             SetQualifiedAce(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType);
3034         }
3035
3036         public bool RemoveAudit(SecurityIdentifier sid, ObjectAuditRule rule)
3037         {
3038             return RemoveAudit(rule.AuditFlags, sid, rule.AccessMask, rule.InheritanceFlags, rule.PropagationFlags, rule.ObjectFlags, rule.ObjectType, rule.InheritedObjectType);
3039         }
3040
3041         public bool RemoveAudit( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType ) 
3042         {
3043             //
3044             // This is valid only for DS Acls 
3045             //
3046             if ( !IsDS )
3047             {
3048                 throw new InvalidOperationException(
3049                     Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
3050             }
3051             Contract.EndContractBlock();
3052
3053             return RemoveQualifiedAces(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), true, objectFlags, objectType, inheritedObjectType);
3054         }
3055
3056         public void RemoveAuditSpecific(SecurityIdentifier sid, ObjectAuditRule rule)
3057         {
3058             RemoveAuditSpecific(rule.AuditFlags, sid, rule.AccessMask, rule.InheritanceFlags, rule.PropagationFlags, rule.ObjectFlags, rule.ObjectType, rule.InheritedObjectType);
3059         }
3060
3061         public void RemoveAuditSpecific( AuditFlags auditFlags, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
3062         {
3063             //
3064             // This is valid only for DS Acls 
3065             //
3066             if ( !IsDS )
3067             {
3068                 throw new InvalidOperationException(
3069                     Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
3070             }
3071             Contract.EndContractBlock();
3072
3073             RemoveQualifiedAcesSpecific(sid, AceQualifier.SystemAudit, accessMask, GenericAce.AceFlagsFromAuditFlags(auditFlags) | GenericAce.AceFlagsFromInheritanceFlags(inheritanceFlags, propagationFlags), objectFlags, objectType, inheritedObjectType);
3074         }
3075
3076         #endregion
3077     }
3078
3079
3080     public sealed class DiscretionaryAcl : CommonAcl
3081     {
3082         #region
3083         static private SecurityIdentifier _sidEveryone = new SecurityIdentifier( WellKnownSidType.WorldSid, null );
3084         private bool everyOneFullAccessForNullDacl = false;
3085         #endregion
3086
3087         #region Constructors
3088
3089         //
3090         // Creates an emtpy ACL
3091         //
3092
3093         public DiscretionaryAcl( bool isContainer, bool isDS, int capacity )
3094             : this( isContainer, isDS, isDS ? AclRevisionDS : AclRevision, capacity )
3095         {
3096         }
3097
3098         public DiscretionaryAcl( bool isContainer, bool isDS, byte revision, int capacity )
3099             : base( isContainer, isDS, revision, capacity )
3100         {
3101         }
3102
3103         //
3104         // Creates an ACL from a given raw ACL
3105         // after canonicalizing it
3106         //
3107
3108         public DiscretionaryAcl( bool isContainer, bool isDS, RawAcl rawAcl )
3109             : this( isContainer, isDS, rawAcl, false )
3110         {
3111         }
3112
3113         //
3114         // Internal version - if 'trusted' is true,
3115         // takes ownership of the given raw ACL
3116         //
3117
3118         internal DiscretionaryAcl( bool isContainer, bool isDS, RawAcl rawAcl, bool trusted )
3119             : base( isContainer, isDS, rawAcl == null ? new RawAcl( isDS ? AclRevisionDS : AclRevision, 0 ) : rawAcl, trusted, true )
3120         {
3121         }
3122
3123         #endregion
3124
3125         #region Public Methods
3126
3127         public void AddAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
3128         {
3129             CheckAccessType( accessType );
3130             CheckFlags( inheritanceFlags, propagationFlags );
3131             everyOneFullAccessForNullDacl = false;
3132             AddQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
3133         }
3134
3135         public void SetAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
3136         {
3137             CheckAccessType( accessType );
3138             CheckFlags( inheritanceFlags, propagationFlags );
3139             everyOneFullAccessForNullDacl = false;
3140             SetQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
3141         }
3142
3143         public bool RemoveAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
3144         {
3145             CheckAccessType( accessType );
3146             everyOneFullAccessForNullDacl = false;
3147             return RemoveQualifiedAces( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), false, ObjectAceFlags.None, Guid.Empty, Guid.Empty );
3148         }
3149
3150         public void RemoveAccessSpecific( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags )
3151         {
3152             CheckAccessType( accessType );
3153             everyOneFullAccessForNullDacl = false;
3154             RemoveQualifiedAcesSpecific(sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), ObjectAceFlags.None, Guid.Empty, Guid.Empty );
3155         }
3156
3157         public void AddAccess(AccessControlType accessType, SecurityIdentifier sid, ObjectAccessRule rule)
3158         {
3159             AddAccess(accessType, sid, rule.AccessMask, rule.InheritanceFlags, rule.PropagationFlags, rule.ObjectFlags, rule.ObjectType, rule.InheritedObjectType);
3160         }
3161
3162         public void AddAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
3163         {
3164             //
3165             // This is valid only for DS Acls 
3166             //
3167             if ( !IsDS )
3168             {
3169                 throw new InvalidOperationException(
3170                     Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
3171             }
3172             Contract.EndContractBlock();
3173
3174             CheckAccessType( accessType );
3175             CheckFlags( inheritanceFlags, propagationFlags );
3176             everyOneFullAccessForNullDacl = false;
3177             AddQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType );
3178         }
3179
3180         public void SetAccess(AccessControlType accessType, SecurityIdentifier sid, ObjectAccessRule rule)
3181         {
3182             SetAccess(accessType, sid, rule.AccessMask, rule.InheritanceFlags, rule.PropagationFlags, rule.ObjectFlags, rule.ObjectType, rule.InheritedObjectType);
3183         }
3184
3185         public void SetAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
3186         {
3187             //
3188             // This is valid only for DS Acls 
3189             //
3190             if ( !IsDS )
3191             {
3192                 throw new InvalidOperationException(
3193                     Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
3194             }
3195             Contract.EndContractBlock();
3196
3197             CheckAccessType( accessType );
3198             CheckFlags( inheritanceFlags, propagationFlags );
3199             everyOneFullAccessForNullDacl = false;
3200             SetQualifiedAce( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType);
3201         }
3202
3203         public bool RemoveAccess(AccessControlType accessType, SecurityIdentifier sid, ObjectAccessRule rule)
3204         {
3205             return RemoveAccess(accessType, sid, rule.AccessMask, rule.InheritanceFlags, rule.PropagationFlags, rule.ObjectFlags, rule.ObjectType, rule.InheritedObjectType);
3206         }
3207
3208         public bool RemoveAccess( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
3209         {
3210             //
3211             // This is valid only for DS Acls 
3212             //
3213             if ( !IsDS )
3214             {
3215                 throw new InvalidOperationException(
3216                     Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
3217             }
3218             Contract.EndContractBlock();
3219
3220             CheckAccessType( accessType );
3221             everyOneFullAccessForNullDacl = false;
3222             return RemoveQualifiedAces(sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), false, objectFlags, objectType, inheritedObjectType );
3223         }
3224
3225         public void RemoveAccessSpecific(AccessControlType accessType, SecurityIdentifier sid, ObjectAccessRule rule)
3226         {
3227             RemoveAccessSpecific(accessType, sid, rule.AccessMask, rule.InheritanceFlags, rule.PropagationFlags, rule.ObjectFlags, rule.ObjectType, rule.InheritedObjectType);
3228         }
3229
3230         public void RemoveAccessSpecific( AccessControlType accessType, SecurityIdentifier sid, int accessMask, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, ObjectAceFlags objectFlags, Guid objectType, Guid inheritedObjectType )
3231         {
3232             //
3233             // This is valid only for DS Acls 
3234             //
3235             if ( !IsDS )
3236             {
3237                 throw new InvalidOperationException(
3238                     Environment.GetResourceString( "InvalidOperation_OnlyValidForDS" ));
3239             }
3240             Contract.EndContractBlock();
3241
3242             CheckAccessType( accessType );
3243             everyOneFullAccessForNullDacl = false;
3244             RemoveQualifiedAcesSpecific( sid, accessType == AccessControlType.Allow ? AceQualifier.AccessAllowed : AceQualifier.AccessDenied, accessMask, GenericAce.AceFlagsFromInheritanceFlags( inheritanceFlags, propagationFlags ), objectFlags, objectType, inheritedObjectType );
3245         }
3246
3247         #endregion
3248
3249         #region internals and privates
3250
3251         //
3252         // DACL's "allow everyone full access may be created to replace a null DACL because managed 
3253         // access control does not want to leave null DACLs around. But we need to remember this MACL
3254         // created ACE when the DACL is modified, we can remove it to match the same native semantics of
3255         // a null DACL.
3256         //         
3257         internal bool EveryOneFullAccessForNullDacl
3258         {
3259             get { return everyOneFullAccessForNullDacl; }
3260             set { everyOneFullAccessForNullDacl = value; }
3261         }
3262
3263         //
3264         // As soon as you tried successfully to modified the ACL, the internally created allow every one full access ACL is materialized
3265         // because in native world, a NULL dacl can't be operated on.
3266         //
3267         internal override void OnAclModificationTried()
3268         {
3269             everyOneFullAccessForNullDacl = false;
3270         }
3271
3272         /// <summary>
3273         /// This static method will create an "allow everyone full control" single ACE DACL.
3274         /// </summary>
3275         /// <param name="isDS">whether it is a DS DACL</param>
3276         /// <param name="isContainer">whether it is a container</param>
3277         /// <returns>The single ACE DACL</returns>
3278         /// Note: This method is created to get the best behavior for using "allow everyone full access"
3279         /// single ACE DACL to replace null DACL from CommonSecurityObject. 
3280         static internal DiscretionaryAcl CreateAllowEveryoneFullAccess(bool isDS, bool isContainer)
3281         {
3282             DiscretionaryAcl dcl = new DiscretionaryAcl( isContainer, isDS, 1 );
3283             dcl.AddAccess(
3284                 AccessControlType.Allow,
3285                 _sidEveryone,
3286                 -1,
3287                 isContainer ? ( InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit ) : InheritanceFlags.None,
3288                 PropagationFlags.None );
3289
3290             dcl.everyOneFullAccessForNullDacl = true;
3291             return dcl;
3292         }
3293         #endregion
3294     }
3295 }