using System.Security;
using System.Security.Permissions;
using System.Text;
+using System.Runtime.InteropServices;
namespace System {
+#if NET_2_0
+ [ComVisible (true)]
+#endif
#if NET_2_0
public static class Environment {
#else
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
- private const int mono_corlib_version = 53;
+ private const int mono_corlib_version = 61;
- [MonoTODO]
public enum SpecialFolder
{ // TODO: Determine if these windoze style folder identifiers
// have unix/linux counterparts
public static string StackTrace {
[EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
get {
- System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace (1, true);
+ System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace (0, true);
return trace.ToString ();
}
}
/// <summary>
/// Gets a flag indicating whether the process is in interactive mode
/// </summary>
- [MonoTODO]
+ [MonoTODO ("Currently always returns false, regardless of interactive state")]
public static bool UserInteractive {
get {
return false;
/// </summary>
public static Version Version {
get {
- return new Version (Consts.RuntimeVersion);
+ return new Version (Consts.FxFileVersion);
}
}
/// <summary>
/// Get the amount of physical memory mapped to process
/// </summary>
- [MonoTODO]
+ [MonoTODO ("Currently always returns zero")]
public static long WorkingSet {
[EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
get { return 0; }
return dir;
}
+ private static string ReadXdgUserDir (string config_dir, string home_dir,
+ string key, string fallback)
+ {
+ string env_path = internalGetEnvironmentVariable (key);
+ if (env_path != null && env_path != String.Empty) {
+ return env_path;
+ }
+
+ string user_dirs_path = Path.Combine (config_dir, "user-dirs.dirs");
+
+ if (!File.Exists (user_dirs_path)) {
+ return Path.Combine (home_dir, fallback);
+ }
+
+ try {
+ using(StreamReader reader = new StreamReader (user_dirs_path)) {
+ string line;
+ while ((line = reader.ReadLine ()) != null) {
+ line = line.Trim ();
+ int delim_index = line.IndexOf ('=');
+ if(delim_index > 8 && line.Substring (0, delim_index) == key) {
+ string path = line.Substring (delim_index + 1).Trim ('"');
+ bool relative = false;
+
+ if (path.StartsWith ("$HOME/")) {
+ relative = true;
+ path = path.Substring (6);
+ } else if (!path.StartsWith ("/")) {
+ relative = true;
+ }
+
+ return relative ? Path.Combine (home_dir, path) : path;
+ }
+ }
+ }
+ } catch (FileNotFoundException) {
+ }
+
+ return Path.Combine (home_dir, fallback);
+ }
+
+
// the security runtime (and maybe other parts of corlib) needs the
// information to initialize themselves before permissions can be checked
internal static string InternalGetFolderPath (SpecialFolder folder)
case SpecialFolder.Desktop:
#endif
case SpecialFolder.DesktopDirectory:
- return Path.Combine (home, "Desktop");
-
+ return ReadXdgUserDir (config, home, "XDG_DESKTOP_DIR", "Desktop");
+
+ case SpecialFolder.MyMusic:
+ return ReadXdgUserDir (config, home, "XDG_MUSIC_DIR", "Music");
+
+ case SpecialFolder.MyPictures:
+ return ReadXdgUserDir (config, home, "XDG_PICTURES_DIR", "Pictures");
+
// these simply dont exist on Linux
// The spec says if a folder doesnt exist, we
// should return ""
case SpecialFolder.SendTo:
case SpecialFolder.StartMenu:
case SpecialFolder.Startup:
- case SpecialFolder.MyMusic:
- case SpecialFolder.MyPictures:
case SpecialFolder.Templates:
case SpecialFolder.Cookies:
case SpecialFolder.History:
}
// FIXME: Anyone using this anywhere ?
- static internal string GetResourceString (string s) { return ""; }
+ static internal string GetResourceString (string s) { return String.Empty; }
#if NET_2_0
- [MonoTODO ("Machine and User targets aren't supported")]
public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target)
{
switch (target) {
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;
}
[EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
public static void SetEnvironmentVariable (string variable, string value)
+ {
+ SetEnvironmentVariable (variable, value, EnvironmentVariableTarget.Process);
+ }
+
+ [EnvironmentPermission (SecurityAction.Demand, Unrestricted = true)]
+ public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target)
{
if (variable == null)
throw new ArgumentNullException ("variable");
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')
+ if (variable[0] == '\0')
throw new ArgumentException ("The first char in the string is the null character.", "variable");
- InternalSetEnvironmentVariable (variable, value);
- }
-
- [MonoTODO]
- [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
- public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target)
- {
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");
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal static extern void InternalSetEnvironmentVariable (string variable, string value);
- [MonoTODO]
- public static int ProcessorCount {
+ public static extern int ProcessorCount {
[EnvironmentPermission (SecurityAction.Demand, Read="NUMBER_OF_PROCESSORS")]
- get {
- // note: Changes to the NUMBER_OF_PROCESSORS environment variable
- // under Windows doesn't affect the (good) value returned.
- throw new NotImplementedException ();
- }
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ get;
}
- [MonoTODO ("not much documented")]
+ [MonoTODO ("Not implemented")]
[SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode=true)]
public static void FailFast (string message)
{
throw new NotImplementedException ();
}
-#endif
-
+#endif
+
// private methods
internal static bool IsRunningOnWindows {