3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
11 ** Purpose: Provides some basic access to some environment
15 ============================================================*/
18 using System.Security;
19 using System.Resources;
20 using System.Globalization;
21 using System.Collections;
22 using System.Security.Permissions;
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;
37 public enum EnvironmentVariableTarget {
39 #if FEATURE_WIN32_REGISTRY
47 public static class Environment {
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;
59 internal sealed class ResourceHelper
61 internal ResourceHelper(String name) {
65 private String m_name;
66 private ResourceManager SystemResMgr;
68 // To avoid infinite loops when calling GetResourceString. See comments
69 // in GetResourceString for this field.
70 private Stack currentlyLoading;
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;
77 // Is this thread currently doing infinite resource lookups?
78 private int infinitelyRecursingCount;
80 // Data representing one individual resource lookup on a thread.
81 internal class GetResourceStringUserData
83 public ResourceHelper m_resourceHelper;
85 public CultureInfo m_culture;
86 public String m_retVal;
87 public bool m_lockWasTaken;
89 public GetResourceStringUserData(ResourceHelper resourceHelper, String key, CultureInfo culture)
91 m_resourceHelper = resourceHelper;
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]";
103 return GetResourceString(key, null);
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]";
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.
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.
133 GetResourceStringUserData userData = new GetResourceStringUserData(this, key, culture);
135 RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(GetResourceStringCode);
136 RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(GetResourceStringBackoutCode);
138 RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData);
139 return userData.m_retVal;
143 [System.Security.SecurityCritical] // auto-generated
145 [System.Security.SecuritySafeCritical]
147 private void GetResourceStringCode(Object userDataIn)
149 GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn;
150 ResourceHelper rh = userData.m_resourceHelper;
151 String key = userData.m_key;
152 CultureInfo culture = userData.m_culture;
154 Monitor.Enter(rh, ref userData.m_lockWasTaken);
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.
162 if (rh.infinitelyRecursingCount > 0) {
163 userData.m_retVal = "[Resource lookup failed - infinite recursion or critical failure detected.]";
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.
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);
180 if (rh.currentlyLoading == null)
181 rh.currentlyLoading = new Stack(4);
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.
188 if (!rh.resourceManagerInited)
190 // process-critical code here. No ThreadAbortExceptions
191 // can be thrown here. Other exceptions percolate as normal.
192 RuntimeHelpers.PrepareConstrainedRegions();
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;
205 rh.currentlyLoading.Push(key);
207 if (rh.SystemResMgr == null) {
208 rh.SystemResMgr = new ResourceManager(m_name, typeof(Object).Assembly);
210 String s = rh.SystemResMgr.GetString(key, null);
211 rh.currentlyLoading.Pop();
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+"\"");
215 userData.m_retVal = s;
219 [System.Security.SecurityCritical] // auto-generated
222 private void GetResourceStringBackoutCode(Object userDataIn, bool exceptionThrown)
224 GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn;
225 ResourceHelper rh = userData.m_resourceHelper;
229 if (userData.m_lockWasTaken)
231 // Backout code - throw away potentially corrupt state
232 rh.SystemResMgr = null;
233 rh.currentlyLoading = null;
236 // Release the lock, if we took it.
237 if (userData.m_lockWasTaken)
245 private static volatile ResourceHelper m_resHelper; // Doesn't need to be initialized as they're zero-init.
247 private const int MaxMachineNameLength = 256;
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)]
254 if (s_InternalSyncObject == null) {
255 Object o = new Object();
256 Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
258 return s_InternalSyncObject;
263 private static volatile OperatingSystem m_os; // Cached OperatingSystem value
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.
270 ==============================================================================*/
271 public static extern int TickCount {
272 [System.Security.SecuritySafeCritical] // auto-generated
273 [ResourceExposure(ResourceScope.None)]
274 [MethodImplAttribute(MethodImplOptions.InternalCall)]
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);
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) {
296 public static extern int ExitCode {
297 [System.Security.SecuritySafeCritical] // auto-generated
298 [ResourceExposure(ResourceScope.None)]
299 [MethodImplAttribute(MethodImplOptions.InternalCall)]
302 [System.Security.SecuritySafeCritical] // auto-generated
303 [ResourceExposure(ResourceScope.None)]
304 [MethodImplAttribute(MethodImplOptions.InternalCall)]
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);
316 [System.Security.SecurityCritical]
317 [ResourceExposure(ResourceScope.Process)]
318 [MethodImplAttribute(MethodImplOptions.InternalCall)]
319 internal static extern void FailFast(String message, uint exitCode);
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.
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).
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);
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);
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();
354 internal static bool IsCLRHosted {
355 [SecuritySafeCritical]
356 get { return GetIsCLRHosted(); }
359 public static String CommandLine {
360 [System.Security.SecuritySafeCritical] // auto-generated
362 new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand();
364 String commandLine = null;
365 GetCommandLine(JitHelpers.GetStringHandleOnStack(ref commandLine));
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
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.
382 ==============================================================================*/
383 public static String CurrentDirectory
385 [ResourceExposure(ResourceScope.Machine)]
386 [ResourceConsumption(ResourceScope.Machine)]
388 return Directory.GetCurrentDirectory();
392 [System.Security.SecurityCritical] // auto-generated
394 [ResourceExposure(ResourceScope.Machine)]
395 [ResourceConsumption(ResourceScope.Machine)]
397 Directory.SetCurrentDirectory(value);
401 // Returns the system directory (ie, C:\WinNT\System32).
402 public static String SystemDirectory {
404 [System.Security.SecurityCritical]
406 [System.Security.SecuritySafeCritical] // auto-generated
408 [ResourceExposure(ResourceScope.Machine)]
409 [ResourceConsumption(ResourceScope.Machine)]
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();
419 new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
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)]
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();
444 [System.Security.SecuritySafeCritical] // auto-generated
445 public static String ExpandEnvironmentVariables(String name)
448 throw new ArgumentNullException("name");
449 Contract.EndContractBlock();
451 if (name.Length == 0) {
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.
461 int currentSize = 100;
462 StringBuilder blob = new StringBuilder(currentSize); // A somewhat reasonable default size
466 bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands();
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();
473 bool fJustExpanded = false; // to accommodate expansion alg.
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)
485 fJustExpanded = false;
486 continue; // Nothing to expand
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.
492 String envVar = "%" + varArray[i] + "%";
493 size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize);
495 Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
497 // some environment variable might be changed while this function is called
498 while (size > currentSize) {
500 blob.Capacity = currentSize;
502 size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize);
504 Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
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]);
519 new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand();
520 #endif // !FEATURE_CORECLR
523 size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize);
525 Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
527 while (size > currentSize) {
529 blob.Capacity = currentSize;
532 size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize);
534 Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
537 return blob.ToString();
539 #endif // FEATURE_PAL
541 public static String MachineName {
542 [System.Security.SecuritySafeCritical] // auto-generated
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();
556 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
557 [SuppressUnmanagedCodeSecurity]
558 private static extern Int32 GetProcessorCount();
560 public static int ProcessorCount {
561 [System.Security.SecuritySafeCritical] // auto-generated
563 return GetProcessorCount();
567 public static int SystemPageSize {
568 [System.Security.SecuritySafeCritical] // auto-generated
570 (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
571 Win32Native.SYSTEM_INFO info = new Win32Native.SYSTEM_INFO();
572 Win32Native.GetSystemInfo(ref info);
573 return info.dwPageSize;
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.
584 ==============================================================================*/
585 [System.Security.SecuritySafeCritical] // auto-generated
586 public static String[] GetCommandLineArgs() {
587 new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand();
588 return GetCommandLineArgsNative();
591 [System.Security.SecurityCritical] // auto-generated
592 [ResourceExposure(ResourceScope.None)]
593 [MethodImplAttribute(MethodImplOptions.InternalCall)]
594 private static extern String[] GetCommandLineArgsNative();
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
606 /*============================GetEnvironmentVariable============================
611 ==============================================================================*/
612 [System.Security.SecuritySafeCritical] // auto-generated
613 [ResourceExposure(ResourceScope.Machine)]
614 [ResourceConsumption(ResourceScope.Machine)]
615 public static String GetEnvironmentVariable(String variable)
617 if (variable == null)
618 throw new ArgumentNullException("variable");
619 Contract.EndContractBlock();
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.
628 (new EnvironmentPermission(EnvironmentPermissionAccess.Read, variable)).Demand();
629 #endif //!FEATURE_CORECLR
631 StringBuilder blob = StringBuilderCache.Acquire(128); // A somewhat reasonable default size
632 int requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity);
634 if (requiredSize == 0) { // GetEnvironmentVariable failed
635 if (Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND) {
636 StringBuilderCache.Release(blob);
641 while (requiredSize > blob.Capacity) { // need to retry since the environment variable might be changed
642 blob.Capacity = requiredSize;
644 requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity);
646 return StringBuilderCache.GetStringAndRelease(blob);
650 [System.Security.SecuritySafeCritical] // auto-generated
651 [ResourceExposure(ResourceScope.Machine)]
652 [ResourceConsumption(ResourceScope.Machine)]
653 public static string GetEnvironmentVariable( string variable, EnvironmentVariableTarget target)
655 if (variable == null)
657 throw new ArgumentNullException("variable");
659 Contract.EndContractBlock();
661 if (target == EnvironmentVariableTarget.Process)
663 return GetEnvironmentVariable(variable);
666 #if FEATURE_WIN32_REGISTRY
667 (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
669 if( target == EnvironmentVariableTarget.Machine) {
670 using (RegistryKey environmentKey =
671 Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) {
673 Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!");
674 if (environmentKey == null) {
678 string value = environmentKey.GetValue(variable) as string;
682 else if( target == EnvironmentVariableTarget.User) {
683 using (RegistryKey environmentKey =
684 Registry.CurrentUser.OpenSubKey("Environment", false)) {
686 Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!");
687 if (environmentKey == null) {
691 string value = environmentKey.GetValue(variable) as string;
696 #endif // FEATURE_WIN32_REGISTRY
698 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
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.
708 ==============================================================================*/
709 [System.Security.SecurityCritical] // auto-generated
710 [ResourceExposure(ResourceScope.Machine)]
711 private unsafe static char[] GetEnvironmentCharArray()
715 // Make sure pStrings is not leaked with async exceptions
716 RuntimeHelpers.PrepareConstrainedRegions();
720 char * pStrings = null;
724 pStrings = Win32Native.GetEnvironmentStrings();
725 if (pStrings == null) {
726 throw new OutOfMemoryException();
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).
734 // Search for terminating \0\0 (two unicode \0's).
736 while (!(*p == '\0' && *(p + 1) == '\0'))
739 int len = (int)(p - pStrings + 1);
740 block = new char[len];
742 fixed (char* pBlock = block)
743 String.wstrcpy(pBlock, pStrings, len);
747 if (pStrings != null)
748 Win32Native.FreeEnvironmentStrings(pStrings);
755 [System.Security.SecuritySafeCritical] // auto-generated
756 [ResourceExposure(ResourceScope.Machine)]
757 [ResourceConsumption(ResourceScope.Machine)]
758 public static IDictionary GetEnvironmentVariables()
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);
767 bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands();
768 StringBuilder vars = isFullTrust ? null : new StringBuilder();
772 char[] block = GetEnvironmentCharArray();
774 Hashtable table = new Hashtable(20);
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.
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.
790 for(int i=0; i<block.Length; i++) {
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') {
799 if(block[i] == '\0') {
803 // Skip over environment variables starting with '='
810 String key = new String(block, startKey, i-startKey);
811 i++; // skip over '='
814 // Read to end of this entry
818 String value = new String(block, startValue, i-startValue);
819 // skip over 0 handled by for loop's i++
837 new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand();
843 internal static IDictionary GetRegistryKeyNameValuePairs(RegistryKey registryKey) {
844 Hashtable table = new Hashtable(20);
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);
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();
864 #if FEATURE_WIN32_REGISTRY
865 (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
867 if( target == EnvironmentVariableTarget.Machine) {
868 using (RegistryKey environmentKey =
869 Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) {
871 return GetRegistryKeyNameValuePairs(environmentKey);
874 else if( target == EnvironmentVariableTarget.User) {
875 using (RegistryKey environmentKey =
876 Registry.CurrentUser.OpenSubKey("Environment", false)) {
877 return GetRegistryKeyNameValuePairs(environmentKey);
881 #endif // FEATURE_WIN32_REGISTRY
883 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
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);
895 new EnvironmentPermission(PermissionState.Unrestricted).Demand();
897 // explicitly null out value if is the empty string.
898 if (String.IsNullOrEmpty(value) || value[0] == '\0') {
902 if( value.Length >= MaxEnvVariableValueLength) {
903 throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));
907 if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
908 // Environment variable accessors are not approved modern API.
909 // so we throw PlatformNotSupportedException.
910 throw new PlatformNotSupportedException();
913 if(!Win32Native.SetEnvironmentVariable(variable, value)) {
914 int errorCode = Marshal.GetLastWin32Error();
916 // Allow user to try to clear a environment variable
917 if( errorCode == Win32Native.ERROR_ENVVAR_NOT_FOUND) {
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"));
927 throw new ArgumentException(Win32Native.GetMessage(errorCode));
931 private static void CheckEnvironmentVariableName(string variable) {
932 if (variable == null) {
933 throw new ArgumentNullException("variable");
936 if( variable.Length == 0) {
937 throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "variable");
940 if( variable[0] == '\0') {
941 throw new ArgumentException(Environment.GetResourceString("Argument_StringFirstCharIsZero"), "variable");
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"));
951 if( variable.IndexOf('=') != -1) {
952 throw new ArgumentException(Environment.GetResourceString("Argument_IllegalEnvVarName"));
954 Contract.EndContractBlock();
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);
967 CheckEnvironmentVariableName(variable);
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"));
975 new EnvironmentPermission(PermissionState.Unrestricted).Demand();
976 // explicitly null out value if is the empty string.
977 if (String.IsNullOrEmpty(value) || value[0] == '\0') {
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)) {
985 Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!");
986 if (environmentKey != null) {
988 environmentKey.DeleteValue(variable, false);
990 environmentKey.SetValue(variable, value);
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"));
1000 using (RegistryKey environmentKey =
1001 Registry.CurrentUser.OpenSubKey("Environment", true)) {
1002 Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!");
1003 if (environmentKey != null) {
1005 environmentKey.DeleteValue(variable, false);
1007 environmentKey.SetValue(variable, value);
1013 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
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);
1018 if (r == IntPtr.Zero) BCLDebug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error());
1020 #else // FEATURE_WIN32_REGISTRY
1021 throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
1027 /*===============================GetLogicalDrives===============================
1028 **Action: Retrieves the names of the logical drives on this machine in the form "C:\".
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();
1037 int drives = Win32Native.GetLogicalDrives();
1039 __Error.WinIOError();
1040 uint d = (uint)drives;
1043 if (((int)d & 1) != 0) count++;
1046 String[] result = new String[count];
1047 char[] root = new char[] {'A', ':', '\\'};
1051 if (((int)d & 1) != 0) {
1052 result[count++] = new String(root);
1060 /*===================================NewLine====================================
1061 **Action: A property which returns the appropriate newline string for the given
1063 **Returns: \r\n on Win32.
1066 ==============================================================================*/
1067 public static String NewLine {
1069 Contract.Ensures(Contract.Result<String>() != null);
1075 /*===================================Version====================================
1076 **Action: Returns the COM+ version struct, describing the build number.
1080 ==============================================================================*/
1081 public static Version Version {
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.
1088 return new Version(4,0,30319,42000);
1093 /*==================================WorkingSet==================================
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();
1104 public static long WorkingSet {
1105 [System.Security.SecuritySafeCritical] // auto-generated
1107 new EnvironmentPermission(PermissionState.Unrestricted).Demand();
1108 return GetWorkingSet();
1113 /*==================================OSVersion===================================
1118 ==============================================================================*/
1119 public static OperatingSystem OSVersion {
1120 [System.Security.SecuritySafeCritical] // auto-generated
1122 Contract.Ensures(Contract.Result<OperatingSystem>() != null);
1124 if (m_os==null) { // We avoid the lock since we don't care if two threads will set this at the same time.
1126 Microsoft.Win32.Win32Native.OSVERSIONINFO osvi = new Microsoft.Win32.Win32Native.OSVERSIONINFO();
1127 if (!GetVersion(osvi)) {
1128 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion"));
1131 Microsoft.Win32.Win32Native.OSVERSIONINFOEX osviEx = new Microsoft.Win32.Win32Native.OSVERSIONINFOEX();
1132 if (!GetVersionEx(osviEx))
1133 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion"));
1135 PlatformID id = PlatformID.Win32NT;
1137 #if FEATURE_LEGACYNETCF
1138 // return platform as WinCE, to ensure apps earlier than WP8 works as expected.
1139 if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
1141 id = PlatformID.WinCE;
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);
1148 Contract.Assert(m_os != null, "m_os != null");
1153 #if FEATURE_CORESYSTEM
1155 internal static bool IsWindows8OrAbove {
1161 #if FEATURE_COMINTEROP
1162 internal static bool IsWinRTSupported {
1167 #endif // FEATURE_COMINTEROP
1169 #else // FEATURE_CORESYSTEM
1171 private static volatile bool s_IsWindows8OrAbove;
1172 private static volatile bool s_CheckedOSWin8OrAbove;
1174 // Windows 8 version is 6.2
1175 internal static bool IsWindows8OrAbove {
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;
1183 return s_IsWindows8OrAbove;
1187 #if FEATURE_COMINTEROP
1188 private static volatile bool s_WinRTSupported;
1189 private static volatile bool s_CheckedWinRT;
1191 // Does the current version of Windows have Windows Runtime suppport?
1192 internal static bool IsWinRTSupported {
1193 [SecuritySafeCritical]
1195 if (!s_CheckedWinRT) {
1196 s_WinRTSupported = WinRTSupported();
1197 s_CheckedWinRT = true;
1200 return s_WinRTSupported;
1205 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
1206 [SuppressUnmanagedCodeSecurity]
1207 [return: MarshalAs(UnmanagedType.Bool)]
1208 private static extern bool WinRTSupported();
1209 #endif // FEATURE_COMINTEROP
1211 #endif // FEATURE_CORESYSTEM
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);
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);
1224 /*==================================StackTrace==================================
1229 ==============================================================================*/
1230 public static String StackTrace {
1231 [System.Security.SecuritySafeCritical] // auto-generated
1233 Contract.Ensures(Contract.Result<String>() != null);
1235 new EnvironmentPermission(PermissionState.Unrestricted).Demand();
1236 return GetStackTrace(null, true);
1241 [System.Security.SecurityCritical] // auto-generated
1243 internal static String GetStackTrace(Exception e, bool needFileInfo)
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. --
1251 st = new StackTrace(needFileInfo);
1253 st = new StackTrace(e, needFileInfo);
1255 // Do no include a trailing newline for backwards compatibility
1256 return st.ToString( System.Diagnostics.StackTrace.TraceFormat.Normal );
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.
1265 bool tookLock = false;
1266 RuntimeHelpers.PrepareConstrainedRegions();
1269 Monitor.Enter(Environment.InternalSyncObject, ref tookLock);
1271 if (m_resHelper == null) {
1272 ResourceHelper rh = new ResourceHelper("mscorlib");
1274 System.Threading.Thread.MemoryBarrier();
1280 Monitor.Exit(Environment.InternalSyncObject);
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);
1291 // Looks up the resource string value for key.
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
1297 [System.Security.SecurityCritical] // auto-generated
1299 internal static String GetResourceStringLocal(String key) {
1300 if (m_resHelper == null)
1301 InitResourceHelper();
1303 return m_resHelper.GetResourceString(key);
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.
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.
1319 [System.Security.SecuritySafeCritical] // auto-generated
1320 [ResourceExposure(ResourceScope.None)]
1321 internal static String GetResourceString(String key) {
1323 return GetResourceStringLocal(key);
1325 return GetResourceFromDefault(key);
1326 #endif //FEATURE_CORECLR
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);
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);
1344 [ResourceExposure(ResourceScope.None)]
1345 internal static String GetRuntimeResourceString(String key, params Object[] values) {
1346 return GetResourceString(key,values);
1349 public static bool Is64BitProcess {
1360 public static bool Is64BitOperatingSystem {
1361 [System.Security.SecuritySafeCritical]
1364 bool isWow64; // WinXP SP2+ and Win2k3 SP1+
1365 return Win32Native.DoesWin32MethodExist(Win32Native.KERNEL32, "IsWow64Process")
1366 && Win32Native.IsWow64Process(Win32Native.GetCurrentProcess(), out isWow64)
1369 // 64-bit programs run only on 64-bit
1377 public static extern bool HasShutdownStarted {
1378 [System.Security.SecuritySafeCritical] // auto-generated
1379 [ResourceExposure(ResourceScope.None)]
1380 [MethodImplAttribute(MethodImplOptions.InternalCall)]
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
1392 public static string UserName {
1393 [System.Security.SecuritySafeCritical] // auto-generated
1395 new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserName").Demand();
1397 StringBuilder sb = new StringBuilder(256);
1398 int size = sb.Capacity;
1399 if (Win32Native.GetUserName(sb, ref size))
1401 return sb.ToString();
1403 return String.Empty;
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;
1416 public static bool UserInteractive {
1417 [System.Security.SecuritySafeCritical] // auto-generated
1418 [ResourceExposure(ResourceScope.None)]
1419 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
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;
1431 processWinStation = hwinsta;
1434 // The logic is reversed to avoid static initialization to true
1435 return !isUserNonInteractive;
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();
1450 return InternalGetFolderPath(folder, SpecialFolderOption.None);
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();
1463 return InternalGetFolderPath(folder, option);
1466 [System.Security.SecurityCritical]
1467 [ResourceExposure(ResourceScope.Machine)]
1468 [ResourceConsumption(ResourceScope.Machine)]
1469 internal static string UnsafeGetFolderPath(SpecialFolder folder)
1471 return InternalGetFolderPath(folder, SpecialFolderOption.None, suppressSecurityChecks: true);
1474 [System.Security.SecurityCritical]
1475 [ResourceExposure(ResourceScope.Machine)]
1476 [ResourceConsumption(ResourceScope.Machine)]
1477 private static string InternalGetFolderPath(SpecialFolder folder, SpecialFolderOption option, bool suppressSecurityChecks = false)
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.
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();
1494 throw new PlatformNotSupportedException();
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();
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 */
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);
1522 case __HResults.COR_E_PLATFORMNOTSUPPORTED:
1523 // This one error is the one we do want to throw.
1526 throw new PlatformNotSupportedException();
1529 // SHGetFolderPath does not initialize the output buffer on error
1537 if (!suppressSecurityChecks)
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.
1543 if (option == SpecialFolderOption.None)
1545 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, s);
1546 state.EnsureState();
1549 #endif // FEATURE_CORECLR
1551 new FileIOPermission(FileIOPermissionAccess.PathDiscovery, s).Demand();
1555 #endif // FEATURE_CORESYSTEM
1559 public static string UserDomainName
1561 [System.Security.SecuritySafeCritical] // auto-generated
1563 new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserDomain").Demand();
1565 byte[] sid = new byte[1024];
1566 int sidLen = sid.Length;
1567 StringBuilder domainName = new StringBuilder(1024);
1568 uint domainNameLen = (uint) domainName.Capacity;
1571 byte ret = Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen);
1573 string samName = domainName.ToString();
1574 int index = samName.IndexOf('\\');
1576 return samName.Substring(0, index);
1579 domainNameLen = (uint) domainName.Capacity;
1581 bool success = Win32Native.LookupAccountName(null, UserName, sid, ref sidLen, domainName, ref domainNameLen, out peUse);
1583 int errorCode = Marshal.GetLastWin32Error();
1584 throw new InvalidOperationException(Win32Native.GetMessage(errorCode));
1587 return domainName.ToString();
1590 #endif // !FEATURE_PAL
1591 public enum SpecialFolderOption {
1593 Create = Win32Native.CSIDL_FLAG_CREATE,
1594 DoNotVerify = Win32Native.CSIDL_FLAG_DONT_VERIFY,
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 //////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!////////
1605 public enum SpecialFolder {
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
1613 ApplicationData = Win32Native.CSIDL_APPDATA,
1615 // Represents the file system directory that serves as a common repository for application-specific data that
1616 // is used by all users.
1618 CommonApplicationData = Win32Native.CSIDL_COMMON_APPDATA,
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.
1623 LocalApplicationData = Win32Native.CSIDL_LOCAL_APPDATA,
1625 // Represents the file system directory that serves as a common repository for Internet
1628 Cookies = Win32Native.CSIDL_COOKIES,
1629 Desktop = Win32Native.CSIDL_DESKTOP,
1631 // Represents the file system directory that serves as a common repository for the user's
1634 Favorites = Win32Native.CSIDL_FAVORITES,
1636 // Represents the file system directory that serves as a common repository for Internet
1639 History = Win32Native.CSIDL_HISTORY,
1641 // Represents the file system directory that serves as a common repository for temporary
1644 InternetCache = Win32Native.CSIDL_INTERNET_CACHE,
1646 // Represents the file system directory that contains
1647 // the user's program groups.
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,
1656 // Represents the file system directory that contains the user's most recently used
1659 Recent = Win32Native.CSIDL_RECENT,
1661 // Represents the file system directory that contains Send To menu items.
1663 SendTo = Win32Native.CSIDL_SENDTO,
1665 // Represents the file system directory that contains the Start menu items.
1667 StartMenu = Win32Native.CSIDL_STARTMENU,
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.
1673 Startup = Win32Native.CSIDL_STARTUP,
1675 // System directory.
1677 System = Win32Native.CSIDL_SYSTEM,
1679 // Represents the file system directory that serves as a common repository for document
1682 Templates = Win32Native.CSIDL_TEMPLATES,
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.
1688 DesktopDirectory = Win32Native.CSIDL_DESKTOPDIRECTORY,
1690 // Represents the file system directory that serves as a common repository for documents.
1692 Personal = Win32Native.CSIDL_PERSONAL,
1694 // "MyDocuments" is a better name than "Personal"
1696 MyDocuments = Win32Native.CSIDL_PERSONAL,
1698 // Represents the program files folder.
1700 ProgramFiles = Win32Native.CSIDL_PROGRAM_FILES,
1702 // Represents the folder for components that are shared across applications.
1704 CommonProgramFiles = Win32Native.CSIDL_PROGRAM_FILES_COMMON,
1705 #if !FEATURE_CORECLR
1707 // <user name>\Start Menu\Programs\Administrative Tools
1709 AdminTools = Win32Native.CSIDL_ADMINTOOLS,
1711 // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
1713 CDBurning = Win32Native.CSIDL_CDBURN_AREA,
1715 // All Users\Start Menu\Programs\Administrative Tools
1717 CommonAdminTools = Win32Native.CSIDL_COMMON_ADMINTOOLS,
1719 // All Users\Documents
1721 CommonDocuments = Win32Native.CSIDL_COMMON_DOCUMENTS,
1723 // All Users\My Music
1725 CommonMusic = Win32Native.CSIDL_COMMON_MUSIC,
1727 // Links to All Users OEM specific apps
1729 CommonOemLinks = Win32Native.CSIDL_COMMON_OEM_LINKS,
1731 // All Users\My Pictures
1733 CommonPictures = Win32Native.CSIDL_COMMON_PICTURES,
1735 // All Users\Start Menu
1737 CommonStartMenu = Win32Native.CSIDL_COMMON_STARTMENU,
1739 // All Users\Start Menu\Programs
1741 CommonPrograms = Win32Native.CSIDL_COMMON_PROGRAMS,
1743 // All Users\Startup
1745 CommonStartup = Win32Native.CSIDL_COMMON_STARTUP,
1747 // All Users\Desktop
1749 CommonDesktopDirectory = Win32Native.CSIDL_COMMON_DESKTOPDIRECTORY,
1751 // All Users\Templates
1753 CommonTemplates = Win32Native.CSIDL_COMMON_TEMPLATES,
1755 // All Users\My Video
1757 CommonVideos = Win32Native.CSIDL_COMMON_VIDEO,
1761 Fonts = Win32Native.CSIDL_FONTS,
1763 // %APPDATA%\Microsoft\Windows\Network Shortcuts
1765 NetworkShortcuts = Win32Native.CSIDL_NETHOOD,
1767 // %APPDATA%\Microsoft\Windows\Printer Shortcuts
1769 PrinterShortcuts = Win32Native.CSIDL_PRINTHOOD,
1773 UserProfile = Win32Native.CSIDL_PROFILE,
1775 // x86 Program Files\Common on RISC
1777 CommonProgramFilesX86 = Win32Native.CSIDL_PROGRAM_FILES_COMMONX86,
1779 // x86 C:\Program Files on RISC
1781 ProgramFilesX86 = Win32Native.CSIDL_PROGRAM_FILESX86,
1783 // Resource Directory
1785 Resources = Win32Native.CSIDL_RESOURCES,
1787 // Localized Resource Directory
1789 LocalizedResources = Win32Native.CSIDL_RESOURCES_LOCALIZED,
1791 // %windir%\System32 or %windir%\syswow64
1793 SystemX86 = Win32Native.CSIDL_SYSTEMX86,
1795 // GetWindowsDirectory()
1797 Windows = Win32Native.CSIDL_WINDOWS,
1798 #endif // !FEATURE_CORECLR
1801 public static int CurrentManagedThreadId
1803 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
1806 return Thread.CurrentThread.ManagedThreadId;