StrictReadToNextElement() private method

private StrictReadToNextElement ( ExceptionAction action ) : void
action ExceptionAction
return void
        // Scans the <configSections> section of a configuration file.  The function is recursive
        // to traverse arbitrarily nested config groups.
        //
        //     <sectionGroup name="foo">
        //         <sectionGroup name="bar">
        //             <section name="fooBarSection" type="..." />
        //     ...
        //
        // Note: This function valiates that the factory record has not been
        //       declared before in a parent record. (it does not check
        //       current record, which allows you to update list)
        //
        private void ScanFactoriesRecursive(XmlUtil xmlUtil, string parentConfigKey, Hashtable factoryList) {

            // discard any accumulated local errors
            xmlUtil.SchemaErrors.ResetLocalErrors();

            int depth = xmlUtil.Reader.Depth;
            xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);

            while (xmlUtil.Reader.Depth == depth + 1) {
                bool    positionedAtNextElement = false;
                
                switch (xmlUtil.Reader.Name) {
                    //
                    // Handle <sectionGroup name="groupName" [type="typename"] />
                    //
                    case KEYWORD_SECTIONGROUP: {
                        string tagName = null;
                        string typeName = null;

                        int lineNumber = xmlUtil.Reader.LineNumber;
                        while (xmlUtil.Reader.MoveToNextAttribute()) {
                            switch (xmlUtil.Reader.Name) {
                                case KEYWORD_SECTIONGROUP_NAME:
                                    tagName = xmlUtil.Reader.Value;
                                    VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false);
                                    break;

                                case KEYWORD_SECTIONGROUP_TYPE:
                                    xmlUtil.VerifyAndGetNonEmptyStringAttribute(ExceptionAction.Local, out typeName);
                                    break;

                                default:
                                    xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.Local);
                                    break;
                            }
                        }
                        xmlUtil.Reader.MoveToElement(); // if on an attribute move back to the element

                        if (!xmlUtil.VerifyRequiredAttribute(
                                tagName, 
                                KEYWORD_SECTIONGROUP_NAME,
                                ExceptionAction.NonSpecific)) {
                                        
                            //
                            // Without a name, we cannot continue parsing the sections and groups within.
                            // Skip the entire section.
                            //
                            xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true);
                            xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                        }
                        else {
                            string configKey = CombineConfigKey(parentConfigKey, tagName);

                            FactoryRecord factoryRecord = (FactoryRecord) factoryList[configKey];
                            if (factoryRecord != null) {
                                // Error: duplicate sectionGroup declaration
                                xmlUtil.SchemaErrors.AddError(
                                        new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined_at_this_level, tagName), xmlUtil),
                                        ExceptionAction.Local);

                            } else {
                                FactoryRecord parentFactoryRecord = _parent.FindFactoryRecord(configKey, true);
                                if (parentFactoryRecord != null) {
                                    configKey = parentFactoryRecord.ConfigKey;


                                    // make sure that an ancestor has not defined a section with the same name as the group
                                    if (    !parentFactoryRecord.IsGroup              ||
                                            !parentFactoryRecord.IsEquivalentSectionGroupFactory(Host, typeName)) {
                                         
                                        xmlUtil.SchemaErrors.AddError(
                                                new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined, tagName), xmlUtil),
                                                ExceptionAction.Local);

                                        parentFactoryRecord = null;
                                    }
                                }

                                if (parentFactoryRecord != null) {
                                    factoryRecord = parentFactoryRecord.CloneSectionGroup(typeName, xmlUtil.Filename, lineNumber);
                                }
                                else {
                                    factoryRecord = new FactoryRecord(configKey, parentConfigKey, tagName, typeName, xmlUtil.Filename, lineNumber);
                                }

                                factoryList[configKey] = factoryRecord;
                            }

                            // Add any errors we may have encountered
                            factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true));

                            // continue recursive scan
                            ScanFactoriesRecursive(xmlUtil, configKey, factoryList);
                        }

                        continue;
                    }

                    case KEYWORD_SECTION: {
                        string tagName = null;
                        string typeName = null;
                        ConfigurationAllowDefinition    allowDefinition = ConfigurationAllowDefinition.Everywhere;
                        ConfigurationAllowExeDefinition allowExeDefinition = ConfigurationAllowExeDefinition.MachineToApplication;
                        bool allowLocation = true;
                        bool restartOnExternalChanges = true;
                        bool requirePermission = true;
                        bool gotType = false;

                        // parse section attributes
                        int lineNumber = xmlUtil.Reader.LineNumber;
                        while (xmlUtil.Reader.MoveToNextAttribute()) {
                            switch (xmlUtil.Reader.Name) {
                                case KEYWORD_SECTION_NAME:
                                    tagName = xmlUtil.Reader.Value;
                                    VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false);
                                    break;

                                case KEYWORD_SECTION_TYPE:
                                    xmlUtil.VerifyAndGetNonEmptyStringAttribute(ExceptionAction.Local, out typeName);
                                    gotType = true;
                                    break;

                                case KEYWORD_SECTION_ALLOWLOCATION:
                                    xmlUtil.VerifyAndGetBooleanAttribute(
                                            ExceptionAction.Local, true, out allowLocation);
                                    break;

                                case KEYWORD_SECTION_ALLOWEXEDEFINITION:
                                    try {
                                        allowExeDefinition = AllowExeDefinitionToEnum(xmlUtil.Reader.Value, xmlUtil);
                                    }
                                    catch (ConfigurationException ce) {
                                        xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                                    }

                                    break;

                                case KEYWORD_SECTION_ALLOWDEFINITION:
                                    try {
                                        allowDefinition = AllowDefinitionToEnum(xmlUtil.Reader.Value, xmlUtil);
                                    }
                                    catch (ConfigurationException ce) {
                                        xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                                    }

                                    break;

                                case KEYWORD_SECTION_RESTARTONEXTERNALCHANGES:
                                    xmlUtil.VerifyAndGetBooleanAttribute(
                                            ExceptionAction.Local, true, out restartOnExternalChanges);

                                    break;

                                case KEYWORD_SECTION_REQUIREPERMISSION:
                                    xmlUtil.VerifyAndGetBooleanAttribute(
                                            ExceptionAction.Local, true, out requirePermission);

                                    break;

                                default:
                                    xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.Local);
                                    break;
                            }
                        }

                        xmlUtil.Reader.MoveToElement(); // if on an attribute move back to the element

                        if (!xmlUtil.VerifyRequiredAttribute(
                                tagName, KEYWORD_SECTION_NAME, ExceptionAction.NonSpecific)) {

                            //
                            // Without a name, we cannot continue to create a factoryRecord.
                            //
                            xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true);
                        }
                        else {
                            // Verify that the Type attribute was present.
                            // Note that 'typeName' will be null if the attribute was present
                            // but specified as an empty string.
                            if (!gotType) {
                                xmlUtil.AddErrorRequiredAttribute(KEYWORD_SECTION_TYPE, ExceptionAction.Local);
                            }

                            string configKey = CombineConfigKey(parentConfigKey, tagName);

                            FactoryRecord factoryRecord = (FactoryRecord) factoryList[configKey];
                            if (factoryRecord != null) {
                                // Error: duplicate section declaration
                                xmlUtil.SchemaErrors.AddError(
                                        new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined_at_this_level, tagName), xmlUtil),
                                        ExceptionAction.Local);
                            } else {
                                FactoryRecord parentFactoryRecord = _parent.FindFactoryRecord(configKey, true);
                                if (parentFactoryRecord != null) {
                                    configKey = parentFactoryRecord.ConfigKey;

                                    // make sure that an ancestor has not defined a section with the same name as the group
                                    if (parentFactoryRecord.IsGroup) {
                                        xmlUtil.SchemaErrors.AddError(
                                                new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined, tagName), xmlUtil),
                                                ExceptionAction.Local);

                                        parentFactoryRecord = null;
                                    }
                                    else if (!parentFactoryRecord.IsEquivalentSectionFactory(Host, typeName, allowLocation, allowDefinition, allowExeDefinition, restartOnExternalChanges, requirePermission)) {
                                        xmlUtil.SchemaErrors.AddError(
                                                new ConfigurationErrorsException(SR.GetString(SR.Config_tag_name_already_defined, tagName), xmlUtil),
                                                ExceptionAction.Local);

                                        parentFactoryRecord = null;
                                    }
                                }

                                if (parentFactoryRecord != null) {
                                    // Note - Clone will propagate the IsFromTrustedConfigRecord bit, 
                                    // which is what we want - if this record is a duplicate of an ancestor,
                                    // the ancestor may be from a trusted config record.
                                    factoryRecord = parentFactoryRecord.CloneSection(xmlUtil.Filename, lineNumber);
                                }
                                else {
                                    factoryRecord = new FactoryRecord(
                                            configKey, 
                                            parentConfigKey, 
                                            tagName, 
                                            typeName, 
                                            allowLocation, 
                                            allowDefinition, 
                                            allowExeDefinition, 
                                            restartOnExternalChanges, 
                                            requirePermission,
                                            _flags[IsTrusted],
                                            false,  // isUndeclared
                                            xmlUtil.Filename,
                                            lineNumber);
                                }

                                factoryList[configKey] = factoryRecord;
                            }

                            // Add any errors we may have encountered
                            factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true));
                        }
                    }
                    break;

                    case KEYWORD_REMOVE: {
                        string name = null;
                        int lineNumber = -1;

                        // parse attributes
                        while (xmlUtil.Reader.MoveToNextAttribute()) {
                            if (xmlUtil.Reader.Name != KEYWORD_SECTION_NAME) {
                                xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.NonSpecific);
                            }

                            name = xmlUtil.Reader.Value;
                            lineNumber = xmlUtil.Reader.LineNumber;
                        }
                        xmlUtil.Reader.MoveToElement();

                        if (xmlUtil.VerifyRequiredAttribute(
                                name, KEYWORD_SECTION_NAME, ExceptionAction.NonSpecific)) {

                            VerifySectionName(name, xmlUtil, ExceptionAction.NonSpecific, false);
                        }
                    }
                    break;

                    case KEYWORD_CLEAR: {
                        xmlUtil.VerifyNoUnrecognizedAttributes(ExceptionAction.NonSpecific);
                    }
                    break;

                    default:
                        xmlUtil.AddErrorUnrecognizedElement(ExceptionAction.NonSpecific);
                        xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                        positionedAtNextElement = true;
                        break;
                }

                if (!positionedAtNextElement) {
                    // Need to read to next element, and check if an unrecognized child
                    // element is found.
                    xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
                    
                    // unrecognized children are not allowed in <configSections>
                    if (xmlUtil.Reader.Depth > depth + 1) {
                        xmlUtil.AddErrorUnrecognizedElement(ExceptionAction.NonSpecific);
                    
                        // Lets try to backup to where we are suppose to be
                        while (xmlUtil.Reader.Depth > (depth + 1)) {
                            xmlUtil.ReadToNextElement();
                        }
                    }
                }
            }
        }
        private void ScanSectionsRecursive(
                XmlUtil xmlUtil, string parentConfigKey, bool inLocation, string locationSubPath, 
                bool lockChildren, bool skipInChildApps) {

            // discard any accumulated local errors
            xmlUtil.SchemaErrors.ResetLocalErrors();

            int depth;

            // only move to child nodes when not on first level (we've already passed the first <configsections>)
            if (parentConfigKey.Length == 0 && !inLocation) {
                depth = 0;
            }
            else {
                depth = xmlUtil.Reader.Depth;
                xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
            }

            while (xmlUtil.Reader.Depth == depth + 1) {

                string tagName = xmlUtil.Reader.Name;

                //
                // Check for reserved elements before looking up the factory,
                // which may have the same name if it is in error.
                //
                if (tagName == KEYWORD_CONFIGSECTIONS) {
                    // Error: duplicate <configSections> tag, or <configSections> not the first tag under <configuration>
                    xmlUtil.SchemaErrors.AddError(
                            new ConfigurationErrorsException(SR.GetString(SR.Config_client_config_too_many_configsections_elements, tagName), xmlUtil),
                            ExceptionAction.NonSpecific);

                    xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                    continue;
                }

                if (tagName == KEYWORD_LOCATION) {
                    if (parentConfigKey.Length > 0 || inLocation) {
                        // Error: <location> section not at top level
                        xmlUtil.SchemaErrors.AddError(
                                new ConfigurationErrorsException(SR.GetString(SR.Config_location_location_not_allowed), xmlUtil),
                                ExceptionAction.Global);

                        xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                    }
                    else {
                        // Recurse into the location section
                        ScanLocationSection(xmlUtil);
                    }

                    continue;
                }

                string configKey = CombineConfigKey(parentConfigKey, tagName);
                FactoryRecord factoryRecord = FindFactoryRecord(configKey, true);


                if (factoryRecord == null) {
                    // 
                    //
                    if (!ClassFlags[ClassIgnoreLocalErrors]) {
                        xmlUtil.SchemaErrors.AddError(
                                new ConfigurationErrorsException(SR.GetString(SR.Config_unrecognized_configuration_section, configKey), xmlUtil),
                                ExceptionAction.Local);
                    }

                    VerifySectionName(tagName, xmlUtil, ExceptionAction.Local, false);

                    factoryRecord = new FactoryRecord(
                            configKey, 
                            parentConfigKey,
                            tagName,
                            typeof(DefaultSection).AssemblyQualifiedName,
                            true,   // allowLocation
                            ConfigurationAllowDefinition.Everywhere,
                            ConfigurationAllowExeDefinition.MachineToRoamingUser,
                            true,   // restartOnExternalChanges
                            true,   // requirePermission
                            _flags[IsTrusted],
                            true,   // isUndeclared
                            null,
                            -1);

                    // Add any errors we may have encountered to the factory record,
                    // so that child config that also refer to this unrecognized section
                    // get the error.
                    factoryRecord.AddErrors(xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(true));

                    // Add the factory to the list of factories
                    EnsureFactories()[configKey] = factoryRecord;
                }

                if (factoryRecord.IsGroup) {
                    //
                    // Section Group
                    //
                    if (factoryRecord.HasErrors) {
                        xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                    }
                    else {
                        if (xmlUtil.Reader.AttributeCount > 0) {
                            while (xmlUtil.Reader.MoveToNextAttribute()) {
                                if (IsReservedAttributeName(xmlUtil.Reader.Name)) {
                                    xmlUtil.AddErrorReservedAttribute(ExceptionAction.NonSpecific);
                                }
                            }

                            xmlUtil.Reader.MoveToElement(); // if on an attribute move back to the element
                        }

                        // Recurse into group definition
                        ScanSectionsRecursive(xmlUtil, configKey, inLocation, locationSubPath, lockChildren, skipInChildApps);
                    }
                }
                else {
                    //
                    // Section
                    //
                    configKey = factoryRecord.ConfigKey;
                    string fileName = xmlUtil.Filename;
                    int lineNumber = xmlUtil.LineNumber;
                    string rawXml = null;
                    string configSource = null;
                    string configSourceStreamName = null;
                    object configSourceStreamVersion = null;
                    string protectionProviderName = null;
                    bool isSectionLocked = false;
                    bool positionedAtNextElement = false;
                    bool isFileInput = (locationSubPath == null);

                    if (!factoryRecord.HasErrors) {
                        // We have a valid factoryRecord for a section
                        if (inLocation && factoryRecord.AllowLocation == false) {
                            xmlUtil.SchemaErrors.AddError(
                                    new ConfigurationErrorsException(SR.GetString(SR.Config_section_cannot_be_used_in_location), xmlUtil), 
                                    ExceptionAction.Local);
                        }
    
                        // Verify correctness for file inputs.
                        if (isFileInput) {
                            // Verify that the section is unique
                            SectionRecord sectionRecord = GetSectionRecord(configKey, true);
                            if (sectionRecord != null && sectionRecord.HasFileInput) {
                                xmlUtil.SchemaErrors.AddError(
                                    new ConfigurationErrorsException(SR.GetString(SR.Config_sections_must_be_unique), xmlUtil),
                                    ExceptionAction.Local);
                            }

                            // Verify that the definition is allowed.
                            try {
                                VerifyDefinitionAllowed(factoryRecord, _configPath, xmlUtil);
                            }
                            catch (ConfigurationException ce) {
                                xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                            }
                        }

                        // Verify that section is unlocked, both for file and location inputs.
                        try {
                            VerifySectionUnlocked(configKey, xmlUtil);
                        }
                        catch (ConfigurationException ce) {
                            isSectionLocked = true;
                            xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                        }

                        // check for configSource or protectionProvider
                        if (xmlUtil.Reader.AttributeCount >= 1) {
                            // First do all the attributes reading without advancing the reader.
                            
                            string configSourceAttribute = xmlUtil.Reader.GetAttribute(KEYWORD_CONFIGSOURCE);
                            if (configSourceAttribute != null) {
                                try {
                                    configSource = NormalizeConfigSource(configSourceAttribute, xmlUtil);
                                }
                                catch (ConfigurationException ce) {
                                    xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                                }

                                if (xmlUtil.Reader.AttributeCount != 1) {
                                    // Error: elements with configSource should not have other attributes
                                    xmlUtil.SchemaErrors.AddError(
                                            new ConfigurationErrorsException(SR.GetString(SR.Config_source_syntax_error), xmlUtil), 
                                            ExceptionAction.Local);
                                }
                            }

                            string protectionProviderAttribute = xmlUtil.Reader.GetAttribute(KEYWORD_PROTECTION_PROVIDER);
                            if (protectionProviderAttribute != null) {
                                try {
                                    protectionProviderName = ValidateProtectionProviderAttribute(protectionProviderAttribute, xmlUtil);
                                }
                                catch (ConfigurationException ce) {
                                    xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Local);
                                }
                                
                                if (xmlUtil.Reader.AttributeCount != 1) {
                                    // Error: elements with protectionProvider should not have other attributes
                                    xmlUtil.SchemaErrors.AddError(
                                            new ConfigurationErrorsException(SR.GetString(SR.Protection_provider_syntax_error), xmlUtil), 
                                            ExceptionAction.Local);
                                }
                            }

                            // The 2nd part of the configSource check requires advancing the reader.
                            // Please note that this part should be done only AFTER all other attributes
                            // checking are done.
                            if (configSourceAttribute != null) {
                                if (!xmlUtil.Reader.IsEmptyElement) {
                                    while (xmlUtil.Reader.Read()) {
                                        XmlNodeType t = xmlUtil.Reader.NodeType;
                                        if (t == XmlNodeType.EndElement)
                                            break;

                                        if (t != XmlNodeType.Comment) {
                                            // Error: elements with configSource should not subelements other than comments
                                            xmlUtil.SchemaErrors.AddError(
                                                    new ConfigurationErrorsException(SR.GetString(SR.Config_source_syntax_error), xmlUtil),
                                                    ExceptionAction.Local);

                                            if (t == XmlNodeType.Element) {
                                                xmlUtil.StrictSkipToOurParentsEndElement(ExceptionAction.NonSpecific);
                                            }
                                            else {
                                                xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);
                                            }

                                            positionedAtNextElement = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        if (configSource != null) {
                            try {
                                try {
                                    configSourceStreamName = Host.GetStreamNameForConfigSource(ConfigStreamInfo.StreamName, configSource);
                                }
                                catch (Exception e) {
                                    throw ExceptionUtil.WrapAsConfigException(SR.GetString(SR.Config_source_invalid), e, xmlUtil);
                                }
                                ValidateUniqueConfigSource(configKey, configSourceStreamName, configSource, xmlUtil);
                                configSourceStreamVersion = MonitorStream(configKey, configSource, configSourceStreamName);
                            }
                            catch (ConfigurationException ex) {
                                xmlUtil.SchemaErrors.AddError(ex, ExceptionAction.Local);
                            }
                        }

                        //
                        // prefetch the raw xml
                        //
                        if (!xmlUtil.SchemaErrors.HasLocalErrors) {
                            if (configSource == null && ShouldPrefetchRawXml(factoryRecord)) {
                                Debug.Assert(!positionedAtNextElement, "!positionedAtNextElement");

                                rawXml = xmlUtil.CopySection();
                                if (xmlUtil.Reader.NodeType != XmlNodeType.Element) {
                                    xmlUtil.VerifyIgnorableNodeType(ExceptionAction.NonSpecific);
                                    xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
                                }

                                positionedAtNextElement = true;
                            }
                        }
                    }

                    // Get the list of errors before advancing the reader
                    List<ConfigurationException> localErrors = xmlUtil.SchemaErrors.RetrieveAndResetLocalErrors(isFileInput);

                    // advance the reader to the next element
                    if (!positionedAtNextElement) {
                        xmlUtil.StrictSkipToNextElement(ExceptionAction.NonSpecific);                            
                    }

                    // Add the input either to:
                    // 1. The file input at the current config level, or
                    // 2. LocationSections, where it will be used in sub paths
                    bool addInput = true;

                    if (isFileInput) {
                        // If isFileInput==true, Input added will be used against this config level.
                        // Need to check if we need to skip it due to inheritInChildApplications.
                        
                        if (ShouldSkipDueToInheritInChildApplications(skipInChildApps)) {
                            addInput = false;
                        }
                    }
                    else {
                        if (!_flags[SupportsLocation]) {
                            // Skip if we have a location input but we don't support location tag.
                            addInput = false;
                        }
                    }
                    
                    if (addInput) {

                        string targetConfigPath = (locationSubPath == null) ? _configPath : null;

                        SectionXmlInfo sectionXmlInfo = new SectionXmlInfo(
                                configKey, _configPath, targetConfigPath, locationSubPath,
                                fileName, lineNumber, ConfigStreamInfo.StreamVersion, rawXml, 
                                configSource, configSourceStreamName, configSourceStreamVersion,
                                protectionProviderName, lockChildren, skipInChildApps);

                        if (locationSubPath == null) {
                            //
                            // Add this file input to the section record
                            //

                            // We've already checked for locked above, so use skip the second check
                            // and set the locked bit.
                            SectionRecord sectionRecord = EnsureSectionRecordUnsafe(configKey, true);

                            Debug.Assert(!sectionRecord.Locked || isSectionLocked,
                                        "!sectionRecord.Locked || isSectionLocked");

                            if (isSectionLocked) {
                                sectionRecord.Locked = true;
                            }
                            
                            SectionInput fileInput = new SectionInput(sectionXmlInfo, localErrors);
                            sectionRecord.AddFileInput(fileInput);
                        }
                        else {
                            //
                            // Add this location input to this list of location sections
                            //
                            LocationSectionRecord locationSectionRecord = new LocationSectionRecord(sectionXmlInfo, localErrors);
                            EnsureLocationSections().Add(locationSectionRecord);
                        }
                    }
                }
            }
        }
        private Hashtable ScanFactories(XmlUtil xmlUtil) {
            Hashtable factoryList;

            factoryList = new Hashtable();
            
            if (xmlUtil.Reader.NodeType != XmlNodeType.Element || xmlUtil.Reader.Name != KEYWORD_CONFIGURATION) {
                string safeFilename = ConfigurationErrorsException.AlwaysSafeFilename(((IConfigErrorInfo)xmlUtil).Filename);

                throw new ConfigurationErrorsException(
                        SR.GetString(SR.Config_file_doesnt_have_root_configuration, safeFilename), 
                        xmlUtil);
            }

            // Ignore xmlns attribute
            while (xmlUtil.Reader.MoveToNextAttribute()) {
                switch (xmlUtil.Reader.Name) {
                case KEYWORD_XMLNS:
                    if (xmlUtil.Reader.Value == KEYWORD_CONFIGURATION_NAMESPACE) {
                        _flags[NamespacePresentInFile] = true;
                        _flags[NamespacePresentCurrent] = true;
                    } else {
                        ConfigurationErrorsException ce;

                        ce = new ConfigurationErrorsException(
                                SR.GetString(SR.Config_namespace_invalid, xmlUtil.Reader.Value, KEYWORD_CONFIGURATION_NAMESPACE),
                                xmlUtil);
                        
                        xmlUtil.SchemaErrors.AddError(ce, ExceptionAction.Global);
                    }
                    
                    break;

                default:
                    xmlUtil.AddErrorUnrecognizedAttribute(ExceptionAction.NonSpecific);
                    break;
                }
            }

            // move to first child of <configuration>
            xmlUtil.StrictReadToNextElement(ExceptionAction.NonSpecific);
            if (xmlUtil.Reader.Depth == 1 && xmlUtil.Reader.Name == KEYWORD_CONFIGSECTIONS) {
                xmlUtil.VerifyNoUnrecognizedAttributes(ExceptionAction.NonSpecific);
                ScanFactoriesRecursive(xmlUtil, string.Empty, factoryList);
            }

            return factoryList;
        }