Environment.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FX-1434 / FX-1434 / 1.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / Environment.cs / 2 / Environment.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class: Environment 
**
** 
** Purpose: Provides some basic access to some environment
** functionality.
**
** 
============================================================*/
namespace System { 
    using System.IO; 
    using System.Security;
    using System.Resources; 
    using System.Globalization;
    using System.Collections;
    using System.Security.Permissions;
    using System.Text; 
    using System.Configuration.Assemblies;
    using System.Runtime.InteropServices; 
    using System.Reflection; 
    using System.Diagnostics;
    using Microsoft.Win32; 
    using System.Runtime.CompilerServices;
    using System.Threading;
    using System.Runtime.ConstrainedExecution;
    using System.Runtime.Versioning; 

#if !FEATURE_PAL 
    [ComVisible(true)] 
    public enum EnvironmentVariableTarget {
        Process = 0, 
        User = 1,
        Machine = 2,
    }
#endif 

    [ComVisible(true)] 
    public static class Environment { 

        const int MaximumLength = 32767;  // maximun length for environment vairable name and value 
        internal sealed class ResourceHelper
        {
            private ResourceManager SystemResMgr;
 
            // To avoid infinite loops when calling GetResourceString.  See comments
            // in GetResourceString for this field. 
            private Stack currentlyLoading; 
 	
            // process-wide state (since this is only used in one domain), 
            // used to avoid the TypeInitialization infinite recusion
            // in GetResourceStringCode
            internal bool resourceManagerInited = false;
 
            internal class GetResourceStringUserData
            { 
                public ResourceHelper m_resourceHelper; 
                public String m_key;
                public String m_retVal; 
                public bool m_lockWasTaken;

                public GetResourceStringUserData(ResourceHelper resourceHelper, String key)
                { 
                    m_resourceHelper = resourceHelper;
                    m_key = key; 
                } 
            }
 
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
            internal String GetResourceString(String key) {
                if (key == null || key.Length == 0) {
                    BCLDebug.Assert(false, "Environment::GetResourceString with null or empty key.  Bug in caller, or weird recursive loading problem?"); 
                    return "[Resource lookup failed - null or empty resource name]";
                } 
 
                // We have a somewhat common potential for infinite
                // loops with mscorlib's ResourceManager.  If "potentially dangerous" 
                // code throws an exception, we will get into an infinite loop
                // inside the ResourceManager and this "potentially dangerous" code.
                // Potentially dangerous code includes the IO package, CultureInfo,
                // parts of the loader, some parts of Reflection, Security (including 
                // custom user-written permissions that may parse an XML file at
                // class load time), assembly load event handlers, etc.  Essentially, 
                // this is not a bounded set of code, and we need to fix the problem. 
                // Fortunately, this is limited to mscorlib's error lookups and is NOT
                // a general problem for all user code using the ResourceManager. 

                // The solution is to make sure only one thread at a time can call
                // GetResourceString.  Also, since resource lookups can be
                // reentrant, if the same thread comes into GetResourceString 
                // twice looking for the exact same resource name before
                // returning, we're going into an infinite loop and we should 
                // return a bogus string. 

                GetResourceStringUserData userData = new GetResourceStringUserData(this, key); 

                RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(GetResourceStringCode);
                RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(GetResourceStringBackoutCode);
 
                RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData);
                return userData.m_retVal; 
 
            }
 
            private void GetResourceStringCode(Object userDataIn)
            {
                GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn;
                ResourceHelper rh = userData.m_resourceHelper; 
                String key = userData.m_key;
 
                Monitor.ReliableEnter(rh, ref userData.m_lockWasTaken); 

                // Are we recursively looking up the same resource? 
                if (rh.currentlyLoading != null && rh.currentlyLoading.Count > 0 && rh.currentlyLoading.Contains(key)) {
                    // This is often a bug in the BCL, security, NLS+ code,
                    // or the loader somewhere.  However, this could also
                    // be a setup problem - check whether mscorlib & 
                    // mscorwks are both of the same build flavor.
                    String stackTrace = "[Couldn't get a stack trace]"; 
                    try 
                    {
                        StackTrace st = new StackTrace(true); 
                        // Don't attempt to localize strings in this stack trace, otherwise it could cause
                        // infinite recursion. This stack trace is used for an Assert message only, and
                        // so the lack of localization should not be an issue.
                        stackTrace = st.ToString( System.Diagnostics.StackTrace.TraceFormat.NoResourceLookup ); 
                    }
                    catch(StackOverflowException) {} 
                    catch(NullReferenceException) {} 
                    catch(OutOfMemoryException) {}
 
                    BCLDebug.Assert(false, "Infinite recursion during resource lookup.  Resource name: "+key+"\r\n"+stackTrace);

                    // Note: can't append the key name, since that may require
                    // an extra allocation... 
                    userData.m_retVal = "[Resource lookup failed - infinite recursion or critical failure detected.]";
                    return; 
                } 
                if (rh.currentlyLoading == null)
                    rh.currentlyLoading = new Stack(4); 

                // Call class constructors preemptively, so that we cannot get into an infinite
                // loop constructing a TypeInitializationException.  If this were omitted,
                // we could get the Infinite recursion assert above by failing type initialization 
                // between the Push and Pop calls below.
		 
                if (!rh.resourceManagerInited) 
                {
                    // process-critical code here.  No ThreadAbortExceptions 
                    // can be thrown here.  Other exceptions percolate as normal.
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try {
                    } 
                    finally {
                        RuntimeHelpers.RunClassConstructor(typeof(ResourceManager).TypeHandle); 
                        RuntimeHelpers.RunClassConstructor(typeof(ResourceReader).TypeHandle); 
                        RuntimeHelpers.RunClassConstructor(typeof(RuntimeResourceSet).TypeHandle);
                        RuntimeHelpers.RunClassConstructor(typeof(BinaryReader).TypeHandle); 
                        rh.resourceManagerInited = true;
                    }
		
                } 
		
                rh.currentlyLoading.Push(key); 
                if (rh.SystemResMgr == null) 
                    rh.SystemResMgr = new ResourceManager("mscorlib", typeof(Object).Assembly);
                String s = rh.SystemResMgr.GetString(key, null); 
                rh.currentlyLoading.Pop();

                BCLDebug.Assert(s!=null, "Managed resource string lookup failed.  Was your resource name misspelled?  Did you rebuild mscorlib after adding a resource to resources.txt?  Debug this w/ cordbg and bug whoever owns the code that called rhironment.GetResourceString.  Resource name was: \""+key+"\"");
 
                userData.m_retVal = s;
            } 
 
            [PrePrepareMethod]
            private void GetResourceStringBackoutCode(Object userDataIn, bool exceptionThrown) 
            {
                GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn;
                ResourceHelper rh = userData.m_resourceHelper;
 
                if (exceptionThrown)
                { 
                    if (userData.m_lockWasTaken) 
                    {
                        // Backout code - throw away potentially corrupt state 
                        rh.SystemResMgr = null;
                        rh.currentlyLoading = null;
                    }
                } 
                // Release the lock, if we took it.
                if (userData.m_lockWasTaken) 
                { 
                    Monitor.Exit(rh);
                } 
            }

        }
 

        private static ResourceHelper m_resHelper;  // Doesn't need to be initialized as they're zero-init. 
#if IO_CANCELLATION_ENABLED 
        private static bool s_IsLonghorn;
        private static bool s_CheckedOSType; 
#endif

        private static bool s_IsW2k3;
        private static volatile bool s_CheckedOSW2k3; 

        private const  int    MaxMachineNameLength = 256; 
 
        // Private object for locking instead of locking on a public type for SQL reliability work.
        private static Object s_InternalSyncObject; 
        private static Object InternalSyncObject {
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
            get {
                if (s_InternalSyncObject == null) { 
                    Object o = new Object();
                    Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); 
                } 
                return s_InternalSyncObject;
            } 
        }


#if !FEATURE_PAL 
        private static OperatingSystem m_os;  // Cached OperatingSystem value
        private static OSName m_osname; 
#endif // !FEATURE_PAL 

        /*==================================TickCount=================================== 
        **Action: Gets the number of ticks since the system was started.
        **Returns: The number of ticks since the system was started.
        **Arguments: None
        **Exceptions: None 
        ==============================================================================*/
        public static int TickCount { 
            get { 
                return nativeGetTickCount();
            } 
        }

        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern int nativeGetTickCount(); 

        // Terminates this process with the given exit code. 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern void ExitNative(int exitCode);
 
        [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
        public static void Exit(int exitCode) {
            ExitNative(exitCode);
        } 

 
        public static int ExitCode { 
            get {
                return nativeGetExitCode(); 
            }

            set {
                nativeSetExitCode(value); 
            }
        } 
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern void nativeSetExitCode(int exitCode); 

        // Gets the exit code of the process.
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern int nativeGetExitCode(); 

 
        [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        public static extern void FailFast(String message); 


        public static String CommandLine {
            get { 
                new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand();
                return GetCommandLineNative(); 
            } 
        }
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern String GetCommandLineNative();

        /*===============================CurrentDirectory=============================== 
        **Action:  Provides a getter and setter for the current directory.  The original
        **         current directory is the one from which the process was started. 
        **Returns: The current directory (from the getter).  Void from the setter. 
        **Arguments: The current directory to which to switch to the setter.
        **Exceptions: 
        ==============================================================================*/
        public static String CurrentDirectory {
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)] 
            get{
                return Directory.GetCurrentDirectory(); 
            } 

            [ResourceExposure(ResourceScope.Machine)] 
            [ResourceConsumption(ResourceScope.Machine)]
            set {
                Directory.SetCurrentDirectory(value);
            } 
        }
 
        // Returns the system directory (ie, C:\WinNT\System32). 
        public static String SystemDirectory {
            [ResourceExposure(ResourceScope.Machine)] 
            [ResourceConsumption(ResourceScope.Machine)]
            get {
                StringBuilder sb = new StringBuilder(Path.MAX_PATH);
                int r = Win32Native.GetSystemDirectory(sb, Path.MAX_PATH); 
                BCLDebug.Assert(r < Path.MAX_PATH, "r < Path.MAX_PATH");
                if (r==0) __Error.WinIOError(); 
                String path = sb.ToString(); 

                // Do security check 
                new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();

                return path;
            } 
        }
 
#if !FEATURE_PAL 
        // Returns the windows directory (ie, C:\WinNT).
        // Used by NLS+ custom culures only at the moment. 
        internal static String InternalWindowsDirectory {
            [ResourceExposure(ResourceScope.Machine)]
            [ResourceConsumption(ResourceScope.Machine)]
            get { 
                StringBuilder sb = new StringBuilder(Path.MAX_PATH);
                int r = Win32Native.GetWindowsDirectory(sb, Path.MAX_PATH); 
                BCLDebug.Assert(r < Path.MAX_PATH, "r < Path.MAX_PATH"); 
                if (r==0) __Error.WinIOError();
                String path = sb.ToString(); 

                return path;
            }
        } 

        public static String ExpandEnvironmentVariables(String name) 
        { 
            if (name == null)
                throw new ArgumentNullException("name"); 

            if (name.Length == 0) {
                return name;
            } 

            // Do a security check to guarantee we can read each of the 
            // individual environment variables requested here. 
            String[] varArray = name.Split(new char[] {'%'});
            StringBuilder vars = new StringBuilder(); 

            int currentSize = 100;
            StringBuilder blob = new StringBuilder(currentSize); // A somewhat reasonable default size
            int size; 

            for(int i=1; i currentSize) {
                    currentSize = size;
                    blob.Capacity = currentSize; 
                    blob.Length = 0;
                    size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize); 
                    if (size == 0) 
                        Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                } 

                String temp = blob.ToString();
                if (temp != envVar) { // We expanded successfully, we need to do String comparision here
                                     // since %FOO% can become %FOOD 
                    vars.Append(varArray[i]);
                    vars.Append(';'); 
                } 
            }
 
            new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand();

            blob.Length = 0;
            size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize); 
            if (size == 0)
                Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 
 
            while (size > currentSize) {
                currentSize = size; 
                blob.Capacity = currentSize;
                blob.Length = 0;

                size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize); 
                if (size == 0)
                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 
            } 

            return blob.ToString(); 
        }
#endif // FEATURE_PAL

        public static String MachineName { 
            get {
                // In future release of operating systems, you might be able to rename a machine without 
                // rebooting.  Therefore, don't cache this machine name. 
                new EnvironmentPermission(EnvironmentPermissionAccess.Read, "COMPUTERNAME").Demand();
                StringBuilder buf = new StringBuilder(MaxMachineNameLength); 
                int len = MaxMachineNameLength;
                if (Win32Native.GetComputerName(buf, ref len) == 0)
                    throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ComputerName"));
                return buf.ToString(); 
            }
        } 
 
        public static int ProcessorCount {
            get { 
                new EnvironmentPermission(EnvironmentPermissionAccess.Read, "NUMBER_OF_PROCESSORS").Demand();
                Win32Native.SYSTEM_INFO info = new Win32Native.SYSTEM_INFO();
                Win32Native.GetSystemInfo( ref info );
                return info.dwNumberOfProcessors; 
            }
        } 
 
        /*==============================GetCommandLineArgs==============================
        **Action: Gets the command line and splits it appropriately to deal with whitespace, 
        **        quotes, and escape characters.
        **Returns: A string array containing your command line arguments.
        **Arguments: None
        **Exceptions: None. 
        ==============================================================================*/
        public static String[] GetCommandLineArgs() { 
            new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand(); 
            return GetCommandLineArgsNative();
        } 

        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        private static extern String[] GetCommandLineArgsNative();
 
        // We need to keep this Fcall since it is used in AppDomain.cs.
        // If we call GetEnvironmentVariable from AppDomain.cs, we will use StringBuilder class. 
        // That has side effect to change the ApartmentState of the calling Thread to MTA. 
        // So runtime can't change the ApartmentState of calling thread any more.
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern String nativeGetEnvironmentVariable(String variable);

        /*============================GetEnvironmentVariable============================
        **Action: 
        **Returns:
        **Arguments: 
        **Exceptions: 
        ==============================================================================*/
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static String GetEnvironmentVariable(String variable)
        {
            if (variable == null) 
                throw new ArgumentNullException("variable");
            (new EnvironmentPermission(EnvironmentPermissionAccess.Read, variable)).Demand(); 
 
            StringBuilder blob = new StringBuilder(128); // A somewhat reasonable default size
            int requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity); 

            if( requiredSize == 0) {  //  GetEnvironmentVariable failed
                if( Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND)
                    return null; 
            }
 
            while (requiredSize > blob.Capacity) { // need to retry since the environment variable might be changed 
                blob.Capacity = requiredSize;
                blob.Length = 0; 
                requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity);
            }
            return blob.ToString();
        } 

#if !FEATURE_PAL 
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static string GetEnvironmentVariable( string variable, EnvironmentVariableTarget target) 
        {
            if( target == EnvironmentVariableTarget.Process) {
                return GetEnvironmentVariable(variable);
            } 

            if (variable == null) { 
                throw new ArgumentNullException("variable"); 
            }
 
            // Win9x doesn't support machine or user level environment variables
            if( IsWin9X() ){
                throw new NotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x"));
            } 

            (new EnvironmentPermission(PermissionState.Unrestricted)).Demand(); 
 
            if( target == EnvironmentVariableTarget.Machine) {
                using (RegistryKey environmentKey = 
                       Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) {
                   string value = environmentKey.GetValue(variable) as string;
                   return value;
                } 
            }
            else if( target == EnvironmentVariableTarget.User) { 
                using (RegistryKey environmentKey = 
                       Registry.CurrentUser.OpenSubKey("Environment", false)) {
                   string value = environmentKey.GetValue(variable) as string; 
                   return value;
                }
            }
            else { 
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Arg_EnumIllegalVal"), (int)target));
            } 
        } 
#endif
 
        /*===========================GetEnvironmentVariables============================
        **Action: Returns an IDictionary containing all enviroment variables and their values.
        **Returns: An IDictionary containing all environment variables and their values.
        **Arguments: None. 
        **Exceptions: None.
        ==============================================================================*/ 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        [ResourceExposure(ResourceScope.Machine)]
        private static extern char[] nativeGetEnvironmentCharArray(); 

        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public static IDictionary GetEnvironmentVariables() 
        {
            // Using an FCall is better than using PInvoke here since 
            // Interop Marshaler can't handle string which contains '\0', we need 
            // to allocate an unmanaged buffer, do the conversion and free the buffer
            // if we do use PInvoke. 
            char[] block = nativeGetEnvironmentCharArray();
            if( block == null) {
                throw new OutOfMemoryException();
            } 

            Hashtable table = new Hashtable(20); 
            StringBuilder vars = new StringBuilder(); 
            // Copy strings out, parsing into pairs and inserting into the table.
            // The first few environment variable entries start with an '='! 
            // The current working directory of every drive (except for those drives
            // you haven't cd'ed into in your DOS window) are stored in the
            // environment block (as =C:=pwd) and the program's exit code is
            // as well (=ExitCode=00000000)  Skip all that start with =. 
            // Read docs about Environment Blocks on MSDN's CreateProcess page.
 
            // Format for GetEnvironmentStrings is: 
            // (=HiddenVar=value\0 | Variable=value\0)* \0
            // See the description of Environment Blocks in MSDN's 
            // CreateProcess page (null-terminated array of null-terminated strings).
            // Note the =HiddenVar's aren't always at the beginning.

            // GetEnvironmentCharArray will not return the trailing 0 to terminate 
            // the array - we have the array length instead.
            bool first = true; 
            for(int i=0; i= MaximumLength) {
                    throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); 
                }
            }

            if(!Win32Native.SetEnvironmentVariable(variable, value)) { 
                int errorCode = Marshal.GetLastWin32Error();
 
                // Allow user to try to clear a environment variable 
                if( errorCode == Win32Native.ERROR_ENVVAR_NOT_FOUND) {
                    return; 
                }

                // The error message from Win32 is "The filename or extension is too long",
                // which is not accurate. 
                if( errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE) {
                    throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); 
                } 

                throw new ArgumentException(Win32Native.GetMessage(errorCode)); 
            }
        }

        private static void CheckEnvironmentVariableName(string variable) { 
            if (variable == null) {
                throw new ArgumentNullException("variable"); 
            } 

            if( variable.Length == 0) { 
                throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "variable");
            }

            if( variable[0] == '\0') { 
                throw new ArgumentException(Environment.GetResourceString("Argument_StringFirstCharIsZero"), "variable");
            } 
 
            if( variable.Length >= MaximumLength ) {
                throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); 
            }

            if( variable.IndexOf('=') != -1) {
                throw new ArgumentException(Environment.GetResourceString("Argument_IllegalEnvVarName")); 
            }
        } 
 
#if !FEATURE_PAL
        [ResourceExposure(ResourceScope.Machine)] 
        [ResourceConsumption(ResourceScope.Machine)]
        public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) {
            if( target == EnvironmentVariableTarget.Process) {
                SetEnvironmentVariable(variable, value); 
                return;
            } 
 
            CheckEnvironmentVariableName(variable);
 
            const int MaxKeyLength = 255;  // maximum registry key length
            // Win9X doesn't support registry name with more than 255 characters
            if( variable.Length >= MaxKeyLength) {
                throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarName")); 
            }
 
            // Win9x doesn't support machine or user level environment variables 
            if( IsWin9X() ){
                throw new NotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x")); 
            }

            new EnvironmentPermission(PermissionState.Unrestricted).Demand();
            // explicitly null out value if is the empty string. 
            if (String.IsNullOrEmpty(value) || value[0] == '\0') {
                value = null; 
            } 

            if( target == EnvironmentVariableTarget.Machine) { 
                using (RegistryKey environmentKey =
                       Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", true)) {
                   if (value == null)
                       environmentKey.DeleteValue(variable, false); 
                   else
                       environmentKey.SetValue(variable, value); 
                } 
            }
            else if( target == EnvironmentVariableTarget.User) { 
                using (RegistryKey environmentKey =
                       Registry.CurrentUser.OpenSubKey("Environment", true)) {
                   if (value == null)
                       environmentKey.DeleteValue(variable, false); 
                   else
                       environmentKey.SetValue(variable, value); 
                } 
            }
            else { 
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Arg_EnumIllegalVal"), (int)target));
            }

            // send a WM_SETTINGCHANGE message to all windows 
            IntPtr r = Win32Native.SendMessageTimeout(new IntPtr(Win32Native.HWND_BROADCAST), Win32Native.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero);
 
            if (r == IntPtr.Zero) BCLDebug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error()); 
        }
#endif 


        /*===============================GetLogicalDrives===============================
        **Action: Retrieves the names of the logical drives on this machine in the  form "C:\". 
        **Arguments:   None.
        **Exceptions:  IOException. 
        **Permissions: SystemInfo Permission. 
        ==============================================================================*/
        public static String[] GetLogicalDrives() { 
#if !PLATFORM_UNIX
            new EnvironmentPermission(PermissionState.Unrestricted).Demand();

            int drives = Win32Native.GetLogicalDrives(); 
            if (drives==0)
                __Error.WinIOError(); 
            uint d = (uint)drives; 
            int count = 0;
            while (d != 0) { 
                if (((int)d & 1) != 0) count++;
                d >>= 1;
            }
            String[] result = new String[count]; 
            char[] root = new char[] {'A', ':', '\\'};
            d = (uint)drives; 
            count = 0; 
            while (d != 0) {
                if (((int)d & 1) != 0) { 
                    result[count++] = new String(root);
                }
                d >>= 1;
                root[0]++; 
            }
            return result; 
#else 
            return new String[0];
#endif // !PLATFORM_UNIX 
        }

        /*===================================NewLine====================================
        **Action: A property which returns the appropriate newline string for the given 
        **        platform.
        **Returns: \r\n on Win32. 
        **Arguments: None. 
        **Exceptions: None.
        ==============================================================================*/ 
        public static String NewLine {
            get {
#if !PLATFORM_UNIX
                return "\r\n"; 
#else
                return "\n"; 
#endif // !PLATFORM_UNIX 
            }
        } 


        /*===================================Version====================================
        **Action: Returns the COM+ version struct, describing the build number. 
        **Returns:
        **Arguments: 
        **Exceptions: 
        ==============================================================================*/
        public static Version Version { 
            get {
                return new Version(ThisAssembly.InformationalVersion);
            }
        } 

 
        /*==================================WorkingSet================================== 
        **Action:
        **Returns: 
        **Arguments:
        **Exceptions:
        ==============================================================================*/
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern long nativeGetWorkingSet();
 
        public static long WorkingSet { 
            get {
                new EnvironmentPermission(PermissionState.Unrestricted).Demand(); 
                return (long)nativeGetWorkingSet();
            }
        }
 
#if !FEATURE_PAL
        /*==================================OSVersion=================================== 
        **Action: 
        **Returns:
        **Arguments: 
        **Exceptions:
        ==============================================================================*/
        public static OperatingSystem OSVersion {
            get { 
                if (m_os==null) { // We avoid the lock since we don't care if two threads will set this at the same time.
                    Microsoft.Win32.Win32Native.OSVERSIONINFO osvi = new Microsoft.Win32.Win32Native.OSVERSIONINFO(); 
                    if (!Win32Native.GetVersionEx(osvi)) { 
                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion"));
                    } 

                    Microsoft.Win32.Win32Native.OSVERSIONINFOEX osviEx = new Microsoft.Win32.Win32Native.OSVERSIONINFOEX();
                    if( osvi.PlatformId != Win32Native.VER_PLATFORM_WIN32_WINDOWS) {
                        // for OS other than win9x, we need to get Service pack information 
                        if (!Win32Native.GetVersionEx(osviEx)) {
                            throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion")); 
                        } 
                    }
 
                    PlatformID id;
                    switch (osvi.PlatformId) {
                    case Win32Native.VER_PLATFORM_WIN32_NT:
                        id = PlatformID.Win32NT; 
                        break;
 
                    case Win32Native.VER_PLATFORM_WIN32_WINDOWS: 
                        id = PlatformID.Win32Windows;
                        break; 

                    case Win32Native.VER_PLATFORM_WIN32s:
                        id = PlatformID.Win32S;
                        break; 

                    case Win32Native.VER_PLATFORM_WINCE: 
                        id = PlatformID.WinCE; 
                        break;
 
                    default:
                        BCLDebug.Assert(false,"false");
                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_InvalidPlatformID"));
                    } 

                    Version v =  new Version(osvi.MajorVersion, osvi.MinorVersion, osvi.BuildNumber, (osviEx.ServicePackMajor << 16) |osviEx.ServicePackMinor); 
                    m_os = new OperatingSystem(id, v, osvi.CSDVersion); 
                }
                BCLDebug.Assert(m_os != null, "m_os != null"); 
                return m_os;
            }
        }
 
#if IO_CANCELLATION_ENABLED
        internal static bool IsLonghorn { 
            get { 
                if (!s_CheckedOSType) {
                    OperatingSystem OS = Environment.OSVersion; 
                    s_IsLonghorn = OS.Platform == PlatformID.Win32NT && OS.Version.Major >= 6;
                    s_CheckedOSType = true;
                }
                return s_IsLonghorn; 
            }
        } 
#endif 

    internal static bool IsW2k3 { 
            get {
                if (!s_CheckedOSW2k3) {
                    OperatingSystem OS = Environment.OSVersion;
                    s_IsW2k3 = ( (OS.Platform == PlatformID.Win32NT) && (OS.Version.Major == 5) && (OS.Version.Minor == 2)); 
                    s_CheckedOSW2k3 = true;
                } 
                return s_IsW2k3; 
            }
        } 

        internal static bool RunningOnWinNT {
            get {
                return OSVersion.Platform == PlatformID.Win32NT; 
            }
        } 
 
        [Serializable]
        internal enum OSName 
        {
            Invalid = 0,
            Unknown = 1,
            Win9x = 0x40, 
            Win95 = 1 | Win9x,
            Win98 = 2 | Win9x, 
            WinMe = 3 | Win9x, 
            WinNT = 0x80,
            Nt4   = 1 | WinNT, 
            Win2k   = 2 | WinNT
        }

        internal static OSName OSInfo 
        {
            get 
            { 
                if (m_osname == OSName.Invalid)
                { 
                    lock(InternalSyncObject)
                    {
                        if (m_osname == OSName.Invalid)
                        { 
                            Microsoft.Win32.Win32Native.OSVERSIONINFO osvi = new Microsoft.Win32.Win32Native.OSVERSIONINFO();
                            bool r = Win32Native.GetVersionEx(osvi); 
                            if (!r) 
                            {
                                BCLDebug.Assert(r, "OSVersion native call failed."); 
                                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion"));
                            }
                            switch (osvi.PlatformId)
                                { 
                                case Win32Native.VER_PLATFORM_WIN32_NT:
                                    switch(osvi.MajorVersion) 
                                    { 
                                        case 5:
                                            m_osname = OSName.Win2k; 
                                            break;
                                        case 4:
                                            m_osname = OSName.Nt4;
                                            break; 
                                        default:
                                            m_osname = OSName.WinNT; 
                                            break; 
                                    }
                                    break; 

                                case Win32Native.VER_PLATFORM_WIN32_WINDOWS:
                                    switch(osvi.MajorVersion)
                                    { 
                                        case 5:
                                            m_osname = OSName.WinMe; 
                                            break; 
                                        case 4:
                                            if (osvi.MinorVersion == 0) 
                                                m_osname = OSName.Win95;
                                            else
                                                m_osname = OSName.Win98;
                                            break; 
                                        default:
                                            m_osname = OSName.Win9x; 
                                            break; 
                                   }
                                   break; 

                                default:
                                    m_osname = OSName.Unknown; // Unknown OS
                                    break; 

                            } 
                        } 
                    }
                } 
                return m_osname;
            }
        }
#endif // !FEATURE_PAL 

        // This needs to be removed in a future release. 
        internal static bool IsWin9X() { 
#if FEATURE_PAL
            return false; 
#else
            return Environment.OSVersion.Platform == PlatformID.Win32Windows;
#endif // FEATURE_PAL
        } 

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal static extern bool nativeIsWin9x(); 

 
        /*==================================StackTrace==================================
        **Action:
        **Returns:
        **Arguments: 
        **Exceptions:
        ==============================================================================*/ 
        public static String StackTrace { 
            get {
                new EnvironmentPermission(PermissionState.Unrestricted).Demand(); 
                return GetStackTrace(null, true);
            }
        }
 
        internal static String GetStackTrace(Exception e, bool needFileInfo)
        { 
            // Note: Setting needFileInfo to true will start up COM and set our 
            // apartment state.  Try to not call this when passing "true"
            // before the EE's ExecuteMainMethod has had a chance to set up the 
            // apartment state.  --
            StackTrace st;
            if (e == null)
                st = new StackTrace(needFileInfo); 
            else
                st = new StackTrace(e, needFileInfo); 
 
            // Do no include a trailing newline for backwards compatibility
            return st.ToString( System.Diagnostics.StackTrace.TraceFormat.Normal ); 
        }

        private static void InitResourceHelper() {
 
            // Only the default AppDomain should have a ResourceHelper.  All calls to
            // GetResourceString from any AppDomain delegate to GetResourceStringLocal 
            // in the default AppDomain via the fcall GetResourceFromDefault. 

            // Use Thread.BeginCriticalRegion to tell the CLR all managed 
            // allocations within this block are appdomain-critical.
            // Use a CER to ensure we always exit this region.
            bool enteredRegion = false;
            bool tookLock = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                RuntimeHelpers.PrepareConstrainedRegions(); 
                try {
                } 
                finally {
                    Thread.BeginCriticalRegion();
                    enteredRegion = true;
                    Monitor.Enter(Environment.InternalSyncObject); 
                    tookLock = true;
                } 
 
                if (m_resHelper == null) {
                    ResourceHelper rh = new ResourceHelper(); 
                    System.Threading.Thread.MemoryBarrier();
                    m_resHelper =rh;
                }
            } 
            finally {
                if (tookLock) 
                    Monitor.Exit(Environment.InternalSyncObject); 
                if (enteredRegion)
                    Thread.EndCriticalRegion(); 
            }
        }

        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        internal extern static String GetResourceFromDefault(String key);
 
        // Looks up the resource string value for key. 
        //
        // if you change this method's signature then you must change the code that calls it 
        // in excep.cpp and probably you will have to visit mscorlib.h to add the new signature
        // as well as metasig.h to create the new signature type
        internal static String GetResourceStringLocal(String key) {
            if (m_resHelper == null) 
                InitResourceHelper();
 
            return m_resHelper.GetResourceString(key); 
        }
 
        [ResourceExposure(ResourceScope.None)]
        internal static String GetResourceString(String key) {
            return GetResourceFromDefault(key);
        } 

        [ResourceExposure(ResourceScope.None)] 
        internal static String GetResourceString(String key, params Object[]values) { 
            String s = GetResourceFromDefault(key);
            return String.Format(CultureInfo.CurrentCulture, s, values); 
        }

        public static bool HasShutdownStarted {
            get { return nativeHasShutdownStarted(); } 
        }
 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        private static extern bool nativeHasShutdownStarted();
 
        // This is the temporary Whidbey stub for compatibility flags
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern bool GetCompatibilityFlag(CompatibilityFlag flag);
 
        public static string UserName {
            get { 
                new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserName").Demand(); 

                StringBuilder sb = new StringBuilder(256); 
                int size = sb.Capacity;
                Win32Native.GetUserName(sb, ref size);
                return sb.ToString();
            } 
        }
 
#if !FEATURE_PAL 
        // Note that this is a handle to a process window station, but it does
        // not need to be closed.  CloseWindowStation would ignore this handle. 
        // We also do handle equality checking as well.  This isn't a great fit
        // for SafeHandle.  We don't gain anything by using SafeHandle here.
        private static IntPtr processWinStation;        // Doesn't need to be initialized as they're zero-init.
        private static bool isUserNonInteractive; 

        public static bool UserInteractive { 
            [ResourceExposure(ResourceScope.None)] 
            [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
            get { 
                if ((OSInfo & OSName.WinNT) == OSName.WinNT) { // On WinNT
                    IntPtr hwinsta = Win32Native.GetProcessWindowStation();
                    if (hwinsta != IntPtr.Zero && processWinStation != hwinsta) {
                        int lengthNeeded = 0; 
                        Win32Native.USEROBJECTFLAGS flags = new Win32Native.USEROBJECTFLAGS();
                        if (Win32Native.GetUserObjectInformation(hwinsta, Win32Native.UOI_FLAGS, flags, Marshal.SizeOf(flags),ref lengthNeeded)) { 
                            if ((flags.dwFlags & Win32Native.WSF_VISIBLE) == 0) { 
                                isUserNonInteractive = true;
                            } 
                        }
                        processWinStation = hwinsta;
                    }
                } 
                // The logic is reversed to avoid static initialization to true
                return !isUserNonInteractive; 
            } 
        }
 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        public static string GetFolderPath(SpecialFolder folder) {
            if (!Enum.IsDefined(typeof(SpecialFolder),folder)) 
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Arg_EnumIllegalVal"), (int)folder));
            StringBuilder sb = new StringBuilder(Path.MAX_PATH); 
            Win32Native.SHGetFolderPath(IntPtr.Zero, (int) folder, IntPtr.Zero, Win32Native.SHGFP_TYPE_CURRENT, sb); 
            String s =  sb.ToString();
            new FileIOPermission( FileIOPermissionAccess.PathDiscovery, s ).Demand(); 
            return s;
        }

        public static string UserDomainName { 
                get {
                    new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserDomain").Demand(); 
 
                    byte[] sid = new byte[1024];
                    int sidLen = sid.Length; 
                    StringBuilder domainName = new StringBuilder(1024);
                    int domainNameLen = domainName.Capacity;
                    int peUse;
 
                    // Note: This doesn't work on Win9x.  We can implement this
                    // functionality on Win9x by writing a 16 bit DLL and 
                    // calling the LAN Manager method NetWkstaGetInfo().  See 
                    // http://support.microsoft.com/support/kb/articles/Q155/6/98.asp
                    // We don't have the time to implement this in V1. Hopefully 
                    // by the time V2 rolls around, everyone will run Windows XP.
                    byte ret;
                    if (OSVersion.Platform == PlatformID.Win32NT) {
                        ret =  Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen); 
                        if (ret == 1) {
                            string samName = domainName.ToString(); 
                            int index = samName.IndexOf('\\'); 
                            if( index != -1) {
                                return samName.Substring(0, index); 
                            }
                        }
                        domainNameLen = domainName.Capacity;
                    } 

                    bool success = Win32Native.LookupAccountName(null, UserName, sid, ref sidLen, domainName, ref domainNameLen, out peUse); 
                    if (!success)  { 
                        int hr = Marshal.GetLastWin32Error();
                        if (hr == Win32Native.ERROR_CALL_NOT_IMPLEMENTED) 
                            throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_Win9x"));
                        throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UserDomainName"));
                    }
 
                    return domainName.ToString();
                } 
            } 

        [ComVisible(true)] 
        public enum SpecialFolder {
            //
            //      Represents the file system directory that serves as a common repository for
            //       application-specific data for the current, roaming user. 
            //     A roaming user works on more than one computer on a network. A roaming user's
            //       profile is kept on a server on the network and is loaded onto a system when the 
            //       user logs on. 
            //
            ApplicationData =  Win32Native.CSIDL_APPDATA, 
            //
            //      Represents the file system directory that serves as a common repository for application-specific data that
            //       is used by all users.
            // 
            CommonApplicationData =  Win32Native.CSIDL_COMMON_APPDATA,
            // 
            //     Represents the file system directory that serves as a common repository for application specific data that 
            //       is used by the current, non-roaming user.
            // 
            LocalApplicationData =  Win32Native.CSIDL_LOCAL_APPDATA,
            //
            //     Represents the file system directory that serves as a common repository for Internet
            //       cookies. 
            //
            Cookies =  Win32Native.CSIDL_COOKIES, 
            Desktop = Win32Native.CSIDL_DESKTOP, 
            //
            //     Represents the file system directory that serves as a common repository for the user's 
            //       favorite items.
            //
            Favorites =  Win32Native.CSIDL_FAVORITES,
            // 
            //     Represents the file system directory that serves as a common repository for Internet
            //       history items. 
            // 
            History =  Win32Native.CSIDL_HISTORY,
            // 
            //     Represents the file system directory that serves as a common repository for temporary
            //       Internet files.
            //
            InternetCache =  Win32Native.CSIDL_INTERNET_CACHE, 
            //
            //      Represents the file system directory that contains 
            //       the user's program groups. 
            //
            Programs =  Win32Native.CSIDL_PROGRAMS, 
            MyComputer =  Win32Native.CSIDL_DRIVES,
            MyMusic =  Win32Native.CSIDL_MYMUSIC,
            MyPictures = Win32Native.CSIDL_MYPICTURES,
            // 
            //     Represents the file system directory that contains the user's most recently used
            //       documents. 
            // 
            Recent =  Win32Native.CSIDL_RECENT,
            // 
            //     Represents the file system directory that contains Send To menu items.
            //
            SendTo =  Win32Native.CSIDL_SENDTO,
            // 
            //     Represents the file system directory that contains the Start menu items.
            // 
            StartMenu =  Win32Native.CSIDL_STARTMENU, 
            //
            //     Represents the file system directory that corresponds to the user's Startup program group. The system 
            //       starts these programs whenever any user logs on to Windows NT, or
            //       starts Windows 95 or Windows 98.
            //
            Startup =  Win32Native.CSIDL_STARTUP, 
            //
            //     System directory. 
            // 
            System =  Win32Native.CSIDL_SYSTEM,
            // 
            //     Represents the file system directory that serves as a common repository for document
            //       templates.
            //
            Templates =  Win32Native.CSIDL_TEMPLATES, 
            //
            //     Represents the file system directory used to physically store file objects on the desktop. 
            //       This should not be confused with the desktop folder itself, which is 
            //       a virtual folder.
            // 
            DesktopDirectory =  Win32Native.CSIDL_DESKTOPDIRECTORY,
            //
            //     Represents the file system directory that serves as a common repository for documents.
            // 
            Personal =  Win32Native.CSIDL_PERSONAL,
 
            // "MyDocuments" is a better name than "Personal" 
            MyDocuments = Win32Native.CSIDL_PERSONAL,
            // 
            //     Represents the program files folder.
            //
            ProgramFiles =  Win32Native.CSIDL_PROGRAM_FILES,
            // 
            //     Represents the folder for components that are shared across applications.
            // 
            CommonProgramFiles =  Win32Native.CSIDL_PROGRAM_FILES_COMMON, 
        }
#endif // !FEATURE_PAL 
    }
}


                        

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