625 lines
24 KiB
C#
625 lines
24 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <copyright file="ClientConfigurationHost.cs" company="Microsoft">
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// </copyright>
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.Configuration {
|
||
|
using System.Configuration.Internal;
|
||
|
using System.IO;
|
||
|
using System.Security.Policy;
|
||
|
using System.Security.Permissions;
|
||
|
using System.Reflection;
|
||
|
using System.Threading;
|
||
|
using System.Security;
|
||
|
using System.Net;
|
||
|
using System.Security.Principal;
|
||
|
using System.Diagnostics.CodeAnalysis;
|
||
|
|
||
|
internal sealed class ClientConfigurationHost : DelegatingConfigHost, IInternalConfigClientHost {
|
||
|
internal const string MachineConfigName = "MACHINE";
|
||
|
internal const string ExeConfigName = "EXE";
|
||
|
internal const string RoamingUserConfigName = "ROAMING_USER";
|
||
|
internal const string LocalUserConfigName = "LOCAL_USER";
|
||
|
|
||
|
internal const string MachineConfigPath = MachineConfigName;
|
||
|
internal const string ExeConfigPath = MachineConfigPath + "/" + ExeConfigName;
|
||
|
internal const string RoamingUserConfigPath = ExeConfigPath + "/" + RoamingUserConfigName;
|
||
|
internal const string LocalUserConfigPath = RoamingUserConfigPath + "/" + LocalUserConfigName;
|
||
|
|
||
|
private const string ConfigExtension = ".config";
|
||
|
private const string MachineConfigFilename = "machine.config";
|
||
|
private const string MachineConfigSubdirectory = "Config";
|
||
|
|
||
|
private static object s_init = new object();
|
||
|
private static object s_version = new object();
|
||
|
private static volatile string s_machineConfigFilePath;
|
||
|
|
||
|
private string _exePath; // the physical path to the exe being configured
|
||
|
private ClientConfigPaths _configPaths; // physical paths to client config files
|
||
|
private ExeConfigurationFileMap _fileMap; // optional file map
|
||
|
private bool _initComplete;
|
||
|
|
||
|
internal ClientConfigurationHost() {
|
||
|
Host = new InternalConfigHost();
|
||
|
}
|
||
|
|
||
|
internal ClientConfigPaths ConfigPaths {
|
||
|
get {
|
||
|
if (_configPaths == null) {
|
||
|
_configPaths = ClientConfigPaths.GetPaths(_exePath, _initComplete);
|
||
|
}
|
||
|
|
||
|
return _configPaths;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void RefreshConfigPaths() {
|
||
|
// Refresh current config paths.
|
||
|
if (_configPaths != null && !_configPaths.HasEntryAssembly && _exePath == null) {
|
||
|
ClientConfigPaths.RefreshCurrent();
|
||
|
_configPaths = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static internal string MachineConfigFilePath {
|
||
|
[FileIOPermissionAttribute(SecurityAction.Assert, AllFiles = FileIOPermissionAccess.PathDiscovery)]
|
||
|
[SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts", Justification = "The callers do not expose this information without performing the appropriate demands themselves.")]
|
||
|
get {
|
||
|
if (s_machineConfigFilePath == null) {
|
||
|
string directory = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
|
||
|
s_machineConfigFilePath = Path.Combine(Path.Combine(directory, MachineConfigSubdirectory), MachineConfigFilename);
|
||
|
}
|
||
|
|
||
|
return s_machineConfigFilePath;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool HasRoamingConfig {
|
||
|
get {
|
||
|
if (_fileMap != null) {
|
||
|
return !String.IsNullOrEmpty(_fileMap.RoamingUserConfigFilename);
|
||
|
}
|
||
|
else {
|
||
|
return ConfigPaths.HasRoamingConfig;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool HasLocalConfig {
|
||
|
get {
|
||
|
if (_fileMap != null) {
|
||
|
return !String.IsNullOrEmpty(_fileMap.LocalUserConfigFilename);
|
||
|
}
|
||
|
else {
|
||
|
return ConfigPaths.HasLocalConfig;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal bool IsAppConfigHttp {
|
||
|
get {
|
||
|
return !IsFile(GetStreamName(ExeConfigPath));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// IInternalConfigClientHost methods are used by Venus and Whitehorse
|
||
|
// so as not to require explicit knowledge of the contents of the
|
||
|
// config path.
|
||
|
|
||
|
// return true if the config path is for an exe config, false otherwise.
|
||
|
bool IInternalConfigClientHost.IsExeConfig(string configPath) {
|
||
|
return StringUtil.EqualsIgnoreCase(configPath, ExeConfigPath);
|
||
|
}
|
||
|
|
||
|
bool IInternalConfigClientHost.IsRoamingUserConfig(string configPath) {
|
||
|
return StringUtil.EqualsIgnoreCase(configPath, RoamingUserConfigPath);
|
||
|
}
|
||
|
|
||
|
bool IInternalConfigClientHost.IsLocalUserConfig(string configPath) {
|
||
|
return StringUtil.EqualsIgnoreCase(configPath, LocalUserConfigPath);
|
||
|
}
|
||
|
|
||
|
// Return true if the config path is for a user.config file, false otherwise.
|
||
|
private bool IsUserConfig(string configPath) {
|
||
|
return StringUtil.EqualsIgnoreCase(configPath, RoamingUserConfigPath) ||
|
||
|
StringUtil.EqualsIgnoreCase(configPath, LocalUserConfigPath);
|
||
|
}
|
||
|
|
||
|
string IInternalConfigClientHost.GetExeConfigPath() {
|
||
|
return ExeConfigPath;
|
||
|
}
|
||
|
|
||
|
string IInternalConfigClientHost.GetRoamingUserConfigPath() {
|
||
|
return RoamingUserConfigPath;
|
||
|
}
|
||
|
|
||
|
string IInternalConfigClientHost.GetLocalUserConfigPath() {
|
||
|
return LocalUserConfigPath;
|
||
|
}
|
||
|
|
||
|
public override void Init(IInternalConfigRoot configRoot, params object[] hostInitParams) {
|
||
|
try {
|
||
|
ConfigurationFileMap fileMap = (ConfigurationFileMap) hostInitParams[0];
|
||
|
_exePath = (string) hostInitParams[1];
|
||
|
|
||
|
Host.Init(configRoot, hostInitParams);
|
||
|
|
||
|
// Do not complete initialization in runtime config, to avoid expense of
|
||
|
// loading user.config files that may not be required.
|
||
|
_initComplete = configRoot.IsDesignTime;
|
||
|
|
||
|
if (fileMap != null && !String.IsNullOrEmpty(_exePath)) {
|
||
|
throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Init");
|
||
|
}
|
||
|
|
||
|
if (String.IsNullOrEmpty(_exePath)) {
|
||
|
_exePath = null;
|
||
|
}
|
||
|
|
||
|
// Initialize the fileMap, if provided.
|
||
|
if (fileMap != null) {
|
||
|
_fileMap = new ExeConfigurationFileMap();
|
||
|
if (!String.IsNullOrEmpty(fileMap.MachineConfigFilename)) {
|
||
|
_fileMap.MachineConfigFilename = Path.GetFullPath(fileMap.MachineConfigFilename);
|
||
|
}
|
||
|
|
||
|
ExeConfigurationFileMap exeFileMap = fileMap as ExeConfigurationFileMap;
|
||
|
if (exeFileMap != null) {
|
||
|
if (!String.IsNullOrEmpty(exeFileMap.ExeConfigFilename)) {
|
||
|
_fileMap.ExeConfigFilename = Path.GetFullPath(exeFileMap.ExeConfigFilename);
|
||
|
}
|
||
|
|
||
|
if (!String.IsNullOrEmpty(exeFileMap.RoamingUserConfigFilename)) {
|
||
|
_fileMap.RoamingUserConfigFilename = Path.GetFullPath(exeFileMap.RoamingUserConfigFilename);
|
||
|
}
|
||
|
|
||
|
if (!String.IsNullOrEmpty(exeFileMap.LocalUserConfigFilename)) {
|
||
|
_fileMap.LocalUserConfigFilename = Path.GetFullPath(exeFileMap.LocalUserConfigFilename);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
catch (SecurityException) {
|
||
|
// Lets try to give them some information telling them
|
||
|
// they don't have enough security privileges
|
||
|
throw new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.Config_client_config_init_security));
|
||
|
}
|
||
|
catch {
|
||
|
throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Init");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void InitForConfiguration(ref string locationSubPath, out string configPath, out string locationConfigPath,
|
||
|
IInternalConfigRoot configRoot, params object[] hostInitConfigurationParams) {
|
||
|
|
||
|
locationSubPath = null;
|
||
|
configPath = (string) hostInitConfigurationParams[2];
|
||
|
locationConfigPath = null;
|
||
|
|
||
|
Init(configRoot, hostInitConfigurationParams);
|
||
|
}
|
||
|
|
||
|
// Delay init if we have not been asked to complete init, and it is a user.config file.
|
||
|
public override bool IsInitDelayed(IInternalConfigRecord configRecord) {
|
||
|
return !_initComplete && IsUserConfig(configRecord.ConfigPath);
|
||
|
}
|
||
|
|
||
|
public override void RequireCompleteInit(IInternalConfigRecord record) {
|
||
|
// Loading information about user.config files is expensive,
|
||
|
// so do it just once by locking.
|
||
|
lock (this) {
|
||
|
if (!_initComplete) {
|
||
|
// Note that all future requests for config must be complete.
|
||
|
_initComplete = true;
|
||
|
|
||
|
// Throw out the ConfigPath for this exe.
|
||
|
ClientConfigPaths.RefreshCurrent();
|
||
|
|
||
|
// Throw out our cached copy.
|
||
|
_configPaths = null;
|
||
|
|
||
|
// Force loading of user.config file information under lock.
|
||
|
ClientConfigPaths configPaths = ConfigPaths;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// config path support
|
||
|
public override bool IsConfigRecordRequired(string configPath) {
|
||
|
string configName = ConfigPathUtility.GetName(configPath);
|
||
|
switch (configName) {
|
||
|
default:
|
||
|
// should never get here
|
||
|
return false;
|
||
|
|
||
|
case MachineConfigName:
|
||
|
case ExeConfigName:
|
||
|
return true;
|
||
|
|
||
|
case RoamingUserConfigName:
|
||
|
// Makes the design easier even if we only have an empty Roaming config record.
|
||
|
return HasRoamingConfig || HasLocalConfig;
|
||
|
|
||
|
case LocalUserConfigName:
|
||
|
return HasLocalConfig;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// stream support
|
||
|
public override string GetStreamName(string configPath) {
|
||
|
string configName = ConfigPathUtility.GetName(configPath);
|
||
|
if (_fileMap != null) {
|
||
|
switch (configName) {
|
||
|
default:
|
||
|
// should never get here
|
||
|
goto case MachineConfigName;
|
||
|
|
||
|
case MachineConfigName:
|
||
|
return _fileMap.MachineConfigFilename;
|
||
|
|
||
|
case ExeConfigName:
|
||
|
return _fileMap.ExeConfigFilename;
|
||
|
|
||
|
case RoamingUserConfigName:
|
||
|
return _fileMap.RoamingUserConfigFilename;
|
||
|
|
||
|
case LocalUserConfigName:
|
||
|
return _fileMap.LocalUserConfigFilename;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
switch (configName) {
|
||
|
default:
|
||
|
// should never get here
|
||
|
goto case MachineConfigName;
|
||
|
|
||
|
case MachineConfigName:
|
||
|
return MachineConfigFilePath;
|
||
|
|
||
|
case ExeConfigName:
|
||
|
return ConfigPaths.ApplicationConfigUri;
|
||
|
|
||
|
case RoamingUserConfigName:
|
||
|
return ConfigPaths.RoamingConfigFilename;
|
||
|
|
||
|
case LocalUserConfigName:
|
||
|
return ConfigPaths.LocalConfigFilename;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override string GetStreamNameForConfigSource(string streamName, string configSource) {
|
||
|
if (IsFile(streamName)) {
|
||
|
return Host.GetStreamNameForConfigSource(streamName, configSource);
|
||
|
}
|
||
|
|
||
|
int index = streamName.LastIndexOf('/');
|
||
|
if (index < 0)
|
||
|
return null;
|
||
|
|
||
|
string parentUri = streamName.Substring(0, index + 1);
|
||
|
string result = parentUri + configSource.Replace('\\', '/');
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
public override object GetStreamVersion(string streamName) {
|
||
|
if (IsFile(streamName)) {
|
||
|
return Host.GetStreamVersion(streamName);
|
||
|
}
|
||
|
|
||
|
// assume it is the same
|
||
|
return s_version;
|
||
|
}
|
||
|
|
||
|
|
||
|
// default impl treats name as a file name
|
||
|
// null means stream doesn't exist for this name
|
||
|
public override Stream OpenStreamForRead(string streamName) {
|
||
|
// the streamName can either be a file name, or a URI
|
||
|
if (IsFile(streamName)) {
|
||
|
return Host.OpenStreamForRead(streamName);
|
||
|
}
|
||
|
|
||
|
if (streamName == null) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// scheme is http
|
||
|
WebClient client = new WebClient();
|
||
|
|
||
|
// Try using default credentials
|
||
|
try {
|
||
|
client.Credentials = CredentialCache.DefaultCredentials;
|
||
|
}
|
||
|
catch {
|
||
|
}
|
||
|
|
||
|
byte[] fileData = null;
|
||
|
try {
|
||
|
fileData = client.DownloadData(streamName);
|
||
|
}
|
||
|
catch {
|
||
|
}
|
||
|
|
||
|
if (fileData == null) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
MemoryStream stream = new MemoryStream(fileData);
|
||
|
return stream;
|
||
|
}
|
||
|
|
||
|
public override Stream OpenStreamForWrite(string streamName, string templateStreamName, ref object writeContext) {
|
||
|
// only support files, not URIs
|
||
|
if (!IsFile(streamName)) {
|
||
|
throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::OpenStreamForWrite");
|
||
|
}
|
||
|
|
||
|
return Host.OpenStreamForWrite(streamName, templateStreamName, ref writeContext);
|
||
|
}
|
||
|
|
||
|
public override void DeleteStream(string streamName) {
|
||
|
// only support files, not URIs
|
||
|
if (!IsFile(streamName)) {
|
||
|
throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::Delete");
|
||
|
}
|
||
|
|
||
|
Host.DeleteStream(streamName);
|
||
|
}
|
||
|
|
||
|
// RefreshConfig support - runtime only
|
||
|
public override bool SupportsRefresh {
|
||
|
get {return true;}
|
||
|
}
|
||
|
|
||
|
// path support
|
||
|
public override bool SupportsPath {
|
||
|
get {return false;}
|
||
|
}
|
||
|
|
||
|
// Do we support location tags?
|
||
|
public override bool SupportsLocation {
|
||
|
get {return false;}
|
||
|
}
|
||
|
|
||
|
public override bool IsDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition, ConfigurationAllowExeDefinition allowExeDefinition) {
|
||
|
string allowedConfigPath;
|
||
|
|
||
|
switch (allowExeDefinition) {
|
||
|
case ConfigurationAllowExeDefinition.MachineOnly:
|
||
|
allowedConfigPath = MachineConfigPath;
|
||
|
break;
|
||
|
|
||
|
case ConfigurationAllowExeDefinition.MachineToApplication:
|
||
|
allowedConfigPath = ExeConfigPath;
|
||
|
break;
|
||
|
|
||
|
case ConfigurationAllowExeDefinition.MachineToRoamingUser:
|
||
|
allowedConfigPath = RoamingUserConfigPath;
|
||
|
break;
|
||
|
|
||
|
// MachineToLocalUser does not current have any definition restrictions
|
||
|
case ConfigurationAllowExeDefinition.MachineToLocalUser:
|
||
|
return true;
|
||
|
|
||
|
default:
|
||
|
// If we have extended ConfigurationAllowExeDefinition
|
||
|
// make sure to update this switch accordingly
|
||
|
throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::IsDefinitionAllowed");
|
||
|
}
|
||
|
|
||
|
return configPath.Length <= allowedConfigPath.Length;
|
||
|
}
|
||
|
|
||
|
public override void VerifyDefinitionAllowed(string configPath, ConfigurationAllowDefinition allowDefinition, ConfigurationAllowExeDefinition allowExeDefinition, IConfigErrorInfo errorInfo) {
|
||
|
if (!IsDefinitionAllowed(configPath, allowDefinition, allowExeDefinition)) {
|
||
|
switch (allowExeDefinition) {
|
||
|
case ConfigurationAllowExeDefinition.MachineOnly:
|
||
|
throw new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.Config_allow_exedefinition_error_machine), errorInfo);
|
||
|
|
||
|
case ConfigurationAllowExeDefinition.MachineToApplication:
|
||
|
throw new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.Config_allow_exedefinition_error_application), errorInfo);
|
||
|
|
||
|
case ConfigurationAllowExeDefinition.MachineToRoamingUser:
|
||
|
throw new ConfigurationErrorsException(
|
||
|
SR.GetString(SR.Config_allow_exedefinition_error_roaminguser), errorInfo);
|
||
|
|
||
|
default:
|
||
|
// If we have extended ConfigurationAllowExeDefinition
|
||
|
// make sure to update this switch accordingly
|
||
|
throw ExceptionUtil.UnexpectedError("ClientConfigurationHost::VerifyDefinitionAllowed");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// prefetch support
|
||
|
public override bool PrefetchAll(string configPath, string streamName) {
|
||
|
// If it's a file, we don't need to. Otherwise (e.g. it's from the web), we'll prefetch everything.
|
||
|
return !IsFile(streamName);
|
||
|
}
|
||
|
|
||
|
public override bool PrefetchSection(string sectionGroupName, string sectionName) {
|
||
|
return sectionGroupName == "system.net";
|
||
|
}
|
||
|
|
||
|
// we trust machine.config - admins settings do not have security restrictions.
|
||
|
public override bool IsTrustedConfigPath(string configPath) {
|
||
|
return configPath == MachineConfigPath;
|
||
|
}
|
||
|
|
||
|
[SecurityPermission(SecurityAction.Assert, ControlEvidence=true)]
|
||
|
public override void GetRestrictedPermissions(IInternalConfigRecord configRecord, out PermissionSet permissionSet, out bool isHostReady) {
|
||
|
// Get the stream name as a URL
|
||
|
string url;
|
||
|
bool isFile = IsFile(configRecord.StreamName);
|
||
|
if (isFile) {
|
||
|
url = UrlPath.ConvertFileNameToUrl(configRecord.StreamName);
|
||
|
}
|
||
|
else {
|
||
|
url = configRecord.StreamName;
|
||
|
}
|
||
|
|
||
|
Evidence evidence = new Evidence();
|
||
|
|
||
|
// Add Url evidence, which is simply the URL.
|
||
|
evidence.AddHostEvidence(new Url(url));
|
||
|
|
||
|
// Add Zone evidence - My Computer, Intranet, Internet, etc.
|
||
|
evidence.AddHostEvidence(Zone.CreateFromUrl(url));
|
||
|
|
||
|
// Add Site evidence if the url is http.
|
||
|
if (!isFile) {
|
||
|
evidence.AddHostEvidence(Site.CreateFromUrl(url));
|
||
|
}
|
||
|
|
||
|
// Get the resulting permission set.
|
||
|
permissionSet = SecurityManager.GetStandardSandbox(evidence);
|
||
|
|
||
|
// Client host is always ready to return permissions.
|
||
|
isHostReady = true;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Impersonate for Client Config
|
||
|
// Use the process identity
|
||
|
//
|
||
|
[SecurityPermissionAttribute(SecurityAction.Assert, Flags=SecurityPermissionFlag.ControlPrincipal | SecurityPermissionFlag.UnmanagedCode)]
|
||
|
public override IDisposable Impersonate() {
|
||
|
// Use the process identity
|
||
|
return WindowsIdentity.Impersonate(IntPtr.Zero);
|
||
|
}
|
||
|
|
||
|
// context support
|
||
|
public override object CreateDeprecatedConfigContext(string configPath) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
// CreateConfigurationContext
|
||
|
//
|
||
|
// Create the new context
|
||
|
//
|
||
|
public override object
|
||
|
CreateConfigurationContext( string configPath,
|
||
|
string locationSubPath )
|
||
|
{
|
||
|
return new ExeContext(GetUserLevel(configPath), ConfigPaths.ApplicationUri);
|
||
|
}
|
||
|
|
||
|
// GetUserLevel
|
||
|
//
|
||
|
// Given a configPath, determine what the user level is?
|
||
|
//
|
||
|
private ConfigurationUserLevel GetUserLevel(string configPath)
|
||
|
{
|
||
|
ConfigurationUserLevel level;
|
||
|
|
||
|
switch (ConfigPathUtility.GetName(configPath)) {
|
||
|
case MachineConfigName:
|
||
|
// Machine Level
|
||
|
level = ConfigurationUserLevel.None;
|
||
|
break;
|
||
|
|
||
|
case ExeConfigName:
|
||
|
// Exe Level
|
||
|
level = ConfigurationUserLevel.None;
|
||
|
break;
|
||
|
|
||
|
case LocalUserConfigName:
|
||
|
// User Level
|
||
|
level = ConfigurationUserLevel.PerUserRoamingAndLocal;
|
||
|
break;
|
||
|
|
||
|
case RoamingUserConfigName:
|
||
|
// Roaming Level
|
||
|
level = ConfigurationUserLevel.PerUserRoaming;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
Debug.Fail("unrecognized configPath " + configPath);
|
||
|
level = ConfigurationUserLevel.None;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return level;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create a Configuration object.
|
||
|
//
|
||
|
static internal Configuration OpenExeConfiguration(ConfigurationFileMap fileMap, bool isMachine, ConfigurationUserLevel userLevel, string exePath) {
|
||
|
// validate userLevel argument
|
||
|
switch (userLevel) {
|
||
|
default:
|
||
|
throw ExceptionUtil.ParameterInvalid("userLevel");
|
||
|
|
||
|
case ConfigurationUserLevel.None:
|
||
|
case ConfigurationUserLevel.PerUserRoaming:
|
||
|
case ConfigurationUserLevel.PerUserRoamingAndLocal:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// validate fileMap arguments
|
||
|
if (fileMap != null) {
|
||
|
if (String.IsNullOrEmpty(fileMap.MachineConfigFilename)) {
|
||
|
throw ExceptionUtil.ParameterNullOrEmpty("fileMap.MachineConfigFilename");
|
||
|
}
|
||
|
|
||
|
ExeConfigurationFileMap exeFileMap = fileMap as ExeConfigurationFileMap;
|
||
|
if (exeFileMap != null) {
|
||
|
switch (userLevel) {
|
||
|
case ConfigurationUserLevel.None:
|
||
|
if (String.IsNullOrEmpty(exeFileMap.ExeConfigFilename)) {
|
||
|
throw ExceptionUtil.ParameterNullOrEmpty("fileMap.ExeConfigFilename");
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case ConfigurationUserLevel.PerUserRoaming:
|
||
|
if (String.IsNullOrEmpty(exeFileMap.RoamingUserConfigFilename)) {
|
||
|
throw ExceptionUtil.ParameterNullOrEmpty("fileMap.RoamingUserConfigFilename");
|
||
|
}
|
||
|
|
||
|
goto case ConfigurationUserLevel.None;
|
||
|
|
||
|
case ConfigurationUserLevel.PerUserRoamingAndLocal:
|
||
|
if (String.IsNullOrEmpty(exeFileMap.LocalUserConfigFilename)) {
|
||
|
throw ExceptionUtil.ParameterNullOrEmpty("fileMap.LocalUserConfigFilename");
|
||
|
}
|
||
|
|
||
|
goto case ConfigurationUserLevel.PerUserRoaming;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
string configPath = null;
|
||
|
if (isMachine) {
|
||
|
configPath = MachineConfigPath;
|
||
|
}
|
||
|
else {
|
||
|
switch (userLevel) {
|
||
|
case ConfigurationUserLevel.None:
|
||
|
configPath = ExeConfigPath;
|
||
|
break;
|
||
|
|
||
|
case ConfigurationUserLevel.PerUserRoaming:
|
||
|
configPath = RoamingUserConfigPath;
|
||
|
break;
|
||
|
|
||
|
case ConfigurationUserLevel.PerUserRoamingAndLocal:
|
||
|
configPath = LocalUserConfigPath;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Configuration configuration = new Configuration(null, typeof(ClientConfigurationHost), fileMap, exePath, configPath);
|
||
|
|
||
|
return configuration;
|
||
|
}
|
||
|
}
|
||
|
}
|