private void CheckBinaryConstructor (string expectedSddl, byte[] binary)
		{
			RawSecurityDescriptor sd = new RawSecurityDescriptor (binary, 0);
			
			Assert.AreEqual (sd.BinaryLength, binary.Length);
			Assert.AreEqual (expectedSddl, sd.GetSddlForm (AccessControlSections.All));
		}
		private void CheckRoundTrip (string sddl)
		{
			RawSecurityDescriptor sd = new RawSecurityDescriptor (sddl);
			
			byte[] buffer = new byte[sd.BinaryLength];
			sd.GetBinaryForm (buffer, 0);
			
			sd = new RawSecurityDescriptor (buffer, 0);
			Assert.AreEqual (sddl, sd.GetSddlForm (AccessControlSections.All));
		}
        private static void CanonicalizeDacl(NativeObjectSecurity objectSecurity)
        {
            if (objectSecurity == null) { throw new ArgumentNullException("objectSecurity"); }
            if (objectSecurity.AreAccessRulesCanonical) { return; }

            // A canonical ACL must have ACES sorted according to the following order:
            // 1. Access-denied on the object
            // 2. Access-denied on a child or property
            // 3. Access-allowed on the object
            // 4. Access-allowed on a child or property
            // 5. All inherited ACEs
            RawSecurityDescriptor descriptor = new RawSecurityDescriptor(objectSecurity.GetSecurityDescriptorSddlForm(AccessControlSections.Access));

            List<CommonAce> implicitDenyDacl = new List<CommonAce>();
            List<CommonAce> implicitDenyObjectDacl = new List<CommonAce>();
            List<CommonAce> inheritedDacl = new List<CommonAce>();
            List<CommonAce> implicitAllowDacl = new List<CommonAce>();
            List<CommonAce> implicitAllowObjectDacl = new List<CommonAce>();

            foreach (CommonAce ace in descriptor.DiscretionaryAcl)
            {
                if ((ace.AceFlags & AceFlags.Inherited) == AceFlags.Inherited) { inheritedDacl.Add(ace); }
                else
                {
                    switch (ace.AceType)
                    {
                        case AceType.AccessAllowed:
                            implicitAllowDacl.Add(ace);
                            break;

                        case AceType.AccessDenied:
                            implicitDenyDacl.Add(ace);
                            break;

                        case AceType.AccessAllowedObject:
                            implicitAllowObjectDacl.Add(ace);
                            break;

                        case AceType.AccessDeniedObject:
                            implicitDenyObjectDacl.Add(ace);
                            break;
                    }
                }
            }

            Int32 aceIndex = 0;
            RawAcl newDacl = new RawAcl(descriptor.DiscretionaryAcl.Revision, descriptor.DiscretionaryAcl.Count);
            implicitDenyDacl.ForEach(x => newDacl.InsertAce(aceIndex++, x));
            implicitDenyObjectDacl.ForEach(x => newDacl.InsertAce(aceIndex++, x));
            implicitAllowDacl.ForEach(x => newDacl.InsertAce(aceIndex++, x));
            implicitAllowObjectDacl.ForEach(x => newDacl.InsertAce(aceIndex++, x));
            inheritedDacl.ForEach(x => newDacl.InsertAce(aceIndex++, x));

            if (aceIndex != descriptor.DiscretionaryAcl.Count)
            {
                System.Diagnostics.Debug.Fail("The DACL cannot be canonicalized since it would potentially result in a loss of information");
                return;
            }

            descriptor.DiscretionaryAcl = newDacl;
            objectSecurity.SetSecurityDescriptorSddlForm(descriptor.GetSddlForm(AccessControlSections.Access), AccessControlSections.Access);
        }
		public void GetSddlForm ()
		{
			RawSecurityDescriptor sd = new RawSecurityDescriptor ("");
			Assert.AreEqual ("", sd.GetSddlForm (AccessControlSections.All));
			
			// Ask for part of SD that isn't represented
			sd.Owner = new SecurityIdentifier (WellKnownSidType.BuiltinUsersSid, null);
			sd.Group = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
			Assert.AreEqual ("", sd.GetSddlForm (AccessControlSections.Access));
			
			// Empty ACL form
			sd.DiscretionaryAcl = new RawAcl (2, 0);
			sd.SystemAcl = new RawAcl (1, 0);
			sd.SetFlags (sd.ControlFlags | ControlFlags.DiscretionaryAclPresent | ControlFlags.SystemAclPresent);
			Assert.AreEqual ("O:BUG:BAD:S:", sd.GetSddlForm (AccessControlSections.All));
			
			// Add an ACE to the DACL
			SecurityIdentifier builtInAdmins = new SecurityIdentifier (WellKnownSidType.BuiltinAdministratorsSid, null);
			CommonAce ace = new CommonAce (AceFlags.None, AceQualifier.AccessAllowed, 0x7FFFFFFF, builtInAdmins, false, null);
			sd.DiscretionaryAcl.InsertAce (0, ace);
			Assert.AreEqual ("O:BUG:BAD:(A;;0x7fffffff;;;BA)S:", sd.GetSddlForm (AccessControlSections.All));
			
			// Add second ACE to the DACL
			SecurityIdentifier randomUser = new SecurityIdentifier ("S-1-5-21-324-23423-234-334");
			ace = new CommonAce (AceFlags.Inherited | AceFlags.ContainerInherit, AceQualifier.AccessDenied, 0x12345678, randomUser, true, null);
			sd.DiscretionaryAcl.InsertAce (0, ace);
			Assert.AreEqual ("O:BUD:(XD;CIID;0x12345678;;;S-1-5-21-324-23423-234-334)(A;;0x7fffffff;;;BA)", sd.GetSddlForm (AccessControlSections.Owner | AccessControlSections.Access));
			
			// DACL & SACL flags
			sd.SetFlags (sd.ControlFlags | ControlFlags.DiscretionaryAclProtected | ControlFlags.DiscretionaryAclAutoInherited | ControlFlags.DiscretionaryAclAutoInheritRequired | ControlFlags.SystemAclAutoInherited);
			sd.DiscretionaryAcl = new RawAcl (1, 0);
			ace = new CommonAce (AceFlags.None, AceQualifier.AccessAllowed, 0x7FFFFFFF, builtInAdmins, false, null);
			sd.DiscretionaryAcl.InsertAce (0, ace);
			Assert.AreEqual ("O:BUG:BAD:PARAI(A;;0x7fffffff;;;BA)S:AI", sd.GetSddlForm (AccessControlSections.All));
			
			sd.SetFlags (sd.ControlFlags | ControlFlags.ServerSecurity | ControlFlags.DiscretionaryAclDefaulted);
			Assert.AreEqual ("O:BUG:BAD:PARAI(A;;0x7fffffff;;;BA)S:AI", sd.GetSddlForm (AccessControlSections.All));
		}
        /// <summary>
        /// Convert _SECURITY_DESCRIPTOR to SDDL string.
        /// </summary>
        /// <param name="securityDescriptor">_SECURITY_DESCRIPTOR to convert.</param>
        /// <returns>SDDL string.</returns>
        public static string ToSddlString(_SECURITY_DESCRIPTOR securityDescriptor)
        {
            byte[] securityDescriptorBytes = DtypUtility.EncodeSecurityDescriptor(securityDescriptor);
            RawSecurityDescriptor rawSecurityDescriptor = new RawSecurityDescriptor(securityDescriptorBytes, 0);

            return rawSecurityDescriptor.GetSddlForm(AccessControlSections.All);
        }