New test.
[mono.git] / mcs / class / corlib / System / Environment.cs
1 //------------------------------------------------------------------------------
2 // 
3 // System.Environment.cs 
4 //
5 // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved
6 // 
7 // Author:         Jim Richardson, develop@wtfo-guru.com
8 //                 Dan Lewis (dihlewis@yahoo.co.uk)
9 // Created:        Saturday, August 11, 2001 
10 //
11 //------------------------------------------------------------------------------
12 //
13 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
14 //
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:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
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.
33 //
34
35 using System.IO;
36 using System.Collections;
37 using System.Runtime.CompilerServices;
38 using System.Security;
39 using System.Security.Permissions;
40 using System.Text;
41
42 namespace System {
43
44 #if NET_2_0
45         public static class Environment {
46 #else
47         public sealed class Environment {
48
49                 private Environment ()
50                 {
51                 }
52 #endif
53                 /*
54                  * This is the version number of the corlib-runtime interface. When
55                  * making changes to this interface (by changing the layout
56                  * of classes the runtime knows about, changing icall signature or
57                  * semantics etc), increment this variable. Also increment the
58                  * pair of this variable in the runtime in metadata/appdomain.c.
59                  * Changes which are already detected at runtime, like the addition
60                  * of icalls, do not require an increment.
61                  */
62                 private const int mono_corlib_version = 54;
63                 
64                 public enum SpecialFolder
65                 {       // TODO: Determine if these windoze style folder identifiers 
66                         //       have unix/linux counterparts
67 #if NET_2_0
68                         MyDocuments = 0x05,
69 #endif
70 #if NET_1_1
71                         Desktop = 0x00,
72                         MyComputer = 0x11,
73 #endif
74                         Programs = 0x02,
75                         Personal = 0x05,
76                         Favorites = 0x06,
77                         Startup = 0x07,
78                         Recent = 0x08,
79                         SendTo = 0x09,
80                         StartMenu = 0x0b,
81                         MyMusic = 0x0d,
82                         DesktopDirectory = 0x10,
83                         Templates = 0x15,
84                         ApplicationData = 0x1a,
85                         LocalApplicationData = 0x1c,
86                         InternetCache = 0x20,
87                         Cookies = 0x21,
88                         History = 0x22,
89                         CommonApplicationData   = 0x23,
90                         System = 0x25,
91                         ProgramFiles = 0x26,
92                         MyPictures = 0x27,
93                         CommonProgramFiles = 0x2b,
94                 }
95
96                 /// <summary>
97                 /// Gets the command line for this process
98                 /// </summary>
99                 public static string CommandLine {
100                         // note: security demand inherited from calling GetCommandLineArgs
101                         get {
102                                 // FIXME: we may need to quote, but any sane person
103                                 // should use GetCommandLineArgs () instead.
104                                 return String.Join (" ", GetCommandLineArgs ());
105                         }
106                 }
107
108                 /// <summary>
109                 /// Gets or sets the current directory. Actually this is supposed to get
110                 /// and/or set the process start directory acording to the documentation
111                 /// but actually test revealed at beta2 it is just Getting/Setting the CurrentDirectory
112                 /// </summary>
113                 public static string CurrentDirectory
114                 {
115                         get {
116                                 return Directory.GetCurrentDirectory ();
117                         }
118                         set {
119                                 Directory.SetCurrentDirectory (value);
120                         }
121                 }
122
123                 /// <summary>
124                 /// Gets or sets the exit code of this process
125                 /// </summary>
126                 public extern static int ExitCode
127                 {       
128                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
129                         get;
130                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
131                         set;
132                 }
133
134 #if NET_1_1
135                 static
136 #endif
137                 public extern bool HasShutdownStarted
138                 {
139                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
140                         get;
141                 }
142                 
143
144                 /// <summary>
145                 /// Gets the name of the local computer
146                 /// </summary>
147                 public extern static string MachineName {
148                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
149                         [EnvironmentPermission (SecurityAction.Demand, Read="COMPUTERNAME")]
150                         [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
151                         get;
152                 }
153
154                 /// <summary>
155                 /// Gets the standard new line value
156                 /// </summary>
157                 public extern static string NewLine {
158                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
159                         get;
160                 }
161
162                 //
163                 // Support methods and fields for OSVersion property
164                 //
165                 static OperatingSystem os;
166
167                 internal static extern PlatformID Platform {
168                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
169                         get;
170                 }
171
172                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
173                 internal static extern string GetOSVersionString ();
174
175                 /// <summary>
176                 /// Gets the current OS version information
177                 /// </summary>
178                 public static OperatingSystem OSVersion {
179                         get {
180                                 if (os == null) {
181                                         Version v = Version.CreateFromString (GetOSVersionString ());
182                                         PlatformID p = Platform;
183 #if NET_2_0
184                                         if ((int) p == 128)
185                                                 p = PlatformID.Unix;
186 #endif
187                                         os = new OperatingSystem (p, v);
188                                 }
189                                 return os;
190                         }
191                 }
192
193                 /// <summary>
194                 /// Get StackTrace
195                 /// </summary>
196                 public static string StackTrace {
197                         [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
198                         get {
199                                 System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace (1, true);
200                                 return trace.ToString ();
201                         }
202                 }
203
204                 /// <summary>
205                 /// Get a fully qualified path to the system directory
206                 /// </summary>
207                 public static string SystemDirectory {
208                         get {
209                                 return GetFolderPath (SpecialFolder.System);
210                         }
211                 }
212
213                 /// <summary>
214                 /// Get the number of milliseconds that have elapsed since the system was booted
215                 /// </summary>
216                 public extern static int TickCount {
217                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
218                         get;
219                 }
220
221                 /// <summary>
222                 /// Get UserDomainName
223                 /// </summary>
224                 public static string UserDomainName {
225                         // FIXME: this variable doesn't exist (at least not on WinXP) - reported to MS as FDBK20562
226                         [EnvironmentPermission (SecurityAction.Demand, Read="USERDOMAINNAME")]
227                         get {
228                                 return MachineName;
229                         }
230                 }
231
232                 /// <summary>
233                 /// Gets a flag indicating whether the process is in interactive mode
234                 /// </summary>
235                 [MonoTODO ("Currently always returns false, regardless of interactive state")]
236                 public static bool UserInteractive {
237                         get {
238                                 return false;
239                         }
240                 }
241
242                 /// <summary>
243                 /// Get the user name of current process is running under
244                 /// </summary>
245                 public extern static string UserName {
246                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
247                         [EnvironmentPermission (SecurityAction.Demand, Read="USERNAME;USER")]
248                         get;
249                 }
250
251                 /// <summary>
252                 /// Get the version of the common language runtime 
253                 /// </summary>
254                 public static Version Version {
255                         get {
256                                 return new Version (Consts.FxFileVersion);
257                         }
258                 }
259
260                 /// <summary>
261                 /// Get the amount of physical memory mapped to process
262                 /// </summary>
263                 [MonoTODO ("Currently always returns zero")]
264                 public static long WorkingSet {
265                         [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
266                         get { return 0; }
267                 }
268
269                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
270                 [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)]
271                 public extern static void Exit (int exitCode);
272
273                 /// <summary>
274                 /// Substitute environment variables in the argument "name"
275                 /// </summary>
276                 public static string ExpandEnvironmentVariables (string name)
277                 {
278                         if (name == null)
279                                 throw new ArgumentNullException ("name");
280
281                         int off1 = name.IndexOf ('%');
282                         if (off1 == -1)
283                                 return name;
284
285                         int len = name.Length;
286                         int off2 = 0;
287                         if (off1 == len - 1 || (off2 = name.IndexOf ('%', off1 + 1)) == -1)
288                                 return name;
289
290                         StringBuilder result = new StringBuilder ();
291                         result.Append (name, 0, off1);
292                         Hashtable tbl = null;
293                         do {
294                                 string var = name.Substring (off1 + 1, off2 - off1 - 1);
295                                 string value = GetEnvironmentVariable (var);
296                                 if (value == null && Environment.IsRunningOnWindows) {
297                                         // On windows, env. vars. are case insensitive
298                                         if (tbl == null)
299                                                 tbl = GetEnvironmentVariablesNoCase ();
300
301                                         value = tbl [var] as string;
302                                 }
303                                 
304                                 // If value not found, add %FOO to stream,
305                                 //  and use the closing % for the next iteration.
306                                 // If value found, expand it in place of %FOO%
307                                 if (value == null) {
308                                         result.Append ('%');
309                                         result.Append (var);
310                                         off2--;
311                                 } else {
312                                         result.Append (value);
313                                 }
314                                 int oldOff2 = off2;
315                                 off1 = name.IndexOf ('%', off2 + 1);
316                                 // If no % found for off1, don't look for one for off2
317                                 off2 = (off1 == -1 || off2 > len-1)? -1 :name.IndexOf ('%', off1 + 1);
318                                 // textLen is the length of text between the closing % of current iteration
319                                 //  and the starting % of the next iteration if any. This text is added to output
320                                 int textLen;
321                                 // If no new % found, use all the remaining text
322                                 if (off1 == -1 || off2 == -1)
323                                         textLen = len - oldOff2 - 1;
324                                 // If value found in current iteration, use text after current closing % and next %
325                                 else if(value != null)
326                                         textLen = off1 - oldOff2 - 1;
327                                 // If value not found in current iteration, but a % was found for next iteration,
328                                 //  use text from current closing % to the next %.
329                                 else
330                                         textLen = off1 - oldOff2;
331                                 if(off1 >= oldOff2 || off1 == -1)
332                                         result.Append (name, oldOff2+1, textLen);
333                         } while (off2 > -1 && off2 < len);
334                                 
335                         return result.ToString ();
336
337                 }
338
339                 /// <summary>
340                 /// Return an array of the command line arguments of the current process
341                 /// </summary>
342                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
343                 [EnvironmentPermissionAttribute (SecurityAction.Demand, Read = "PATH")]
344                 public extern static string[] GetCommandLineArgs ();
345
346                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
347                 internal extern static string internalGetEnvironmentVariable (string name);
348
349                 /// <summary>
350                 /// Return a string containing the value of the environment
351                 /// variable identifed by parameter "variable"
352                 /// </summary>
353                 public static string GetEnvironmentVariable (string name)
354                 {
355                         if (SecurityManager.SecurityEnabled) {
356                                 new EnvironmentPermission (EnvironmentPermissionAccess.Read, name).Demand ();
357                         }
358                         return internalGetEnvironmentVariable (name);
359                 }
360
361                 static Hashtable GetEnvironmentVariablesNoCase ()
362                 {
363                         Hashtable vars = new Hashtable (CaseInsensitiveHashCodeProvider.Default,
364                                                         CaseInsensitiveComparer.Default);
365
366                         foreach (string name in GetEnvironmentVariableNames ()) {
367                                 vars [name] = internalGetEnvironmentVariable (name);
368                         }
369
370                         return vars;
371                 }
372
373                 /// <summary>
374                 /// Return a set of all environment variables and their values
375                 /// </summary>
376 #if NET_2_0
377                 public static IDictionary GetEnvironmentVariables ()
378                 {
379                         StringBuilder sb = null;
380                         if (SecurityManager.SecurityEnabled) {
381                                 // we must have access to each variable to get the lot
382                                 sb = new StringBuilder ();
383                                 // but (performance-wise) we do not want a stack-walk
384                                 // for each of them so we concatenate them
385                         }
386
387                         Hashtable vars = new Hashtable ();
388                         foreach (string name in GetEnvironmentVariableNames ()) {
389                                 vars [name] = internalGetEnvironmentVariable (name);
390                                 if (sb != null) {
391                                         sb.Append (name);
392                                         sb.Append (";");
393                                 }
394                         }
395
396                         if (sb != null) {
397                                 new EnvironmentPermission (EnvironmentPermissionAccess.Read, sb.ToString ()).Demand ();
398                         }
399                         return vars;
400                 }
401 #else
402                 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
403                 public static IDictionary GetEnvironmentVariables ()
404                 {
405                         Hashtable vars = new Hashtable ();
406                         foreach (string name in GetEnvironmentVariableNames ()) {
407                                 vars [name] = internalGetEnvironmentVariable (name);
408                         }
409                         return vars;
410                 }
411 #endif
412
413                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
414                 private extern static string GetWindowsFolderPath (int folder);
415
416                 /// <summary>
417                 /// Returns the fully qualified path of the
418                 /// folder specified by the "folder" parameter
419                 /// </summary>
420                 public static string GetFolderPath (SpecialFolder folder)
421                 {
422                         string dir = null;
423
424                         if (Environment.IsRunningOnWindows) {
425                                 dir = GetWindowsFolderPath ((int) folder);
426                         } else {
427                                 dir = InternalGetFolderPath (folder);
428                         }
429
430                         if ((dir != null) && (dir.Length > 0) && SecurityManager.SecurityEnabled) {
431                                 new FileIOPermission (FileIOPermissionAccess.PathDiscovery, dir).Demand ();
432                         }
433                         return dir;
434                 }
435
436                 // the security runtime (and maybe other parts of corlib) needs the
437                 // information to initialize themselves before permissions can be checked
438                 internal static string InternalGetFolderPath (SpecialFolder folder)
439                 {
440                         string home = internalGetHome ();
441
442                         // http://freedesktop.org/Standards/basedir-spec/basedir-spec-0.6.html
443
444                         // note: skip security check for environment variables
445                         string data = internalGetEnvironmentVariable ("XDG_DATA_HOME");
446                         if ((data == null) || (data == String.Empty)) {
447                                 data = Path.Combine (home, ".local");
448                                 data = Path.Combine (data, "share");
449                         }
450
451                         // note: skip security check for environment variables
452                         string config = internalGetEnvironmentVariable ("XDG_CONFIG_HOME");
453                         if ((config == null) || (config == String.Empty)) {
454                                 config = Path.Combine (home, ".config");
455                         }
456
457                         switch (folder) {
458 #if NET_1_1
459                         // MyComputer is a virtual directory
460                         case SpecialFolder.MyComputer:
461                                 return String.Empty;
462 #endif
463                         // personal == ~
464                         case SpecialFolder.Personal:
465                                 return home;
466                         // use FDO's CONFIG_HOME. This data will be synced across a network like the windows counterpart.
467                         case SpecialFolder.ApplicationData:
468                                 return config;
469                         //use FDO's DATA_HOME. This is *NOT* synced
470                         case SpecialFolder.LocalApplicationData:
471                                 return data;
472 #if NET_1_1
473                         case SpecialFolder.Desktop:
474 #endif
475                         case SpecialFolder.DesktopDirectory:
476                                 return Path.Combine (home, "Desktop");
477
478                         case SpecialFolder.MyMusic:
479                                 return Path.Combine (home, "Music");
480                                 
481                         // these simply dont exist on Linux
482                         // The spec says if a folder doesnt exist, we
483                         // should return ""
484                         case SpecialFolder.Favorites:
485                         case SpecialFolder.Programs:
486                         case SpecialFolder.SendTo:
487                         case SpecialFolder.StartMenu:
488                         case SpecialFolder.Startup:
489                         case SpecialFolder.MyPictures:
490                         case SpecialFolder.Templates:
491                         case SpecialFolder.Cookies:
492                         case SpecialFolder.History:
493                         case SpecialFolder.InternetCache:
494                         case SpecialFolder.Recent:
495                         case SpecialFolder.CommonProgramFiles:
496                         case SpecialFolder.ProgramFiles:
497                         case SpecialFolder.System:
498                                 return String.Empty;
499                         // This is where data common to all users goes
500                         case SpecialFolder.CommonApplicationData:
501                                 return "/usr/share";
502                         default:
503                                 throw new ArgumentException ("Invalid SpecialFolder");
504                         }
505                 }
506
507                 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
508                 public static string[] GetLogicalDrives ()
509                 {
510                         return GetLogicalDrivesInternal ();
511                 }
512
513                 // FIXME: Anyone using this anywhere ?
514                 static internal string GetResourceString (string s) { return String.Empty; }
515
516                 
517 #if NET_2_0
518                 public static string GetEnvironmentVariable (string variable, EnvironmentVariableTarget target)
519                 {
520                         switch (target) {
521                         case EnvironmentVariableTarget.Process:
522                                 return GetEnvironmentVariable (variable);
523                         case EnvironmentVariableTarget.Machine:
524                                 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
525                                 if (!IsRunningOnWindows)
526                                         return null;
527                                 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
528                                         return env.GetValue (variable).ToString ();
529                                 }
530                         case EnvironmentVariableTarget.User:
531                                 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
532                                 if (!IsRunningOnWindows)
533                                         return null;
534                                 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", false)) {
535                                         return env.GetValue (variable).ToString ();
536                                 }
537                         default:
538                                 throw new ArgumentException ("target");
539                         }
540                 }
541
542                 public static IDictionary GetEnvironmentVariables (EnvironmentVariableTarget target)
543                 {
544                         IDictionary variables = (IDictionary)new Hashtable ();
545                         switch (target) {
546                         case EnvironmentVariableTarget.Process:
547                                 variables = GetEnvironmentVariables ();
548                                 break;
549                         case EnvironmentVariableTarget.Machine:
550                                 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
551                                 if (IsRunningOnWindows) {
552                                         using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment")) {
553                                                 string[] value_names = env.GetValueNames ();
554                                                 foreach (string value_name in value_names)
555                                                         variables.Add (value_name, env.GetValue (value_name));
556                                         }
557                                 }
558                                 break;
559                         case EnvironmentVariableTarget.User:
560                                 new EnvironmentPermission (PermissionState.Unrestricted).Demand ();
561                                 if (IsRunningOnWindows) {
562                                         using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment")) {
563                                                 string[] value_names = env.GetValueNames ();
564                                                 foreach (string value_name in value_names)
565                                                         variables.Add (value_name, env.GetValue (value_name));
566                                         }
567                                 }
568                                 break;
569                         default:
570                                 throw new ArgumentException ("target");
571                         }
572                         return variables;
573                 }
574
575                 [EnvironmentPermission (SecurityAction.Demand, Unrestricted=true)]
576                 public static void SetEnvironmentVariable (string variable, string value)
577                 {
578                         SetEnvironmentVariable (variable, value, EnvironmentVariableTarget.Process);
579                 }
580
581                 [EnvironmentPermission (SecurityAction.Demand, Unrestricted = true)]
582                 public static void SetEnvironmentVariable (string variable, string value, EnvironmentVariableTarget target)
583                 {
584                         if (variable == null)
585                                 throw new ArgumentNullException ("variable");
586                         if (variable == String.Empty)
587                                 throw new ArgumentException ("String cannot be of zero length.", "variable");
588                         if (variable.IndexOf ('=') != -1)
589                                 throw new ArgumentException ("Environment variable name cannot contain an equal character.", "variable");
590                         if (variable[0] == '\0')
591                                 throw new ArgumentException ("The first char in the string is the null character.", "variable");
592
593                         switch (target) {
594                         case EnvironmentVariableTarget.Process:
595                                 InternalSetEnvironmentVariable (variable, value);
596                                 break;
597                         case EnvironmentVariableTarget.Machine:
598                                 if (!IsRunningOnWindows)
599                                         return;
600                                 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.LocalMachine.OpenSubKey (@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true)) {
601                                         if (value == null || value.Length == 0)
602                                                 env.DeleteValue (variable, false);
603                                         else
604                                                 env.SetValue (variable, value);
605                                 }
606                                 break;
607                         case EnvironmentVariableTarget.User:
608                                 if (!IsRunningOnWindows)
609                                         return;
610                                 using (Microsoft.Win32.RegistryKey env = Microsoft.Win32.Registry.CurrentUser.OpenSubKey ("Environment", true)) {
611                                         if (value == null || value.Length == 0)
612                                                 env.DeleteValue (variable, false);
613                                         else
614                                                 env.SetValue (variable, value);
615                                 }
616                                 break;
617                         default:
618                                 throw new ArgumentException ("target");
619                         }
620                 }
621
622                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
623                 internal static extern void InternalSetEnvironmentVariable (string variable, string value);
624
625                 public static extern int ProcessorCount {
626                         [EnvironmentPermission (SecurityAction.Demand, Read="NUMBER_OF_PROCESSORS")]
627                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
628                         get;                    
629                 }
630
631                 [MonoTODO ("Not implemented")]
632                 [SecurityPermission (SecurityAction.LinkDemand, UnmanagedCode=true)]
633                 public static void FailFast (string message)
634                 {
635                         throw new NotImplementedException ();
636                 }
637 #endif
638
639                 // private methods
640
641                 internal static bool IsRunningOnWindows {
642                         get { return ((int) Platform != 128); }
643                 }
644
645                 private static string GacPath {
646                         get {
647                                 if (Environment.IsRunningOnWindows) {
648                                         /* On windows, we don't know the path where mscorlib.dll will be installed */
649                                         string corlibDir = new DirectoryInfo (Path.GetDirectoryName (typeof (int).Assembly.Location)).Parent.Parent.FullName;
650                                         return Path.Combine (Path.Combine (corlibDir, "mono"), "gac");
651                                 }
652
653                                 return Path.Combine (Path.Combine (internalGetGacPath (), "mono"), "gac");
654                         }
655                 }
656
657                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
658                 private extern static string [] GetLogicalDrivesInternal ();
659
660                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
661                 private extern static string [] GetEnvironmentVariableNames ();
662
663                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
664                 internal extern static string GetMachineConfigPath ();
665
666                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
667                 internal extern static string internalGetGacPath ();
668
669                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
670                 internal extern static string internalGetHome ();
671         }
672 }
673