//
//------------------------------------------------------------------------------
//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
using System.IO;
-//using System.Diagnostics;
using System.Collections;
+using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
-using System.Runtime.CompilerServices;
using System.Text;
-namespace System
-{
- public sealed class Environment
- {
+namespace System {
+
+#if NET_2_0
+ 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
- * 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 = 31;
-
- private Environment ()
- {
- }
-
+ private const int mono_corlib_version = 54;
+
[MonoTODO]
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,
CommonProgramFiles = 0x2b,
}
- // TODO: Make sure the security attributes do what I expect
-
/// <summary>
/// Gets the command line for this process
/// </summary>
- public static string CommandLine
- { // TODO: Coordinate with implementor of EnvironmentPermissionAttribute
- // [EnvironmentPermissionAttribute(SecurityAction.Demand, Read = "COMMANDLINE")]
- get
- {
+ public static string CommandLine {
+ // note: security demand inherited from calling GetCommandLineArgs
+ get {
// FIXME: we may need to quote, but any sane person
// should use GetCommandLineArgs () instead.
return String.Join (" ", GetCommandLineArgs ());
/// </summary>
public static string CurrentDirectory
{
- // originally it was my thought that the external call would be made in
- // the directory class however that class has additional security requirements
- // so the Directory class will call this class for its get/set current directory
get {
return Directory.GetCurrentDirectory ();
}
/// </summary>
public extern static string MachineName {
[MethodImplAttribute (MethodImplOptions.InternalCall)]
+ [EnvironmentPermission (SecurityAction.Demand, Read="COMPUTERNAME")]
+ [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
get;
}
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;
}
/// Get StackTrace
/// </summary>
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 ();
}
}
/// Get UserDomainName
/// </summary>
public static string UserDomainName {
+ // FIXME: this variable doesn't exist (at least not on WinXP) - reported to MS as FDBK20562
+ [EnvironmentPermission (SecurityAction.Demand, Read="USERDOMAINNAME")]
get {
return MachineName;
}
/// <summary>
/// Get the user name of current process is running under
/// </summary>
- public extern static string UserName
- {
+ public extern static string UserName {
[MethodImplAttribute (MethodImplOptions.InternalCall)]
+ [EnvironmentPermission (SecurityAction.Demand, Read="USERNAME;USER")]
get;
}
/// </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);
}
}
/// Get the amount of physical memory mapped to process
/// </summary>
[MonoTODO]
- public static long WorkingSet
- {
- get {
- return 0;
- }
+ public static long WorkingSet {
+ [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
+ get { return 0; }
}
[MethodImplAttribute (MethodImplOptions.InternalCall)]
+ [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
public extern static void Exit (int exitCode);
/// <summary>
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 ();
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 ();
/// Return an array of the command line arguments of the current process
/// </summary>
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- public extern static string[] GetCommandLineArgs();
+ [EnvironmentPermissionAttribute (SecurityAction.Demand, Read = "PATH")]
+ public extern static string[] GetCommandLineArgs ();
+
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ internal extern static string internalGetEnvironmentVariable (string name);
/// <summary>
/// Return a string containing the value of the environment
/// variable identifed by parameter "variable"
/// </summary>
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- public extern static string GetEnvironmentVariable (string name);
+ public static string GetEnvironmentVariable (string name)
+ {
+ if (SecurityManager.SecurityEnabled) {
+ new EnvironmentPermission (EnvironmentPermissionAccess.Read, name).Demand ();
+ }
+ return internalGetEnvironmentVariable (name);
+ }
static Hashtable GetEnvironmentVariablesNoCase ()
{
CaseInsensitiveComparer.Default);
foreach (string name in GetEnvironmentVariableNames ()) {
- vars [name] = GetEnvironmentVariable (name);
+ vars [name] = internalGetEnvironmentVariable (name);
}
return vars;
/// <summary>
/// Return a set of all environment variables and their values
/// </summary>
-
- public static IDictionary GetEnvironmentVariables()
+#if NET_2_0
+ public static IDictionary GetEnvironmentVariables ()
{
+ StringBuilder sb = null;
+ if (SecurityManager.SecurityEnabled) {
+ // we must have access to each variable to get the lot
+ sb = new StringBuilder ();
+ // but (performance-wise) we do not want a stack-walk
+ // for each of them so we concatenate them
+ }
+
Hashtable vars = new Hashtable ();
foreach (string name in GetEnvironmentVariableNames ()) {
- vars [name] = GetEnvironmentVariable (name);
+ vars [name] = internalGetEnvironmentVariable (name);
+ if (sb != null) {
+ sb.Append (name);
+ sb.Append (";");
+ }
}
+ if (sb != null) {
+ new EnvironmentPermission (EnvironmentPermissionAccess.Read, sb.ToString ()).Demand ();
+ }
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);
/// </summary>
public static string GetFolderPath (SpecialFolder folder)
{
- if ((int) Platform != 128)
- return GetWindowsFolderPath ((int) folder);
+ string dir = null;
+
+ if (Environment.IsRunningOnWindows) {
+ dir = GetWindowsFolderPath ((int) folder);
+ } else {
+ dir = InternalGetFolderPath (folder);
+ }
+
+ if ((dir != null) && (dir.Length > 0) && SecurityManager.SecurityEnabled) {
+ new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dir).Demand ();
+ }
+ return dir;
+ }
+ // 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)
+ {
string home = internalGetHome ();
// http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html
- string data = GetEnvironmentVariable ("XDG_DATA_HOME");
+
+ // note: skip security check for environment variables
+ string data = internalGetEnvironmentVariable ("XDG_DATA_HOME");
if ((data == null) || (data == String.Empty)) {
data = Path.Combine (home, ".local");
data = Path.Combine (data, "share");
}
- string config = GetEnvironmentVariable ("XDG_CONFIG_HOME");
+ // note: skip security check for environment variables
+ string config = internalGetEnvironmentVariable ("XDG_CONFIG_HOME");
if ((config == null) || (config == String.Empty)) {
config = Path.Combine (home, ".config");
}
#if NET_1_1
// MyComputer is a virtual directory
case SpecialFolder.MyComputer:
- return "";
+ return String.Empty;
#endif
// personal == ~
case SpecialFolder.Personal:
case SpecialFolder.CommonProgramFiles:
case SpecialFolder.ProgramFiles:
case SpecialFolder.System:
- return "";
+ return String.Empty;
// This is where data common to all users goes
case SpecialFolder.CommonApplicationData:
return "/usr/share";
}
}
+ [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
public static string[] GetLogicalDrives ()
{
return GetLogicalDrivesInternal ();
}
+ // FIXME: Anyone using this anywhere ?
static internal string GetResourceString (string s) { return ""; }
#if NET_2_0
public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target)
{
- return (string)(GetEnvironmentVariables (target) [variable]);
+ switch (target) {
+ case EnvironmentVariableTarget.Process:
+ return GetEnvironmentVariable (variable);
+ case EnvironmentVariableTarget.Machine:
+ new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
+ 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 ();
+ 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]
public static IDictionary GetEnvironmentVariables (EnvironmentVariableTarget target)
{
- throw new NotImplementedException ();
+ IDictionary variables = (IDictionary)new Hashtable ();
+ switch (target) {
+ case EnvironmentVariableTarget.Process:
+ variables = GetEnvironmentVariables ();
+ break;
+ case EnvironmentVariableTarget.Machine:
+ new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
+ 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 ();
+ 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);
}
- [MonoTODO]
+ [EnvironmentPermission (SecurityAction.Demand, Unrestricted = true)]
public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target)
{
- throw new NotImplementedException ();
+ 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:
+ 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:
+ 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]
- static bool IsServerGC {
+ public static 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 ();
}
}
- [MonoTODO]
- static int ProcessorCount {
- get {
- throw new NotImplementedException ();
- }
+ [MonoTODO ("not much documented")]
+ [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");