1 //------------------------------------------------------------------------------
3 // System.Environment.cs
5 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
7 // Author: Jim Richardson, develop@wtfo-guru.com
8 // Dan Lewis (dihlewis@yahoo.co.uk)
9 // Created: Saturday, August 11, 2001
11 //------------------------------------------------------------------------------
13 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Security;
39 using System.Security.Permissions;
41 using System.Runtime.InteropServices;
46 public static class Environment {
49 * This is the version number of the corlib-runtime interface. When
50 * making changes to this interface (by changing the layout
51 * of classes the runtime knows about, changing icall signature or
52 * semantics etc), increment this variable. Also increment the
53 * pair of this variable in the runtime in metadata/appdomain.c.
54 * Changes which are already detected at runtime, like the addition
55 * of icalls, do not require an increment.
57 #pragma warning disable 169
58 private const int mono_corlib_version = 94;
59 #pragma warning restore 169
62 public enum SpecialFolder
75 DesktopDirectory = 0x10,
77 ApplicationData = 0x1a,
78 LocalApplicationData = 0x1c,
82 CommonApplicationData = 0x23,
86 CommonProgramFiles = 0x2b,
87 #if NET_4_0 || MOONLIGHT
91 NetworkShortcuts = 0x13,
93 CommonStartMenu = 0x16,
94 CommonPrograms = 0x17,
96 CommonDesktopDirectory = 0x19,
97 PrinterShortcuts = 0x1b,
101 ProgramFilesX86 = 0x2a,
102 CommonProgramFilesX86 = 0x2c,
103 CommonTemplates = 0x2d,
104 CommonDocuments = 0x2e,
105 CommonAdminTools = 0x2f,
108 CommonPictures = 0x36,
111 LocalizedResources = 0x39,
112 CommonOemLinks = 0x3a,
122 enum SpecialFolderOption {
124 DoNotVerify = 0x4000,
129 /// Gets the command line for this process
131 public static string CommandLine {
132 // note: security demand inherited from calling GetCommandLineArgs
134 StringBuilder sb = new StringBuilder ();
135 foreach (string str in GetCommandLineArgs ()) {
139 for (int i = 0; i < s.Length; i++) {
140 if (quote.Length == 0 && Char.IsWhiteSpace (s [i])) {
142 } else if (s [i] == '"') {
146 if (escape && quote.Length != 0) {
147 s = s.Replace ("\"", "\\\"");
149 sb.AppendFormat ("{0}{1}{0} ", quote, s);
153 return sb.ToString ();
158 /// Gets or sets the current directory. Actually this is supposed to get
159 /// and/or set the process start directory acording to the documentation
160 /// but actually test revealed at beta2 it is just Getting/Setting the CurrentDirectory
162 public static string CurrentDirectory
165 return Directory.GetCurrentDirectory ();
168 Directory.SetCurrentDirectory (value);
173 /// Gets or sets the exit code of this process
175 public extern static int ExitCode
177 [MethodImplAttribute (MethodImplOptions.InternalCall)]
179 [MethodImplAttribute (MethodImplOptions.InternalCall)]
183 static public extern bool HasShutdownStarted
185 [MethodImplAttribute (MethodImplOptions.InternalCall)]
191 /// Gets the name of the local computer
193 public extern static string MachineName {
194 [MethodImplAttribute (MethodImplOptions.InternalCall)]
195 [EnvironmentPermission (SecurityAction.Demand, Read="COMPUTERNAME")]
196 [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
201 /// Gets the standard new line value
203 public extern static string NewLine {
204 [MethodImplAttribute (MethodImplOptions.InternalCall)]
209 // Support methods and fields for OSVersion property
211 static OperatingSystem os;
213 static extern PlatformID Platform {
214 [MethodImplAttribute (MethodImplOptions.InternalCall)]
218 [MethodImplAttribute (MethodImplOptions.InternalCall)]
219 internal static extern string GetOSVersionString ();
222 /// Gets the current OS version information
224 public static OperatingSystem OSVersion {
227 Version v = Version.CreateFromString (GetOSVersionString ());
228 PlatformID p = Platform;
229 if (p == PlatformID.MacOSX)
231 os = new OperatingSystem (p, v);
240 public static string StackTrace {
241 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
243 System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace (0, true);
244 return trace.ToString ();
249 /// Get a fully qualified path to the system directory
251 public static string SystemDirectory {
253 return GetFolderPath (SpecialFolder.System);
258 /// Get the number of milliseconds that have elapsed since the system was booted
260 public extern static int TickCount {
261 [MethodImplAttribute (MethodImplOptions.InternalCall)]
266 /// Get UserDomainName
268 public static string UserDomainName {
269 // FIXME: this variable doesn't exist (at least not on WinXP) - reported to MS as FDBK20562
270 [EnvironmentPermission (SecurityAction.Demand, Read="USERDOMAINNAME")]
277 /// Gets a flag indicating whether the process is in interactive mode
279 [MonoTODO ("Currently always returns false, regardless of interactive state")]
280 public static bool UserInteractive {
287 /// Get the user name of current process is running under
289 public extern static string UserName {
290 [MethodImplAttribute (MethodImplOptions.InternalCall)]
291 [EnvironmentPermission (SecurityAction.Demand, Read="USERNAME;USER")]
296 /// Get the version of the common language runtime
298 public static Version Version {
300 return new Version (Consts.FxFileVersion);
305 /// Get the amount of physical memory mapped to process
307 [MonoTODO ("Currently always returns zero")]
308 public static long WorkingSet {
309 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
313 [MethodImplAttribute (MethodImplOptions.InternalCall)]
314 [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
315 public extern static void Exit (int exitCode);
318 /// Substitute environment variables in the argument "name"
320 public static string ExpandEnvironmentVariables (string name)
323 throw new ArgumentNullException ("name");
325 int off1 = name.IndexOf ('%');
329 int len = name.Length;
331 if (off1 == len - 1 || (off2 = name.IndexOf ('%', off1 + 1)) == -1)
334 StringBuilder result = new StringBuilder ();
335 result.Append (name, 0, off1);
336 Hashtable tbl = null;
338 string var = name.Substring (off1 + 1, off2 - off1 - 1);
339 string value = GetEnvironmentVariable (var);
340 if (value == null && Environment.IsRunningOnWindows) {
341 // On windows, env. vars. are case insensitive
343 tbl = GetEnvironmentVariablesNoCase ();
345 value = tbl [var] as string;
348 // If value not found, add %FOO to stream,
349 // and use the closing % for the next iteration.
350 // If value found, expand it in place of %FOO%
356 result.Append (value);
359 off1 = name.IndexOf ('%', off2 + 1);
360 // If no % found for off1, don't look for one for off2
361 off2 = (off1 == -1 || off2 > len-1)? -1 :name.IndexOf ('%', off1 + 1);
362 // textLen is the length of text between the closing % of current iteration
363 // and the starting % of the next iteration if any. This text is added to output
365 // If no new % found, use all the remaining text
366 if (off1 == -1 || off2 == -1)
367 textLen = len - oldOff2 - 1;
368 // If value found in current iteration, use text after current closing % and next %
369 else if(value != null)
370 textLen = off1 - oldOff2 - 1;
371 // If value not found in current iteration, but a % was found for next iteration,
372 // use text from current closing % to the next %.
374 textLen = off1 - oldOff2;
375 if(off1 >= oldOff2 || off1 == -1)
376 result.Append (name, oldOff2+1, textLen);
377 } while (off2 > -1 && off2 < len);
379 return result.ToString ();
384 /// Return an array of the command line arguments of the current process
386 [MethodImplAttribute (MethodImplOptions.InternalCall)]
387 [EnvironmentPermissionAttribute (SecurityAction.Demand, Read = "PATH")]
388 public extern static string[] GetCommandLineArgs ();
390 [MethodImplAttribute (MethodImplOptions.InternalCall)]
391 internal extern static string internalGetEnvironmentVariable (string variable);
394 /// Return a string containing the value of the environment
395 /// variable identifed by parameter "variable"
397 public static string GetEnvironmentVariable (string variable)
400 if (SecurityManager.SecurityEnabled) {
401 new EnvironmentPermission (EnvironmentPermissionAccess.Read, variable).Demand ();
404 return internalGetEnvironmentVariable (variable);
407 static Hashtable GetEnvironmentVariablesNoCase ()
409 Hashtable vars = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
410 CaseInsensitiveComparer.Default);
412 foreach (string name in GetEnvironmentVariableNames ()) {
413 vars [name] = internalGetEnvironmentVariable (name);
420 /// Return a set of all environment variables and their values
423 public static IDictionary GetEnvironmentVariables ()
425 StringBuilder sb = null;
426 if (SecurityManager.SecurityEnabled) {
427 // we must have access to each variable to get the lot
428 sb = new StringBuilder ();
429 // but (performance-wise) we do not want a stack-walk
430 // for each of them so we concatenate them
433 Hashtable vars = new Hashtable ();
434 foreach (string name in GetEnvironmentVariableNames ()) {
435 vars [name] = internalGetEnvironmentVariable (name);
443 new EnvironmentPermission (EnvironmentPermissionAccess.Read, sb.ToString ()).Demand ();
448 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
449 public static IDictionary GetEnvironmentVariables ()
451 Hashtable vars = new Hashtable ();
452 foreach (string name in GetEnvironmentVariableNames ()) {
453 vars [name] = internalGetEnvironmentVariable (name);
459 [MethodImplAttribute (MethodImplOptions.InternalCall)]
460 private extern static string GetWindowsFolderPath (int folder);
463 /// Returns the fully qualified path of the
464 /// folder specified by the "folder" parameter
466 public static string GetFolderPath (SpecialFolder folder)
468 return GetFolderPath (folder, SpecialFolderOption.None);
473 static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
475 SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight
479 if (Environment.IsRunningOnWindows)
480 dir = GetWindowsFolderPath ((int) folder);
482 dir = UnixGetFolderPath (folder, option);
485 if ((dir != null) && (dir.Length > 0) && SecurityManager.SecurityEnabled) {
486 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dir).Demand ();
492 private static string ReadXdgUserDir (string config_dir, string home_dir, string key, string fallback)
494 string env_path = internalGetEnvironmentVariable (key);
495 if (env_path != null && env_path != String.Empty) {
499 string user_dirs_path = Path.Combine (config_dir, "user-dirs.dirs");
501 if (!File.Exists (user_dirs_path)) {
502 return Path.Combine (home_dir, fallback);
506 using(StreamReader reader = new StreamReader (user_dirs_path)) {
508 while ((line = reader.ReadLine ()) != null) {
510 int delim_index = line.IndexOf ('=');
511 if(delim_index > 8 && line.Substring (0, delim_index) == key) {
512 string path = line.Substring (delim_index + 1).Trim ('"');
513 bool relative = false;
515 if (path.StartsWith ("$HOME/")) {
517 path = path.Substring (6);
518 } else if (!path.StartsWith ("/")) {
522 return relative ? Path.Combine (home_dir, path) : path;
526 } catch (FileNotFoundException) {
529 return Path.Combine (home_dir, fallback);
533 // the security runtime (and maybe other parts of corlib) needs the
534 // information to initialize themselves before permissions can be checked
535 internal static string UnixGetFolderPath (SpecialFolder folder, SpecialFolderOption option)
537 string home = internalGetHome ();
539 // http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html
541 // note: skip security check for environment variables
542 string data = internalGetEnvironmentVariable ("XDG_DATA_HOME");
543 if ((data == null) || (data == String.Empty)) {
544 data = Path.Combine (home, ".local");
545 data = Path.Combine (data, "share");
548 // note: skip security check for environment variables
549 string config = internalGetEnvironmentVariable ("XDG_CONFIG_HOME");
550 if ((config == null) || (config == String.Empty)) {
551 config = Path.Combine (home, ".config");
555 // MyComputer is a virtual directory
556 case SpecialFolder.MyComputer:
560 case SpecialFolder.Personal:
562 return Path.Combine (home, "Documents");
566 // use FDO's CONFIG_HOME. This data will be synced across a network like the windows counterpart.
567 case SpecialFolder.ApplicationData:
570 string dir = Path.Combine (Path.Combine (home, "Documents"), ".config");
571 if (option == SpecialFolderOption.Create){
572 if (!Directory.Exists (dir))
573 Directory.CreateDirectory (dir);
580 //use FDO's DATA_HOME. This is *NOT* synced
581 case SpecialFolder.LocalApplicationData:
584 string dir = Path.Combine (home, "Documents");
585 if (!Directory.Exists (dir))
586 Directory.CreateDirectory (dir);
594 case SpecialFolder.Desktop:
595 case SpecialFolder.DesktopDirectory:
596 return ReadXdgUserDir (config, home, "XDG_DESKTOP_DIR", "Desktop");
598 case SpecialFolder.MyMusic:
599 if (Platform == PlatformID.MacOSX)
600 return Path.Combine (home, "Music");
602 return ReadXdgUserDir (config, home, "XDG_MUSIC_DIR", "Music");
604 case SpecialFolder.MyPictures:
605 if (Platform == PlatformID.MacOSX)
606 return Path.Combine (home, "Pictures");
608 return ReadXdgUserDir (config, home, "XDG_PICTURES_DIR", "Pictures");
610 case SpecialFolder.Templates:
611 return ReadXdgUserDir (config, home, "XDG_TEMPLATES_DIR", "Templates");
612 #if NET_4_0 || MOONLIGHT
613 case SpecialFolder.MyVideos:
614 return ReadXdgUserDir (config, home, "XDG_VIDEOS_DIR", "Videos");
617 case SpecialFolder.CommonTemplates:
618 return "/usr/share/templates";
619 case SpecialFolder.Fonts:
620 if (Platform == PlatformID.MacOSX)
621 return Path.Combine (home, "Library", "Fonts");
623 return Path.Combine (home, ".fonts");
625 // these simply dont exist on Linux
626 // The spec says if a folder doesnt exist, we
628 case SpecialFolder.Favorites:
629 if (Platform == PlatformID.MacOSX)
630 return Path.Combine (home, "Library", "Favorites");
634 case SpecialFolder.ProgramFiles:
635 if (Platform == PlatformID.MacOSX)
636 return "/Applications";
640 case SpecialFolder.InternetCache:
641 if (Platform == PlatformID.MacOSX)
642 return Path.Combine (home, "Library", "Caches");
646 case SpecialFolder.Programs:
647 case SpecialFolder.SendTo:
648 case SpecialFolder.StartMenu:
649 case SpecialFolder.Startup:
650 case SpecialFolder.Cookies:
651 case SpecialFolder.History:
652 case SpecialFolder.Recent:
653 case SpecialFolder.CommonProgramFiles:
654 case SpecialFolder.System:
656 case SpecialFolder.NetworkShortcuts:
657 case SpecialFolder.CommonStartMenu:
658 case SpecialFolder.CommonPrograms:
659 case SpecialFolder.CommonStartup:
660 case SpecialFolder.CommonDesktopDirectory:
661 case SpecialFolder.PrinterShortcuts:
662 case SpecialFolder.Windows:
663 case SpecialFolder.UserProfile:
664 case SpecialFolder.SystemX86:
665 case SpecialFolder.ProgramFilesX86:
666 case SpecialFolder.CommonProgramFilesX86:
667 case SpecialFolder.CommonDocuments:
668 case SpecialFolder.CommonAdminTools:
669 case SpecialFolder.AdminTools:
670 case SpecialFolder.CommonMusic:
671 case SpecialFolder.CommonPictures:
672 case SpecialFolder.CommonVideos:
673 case SpecialFolder.Resources:
674 case SpecialFolder.LocalizedResources:
675 case SpecialFolder.CommonOemLinks:
676 case SpecialFolder.CDBurning:
679 // This is where data common to all users goes
680 case SpecialFolder.CommonApplicationData:
683 throw new ArgumentException ("Invalid SpecialFolder");
688 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
689 public static string[] GetLogicalDrives ()
691 return GetLogicalDrivesInternal ();
695 [MethodImplAttribute (MethodImplOptions.InternalCall)]
696 private static extern void internalBroadcastSettingChange ();
698 public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target)
701 case EnvironmentVariableTarget.Process:
702 return GetEnvironmentVariable (variable);
703 case EnvironmentVariableTarget.Machine:
704 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
705 if (!IsRunningOnWindows)
707 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
708 object regvalue = env.GetValue (variable);
709 return (regvalue == null) ? null : regvalue.ToString ();
711 case EnvironmentVariableTarget.User:
712 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
713 if (!IsRunningOnWindows)
715 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", false)) {
716 object regvalue = env.GetValue (variable);
717 return (regvalue == null) ? null : regvalue.ToString ();
720 throw new ArgumentException ("target");
724 public static IDictionary GetEnvironmentVariables (EnvironmentVariableTarget target)
726 IDictionary variables = (IDictionary)new Hashtable ();
728 case EnvironmentVariableTarget.Process:
729 variables = GetEnvironmentVariables ();
731 case EnvironmentVariableTarget.Machine:
732 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
733 if (IsRunningOnWindows) {
734 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
735 string[] value_names = env.GetValueNames ();
736 foreach (string value_name in value_names)
737 variables.Add (value_name, env.GetValue (value_name));
741 case EnvironmentVariableTarget.User:
742 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
743 if (IsRunningOnWindows) {
744 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment")) {
745 string[] value_names = env.GetValueNames ();
746 foreach (string value_name in value_names)
747 variables.Add (value_name, env.GetValue (value_name));
752 throw new ArgumentException ("target");
757 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
758 public static void SetEnvironmentVariable (string variable, string value)
760 SetEnvironmentVariable (variable, value, EnvironmentVariableTarget.Process);
763 [EnvironmentPermission (SecurityAction.Demand, Unrestricted = true)]
764 public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target)
766 if (variable == null)
767 throw new ArgumentNullException ("variable");
768 if (variable == String.Empty)
769 throw new ArgumentException ("String cannot be of zero length.", "variable");
770 if (variable.IndexOf ('=') != -1)
771 throw new ArgumentException ("Environment variable name cannot contain an equal character.", "variable");
772 if (variable[0] == '\0')
773 throw new ArgumentException ("The first char in the string is the null character.", "variable");
776 case EnvironmentVariableTarget.Process:
777 InternalSetEnvironmentVariable (variable, value);
779 case EnvironmentVariableTarget.Machine:
780 if (!IsRunningOnWindows)
782 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true)) {
783 if (String.IsNullOrEmpty (value))
784 env.DeleteValue (variable, false);
786 env.SetValue (variable, value);
787 internalBroadcastSettingChange ();
790 case EnvironmentVariableTarget.User:
791 if (!IsRunningOnWindows)
793 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", true)) {
794 if (String.IsNullOrEmpty (value))
795 env.DeleteValue (variable, false);
797 env.SetValue (variable, value);
798 internalBroadcastSettingChange ();
802 throw new ArgumentException ("target");
806 [MethodImplAttribute (MethodImplOptions.InternalCall)]
807 internal static extern void InternalSetEnvironmentVariable (string variable, string value);
809 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode=true)]
810 public static void FailFast (string message)
812 throw new NotImplementedException ();
815 #if NET_4_0 || MOONLIGHT
817 public static void FailFast (string message, Exception exception)
819 throw new NotImplementedException ();
824 public static bool Is64BitOperatingSystem {
825 get { return IntPtr.Size == 8; } // FIXME: is this good enough?
828 public static bool Is64BitProcess {
829 get { return Is64BitOperatingSystem; }
832 public static int SystemPageSize {
833 get { return GetPageSize (); }
837 public static extern int ProcessorCount {
838 [EnvironmentPermission (SecurityAction.Demand, Read="NUMBER_OF_PROCESSORS")]
839 [MethodImplAttribute (MethodImplOptions.InternalCall)]
845 internal static bool IsRunningOnWindows {
846 get { return ((int) Platform < 4); }
850 // Used by gacutil.exe
852 #pragma warning disable 169
853 private static string GacPath {
855 if (Environment.IsRunningOnWindows) {
856 /* On windows, we don't know the path where mscorlib.dll will be installed */
857 string corlibDir = new DirectoryInfo (Path.GetDirectoryName (typeof (int).Assembly.Location)).Parent.Parent.FullName;
858 return Path.Combine (Path.Combine (corlibDir, "mono"), "gac");
861 return Path.Combine (Path.Combine (internalGetGacPath (), "mono"), "gac");
864 #pragma warning restore 169
865 [MethodImplAttribute (MethodImplOptions.InternalCall)]
866 internal extern static string internalGetGacPath ();
868 [MethodImplAttribute (MethodImplOptions.InternalCall)]
869 private extern static string [] GetLogicalDrivesInternal ();
871 [MethodImplAttribute (MethodImplOptions.InternalCall)]
872 private extern static string [] GetEnvironmentVariableNames ();
874 [MethodImplAttribute (MethodImplOptions.InternalCall)]
875 internal extern static string GetMachineConfigPath ();
877 [MethodImplAttribute (MethodImplOptions.InternalCall)]
878 internal extern static string internalGetHome ();
880 [MethodImplAttribute (MethodImplOptions.InternalCall)]
881 internal extern static int GetPageSize ();
883 static internal bool IsUnix {
885 int platform = (int) Environment.Platform;
887 return (platform == 4 || platform == 128 || platform == 6);