using System.Security;
using System.Security.Permissions;
using System.Text;
+using System.Runtime.InteropServices;
namespace System {
-#if NET_2_0
+ [ComVisible (true)]
public static class Environment {
-#else
- public sealed class Environment {
- private Environment ()
- {
- }
-#endif
/*
* This is the version number of the corlib-runtime interface. When
* making changes to this interface (by changing the layout
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
- private const int mono_corlib_version = 54;
-
- [MonoTODO]
+#pragma warning disable 169
+ private const int mono_corlib_version = 90;
+#pragma warning restore 169
+
+ [ComVisible (true)]
public enum SpecialFolder
- { // TODO: Determine if these windoze style folder identifiers
- // have unix/linux counterparts
-#if NET_2_0
+ {
MyDocuments = 0x05,
-#endif
-#if NET_1_1
Desktop = 0x00,
MyComputer = 0x11,
-#endif
Programs = 0x02,
Personal = 0x05,
Favorites = 0x06,
ProgramFiles = 0x26,
MyPictures = 0x27,
CommonProgramFiles = 0x2b,
+#if NET_4_0 || MOONLIGHT
+ MyVideos = 0x0e,
+#endif
+#if NET_4_0
+ NetworkShortcuts = 0x13,
+ Fonts = 0x14,
+ CommonStartMenu = 0x16,
+ CommonPrograms = 0x17,
+ CommonStartup = 0x18,
+ CommonDesktopDirectory = 0x19,
+ PrinterShortcuts = 0x1b,
+ Windows = 0x24,
+ UserProfile = 0x28,
+ SystemX86 = 0x29,
+ ProgramFilesX86 = 0x2a,
+ CommonProgramFilesX86 = 0x2c,
+ CommonTemplates = 0x2d,
+ CommonDocuments = 0x2e,
+ CommonAdminTools = 0x2f,
+ AdminTools = 0x30,
+ CommonMusic = 0x35,
+ CommonPictures = 0x36,
+ CommonVideos = 0x37,
+ Resources = 0x38,
+ LocalizedResources = 0x39,
+ CommonOemLinks = 0x3a,
+ CDBurning = 0x3b,
+#endif
+ }
+
+#if NET_4_0
+ public
+#endif
+ enum SpecialFolderOption {
+ None = 0,
+ DoNotVerify = 0x4000,
+ Create = 0x8000
}
/// <summary>
set;
}
-#if NET_1_1
- static
-#endif
- public extern bool HasShutdownStarted
+ static public extern bool HasShutdownStarted
{
[MethodImplAttribute (MethodImplOptions.InternalCall)]
get;
if (os == null) {
Version v = Version.CreateFromString (GetOSVersionString ());
PlatformID p = Platform;
-#if NET_2_0
- if ((int) p == 128)
- p = PlatformID.Unix;
-#endif
os = new OperatingSystem (p, v);
}
return os;
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 ();
}
}
-
+#if !NET_2_1
/// <summary>
/// Get a fully qualified path to the system directory
/// </summary>
return GetFolderPath (SpecialFolder.System);
}
}
-
+#endif
/// <summary>
/// Get the number of milliseconds that have elapsed since the system was booted
/// </summary>
/// <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>
/// 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; }
public extern static string[] GetCommandLineArgs ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal extern static string internalGetEnvironmentVariable (string name);
+ internal extern static string internalGetEnvironmentVariable (string variable);
/// <summary>
/// Return a string containing the value of the environment
/// variable identifed by parameter "variable"
/// </summary>
- public static string GetEnvironmentVariable (string name)
+ public static string GetEnvironmentVariable (string variable)
{
+#if !NET_2_1
if (SecurityManager.SecurityEnabled) {
- new EnvironmentPermission (EnvironmentPermissionAccess.Read, name).Demand ();
+ new EnvironmentPermission (EnvironmentPermissionAccess.Read, variable).Demand ();
}
- return internalGetEnvironmentVariable (name);
+#endif
+ return internalGetEnvironmentVariable (variable);
}
static Hashtable GetEnvironmentVariablesNoCase ()
/// <summary>
/// Return a set of all environment variables and their values
/// </summary>
-#if NET_2_0
+#if !NET_2_1
public static IDictionary GetEnvironmentVariables ()
{
StringBuilder sb = null;
/// </summary>
public static string GetFolderPath (SpecialFolder folder)
{
+ return GetFolderPath (folder, SpecialFolderOption.None);
+ }
+#if NET_4_0
+ [MonoTODO ("Figure out the folder path for all the new values in SpecialFolder. Use the 'option' argument.")]
+ public
+#endif
+ static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
+ {
+ SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
+
string dir = null;
if (Environment.IsRunningOnWindows) {
} else {
dir = InternalGetFolderPath (folder);
}
-
+#if !NET_2_1
if ((dir != null) && (dir.Length > 0) && SecurityManager.SecurityEnabled) {
new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dir).Demand ();
}
+#endif
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)
}
switch (folder) {
-#if NET_1_1
// MyComputer is a virtual directory
case SpecialFolder.MyComputer:
return String.Empty;
-#endif
+
// personal == ~
case SpecialFolder.Personal:
+#if MONOTOUCH
+ return Path.Combine (home, "Documents");
+#else
return home;
+#endif
// use FDO's CONFIG_HOME. This data will be synced across a network like the windows counterpart.
case SpecialFolder.ApplicationData:
return config;
//use FDO's DATA_HOME. This is *NOT* synced
case SpecialFolder.LocalApplicationData:
return data;
-#if NET_1_1
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:
return GetLogicalDrivesInternal ();
}
- // FIXME: Anyone using this anywhere ?
- static internal string GetResourceString (string s) { return String.Empty; }
+#if !NET_2_1
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private static extern void internalBroadcastSettingChange ();
-
-#if NET_2_0
public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target)
{
switch (target) {
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 ();
+ object regvalue = env.GetValue (variable);
+ return (regvalue == null) ? null : regvalue.ToString ();
}
case EnvironmentVariableTarget.User:
new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
if (!IsRunningOnWindows)
return null;
using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", false)) {
- return env.GetValue (variable).ToString ();
+ object regvalue = env.GetValue (variable);
+ return (regvalue == null) ? null : regvalue.ToString ();
}
default:
throw new ArgumentException ("target");
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)
+ if (String.IsNullOrEmpty (value))
env.DeleteValue (variable, false);
else
env.SetValue (variable, value);
+ internalBroadcastSettingChange ();
}
break;
case EnvironmentVariableTarget.User:
if (!IsRunningOnWindows)
return;
using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", true)) {
- if (value == null || value.Length == 0)
+ if (String.IsNullOrEmpty (value))
env.DeleteValue (variable, false);
else
env.SetValue (variable, value);
+ internalBroadcastSettingChange ();
}
break;
default:
[MethodImplAttribute (MethodImplOptions.InternalCall)]
internal static extern void InternalSetEnvironmentVariable (string variable, string value);
-
- public static extern int ProcessorCount {
- [EnvironmentPermission (SecurityAction.Demand, Read="NUMBER_OF_PROCESSORS")]
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- get;
- }
-
- [MonoTODO ("not much documented")]
+#endif
[SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode=true)]
public static void FailFast (string message)
{
throw new NotImplementedException ();
}
+
+#if NET_4_0 || MOONLIGHT
+ [SecurityCritical]
+ public static void FailFast (string message, Exception exception)
+ {
+ throw new NotImplementedException ();
+ }
+#endif
+
+#if NET_4_0
+ public static bool Is64BitOperatingSystem {
+ get { return IntPtr.Size == 8; } // FIXME: is this good enough?
+ }
+
+ public static bool Is64BitProcess {
+ get { return Is64BitOperatingSystem; }
+ }
+
+ public static int SystemPageSize {
+ get { return GetPageSize (); }
+ }
#endif
+ public static extern int ProcessorCount {
+ [EnvironmentPermission (SecurityAction.Demand, Read="NUMBER_OF_PROCESSORS")]
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ get;
+ }
+
// private methods
internal static bool IsRunningOnWindows {
- get { return ((int) Platform != 128); }
+ get { return ((int) Platform < 4); }
}
-
+#if !NET_2_1
+ //
+ // Used by gacutil.exe
+ //
+#pragma warning disable 169
private static string GacPath {
get {
if (Environment.IsRunningOnWindows) {
return Path.Combine (Path.Combine (internalGetGacPath (), "mono"), "gac");
}
}
-
+#pragma warning restore 169
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ internal extern static string internalGetGacPath ();
+#endif
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern static string [] GetLogicalDrivesInternal ();
internal extern static string GetMachineConfigPath ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal extern static string internalGetGacPath ();
+ internal extern static string internalGetHome ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal extern static string internalGetHome ();
+ internal extern static int GetPageSize ();
+
+ static internal bool IsUnix {
+ get {
+ int platform = (int) Environment.Platform;
+
+ return (platform == 4 || platform == 128 || platform == 6);
+ }
+ }
}
}