* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / corlib / System / Environment.cs
index 1149d1d2b0b89a385dd726530b94c52558f6286b..34aab93f79f970d64e7f3eb654401b2a0f31a7f9 100644 (file)
@@ -41,7 +41,7 @@ using System.Text;
 
 namespace System {
 
-#if NET_2_0_WAIT_TILL_FIX_IS_MERGED_INTO_GMCS
+#if NET_2_0
        public static class Environment {
 #else
        public sealed class Environment {
@@ -53,14 +53,14 @@ namespace System {
                /*
                 * This is the version number of the corlib-runtime interface. When
                 * making changes to this interface (by changing the layout
-                * of classes the runtime knows about, changing icall semantics etc),
-                * increment this variable. Also increment the
+                * of classes the runtime knows about, changing icall signature or
+                * semantics etc), increment this variable. Also increment the
                 * pair of this variable in the runtime in metadata/appdomain.c.
                 * Changes which are already detected at runtime, like the addition
                 * of icalls, do not require an increment.
                 */
-               private const int mono_corlib_version = 32;
-               
+               private const int mono_corlib_version = 54;
+               
                [MonoTODO]
                public enum SpecialFolder
                {       // TODO: Determine if these windoze style folder identifiers 
@@ -180,7 +180,12 @@ namespace System {
                        get {
                                if (os == null) {
                                        Version v = Version.CreateFromString (GetOSVersionString ());
-                                       os = new OperatingSystem (Platform, v);
+                                       PlatformID p = Platform;
+#if NET_2_0
+                                       if ((int) p == 128)
+                                               p = PlatformID.Unix;
+#endif
+                                       os = new OperatingSystem (p, v);
                                }
                                return os;
                        }
@@ -192,7 +197,7 @@ namespace System {
                public static string StackTrace {
                        [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
                        get {
-                               System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace (1);
+                               System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace (1, true);
                                return trace.ToString ();
                        }
                }
@@ -249,15 +254,7 @@ namespace System {
                /// </summary>
                public static Version Version {
                        get {
-#if NET_2_0
-                               // FIXME: this is the version number for MS.NET 2.0 beta1. 
-                               // It must be changed when the final version is released.
-                               return new Version (2, 0, 40607, 16);
-#elif NET_1_1                              
-                               return new Version (1, 1, 4322, 573);
-#else
-                               return new Version (1, 0, 3705, 288);
-#endif
+                               return new Version (Consts.FxFileVersion);
                        }
                }
 
@@ -291,14 +288,13 @@ namespace System {
                        if (off1 == len - 1 || (off2 = name.IndexOf ('%', off1 + 1)) == -1)
                                return name;
 
-                       PlatformID platform = Platform;
                        StringBuilder result = new StringBuilder ();
                        result.Append (name, 0, off1);
                        Hashtable tbl = null;
                        do {
                                string var = name.Substring (off1 + 1, off2 - off1 - 1);
                                string value = GetEnvironmentVariable (var);
-                               if (value == null && (int) platform != 128) {
+                               if (value == null && Environment.IsRunningOnWindows) {
                                        // On windows, env. vars. are case insensitive
                                        if (tbl == null)
                                                tbl = GetEnvironmentVariablesNoCase ();
@@ -334,7 +330,7 @@ namespace System {
                                else
                                        textLen = off1 - oldOff2;
                                if(off1 >= oldOff2 || off1 == -1)
-                                       result.Append (name.Substring (oldOff2+1, textLen));
+                                       result.Append (name, oldOff2+1, textLen);
                        } while (off2 > -1 && off2 < len);
                                
                        return result.ToString ();
@@ -378,7 +374,7 @@ namespace System {
                /// <summary>
                /// Return a set of all environment variables and their values
                /// </summary>
-          
+#if NET_2_0
                public static IDictionary GetEnvironmentVariables ()
                {
                        StringBuilder sb = null;
@@ -403,7 +399,17 @@ namespace System {
                        }
                        return vars;
                }
-
+#else
+               [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
+               public static IDictionary GetEnvironmentVariables ()
+               {
+                       Hashtable vars = new Hashtable ();
+                       foreach (string name in GetEnvironmentVariableNames ()) {
+                               vars [name] = internalGetEnvironmentVariable (name);
+                       }
+                       return vars;
+               }
+#endif
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                private extern static string GetWindowsFolderPath (int folder);
@@ -416,7 +422,7 @@ namespace System {
                {
                        string dir = null;
 
-                       if ((int) Platform != 128) {
+                       if (Environment.IsRunningOnWindows) {
                                dir = GetWindowsFolderPath ((int) folder);
                        } else {
                                dir = InternalGetFolderPath (folder);
@@ -508,7 +514,6 @@ namespace System {
 
                 
 #if NET_2_0
-               [MonoTODO ("Machine and User targets aren't supported")]
                public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target)
                {
                        switch (target) {
@@ -516,67 +521,105 @@ namespace System {
                                return GetEnvironmentVariable (variable);
                        case EnvironmentVariableTarget.Machine:
                                new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
-                               // under Windows this reads the LOCAL_MACHINE registry key for env vars
-                               throw new NotImplementedException ();
+                               if (!IsRunningOnWindows)
+                                       return null;
+                               using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
+                                       return env.GetValue (variable).ToString ();
+                               }
                        case EnvironmentVariableTarget.User:
                                new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
-                               // under Windows this reads the CURRENT_USER registry key for env vars
-                               throw new NotImplementedException ();
+                               if (!IsRunningOnWindows)
+                                       return null;
+                               using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", false)) {
+                                       return env.GetValue (variable).ToString ();
+                               }
                        default:
                                throw new ArgumentException ("target");
                        }
                }
 
-               [MonoTODO ("Machine and User targets aren't supported")]
                public static IDictionary GetEnvironmentVariables (EnvironmentVariableTarget target)
                {
+                       IDictionary variables = (IDictionary)new Hashtable ();
                        switch (target) {
                        case EnvironmentVariableTarget.Process:
-                               return GetEnvironmentVariables ();
+                               variables = GetEnvironmentVariables ();
+                               break;
                        case EnvironmentVariableTarget.Machine:
                                new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
-                               // under Windows this reads the LOCAL_MACHINE registry key for env vars
-                               throw new NotImplementedException ();
+                               if (IsRunningOnWindows) {
+                                       using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
+                                               string[] value_names = env.GetValueNames ();
+                                               foreach (string value_name in value_names)
+                                                       variables.Add (value_name, env.GetValue (value_name));
+                                       }
+                               }
+                               break;
                        case EnvironmentVariableTarget.User:
                                new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
-                               // under Windows this reads the CURRENT_USER registry key for env vars
-                               throw new NotImplementedException ();
+                               if (IsRunningOnWindows) {
+                                       using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment")) {
+                                               string[] value_names = env.GetValueNames ();
+                                               foreach (string value_name in value_names)
+                                                       variables.Add (value_name, env.GetValue (value_name));
+                                       }
+                               }
+                               break;
                        default:
                                throw new ArgumentException ("target");
                        }
+                       return variables;
                }
 
-               [MonoTODO]
                [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
                public static void SetEnvironmentVariable (string variable, string value)
                {
-                       InternalSetEnvironmentVariable (variable, value);
+                       SetEnvironmentVariable (variable, value, EnvironmentVariableTarget.Process);
                }
 
-               [MonoTODO]
-               [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
+               [EnvironmentPermission (SecurityAction.Demand, Unrestricted = true)]
                public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target)
                {
+                       if (variable == null)
+                               throw new ArgumentNullException ("variable");
+                       if (variable == String.Empty)
+                               throw new ArgumentException ("String cannot be of zero length.", "variable");
+                       if (variable.IndexOf ('=') != -1)
+                               throw new ArgumentException ("Environment variable name cannot contain an equal character.", "variable");
+                       if (variable[0] == '\0')
+                               throw new ArgumentException ("The first char in the string is the null character.", "variable");
+
                        switch (target) {
                        case EnvironmentVariableTarget.Process:
                                InternalSetEnvironmentVariable (variable, value);
                                break;
                        case EnvironmentVariableTarget.Machine:
-                               // under Windows this reads the LOCAL_MACHINE registry key for env vars
-                               throw new NotImplementedException ();
+                               if (!IsRunningOnWindows)
+                                       return;
+                               using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true)) {
+                                       if (value == null || value.Length == 0)
+                                               env.DeleteValue (variable, false);
+                                       else
+                                               env.SetValue (variable, value);
+                               }
+                               break;
                        case EnvironmentVariableTarget.User:
-                               // under Windows this reads the CURRENT_USER registry key for env vars
-                               throw new NotImplementedException ();
+                               if (!IsRunningOnWindows)
+                                       return;
+                               using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", true)) {
+                                       if (value == null || value.Length == 0)
+                                               env.DeleteValue (variable, false);
+                                       else
+                                               env.SetValue (variable, value);
+                               }
+                               break;
                        default:
                                throw new ArgumentException ("target");
                        }
                }
 
-               // FIXME: to be changed as an icall when implemented
-               internal static void InternalSetEnvironmentVariable (string variable, string value)
-               {
-                       throw new NotImplementedException ();
-               }
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               internal static extern void InternalSetEnvironmentVariable (string variable, string value);
 
                [MonoTODO]
                public static int ProcessorCount {
@@ -589,18 +632,22 @@ namespace System {
                }
 
                [MonoTODO ("not much documented")]
-               // FIXME: doesn't seems to have any protection ?!? reported as FDBK20543
+               [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode=true)]
                public static void FailFast (string message)
                {
                        throw new NotImplementedException ();
                }
-#endif                
-                
+#endif
+
                // private methods
 
+               internal static bool IsRunningOnWindows {
+                       get { return ((int) Platform != 128); }
+               }
+
                private static string GacPath {
                        get {
-                               if ((int) Platform != 128) {
+                               if (Environment.IsRunningOnWindows) {
                                        /* On windows, we don't know the path where mscorlib.dll will be installed */
                                        string corlibDir = new DirectoryInfo (Path.GetDirectoryName (typeof (int).Assembly.Location)).Parent.Parent.FullName;
                                        return Path.Combine (Path.Combine (corlibDir, "mono"), "gac");