[coop] Temporarily restore MonoThreadInfo when TLS destructor runs. Fixes #43099
[mono.git] / mcs / class / referencesource / mscorlib / system / environment.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*============================================================
7 **
8 ** Class: Environment
9 **
10 **
11 ** Purpose: Provides some basic access to some environment 
12 ** functionality.
13 **
14 **
15 ============================================================*/
16 namespace System {
17     using System.IO;
18     using System.Security;
19     using System.Resources;
20     using System.Globalization;
21     using System.Collections;
22     using System.Security.Permissions;
23     using System.Text;
24     using System.Configuration.Assemblies;
25     using System.Runtime.InteropServices;
26     using System.Reflection;
27     using System.Diagnostics;
28     using Microsoft.Win32;
29     using System.Runtime.CompilerServices;
30     using System.Threading;
31     using System.Runtime.ConstrainedExecution;
32     using System.Runtime.Versioning;
33     using System.Diagnostics.Contracts;
34
35 #if !FEATURE_PAL
36     [ComVisible(true)]
37     public enum EnvironmentVariableTarget {
38         Process = 0,
39 #if FEATURE_WIN32_REGISTRY            
40         User = 1,
41         Machine = 2,
42 #endif        
43     }
44 #endif 
45
46     [ComVisible(true)]
47     public static class Environment {
48
49         // Assume the following constants include the terminating '\0' - use <, not <=
50         const int MaxEnvVariableValueLength = 32767;  // maximum length for environment variable name and value
51         // System environment variables are stored in the registry, and have 
52         // a size restriction that is separate from both normal environment 
53         // variables and registry value name lengths, according to MSDN.
54         // MSDN doesn't detail whether the name is limited to 1024, or whether
55         // that includes the contents of the environment variable.
56         const int MaxSystemEnvVariableLength = 1024;
57         const int MaxUserEnvVariableLength = 255;
58
59         internal sealed class ResourceHelper
60         {
61             internal ResourceHelper(String name) {
62                 m_name = name;
63             }
64
65             private String m_name;
66             private ResourceManager SystemResMgr;
67
68             // To avoid infinite loops when calling GetResourceString.  See comments
69             // in GetResourceString for this field.
70             private Stack currentlyLoading;
71         
72             // process-wide state (since this is only used in one domain), 
73             // used to avoid the TypeInitialization infinite recusion
74             // in GetResourceStringCode
75             internal bool resourceManagerInited = false;
76
77             // Is this thread currently doing infinite resource lookups?
78             private int infinitelyRecursingCount;
79
80             // Data representing one individual resource lookup on a thread.
81             internal class GetResourceStringUserData
82             {
83                 public ResourceHelper m_resourceHelper;
84                 public String m_key;
85                 public CultureInfo m_culture;
86                 public String m_retVal;
87                 public bool m_lockWasTaken;
88
89                 public GetResourceStringUserData(ResourceHelper resourceHelper, String key, CultureInfo culture)
90                 {
91                     m_resourceHelper = resourceHelper;
92                     m_key = key;
93                     m_culture = culture;
94                 }
95             }
96             
97             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
98             internal String GetResourceString(String key) {
99                 if (key == null || key.Length == 0) {
100                     Contract.Assert(false, "Environment::GetResourceString with null or empty key.  Bug in caller, or weird recursive loading problem?");
101                     return "[Resource lookup failed - null or empty resource name]";
102                 }
103                 return GetResourceString(key, null);
104             }
105
106             [System.Security.SecuritySafeCritical]  // auto-generated
107             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
108             internal String GetResourceString(String key, CultureInfo culture)  {
109                 if (key == null || key.Length == 0) {
110                     Contract.Assert(false, "Environment::GetResourceString with null or empty key.  Bug in caller, or weird recursive loading problem?");
111                     return "[Resource lookup failed - null or empty resource name]";
112                 }
113
114                 // We have a somewhat common potential for infinite 
115                 // loops with mscorlib's ResourceManager.  If "potentially dangerous"
116                 // code throws an exception, we will get into an infinite loop
117                 // inside the ResourceManager and this "potentially dangerous" code.
118                 // Potentially dangerous code includes the IO package, CultureInfo,
119                 // parts of the loader, some parts of Reflection, Security (including 
120                 // custom user-written permissions that may parse an XML file at
121                 // class load time), assembly load event handlers, etc.  Essentially,
122                 // this is not a bounded set of code, and we need to fix the problem.
123                 // Fortunately, this is limited to mscorlib's error lookups and is NOT
124                 // a general problem for all user code using the ResourceManager.
125                 
126                 // The solution is to make sure only one thread at a time can call 
127                 // GetResourceString.  Also, since resource lookups can be 
128                 // reentrant, if the same thread comes into GetResourceString
129                 // twice looking for the exact same resource name before 
130                 // returning, we're going into an infinite loop and we should 
131                 // return a bogus string.  
132
133                 GetResourceStringUserData userData = new GetResourceStringUserData(this, key, culture);
134
135                 RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(GetResourceStringCode);
136                 RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(GetResourceStringBackoutCode);
137
138                 RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData);
139                 return userData.m_retVal;
140             }
141
142             #if FEATURE_CORECLR
143             [System.Security.SecurityCritical] // auto-generated
144             #else
145             [System.Security.SecuritySafeCritical]
146             #endif
147             private void GetResourceStringCode(Object userDataIn)
148             {
149                 GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn;
150                 ResourceHelper rh = userData.m_resourceHelper;
151                 String key = userData.m_key;
152                 CultureInfo culture = userData.m_culture;
153
154                 Monitor.Enter(rh, ref userData.m_lockWasTaken);
155
156                 // Are we recursively looking up the same resource?  Note - our backout code will set
157                 // the ResourceHelper's currentlyLoading stack to null if an exception occurs.
158                 if (rh.currentlyLoading != null && rh.currentlyLoading.Count > 0 && rh.currentlyLoading.Contains(key)) {
159                     // We can start infinitely recursing for one resource lookup,
160                     // then during our failure reporting, start infinitely recursing again.
161                     // avoid that.
162                     if (rh.infinitelyRecursingCount > 0) {
163                         userData.m_retVal = "[Resource lookup failed - infinite recursion or critical failure detected.]";
164                         return;
165                     }
166                     rh.infinitelyRecursingCount++;
167                     // This is often a bug in the BCL, security, NLS+ code,
168                     // or the loader somewhere.  However, this could also
169                     // be a setup problem - check whether mscorlib & 
170                     // clr.dll are both of the same build flavor.  Also, user 
171                     // code in the resource lookup process (like an assembly 
172                     // resolve event or custom CultureInfo) might potentially cause issues.
173
174                     // Note: our infrastructure for reporting this exception will again cause resource lookup.
175                     // This is the most direct way of dealing with that problem.
176                     String message = "Infinite recursion during resource lookup within mscorlib.  This may be a bug in mscorlib, or potentially in certain extensibility points such as assembly resolve events or CultureInfo names.  Resource name: " + key;
177                     Assert.Fail("[mscorlib recursive resource lookup bug]", message, Assert.COR_E_FAILFAST, System.Diagnostics.StackTrace.TraceFormat.NoResourceLookup);
178                     Environment.FailFast(message);
179                 }
180                 if (rh.currentlyLoading == null)
181                     rh.currentlyLoading = new Stack(4);
182
183                 // Call class constructors preemptively, so that we cannot get into an infinite
184                 // loop constructing a TypeInitializationException.  If this were omitted,
185                 // we could get the Infinite recursion assert above by failing type initialization
186                 // between the Push and Pop calls below.
187         
188                 if (!rh.resourceManagerInited)
189                 {
190                     // process-critical code here.  No ThreadAbortExceptions
191                     // can be thrown here.  Other exceptions percolate as normal.
192                     RuntimeHelpers.PrepareConstrainedRegions();
193                     try {
194                     }
195                     finally {
196                         RuntimeHelpers.RunClassConstructor(typeof(ResourceManager).TypeHandle);
197                         RuntimeHelpers.RunClassConstructor(typeof(ResourceReader).TypeHandle);
198                         RuntimeHelpers.RunClassConstructor(typeof(RuntimeResourceSet).TypeHandle);
199                         RuntimeHelpers.RunClassConstructor(typeof(BinaryReader).TypeHandle);
200                         rh.resourceManagerInited = true; 
201                     }
202             
203                 } 
204         
205                 rh.currentlyLoading.Push(key);
206
207                 if (rh.SystemResMgr == null) {
208                     rh.SystemResMgr = new ResourceManager(m_name, typeof(Object).Assembly);
209                 }
210                 String s = rh.SystemResMgr.GetString(key, null);
211                 rh.currentlyLoading.Pop();
212
213                 Contract.Assert(s!=null, "Managed resource string lookup failed.  Was your resource name misspelled?  Did you rebuild mscorlib after adding a resource to resources.txt?  Debug this w/ cordbg and bug whoever owns the code that called Environment.GetResourceString.  Resource name was: \""+key+"\"");
214
215                 userData.m_retVal = s;
216             }
217
218             #if FEATURE_CORECLR
219             [System.Security.SecurityCritical] // auto-generated
220             #endif
221             [PrePrepareMethod]
222             private void GetResourceStringBackoutCode(Object userDataIn, bool exceptionThrown)
223             {
224                 GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn;
225                 ResourceHelper rh = userData.m_resourceHelper;
226
227                 if (exceptionThrown)
228                 {
229                     if (userData.m_lockWasTaken) 
230                     {
231                         // Backout code - throw away potentially corrupt state
232                         rh.SystemResMgr = null;
233                         rh.currentlyLoading = null;
234                     }
235                 }
236                 // Release the lock, if we took it.
237                 if (userData.m_lockWasTaken)
238                 {
239                     Monitor.Exit(rh);
240                 }
241             }
242         
243         }
244
245               private static volatile ResourceHelper m_resHelper;  // Doesn't need to be initialized as they're zero-init.
246
247         private const  int    MaxMachineNameLength = 256;
248
249         // Private object for locking instead of locking on a public type for SQL reliability work.
250         private static Object s_InternalSyncObject;
251         private static Object InternalSyncObject {
252             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
253             get {
254                 if (s_InternalSyncObject == null) {
255                     Object o = new Object();
256                     Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
257                 }
258                 return s_InternalSyncObject;
259             }
260         }
261
262
263         private static volatile OperatingSystem m_os;  // Cached OperatingSystem value
264
265         /*==================================TickCount===================================
266         **Action: Gets the number of ticks since the system was started.
267         **Returns: The number of ticks since the system was started.
268         **Arguments: None
269         **Exceptions: None
270         ==============================================================================*/
271         public static extern int TickCount {
272             [System.Security.SecuritySafeCritical]  // auto-generated
273             [ResourceExposure(ResourceScope.None)]
274             [MethodImplAttribute(MethodImplOptions.InternalCall)]
275             get;
276         }
277         
278         // Terminates this process with the given exit code.
279         [System.Security.SecurityCritical]  // auto-generated
280         [ResourceExposure(ResourceScope.Process)]
281         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
282         [SuppressUnmanagedCodeSecurity]
283         internal static extern void _Exit(int exitCode);
284
285         [System.Security.SecuritySafeCritical]  // auto-generated
286         [ResourceExposure(ResourceScope.Process)]
287         [ResourceConsumption(ResourceScope.Process)]
288 #pragma warning disable 618
289         [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
290 #pragma warning restore 618
291         public static void Exit(int exitCode) {
292             _Exit(exitCode);
293         }
294
295
296         public static extern int ExitCode {
297             [System.Security.SecuritySafeCritical]  // auto-generated
298             [ResourceExposure(ResourceScope.None)]
299             [MethodImplAttribute(MethodImplOptions.InternalCall)]
300             get;
301     
302             [System.Security.SecuritySafeCritical]  // auto-generated
303             [ResourceExposure(ResourceScope.None)]
304             [MethodImplAttribute(MethodImplOptions.InternalCall)]
305             set;
306         }
307
308         // Note: The CLR's Watson bucketization code looks at the caller of the FCALL method
309         // to assign blame for crashes.  Don't mess with this, such as by making it call 
310         // another managed helper method, unless you consult with some CLR Watson experts.
311         [System.Security.SecurityCritical]
312         [ResourceExposure(ResourceScope.Process)]
313         [MethodImplAttribute(MethodImplOptions.InternalCall)]
314         public static extern void FailFast(String message);
315
316         [System.Security.SecurityCritical]
317         [ResourceExposure(ResourceScope.Process)]
318         [MethodImplAttribute(MethodImplOptions.InternalCall)]
319         internal static extern void FailFast(String message, uint exitCode);
320
321         // This overload of FailFast will allow you to specify the exception object
322         // whose bucket details *could* be used when undergoing the failfast process.
323         // To be specific:
324         //
325         // 1) When invoked from within a managed EH clause (fault/finally/catch),
326         //    if the exception object is preallocated, the runtime will try to find its buckets
327         //    and use them. If the exception object is not preallocated, it will use the bucket
328         //    details contained in the object (if any).
329         //
330         // 2) When invoked from outside the managed EH clauses (fault/finally/catch),
331         //    if the exception object is preallocated, the runtime will use the callsite's
332         //    IP for bucketing. If the exception object is not preallocated, it will use the bucket
333         //    details contained in the object (if any).
334         [System.Security.SecurityCritical]
335         [ResourceExposure(ResourceScope.Process)]
336         [MethodImplAttribute(MethodImplOptions.InternalCall)]
337         public static extern void FailFast(String message, Exception exception);
338
339 #if !FEATURE_CORECLR
340         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
341         [SecurityCritical]  // Our security team doesn't yet allow safe-critical P/Invoke methods.
342         [ResourceExposure(ResourceScope.None)]
343         [SuppressUnmanagedCodeSecurity]
344         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
345         internal static extern void TriggerCodeContractFailure(ContractFailureKind failureKind, String message, String condition, String exceptionAsString);
346
347         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
348         [SecurityCritical]  // Our security team doesn't yet allow safe-critical P/Invoke methods.
349         [ResourceExposure(ResourceScope.None)]
350         [SuppressUnmanagedCodeSecurity]
351         [return: MarshalAs(UnmanagedType.Bool)]
352         private static extern bool GetIsCLRHosted();
353
354         internal static bool IsCLRHosted {
355             [SecuritySafeCritical]
356             get { return GetIsCLRHosted(); }
357         }
358
359         public static String CommandLine {
360             [System.Security.SecuritySafeCritical]  // auto-generated
361             get {
362                 new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand();
363
364                 String commandLine = null;
365                 GetCommandLine(JitHelpers.GetStringHandleOnStack(ref commandLine));
366                 return commandLine;
367             }
368         }
369
370         [System.Security.SecurityCritical]  // auto-generated
371         [ResourceExposure(ResourceScope.None)]
372         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
373         private static extern void GetCommandLine(StringHandleOnStack retString);
374 #endif // !FEATURE_CORECLR
375
376         /*===============================CurrentDirectory===============================
377         **Action:  Provides a getter and setter for the current directory.  The original
378         **         current directory is the one from which the process was started.  
379         **Returns: The current directory (from the getter).  Void from the setter.
380         **Arguments: The current directory to which to switch to the setter.
381         **Exceptions: 
382         ==============================================================================*/
383         public static String CurrentDirectory
384         {
385             [ResourceExposure(ResourceScope.Machine)]
386             [ResourceConsumption(ResourceScope.Machine)]
387             get{
388                 return Directory.GetCurrentDirectory();
389             }
390
391             #if FEATURE_CORECLR
392             [System.Security.SecurityCritical] // auto-generated
393             #endif
394             [ResourceExposure(ResourceScope.Machine)]
395             [ResourceConsumption(ResourceScope.Machine)]
396             set { 
397                 Directory.SetCurrentDirectory(value);
398             }
399         }
400
401         // Returns the system directory (ie, C:\WinNT\System32).
402         public static String SystemDirectory {
403 #if FEATURE_CORECLR
404             [System.Security.SecurityCritical]
405 #else
406             [System.Security.SecuritySafeCritical]  // auto-generated
407 #endif
408             [ResourceExposure(ResourceScope.Machine)]
409             [ResourceConsumption(ResourceScope.Machine)]
410             get {
411                 StringBuilder sb = new StringBuilder(Path.MAX_PATH);
412                 int r = Win32Native.GetSystemDirectory(sb, Path.MAX_PATH);
413                 Contract.Assert(r < Path.MAX_PATH, "r < Path.MAX_PATH");
414                 if (r==0) __Error.WinIOError();
415                 String path = sb.ToString();
416                 
417 #if !FEATURE_CORECLR
418                 // Do security check
419                 new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
420 #endif
421
422                 return path;
423             }
424         }
425
426 #if !FEATURE_PAL
427         // Returns the windows directory (ie, C:\WinNT).
428         // Used by NLS+ custom culures only at the moment.
429         internal static String InternalWindowsDirectory {
430             [System.Security.SecurityCritical]  // auto-generated
431             [ResourceExposure(ResourceScope.Machine)]
432             [ResourceConsumption(ResourceScope.Machine)]
433             get {
434                 StringBuilder sb = new StringBuilder(Path.MAX_PATH);
435                 int r = Win32Native.GetWindowsDirectory(sb, Path.MAX_PATH);
436                 Contract.Assert(r < Path.MAX_PATH, "r < Path.MAX_PATH");
437                 if (r==0) __Error.WinIOError();
438                 String path = sb.ToString();
439                 
440                 return path;
441             }
442         }
443
444         [System.Security.SecuritySafeCritical]  // auto-generated
445         public static String ExpandEnvironmentVariables(String name)
446         {
447             if (name == null)
448                 throw new ArgumentNullException("name");
449             Contract.EndContractBlock();
450
451             if (name.Length == 0) {
452                 return name;
453             }
454
455             if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
456                 // Environment variable accessors are not approved modern API.
457                 // Behave as if no variables are defined in this case.
458                 return name; 
459             }
460
461             int currentSize = 100;
462             StringBuilder blob = new StringBuilder(currentSize); // A somewhat reasonable default size
463             int size;
464
465 #if !FEATURE_CORECLR
466             bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands();
467
468             // Do a security check to guarantee we can read each of the 
469             // individual environment variables requested here.
470             String[] varArray = name.Split(new char[] {'%'});
471             StringBuilder vars = isFullTrust ? null : new StringBuilder();
472
473             bool fJustExpanded = false; // to accommodate expansion alg.
474
475             for(int i=1; i<varArray.Length-1; i++) { // Skip first and last tokens
476                 // ExpandEnvironmentStrings' greedy algorithm expands every
477                 // non-boundary %-delimited substring, provided the previous
478                 // has not been expanded.
479                 // if "foo" is not expandable, and "PATH" is, then both
480                 // %foo%PATH% and %foo%foo%PATH% will expand PATH, but
481                 // %PATH%PATH% will expand only once.
482                 // Therefore, if we've just expanded, skip this substring.
483                 if (varArray[i].Length == 0 || fJustExpanded == true)
484                 {
485                     fJustExpanded = false;
486                     continue; // Nothing to expand
487                 }
488                 // Guess a somewhat reasonable initial size, call the method, then if
489                 // it fails (ie, the return value is larger than our buffer size),
490                 // make a new buffer & try again.
491                 blob.Length = 0;
492                 String envVar = "%" + varArray[i] + "%";
493                 size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize);
494                 if (size == 0)
495                     Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
496
497                 // some environment variable might be changed while this function is called
498                 while (size > currentSize) {
499                     currentSize = size;
500                     blob.Capacity = currentSize;
501                     blob.Length = 0;
502                     size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize);
503                     if (size == 0)
504                         Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
505                 }
506
507                 if (!isFullTrust) {
508                     String temp = blob.ToString();
509                     fJustExpanded = (temp != envVar);
510                     if (fJustExpanded) { // We expanded successfully, we need to do String comparison here
511                         // since %FOO% can become %FOOD
512                         vars.Append(varArray[i]);
513                         vars.Append(';');
514                     }
515                 }
516             }
517      
518             if (!isFullTrust)
519                 new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand();
520 #endif // !FEATURE_CORECLR
521
522             blob.Length = 0;
523             size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize);
524             if (size == 0)
525                 Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
526             
527             while (size > currentSize) {
528                 currentSize = size;
529                 blob.Capacity = currentSize;
530                 blob.Length = 0;
531
532                 size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize);
533                 if (size == 0)
534                     Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
535             }
536
537             return blob.ToString();
538         }
539 #endif // FEATURE_PAL
540
541         public static String MachineName {
542             [System.Security.SecuritySafeCritical]  // auto-generated
543             get {
544                 // In future release of operating systems, you might be able to rename a machine without
545                 // rebooting.  Therefore, don't cache this machine name.
546                 new EnvironmentPermission(EnvironmentPermissionAccess.Read, "COMPUTERNAME").Demand();
547                 StringBuilder buf = new StringBuilder(MaxMachineNameLength);
548                 int len = MaxMachineNameLength;
549                 if (Win32Native.GetComputerName(buf, ref len) == 0)
550                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ComputerName"));
551                 return buf.ToString();
552             }
553         }
554
555         [SecurityCritical]
556         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
557         [SuppressUnmanagedCodeSecurity]
558         private static extern Int32 GetProcessorCount();
559
560         public static int ProcessorCount {
561             [System.Security.SecuritySafeCritical]  // auto-generated
562             get {
563                 return GetProcessorCount();
564             }
565         }
566
567         public static int SystemPageSize {
568             [System.Security.SecuritySafeCritical]  // auto-generated
569             get {
570                 (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
571                 Win32Native.SYSTEM_INFO info = new Win32Native.SYSTEM_INFO();
572                 Win32Native.GetSystemInfo(ref info);
573                 return info.dwPageSize;
574             }
575         }
576
577 #if !FEATURE_CORECLR
578         /*==============================GetCommandLineArgs==============================
579         **Action: Gets the command line and splits it appropriately to deal with whitespace,
580         **        quotes, and escape characters.
581         **Returns: A string array containing your command line arguments.
582         **Arguments: None
583         **Exceptions: None.
584         ==============================================================================*/
585         [System.Security.SecuritySafeCritical]  // auto-generated
586         public static String[] GetCommandLineArgs() {
587             new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand();
588             return GetCommandLineArgsNative();
589         }
590
591         [System.Security.SecurityCritical]  // auto-generated
592         [ResourceExposure(ResourceScope.None)]
593         [MethodImplAttribute(MethodImplOptions.InternalCall)]
594         private static extern String[] GetCommandLineArgsNative();
595         
596         // We need to keep this Fcall since it is used in AppDomain.cs.
597         // If we call GetEnvironmentVariable from AppDomain.cs, we will use StringBuilder class.
598         // That has side effect to change the ApartmentState of the calling Thread to MTA.
599         // So runtime can't change the ApartmentState of calling thread any more.
600         [System.Security.SecurityCritical]  // auto-generated
601         [ResourceExposure(ResourceScope.Process)]
602         [MethodImplAttribute(MethodImplOptions.InternalCall)]
603         internal static extern String nativeGetEnvironmentVariable(String variable);
604 #endif //!FEATURE_CORECLR
605         
606         /*============================GetEnvironmentVariable============================
607         **Action:
608         **Returns:
609         **Arguments:
610         **Exceptions:
611         ==============================================================================*/
612         [System.Security.SecuritySafeCritical]  // auto-generated
613         [ResourceExposure(ResourceScope.Machine)]
614         [ResourceConsumption(ResourceScope.Machine)]
615         public static String GetEnvironmentVariable(String variable)
616         {
617             if (variable == null)
618                 throw new ArgumentNullException("variable");
619             Contract.EndContractBlock();
620
621             if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
622                 // Environment variable accessors are not approved modern API.
623                 // Behave as if the variable was not found in this case.
624                 return null; 
625             }
626
627 #if !FEATURE_CORECLR
628             (new EnvironmentPermission(EnvironmentPermissionAccess.Read, variable)).Demand();
629 #endif //!FEATURE_CORECLR
630             
631             StringBuilder blob = StringBuilderCache.Acquire(128); // A somewhat reasonable default size
632             int requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity);
633
634             if (requiredSize == 0) {  //  GetEnvironmentVariable failed
635                 if (Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND) {
636                     StringBuilderCache.Release(blob);
637                     return null;
638                 }
639             }
640
641             while (requiredSize > blob.Capacity) { // need to retry since the environment variable might be changed 
642                 blob.Capacity = requiredSize;
643                 blob.Length = 0;
644                 requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity);
645             }
646             return StringBuilderCache.GetStringAndRelease(blob);
647         }
648         
649 #if !FEATURE_PAL
650         [System.Security.SecuritySafeCritical]  // auto-generated
651         [ResourceExposure(ResourceScope.Machine)]
652         [ResourceConsumption(ResourceScope.Machine)]
653         public static string GetEnvironmentVariable( string variable, EnvironmentVariableTarget target)                
654         {
655             if (variable == null)
656             {
657                 throw new ArgumentNullException("variable");
658             }
659             Contract.EndContractBlock();
660
661             if (target == EnvironmentVariableTarget.Process)
662             {
663                 return GetEnvironmentVariable(variable);
664             }
665
666 #if FEATURE_WIN32_REGISTRY
667             (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
668
669             if( target == EnvironmentVariableTarget.Machine) {
670                 using (RegistryKey environmentKey = 
671                        Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) {
672
673                    Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!");
674                    if (environmentKey == null) {
675                        return null; 
676                    }
677
678                    string value = environmentKey.GetValue(variable) as string;
679                    return value;
680                 }
681             }
682             else if( target == EnvironmentVariableTarget.User) {
683                 using (RegistryKey environmentKey = 
684                        Registry.CurrentUser.OpenSubKey("Environment", false)) {
685
686                    Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!");
687                    if (environmentKey == null) {
688                        return null; 
689                    }
690
691                    string value = environmentKey.GetValue(variable) as string;
692                    return value;
693                 }
694             }
695             else 
696 #endif // FEATURE_WIN32_REGISTRY                
697                 {
698                 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
699             }
700         }
701 #endif
702
703         /*===========================GetEnvironmentVariables============================
704         **Action: Returns an IDictionary containing all enviroment variables and their values.
705         **Returns: An IDictionary containing all environment variables and their values.
706         **Arguments: None.
707         **Exceptions: None.
708         ==============================================================================*/
709         [System.Security.SecurityCritical]  // auto-generated
710         [ResourceExposure(ResourceScope.Machine)]
711         private unsafe static char[] GetEnvironmentCharArray()
712         {
713             char[] block = null;
714
715             // Make sure pStrings is not leaked with async exceptions
716             RuntimeHelpers.PrepareConstrainedRegions();
717             try {
718             }
719             finally {
720                 char * pStrings = null;
721
722                 try
723                 {
724                     pStrings = Win32Native.GetEnvironmentStrings();
725                     if (pStrings == null) {
726                         throw new OutOfMemoryException();
727                     }
728
729                     // Format for GetEnvironmentStrings is:
730                     // [=HiddenVar=value\0]* [Variable=value\0]* \0
731                     // See the description of Environment Blocks in MSDN's
732                     // CreateProcess page (null-terminated array of null-terminated strings).
733
734                     // Search for terminating \0\0 (two unicode \0's).
735                     char * p = pStrings;
736                     while (!(*p == '\0' && *(p + 1) == '\0'))
737                         p++;
738
739                     int len = (int)(p - pStrings + 1);
740                     block = new char[len];
741
742                     fixed (char* pBlock = block)
743                         String.wstrcpy(pBlock, pStrings, len);
744                 }
745                 finally
746                 {
747                     if (pStrings != null)
748                         Win32Native.FreeEnvironmentStrings(pStrings);
749                 }
750             }
751
752             return block;
753         }
754
755         [System.Security.SecuritySafeCritical]  // auto-generated
756         [ResourceExposure(ResourceScope.Machine)]
757         [ResourceConsumption(ResourceScope.Machine)]
758         public static IDictionary GetEnvironmentVariables()
759         {
760             if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
761                 // Environment variable accessors are not approved modern API.
762                 // Behave as if no environment variables are defined in this case.
763                 return new Hashtable(0);
764             }
765
766 #if !FEATURE_CORECLR
767             bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands();
768             StringBuilder vars = isFullTrust ? null : new StringBuilder();  
769             bool first = true;
770 #endif
771
772             char[] block = GetEnvironmentCharArray();
773
774             Hashtable table = new Hashtable(20);
775
776             // Copy strings out, parsing into pairs and inserting into the table.
777             // The first few environment variable entries start with an '='!
778             // The current working directory of every drive (except for those drives
779             // you haven't cd'ed into in your DOS window) are stored in the 
780             // environment block (as =C:=pwd) and the program's exit code is 
781             // as well (=ExitCode=00000000)  Skip all that start with =.
782             // Read docs about Environment Blocks on MSDN's CreateProcess page.
783             
784             // Format for GetEnvironmentStrings is:
785             // (=HiddenVar=value\0 | Variable=value\0)* \0
786             // See the description of Environment Blocks in MSDN's
787             // CreateProcess page (null-terminated array of null-terminated strings).
788             // Note the =HiddenVar's aren't always at the beginning.
789             
790             for(int i=0; i<block.Length; i++) {
791                 int startKey = i;
792                 // Skip to key
793                 // On some old OS, the environment block can be corrupted. 
794                 // Someline will not have '=', so we need to check for '\0'. 
795                 while(block[i]!='=' && block[i] != '\0') {
796                     i++;
797                 }
798
799                 if(block[i] == '\0') {
800                     continue;
801                 }
802
803                 // Skip over environment variables starting with '='
804                 if (i-startKey==0) {
805                     while(block[i]!=0) {
806                         i++;
807                     }
808                     continue;
809                 }
810                 String key = new String(block, startKey, i-startKey);
811                 i++;  // skip over '='
812                 int startValue = i;
813                 while(block[i]!=0) {
814                     // Read to end of this entry 
815                     i++;
816                 }
817
818                 String value = new String(block, startValue, i-startValue);
819                 // skip over 0 handled by for loop's i++
820                 table[key]=value;
821
822 #if !FEATURE_CORECLR
823                 if (!isFullTrust) {
824                     if( first) {      
825                         first = false;
826                     }
827                     else {
828                         vars.Append(';');
829                     }
830                     vars.Append(key);
831                 }
832 #endif
833             }
834
835 #if !FEATURE_CORECLR
836             if (!isFullTrust)
837                 new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand();
838 #endif
839             return table;
840         }
841         
842 #if !FEATURE_PAL
843         internal static IDictionary GetRegistryKeyNameValuePairs(RegistryKey registryKey) {
844             Hashtable table = new Hashtable(20);
845
846             if (registryKey != null) {
847                 string[] names = registryKey.GetValueNames();
848                 foreach( string name in names) {
849                     string value = registryKey.GetValue(name, "").ToString();
850                     table.Add(name, value);                
851                 }            
852             }
853             return table;
854         }
855
856         [System.Security.SecuritySafeCritical]  // auto-generated
857         [ResourceExposure(ResourceScope.Machine)]
858         [ResourceConsumption(ResourceScope.Machine)]
859         public static IDictionary GetEnvironmentVariables( EnvironmentVariableTarget target) {
860             if( target == EnvironmentVariableTarget.Process) {
861                 return GetEnvironmentVariables();
862             }
863
864 #if FEATURE_WIN32_REGISTRY
865             (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
866
867             if( target == EnvironmentVariableTarget.Machine) {
868                 using (RegistryKey environmentKey = 
869                        Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) {
870
871                    return GetRegistryKeyNameValuePairs(environmentKey);
872                 }
873             }
874             else if( target == EnvironmentVariableTarget.User) {
875                 using (RegistryKey environmentKey = 
876                        Registry.CurrentUser.OpenSubKey("Environment", false)) {
877                    return GetRegistryKeyNameValuePairs(environmentKey);
878                 }
879             }
880             else 
881 #endif // FEATURE_WIN32_REGISTRY                
882                 {
883                 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
884             }
885         }
886 #endif
887
888         [System.Security.SecuritySafeCritical]  // auto-generated
889         [ResourceExposure(ResourceScope.Machine)]
890         [ResourceConsumption(ResourceScope.Machine)]
891         public static void SetEnvironmentVariable(string variable, string value) {
892             CheckEnvironmentVariableName(variable);
893
894 #if !FEATURE_CORECLR
895             new EnvironmentPermission(PermissionState.Unrestricted).Demand();
896 #endif
897             // explicitly null out value if is the empty string. 
898             if (String.IsNullOrEmpty(value) || value[0] == '\0') {
899                 value = null;
900             }
901             else {
902                 if( value.Length >= MaxEnvVariableValueLength) {
903                     throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));                                    
904                 }
905             }
906
907             if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
908                 // Environment variable accessors are not approved modern API.
909                 // so we throw PlatformNotSupportedException.
910                 throw new PlatformNotSupportedException();
911             }
912
913             if(!Win32Native.SetEnvironmentVariable(variable, value)) {
914                 int errorCode = Marshal.GetLastWin32Error();
915                 
916                 // Allow user to try to clear a environment variable                
917                 if( errorCode == Win32Native.ERROR_ENVVAR_NOT_FOUND) {
918                     return;
919                 }
920                 
921                 // The error message from Win32 is "The filename or extension is too long",
922                 // which is not accurate.
923                 if( errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE) {
924                     throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));
925                 }
926                 
927                 throw new ArgumentException(Win32Native.GetMessage(errorCode));
928             }
929         }
930
931         private static void CheckEnvironmentVariableName(string variable) {
932             if (variable == null) {
933                 throw new ArgumentNullException("variable");
934             }
935
936             if( variable.Length == 0) {
937                 throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "variable");
938             }
939
940             if( variable[0] == '\0') {
941                 throw new ArgumentException(Environment.GetResourceString("Argument_StringFirstCharIsZero"), "variable");
942             }
943
944             // Make sure the environment variable name isn't longer than the 
945             // max limit on environment variable values.  (MSDN is ambiguous 
946             // on whether this check is necessary.)
947             if( variable.Length >= MaxEnvVariableValueLength ) {
948                 throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));                
949             }
950             
951             if( variable.IndexOf('=') != -1) {
952                 throw new ArgumentException(Environment.GetResourceString("Argument_IllegalEnvVarName"));
953             }
954             Contract.EndContractBlock();
955         }
956
957 #if !FEATURE_PAL
958         [System.Security.SecuritySafeCritical]  // auto-generated
959         [ResourceExposure(ResourceScope.Machine)]
960         [ResourceConsumption(ResourceScope.Machine)]
961         public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) { 
962             if( target == EnvironmentVariableTarget.Process) {
963                 SetEnvironmentVariable(variable, value);
964                 return;
965             }
966         
967             CheckEnvironmentVariableName(variable);
968
969             // System-wide environment variables stored in the registry are
970             // limited to 1024 chars for the environment variable name.
971             if (variable.Length >= MaxSystemEnvVariableLength) {
972                 throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarName"));
973             }
974
975             new EnvironmentPermission(PermissionState.Unrestricted).Demand();
976             // explicitly null out value if is the empty string. 
977             if (String.IsNullOrEmpty(value) || value[0] == '\0') {
978                 value = null;
979             }
980 #if FEATURE_WIN32_REGISTRY
981             if( target == EnvironmentVariableTarget.Machine) {
982                 using (RegistryKey environmentKey = 
983                        Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", true)) {
984
985                    Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!");
986                    if (environmentKey != null) {
987                        if (value == null)
988                            environmentKey.DeleteValue(variable, false);
989                        else
990                            environmentKey.SetValue(variable, value);
991                    }
992                 }
993             }
994             else if( target == EnvironmentVariableTarget.User) {
995                 // User-wide environment variables stored in the registry are
996                 // limited to 255 chars for the environment variable name.
997                 if (variable.Length >= MaxUserEnvVariableLength) {
998                     throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));
999                 }
1000                 using (RegistryKey environmentKey = 
1001                        Registry.CurrentUser.OpenSubKey("Environment", true)) {
1002                    Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!");
1003                    if (environmentKey != null) {
1004                       if (value == null)
1005                           environmentKey.DeleteValue(variable, false);
1006                       else
1007                           environmentKey.SetValue(variable, value);
1008                    }
1009                 }
1010             }
1011             else
1012             {
1013                 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
1014             }
1015             // send a WM_SETTINGCHANGE message to all windows
1016             IntPtr r = Win32Native.SendMessageTimeout(new IntPtr(Win32Native.HWND_BROADCAST), Win32Native.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero);
1017
1018             if (r == IntPtr.Zero) BCLDebug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error());
1019
1020 #else // FEATURE_WIN32_REGISTRY
1021             throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
1022 #endif
1023         }
1024 #endif
1025
1026         
1027         /*===============================GetLogicalDrives===============================
1028         **Action: Retrieves the names of the logical drives on this machine in the  form "C:\". 
1029         **Arguments:   None.
1030         **Exceptions:  IOException.
1031         **Permissions: SystemInfo Permission.
1032         ==============================================================================*/
1033         [System.Security.SecuritySafeCritical]  // auto-generated
1034         public static String[] GetLogicalDrives() {
1035             new EnvironmentPermission(PermissionState.Unrestricted).Demand();
1036                                  
1037             int drives = Win32Native.GetLogicalDrives();
1038             if (drives==0)
1039                 __Error.WinIOError();
1040             uint d = (uint)drives;
1041             int count = 0;
1042             while (d != 0) {
1043                 if (((int)d & 1) != 0) count++;
1044                 d >>= 1;
1045             }
1046             String[] result = new String[count];
1047             char[] root = new char[] {'A', ':', '\\'};
1048             d = (uint)drives;
1049             count = 0;
1050             while (d != 0) {
1051                 if (((int)d & 1) != 0) {
1052                     result[count++] = new String(root);
1053                 }
1054                 d >>= 1;
1055                 root[0]++;
1056             }
1057             return result;
1058         }
1059         
1060         /*===================================NewLine====================================
1061         **Action: A property which returns the appropriate newline string for the given
1062         **        platform.
1063         **Returns: \r\n on Win32.
1064         **Arguments: None.
1065         **Exceptions: None.
1066         ==============================================================================*/
1067         public static String NewLine {
1068             get {
1069                 Contract.Ensures(Contract.Result<String>() != null);
1070                 return "\r\n";
1071             }
1072         }
1073
1074         
1075         /*===================================Version====================================
1076         **Action: Returns the COM+ version struct, describing the build number.
1077         **Returns:
1078         **Arguments:
1079         **Exceptions:
1080         ==============================================================================*/
1081         public static Version Version {
1082             get {
1083
1084                 // Previously this represented the File version of mscorlib.dll.  Many other libraries in the framework and outside took dependencies on the first three parts of this version 
1085                 // remaining constant throughout 4.x.  From 4.0 to 4.5.2 this was fine since the file version only incremented the last part.Starting with 4.6 we switched to a file versioning
1086                 // scheme that matched the product version.  In order to preserve compatibility with existing libraries, this needs to be hard-coded.
1087                 
1088                 return new Version(4,0,30319,42000);
1089             }
1090         }
1091
1092         
1093         /*==================================WorkingSet==================================
1094         **Action:
1095         **Returns:
1096         **Arguments:
1097         **Exceptions:
1098         ==============================================================================*/
1099         [System.Security.SecurityCritical]  // auto-generated
1100         [ResourceExposure(ResourceScope.None)]
1101         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
1102         private static extern long GetWorkingSet();
1103
1104         public static long WorkingSet {
1105             [System.Security.SecuritySafeCritical]  // auto-generated
1106             get {
1107                 new EnvironmentPermission(PermissionState.Unrestricted).Demand();
1108                 return GetWorkingSet();
1109             }
1110         }
1111
1112
1113         /*==================================OSVersion===================================
1114         **Action:
1115         **Returns:
1116         **Arguments:
1117         **Exceptions:
1118         ==============================================================================*/
1119         public static OperatingSystem OSVersion {
1120             [System.Security.SecuritySafeCritical]  // auto-generated
1121             get {
1122                 Contract.Ensures(Contract.Result<OperatingSystem>() != null);
1123
1124                 if (m_os==null) { // We avoid the lock since we don't care if two threads will set this at the same time.
1125                             
1126                     Microsoft.Win32.Win32Native.OSVERSIONINFO osvi = new Microsoft.Win32.Win32Native.OSVERSIONINFO();
1127                     if (!GetVersion(osvi)) {
1128                         throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion"));
1129                     }
1130
1131                     Microsoft.Win32.Win32Native.OSVERSIONINFOEX osviEx = new Microsoft.Win32.Win32Native.OSVERSIONINFOEX();
1132                     if (!GetVersionEx(osviEx))
1133                         throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion"));
1134
1135                     PlatformID id = PlatformID.Win32NT;
1136
1137 #if FEATURE_LEGACYNETCF
1138                     // return platform as WinCE, to ensure apps earlier than WP8 works as expected. 
1139                     if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
1140                     {
1141                         id = PlatformID.WinCE;
1142                     }
1143 #endif
1144
1145                     Version v =  new Version(osvi.MajorVersion, osvi.MinorVersion, osvi.BuildNumber, (osviEx.ServicePackMajor << 16) |osviEx.ServicePackMinor);
1146                     m_os = new OperatingSystem(id, v, osvi.CSDVersion);
1147                 }
1148                 Contract.Assert(m_os != null, "m_os != null");
1149                 return m_os;
1150             }
1151         }
1152
1153 #if FEATURE_CORESYSTEM
1154
1155         internal static bool IsWindows8OrAbove {
1156             get {
1157                 return true;
1158             }
1159         }
1160
1161 #if FEATURE_COMINTEROP
1162         internal static bool IsWinRTSupported {
1163             get {
1164                 return true;
1165             }
1166         }
1167 #endif // FEATURE_COMINTEROP
1168
1169 #else // FEATURE_CORESYSTEM
1170
1171         private static volatile bool s_IsWindows8OrAbove;
1172         private static volatile bool s_CheckedOSWin8OrAbove;
1173
1174         // Windows 8 version is 6.2
1175         internal static bool IsWindows8OrAbove {
1176             get {
1177                 if (!s_CheckedOSWin8OrAbove) {
1178                     OperatingSystem OS = Environment.OSVersion;
1179                     s_IsWindows8OrAbove = (OS.Platform == PlatformID.Win32NT && 
1180                                    ((OS.Version.Major == 6 && OS.Version.Minor >= 2) || (OS.Version.Major > 6)));
1181                     s_CheckedOSWin8OrAbove = true;
1182                 }
1183                 return s_IsWindows8OrAbove;
1184             }
1185         }
1186
1187 #if FEATURE_COMINTEROP
1188         private static volatile bool s_WinRTSupported;
1189         private static volatile bool s_CheckedWinRT;
1190
1191         // Does the current version of Windows have Windows Runtime suppport?
1192         internal static bool IsWinRTSupported {
1193             [SecuritySafeCritical]
1194             get {
1195                 if (!s_CheckedWinRT) {
1196                     s_WinRTSupported = WinRTSupported();
1197                     s_CheckedWinRT = true;
1198                 }
1199
1200                 return s_WinRTSupported;
1201             }
1202         }
1203
1204         [SecurityCritical]
1205         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
1206         [SuppressUnmanagedCodeSecurity]
1207         [return: MarshalAs(UnmanagedType.Bool)]
1208         private static extern bool WinRTSupported();
1209 #endif // FEATURE_COMINTEROP
1210
1211 #endif // FEATURE_CORESYSTEM
1212
1213         [System.Security.SecurityCritical]  // auto-generated
1214         [ResourceExposure(ResourceScope.None)]
1215         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1216         internal static extern bool GetVersion(Microsoft.Win32.Win32Native.OSVERSIONINFO  osVer);
1217
1218         [System.Security.SecurityCritical]  // auto-generated
1219         [ResourceExposure(ResourceScope.None)]
1220         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1221         internal static extern bool GetVersionEx(Microsoft.Win32.Win32Native.OSVERSIONINFOEX  osVer);
1222
1223
1224         /*==================================StackTrace==================================
1225         **Action:
1226         **Returns:
1227         **Arguments:
1228         **Exceptions:
1229         ==============================================================================*/
1230         public static String StackTrace {
1231             [System.Security.SecuritySafeCritical]  // auto-generated
1232             get {
1233                 Contract.Ensures(Contract.Result<String>() != null);
1234
1235                 new EnvironmentPermission(PermissionState.Unrestricted).Demand();
1236                 return GetStackTrace(null, true);
1237             }
1238         }
1239
1240         #if FEATURE_CORECLR
1241         [System.Security.SecurityCritical] // auto-generated
1242         #endif
1243         internal static String GetStackTrace(Exception e, bool needFileInfo)
1244         {
1245             // Note: Setting needFileInfo to true will start up COM and set our
1246             // apartment state.  Try to not call this when passing "true" 
1247             // before the EE's ExecuteMainMethod has had a chance to set up the
1248             // apartment state.  -- 
1249             StackTrace st;
1250             if (e == null)
1251                 st = new StackTrace(needFileInfo);
1252             else
1253                 st = new StackTrace(e, needFileInfo);
1254
1255             // Do no include a trailing newline for backwards compatibility
1256             return st.ToString( System.Diagnostics.StackTrace.TraceFormat.Normal );
1257         }
1258
1259         [System.Security.SecuritySafeCritical]  // auto-generated
1260         private static void InitResourceHelper() {
1261             // Only the default AppDomain should have a ResourceHelper.  All calls to 
1262             // GetResourceString from any AppDomain delegate to GetResourceStringLocal 
1263             // in the default AppDomain via the fcall GetResourceFromDefault.
1264
1265             bool tookLock = false;
1266             RuntimeHelpers.PrepareConstrainedRegions();
1267             try {
1268
1269                 Monitor.Enter(Environment.InternalSyncObject, ref tookLock);
1270
1271                 if (m_resHelper == null) {
1272                     ResourceHelper rh = new ResourceHelper("mscorlib");
1273
1274                     System.Threading.Thread.MemoryBarrier();
1275                     m_resHelper =rh;
1276                 }
1277             }
1278             finally {
1279                 if (tookLock)
1280                     Monitor.Exit(Environment.InternalSyncObject);
1281             }
1282         }
1283
1284 #if !FEATURE_CORECLR
1285         [System.Security.SecurityCritical]  // auto-generated
1286         [ResourceExposure(ResourceScope.None)]
1287         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1288         internal extern static String GetResourceFromDefault(String key);           
1289 #endif  
1290
1291         // Looks up the resource string value for key.
1292         // 
1293         // if you change this method's signature then you must change the code that calls it
1294         // in excep.cpp and probably you will have to visit mscorlib.h to add the new signature
1295         // as well as metasig.h to create the new signature type
1296         #if FEATURE_CORECLR
1297         [System.Security.SecurityCritical] // auto-generated
1298         #endif
1299         internal static String GetResourceStringLocal(String key) {
1300             if (m_resHelper == null)
1301                 InitResourceHelper();
1302
1303             return m_resHelper.GetResourceString(key);
1304         }
1305
1306         // #threadCultureInfo
1307         // Currently in silverlight, CurrentCulture and CurrentUICulture are isolated 
1308         // within an AppDomain. This is in contrast to the desktop, in which cultures 
1309         // leak across AppDomain boundaries with the thread. 
1310         // 
1311         // Note that mscorlib transitions to the default domain to perform resource 
1312         // lookup. This causes problems for the silverlight changes: since culture isn't
1313         // passed, resource string lookup won't necessarily use the culture of the thread 
1314         // originating the request. To get around that problem, we pass the CultureInfo 
1315         // so that the ResourceManager GetString(x, cultureInfo) overload can be used. 
1316         // We first perform the same check as in CultureInfo to make sure it's safe to 
1317         // let the CultureInfo travel across AppDomains. 
1318
1319         [System.Security.SecuritySafeCritical]  // auto-generated
1320         [ResourceExposure(ResourceScope.None)]
1321         internal static String GetResourceString(String key) {
1322 #if FEATURE_CORECLR
1323             return GetResourceStringLocal(key);
1324 #else
1325             return GetResourceFromDefault(key);
1326 #endif //FEATURE_CORECLR
1327         }
1328
1329         [System.Security.SecuritySafeCritical]  // auto-generated
1330         [ResourceExposure(ResourceScope.None)]
1331         internal static String GetResourceString(String key, params Object[] values) {
1332             String s = GetResourceString(key);
1333             return String.Format(CultureInfo.CurrentCulture, s, values);
1334         }
1335
1336         //The following two internal methods are not used anywhere within the framework,
1337         // but are being kept around as external platforms built on top of us have taken 
1338         // dependency by using private reflection on them for getting system resource strings 
1339         [ResourceExposure(ResourceScope.None)]
1340         internal static String GetRuntimeResourceString(String key) {
1341             return GetResourceString(key);
1342         }
1343
1344         [ResourceExposure(ResourceScope.None)]
1345         internal static String GetRuntimeResourceString(String key, params Object[] values) {
1346             return GetResourceString(key,values);
1347         }
1348
1349         public static bool Is64BitProcess {
1350             get {
1351                 #if WIN32
1352                     return false;
1353                 #else
1354                     return true;
1355                 #endif
1356             }
1357         }
1358
1359 #if !FEATURE_PAL
1360         public static bool Is64BitOperatingSystem {
1361             [System.Security.SecuritySafeCritical]
1362             get {
1363                 #if WIN32                    
1364                     bool isWow64; // WinXP SP2+ and Win2k3 SP1+
1365                     return Win32Native.DoesWin32MethodExist(Win32Native.KERNEL32, "IsWow64Process")
1366                         && Win32Native.IsWow64Process(Win32Native.GetCurrentProcess(), out isWow64)
1367                         && isWow64;
1368                 #else
1369                     // 64-bit programs run only on 64-bit
1370                     //<
1371                     return true;
1372                 #endif
1373             }
1374         }
1375 #endif
1376
1377         public static extern bool HasShutdownStarted {
1378         [System.Security.SecuritySafeCritical]  // auto-generated
1379         [ResourceExposure(ResourceScope.None)]
1380         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1381             get;
1382         }
1383
1384 #if !FEATURE_CORECLR
1385         // This is the temporary Whidbey stub for compatibility flags
1386         [ResourceExposure(ResourceScope.None)]
1387         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1388         [System.Security.SecurityCritical]
1389         internal static extern bool GetCompatibilityFlag(CompatibilityFlag flag);
1390 #endif //!FEATURE_CORECLR
1391
1392         public static string UserName {
1393             [System.Security.SecuritySafeCritical]  // auto-generated
1394             get {
1395                 new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserName").Demand();
1396
1397                 StringBuilder sb = new StringBuilder(256);
1398                 int size = sb.Capacity;
1399                 if (Win32Native.GetUserName(sb, ref size))
1400                 {
1401                     return sb.ToString();
1402                 }
1403                 return String.Empty;
1404             }
1405         }
1406
1407         // Note that this is a handle to a process window station, but it does
1408         // not need to be closed.  CloseWindowStation would ignore this handle.
1409         // We also do handle equality checking as well.  This isn't a great fit
1410         // for SafeHandle.  We don't gain anything by using SafeHandle here.
1411 #if !FEATURE_PAL && !FEATURE_CORESYSTEM
1412         private static volatile IntPtr processWinStation;        // Doesn't need to be initialized as they're zero-init.
1413         private static volatile bool isUserNonInteractive;   
1414 #endif
1415
1416         public static bool UserInteractive {
1417             [System.Security.SecuritySafeCritical]  // auto-generated
1418             [ResourceExposure(ResourceScope.None)]
1419             [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
1420             get {
1421 #if !FEATURE_PAL && !FEATURE_CORESYSTEM
1422                 IntPtr hwinsta = Win32Native.GetProcessWindowStation();
1423                 if (hwinsta != IntPtr.Zero && processWinStation != hwinsta) {
1424                     int lengthNeeded = 0;
1425                     Win32Native.USEROBJECTFLAGS flags = new Win32Native.USEROBJECTFLAGS();
1426                     if (Win32Native.GetUserObjectInformation(hwinsta, Win32Native.UOI_FLAGS, flags, Marshal.SizeOf(flags),ref lengthNeeded)) {
1427                         if ((flags.dwFlags & Win32Native.WSF_VISIBLE) == 0) {
1428                             isUserNonInteractive = true;
1429                         }
1430                     }
1431                     processWinStation = hwinsta;
1432                 }
1433
1434                 // The logic is reversed to avoid static initialization to true
1435                 return !isUserNonInteractive;
1436 #else
1437                 return true;
1438 #endif
1439             }
1440         }
1441         
1442         [System.Security.SecuritySafeCritical]  // auto-generated
1443         [ResourceExposure(ResourceScope.Machine)]
1444         [ResourceConsumption(ResourceScope.Machine)]
1445         public static string GetFolderPath(SpecialFolder folder) {
1446             if (!Enum.IsDefined(typeof(SpecialFolder), folder))
1447                 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)folder));
1448             Contract.EndContractBlock();
1449
1450             return InternalGetFolderPath(folder, SpecialFolderOption.None);
1451         }
1452
1453         [System.Security.SecuritySafeCritical]  // auto-generated
1454         [ResourceExposure(ResourceScope.Machine)]
1455         [ResourceConsumption(ResourceScope.Machine)]
1456         public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option) {
1457             if (!Enum.IsDefined(typeof(SpecialFolder),folder))
1458                 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)folder));
1459             if (!Enum.IsDefined(typeof(SpecialFolderOption),option))
1460                 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)option));
1461             Contract.EndContractBlock();
1462
1463             return InternalGetFolderPath(folder, option);
1464         }
1465
1466         [System.Security.SecurityCritical]
1467         [ResourceExposure(ResourceScope.Machine)]
1468         [ResourceConsumption(ResourceScope.Machine)]
1469         internal static string UnsafeGetFolderPath(SpecialFolder folder)
1470         {
1471             return InternalGetFolderPath(folder, SpecialFolderOption.None, suppressSecurityChecks: true);
1472         }
1473
1474         [System.Security.SecurityCritical]
1475         [ResourceExposure(ResourceScope.Machine)]
1476         [ResourceConsumption(ResourceScope.Machine)]
1477         private static string InternalGetFolderPath(SpecialFolder folder, SpecialFolderOption option, bool suppressSecurityChecks = false)
1478         {
1479 #if FEATURE_CORESYSTEM
1480             // This is currently customized for Windows Phone since CoreSystem doesn't support
1481             // SHGetFolderPath. The allowed folder values are based on the version of .NET CF WP7 was using.
1482             switch (folder)
1483             {
1484                 case SpecialFolder.System:
1485                     return SystemDirectory;
1486                 case SpecialFolder.ApplicationData:
1487                 case SpecialFolder.Favorites:
1488                 case SpecialFolder.Programs:
1489                 case SpecialFolder.StartMenu:
1490                 case SpecialFolder.Startup:
1491                 case SpecialFolder.Personal:
1492                     throw new PlatformNotSupportedException();
1493                 default:
1494                     throw new PlatformNotSupportedException();
1495             }
1496 #else // FEATURE_CORESYSTEM
1497 #if !FEATURE_CORECLR
1498             if (option == SpecialFolderOption.Create && !suppressSecurityChecks) {
1499                 FileIOPermission createPermission = new FileIOPermission(PermissionState.None);
1500                 createPermission.AllFiles = FileIOPermissionAccess.Write;
1501                 createPermission.Demand();
1502             }
1503 #endif
1504
1505             StringBuilder sb = new StringBuilder(Path.MAX_PATH);
1506             int hresult = Win32Native.SHGetFolderPath(IntPtr.Zero,                    /* hwndOwner: [in] Reserved */
1507                                                       ((int)folder | (int)option),    /* nFolder:   [in] CSIDL    */
1508                                                       IntPtr.Zero,                    /* hToken:    [in] access token */
1509                                                       Win32Native.SHGFP_TYPE_CURRENT, /* dwFlags:   [in] retrieve current path */
1510                                                       sb);                            /* pszPath:   [out]resultant path */
1511             String s;
1512             if (hresult < 0)
1513             {
1514                 switch (hresult)
1515                 {
1516                 default:
1517                     // The previous incarnation threw away all errors. In order to limit
1518                     // breaking changes, we will be permissive about these errors
1519                     // instead of calling ThowExceptionForHR.
1520                     //Runtime.InteropServices.Marshal.ThrowExceptionForHR(hresult);
1521                     break;
1522                 case __HResults.COR_E_PLATFORMNOTSUPPORTED:
1523                     // This one error is the one we do want to throw.
1524                     // <
1525
1526                     throw new PlatformNotSupportedException();
1527                 }
1528
1529                 // SHGetFolderPath does not initialize the output buffer on error
1530                 s = String.Empty;
1531             }
1532             else
1533             {
1534                 s = sb.ToString();
1535             }
1536
1537             if (!suppressSecurityChecks)
1538             {
1539                 // On CoreCLR we can check with the host if we're not trying to use any special options.
1540                 // Otherwise, we need to do a full demand since hosts aren't expecting to handle requests to
1541                 // create special folders.
1542 #if FEATURE_CORECLR
1543                 if (option == SpecialFolderOption.None)
1544                 {
1545                     FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, s);
1546                     state.EnsureState();
1547                 }
1548                 else
1549 #endif // FEATURE_CORECLR
1550                 {
1551                     new FileIOPermission(FileIOPermissionAccess.PathDiscovery, s).Demand();
1552                 }
1553             }
1554             return s;
1555 #endif // FEATURE_CORESYSTEM
1556         }
1557         
1558 #if !FEATURE_PAL
1559         public static string UserDomainName
1560         {
1561                 [System.Security.SecuritySafeCritical]  // auto-generated
1562                 get {
1563                     new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserDomain").Demand();
1564
1565                     byte[] sid = new byte[1024];
1566                     int sidLen = sid.Length;
1567                     StringBuilder domainName = new StringBuilder(1024);
1568                     uint domainNameLen = (uint) domainName.Capacity;
1569                     int peUse;
1570
1571                     byte ret = Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen);
1572                         if (ret == 1) {                        
1573                             string samName = domainName.ToString();
1574                             int index = samName.IndexOf('\\');
1575                             if( index != -1) {
1576                                 return samName.Substring(0, index);
1577                             }
1578                         }
1579                         domainNameLen = (uint) domainName.Capacity;                    
1580                     
1581                     bool success = Win32Native.LookupAccountName(null, UserName, sid, ref sidLen, domainName, ref domainNameLen, out peUse);
1582                     if (!success)  {
1583                         int errorCode = Marshal.GetLastWin32Error();
1584                         throw new InvalidOperationException(Win32Native.GetMessage(errorCode));
1585                     }
1586
1587                     return domainName.ToString();
1588                 }
1589             }
1590 #endif // !FEATURE_PAL
1591         public enum SpecialFolderOption {
1592             None        = 0,
1593             Create      = Win32Native.CSIDL_FLAG_CREATE,
1594             DoNotVerify = Win32Native.CSIDL_FLAG_DONT_VERIFY,
1595         }
1596         
1597 //////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!////////
1598 //////!!!!!! Keep the following locations synchronized            !!!!!!////////
1599 //////!!!!!! 1) ndp\clr\src\BCL\Microsoft\Win32\Win32Native.cs    !!!!!!////////
1600 //////!!!!!! 2) ndp\clr\src\BCL\System\Environment.cs             !!!!!!////////
1601 //////!!!!!! 3) rotor\pal\inc\rotor_pal.h                         !!!!!!////////
1602 //////!!!!!! 4) rotor\pal\corunix\shfolder\shfolder.cpp           !!!!!!////////
1603 //////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!////////
1604         [ComVisible(true)]
1605         public enum SpecialFolder {
1606             //  
1607             //      Represents the file system directory that serves as a common repository for
1608             //       application-specific data for the current, roaming user. 
1609             //     A roaming user works on more than one computer on a network. A roaming user's 
1610             //       profile is kept on a server on the network and is loaded onto a system when the
1611             //       user logs on. 
1612             //  
1613             ApplicationData =  Win32Native.CSIDL_APPDATA,
1614             //  
1615             //      Represents the file system directory that serves as a common repository for application-specific data that
1616             //       is used by all users. 
1617             //  
1618             CommonApplicationData =  Win32Native.CSIDL_COMMON_APPDATA,
1619             //  
1620             //     Represents the file system directory that serves as a common repository for application specific data that
1621             //       is used by the current, non-roaming user. 
1622             //  
1623             LocalApplicationData =  Win32Native.CSIDL_LOCAL_APPDATA,
1624             //  
1625             //     Represents the file system directory that serves as a common repository for Internet
1626             //       cookies. 
1627             //  
1628             Cookies =  Win32Native.CSIDL_COOKIES,
1629             Desktop = Win32Native.CSIDL_DESKTOP,
1630             //  
1631             //     Represents the file system directory that serves as a common repository for the user's
1632             //       favorite items. 
1633             //  
1634             Favorites =  Win32Native.CSIDL_FAVORITES,
1635             //  
1636             //     Represents the file system directory that serves as a common repository for Internet
1637             //       history items. 
1638             //  
1639             History =  Win32Native.CSIDL_HISTORY,
1640             //  
1641             //     Represents the file system directory that serves as a common repository for temporary 
1642             //       Internet files. 
1643             //  
1644             InternetCache =  Win32Native.CSIDL_INTERNET_CACHE,
1645             //  
1646             //      Represents the file system directory that contains
1647             //       the user's program groups. 
1648             //  
1649             Programs =  Win32Native.CSIDL_PROGRAMS,
1650             MyComputer =  Win32Native.CSIDL_DRIVES,
1651             MyMusic =  Win32Native.CSIDL_MYMUSIC,
1652             MyPictures = Win32Native.CSIDL_MYPICTURES,
1653             //      "My Videos" folder
1654             MyVideos = Win32Native.CSIDL_MYVIDEO,
1655             //  
1656             //     Represents the file system directory that contains the user's most recently used
1657             //       documents. 
1658             //  
1659             Recent =  Win32Native.CSIDL_RECENT,
1660             //  
1661             //     Represents the file system directory that contains Send To menu items. 
1662             //  
1663             SendTo =  Win32Native.CSIDL_SENDTO,
1664             //  
1665             //     Represents the file system directory that contains the Start menu items. 
1666             //  
1667             StartMenu =  Win32Native.CSIDL_STARTMENU,
1668             //  
1669             //     Represents the file system directory that corresponds to the user's Startup program group. The system
1670             //       starts these programs whenever any user logs on to Windows NT, or
1671             //       starts Windows 95 or Windows 98. 
1672             //  
1673             Startup =  Win32Native.CSIDL_STARTUP,
1674             //  
1675             //     System directory.
1676             //  
1677             System =  Win32Native.CSIDL_SYSTEM,
1678             //  
1679             //     Represents the file system directory that serves as a common repository for document
1680             //       templates. 
1681             //  
1682             Templates =  Win32Native.CSIDL_TEMPLATES,
1683             //  
1684             //     Represents the file system directory used to physically store file objects on the desktop.
1685             //       This should not be confused with the desktop folder itself, which is
1686             //       a virtual folder. 
1687             //  
1688             DesktopDirectory =  Win32Native.CSIDL_DESKTOPDIRECTORY,
1689             //  
1690             //     Represents the file system directory that serves as a common repository for documents. 
1691             //  
1692             Personal =  Win32Native.CSIDL_PERSONAL, 
1693             //          
1694             // "MyDocuments" is a better name than "Personal"
1695             //
1696             MyDocuments = Win32Native.CSIDL_PERSONAL,                         
1697             //  
1698             //     Represents the program files folder. 
1699             //  
1700             ProgramFiles =  Win32Native.CSIDL_PROGRAM_FILES,
1701             //  
1702             //     Represents the folder for components that are shared across applications. 
1703             //  
1704             CommonProgramFiles =  Win32Native.CSIDL_PROGRAM_FILES_COMMON,            
1705 #if !FEATURE_CORECLR
1706             //
1707             //      <user name>\Start Menu\Programs\Administrative Tools
1708             //
1709             AdminTools             = Win32Native.CSIDL_ADMINTOOLS,
1710             //
1711             //      USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
1712             //
1713             CDBurning              = Win32Native.CSIDL_CDBURN_AREA,
1714             //
1715             //      All Users\Start Menu\Programs\Administrative Tools
1716             //
1717             CommonAdminTools       = Win32Native.CSIDL_COMMON_ADMINTOOLS,
1718             //
1719             //      All Users\Documents
1720             //
1721             CommonDocuments        = Win32Native.CSIDL_COMMON_DOCUMENTS,
1722             //
1723             //      All Users\My Music
1724             //
1725             CommonMusic            = Win32Native.CSIDL_COMMON_MUSIC,
1726             //
1727             //      Links to All Users OEM specific apps
1728             //
1729             CommonOemLinks         = Win32Native.CSIDL_COMMON_OEM_LINKS,
1730             //
1731             //      All Users\My Pictures
1732             //
1733             CommonPictures         = Win32Native.CSIDL_COMMON_PICTURES,
1734             //
1735             //      All Users\Start Menu
1736             //
1737             CommonStartMenu        = Win32Native.CSIDL_COMMON_STARTMENU,
1738             //
1739             //      All Users\Start Menu\Programs
1740             //
1741             CommonPrograms         = Win32Native.CSIDL_COMMON_PROGRAMS,
1742             //
1743             //     All Users\Startup
1744             //
1745             CommonStartup          = Win32Native.CSIDL_COMMON_STARTUP,
1746             //
1747             //      All Users\Desktop
1748             //
1749             CommonDesktopDirectory = Win32Native.CSIDL_COMMON_DESKTOPDIRECTORY,
1750             //
1751             //      All Users\Templates
1752             //
1753             CommonTemplates        = Win32Native.CSIDL_COMMON_TEMPLATES,
1754             //
1755             //      All Users\My Video
1756             //
1757             CommonVideos           = Win32Native.CSIDL_COMMON_VIDEO,
1758             //
1759             //      windows\fonts
1760             //
1761             Fonts                  = Win32Native.CSIDL_FONTS,
1762             //
1763             //      %APPDATA%\Microsoft\Windows\Network Shortcuts
1764             //
1765             NetworkShortcuts       = Win32Native.CSIDL_NETHOOD,
1766             //
1767             //      %APPDATA%\Microsoft\Windows\Printer Shortcuts
1768             //
1769             PrinterShortcuts       = Win32Native.CSIDL_PRINTHOOD,
1770             //
1771             //      USERPROFILE
1772             //
1773             UserProfile            = Win32Native.CSIDL_PROFILE,
1774             //
1775             //      x86 Program Files\Common on RISC
1776             //
1777             CommonProgramFilesX86  = Win32Native.CSIDL_PROGRAM_FILES_COMMONX86,
1778             //
1779             //      x86 C:\Program Files on RISC
1780             //
1781             ProgramFilesX86        = Win32Native.CSIDL_PROGRAM_FILESX86,
1782             //
1783             //      Resource Directory
1784             //
1785             Resources              = Win32Native.CSIDL_RESOURCES,
1786             //
1787             //      Localized Resource Directory
1788             //
1789             LocalizedResources     = Win32Native.CSIDL_RESOURCES_LOCALIZED,
1790             //
1791             //      %windir%\System32 or %windir%\syswow64
1792             //
1793             SystemX86               = Win32Native.CSIDL_SYSTEMX86,
1794             //
1795             //      GetWindowsDirectory()
1796             //
1797             Windows                = Win32Native.CSIDL_WINDOWS,
1798 #endif // !FEATURE_CORECLR
1799         }
1800
1801         public static int CurrentManagedThreadId
1802         {
1803             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
1804             get
1805             {
1806                 return Thread.CurrentThread.ManagedThreadId;
1807             }
1808         }
1809
1810     }
1811 }