The Labs \ Source Viewer \ SSCLI \ System.Configuration \ ClientConfigurationHost

  1. //------------------------------------------------------------------------------
  2. // <copyright file="ClientConfigurationHost.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Configuration
  16. {
  17.     using System.Configuration.Internal;
  18.     using System.IO;
  19.     using System.Security.Policy;
  20.     using System.Security.Permissions;
  21.     using System.Reflection;
  22.     using System.Threading;
  23.     using System.Security;
  24.     using System.Net;
  25.     using System.Security.Principal;
  26.    
  27.     internal sealed class ClientConfigurationHost : DelegatingConfigHost, IInternalConfigClientHost
  28.     {
  29.         internal const string MachineConfigName = "MACHINE";
  30.         internal const string ExeConfigName = "EXE";
  31.         internal const string RoamingUserConfigName = "ROAMING_USER";
  32.         internal const string LocalUserConfigName = "LOCAL_USER";
  33.        
  34.         internal const string MachineConfigPath = MachineConfigName;
  35.         internal const string ExeConfigPath = MachineConfigPath + "/" + ExeConfigName;
  36.         internal const string RoamingUserConfigPath = ExeConfigPath + "/" + RoamingUserConfigName;
  37.         internal const string LocalUserConfigPath = RoamingUserConfigPath + "/" + LocalUserConfigName;
  38.        
  39.         private const string ConfigExtension = ".config";
  40.         private const string MachineConfigFilename = "machine.config";
  41.         private const string MachineConfigSubdirectory = "Config";
  42.        
  43.         private static object s_init = new object();
  44.         private static object s_version = new object();
  45.         private static string s_machineConfigFilePath;
  46.        
  47.         private string _exePath;
  48.         // the physical path to the exe being configured
  49.         private ClientConfigPaths _configPaths;
  50.         // physical paths to client config files
  51.         private ExeConfigurationFileMap _fileMap;
  52.         // optional file map
  53.         private bool _initComplete;
  54.        
  55.         internal ClientConfigurationHost()
  56.         {
  57.             Host = new InternalConfigHost();
  58.         }
  59.        
  60.         internal ClientConfigPaths ConfigPaths {
  61.             get {
  62.                 if (_configPaths == null) {
  63.                     _configPaths = ClientConfigPaths.GetPaths(_exePath, _initComplete);
  64.                 }
  65.                
  66.                 return _configPaths;
  67.             }
  68.         }
  69.        
  70.         internal void RefreshConfigPaths()
  71.         {
  72.             // Refresh current config paths.
  73.             if (_configPaths != null && !_configPaths.HasEntryAssembly && _exePath == null) {
  74.                 ClientConfigPaths.RefreshCurrent();
  75.                 _configPaths = null;
  76.             }
  77.         }
  78.        
  79.         static internal string MachineConfigFilePath {
  80.             [FileIOPermissionAttribute(SecurityAction.Assert, AllFiles = FileIOPermissionAccess.PathDiscovery)]
  81.             get {
  82.                 if (s_machineConfigFilePath == null) {
  83.                     string directory = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
  84.                     s_machineConfigFilePath = Path.Combine(Path.Combine(directory, MachineConfigSubdirectory), MachineConfigFilename);
  85.                 }
  86.                
  87.                 return s_machineConfigFilePath;
  88.             }
  89.         }
  90.        
  91.         internal bool HasRoamingConfig {
  92.             get {
  93.                 if (_fileMap != null) {
  94.                     return !String.IsNullOrEmpty(_fileMap.RoamingUserConfigFilename);
  95.                 }
  96.                 else {
  97.                     return ConfigPaths.HasRoamingConfig;
  98.                 }
  99.             }
  100.         }
  101.        
  102.         internal bool HasLocalConfig {
  103.             get {
  104.                 if (_fileMap != null) {
  105.                     return !String.IsNullOrEmpty(_fileMap.LocalUserConfigFilename);
  106.                 }
  107.                 else {
  108.                     return ConfigPaths.HasLocalConfig;
  109.                 }
  110.             }
  111.         }
  112.        
  113.         internal bool IsAppConfigHttp {
  114.             get { return !IsFile(GetStreamName(ExeConfigPath)); }
  115.         }
  116.        
  117.         // IInternalConfigClientHost methods are used by Venus and Whitehorse
  118.         // so as not to require explicit knowledge of the contents of the
  119.         // config path.
  120.        
  121.         // return true if the config path is for an exe config, false otherwise.
  122.         bool IInternalConfigClientHost.IsExeConfig(string configPath)
  123.         {
  124.             return StringUtil.EqualsIgnoreCase(configPath, ExeConfigPath);
  125.         }
  126.        
  127.         bool IInternalConfigClientHost.IsRoamingUserConfig(string configPath)
  128.         {
  129.             return StringUtil.EqualsIgnoreCase(configPath, RoamingUserConfigPath);
  130.         }
  131.        
  132.         bool IInternalConfigClientHost.IsLocalUserConfig(string configPath)
  133.         {
  134.             return StringUtil.EqualsIgnoreCase(configPath, LocalUserConfigPath);
  135.         }
  136.        
  137.         // Return true if the config path is for a user.config file, false otherwise.
  138.         private bool IsUserConfig(string configPath)
  139.         {
  140.             return StringUtil.EqualsIgnoreCase(configPath, RoamingUserConfigPath) || StringUtil.EqualsIgnoreCase(configPath, LocalUserConfigPath);
  141.         }
  142.        
  143.         string IInternalConfigClientHost.GetExeConfigPath()
  144.         {
  145.             return ExeConfigPath;
  146.         }
  147.        
  148.         string IInternalConfigClientHost.GetRoamingUserConfigPath()
  149.         {
  150.             return RoamingUserConfigPath;
  151.         }
  152.        
  153.         string IInternalConfigClientHost.GetLocalUserConfigPath()
  154.         {
  155.             return LocalUserConfigPath;
  156.         }
  157.        
  158.         public override void Init(IInternalConfigRoot configRoot, params object[] hostInitParams)
  159.         {
  160.             try {
  161.                 ConfigurationFileMap fileMap = (ConfigurationFileMap)hostInitParams[0];
  162.                 _exePath = (string)hostInitParams[1];
  163.                
  164.                 Host.Init(configRoot, hostInitParams);
  165.                
  166.                 // Do not complete initialization in runtime config, to avoid expense of
  167.                 // loading user.config files that may not be required.
  168.                 _initComplete = configRoot.IsDesignTime;
  169.                
  170.                 if (fileMap != null && !String.IsNullOrEmpty(_exePath)) {
  171.                     throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Init");
  172.                 }
  173.                
  174.                 if (String.IsNullOrEmpty(_exePath)) {
  175.                     _exePath = null;
  176.                 }
  177.                
  178.                 // Initialize the fileMap, if provided.
  179.                 if (fileMap != null) {
  180.                     _fileMap = new ExeConfigurationFileMap();
  181.                     if (!String.IsNullOrEmpty(fileMap.MachineConfigFilename)) {
  182.                         _fileMap.MachineConfigFilename = Path.GetFullPath(fileMap.MachineConfigFilename);
  183.                     }
  184.                    
  185.                     ExeConfigurationFileMap exeFileMap = fileMap as ExeConfigurationFileMap;
  186.                     if (exeFileMap != null) {
  187.                         if (!String.IsNullOrEmpty(exeFileMap.ExeConfigFilename)) {
  188.                             _fileMap.ExeConfigFilename = Path.GetFullPath(exeFileMap.ExeConfigFilename);
  189.                         }
  190.                        
  191.                         if (!String.IsNullOrEmpty(exeFileMap.RoamingUserConfigFilename)) {
  192.                             _fileMap.RoamingUserConfigFilename = Path.GetFullPath(exeFileMap.RoamingUserConfigFilename);
  193.                         }
  194.                        
  195.                         if (!String.IsNullOrEmpty(exeFileMap.LocalUserConfigFilename)) {
  196.                             _fileMap.LocalUserConfigFilename = Path.GetFullPath(exeFileMap.LocalUserConfigFilename);
  197.                         }
  198.                     }
  199.                 }
  200.             }
  201.             catch (SecurityException) {
  202.                 // Lets try to give them some information telling them
  203.                 // they don't have enough security privileges
  204.                 throw new ConfigurationErrorsException(SR.GetString(SR.Config_client_config_init_security));
  205.             }
  206.             catch {
  207.                 throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Init");
  208.             }
  209.         }
  210.        
  211.         public override void InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath, IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams)
  212.         {
  213.            
  214.             locationSubPath = null;
  215.             configPath = (string)hostInitConfigurationParams[2];
  216.             locationConfigPath = null;
  217.            
  218.             Init(configRoot, hostInitConfigurationParams);
  219.         }
  220.        
  221.         // Delay init if we have not been asked to complete init, and it is a user.config file.
  222.         public override bool IsInitDelayed(IInternalConfigRecord configRecord)
  223.         {
  224.             return !_initComplete && IsUserConfig(configRecord.ConfigPath);
  225.         }
  226.        
  227.         public override void RequireCompleteInit(IInternalConfigRecord record)
  228.         {
  229.             // Loading information about user.config files is expensive,
  230.             // so do it just once by locking.
  231.             lock (this) {
  232.                 if (!_initComplete) {
  233.                     // Note that all future requests for config must be complete.
  234.                     _initComplete = true;
  235.                    
  236.                     // Throw out the ConfigPath for this exe.
  237.                     ClientConfigPaths.RefreshCurrent();
  238.                    
  239.                     // Throw out our cached copy.
  240.                     _configPaths = null;
  241.                    
  242.                     // Force loading of user.config file information under lock.
  243.                     ClientConfigPaths configPaths = ConfigPaths;
  244.                 }
  245.             }
  246.         }
  247.        
  248.         // config path support
  249.         public override bool IsConfigRecordRequired(string configPath)
  250.         {
  251.             string configName = ConfigPathUtility.GetName(configPath);
  252.             switch (configName) {
  253.                 default:
  254.                     // should never get here
  255.                     return false;
  256.                 case MachineConfigName:
  257.                 case ExeConfigName:
  258.                    
  259.                     return true;
  260.                 case RoamingUserConfigName:
  261.                    
  262.                     // Makes the design easier even if we only have an empty Roaming config record.
  263.                     return HasRoamingConfig || HasLocalConfig;
  264.                 case LocalUserConfigName:
  265.                    
  266.                     return HasLocalConfig;
  267.             }
  268.         }
  269.        
  270.         // stream support
  271.         public override string GetStreamName(string configPath)
  272.         {
  273.             string configName = ConfigPathUtility.GetName(configPath);
  274.             if (_fileMap != null) {
  275.                 switch (configName) {
  276.                     default:
  277.                         // should never get here
  278.                         goto case MachineConfigName;
  279.                         break;
  280.                     case MachineConfigName:
  281.                        
  282.                         return _fileMap.MachineConfigFilename;
  283.                     case ExeConfigName:
  284.                        
  285.                         return _fileMap.ExeConfigFilename;
  286.                     case RoamingUserConfigName:
  287.                        
  288.                         return _fileMap.RoamingUserConfigFilename;
  289.                     case LocalUserConfigName:
  290.                        
  291.                         return _fileMap.LocalUserConfigFilename;
  292.                 }
  293.             }
  294.             else {
  295.                 switch (configName) {
  296.                     default:
  297.                         // should never get here
  298.                         goto case MachineConfigName;
  299.                         break;
  300.                     case MachineConfigName:
  301.                        
  302.                         return MachineConfigFilePath;
  303.                     case ExeConfigName:
  304.                        
  305.                         return ConfigPaths.ApplicationConfigUri;
  306.                     case RoamingUserConfigName:
  307.                        
  308.                         return ConfigPaths.RoamingConfigFilename;
  309.                     case LocalUserConfigName:
  310.                        
  311.                         return ConfigPaths.LocalConfigFilename;
  312.                 }
  313.             }
  314.         }
  315.        
  316.         public override string GetStreamNameForConfigSource(string streamName, string configSource)
  317.         {
  318.             if (IsFile(streamName)) {
  319.                 return Host.GetStreamNameForConfigSource(streamName, configSource);
  320.             }
  321.            
  322.             int index = streamName.LastIndexOf('/');
  323.             if (index < 0)
  324.                 return null;
  325.            
  326.             string parentUri = streamName.Substring(0, index + 1);
  327.             string result = parentUri + configSource.Replace('\\', '/');
  328.            
  329.             return result;
  330.         }
  331.        
  332.         public override object GetStreamVersion(string streamName)
  333.         {
  334.             if (IsFile(streamName)) {
  335.                 return Host.GetStreamVersion(streamName);
  336.             }
  337.            
  338.             // assume it is the same
  339.             return s_version;
  340.         }
  341.        
  342.        
  343.         // default impl treats name as a file name
  344.         // null means stream doesn't exist for this name
  345.         public override Stream OpenStreamForRead(string streamName)
  346.         {
  347.             // the streamName can either be a file name, or a URI
  348.             if (IsFile(streamName)) {
  349.                 return Host.OpenStreamForRead(streamName);
  350.             }
  351.            
  352.             if (streamName == null) {
  353.                 return null;
  354.             }
  355.            
  356.             // scheme is http
  357.             WebClient client = new WebClient();
  358.            
  359.             // Try using default credentials
  360.             try {
  361.                 client.Credentials = CredentialCache.DefaultCredentials;
  362.             }
  363.             catch {
  364.             }
  365.            
  366.             byte[] fileData = null;
  367.             try {
  368.                 fileData = client.DownloadData(streamName);
  369.             }
  370.             catch {
  371.             }
  372.            
  373.             if (fileData == null) {
  374.                 return null;
  375.             }
  376.            
  377.             MemoryStream stream = new MemoryStream(fileData);
  378.             return stream;
  379.         }
  380.        
  381.         public override Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext)
  382.         {
  383.             // only support files, not URIs
  384.             if (!IsFile(streamName)) {
  385.                 throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::OpenStreamForWrite");
  386.             }
  387.            
  388.             return Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext);
  389.         }
  390.        
  391.         public override void DeleteStream(string streamName)
  392.         {
  393.             // only support files, not URIs
  394.             if (!IsFile(streamName)) {
  395.                 throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Delete");
  396.             }
  397.            
  398.             Host.DeleteStream(streamName);
  399.         }
  400.        
  401.         // RefreshConfig support - runtime only
  402.         public override bool SupportsRefresh {
  403.             get { return true; }
  404.         }
  405.        
  406.         // path support
  407.         public override bool SupportsPath {
  408.             get { return false; }
  409.         }
  410.        
  411.         // Do we support location tags?
  412.         public override bool SupportsLocation {
  413.             get { return false; }
  414.         }
  415.        
  416.         public override bool IsDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition, ConfigurationAllowExeDefinition allowExeDefinition)
  417.         {
  418.             string allowedConfigPath;
  419.            
  420.             switch (allowExeDefinition) {
  421.                 case ConfigurationAllowExeDefinition.MachineOnly:
  422.                     allowedConfigPath = MachineConfigPath;
  423.                     break;
  424.                 case ConfigurationAllowExeDefinition.MachineToApplication:
  425.                    
  426.                     allowedConfigPath = ExeConfigPath;
  427.                     break;
  428.                 case ConfigurationAllowExeDefinition.MachineToRoamingUser:
  429.                    
  430.                     allowedConfigPath = RoamingUserConfigPath;
  431.                     break;
  432.                 case ConfigurationAllowExeDefinition.MachineToLocalUser:
  433.                    
  434.                     // MachineToLocalUser does not current have any definition restrictions
  435.                     return true;
  436.                 default:
  437.                    
  438.                     // If we have extended ConfigurationAllowExeDefinition
  439.                     // make sure to update this switch accordingly
  440.                     throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::IsDefinitionAllowed");
  441.                     break;
  442.             }
  443.            
  444.             return configPath.Length <= allowedConfigPath.Length;
  445.         }
  446.        
  447.         public override void VerifyDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition, ConfigurationAllowExeDefinition allowExeDefinition, IConfigErrorInfo errorInfo)
  448.         {
  449.             if (!IsDefinitionAllowed(configPath, allowDefinition, allowExeDefinition)) {
  450.                 switch (allowExeDefinition) {
  451.                     case ConfigurationAllowExeDefinition.MachineOnly:
  452.                         throw new ConfigurationErrorsException(SR.GetString(SR.Config_allow_exedefinition_error_machine), errorInfo);
  453.                         break;
  454.                     case ConfigurationAllowExeDefinition.MachineToApplication:
  455.                        
  456.                         throw new ConfigurationErrorsException(SR.GetString(SR.Config_allow_exedefinition_error_application), errorInfo);
  457.                         break;
  458.                     case ConfigurationAllowExeDefinition.MachineToRoamingUser:
  459.                        
  460.                         throw new ConfigurationErrorsException(SR.GetString(SR.Config_allow_exedefinition_error_roaminguser), errorInfo);
  461.                         break;
  462.                     default:
  463.                        
  464.                         // If we have extended ConfigurationAllowExeDefinition
  465.                         // make sure to update this switch accordingly
  466.                         throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::VerifyDefinitionAllowed");
  467.                         break;
  468.                 }
  469.             }
  470.         }
  471.        
  472.         // prefetch support
  473.         public override bool PrefetchAll(string configPath, string streamName)
  474.         {
  475.             // If it's a file, we don't need to. Otherwise (e.g. it's from the web), we'll prefetch everything.
  476.             return !IsFile(streamName);
  477.         }
  478.        
  479.         public override bool PrefetchSection(string sectionGroupName, string sectionName)
  480.         {
  481.             return sectionGroupName == "system.net";
  482.         }
  483.        
  484.         // we trust machine.config - admins settings do not have security restrictions.
  485.         public override bool IsTrustedConfigPath(string configPath)
  486.         {
  487.             return configPath == MachineConfigPath;
  488.         }
  489.        
  490.         [SecurityPermission(SecurityAction.Assert, ControlEvidence = true)]
  491.         public override void GetRestrictedPermissions(IInternalConfigRecord configRecord, out PermissionSet permissionSet, out bool isHostReady)
  492.         {
  493.             // Get the stream name as a URL
  494.             string url;
  495.             bool isFile = IsFile(configRecord.StreamName);
  496.             if (isFile) {
  497.                 url = UrlPath.ConvertFileNameToUrl(configRecord.StreamName);
  498.             }
  499.             else {
  500.                 url = configRecord.StreamName;
  501.             }
  502.            
  503.             Evidence evidence = new Evidence();
  504.            
  505.             // Add Url evidence, which is simply the URL.
  506.             evidence.AddHost(new Url(url));
  507.            
  508.             // Add Zone evidence - My Computer, Intranet, Internet, etc.
  509.             evidence.AddHost(Zone.CreateFromUrl(url));
  510.            
  511.             // Add Site evidence if the url is http.
  512.             if (!isFile) {
  513.                 evidence.AddHost(Site.CreateFromUrl(url));
  514.             }
  515.            
  516.             // Get the resulting permission set.
  517.             permissionSet = SecurityManager.ResolvePolicy(evidence);
  518.            
  519.             // Client host is always ready to return permissions.
  520.             isHostReady = true;
  521.         }
  522.        
  523.         //
  524.         // Impersonate for Client Config
  525.         // Use the process identity
  526.         //
  527.         [SecurityPermissionAttribute(SecurityAction.Assert, Flags = SecurityPermissionFlag.ControlPrincipal)]
  528.         public override IDisposable Impersonate()
  529.         {
  530.             return null;
  531.         }
  532.        
  533.         // context support
  534.         public override object CreateDeprecatedConfigContext(string configPath)
  535.         {
  536.             return null;
  537.         }
  538.        
  539.         // CreateConfigurationContext
  540.         //
  541.         // Create the new context
  542.         //
  543.         public override object CreateConfigurationContext(string configPath, string locationSubPath)
  544.         {
  545.             return new ExeContext(GetUserLevel(configPath), ConfigPaths.ApplicationUri);
  546.         }
  547.        
  548.         // GetUserLevel
  549.         //
  550.         // Given a configPath, determine what the user level is?
  551.         //
  552.         private ConfigurationUserLevel GetUserLevel(string configPath)
  553.         {
  554.             ConfigurationUserLevel level;
  555.            
  556.             switch (ConfigPathUtility.GetName(configPath)) {
  557.                 case MachineConfigName:
  558.                     // Machine Level
  559.                     level = ConfigurationUserLevel.None;
  560.                     break;
  561.                 case ExeConfigName:
  562.                    
  563.                     // Exe Level
  564.                     level = ConfigurationUserLevel.None;
  565.                     break;
  566.                 case LocalUserConfigName:
  567.                    
  568.                     // User Level
  569.                     level = ConfigurationUserLevel.PerUserRoamingAndLocal;
  570.                     break;
  571.                 case RoamingUserConfigName:
  572.                    
  573.                     // Roaming Level
  574.                     level = ConfigurationUserLevel.PerUserRoaming;
  575.                     break;
  576.                 default:
  577.                    
  578.                     Debug.Fail("unrecognized configPath " + configPath);
  579.                     level = ConfigurationUserLevel.None;
  580.                     break;
  581.             }
  582.            
  583.             return level;
  584.         }
  585.        
  586.         //
  587.         // Create a Configuration object.
  588.         //
  589.         static internal Configuration OpenExeConfiguration(ConfigurationFileMap fileMap, bool isMachine, ConfigurationUserLevel userLevel, string exePath)
  590.         {
  591.             // validate userLevel argument
  592.             switch (userLevel) {
  593.                 default:
  594.                     throw ExceptionUtil.ParameterInvalid("userLevel");
  595.                     break;
  596.                 case ConfigurationUserLevel.None:
  597.                 case ConfigurationUserLevel.PerUserRoaming:
  598.                 case ConfigurationUserLevel.PerUserRoamingAndLocal:
  599.                    
  600.                     break;
  601.             }
  602.            
  603.             // validate fileMap arguments
  604.             if (fileMap != null) {
  605.                 if (String.IsNullOrEmpty(fileMap.MachineConfigFilename)) {
  606.                     throw ExceptionUtil.ParameterNullOrEmpty("fileMap.MachineConfigFilename");
  607.                 }
  608.                
  609.                 ExeConfigurationFileMap exeFileMap = fileMap as ExeConfigurationFileMap;
  610.                 if (exeFileMap != null) {
  611.                     switch (userLevel) {
  612.                         case ConfigurationUserLevel.None:
  613.                             if (String.IsNullOrEmpty(exeFileMap.ExeConfigFilename)) {
  614.                                 throw ExceptionUtil.ParameterNullOrEmpty("fileMap.ExeConfigFilename");
  615.                             }
  616.                            
  617.                             break;
  618.                         case ConfigurationUserLevel.PerUserRoaming:
  619.                            
  620.                             if (String.IsNullOrEmpty(exeFileMap.RoamingUserConfigFilename)) {
  621.                                 throw ExceptionUtil.ParameterNullOrEmpty("fileMap.RoamingUserConfigFilename");
  622.                             }
  623.                            
  624.                             goto case ConfigurationUserLevel.None;
  625.                             break;
  626.                         case ConfigurationUserLevel.PerUserRoamingAndLocal:
  627.                            
  628.                             if (String.IsNullOrEmpty(exeFileMap.LocalUserConfigFilename)) {
  629.                                 throw ExceptionUtil.ParameterNullOrEmpty("fileMap.LocalUserConfigFilename");
  630.                             }
  631.                            
  632.                             goto case ConfigurationUserLevel.PerUserRoaming;
  633.                             break;
  634.                     }
  635.                 }
  636.             }
  637.            
  638.             string configPath = null;
  639.             if (isMachine) {
  640.                 configPath = MachineConfigPath;
  641.             }
  642.             else {
  643.                 switch (userLevel) {
  644.                     case ConfigurationUserLevel.None:
  645.                         configPath = ExeConfigPath;
  646.                         break;
  647.                     case ConfigurationUserLevel.PerUserRoaming:
  648.                        
  649.                         configPath = RoamingUserConfigPath;
  650.                         break;
  651.                     case ConfigurationUserLevel.PerUserRoamingAndLocal:
  652.                        
  653.                         configPath = LocalUserConfigPath;
  654.                         break;
  655.                 }
  656.             }
  657.            
  658.             Configuration configuration = new Configuration(null, typeof(ClientConfigurationHost), fileMap, exePath, configPath);
  659.            
  660.             return configuration;
  661.         }
  662.     }
  663. }

Developer Fusion