ClientConfigPaths.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Configuration / System / Configuration / ClientConfigPaths.cs / 1 / ClientConfigPaths.cs

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

namespace System.Configuration { 
    using System; 
    using System.Collections;
    using System.IO; 
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Runtime.Serialization.Formatters.Binary; 
    using System.Security;
    using System.Security.Cryptography; 
    using System.Security.Policy; 
    using System.Security.Permissions;
    using System.Text; 
    using System.Globalization;
    using Microsoft.Win32;

    class ClientConfigPaths { 
        internal const string       UserConfigFilename = "user.config";
 
        const string                ClickOnceDataDirectory = "DataDirectory"; 
        const string                ConfigExtension = ".config";
        const int                   MAX_PATH = 260; 
        const int                   MAX_LENGTH_TO_USE = 25;
        const string                FILE_URI_LOCAL = "file:///";
        const string                FILE_URI_UNC = "file://";
        const string                FILE_URI = "file:"; 
        const string                HTTP_URI = "http://";
        const string                StrongNameDesc = "StrongName"; 
        const string                UrlDesc = "Url"; 
        const string                PathDesc = "Path";
 
        static Char[] s_Base32Char   = {
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
                'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
                'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
                'y', 'z', '0', '1', '2', '3', '4', '5'};
 
        static  volatile ClientConfigPaths  s_current; 
        static  volatile bool               s_currentIncludesUserConfig;
        static  SecurityPermission          s_serializationPerm; 
        static  SecurityPermission          s_controlEvidencePerm;

        bool    _hasEntryAssembly;
        bool    _includesUserConfig; 
        string  _applicationUri;
        string  _applicationConfigUri; 
        string  _roamingConfigDirectory; 
        string  _roamingConfigFilename;
        string  _localConfigDirectory; 
        string  _localConfigFilename;
        string  _companyName;
        string  _productName;
        string  _productVersion; 

 
        [FileIOPermission(SecurityAction.Assert, AllFiles=FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read)] 
        [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
        private ClientConfigPaths(string exePath, bool includeUserConfig) { 

            _includesUserConfig = includeUserConfig;

            Assembly    exeAssembly = null; 
            string      applicationUri = null;
            string      applicationFilename = null; 
 
            // get the assembly and applicationUri for the file
            if (exePath == null) { 
                // First check if a configuration file has been set for this app domain. If so, we will use that.
                // The CLR would already have normalized this, so no further processing necessary.
                AppDomain domain = AppDomain.CurrentDomain;
                AppDomainSetup setup = domain.SetupInformation; 
                _applicationConfigUri = setup.ConfigurationFile;
 
                // Now figure out the application path. 
                exeAssembly = Assembly.GetEntryAssembly();
                if (exeAssembly != null) { 
                    _hasEntryAssembly = true;
                    applicationUri = exeAssembly.CodeBase;

                    bool isFile = false; 

                    // If it is a local file URI, convert it to its filename, without invoking Uri class. 
                    // example: "file:///C:/WINNT/Microsoft.NET/Framework/v2.0.x86fre/csc.exe" 
                    if (StringUtil.StartsWithIgnoreCase(applicationUri, FILE_URI_LOCAL)) {
                        isFile = true; 
                        applicationUri = applicationUri.Substring(FILE_URI_LOCAL.Length);
                    }
                    // If it is a UNC file URI, convert it to its filename, without invoking Uri class.
                    // example: "file://server/share/csc.exe" 
                    else if (StringUtil.StartsWithIgnoreCase(applicationUri, FILE_URI_UNC)) {
                        isFile = true; 
                        applicationUri = applicationUri.Substring(FILE_URI.Length); 
                    }
 
                    if (isFile) {
                        applicationUri = applicationUri.Replace('/', '\\');
                        applicationFilename = applicationUri;
                    } 
                    else {
                        applicationUri = exeAssembly.EscapedCodeBase; 
                    } 
                }
                else { 
                    StringBuilder sb = new StringBuilder(MAX_PATH);
                    UnsafeNativeMethods.GetModuleFileName(new HandleRef(null, IntPtr.Zero), sb, sb.Capacity);
                    applicationUri = Path.GetFullPath(sb.ToString());
                    applicationFilename = applicationUri; 
                }
            } 
            else { 
                applicationUri = Path.GetFullPath(exePath);
                if (!FileUtil.FileExists(applicationUri, false)) 
                    throw ExceptionUtil.ParameterInvalid("exePath");

                applicationFilename = applicationUri;
            } 

            // Fallback if we haven't set the app config file path yet. 
            if (_applicationConfigUri == null) { 
                _applicationConfigUri = applicationUri + ConfigExtension;
            } 

            // Set application path
            _applicationUri = applicationUri;
 
            // In the case when exePath was explicitly supplied, we will not be able to
            // construct user.config paths, so quit here. 
            if (exePath != null) { 
                return;
            } 

            // Skip expensive initialization of user config file information if requested.
            if (!_includesUserConfig) {
                return; 
            }
 
            bool isHttp = StringUtil.StartsWithIgnoreCase(_applicationConfigUri, HTTP_URI); 

            SetNamesAndVersion(applicationFilename, exeAssembly, isHttp); 

            // Check if this is a clickonce deployed application. If so, point the user config
            // files to the clickonce data directory.
            if (this.IsClickOnceDeployed(AppDomain.CurrentDomain)) { 
                string dataPath = AppDomain.CurrentDomain.GetData(ClickOnceDataDirectory) as string;
                string versionSuffix = Validate(_productVersion, false); 
 
                // NOTE: No roaming config for clickonce - not supported.
                if (Path.IsPathRooted(dataPath)) { 
                    _localConfigDirectory = CombineIfValid(dataPath, versionSuffix);
                    _localConfigFilename  = CombineIfValid(_localConfigDirectory, UserConfigFilename);
                }
 
            }
            else if (!isHttp) { 
                // If we get the config from http, we do not have a roaming or local config directory, 
                // as it cannot be edited by the app in those cases because it does not have Full Trust.
 
                // suffix for user config paths

                string part1 = Validate(_companyName, true);
 
                string validAppDomainName = Validate(AppDomain.CurrentDomain.FriendlyName, true);
                string applicationUriLower = !String.IsNullOrEmpty(_applicationUri) ? _applicationUri.ToLower(CultureInfo.InvariantCulture) : null; 
                string namePrefix = !String.IsNullOrEmpty(validAppDomainName) ? validAppDomainName : Validate(_productName, true); 
                string hashSuffix = GetTypeAndHashSuffix(AppDomain.CurrentDomain, applicationUriLower);
 
                string part2 = (!String.IsNullOrEmpty(namePrefix) && !String.IsNullOrEmpty(hashSuffix)) ? namePrefix + hashSuffix : null;

                string part3 = Validate(_productVersion, false);
 
                string dirSuffix = CombineIfValid(CombineIfValid(part1, part2), part3);
 
                string roamingFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); 
                if (Path.IsPathRooted(roamingFolderPath)) {
                    _roamingConfigDirectory = CombineIfValid(roamingFolderPath, dirSuffix); 
                    _roamingConfigFilename = CombineIfValid(_roamingConfigDirectory, UserConfigFilename);
                }

                string localFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 
                if (Path.IsPathRooted(localFolderPath)) {
                    _localConfigDirectory = CombineIfValid(localFolderPath, dirSuffix); 
                    _localConfigFilename = CombineIfValid(_localConfigDirectory, UserConfigFilename); 
                }
            } 
        }

        internal static ClientConfigPaths GetPaths(string exePath, bool includeUserConfig) {
            ClientConfigPaths result = null; 

            if (exePath == null) { 
                if (s_current == null || (includeUserConfig && !s_currentIncludesUserConfig)) { 
                    s_current = new ClientConfigPaths(null, includeUserConfig);
                    s_currentIncludesUserConfig = includeUserConfig; 
                }

                result = s_current;
            } 
            else {
                result = new ClientConfigPaths(exePath, includeUserConfig); 
            } 

            return result; 
        }

        internal static void RefreshCurrent() {
            s_currentIncludesUserConfig = false; 
            s_current = null;
        } 
 
        internal static ClientConfigPaths Current {
            get { 
                return GetPaths(null, true);
            }
        }
 
        internal bool HasEntryAssembly {
            get { 
                return _hasEntryAssembly; 
            }
        } 

        internal string ApplicationUri {
            get {
                return _applicationUri; 
            }
        } 
 
        internal string ApplicationConfigUri {
            get { 
                return _applicationConfigUri;
            }
        }
 
        internal string RoamingConfigFilename {
            get { 
                return _roamingConfigFilename; 
            }
        } 

        internal string RoamingConfigDirectory {
            get {
                return _roamingConfigDirectory; 
            }
        } 
 
        internal bool HasRoamingConfig {
            get { 
                // Assume we have roaming config if we haven't loaded user config file information.
                return RoamingConfigFilename != null || !_includesUserConfig;
            }
        } 

        internal string LocalConfigFilename { 
            get { 
                return _localConfigFilename;
            } 
        }

        internal string LocalConfigDirectory {
            get { 
                return _localConfigDirectory;
            } 
        } 

        internal bool HasLocalConfig { 
            get {
                // Assume we have roaming config if we haven't loaded user config file information.
                return LocalConfigFilename != null || !_includesUserConfig;
            } 
        }
 
        internal string ProductName { 
            get {
                return _productName; 
            }
        }

        internal string ProductVersion { 
            get {
                return _productVersion; 
            } 
        }
 
        private static SecurityPermission ControlEvidencePermission {
            get {
                if (s_controlEvidencePerm == null) {
                    s_controlEvidencePerm = new SecurityPermission(SecurityPermissionFlag.ControlEvidence); 
                }
                return s_controlEvidencePerm; 
            } 
        }
 
        private static SecurityPermission SerializationFormatterPermission {
            get {
                if (s_serializationPerm == null) {
                    s_serializationPerm = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter); 
                }
                return s_serializationPerm; 
            } 
        }
 
        // Combines path2 with path1 if possible, else returns null.
        private string CombineIfValid(string path1, string path2) {
            string returnPath = null;
 
            if (path1 != null && path2 != null) {
                try { 
                    string combinedPath = Path.Combine(path1, path2); 
                    if (combinedPath.Length < MAX_PATH) {
                        returnPath = combinedPath; 
                    }
                }
                catch {
                } 
            }
 
            return returnPath; 
        }
 
        // Returns a type and hash suffix based on app domain evidence. The evidence we use, in
        // priority order, is Strong Name, Url and Exe Path. If one of these is found, we compute a
        // SHA1 hash of it and return a suffix based on that. If none is found, we return null.
        private string GetTypeAndHashSuffix(AppDomain appDomain, string exePath) { 
            string suffix       = null;
            string typeName     = null; 
            object evidenceObj  = null; 

            evidenceObj = GetEvidenceInfo(appDomain, exePath, out typeName); 

            if (evidenceObj != null && !String.IsNullOrEmpty(typeName)) {
                MemoryStream ms   = new MemoryStream();
                BinaryFormatter bSer = new BinaryFormatter(); 
                SerializationFormatterPermission.Assert();
                bSer.Serialize(ms, evidenceObj); 
                ms.Position = 0; 
                string evidenceHash = GetHash(ms);
 
                if (!String.IsNullOrEmpty(evidenceHash)) {
                    suffix = "_" + typeName + "_" + evidenceHash;
                }
            } 

            return suffix; 
        } 

        // Mostly borrowed from IsolatedStorage, with some modifications 
        private static object GetEvidenceInfo(AppDomain appDomain, string exePath, out string typeName) {
            ControlEvidencePermission.Assert();
            Evidence evidence = appDomain.Evidence;
            StrongName  sn   = null; 
            Url         url  = null;
 
            if (evidence != null) { 
                IEnumerator e = evidence.GetHostEnumerator();
                object      temp = null; 

                while (e.MoveNext()) {
                    temp = e.Current;
 
                    if (temp is StrongName) {
                        sn = (StrongName) temp; 
                        break; 
                    }
                    else if (temp is Url) { 
                        url = (Url) temp;
                    }
                }
            } 

            object o = null; 
 
            // The order of preference is StrongName, Url, ExePath.
            if (sn != null) { 
                o = MakeVersionIndependent(sn);
                typeName = StrongNameDesc;
            }
            else if (url != null) { 
                // Extract the url string and normalize it to use as evidence
                o = url.Value.ToUpperInvariant(); 
                typeName = UrlDesc; 
            }
            else if (exePath != null) { 
                o = exePath;
                typeName = PathDesc;
            }
            else { 
                typeName = null;
            } 
 
            return o;
        } 

        private static String GetHash(Stream s) {
            byte[] hash;
 
            using (SHA1 sha1 = new SHA1CryptoServiceProvider()) {
                hash = sha1.ComputeHash(s); 
            } 

            return ToBase32StringSuitableForDirName(hash); 
        }

        private bool IsClickOnceDeployed(AppDomain appDomain) {
            // NOTE: For perf & servicing reasons, we don't want to introduce a dependency on 
            //       System.Deployment.dll here. The following code is an alternative to calling
            //       ApplicationDeployment.IsNetworkDeployed. 
 
            ActivationContext actCtx = appDomain.ActivationContext;
 
            // Ensures the app is running with a context from the store.
            if (actCtx != null && actCtx.Form == ActivationContext.ContextForm.StoreBounded) {
                string fullAppId = actCtx.Identity.FullName;
                if (!String.IsNullOrEmpty(fullAppId)) { 
                    return true;
                } 
            } 

            return false; 
        }

        private static StrongName MakeVersionIndependent(StrongName sn) {
            return new StrongName(sn.PublicKey, sn.Name, new Version(0,0,0,0)); 
        }
 
        private void SetNamesAndVersion(string applicationFilename, Assembly exeAssembly, bool isHttp) { 
            Type        mainType = null;
 
            //
            // Get CompanyName, ProductName, and ProductVersion
            // First try custom attributes on the assembly.
            // 
            if (exeAssembly != null) {
                object[] attrs = exeAssembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); 
                if (attrs != null && attrs.Length > 0) { 
                    _companyName = ((AssemblyCompanyAttribute)attrs[0]).Company;
                    if (_companyName != null) { 
                        _companyName = _companyName.Trim();
                    }
                }
 
                attrs = exeAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
                if (attrs != null && attrs.Length > 0) { 
                    _productName = ((AssemblyProductAttribute)attrs[0]).Product; 
                    if (_productName != null) {
                        _productName = _productName.Trim(); 
                    }
                }

                _productVersion = exeAssembly.GetName().Version.ToString(); 
                if (_productVersion != null) {
                    _productVersion = _productVersion.Trim(); 
                } 
            }
 
            //
            // If we couldn't get custom attributes, try the Win32 file version
            //
            if (!isHttp && (String.IsNullOrEmpty(_companyName) || String.IsNullOrEmpty(_productName) || String.IsNullOrEmpty(_productVersion))) { 
                string versionInfoFileName = null;
 
                if (exeAssembly != null) { 
                    MethodInfo entryPoint = exeAssembly.EntryPoint;
                    if (entryPoint != null) { 
                        mainType = entryPoint.ReflectedType;
                        if (mainType != null) {
                            versionInfoFileName = mainType.Module.FullyQualifiedName;
                        } 
                    }
                } 
 
                if (versionInfoFileName == null) {
                    versionInfoFileName = applicationFilename; 
                }

                if (versionInfoFileName != null) {
                    System.Diagnostics.FileVersionInfo version = System.Diagnostics.FileVersionInfo.GetVersionInfo(versionInfoFileName); 
                    if (version != null) {
                        if (String.IsNullOrEmpty(_companyName)) { 
                            _companyName = version.CompanyName; 
                            if (_companyName != null) {
                                _companyName = _companyName.Trim(); 
                            }
                        }

                        if (String.IsNullOrEmpty(_productName)) { 
                            _productName = version.ProductName;
                            if (_productName != null) { 
                                _productName = _productName.Trim(); 
                            }
                        } 

                        if (String.IsNullOrEmpty(_productVersion)) {
                            _productVersion = version.ProductVersion;
                            if (_productVersion != null) { 
                                _productVersion = _productVersion.Trim();
                            } 
                        } 
                    }
                } 
            }

            if (String.IsNullOrEmpty(_companyName) || String.IsNullOrEmpty(_productName)) {
                string  ns = null; 
                if (mainType != null) {
                    ns = mainType.Namespace; 
                } 

                // Desperate measures for product name 
                if (String.IsNullOrEmpty(_productName)) {
                    // Try the remainder of the namespace
                    if (ns != null) {
                        int lastDot = ns.LastIndexOf(".", StringComparison.Ordinal); 
                        if (lastDot != -1 && lastDot < ns.Length - 1) {
                            _productName = ns.Substring(lastDot+1); 
                        } 
                        else {
                            _productName = ns; 
                        }

                        _productName = _productName.Trim();
                    } 

                    // Try the type of the entry assembly 
                    if (String.IsNullOrEmpty(_productName) && mainType != null) { 
                        _productName = mainType.Name.Trim();
                    } 

                    // give up, return empty string
                    if (_productName == null) {
                        _productName = string.Empty; 
                    }
                } 
 
                // Desperate measures for company name
                if (String.IsNullOrEmpty(_companyName)) { 
                    // Try the first part of the namespace
                    if (ns != null) {
                        int firstDot = ns.IndexOf(".", StringComparison.Ordinal);
                        if (firstDot != -1) { 
                            _companyName = ns.Substring(0, firstDot);
                        } 
                        else { 
                            _companyName = ns;
                        } 

                        _companyName = _companyName.Trim();
                    }
 
                    // If that doesn't work, use the product name
                    if (String.IsNullOrEmpty(_companyName)) { 
                        _companyName = _productName; 
                    }
                } 
            }

            // Desperate measures for product version - assume 1.0
            if (String.IsNullOrEmpty(_productVersion)) { 
                _productVersion = "1.0.0.0";
            } 
        } 

        // Borrowed from IsolatedStorage 
        private static string ToBase32StringSuitableForDirName(byte[] buff) {
            StringBuilder sb = new StringBuilder();
            byte b0, b1, b2, b3, b4;
            int  l, i; 

            l = buff.Length; 
            i = 0; 

            // Create l chars using the last 5 bits of each byte. 
            // Consume 3 MSB bits 5 bytes at a time.

            do
            { 
                b0 = (i < l) ? buff[i++] : (byte)0;
                b1 = (i < l) ? buff[i++] : (byte)0; 
                b2 = (i < l) ? buff[i++] : (byte)0; 
                b3 = (i < l) ? buff[i++] : (byte)0;
                b4 = (i < l) ? buff[i++] : (byte)0; 

                // Consume the 5 Least significant bits of each byte
                sb.Append(s_Base32Char[b0 & 0x1F]);
                sb.Append(s_Base32Char[b1 & 0x1F]); 
                sb.Append(s_Base32Char[b2 & 0x1F]);
                sb.Append(s_Base32Char[b3 & 0x1F]); 
                sb.Append(s_Base32Char[b4 & 0x1F]); 

                // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4 
                sb.Append(s_Base32Char[(
                        ((b0 & 0xE0) >> 5) |
                        ((b3 & 0x60) >> 2))]);
 
                sb.Append(s_Base32Char[(
                        ((b1 & 0xE0) >> 5) | 
                        ((b4 & 0x60) >> 2))]); 

                // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4 

                b2 >>= 5;

                if ((b3 & 0x80) != 0) 
                    b2 |= 0x08;
                if ((b4 & 0x80) != 0) 
                    b2 |= 0x10; 

                sb.Append(s_Base32Char[b2]); 

            } while (i < l);

            return sb.ToString(); 
        }
 
        // Makes the passed in string suitable to use as a path name by replacing illegal characters 
        // with underscores. Additionally, we do two things - replace spaces too with underscores and
        // limit the resultant string's length to MAX_LENGTH_TO_USE if limitSize is true. 
        private string Validate(string str, bool limitSize) {
            string validated = str;

            if (!String.IsNullOrEmpty(validated)) { 
                // First replace all illegal characters with underscores
                foreach (char c in Path.GetInvalidFileNameChars()) { 
                    validated = validated.Replace(c, '_'); 
                }
 
                // Replace all spaces with underscores
                validated = validated.Replace(' ', '_');

                if (limitSize) { 
                    validated = (validated.Length > MAX_LENGTH_TO_USE) ? validated.Substring(0, MAX_LENGTH_TO_USE) : validated;
                } 
            } 

            return validated; 
        }
    }
}

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

namespace System.Configuration { 
    using System; 
    using System.Collections;
    using System.IO; 
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices;
    using System.Runtime.Serialization.Formatters.Binary; 
    using System.Security;
    using System.Security.Cryptography; 
    using System.Security.Policy; 
    using System.Security.Permissions;
    using System.Text; 
    using System.Globalization;
    using Microsoft.Win32;

    class ClientConfigPaths { 
        internal const string       UserConfigFilename = "user.config";
 
        const string                ClickOnceDataDirectory = "DataDirectory"; 
        const string                ConfigExtension = ".config";
        const int                   MAX_PATH = 260; 
        const int                   MAX_LENGTH_TO_USE = 25;
        const string                FILE_URI_LOCAL = "file:///";
        const string                FILE_URI_UNC = "file://";
        const string                FILE_URI = "file:"; 
        const string                HTTP_URI = "http://";
        const string                StrongNameDesc = "StrongName"; 
        const string                UrlDesc = "Url"; 
        const string                PathDesc = "Path";
 
        static Char[] s_Base32Char   = {
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
                'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
                'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 
                'y', 'z', '0', '1', '2', '3', '4', '5'};
 
        static  volatile ClientConfigPaths  s_current; 
        static  volatile bool               s_currentIncludesUserConfig;
        static  SecurityPermission          s_serializationPerm; 
        static  SecurityPermission          s_controlEvidencePerm;

        bool    _hasEntryAssembly;
        bool    _includesUserConfig; 
        string  _applicationUri;
        string  _applicationConfigUri; 
        string  _roamingConfigDirectory; 
        string  _roamingConfigFilename;
        string  _localConfigDirectory; 
        string  _localConfigFilename;
        string  _companyName;
        string  _productName;
        string  _productVersion; 

 
        [FileIOPermission(SecurityAction.Assert, AllFiles=FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read)] 
        [SecurityPermission(SecurityAction.Assert, UnmanagedCode=true)]
        private ClientConfigPaths(string exePath, bool includeUserConfig) { 

            _includesUserConfig = includeUserConfig;

            Assembly    exeAssembly = null; 
            string      applicationUri = null;
            string      applicationFilename = null; 
 
            // get the assembly and applicationUri for the file
            if (exePath == null) { 
                // First check if a configuration file has been set for this app domain. If so, we will use that.
                // The CLR would already have normalized this, so no further processing necessary.
                AppDomain domain = AppDomain.CurrentDomain;
                AppDomainSetup setup = domain.SetupInformation; 
                _applicationConfigUri = setup.ConfigurationFile;
 
                // Now figure out the application path. 
                exeAssembly = Assembly.GetEntryAssembly();
                if (exeAssembly != null) { 
                    _hasEntryAssembly = true;
                    applicationUri = exeAssembly.CodeBase;

                    bool isFile = false; 

                    // If it is a local file URI, convert it to its filename, without invoking Uri class. 
                    // example: "file:///C:/WINNT/Microsoft.NET/Framework/v2.0.x86fre/csc.exe" 
                    if (StringUtil.StartsWithIgnoreCase(applicationUri, FILE_URI_LOCAL)) {
                        isFile = true; 
                        applicationUri = applicationUri.Substring(FILE_URI_LOCAL.Length);
                    }
                    // If it is a UNC file URI, convert it to its filename, without invoking Uri class.
                    // example: "file://server/share/csc.exe" 
                    else if (StringUtil.StartsWithIgnoreCase(applicationUri, FILE_URI_UNC)) {
                        isFile = true; 
                        applicationUri = applicationUri.Substring(FILE_URI.Length); 
                    }
 
                    if (isFile) {
                        applicationUri = applicationUri.Replace('/', '\\');
                        applicationFilename = applicationUri;
                    } 
                    else {
                        applicationUri = exeAssembly.EscapedCodeBase; 
                    } 
                }
                else { 
                    StringBuilder sb = new StringBuilder(MAX_PATH);
                    UnsafeNativeMethods.GetModuleFileName(new HandleRef(null, IntPtr.Zero), sb, sb.Capacity);
                    applicationUri = Path.GetFullPath(sb.ToString());
                    applicationFilename = applicationUri; 
                }
            } 
            else { 
                applicationUri = Path.GetFullPath(exePath);
                if (!FileUtil.FileExists(applicationUri, false)) 
                    throw ExceptionUtil.ParameterInvalid("exePath");

                applicationFilename = applicationUri;
            } 

            // Fallback if we haven't set the app config file path yet. 
            if (_applicationConfigUri == null) { 
                _applicationConfigUri = applicationUri + ConfigExtension;
            } 

            // Set application path
            _applicationUri = applicationUri;
 
            // In the case when exePath was explicitly supplied, we will not be able to
            // construct user.config paths, so quit here. 
            if (exePath != null) { 
                return;
            } 

            // Skip expensive initialization of user config file information if requested.
            if (!_includesUserConfig) {
                return; 
            }
 
            bool isHttp = StringUtil.StartsWithIgnoreCase(_applicationConfigUri, HTTP_URI); 

            SetNamesAndVersion(applicationFilename, exeAssembly, isHttp); 

            // Check if this is a clickonce deployed application. If so, point the user config
            // files to the clickonce data directory.
            if (this.IsClickOnceDeployed(AppDomain.CurrentDomain)) { 
                string dataPath = AppDomain.CurrentDomain.GetData(ClickOnceDataDirectory) as string;
                string versionSuffix = Validate(_productVersion, false); 
 
                // NOTE: No roaming config for clickonce - not supported.
                if (Path.IsPathRooted(dataPath)) { 
                    _localConfigDirectory = CombineIfValid(dataPath, versionSuffix);
                    _localConfigFilename  = CombineIfValid(_localConfigDirectory, UserConfigFilename);
                }
 
            }
            else if (!isHttp) { 
                // If we get the config from http, we do not have a roaming or local config directory, 
                // as it cannot be edited by the app in those cases because it does not have Full Trust.
 
                // suffix for user config paths

                string part1 = Validate(_companyName, true);
 
                string validAppDomainName = Validate(AppDomain.CurrentDomain.FriendlyName, true);
                string applicationUriLower = !String.IsNullOrEmpty(_applicationUri) ? _applicationUri.ToLower(CultureInfo.InvariantCulture) : null; 
                string namePrefix = !String.IsNullOrEmpty(validAppDomainName) ? validAppDomainName : Validate(_productName, true); 
                string hashSuffix = GetTypeAndHashSuffix(AppDomain.CurrentDomain, applicationUriLower);
 
                string part2 = (!String.IsNullOrEmpty(namePrefix) && !String.IsNullOrEmpty(hashSuffix)) ? namePrefix + hashSuffix : null;

                string part3 = Validate(_productVersion, false);
 
                string dirSuffix = CombineIfValid(CombineIfValid(part1, part2), part3);
 
                string roamingFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); 
                if (Path.IsPathRooted(roamingFolderPath)) {
                    _roamingConfigDirectory = CombineIfValid(roamingFolderPath, dirSuffix); 
                    _roamingConfigFilename = CombineIfValid(_roamingConfigDirectory, UserConfigFilename);
                }

                string localFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); 
                if (Path.IsPathRooted(localFolderPath)) {
                    _localConfigDirectory = CombineIfValid(localFolderPath, dirSuffix); 
                    _localConfigFilename = CombineIfValid(_localConfigDirectory, UserConfigFilename); 
                }
            } 
        }

        internal static ClientConfigPaths GetPaths(string exePath, bool includeUserConfig) {
            ClientConfigPaths result = null; 

            if (exePath == null) { 
                if (s_current == null || (includeUserConfig && !s_currentIncludesUserConfig)) { 
                    s_current = new ClientConfigPaths(null, includeUserConfig);
                    s_currentIncludesUserConfig = includeUserConfig; 
                }

                result = s_current;
            } 
            else {
                result = new ClientConfigPaths(exePath, includeUserConfig); 
            } 

            return result; 
        }

        internal static void RefreshCurrent() {
            s_currentIncludesUserConfig = false; 
            s_current = null;
        } 
 
        internal static ClientConfigPaths Current {
            get { 
                return GetPaths(null, true);
            }
        }
 
        internal bool HasEntryAssembly {
            get { 
                return _hasEntryAssembly; 
            }
        } 

        internal string ApplicationUri {
            get {
                return _applicationUri; 
            }
        } 
 
        internal string ApplicationConfigUri {
            get { 
                return _applicationConfigUri;
            }
        }
 
        internal string RoamingConfigFilename {
            get { 
                return _roamingConfigFilename; 
            }
        } 

        internal string RoamingConfigDirectory {
            get {
                return _roamingConfigDirectory; 
            }
        } 
 
        internal bool HasRoamingConfig {
            get { 
                // Assume we have roaming config if we haven't loaded user config file information.
                return RoamingConfigFilename != null || !_includesUserConfig;
            }
        } 

        internal string LocalConfigFilename { 
            get { 
                return _localConfigFilename;
            } 
        }

        internal string LocalConfigDirectory {
            get { 
                return _localConfigDirectory;
            } 
        } 

        internal bool HasLocalConfig { 
            get {
                // Assume we have roaming config if we haven't loaded user config file information.
                return LocalConfigFilename != null || !_includesUserConfig;
            } 
        }
 
        internal string ProductName { 
            get {
                return _productName; 
            }
        }

        internal string ProductVersion { 
            get {
                return _productVersion; 
            } 
        }
 
        private static SecurityPermission ControlEvidencePermission {
            get {
                if (s_controlEvidencePerm == null) {
                    s_controlEvidencePerm = new SecurityPermission(SecurityPermissionFlag.ControlEvidence); 
                }
                return s_controlEvidencePerm; 
            } 
        }
 
        private static SecurityPermission SerializationFormatterPermission {
            get {
                if (s_serializationPerm == null) {
                    s_serializationPerm = new SecurityPermission(SecurityPermissionFlag.SerializationFormatter); 
                }
                return s_serializationPerm; 
            } 
        }
 
        // Combines path2 with path1 if possible, else returns null.
        private string CombineIfValid(string path1, string path2) {
            string returnPath = null;
 
            if (path1 != null && path2 != null) {
                try { 
                    string combinedPath = Path.Combine(path1, path2); 
                    if (combinedPath.Length < MAX_PATH) {
                        returnPath = combinedPath; 
                    }
                }
                catch {
                } 
            }
 
            return returnPath; 
        }
 
        // Returns a type and hash suffix based on app domain evidence. The evidence we use, in
        // priority order, is Strong Name, Url and Exe Path. If one of these is found, we compute a
        // SHA1 hash of it and return a suffix based on that. If none is found, we return null.
        private string GetTypeAndHashSuffix(AppDomain appDomain, string exePath) { 
            string suffix       = null;
            string typeName     = null; 
            object evidenceObj  = null; 

            evidenceObj = GetEvidenceInfo(appDomain, exePath, out typeName); 

            if (evidenceObj != null && !String.IsNullOrEmpty(typeName)) {
                MemoryStream ms   = new MemoryStream();
                BinaryFormatter bSer = new BinaryFormatter(); 
                SerializationFormatterPermission.Assert();
                bSer.Serialize(ms, evidenceObj); 
                ms.Position = 0; 
                string evidenceHash = GetHash(ms);
 
                if (!String.IsNullOrEmpty(evidenceHash)) {
                    suffix = "_" + typeName + "_" + evidenceHash;
                }
            } 

            return suffix; 
        } 

        // Mostly borrowed from IsolatedStorage, with some modifications 
        private static object GetEvidenceInfo(AppDomain appDomain, string exePath, out string typeName) {
            ControlEvidencePermission.Assert();
            Evidence evidence = appDomain.Evidence;
            StrongName  sn   = null; 
            Url         url  = null;
 
            if (evidence != null) { 
                IEnumerator e = evidence.GetHostEnumerator();
                object      temp = null; 

                while (e.MoveNext()) {
                    temp = e.Current;
 
                    if (temp is StrongName) {
                        sn = (StrongName) temp; 
                        break; 
                    }
                    else if (temp is Url) { 
                        url = (Url) temp;
                    }
                }
            } 

            object o = null; 
 
            // The order of preference is StrongName, Url, ExePath.
            if (sn != null) { 
                o = MakeVersionIndependent(sn);
                typeName = StrongNameDesc;
            }
            else if (url != null) { 
                // Extract the url string and normalize it to use as evidence
                o = url.Value.ToUpperInvariant(); 
                typeName = UrlDesc; 
            }
            else if (exePath != null) { 
                o = exePath;
                typeName = PathDesc;
            }
            else { 
                typeName = null;
            } 
 
            return o;
        } 

        private static String GetHash(Stream s) {
            byte[] hash;
 
            using (SHA1 sha1 = new SHA1CryptoServiceProvider()) {
                hash = sha1.ComputeHash(s); 
            } 

            return ToBase32StringSuitableForDirName(hash); 
        }

        private bool IsClickOnceDeployed(AppDomain appDomain) {
            // NOTE: For perf & servicing reasons, we don't want to introduce a dependency on 
            //       System.Deployment.dll here. The following code is an alternative to calling
            //       ApplicationDeployment.IsNetworkDeployed. 
 
            ActivationContext actCtx = appDomain.ActivationContext;
 
            // Ensures the app is running with a context from the store.
            if (actCtx != null && actCtx.Form == ActivationContext.ContextForm.StoreBounded) {
                string fullAppId = actCtx.Identity.FullName;
                if (!String.IsNullOrEmpty(fullAppId)) { 
                    return true;
                } 
            } 

            return false; 
        }

        private static StrongName MakeVersionIndependent(StrongName sn) {
            return new StrongName(sn.PublicKey, sn.Name, new Version(0,0,0,0)); 
        }
 
        private void SetNamesAndVersion(string applicationFilename, Assembly exeAssembly, bool isHttp) { 
            Type        mainType = null;
 
            //
            // Get CompanyName, ProductName, and ProductVersion
            // First try custom attributes on the assembly.
            // 
            if (exeAssembly != null) {
                object[] attrs = exeAssembly.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); 
                if (attrs != null && attrs.Length > 0) { 
                    _companyName = ((AssemblyCompanyAttribute)attrs[0]).Company;
                    if (_companyName != null) { 
                        _companyName = _companyName.Trim();
                    }
                }
 
                attrs = exeAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
                if (attrs != null && attrs.Length > 0) { 
                    _productName = ((AssemblyProductAttribute)attrs[0]).Product; 
                    if (_productName != null) {
                        _productName = _productName.Trim(); 
                    }
                }

                _productVersion = exeAssembly.GetName().Version.ToString(); 
                if (_productVersion != null) {
                    _productVersion = _productVersion.Trim(); 
                } 
            }
 
            //
            // If we couldn't get custom attributes, try the Win32 file version
            //
            if (!isHttp && (String.IsNullOrEmpty(_companyName) || String.IsNullOrEmpty(_productName) || String.IsNullOrEmpty(_productVersion))) { 
                string versionInfoFileName = null;
 
                if (exeAssembly != null) { 
                    MethodInfo entryPoint = exeAssembly.EntryPoint;
                    if (entryPoint != null) { 
                        mainType = entryPoint.ReflectedType;
                        if (mainType != null) {
                            versionInfoFileName = mainType.Module.FullyQualifiedName;
                        } 
                    }
                } 
 
                if (versionInfoFileName == null) {
                    versionInfoFileName = applicationFilename; 
                }

                if (versionInfoFileName != null) {
                    System.Diagnostics.FileVersionInfo version = System.Diagnostics.FileVersionInfo.GetVersionInfo(versionInfoFileName); 
                    if (version != null) {
                        if (String.IsNullOrEmpty(_companyName)) { 
                            _companyName = version.CompanyName; 
                            if (_companyName != null) {
                                _companyName = _companyName.Trim(); 
                            }
                        }

                        if (String.IsNullOrEmpty(_productName)) { 
                            _productName = version.ProductName;
                            if (_productName != null) { 
                                _productName = _productName.Trim(); 
                            }
                        } 

                        if (String.IsNullOrEmpty(_productVersion)) {
                            _productVersion = version.ProductVersion;
                            if (_productVersion != null) { 
                                _productVersion = _productVersion.Trim();
                            } 
                        } 
                    }
                } 
            }

            if (String.IsNullOrEmpty(_companyName) || String.IsNullOrEmpty(_productName)) {
                string  ns = null; 
                if (mainType != null) {
                    ns = mainType.Namespace; 
                } 

                // Desperate measures for product name 
                if (String.IsNullOrEmpty(_productName)) {
                    // Try the remainder of the namespace
                    if (ns != null) {
                        int lastDot = ns.LastIndexOf(".", StringComparison.Ordinal); 
                        if (lastDot != -1 && lastDot < ns.Length - 1) {
                            _productName = ns.Substring(lastDot+1); 
                        } 
                        else {
                            _productName = ns; 
                        }

                        _productName = _productName.Trim();
                    } 

                    // Try the type of the entry assembly 
                    if (String.IsNullOrEmpty(_productName) && mainType != null) { 
                        _productName = mainType.Name.Trim();
                    } 

                    // give up, return empty string
                    if (_productName == null) {
                        _productName = string.Empty; 
                    }
                } 
 
                // Desperate measures for company name
                if (String.IsNullOrEmpty(_companyName)) { 
                    // Try the first part of the namespace
                    if (ns != null) {
                        int firstDot = ns.IndexOf(".", StringComparison.Ordinal);
                        if (firstDot != -1) { 
                            _companyName = ns.Substring(0, firstDot);
                        } 
                        else { 
                            _companyName = ns;
                        } 

                        _companyName = _companyName.Trim();
                    }
 
                    // If that doesn't work, use the product name
                    if (String.IsNullOrEmpty(_companyName)) { 
                        _companyName = _productName; 
                    }
                } 
            }

            // Desperate measures for product version - assume 1.0
            if (String.IsNullOrEmpty(_productVersion)) { 
                _productVersion = "1.0.0.0";
            } 
        } 

        // Borrowed from IsolatedStorage 
        private static string ToBase32StringSuitableForDirName(byte[] buff) {
            StringBuilder sb = new StringBuilder();
            byte b0, b1, b2, b3, b4;
            int  l, i; 

            l = buff.Length; 
            i = 0; 

            // Create l chars using the last 5 bits of each byte. 
            // Consume 3 MSB bits 5 bytes at a time.

            do
            { 
                b0 = (i < l) ? buff[i++] : (byte)0;
                b1 = (i < l) ? buff[i++] : (byte)0; 
                b2 = (i < l) ? buff[i++] : (byte)0; 
                b3 = (i < l) ? buff[i++] : (byte)0;
                b4 = (i < l) ? buff[i++] : (byte)0; 

                // Consume the 5 Least significant bits of each byte
                sb.Append(s_Base32Char[b0 & 0x1F]);
                sb.Append(s_Base32Char[b1 & 0x1F]); 
                sb.Append(s_Base32Char[b2 & 0x1F]);
                sb.Append(s_Base32Char[b3 & 0x1F]); 
                sb.Append(s_Base32Char[b4 & 0x1F]); 

                // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4 
                sb.Append(s_Base32Char[(
                        ((b0 & 0xE0) >> 5) |
                        ((b3 & 0x60) >> 2))]);
 
                sb.Append(s_Base32Char[(
                        ((b1 & 0xE0) >> 5) | 
                        ((b4 & 0x60) >> 2))]); 

                // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4 

                b2 >>= 5;

                if ((b3 & 0x80) != 0) 
                    b2 |= 0x08;
                if ((b4 & 0x80) != 0) 
                    b2 |= 0x10; 

                sb.Append(s_Base32Char[b2]); 

            } while (i < l);

            return sb.ToString(); 
        }
 
        // Makes the passed in string suitable to use as a path name by replacing illegal characters 
        // with underscores. Additionally, we do two things - replace spaces too with underscores and
        // limit the resultant string's length to MAX_LENGTH_TO_USE if limitSize is true. 
        private string Validate(string str, bool limitSize) {
            string validated = str;

            if (!String.IsNullOrEmpty(validated)) { 
                // First replace all illegal characters with underscores
                foreach (char c in Path.GetInvalidFileNameChars()) { 
                    validated = validated.Replace(c, '_'); 
                }
 
                // Replace all spaces with underscores
                validated = validated.Replace(' ', '_');

                if (limitSize) { 
                    validated = (validated.Length > MAX_LENGTH_TO_USE) ? validated.Substring(0, MAX_LENGTH_TO_USE) : validated;
                } 
            } 

            return validated; 
        }
    }
}

// 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