// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: Environment ** ** ** Purpose: Provides some basic access to some environment ** functionality. ** ** ============================================================*/ namespace System { using System.IO; using System.Security; using System.Resources; using System.Globalization; using System.Collections; using System.Security.Permissions; using System.Text; using System.Configuration.Assemblies; using System.Runtime.InteropServices; using System.Reflection; using System.Diagnostics; using Microsoft.Win32; using System.Runtime.CompilerServices; using System.Threading; using System.Runtime.ConstrainedExecution; using System.Runtime.Versioning; using System.Diagnostics.Contracts; #if !FEATURE_PAL [ComVisible(true)] public enum EnvironmentVariableTarget { Process = 0, #if FEATURE_WIN32_REGISTRY User = 1, Machine = 2, #endif } #endif [ComVisible(true)] public static class Environment { // Assume the following constants include the terminating '\0' - use <, not <= const int MaxEnvVariableValueLength = 32767; // maximum length for environment variable name and value // System environment variables are stored in the registry, and have // a size restriction that is separate from both normal environment // variables and registry value name lengths, according to MSDN. // MSDN doesn't detail whether the name is limited to 1024, or whether // that includes the contents of the environment variable. const int MaxSystemEnvVariableLength = 1024; const int MaxUserEnvVariableLength = 255; internal sealed class ResourceHelper { internal ResourceHelper(String name) { m_name = name; } private String m_name; private ResourceManager SystemResMgr; // To avoid infinite loops when calling GetResourceString. See comments // in GetResourceString for this field. private Stack currentlyLoading; // process-wide state (since this is only used in one domain), // used to avoid the TypeInitialization infinite recusion // in GetResourceStringCode internal bool resourceManagerInited = false; // Is this thread currently doing infinite resource lookups? private int infinitelyRecursingCount; // Data representing one individual resource lookup on a thread. internal class GetResourceStringUserData { public ResourceHelper m_resourceHelper; public String m_key; public CultureInfo m_culture; public String m_retVal; public bool m_lockWasTaken; public GetResourceStringUserData(ResourceHelper resourceHelper, String key, CultureInfo culture) { m_resourceHelper = resourceHelper; m_key = key; m_culture = culture; } } [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal String GetResourceString(String key) { if (key == null || key.Length == 0) { Contract.Assert(false, "Environment::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); return "[Resource lookup failed - null or empty resource name]"; } return GetResourceString(key, null); } [System.Security.SecuritySafeCritical] // auto-generated [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal String GetResourceString(String key, CultureInfo culture) { if (key == null || key.Length == 0) { Contract.Assert(false, "Environment::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?"); return "[Resource lookup failed - null or empty resource name]"; } // We have a somewhat common potential for infinite // loops with mscorlib's ResourceManager. If "potentially dangerous" // code throws an exception, we will get into an infinite loop // inside the ResourceManager and this "potentially dangerous" code. // Potentially dangerous code includes the IO package, CultureInfo, // parts of the loader, some parts of Reflection, Security (including // custom user-written permissions that may parse an XML file at // class load time), assembly load event handlers, etc. Essentially, // this is not a bounded set of code, and we need to fix the problem. // Fortunately, this is limited to mscorlib's error lookups and is NOT // a general problem for all user code using the ResourceManager. // The solution is to make sure only one thread at a time can call // GetResourceString. Also, since resource lookups can be // reentrant, if the same thread comes into GetResourceString // twice looking for the exact same resource name before // returning, we're going into an infinite loop and we should // return a bogus string. GetResourceStringUserData userData = new GetResourceStringUserData(this, key, culture); RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(GetResourceStringCode); RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(GetResourceStringBackoutCode); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData); return userData.m_retVal; } #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated #else [System.Security.SecuritySafeCritical] #endif private void GetResourceStringCode(Object userDataIn) { GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn; ResourceHelper rh = userData.m_resourceHelper; String key = userData.m_key; CultureInfo culture = userData.m_culture; Monitor.Enter(rh, ref userData.m_lockWasTaken); // Are we recursively looking up the same resource? Note - our backout code will set // the ResourceHelper's currentlyLoading stack to null if an exception occurs. if (rh.currentlyLoading != null && rh.currentlyLoading.Count > 0 && rh.currentlyLoading.Contains(key)) { // We can start infinitely recursing for one resource lookup, // then during our failure reporting, start infinitely recursing again. // avoid that. if (rh.infinitelyRecursingCount > 0) { userData.m_retVal = "[Resource lookup failed - infinite recursion or critical failure detected.]"; return; } rh.infinitelyRecursingCount++; // This is often a bug in the BCL, security, NLS+ code, // or the loader somewhere. However, this could also // be a setup problem - check whether mscorlib & // clr.dll are both of the same build flavor. Also, user // code in the resource lookup process (like an assembly // resolve event or custom CultureInfo) might potentially cause issues. // Note: our infrastructure for reporting this exception will again cause resource lookup. // This is the most direct way of dealing with that problem. 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; Assert.Fail("[mscorlib recursive resource lookup bug]", message, Assert.COR_E_FAILFAST, System.Diagnostics.StackTrace.TraceFormat.NoResourceLookup); Environment.FailFast(message); } if (rh.currentlyLoading == null) rh.currentlyLoading = new Stack(4); // Call class constructors preemptively, so that we cannot get into an infinite // loop constructing a TypeInitializationException. If this were omitted, // we could get the Infinite recursion assert above by failing type initialization // between the Push and Pop calls below. if (!rh.resourceManagerInited) { // process-critical code here. No ThreadAbortExceptions // can be thrown here. Other exceptions percolate as normal. RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { RuntimeHelpers.RunClassConstructor(typeof(ResourceManager).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(ResourceReader).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(RuntimeResourceSet).TypeHandle); RuntimeHelpers.RunClassConstructor(typeof(BinaryReader).TypeHandle); rh.resourceManagerInited = true; } } rh.currentlyLoading.Push(key); if (rh.SystemResMgr == null) { rh.SystemResMgr = new ResourceManager(m_name, typeof(Object).Assembly); } String s = rh.SystemResMgr.GetString(key, null); rh.currentlyLoading.Pop(); 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+"\""); userData.m_retVal = s; } #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated #endif [PrePrepareMethod] private void GetResourceStringBackoutCode(Object userDataIn, bool exceptionThrown) { GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn; ResourceHelper rh = userData.m_resourceHelper; if (exceptionThrown) { if (userData.m_lockWasTaken) { // Backout code - throw away potentially corrupt state rh.SystemResMgr = null; rh.currentlyLoading = null; } } // Release the lock, if we took it. if (userData.m_lockWasTaken) { Monitor.Exit(rh); } } } private static volatile ResourceHelper m_resHelper; // Doesn't need to be initialized as they're zero-init. private const int MaxMachineNameLength = 256; // Private object for locking instead of locking on a public type for SQL reliability work. private static Object s_InternalSyncObject; private static Object InternalSyncObject { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] get { if (s_InternalSyncObject == null) { Object o = new Object(); Interlocked.CompareExchange(ref s_InternalSyncObject, o, null); } return s_InternalSyncObject; } } private static volatile OperatingSystem m_os; // Cached OperatingSystem value /*==================================TickCount=================================== **Action: Gets the number of ticks since the system was started. **Returns: The number of ticks since the system was started. **Arguments: None **Exceptions: None ==============================================================================*/ public static extern int TickCount { [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] get; } // Terminates this process with the given exit code. [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Process)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] internal static extern void _Exit(int exitCode); [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Process)] [ResourceConsumption(ResourceScope.Process)] #pragma warning disable 618 [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)] #pragma warning restore 618 public static void Exit(int exitCode) { _Exit(exitCode); } public static extern int ExitCode { [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] get; [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] set; } // Note: The CLR's Watson bucketization code looks at the caller of the FCALL method // to assign blame for crashes. Don't mess with this, such as by making it call // another managed helper method, unless you consult with some CLR Watson experts. [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.Process)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void FailFast(String message); [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.Process)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern void FailFast(String message, uint exitCode); // This overload of FailFast will allow you to specify the exception object // whose bucket details *could* be used when undergoing the failfast process. // To be specific: // // 1) When invoked from within a managed EH clause (fault/finally/catch), // if the exception object is preallocated, the runtime will try to find its buckets // and use them. If the exception object is not preallocated, it will use the bucket // details contained in the object (if any). // // 2) When invoked from outside the managed EH clauses (fault/finally/catch), // if the exception object is preallocated, the runtime will use the callsite's // IP for bucketing. If the exception object is not preallocated, it will use the bucket // details contained in the object (if any). [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.Process)] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void FailFast(String message, Exception exception); #if !FEATURE_CORECLR [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods. [ResourceExposure(ResourceScope.None)] [SuppressUnmanagedCodeSecurity] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] internal static extern void TriggerCodeContractFailure(ContractFailureKind failureKind, String message, String condition, String exceptionAsString); [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods. [ResourceExposure(ResourceScope.None)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetIsCLRHosted(); internal static bool IsCLRHosted { [SecuritySafeCritical] get { return GetIsCLRHosted(); } } public static String CommandLine { [System.Security.SecuritySafeCritical] // auto-generated get { new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand(); String commandLine = null; GetCommandLine(JitHelpers.GetStringHandleOnStack(ref commandLine)); return commandLine; } } [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern void GetCommandLine(StringHandleOnStack retString); #endif // !FEATURE_CORECLR /*===============================CurrentDirectory=============================== **Action: Provides a getter and setter for the current directory. The original ** current directory is the one from which the process was started. **Returns: The current directory (from the getter). Void from the setter. **Arguments: The current directory to which to switch to the setter. **Exceptions: ==============================================================================*/ public static String CurrentDirectory { [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] get{ return Directory.GetCurrentDirectory(); } #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated #endif [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] set { Directory.SetCurrentDirectory(value); } } // Returns the system directory (ie, C:\WinNT\System32). public static String SystemDirectory { #if FEATURE_CORECLR [System.Security.SecurityCritical] #else [System.Security.SecuritySafeCritical] // auto-generated #endif [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] get { StringBuilder sb = new StringBuilder(Path.MAX_PATH); int r = Win32Native.GetSystemDirectory(sb, Path.MAX_PATH); Contract.Assert(r < Path.MAX_PATH, "r < Path.MAX_PATH"); if (r==0) __Error.WinIOError(); String path = sb.ToString(); #if !FEATURE_CORECLR // Do security check new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand(); #endif return path; } } #if !FEATURE_PAL // Returns the windows directory (ie, C:\WinNT). // Used by NLS+ custom culures only at the moment. internal static String InternalWindowsDirectory { [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] get { StringBuilder sb = new StringBuilder(Path.MAX_PATH); int r = Win32Native.GetWindowsDirectory(sb, Path.MAX_PATH); Contract.Assert(r < Path.MAX_PATH, "r < Path.MAX_PATH"); if (r==0) __Error.WinIOError(); String path = sb.ToString(); return path; } } [System.Security.SecuritySafeCritical] // auto-generated public static String ExpandEnvironmentVariables(String name) { if (name == null) throw new ArgumentNullException("name"); Contract.EndContractBlock(); if (name.Length == 0) { return name; } if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) { // Environment variable accessors are not approved modern API. // Behave as if no variables are defined in this case. return name; } int currentSize = 100; StringBuilder blob = new StringBuilder(currentSize); // A somewhat reasonable default size int size; #if !FEATURE_CORECLR bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands(); // Do a security check to guarantee we can read each of the // individual environment variables requested here. String[] varArray = name.Split(new char[] {'%'}); StringBuilder vars = isFullTrust ? null : new StringBuilder(); bool fJustExpanded = false; // to accommodate expansion alg. for(int i=1; i currentSize) { currentSize = size; blob.Capacity = currentSize; blob.Length = 0; size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize); if (size == 0) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } if (!isFullTrust) { String temp = blob.ToString(); fJustExpanded = (temp != envVar); if (fJustExpanded) { // We expanded successfully, we need to do String comparison here // since %FOO% can become %FOOD vars.Append(varArray[i]); vars.Append(';'); } } } if (!isFullTrust) new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand(); #endif // !FEATURE_CORECLR blob.Length = 0; size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize); if (size == 0) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); while (size > currentSize) { currentSize = size; blob.Capacity = currentSize; blob.Length = 0; size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize); if (size == 0) Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } return blob.ToString(); } #endif // FEATURE_PAL public static String MachineName { [System.Security.SecuritySafeCritical] // auto-generated get { // In future release of operating systems, you might be able to rename a machine without // rebooting. Therefore, don't cache this machine name. new EnvironmentPermission(EnvironmentPermissionAccess.Read, "COMPUTERNAME").Demand(); StringBuilder buf = new StringBuilder(MaxMachineNameLength); int len = MaxMachineNameLength; if (Win32Native.GetComputerName(buf, ref len) == 0) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ComputerName")); return buf.ToString(); } } [SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] private static extern Int32 GetProcessorCount(); public static int ProcessorCount { [System.Security.SecuritySafeCritical] // auto-generated get { return GetProcessorCount(); } } public static int SystemPageSize { [System.Security.SecuritySafeCritical] // auto-generated get { (new EnvironmentPermission(PermissionState.Unrestricted)).Demand(); Win32Native.SYSTEM_INFO info = new Win32Native.SYSTEM_INFO(); Win32Native.GetSystemInfo(ref info); return info.dwPageSize; } } #if !FEATURE_CORECLR /*==============================GetCommandLineArgs============================== **Action: Gets the command line and splits it appropriately to deal with whitespace, ** quotes, and escape characters. **Returns: A string array containing your command line arguments. **Arguments: None **Exceptions: None. ==============================================================================*/ [System.Security.SecuritySafeCritical] // auto-generated public static String[] GetCommandLineArgs() { new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand(); return GetCommandLineArgsNative(); } [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern String[] GetCommandLineArgsNative(); // We need to keep this Fcall since it is used in AppDomain.cs. // If we call GetEnvironmentVariable from AppDomain.cs, we will use StringBuilder class. // That has side effect to change the ApartmentState of the calling Thread to MTA. // So runtime can't change the ApartmentState of calling thread any more. [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Process)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern String nativeGetEnvironmentVariable(String variable); #endif //!FEATURE_CORECLR /*============================GetEnvironmentVariable============================ **Action: **Returns: **Arguments: **Exceptions: ==============================================================================*/ [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String GetEnvironmentVariable(String variable) { if (variable == null) throw new ArgumentNullException("variable"); Contract.EndContractBlock(); if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) { // Environment variable accessors are not approved modern API. // Behave as if the variable was not found in this case. return null; } #if !FEATURE_CORECLR (new EnvironmentPermission(EnvironmentPermissionAccess.Read, variable)).Demand(); #endif //!FEATURE_CORECLR StringBuilder blob = StringBuilderCache.Acquire(128); // A somewhat reasonable default size int requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity); if (requiredSize == 0) { // GetEnvironmentVariable failed if (Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND) { StringBuilderCache.Release(blob); return null; } } while (requiredSize > blob.Capacity) { // need to retry since the environment variable might be changed blob.Capacity = requiredSize; blob.Length = 0; requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity); } return StringBuilderCache.GetStringAndRelease(blob); } #if !FEATURE_PAL [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static string GetEnvironmentVariable( string variable, EnvironmentVariableTarget target) { if (variable == null) { throw new ArgumentNullException("variable"); } Contract.EndContractBlock(); if (target == EnvironmentVariableTarget.Process) { return GetEnvironmentVariable(variable); } #if FEATURE_WIN32_REGISTRY (new EnvironmentPermission(PermissionState.Unrestricted)).Demand(); if( target == EnvironmentVariableTarget.Machine) { using (RegistryKey environmentKey = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) { Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!"); if (environmentKey == null) { return null; } string value = environmentKey.GetValue(variable) as string; return value; } } else if( target == EnvironmentVariableTarget.User) { using (RegistryKey environmentKey = Registry.CurrentUser.OpenSubKey("Environment", false)) { Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!"); if (environmentKey == null) { return null; } string value = environmentKey.GetValue(variable) as string; return value; } } else #endif // FEATURE_WIN32_REGISTRY { throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target)); } } #endif /*===========================GetEnvironmentVariables============================ **Action: Returns an IDictionary containing all enviroment variables and their values. **Returns: An IDictionary containing all environment variables and their values. **Arguments: None. **Exceptions: None. ==============================================================================*/ [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] private unsafe static char[] GetEnvironmentCharArray() { char[] block = null; // Make sure pStrings is not leaked with async exceptions RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { char * pStrings = null; try { pStrings = Win32Native.GetEnvironmentStrings(); if (pStrings == null) { throw new OutOfMemoryException(); } // Format for GetEnvironmentStrings is: // [=HiddenVar=value\0]* [Variable=value\0]* \0 // See the description of Environment Blocks in MSDN's // CreateProcess page (null-terminated array of null-terminated strings). // Search for terminating \0\0 (two unicode \0's). char * p = pStrings; while (!(*p == '\0' && *(p + 1) == '\0')) p++; int len = (int)(p - pStrings + 1); block = new char[len]; fixed (char* pBlock = block) String.wstrcpy(pBlock, pStrings, len); } finally { if (pStrings != null) Win32Native.FreeEnvironmentStrings(pStrings); } } return block; } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static IDictionary GetEnvironmentVariables() { if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) { // Environment variable accessors are not approved modern API. // Behave as if no environment variables are defined in this case. return new Hashtable(0); } #if !FEATURE_CORECLR bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands(); StringBuilder vars = isFullTrust ? null : new StringBuilder(); bool first = true; #endif char[] block = GetEnvironmentCharArray(); Hashtable table = new Hashtable(20); // Copy strings out, parsing into pairs and inserting into the table. // The first few environment variable entries start with an '='! // The current working directory of every drive (except for those drives // you haven't cd'ed into in your DOS window) are stored in the // environment block (as =C:=pwd) and the program's exit code is // as well (=ExitCode=00000000) Skip all that start with =. // Read docs about Environment Blocks on MSDN's CreateProcess page. // Format for GetEnvironmentStrings is: // (=HiddenVar=value\0 | Variable=value\0)* \0 // See the description of Environment Blocks in MSDN's // CreateProcess page (null-terminated array of null-terminated strings). // Note the =HiddenVar's aren't always at the beginning. for(int i=0; i= MaxEnvVariableValueLength) { throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); } } if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) { // Environment variable accessors are not approved modern API. // so we throw PlatformNotSupportedException. throw new PlatformNotSupportedException(); } if(!Win32Native.SetEnvironmentVariable(variable, value)) { int errorCode = Marshal.GetLastWin32Error(); // Allow user to try to clear a environment variable if( errorCode == Win32Native.ERROR_ENVVAR_NOT_FOUND) { return; } // The error message from Win32 is "The filename or extension is too long", // which is not accurate. if( errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE) { throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); } throw new ArgumentException(Win32Native.GetMessage(errorCode)); } } private static void CheckEnvironmentVariableName(string variable) { if (variable == null) { throw new ArgumentNullException("variable"); } if( variable.Length == 0) { throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "variable"); } if( variable[0] == '\0') { throw new ArgumentException(Environment.GetResourceString("Argument_StringFirstCharIsZero"), "variable"); } // Make sure the environment variable name isn't longer than the // max limit on environment variable values. (MSDN is ambiguous // on whether this check is necessary.) if( variable.Length >= MaxEnvVariableValueLength ) { throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); } if( variable.IndexOf('=') != -1) { throw new ArgumentException(Environment.GetResourceString("Argument_IllegalEnvVarName")); } Contract.EndContractBlock(); } #if !FEATURE_PAL [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) { if( target == EnvironmentVariableTarget.Process) { SetEnvironmentVariable(variable, value); return; } CheckEnvironmentVariableName(variable); // System-wide environment variables stored in the registry are // limited to 1024 chars for the environment variable name. if (variable.Length >= MaxSystemEnvVariableLength) { throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarName")); } new EnvironmentPermission(PermissionState.Unrestricted).Demand(); // explicitly null out value if is the empty string. if (String.IsNullOrEmpty(value) || value[0] == '\0') { value = null; } #if FEATURE_WIN32_REGISTRY if( target == EnvironmentVariableTarget.Machine) { using (RegistryKey environmentKey = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", true)) { Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!"); if (environmentKey != null) { if (value == null) environmentKey.DeleteValue(variable, false); else environmentKey.SetValue(variable, value); } } } else if( target == EnvironmentVariableTarget.User) { // User-wide environment variables stored in the registry are // limited to 255 chars for the environment variable name. if (variable.Length >= MaxUserEnvVariableLength) { throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue")); } using (RegistryKey environmentKey = Registry.CurrentUser.OpenSubKey("Environment", true)) { Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!"); if (environmentKey != null) { if (value == null) environmentKey.DeleteValue(variable, false); else environmentKey.SetValue(variable, value); } } } else { throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target)); } // send a WM_SETTINGCHANGE message to all windows IntPtr r = Win32Native.SendMessageTimeout(new IntPtr(Win32Native.HWND_BROADCAST), Win32Native.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero); if (r == IntPtr.Zero) BCLDebug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error()); #else // FEATURE_WIN32_REGISTRY throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target)); #endif } #endif /*===============================GetLogicalDrives=============================== **Action: Retrieves the names of the logical drives on this machine in the form "C:\". **Arguments: None. **Exceptions: IOException. **Permissions: SystemInfo Permission. ==============================================================================*/ [System.Security.SecuritySafeCritical] // auto-generated public static String[] GetLogicalDrives() { new EnvironmentPermission(PermissionState.Unrestricted).Demand(); int drives = Win32Native.GetLogicalDrives(); if (drives==0) __Error.WinIOError(); uint d = (uint)drives; int count = 0; while (d != 0) { if (((int)d & 1) != 0) count++; d >>= 1; } String[] result = new String[count]; char[] root = new char[] {'A', ':', '\\'}; d = (uint)drives; count = 0; while (d != 0) { if (((int)d & 1) != 0) { result[count++] = new String(root); } d >>= 1; root[0]++; } return result; } /*===================================NewLine==================================== **Action: A property which returns the appropriate newline string for the given ** platform. **Returns: \r\n on Win32. **Arguments: None. **Exceptions: None. ==============================================================================*/ public static String NewLine { get { Contract.Ensures(Contract.Result() != null); return "\r\n"; } } /*===================================Version==================================== **Action: Returns the COM+ version struct, describing the build number. **Returns: **Arguments: **Exceptions: ==============================================================================*/ public static Version Version { get { // 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 // 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 // scheme that matched the product version. In order to preserve compatibility with existing libraries, this needs to be hard-coded. return new Version(4,0,30319,42000); } } /*==================================WorkingSet================================== **Action: **Returns: **Arguments: **Exceptions: ==============================================================================*/ [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity] private static extern long GetWorkingSet(); public static long WorkingSet { [System.Security.SecuritySafeCritical] // auto-generated get { new EnvironmentPermission(PermissionState.Unrestricted).Demand(); return GetWorkingSet(); } } /*==================================OSVersion=================================== **Action: **Returns: **Arguments: **Exceptions: ==============================================================================*/ public static OperatingSystem OSVersion { [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); if (m_os==null) { // We avoid the lock since we don't care if two threads will set this at the same time. Microsoft.Win32.Win32Native.OSVERSIONINFO osvi = new Microsoft.Win32.Win32Native.OSVERSIONINFO(); if (!GetVersion(osvi)) { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion")); } Microsoft.Win32.Win32Native.OSVERSIONINFOEX osviEx = new Microsoft.Win32.Win32Native.OSVERSIONINFOEX(); if (!GetVersionEx(osviEx)) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion")); PlatformID id = PlatformID.Win32NT; #if FEATURE_LEGACYNETCF // return platform as WinCE, to ensure apps earlier than WP8 works as expected. if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8) { id = PlatformID.WinCE; } #endif Version v = new Version(osvi.MajorVersion, osvi.MinorVersion, osvi.BuildNumber, (osviEx.ServicePackMajor << 16) |osviEx.ServicePackMinor); m_os = new OperatingSystem(id, v, osvi.CSDVersion); } Contract.Assert(m_os != null, "m_os != null"); return m_os; } } #if FEATURE_CORESYSTEM internal static bool IsWindows8OrAbove { get { return true; } } #if FEATURE_COMINTEROP internal static bool IsWinRTSupported { get { return true; } } #endif // FEATURE_COMINTEROP #else // FEATURE_CORESYSTEM private static volatile bool s_IsWindows8OrAbove; private static volatile bool s_CheckedOSWin8OrAbove; // Windows 8 version is 6.2 internal static bool IsWindows8OrAbove { get { if (!s_CheckedOSWin8OrAbove) { OperatingSystem OS = Environment.OSVersion; s_IsWindows8OrAbove = (OS.Platform == PlatformID.Win32NT && ((OS.Version.Major == 6 && OS.Version.Minor >= 2) || (OS.Version.Major > 6))); s_CheckedOSWin8OrAbove = true; } return s_IsWindows8OrAbove; } } #if FEATURE_COMINTEROP private static volatile bool s_WinRTSupported; private static volatile bool s_CheckedWinRT; // Does the current version of Windows have Windows Runtime suppport? internal static bool IsWinRTSupported { [SecuritySafeCritical] get { if (!s_CheckedWinRT) { s_WinRTSupported = WinRTSupported(); s_CheckedWinRT = true; } return s_WinRTSupported; } } [SecurityCritical] [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool WinRTSupported(); #endif // FEATURE_COMINTEROP #endif // FEATURE_CORESYSTEM [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool GetVersion(Microsoft.Win32.Win32Native.OSVERSIONINFO osVer); [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern bool GetVersionEx(Microsoft.Win32.Win32Native.OSVERSIONINFOEX osVer); /*==================================StackTrace================================== **Action: **Returns: **Arguments: **Exceptions: ==============================================================================*/ public static String StackTrace { [System.Security.SecuritySafeCritical] // auto-generated get { Contract.Ensures(Contract.Result() != null); new EnvironmentPermission(PermissionState.Unrestricted).Demand(); return GetStackTrace(null, true); } } #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated #endif internal static String GetStackTrace(Exception e, bool needFileInfo) { // Note: Setting needFileInfo to true will start up COM and set our // apartment state. Try to not call this when passing "true" // before the EE's ExecuteMainMethod has had a chance to set up the // apartment state. -- StackTrace st; if (e == null) st = new StackTrace(needFileInfo); else st = new StackTrace(e, needFileInfo); // Do no include a trailing newline for backwards compatibility return st.ToString( System.Diagnostics.StackTrace.TraceFormat.Normal ); } [System.Security.SecuritySafeCritical] // auto-generated private static void InitResourceHelper() { // Only the default AppDomain should have a ResourceHelper. All calls to // GetResourceString from any AppDomain delegate to GetResourceStringLocal // in the default AppDomain via the fcall GetResourceFromDefault. bool tookLock = false; RuntimeHelpers.PrepareConstrainedRegions(); try { Monitor.Enter(Environment.InternalSyncObject, ref tookLock); if (m_resHelper == null) { ResourceHelper rh = new ResourceHelper("mscorlib"); System.Threading.Thread.MemoryBarrier(); m_resHelper =rh; } } finally { if (tookLock) Monitor.Exit(Environment.InternalSyncObject); } } #if !FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern static String GetResourceFromDefault(String key); #endif // Looks up the resource string value for key. // // if you change this method's signature then you must change the code that calls it // in excep.cpp and probably you will have to visit mscorlib.h to add the new signature // as well as metasig.h to create the new signature type #if FEATURE_CORECLR [System.Security.SecurityCritical] // auto-generated #endif internal static String GetResourceStringLocal(String key) { if (m_resHelper == null) InitResourceHelper(); return m_resHelper.GetResourceString(key); } // #threadCultureInfo // Currently in silverlight, CurrentCulture and CurrentUICulture are isolated // within an AppDomain. This is in contrast to the desktop, in which cultures // leak across AppDomain boundaries with the thread. // // Note that mscorlib transitions to the default domain to perform resource // lookup. This causes problems for the silverlight changes: since culture isn't // passed, resource string lookup won't necessarily use the culture of the thread // originating the request. To get around that problem, we pass the CultureInfo // so that the ResourceManager GetString(x, cultureInfo) overload can be used. // We first perform the same check as in CultureInfo to make sure it's safe to // let the CultureInfo travel across AppDomains. [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.None)] internal static String GetResourceString(String key) { #if FEATURE_CORECLR return GetResourceStringLocal(key); #else return GetResourceFromDefault(key); #endif //FEATURE_CORECLR } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.None)] internal static String GetResourceString(String key, params Object[] values) { String s = GetResourceString(key); return String.Format(CultureInfo.CurrentCulture, s, values); } //The following two internal methods are not used anywhere within the framework, // but are being kept around as external platforms built on top of us have taken // dependency by using private reflection on them for getting system resource strings [ResourceExposure(ResourceScope.None)] internal static String GetRuntimeResourceString(String key) { return GetResourceString(key); } [ResourceExposure(ResourceScope.None)] internal static String GetRuntimeResourceString(String key, params Object[] values) { return GetResourceString(key,values); } public static bool Is64BitProcess { get { #if WIN32 return false; #else return true; #endif } } #if !FEATURE_PAL public static bool Is64BitOperatingSystem { [System.Security.SecuritySafeCritical] get { #if WIN32 bool isWow64; // WinXP SP2+ and Win2k3 SP1+ return Win32Native.DoesWin32MethodExist(Win32Native.KERNEL32, "IsWow64Process") && Win32Native.IsWow64Process(Win32Native.GetCurrentProcess(), out isWow64) && isWow64; #else // 64-bit programs run only on 64-bit //< return true; #endif } } #endif public static extern bool HasShutdownStarted { [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] get; } #if !FEATURE_CORECLR // This is the temporary Whidbey stub for compatibility flags [ResourceExposure(ResourceScope.None)] [MethodImplAttribute(MethodImplOptions.InternalCall)] [System.Security.SecurityCritical] internal static extern bool GetCompatibilityFlag(CompatibilityFlag flag); #endif //!FEATURE_CORECLR public static string UserName { [System.Security.SecuritySafeCritical] // auto-generated get { new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserName").Demand(); StringBuilder sb = new StringBuilder(256); int size = sb.Capacity; if (Win32Native.GetUserName(sb, ref size)) { return sb.ToString(); } return String.Empty; } } // Note that this is a handle to a process window station, but it does // not need to be closed. CloseWindowStation would ignore this handle. // We also do handle equality checking as well. This isn't a great fit // for SafeHandle. We don't gain anything by using SafeHandle here. #if !FEATURE_PAL && !FEATURE_CORESYSTEM private static volatile IntPtr processWinStation; // Doesn't need to be initialized as they're zero-init. private static volatile bool isUserNonInteractive; #endif public static bool UserInteractive { [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] get { #if !FEATURE_PAL && !FEATURE_CORESYSTEM IntPtr hwinsta = Win32Native.GetProcessWindowStation(); if (hwinsta != IntPtr.Zero && processWinStation != hwinsta) { int lengthNeeded = 0; Win32Native.USEROBJECTFLAGS flags = new Win32Native.USEROBJECTFLAGS(); if (Win32Native.GetUserObjectInformation(hwinsta, Win32Native.UOI_FLAGS, flags, Marshal.SizeOf(flags),ref lengthNeeded)) { if ((flags.dwFlags & Win32Native.WSF_VISIBLE) == 0) { isUserNonInteractive = true; } } processWinStation = hwinsta; } // The logic is reversed to avoid static initialization to true return !isUserNonInteractive; #else return true; #endif } } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static string GetFolderPath(SpecialFolder folder) { if (!Enum.IsDefined(typeof(SpecialFolder), folder)) throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)folder)); Contract.EndContractBlock(); return InternalGetFolderPath(folder, SpecialFolderOption.None); } [System.Security.SecuritySafeCritical] // auto-generated [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option) { if (!Enum.IsDefined(typeof(SpecialFolder),folder)) throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)folder)); if (!Enum.IsDefined(typeof(SpecialFolderOption),option)) throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)option)); Contract.EndContractBlock(); return InternalGetFolderPath(folder, option); } [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] internal static string UnsafeGetFolderPath(SpecialFolder folder) { return InternalGetFolderPath(folder, SpecialFolderOption.None, suppressSecurityChecks: true); } [System.Security.SecurityCritical] [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private static string InternalGetFolderPath(SpecialFolder folder, SpecialFolderOption option, bool suppressSecurityChecks = false) { #if FEATURE_CORESYSTEM // This is currently customized for Windows Phone since CoreSystem doesn't support // SHGetFolderPath. The allowed folder values are based on the version of .NET CF WP7 was using. switch (folder) { case SpecialFolder.System: return SystemDirectory; case SpecialFolder.ApplicationData: case SpecialFolder.Favorites: case SpecialFolder.Programs: case SpecialFolder.StartMenu: case SpecialFolder.Startup: case SpecialFolder.Personal: throw new PlatformNotSupportedException(); default: throw new PlatformNotSupportedException(); } #else // FEATURE_CORESYSTEM #if !FEATURE_CORECLR if (option == SpecialFolderOption.Create && !suppressSecurityChecks) { FileIOPermission createPermission = new FileIOPermission(PermissionState.None); createPermission.AllFiles = FileIOPermissionAccess.Write; createPermission.Demand(); } #endif StringBuilder sb = new StringBuilder(Path.MAX_PATH); int hresult = Win32Native.SHGetFolderPath(IntPtr.Zero, /* hwndOwner: [in] Reserved */ ((int)folder | (int)option), /* nFolder: [in] CSIDL */ IntPtr.Zero, /* hToken: [in] access token */ Win32Native.SHGFP_TYPE_CURRENT, /* dwFlags: [in] retrieve current path */ sb); /* pszPath: [out]resultant path */ String s; if (hresult < 0) { switch (hresult) { default: // The previous incarnation threw away all errors. In order to limit // breaking changes, we will be permissive about these errors // instead of calling ThowExceptionForHR. //Runtime.InteropServices.Marshal.ThrowExceptionForHR(hresult); break; case __HResults.COR_E_PLATFORMNOTSUPPORTED: // This one error is the one we do want to throw. // < throw new PlatformNotSupportedException(); } // SHGetFolderPath does not initialize the output buffer on error s = String.Empty; } else { s = sb.ToString(); } if (!suppressSecurityChecks) { // On CoreCLR we can check with the host if we're not trying to use any special options. // Otherwise, we need to do a full demand since hosts aren't expecting to handle requests to // create special folders. #if FEATURE_CORECLR if (option == SpecialFolderOption.None) { FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, s); state.EnsureState(); } else #endif // FEATURE_CORECLR { new FileIOPermission(FileIOPermissionAccess.PathDiscovery, s).Demand(); } } return s; #endif // FEATURE_CORESYSTEM } #if !FEATURE_PAL public static string UserDomainName { [System.Security.SecuritySafeCritical] // auto-generated get { new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserDomain").Demand(); byte[] sid = new byte[1024]; int sidLen = sid.Length; StringBuilder domainName = new StringBuilder(1024); uint domainNameLen = (uint) domainName.Capacity; int peUse; byte ret = Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen); if (ret == 1) { string samName = domainName.ToString(); int index = samName.IndexOf('\\'); if( index != -1) { return samName.Substring(0, index); } } domainNameLen = (uint) domainName.Capacity; bool success = Win32Native.LookupAccountName(null, UserName, sid, ref sidLen, domainName, ref domainNameLen, out peUse); if (!success) { int errorCode = Marshal.GetLastWin32Error(); throw new InvalidOperationException(Win32Native.GetMessage(errorCode)); } return domainName.ToString(); } } #endif // !FEATURE_PAL public enum SpecialFolderOption { None = 0, Create = Win32Native.CSIDL_FLAG_CREATE, DoNotVerify = Win32Native.CSIDL_FLAG_DONT_VERIFY, } //////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//////// //////!!!!!! Keep the following locations synchronized !!!!!!//////// //////!!!!!! 1) ndp\clr\src\BCL\Microsoft\Win32\Win32Native.cs !!!!!!//////// //////!!!!!! 2) ndp\clr\src\BCL\System\Environment.cs !!!!!!//////// //////!!!!!! 3) rotor\pal\inc\rotor_pal.h !!!!!!//////// //////!!!!!! 4) rotor\pal\corunix\shfolder\shfolder.cpp !!!!!!//////// //////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//////// [ComVisible(true)] public enum SpecialFolder { // // Represents the file system directory that serves as a common repository for // application-specific data for the current, roaming user. // A roaming user works on more than one computer on a network. A roaming user's // profile is kept on a server on the network and is loaded onto a system when the // user logs on. // ApplicationData = Win32Native.CSIDL_APPDATA, // // Represents the file system directory that serves as a common repository for application-specific data that // is used by all users. // CommonApplicationData = Win32Native.CSIDL_COMMON_APPDATA, // // Represents the file system directory that serves as a common repository for application specific data that // is used by the current, non-roaming user. // LocalApplicationData = Win32Native.CSIDL_LOCAL_APPDATA, // // Represents the file system directory that serves as a common repository for Internet // cookies. // Cookies = Win32Native.CSIDL_COOKIES, Desktop = Win32Native.CSIDL_DESKTOP, // // Represents the file system directory that serves as a common repository for the user's // favorite items. // Favorites = Win32Native.CSIDL_FAVORITES, // // Represents the file system directory that serves as a common repository for Internet // history items. // History = Win32Native.CSIDL_HISTORY, // // Represents the file system directory that serves as a common repository for temporary // Internet files. // InternetCache = Win32Native.CSIDL_INTERNET_CACHE, // // Represents the file system directory that contains // the user's program groups. // Programs = Win32Native.CSIDL_PROGRAMS, MyComputer = Win32Native.CSIDL_DRIVES, MyMusic = Win32Native.CSIDL_MYMUSIC, MyPictures = Win32Native.CSIDL_MYPICTURES, // "My Videos" folder MyVideos = Win32Native.CSIDL_MYVIDEO, // // Represents the file system directory that contains the user's most recently used // documents. // Recent = Win32Native.CSIDL_RECENT, // // Represents the file system directory that contains Send To menu items. // SendTo = Win32Native.CSIDL_SENDTO, // // Represents the file system directory that contains the Start menu items. // StartMenu = Win32Native.CSIDL_STARTMENU, // // Represents the file system directory that corresponds to the user's Startup program group. The system // starts these programs whenever any user logs on to Windows NT, or // starts Windows 95 or Windows 98. // Startup = Win32Native.CSIDL_STARTUP, // // System directory. // System = Win32Native.CSIDL_SYSTEM, // // Represents the file system directory that serves as a common repository for document // templates. // Templates = Win32Native.CSIDL_TEMPLATES, // // Represents the file system directory used to physically store file objects on the desktop. // This should not be confused with the desktop folder itself, which is // a virtual folder. // DesktopDirectory = Win32Native.CSIDL_DESKTOPDIRECTORY, // // Represents the file system directory that serves as a common repository for documents. // Personal = Win32Native.CSIDL_PERSONAL, // // "MyDocuments" is a better name than "Personal" // MyDocuments = Win32Native.CSIDL_PERSONAL, // // Represents the program files folder. // ProgramFiles = Win32Native.CSIDL_PROGRAM_FILES, // // Represents the folder for components that are shared across applications. // CommonProgramFiles = Win32Native.CSIDL_PROGRAM_FILES_COMMON, #if !FEATURE_CORECLR // // \Start Menu\Programs\Administrative Tools // AdminTools = Win32Native.CSIDL_ADMINTOOLS, // // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning // CDBurning = Win32Native.CSIDL_CDBURN_AREA, // // All Users\Start Menu\Programs\Administrative Tools // CommonAdminTools = Win32Native.CSIDL_COMMON_ADMINTOOLS, // // All Users\Documents // CommonDocuments = Win32Native.CSIDL_COMMON_DOCUMENTS, // // All Users\My Music // CommonMusic = Win32Native.CSIDL_COMMON_MUSIC, // // Links to All Users OEM specific apps // CommonOemLinks = Win32Native.CSIDL_COMMON_OEM_LINKS, // // All Users\My Pictures // CommonPictures = Win32Native.CSIDL_COMMON_PICTURES, // // All Users\Start Menu // CommonStartMenu = Win32Native.CSIDL_COMMON_STARTMENU, // // All Users\Start Menu\Programs // CommonPrograms = Win32Native.CSIDL_COMMON_PROGRAMS, // // All Users\Startup // CommonStartup = Win32Native.CSIDL_COMMON_STARTUP, // // All Users\Desktop // CommonDesktopDirectory = Win32Native.CSIDL_COMMON_DESKTOPDIRECTORY, // // All Users\Templates // CommonTemplates = Win32Native.CSIDL_COMMON_TEMPLATES, // // All Users\My Video // CommonVideos = Win32Native.CSIDL_COMMON_VIDEO, // // windows\fonts // Fonts = Win32Native.CSIDL_FONTS, // // %APPDATA%\Microsoft\Windows\Network Shortcuts // NetworkShortcuts = Win32Native.CSIDL_NETHOOD, // // %APPDATA%\Microsoft\Windows\Printer Shortcuts // PrinterShortcuts = Win32Native.CSIDL_PRINTHOOD, // // USERPROFILE // UserProfile = Win32Native.CSIDL_PROFILE, // // x86 Program Files\Common on RISC // CommonProgramFilesX86 = Win32Native.CSIDL_PROGRAM_FILES_COMMONX86, // // x86 C:\Program Files on RISC // ProgramFilesX86 = Win32Native.CSIDL_PROGRAM_FILESX86, // // Resource Directory // Resources = Win32Native.CSIDL_RESOURCES, // // Localized Resource Directory // LocalizedResources = Win32Native.CSIDL_RESOURCES_LOCALIZED, // // %windir%\System32 or %windir%\syswow64 // SystemX86 = Win32Native.CSIDL_SYSTEMX86, // // GetWindowsDirectory() // Windows = Win32Native.CSIDL_WINDOWS, #endif // !FEATURE_CORECLR } public static int CurrentManagedThreadId { [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] get { return Thread.CurrentThread.ManagedThreadId; } } } }