public override void SaveDirectoryObject(DirectoryObject directoryObject)
 {
     if (directoryObject == null)
     {
         throw new ArgumentNullException("directoryObject");
     }
     using (DirectoryEntry directoryEntry = GetDirectoryEntry()) {
         string filter = string.Format(CultureInfo.InvariantCulture, FilterAndFormat, BaseFilter + string.Format(CultureInfo.InvariantCulture, FilterFormat, this.IdentifyingPropertyName, directoryObject.Id));
         using (DirectorySearcher directorySearcher = new DirectorySearcher(
                    directoryEntry,
                    filter,
                    PropertyNames,
                    SearchScope.Subtree)) {
             using (DirectoryEntry directoryEntryWrite = directorySearcher.FindOne().GetDirectoryEntry()) {
                 bool commitChanges = false;
                 foreach (string propertyName in this.PropertyNames)
                 {
                     PropertyValueCollection pvc = directoryEntryWrite.Properties[propertyName];
                     string newValue             = directoryObject[propertyName];
                     if (pvc.Value != null)
                     {
                         if (!pvc.Value.ToString().Equals(newValue))
                         {
                             if (!string.IsNullOrEmpty(newValue))
                             {
                                 pvc.Value = newValue;
                             }
                             else
                             {
                                 pvc.RemoveAt(0);
                             }
                             commitChanges = true;
                         }
                     }
                     else if (!string.IsNullOrEmpty(newValue))
                     {
                         pvc.Add(newValue);
                         commitChanges = true;
                     }
                 }
                 if (commitChanges)
                 {
                     directoryEntryWrite.CommitChanges();
                 }
             }
         }
     }
 }
        /// <summary>
        /// Method validates the requirements under LDSCrossRefContainer Scenario.
        /// </summary>
        public void ValidateLDSCrossRefContainer()
        {
            DirectoryEntry dirPartitions = new DirectoryEntry();
            DirectoryEntry domainEntry   = new DirectoryEntry();
            DirectoryEntry childEntry    = new DirectoryEntry();
            DirectoryEntry requiredEntry = new DirectoryEntry();
            string         systemFlag;
            int            systemFlagVal;

            //Variables for holding the paths for NCs.
            if (!adAdapter.GetLdsObjectByDN("CN=Partitions,CN=Configuration," + adAdapter.LDSRootObjectName, out dirPartitions))
            {
                DataSchemaSite.Assert.IsTrue(
                    false,
                    "CN=Partitions,CN=Configuration,"
                    + adAdapter.LDSRootObjectName
                    + "Object is not found in server");
            }
            string parentAttribute = dirPartitions.Parent.Name.ToString();

            //MS-ADTS-Schema_R402
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                "CN=Configuration",
                parentAttribute,
                402,
                "The Parent of the Cross-Ref-Container Container must be Config NC root.");

            //MS-ADTS-Schema_R403
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                "Partitions",
                dirPartitions.Properties["name"].Value.ToString(),
                403,
                "The name attribute of the Cross-Ref-Container Container must be Partitions.");

            PropertyValueCollection objectClass = dirPartitions.Properties["objectClass"];

            //MS-ADTS-Schema_R404
            DataSchemaSite.CaptureRequirementIfIsTrue(
                objectClass.Contains((object)"crossRefContainer"),
                404,
                "The objectClass attribute of the Cross-Ref-Container Container must be crossRefContainer.");

            //MS-ADTS-Schema_R406
            systemFlag    = dirPartitions.Properties["systemFlags"].Value.ToString();
            systemFlagVal = ParseSystemFlagsValue("FLAG_DISALLOW_DELETE");

            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                systemFlagVal.ToString(),
                systemFlag,
                406,
                "The systemFlags attribute of the Cross-Ref-Container Container must be FLAG_DISALLOW_DELETE.");

            bool             isCrossRef            = true;
            bool             isObjectClassCrossRef = true;
            DirectoryEntries Childs = dirPartitions.Children;

            foreach (DirectoryEntry child in Childs)
            {
                if (!child.Parent.Name.Equals("CN=Partitions"))
                {
                    isCrossRef = false;
                }
                PropertyValueCollection objClass = child.Properties["objectClass"];
                objClass.RemoveAt(0);
                if (objClass.Count != 1 || !objClass.Contains((object)"crossRef"))
                {
                    isObjectClassCrossRef = false;
                }
            }

            //MS-ADTS-Schema_R408
            DataSchemaSite.CaptureRequirementIfIsTrue(
                isCrossRef,
                408,
                "The parent of the Cross-Ref Objects must be crossRefContainer object.");

            //MS-ADTS-Schema_R409
            DataSchemaSite.CaptureRequirementIfIsTrue(
                isObjectClassCrossRef,
                409,
                "The objectClass attribute of the Cross-Ref Objects must be crossRef.");

            childEntry = dirPartitions.Children.Find("CN=Enterprise Configuration");
            //MS-ADTS-Schema_R410
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                "CN=Configuration," + adAdapter.LDSRootObjectName,
                childEntry.Properties["nCName"].Value.ToString(),
                410,
                "The nCName attribute of the Configuration crossRef Object must equal to the config NC root.");

            //MS-ADTS-Schema_R412
            DataSchemaSite.CaptureRequirementIfIsFalse(
                childEntry.Properties.Contains("dnsRoot"),
                412,
                "In AD/LDS the dnsroot attribute is not presented for the Configuration crossRef Object. ");

            childEntry = dirPartitions.Children.Find("CN=Enterprise Schema");
            //MS-ADTS-Schema_R413
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                "CN=Schema,CN=Configuration," + adAdapter.LDSRootObjectName,
                childEntry.Properties["nCName"].Value.ToString(),
                413,
                "The nCName attribute of the Schema crossRef Object must equal to the Schema NC root.");

            //MS-ADTS-Schema_R415
            DataSchemaSite.CaptureRequirementIfIsFalse(
                childEntry.Properties.Contains("dnsRoot"),
                415,
                "In AD/LDS the dnsroot attribute is not presented for the Schema crossRef Object.");

            childEntry = dirPartitions.Children.Find("CN=Enterprise Configuration");
            //MS-ADTS-Schema_R421
            DataSchemaSite.CaptureRequirementIfIsFalse(
                childEntry.Properties.Contains("dnsRoot"),
                421,
                "In AD/LDS the dnsroot attribute is not presented for Application NC crossRef Object.");

            //MS-ADTS-Schema_R852
            childEntry = dirPartitions.Children.Find("CN=Enterprise Schema");
            if (!adAdapter.GetLdsObjectByDN("CN=Schema,CN=Configuration," + adAdapter.LDSRootObjectName,
                                            out dirPartitions))
            {
                DataSchemaSite.Assert.IsTrue(
                    false,
                    "CN=Schema,CN=Configuration,"
                    + adAdapter.LDSRootObjectName
                    + " Object is not found in server");
            }

            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                childEntry.Properties["nCName"].Value.ToString(),
                dirPartitions.Properties["distinguishedName"].Value.ToString(),
                852,
                "The nCName attribute of the crossRef object must equal the dsname of the NC root object.");
        }
        /// <summary>
        /// Method validates the requirements under CrossRefContainer Scenario.
        /// </summary>
        public void ValidateCrossRefContainer()
        {
            //Variables required for Directory Entries.
            DirectoryEntry dirPartitions = new DirectoryEntry();
            DirectoryEntry domainEntry   = new DirectoryEntry();
            DirectoryEntry childEntry    = new DirectoryEntry();

            if (!Utilities.IsObjectExist(adAdapter.PartitionPath + "," + adAdapter.rootDomainDN, adAdapter.PDCNetbiosName,
                                         adAdapter.ADDSPortNum, adAdapter.DomainAdministratorName, adAdapter.DomainUserPassword))
            {
                //To create the Application NC in the Active Directory.
                AdLdapClient.Instance().ConnectAndBind(adAdapter.PDCNetbiosName,
                                                       adAdapter.PDCIPAddr, Convert.ToInt32(adAdapter.ADDSPortNum), adAdapter.DomainAdministratorName,
                                                       adAdapter.DomainUserPassword, adAdapter.PrimaryDomainDnsName,
                                                       AuthType.Basic | AuthType.Kerberos);
                List <DirectoryAttribute> attrs = new List <DirectoryAttribute>();
                attrs.Add(new DirectoryAttribute("instancetype:5"));
                attrs.Add(new DirectoryAttribute("objectclass:domainDNS"));
                AdLdapClient.Instance().AddObject(adAdapter.PartitionPath + "," + adAdapter.rootDomainDN, attrs, null);
                AdLdapClient.Instance().Unbind();
            }
            string configNC = "CN=Configuration," + adAdapter.rootDomainDN;
            string SchemaNC = "CN=Schema," + configNC;
            //Returns Fully Qualified DNS Name for the Current Domain.
            string strReturn = adAdapter.PrimaryDomainDnsName;

            if (!adAdapter.GetObjectByDN("CN=Partitions," + configNC, out dirPartitions))
            {
                DataSchemaSite.Assume.IsTrue(false, "CN=Partitions," + configNC + " Object is not found in server");
            }
            string parent = dirPartitions.Parent.Name, systemFlag;
            bool   isPresent = false;

            int systemFlagVal;

            //MS-ADTS-Schema_R402
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                "CN=Configuration",
                parent,
                402,
                "The Parent of the Cross-Ref-Container Container must be Config NC root.");

            //MS-ADTS-Schema_R403
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                "Partitions",
                dirPartitions.Properties["name"].Value.ToString(),
                403,
                @"The name attribute of the Cross-Ref-Container Container must be Partitions.");

            //MS-ADTS-Schema_R404
            PropertyValueCollection objectClass = dirPartitions.Properties["objectClass"];

            DataSchemaSite.CaptureRequirementIfIsTrue(
                objectClass.Contains((object)"crossRefContainer"),
                404,
                "The objectClass attribute of the Cross-Ref-Container Container must be crossRefContainer.");
            string fsmoRoleOwner = dirPartitions.Properties["fSMORoleOwner"].Value.ToString();

            //MS-ADTS-Schema_R406
            systemFlag    = dirPartitions.Properties["systemFlags"].Value.ToString();
            systemFlagVal = ParseSystemFlagsValue("FLAG_DISALLOW_DELETE");

            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                systemFlagVal.ToString(),
                systemFlag,
                406,
                "The systemFlags attribute of the Cross-Ref-Container Container must be FLAG_DISALLOW_DELETE.");

            //MS-ADTS-Schema_R405
            if (!adAdapter.GetObjectByDN(adAdapter.rootDomainDN, out domainEntry))
            {
                DataSchemaSite.Assume.IsTrue(false, adAdapter.rootDomainDN + " Object is not found in server");
            }
            string domainFSMO = domainEntry.Properties["fSMORoleOwner"].Value.ToString();

            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                fsmoRoleOwner,
                domainFSMO,
                405,
                "The fSMORoleOwner attribute of the Cross-Ref-Container Container must references the Domain "
                + "Naming Master FSMO role owner.");

            //MS-ADTS-Schema_R408
            //Query the Partitions for CrossRef container get the childrens and validate the requirments as such.
            bool             isCrossRef            = true;
            bool             isObjectClassCrossRef = true;
            DirectoryEntries Childs = dirPartitions.Children;

            foreach (DirectoryEntry child in Childs)
            {
                if (!child.Parent.Name.Equals("CN=Partitions"))
                {
                    isCrossRef = false;
                }
                PropertyValueCollection objClass = child.Properties["objectClass"];
                objClass.RemoveAt(0);
                if (objClass.Count != 1 || !objClass.Contains((object)"crossRef"))
                {
                    isObjectClassCrossRef = false;
                }
                if (dirPartitions.Parent.Name.ToString().Equals("CN=Configuration"))
                {
                    isPresent = true;
                }
            }
            //Validate the parent of the crossref objects,objectClass,nCName and
            //dnsRoot for all childs and crossRef container in the configNC.
            DataSchemaSite.CaptureRequirementIfIsTrue(
                isCrossRef,
                408,
                "The parent of the Cross-Ref Objects must be crossRefContainer object.");

            //MS-ADTS-Schema_R851
            DataSchemaSite.CaptureRequirementIfIsTrue(
                isPresent & isCrossRef,
                851,
                "For any NC in the forest crossRef,NC root objects must be exist.");

            // MS-ADTS-Schema_R409
            DataSchemaSite.CaptureRequirementIfIsTrue(
                isObjectClassCrossRef,
                409,
                "The objectClass attribute of the Cross-Ref Objects must be crossRef.");

            //This is the crossRef container or crossRefObject
            //MS-ADTS-Schema_R410
            childEntry = dirPartitions.Children.Find("CN=Enterprise Configuration");
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                configNC.ToLower(),
                childEntry.Properties["nCName"].Value.ToString().ToLower(),
                410,
                "The nCName attribute of the Configuration crossRef Object must equal to the config NC root.");

            //MS-ADTS-Schema_R411
            string dnsRoot = childEntry.Properties["dnsRoot"].Value.ToString().ToLower();

            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                strReturn.ToLower(),
                dnsRoot.ToLower(),
                411,
                "In AD/DS the dnsroot attribute of the Configuration crossRef Object must be the forest "
                + "root's fully qualified DNS name.");

            //This is the crossRef child or crossRefObject
            //MS-ADTS-Schema_R413
            childEntry = dirPartitions.Children.Find("CN=Enterprise Schema");
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                SchemaNC.ToLower(),
                childEntry.Properties["nCName"].Value.ToString().ToLower(),
                413,
                "The nCName attribute of the Schema crossRef Object must equal to the Schema NC root.");

            //MS-ADTS-Schema_R414
            dnsRoot = childEntry.Properties["dnsRoot"].Value.ToString().ToLower();
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                strReturn.ToLower(),
                dnsRoot.ToLower(),
                414,
                "In AD/DS the dnsroot attribute of the Schema crossRef Object must be the forest "
                + "root's fully qualified DNS name.");

            //MS-ADTS-Schema_R852
            if (!adAdapter.GetObjectByDN(SchemaNC, out dirPartitions))
            {
                DataSchemaSite.Assume.IsTrue(false, SchemaNC + " Object is not found in server");
            }
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                childEntry.Properties["nCName"].Value.ToString(),
                dirPartitions.Properties["distinguishedName"].Value.ToString(),
                852,
                "The nCName attribute of the crossRef object must equal the dsname of the NC root object.");

            if (!adAdapter.GetObjectByDN("CN=Partitions," + configNC, out dirPartitions))
            {
                DataSchemaSite.Assume.IsTrue(false, "CN=Partitions," + configNC + " Object is not found in server");
            }
            foreach (DirectoryEntry partitionEntry in dirPartitions.Children)
            {
                if (partitionEntry.Properties["objectCategory"].Value.ToString().ToLower().Contains("cn=cross-ref"))
                {
                    if (partitionEntry.Properties["nCName"].Value.ToString().Contains(adAdapter.PartitionPath))
                    {
                        partitionEntry.RefreshCache(new string[] { "msDS-SDReferenceDomain" });
                        if (partitionEntry.Properties.Contains("msDS-SDReferenceDomain") && partitionEntry.Properties["msDS-SDReferenceDomain"].Value != null)
                        {
                            //MS-ADTS-Schema_R422
                            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                                adAdapter.rootDomainDN.ToLower(),
                                partitionEntry.Properties["msDS-SDReferenceDomain"].Value.ToString().ToLower(),
                                422,
                                "In AD/DS msDS-SDReferenceDomain attribute of the Application NC crossRef object,"
                                + "references an NC root object for a domain. All security descriptors in this application NC "
                                + "must use the NC represented as the reference domain for resolution.");
                        }
                        else
                        {
                            DataSchemaSite.Log.Add(LogEntryKind.Warning, "The value of msDS-SDReferenceDomain attribute of the Application NC crossRef object is null");
                        }
                    }
                    if (partitionEntry.Properties["nCName"].Value.ToString().Equals(adAdapter.rootDomainDN))
                    {
                        //MS-ADTS-Schema_R416
                        DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                            partitionEntry.Properties["name"].Value.ToString(),
                            partitionEntry.Properties["nETBIOSName"].Value.ToString(),
                            416,
                            "The name attribute of the Domain crossRef Object must be the Netbios name of the domain.");

                        //MS-ADTS-Schema_R417
                        DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                            adAdapter.rootDomainDN,
                            partitionEntry.Properties["nCName"].Value.ToString(),
                            417,
                            "The nCName attribute of the Domain crossRef Object must be reference to the Domain NC root.");

                        //MS-ADTS-Schema_R418
                        if (!adAdapter.GetObjectByDN(adAdapter.rootDomainDN, out domainEntry))
                        {
                            DataSchemaSite.Assume.IsTrue(false, adAdapter.rootDomainDN + " Object is not found in server");
                        }
                        DirectoryEntry domainChildEntry = new DirectoryEntry();

                        DataSchemaSite.CaptureRequirementIfIsTrue(
                            adAdapter.rootDomainDN.ToLower().Contains(partitionEntry.Properties["nETBIOSName"].Value.ToString().ToLower()),
                            418,
                            "The nETBIOSName attribute of the Domain crossRef Object must be the Netbios name of the domain.");

                        //MS-ADTS-Schema trustParent
                        DataSchemaSite.Assert.IsNull(
                            partitionEntry.Properties["trustParent"].Value,
                            "The trustParent attribute is not present on the root domain NC's crossRef object.");

                        //MS-ADTS-Schema_R419
                        systemFlag    = partitionEntry.Properties["systemFlags"].Value.ToString();
                        systemFlagVal = ParseSystemFlagsValue("FLAG_ATTR_NOT_REPLICATED|FLAG_ATTR_REQ_PARTIAL_SET_MEMBER");

                        DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                            systemFlagVal.ToString(),
                            systemFlag,
                            419,
                            @"The systemFlags attribute of the Domain crossRef Object must be FLAG_CR_NTDS_NC | FLAG_CR_NTDS_DOMAIN.");
                    }
                    if (partitionEntry.Properties["nCName"].Value.ToString().Equals(adAdapter.childDomainDN))
                    {
                        //MS-ADTS-Schema_R416
                        DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                            partitionEntry.Properties["name"].Value.ToString(),
                            partitionEntry.Properties["nETBIOSName"].Value.ToString(),
                            416,
                            "The name attribute of the Domain crossRef Object must be the Netbios name of the domain.");

                        //MS-ADTS-Schema_R417
                        DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                            adAdapter.childDomainDN,
                            partitionEntry.Properties["nCName"].Value.ToString(),
                            417,
                            "The nCName attribute of the Domain crossRef Object must be reference to the Domain NC root.");

                        //MS-ADTS-Schema_R418
                        if (!adAdapter.GetObjectByDN(adAdapter.childDomainDN, out domainEntry))
                        {
                            DataSchemaSite.Assume.IsTrue(false, adAdapter.childDomainDN + " Object is not found in server");
                        }
                        DirectoryEntry domainChildEntry = new DirectoryEntry();

                        DataSchemaSite.CaptureRequirementIfIsTrue(
                            adAdapter.childDomainDN.ToLower().Contains(partitionEntry.Properties["nETBIOSName"].Value.ToString().ToLower()),
                            418,
                            "The nETBIOSName attribute of the Domain crossRef Object must be the Netbios name of the domain.");

                        //MS-ADTS-Schema trustParent
                        DirectoryEntry parentEntry   = new DirectoryEntry();
                        string         netbiosDomain = adAdapter.PrimaryDomainNetBiosName;
                        parentEntry = dirPartitions.Children.Find(string.Format("CN={0}", netbiosDomain));
                        DataSchemaSite.Assert.AreEqual <string>(
                            parentEntry.Properties["distinguishedName"].Value.ToString(),
                            partitionEntry.Properties["trustParent"].Value.ToString(),
                            "For child NCs, the trustParent attribute value references the parent NC's crossRef object.");

                        //MS-ADTS-Schema_R419
                        systemFlag    = partitionEntry.Properties["systemFlags"].Value.ToString();
                        systemFlagVal = ParseSystemFlagsValue("FLAG_ATTR_NOT_REPLICATED|FLAG_ATTR_REQ_PARTIAL_SET_MEMBER");

                        DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                            systemFlagVal.ToString(),
                            systemFlag,
                            419,
                            @"The systemFlags attribute of the Domain crossRef Object must be FLAG_CR_NTDS_NC | FLAG_CR_NTDS_DOMAIN.");
                    }
                }
            }
            //MS-ADTS-Schema_R420
            dnsRoot = childEntry.Properties["dnsRoot"].Value.ToString().ToLower();
            DataSchemaSite.CaptureRequirementIfAreEqual <string>(
                strReturn.ToLower(),
                dnsRoot.ToLower(),
                420,
                "In AD/DS the the value for dnsRoot for an application NC crossRef is derived by syntactically "
                + "converting the DN portion of the crossRef's nCName into a fully qualified DNS name.");
        }