ClientSettingsStore.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Sys / System / Configuration / ClientSettingsStore.cs / 1305376 / ClientSettingsStore.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

using System.Diagnostics.CodeAnalysis; 
 
[assembly: SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Scope="member", Target="System.Configuration.ClientSettingsStore+QuotaEnforcedStream.Dispose(System.Boolean):System.Void")]
 
namespace System.Configuration {
    using System;
    using System.Collections;
    using System.Collections.Specialized; 
    using System.Configuration;
    using System.Configuration.Internal; 
    using System.Configuration.Provider; 
    using System.Diagnostics;
    using System.IO; 
    using System.Security;
    using System.Security.Permissions;
    using System.Xml;
 

    ///  
    ///     This class abstracts the details of config system away from the LocalFileSettingsProvider. It talks to 
    ///     the configuration API and the relevant Sections to read and write settings.
    ///     It understands sections of type ClientSettingsSection. 
    ///
    ///     NOTE: This API supports reading from app.exe.config and user.config, but writing only to
    ///           user.config.
    ///  
    internal sealed class ClientSettingsStore {
        private const string ApplicationSettingsGroupName   = "applicationSettings"; 
        private const string UserSettingsGroupName          = "userSettings"; 
        private const string ApplicationSettingsGroupPrefix = ApplicationSettingsGroupName + "/";
        private const string UserSettingsGroupPrefix        = UserSettingsGroupName + "/"; 

        private Configuration GetUserConfig(bool isRoaming) {
            ConfigurationUserLevel userLevel = isRoaming ? ConfigurationUserLevel.PerUserRoaming :
                                                           ConfigurationUserLevel.PerUserRoamingAndLocal; 

            return ClientSettingsConfigurationHost.OpenExeConfiguration(userLevel); 
        } 

        private ClientSettingsSection GetConfigSection(Configuration config, string sectionName, bool declare) { 
            string fullSectionName = UserSettingsGroupPrefix + sectionName;
            ClientSettingsSection section = null;

            if (config != null) { 
                section = config.GetSection(fullSectionName) as ClientSettingsSection;
 
                if (section == null && declare) { 
                    // Looks like the section isn't declared - let's declare it and try again.
                    DeclareSection(config, sectionName); 
                    section = config.GetSection(fullSectionName) as ClientSettingsSection;
                }
            }
 
            return section;
        } 
 
        // Declares the section handler of a given section in its section group, if a declaration isn't already
        // present. 
        private void DeclareSection(Configuration config, string sectionName) {
            ConfigurationSectionGroup settingsGroup = config.GetSectionGroup(UserSettingsGroupName);

            if (settingsGroup == null) { 
                //Declare settings group
                ConfigurationSectionGroup group = new UserSettingsGroup(); 
                config.SectionGroups.Add(UserSettingsGroupName, group); 
            }
 
            settingsGroup = config.GetSectionGroup(UserSettingsGroupName);

            Debug.Assert(settingsGroup != null, "Failed to declare settings group");
 
            if (settingsGroup != null) {
                ConfigurationSection section = settingsGroup.Sections[sectionName]; 
                if (section == null) { 
                    section = new ClientSettingsSection();
                    section.SectionInformation.AllowExeDefinition = ConfigurationAllowExeDefinition.MachineToLocalUser; 
                    section.SectionInformation.RequirePermission = false;
                    settingsGroup.Sections.Add(sectionName, section);
                }
            } 
        }
 
        internal IDictionary ReadSettings(string sectionName, bool isUserScoped) { 
            IDictionary settings = new Hashtable();
 
            if( isUserScoped && !ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) {
                return settings;
            }
 
            string prefix = isUserScoped ? UserSettingsGroupPrefix : ApplicationSettingsGroupPrefix;
            ConfigurationManager.RefreshSection(prefix + sectionName); 
            ClientSettingsSection section = ConfigurationManager.GetSection(prefix + sectionName) as ClientSettingsSection; 

            if (section != null) { 
                foreach (SettingElement setting in section.Settings) {
                    settings[setting.Name] = new StoredSetting(setting.SerializeAs, setting.Value.ValueXml);
                }
            } 

            return settings; 
        } 

        internal static IDictionary ReadSettingsFromFile(string configFileName, string sectionName, bool isUserScoped) { 
            IDictionary settings = new Hashtable();

            if( isUserScoped && !ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) {
                return settings; 
            }
 
            string prefix = isUserScoped ? UserSettingsGroupPrefix : ApplicationSettingsGroupPrefix; 
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
 
            // NOTE: When isUserScoped is true, we don't care if configFileName represents a roaming file or
            //       a local one. All we want is three levels of configuration. So, we use the PerUserRoaming level.
            ConfigurationUserLevel userLevel = isUserScoped ? ConfigurationUserLevel.PerUserRoaming : ConfigurationUserLevel.None;
 
            if (isUserScoped) {
                fileMap.ExeConfigFilename = ConfigurationManagerInternalFactory.Instance.ApplicationConfigUri; 
                fileMap.RoamingUserConfigFilename = configFileName; 
            }
            else { 
                fileMap.ExeConfigFilename = configFileName;
            }

            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, userLevel); 
            ClientSettingsSection section = config.GetSection(prefix + sectionName) as ClientSettingsSection;
 
            if (section != null) { 
                foreach (SettingElement setting in section.Settings) {
                    settings[setting.Name] = new StoredSetting(setting.SerializeAs, setting.Value.ValueXml); 
                }
            }

            return settings; 
        }
 
        internal ConnectionStringSettingsCollection ReadConnectionStrings() { 
            return PrivilegedConfigurationManager.ConnectionStrings;
        } 

        internal void RevertToParent(string sectionName, bool isRoaming) {
            if (!ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) {
                throw new ConfigurationErrorsException(SR.GetString(SR.UserSettingsNotSupported)); 
            }
 
            Configuration config = GetUserConfig(isRoaming); 
            ClientSettingsSection section = GetConfigSection(config, sectionName, false);
 
            // If the section is null, there is nothing to revert.
            if (section != null) {
                section.SectionInformation.RevertToParent();
                config.Save(); 
            }
        } 
 
        internal void WriteSettings(string sectionName, bool isRoaming, IDictionary newSettings) {
            if (!ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.UserSettingsNotSupported));
            }

            Configuration config = GetUserConfig(isRoaming); 
            ClientSettingsSection section = GetConfigSection(config, sectionName, true);
 
            if (section != null) { 
                SettingElementCollection sec = section.Settings;
                foreach (DictionaryEntry entry in newSettings) { 
                    SettingElement se = sec.Get((string) entry.Key);

                    if (se == null) {
                        se = new SettingElement(); 
                        se.Name = (string) entry.Key;
                        sec.Add(se); 
                    } 

                    StoredSetting ss = (StoredSetting) entry.Value; 
                    se.SerializeAs = ss.SerializeAs;
                    se.Value.ValueXml = ss.Value;
                }
 
                try {
                    config.Save(); 
                } 
                catch (ConfigurationErrorsException ex) {
                    // We wrap this in an exception with our error message and throw again. 
                    throw new ConfigurationErrorsException(SR.GetString(SR.SettingsSaveFailed, ex.Message), ex);
                }
            }
            else { 
                throw new ConfigurationErrorsException(SR.GetString(SR.SettingsSaveFailedNoSection));
            } 
        } 

        ///  
        ///     A private configuration host that we use to write settings to config. We need this so we
        ///     can enforce a quota on the size of stuff written out.
        /// 
        private sealed class ClientSettingsConfigurationHost : DelegatingConfigHost { 
            private const string ClientConfigurationHostTypeName = "System.Configuration.ClientConfigurationHost," + AssemblyRef.SystemConfiguration;
            private const string InternalConfigConfigurationFactoryTypeName = "System.Configuration.Internal.InternalConfigConfigurationFactory," + AssemblyRef.SystemConfiguration; 
            private static IInternalConfigConfigurationFactory s_configFactory; 

            ///  
            ///     ClientConfigurationHost implements this - a way of getting some info from it without
            ///     depending too much on its internals.
            /// 
            private IInternalConfigClientHost ClientHost { 
                get {
                    return (IInternalConfigClientHost) Host; 
                } 
            }
 
            internal static IInternalConfigConfigurationFactory ConfigFactory {
                get {
                    if (s_configFactory == null) {
                        s_configFactory = (IInternalConfigConfigurationFactory) 
                                            TypeUtil.CreateInstanceWithReflectionPermission(InternalConfigConfigurationFactoryTypeName);
                    } 
                    return s_configFactory; 
                }
            } 

            private ClientSettingsConfigurationHost() {}

            public override void Init(IInternalConfigRoot configRoot, params object[] hostInitParams) { 
                Debug.Fail("Did not expect to get called here");
            } 
 
            /// 
            ///     We delegate this to the ClientConfigurationHost. The only thing we need to do here is to 
            ///     build a configPath from the ConfigurationUserLevel we get passed in.
            /// 
            public override void InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath,
                    IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams) { 

                ConfigurationUserLevel userLevel = (ConfigurationUserLevel) hostInitConfigurationParams[0]; 
                string desiredConfigPath = null; 
                Host = (IInternalConfigHost) TypeUtil.CreateInstanceWithReflectionPermission(ClientConfigurationHostTypeName);
 
                switch (userLevel) {
                    case ConfigurationUserLevel.None:
                        desiredConfigPath = ClientHost.GetExeConfigPath();
                        break; 

                    case ConfigurationUserLevel.PerUserRoaming: 
                        desiredConfigPath = ClientHost.GetRoamingUserConfigPath(); 
                        break;
 
                    case ConfigurationUserLevel.PerUserRoamingAndLocal:
                        desiredConfigPath = ClientHost.GetLocalUserConfigPath();
                        break;
 
                    default:
                        throw new ArgumentException(SR.GetString(SR.UnknownUserLevel)); 
                } 

 
                Host.InitForConfiguration(ref locationSubPath, out configPath, out locationConfigPath, configRoot, null, null, desiredConfigPath);
            }

            private bool IsKnownConfigFile(string filename) { 
                return
                  String.Equals(filename, ConfigurationManagerInternalFactory.Instance.MachineConfigPath, StringComparison.OrdinalIgnoreCase) || 
                  String.Equals(filename, ConfigurationManagerInternalFactory.Instance.ApplicationConfigUri, StringComparison.OrdinalIgnoreCase) || 
                  String.Equals(filename, ConfigurationManagerInternalFactory.Instance.ExeLocalConfigPath, StringComparison.OrdinalIgnoreCase) ||
                  String.Equals(filename, ConfigurationManagerInternalFactory.Instance.ExeRoamingConfigPath, StringComparison.OrdinalIgnoreCase); 

            }

            internal static Configuration OpenExeConfiguration(ConfigurationUserLevel userLevel) { 
                return ConfigFactory.Create(typeof(ClientSettingsConfigurationHost), userLevel);
            } 
 
            /// 
            ///     If the stream we are asked for represents a config file that we know about, we ask 
            ///     the host to assert appropriate permissions.
            /// 
            public override Stream OpenStreamForRead(string streamName) {
                if (IsKnownConfigFile(streamName)) { 
                    return Host.OpenStreamForRead(streamName, true);
                } 
                else { 
                    return Host.OpenStreamForRead(streamName);
                } 
            }

            /// 
            ///     If the stream we are asked for represents a user.config file that we know about, we wrap it in a 
            ///     QuotaEnforcedStream, after asking the host to assert appropriate permissions.///
            ///  
            public override Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext) { 
                Stream stream = null;
 
                if (String.Equals(streamName, ConfigurationManagerInternalFactory.Instance.ExeLocalConfigPath, StringComparison.OrdinalIgnoreCase)) {
                    stream = new QuotaEnforcedStream(
                                   Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext, true),
                                   false); 
                }
                else if (String.Equals(streamName, ConfigurationManagerInternalFactory.Instance.ExeRoamingConfigPath, StringComparison.OrdinalIgnoreCase)) { 
                    stream = new QuotaEnforcedStream( 
                                   Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext, true),
                                   true); 
                }
                else {
                    stream = Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext);
                } 

                return stream; 
            } 

            ///  
            ///     If this is a stream that represents a user.config file that we know about, we ask
            ///     the host to assert appropriate permissions.
            /// 
            public override void WriteCompleted(string streamName, bool success, object writeContext) { 
                if (String.Equals(streamName, ConfigurationManagerInternalFactory.Instance.ExeLocalConfigPath, StringComparison.OrdinalIgnoreCase) ||
                    String.Equals(streamName, ConfigurationManagerInternalFactory.Instance.ExeRoamingConfigPath, StringComparison.OrdinalIgnoreCase)) { 
 
                    Host.WriteCompleted(streamName, success, writeContext, true);
                } 
                else {
                    Host.WriteCompleted(streamName, success, writeContext);
                }
            } 
        }
 
        ///  
        ///     A private stream class that wraps a stream and enforces a quota. The quota enforcement uses
        ///     IsolatedStorageFilePermission. We override nearly all methods on the Stream class so we can 
        ///     forward to the wrapped stream. In the methods that affect stream length, we verify that the
        ///     quota is respected before forwarding.
        /// 
        private sealed class QuotaEnforcedStream : Stream { 
            private Stream _originalStream;
            private bool _isRoaming; 
 
            internal QuotaEnforcedStream(Stream originalStream, bool isRoaming) {
                _originalStream = originalStream; 
                _isRoaming = isRoaming;

                Debug.Assert(_originalStream != null, "originalStream was null.");
            } 

            public override bool CanRead { 
                get { return _originalStream.CanRead; } 
            }
 
            public override bool CanWrite {
                get { return _originalStream.CanWrite; }
            }
 
            public override bool CanSeek {
                get { return _originalStream.CanSeek; } 
            } 

            public override long Length { 
                get { return _originalStream.Length; }
            }

            public override long Position { 

                get { return _originalStream.Position; } 
 
                set {
                    if (value < 0) { 
                        throw new ArgumentOutOfRangeException("value", SR.GetString(SR.PositionOutOfRange));
                    }

                    Seek(value, SeekOrigin.Begin); 
                }
            } 
 
            public override void Close() {
                _originalStream.Close(); 
            }

            protected override void Dispose(bool disposing) {
                if (disposing) { 
                    if (_originalStream != null) {
                        ((IDisposable)_originalStream).Dispose(); 
                        _originalStream = null; 
                    }
 
                }

                base.Dispose(disposing);
            } 

            public override void Flush() { 
                _originalStream.Flush(); 
            }
 
            public override void SetLength(long value) {
                long oldLen = _originalStream.Length;
                long newLen = value;
 
                EnsureQuota(Math.Max(oldLen, newLen));
                _originalStream.SetLength(value); 
            } 

            public override int Read(byte[] buffer, int offset, int count) { 
                return _originalStream.Read(buffer, offset, count);
            }

            public override int ReadByte() { 
                return _originalStream.ReadByte();
            } 
 
            public override long Seek(long offset, SeekOrigin origin) {
                if (!CanSeek) { 
                    throw new NotSupportedException();
                }

                long oldLen = _originalStream.Length; 
                long newLen;
 
                switch (origin) { 
                    case SeekOrigin.Begin:
                        newLen = offset; 
                        break;
                    case SeekOrigin.Current:
                        newLen = _originalStream.Position + offset;
                        break; 
                    case SeekOrigin.End:
                        newLen = oldLen + offset; 
                        break; 
                    default:
                        throw new ArgumentException(SR.GetString(SR.UnknownSeekOrigin), "origin"); 
                }

                EnsureQuota(Math.Max(oldLen, newLen));
                return _originalStream.Seek(offset, origin); 
            }
 
            public override void Write(byte[] buffer, int offset, int count) { 
                if (!CanWrite) {
                    throw new NotSupportedException(); 
                }

                long oldLen = _originalStream.Length;
                long newLen = _originalStream.CanSeek ? _originalStream.Position + (long)count : 
                                                        _originalStream.Length + (long)count;
                EnsureQuota(Math.Max(oldLen, newLen)); 
                _originalStream.Write(buffer, offset, count); 
            }
 
            public override void WriteByte(byte value) {
                if (!CanWrite) {
                    throw new NotSupportedException();
                } 

                long oldLen = _originalStream.Length; 
                long newLen = _originalStream.CanSeek ? _originalStream.Position + 1 : _originalStream.Length + 1; 
                EnsureQuota(Math.Max(oldLen, newLen));
 
                _originalStream.WriteByte(value);
            }

            public override IAsyncResult BeginRead(byte[] buffer, int offset, int numBytes, 
                                                   AsyncCallback userCallback, Object stateObject) {
                return _originalStream.BeginRead(buffer, offset, numBytes, userCallback, stateObject); 
            } 

            public override int EndRead(IAsyncResult asyncResult) { 
                return _originalStream.EndRead(asyncResult);

            }
 
            public override IAsyncResult BeginWrite(byte[] buffer, int offset, int numBytes,
                                                    AsyncCallback userCallback, Object stateObject) { 
                if (!CanWrite) { 
                    throw new NotSupportedException();
                } 

                long oldLen = _originalStream.Length;
                long newLen = _originalStream.CanSeek ? _originalStream.Position + (long)numBytes :
                                                        _originalStream.Length + (long)numBytes; 
                EnsureQuota(Math.Max(oldLen, newLen));
                return _originalStream.BeginWrite(buffer, offset, numBytes, userCallback, stateObject); 
            } 

            public override void EndWrite(IAsyncResult asyncResult) { 
                _originalStream.EndWrite(asyncResult);
            }

            // 
            private void EnsureQuota(long size) {
                IsolatedStoragePermission storagePerm = new IsolatedStorageFilePermission(PermissionState.None); 
                storagePerm.UserQuota = size; 
                storagePerm.UsageAllowed = _isRoaming? IsolatedStorageContainment.DomainIsolationByRoamingUser :
                                                       IsolatedStorageContainment.DomainIsolationByUser; 
                storagePerm.Demand();
            }
        }
    } 

    ///  
    ///     The ClientSettingsStore talks to the LocalFileSettingsProvider through a dictionary which maps from 
    ///     setting names to StoredSetting structs. This struct contains the relevant information.
    ///  
    internal struct StoredSetting {
        internal StoredSetting(SettingsSerializeAs serializeAs, XmlNode value) {
            SerializeAs = serializeAs;
            Value = value; 
        }
        internal SettingsSerializeAs SerializeAs; 
        internal XmlNode Value; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

using System.Diagnostics.CodeAnalysis; 
 
[assembly: SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Scope="member", Target="System.Configuration.ClientSettingsStore+QuotaEnforcedStream.Dispose(System.Boolean):System.Void")]
 
namespace System.Configuration {
    using System;
    using System.Collections;
    using System.Collections.Specialized; 
    using System.Configuration;
    using System.Configuration.Internal; 
    using System.Configuration.Provider; 
    using System.Diagnostics;
    using System.IO; 
    using System.Security;
    using System.Security.Permissions;
    using System.Xml;
 

    ///  
    ///     This class abstracts the details of config system away from the LocalFileSettingsProvider. It talks to 
    ///     the configuration API and the relevant Sections to read and write settings.
    ///     It understands sections of type ClientSettingsSection. 
    ///
    ///     NOTE: This API supports reading from app.exe.config and user.config, but writing only to
    ///           user.config.
    ///  
    internal sealed class ClientSettingsStore {
        private const string ApplicationSettingsGroupName   = "applicationSettings"; 
        private const string UserSettingsGroupName          = "userSettings"; 
        private const string ApplicationSettingsGroupPrefix = ApplicationSettingsGroupName + "/";
        private const string UserSettingsGroupPrefix        = UserSettingsGroupName + "/"; 

        private Configuration GetUserConfig(bool isRoaming) {
            ConfigurationUserLevel userLevel = isRoaming ? ConfigurationUserLevel.PerUserRoaming :
                                                           ConfigurationUserLevel.PerUserRoamingAndLocal; 

            return ClientSettingsConfigurationHost.OpenExeConfiguration(userLevel); 
        } 

        private ClientSettingsSection GetConfigSection(Configuration config, string sectionName, bool declare) { 
            string fullSectionName = UserSettingsGroupPrefix + sectionName;
            ClientSettingsSection section = null;

            if (config != null) { 
                section = config.GetSection(fullSectionName) as ClientSettingsSection;
 
                if (section == null && declare) { 
                    // Looks like the section isn't declared - let's declare it and try again.
                    DeclareSection(config, sectionName); 
                    section = config.GetSection(fullSectionName) as ClientSettingsSection;
                }
            }
 
            return section;
        } 
 
        // Declares the section handler of a given section in its section group, if a declaration isn't already
        // present. 
        private void DeclareSection(Configuration config, string sectionName) {
            ConfigurationSectionGroup settingsGroup = config.GetSectionGroup(UserSettingsGroupName);

            if (settingsGroup == null) { 
                //Declare settings group
                ConfigurationSectionGroup group = new UserSettingsGroup(); 
                config.SectionGroups.Add(UserSettingsGroupName, group); 
            }
 
            settingsGroup = config.GetSectionGroup(UserSettingsGroupName);

            Debug.Assert(settingsGroup != null, "Failed to declare settings group");
 
            if (settingsGroup != null) {
                ConfigurationSection section = settingsGroup.Sections[sectionName]; 
                if (section == null) { 
                    section = new ClientSettingsSection();
                    section.SectionInformation.AllowExeDefinition = ConfigurationAllowExeDefinition.MachineToLocalUser; 
                    section.SectionInformation.RequirePermission = false;
                    settingsGroup.Sections.Add(sectionName, section);
                }
            } 
        }
 
        internal IDictionary ReadSettings(string sectionName, bool isUserScoped) { 
            IDictionary settings = new Hashtable();
 
            if( isUserScoped && !ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) {
                return settings;
            }
 
            string prefix = isUserScoped ? UserSettingsGroupPrefix : ApplicationSettingsGroupPrefix;
            ConfigurationManager.RefreshSection(prefix + sectionName); 
            ClientSettingsSection section = ConfigurationManager.GetSection(prefix + sectionName) as ClientSettingsSection; 

            if (section != null) { 
                foreach (SettingElement setting in section.Settings) {
                    settings[setting.Name] = new StoredSetting(setting.SerializeAs, setting.Value.ValueXml);
                }
            } 

            return settings; 
        } 

        internal static IDictionary ReadSettingsFromFile(string configFileName, string sectionName, bool isUserScoped) { 
            IDictionary settings = new Hashtable();

            if( isUserScoped && !ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) {
                return settings; 
            }
 
            string prefix = isUserScoped ? UserSettingsGroupPrefix : ApplicationSettingsGroupPrefix; 
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
 
            // NOTE: When isUserScoped is true, we don't care if configFileName represents a roaming file or
            //       a local one. All we want is three levels of configuration. So, we use the PerUserRoaming level.
            ConfigurationUserLevel userLevel = isUserScoped ? ConfigurationUserLevel.PerUserRoaming : ConfigurationUserLevel.None;
 
            if (isUserScoped) {
                fileMap.ExeConfigFilename = ConfigurationManagerInternalFactory.Instance.ApplicationConfigUri; 
                fileMap.RoamingUserConfigFilename = configFileName; 
            }
            else { 
                fileMap.ExeConfigFilename = configFileName;
            }

            Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, userLevel); 
            ClientSettingsSection section = config.GetSection(prefix + sectionName) as ClientSettingsSection;
 
            if (section != null) { 
                foreach (SettingElement setting in section.Settings) {
                    settings[setting.Name] = new StoredSetting(setting.SerializeAs, setting.Value.ValueXml); 
                }
            }

            return settings; 
        }
 
        internal ConnectionStringSettingsCollection ReadConnectionStrings() { 
            return PrivilegedConfigurationManager.ConnectionStrings;
        } 

        internal void RevertToParent(string sectionName, bool isRoaming) {
            if (!ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) {
                throw new ConfigurationErrorsException(SR.GetString(SR.UserSettingsNotSupported)); 
            }
 
            Configuration config = GetUserConfig(isRoaming); 
            ClientSettingsSection section = GetConfigSection(config, sectionName, false);
 
            // If the section is null, there is nothing to revert.
            if (section != null) {
                section.SectionInformation.RevertToParent();
                config.Save(); 
            }
        } 
 
        internal void WriteSettings(string sectionName, bool isRoaming, IDictionary newSettings) {
            if (!ConfigurationManagerInternalFactory.Instance.SupportsUserConfig) { 
                throw new ConfigurationErrorsException(SR.GetString(SR.UserSettingsNotSupported));
            }

            Configuration config = GetUserConfig(isRoaming); 
            ClientSettingsSection section = GetConfigSection(config, sectionName, true);
 
            if (section != null) { 
                SettingElementCollection sec = section.Settings;
                foreach (DictionaryEntry entry in newSettings) { 
                    SettingElement se = sec.Get((string) entry.Key);

                    if (se == null) {
                        se = new SettingElement(); 
                        se.Name = (string) entry.Key;
                        sec.Add(se); 
                    } 

                    StoredSetting ss = (StoredSetting) entry.Value; 
                    se.SerializeAs = ss.SerializeAs;
                    se.Value.ValueXml = ss.Value;
                }
 
                try {
                    config.Save(); 
                } 
                catch (ConfigurationErrorsException ex) {
                    // We wrap this in an exception with our error message and throw again. 
                    throw new ConfigurationErrorsException(SR.GetString(SR.SettingsSaveFailed, ex.Message), ex);
                }
            }
            else { 
                throw new ConfigurationErrorsException(SR.GetString(SR.SettingsSaveFailedNoSection));
            } 
        } 

        ///  
        ///     A private configuration host that we use to write settings to config. We need this so we
        ///     can enforce a quota on the size of stuff written out.
        /// 
        private sealed class ClientSettingsConfigurationHost : DelegatingConfigHost { 
            private const string ClientConfigurationHostTypeName = "System.Configuration.ClientConfigurationHost," + AssemblyRef.SystemConfiguration;
            private const string InternalConfigConfigurationFactoryTypeName = "System.Configuration.Internal.InternalConfigConfigurationFactory," + AssemblyRef.SystemConfiguration; 
            private static IInternalConfigConfigurationFactory s_configFactory; 

            ///  
            ///     ClientConfigurationHost implements this - a way of getting some info from it without
            ///     depending too much on its internals.
            /// 
            private IInternalConfigClientHost ClientHost { 
                get {
                    return (IInternalConfigClientHost) Host; 
                } 
            }
 
            internal static IInternalConfigConfigurationFactory ConfigFactory {
                get {
                    if (s_configFactory == null) {
                        s_configFactory = (IInternalConfigConfigurationFactory) 
                                            TypeUtil.CreateInstanceWithReflectionPermission(InternalConfigConfigurationFactoryTypeName);
                    } 
                    return s_configFactory; 
                }
            } 

            private ClientSettingsConfigurationHost() {}

            public override void Init(IInternalConfigRoot configRoot, params object[] hostInitParams) { 
                Debug.Fail("Did not expect to get called here");
            } 
 
            /// 
            ///     We delegate this to the ClientConfigurationHost. The only thing we need to do here is to 
            ///     build a configPath from the ConfigurationUserLevel we get passed in.
            /// 
            public override void InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath,
                    IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams) { 

                ConfigurationUserLevel userLevel = (ConfigurationUserLevel) hostInitConfigurationParams[0]; 
                string desiredConfigPath = null; 
                Host = (IInternalConfigHost) TypeUtil.CreateInstanceWithReflectionPermission(ClientConfigurationHostTypeName);
 
                switch (userLevel) {
                    case ConfigurationUserLevel.None:
                        desiredConfigPath = ClientHost.GetExeConfigPath();
                        break; 

                    case ConfigurationUserLevel.PerUserRoaming: 
                        desiredConfigPath = ClientHost.GetRoamingUserConfigPath(); 
                        break;
 
                    case ConfigurationUserLevel.PerUserRoamingAndLocal:
                        desiredConfigPath = ClientHost.GetLocalUserConfigPath();
                        break;
 
                    default:
                        throw new ArgumentException(SR.GetString(SR.UnknownUserLevel)); 
                } 

 
                Host.InitForConfiguration(ref locationSubPath, out configPath, out locationConfigPath, configRoot, null, null, desiredConfigPath);
            }

            private bool IsKnownConfigFile(string filename) { 
                return
                  String.Equals(filename, ConfigurationManagerInternalFactory.Instance.MachineConfigPath, StringComparison.OrdinalIgnoreCase) || 
                  String.Equals(filename, ConfigurationManagerInternalFactory.Instance.ApplicationConfigUri, StringComparison.OrdinalIgnoreCase) || 
                  String.Equals(filename, ConfigurationManagerInternalFactory.Instance.ExeLocalConfigPath, StringComparison.OrdinalIgnoreCase) ||
                  String.Equals(filename, ConfigurationManagerInternalFactory.Instance.ExeRoamingConfigPath, StringComparison.OrdinalIgnoreCase); 

            }

            internal static Configuration OpenExeConfiguration(ConfigurationUserLevel userLevel) { 
                return ConfigFactory.Create(typeof(ClientSettingsConfigurationHost), userLevel);
            } 
 
            /// 
            ///     If the stream we are asked for represents a config file that we know about, we ask 
            ///     the host to assert appropriate permissions.
            /// 
            public override Stream OpenStreamForRead(string streamName) {
                if (IsKnownConfigFile(streamName)) { 
                    return Host.OpenStreamForRead(streamName, true);
                } 
                else { 
                    return Host.OpenStreamForRead(streamName);
                } 
            }

            /// 
            ///     If the stream we are asked for represents a user.config file that we know about, we wrap it in a 
            ///     QuotaEnforcedStream, after asking the host to assert appropriate permissions.///
            ///  
            public override Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext) { 
                Stream stream = null;
 
                if (String.Equals(streamName, ConfigurationManagerInternalFactory.Instance.ExeLocalConfigPath, StringComparison.OrdinalIgnoreCase)) {
                    stream = new QuotaEnforcedStream(
                                   Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext, true),
                                   false); 
                }
                else if (String.Equals(streamName, ConfigurationManagerInternalFactory.Instance.ExeRoamingConfigPath, StringComparison.OrdinalIgnoreCase)) { 
                    stream = new QuotaEnforcedStream( 
                                   Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext, true),
                                   true); 
                }
                else {
                    stream = Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext);
                } 

                return stream; 
            } 

            ///  
            ///     If this is a stream that represents a user.config file that we know about, we ask
            ///     the host to assert appropriate permissions.
            /// 
            public override void WriteCompleted(string streamName, bool success, object writeContext) { 
                if (String.Equals(streamName, ConfigurationManagerInternalFactory.Instance.ExeLocalConfigPath, StringComparison.OrdinalIgnoreCase) ||
                    String.Equals(streamName, ConfigurationManagerInternalFactory.Instance.ExeRoamingConfigPath, StringComparison.OrdinalIgnoreCase)) { 
 
                    Host.WriteCompleted(streamName, success, writeContext, true);
                } 
                else {
                    Host.WriteCompleted(streamName, success, writeContext);
                }
            } 
        }
 
        ///  
        ///     A private stream class that wraps a stream and enforces a quota. The quota enforcement uses
        ///     IsolatedStorageFilePermission. We override nearly all methods on the Stream class so we can 
        ///     forward to the wrapped stream. In the methods that affect stream length, we verify that the
        ///     quota is respected before forwarding.
        /// 
        private sealed class QuotaEnforcedStream : Stream { 
            private Stream _originalStream;
            private bool _isRoaming; 
 
            internal QuotaEnforcedStream(Stream originalStream, bool isRoaming) {
                _originalStream = originalStream; 
                _isRoaming = isRoaming;

                Debug.Assert(_originalStream != null, "originalStream was null.");
            } 

            public override bool CanRead { 
                get { return _originalStream.CanRead; } 
            }
 
            public override bool CanWrite {
                get { return _originalStream.CanWrite; }
            }
 
            public override bool CanSeek {
                get { return _originalStream.CanSeek; } 
            } 

            public override long Length { 
                get { return _originalStream.Length; }
            }

            public override long Position { 

                get { return _originalStream.Position; } 
 
                set {
                    if (value < 0) { 
                        throw new ArgumentOutOfRangeException("value", SR.GetString(SR.PositionOutOfRange));
                    }

                    Seek(value, SeekOrigin.Begin); 
                }
            } 
 
            public override void Close() {
                _originalStream.Close(); 
            }

            protected override void Dispose(bool disposing) {
                if (disposing) { 
                    if (_originalStream != null) {
                        ((IDisposable)_originalStream).Dispose(); 
                        _originalStream = null; 
                    }
 
                }

                base.Dispose(disposing);
            } 

            public override void Flush() { 
                _originalStream.Flush(); 
            }
 
            public override void SetLength(long value) {
                long oldLen = _originalStream.Length;
                long newLen = value;
 
                EnsureQuota(Math.Max(oldLen, newLen));
                _originalStream.SetLength(value); 
            } 

            public override int Read(byte[] buffer, int offset, int count) { 
                return _originalStream.Read(buffer, offset, count);
            }

            public override int ReadByte() { 
                return _originalStream.ReadByte();
            } 
 
            public override long Seek(long offset, SeekOrigin origin) {
                if (!CanSeek) { 
                    throw new NotSupportedException();
                }

                long oldLen = _originalStream.Length; 
                long newLen;
 
                switch (origin) { 
                    case SeekOrigin.Begin:
                        newLen = offset; 
                        break;
                    case SeekOrigin.Current:
                        newLen = _originalStream.Position + offset;
                        break; 
                    case SeekOrigin.End:
                        newLen = oldLen + offset; 
                        break; 
                    default:
                        throw new ArgumentException(SR.GetString(SR.UnknownSeekOrigin), "origin"); 
                }

                EnsureQuota(Math.Max(oldLen, newLen));
                return _originalStream.Seek(offset, origin); 
            }
 
            public override void Write(byte[] buffer, int offset, int count) { 
                if (!CanWrite) {
                    throw new NotSupportedException(); 
                }

                long oldLen = _originalStream.Length;
                long newLen = _originalStream.CanSeek ? _originalStream.Position + (long)count : 
                                                        _originalStream.Length + (long)count;
                EnsureQuota(Math.Max(oldLen, newLen)); 
                _originalStream.Write(buffer, offset, count); 
            }
 
            public override void WriteByte(byte value) {
                if (!CanWrite) {
                    throw new NotSupportedException();
                } 

                long oldLen = _originalStream.Length; 
                long newLen = _originalStream.CanSeek ? _originalStream.Position + 1 : _originalStream.Length + 1; 
                EnsureQuota(Math.Max(oldLen, newLen));
 
                _originalStream.WriteByte(value);
            }

            public override IAsyncResult BeginRead(byte[] buffer, int offset, int numBytes, 
                                                   AsyncCallback userCallback, Object stateObject) {
                return _originalStream.BeginRead(buffer, offset, numBytes, userCallback, stateObject); 
            } 

            public override int EndRead(IAsyncResult asyncResult) { 
                return _originalStream.EndRead(asyncResult);

            }
 
            public override IAsyncResult BeginWrite(byte[] buffer, int offset, int numBytes,
                                                    AsyncCallback userCallback, Object stateObject) { 
                if (!CanWrite) { 
                    throw new NotSupportedException();
                } 

                long oldLen = _originalStream.Length;
                long newLen = _originalStream.CanSeek ? _originalStream.Position + (long)numBytes :
                                                        _originalStream.Length + (long)numBytes; 
                EnsureQuota(Math.Max(oldLen, newLen));
                return _originalStream.BeginWrite(buffer, offset, numBytes, userCallback, stateObject); 
            } 

            public override void EndWrite(IAsyncResult asyncResult) { 
                _originalStream.EndWrite(asyncResult);
            }

            // 
            private void EnsureQuota(long size) {
                IsolatedStoragePermission storagePerm = new IsolatedStorageFilePermission(PermissionState.None); 
                storagePerm.UserQuota = size; 
                storagePerm.UsageAllowed = _isRoaming? IsolatedStorageContainment.DomainIsolationByRoamingUser :
                                                       IsolatedStorageContainment.DomainIsolationByUser; 
                storagePerm.Demand();
            }
        }
    } 

    ///  
    ///     The ClientSettingsStore talks to the LocalFileSettingsProvider through a dictionary which maps from 
    ///     setting names to StoredSetting structs. This struct contains the relevant information.
    ///  
    internal struct StoredSetting {
        internal StoredSetting(SettingsSerializeAs serializeAs, XmlNode value) {
            SerializeAs = serializeAs;
            Value = value; 
        }
        internal SettingsSerializeAs SerializeAs; 
        internal XmlNode Value; 
    }
} 

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

                        

Link Menu

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