Browse Source

Switch CoreLib over to using shared Environment from corefx (#22106)

This requires merging/adapting the implementation with EnvironmentAugments (which goes away completely), the shared files, what corert has, etc.

Signed-off-by: dotnet-bot <[email protected]>
Stephen Toub 7 năm trước cách đây
mục cha
commit
8eeffb8628

+ 2 - 2
netcore/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.ExpandEnvironmentStrings.cs

@@ -8,7 +8,7 @@ internal partial class Interop
 {
     internal partial class Kernel32
     {
-        [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)]
-        internal static extern uint ExpandEnvironmentStringsW(string lpSrc, ref char lpDst, uint nSize);
+        [DllImport(Libraries.Kernel32, EntryPoint = "ExpandEnvironmentStringsW", CharSet = CharSet.Unicode, SetLastError = true)]
+        internal static extern uint ExpandEnvironmentStrings(string lpSrc, ref char lpDst, uint nSize);
     }
 }

+ 23 - 0
netcore/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetEnvironmentVariable.cs

@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+    internal partial class Kernel32
+    {
+        internal static unsafe int GetEnvironmentVariable(string lpName, Span<char> buffer)
+        {
+            fixed (char* bufferPtr = &MemoryMarshal.GetReference(buffer))
+            {
+                return GetEnvironmentVariable(lpName, bufferPtr, buffer.Length);
+            }
+        }
+
+        [DllImport(Libraries.Kernel32, EntryPoint = "GetEnvironmentVariableW", SetLastError = true, CharSet = CharSet.Unicode)]
+        private static extern unsafe int GetEnvironmentVariable(string lpName, char* lpBuffer, int nSize);
+    }
+}

+ 45 - 3
netcore/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems

@@ -211,6 +211,9 @@
     <Compile Include="$(MSBuildThisFileDirectory)System\DuplicateWaitObjectException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Empty.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\EntryPointNotFoundException.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.SpecialFolder.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.SpecialFolderOption.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\EnvironmentVariableTarget.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\EventArgs.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\EventHandler.cs" />
@@ -370,12 +373,15 @@
     <Compile Include="$(MSBuildThisFileDirectory)System\Object.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\ObjectDisposedException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\ObsoleteAttribute.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\OperatingSystem.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\OperationCanceledException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\OutOfMemoryException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\OverflowException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\ParamArrayAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\ParamsArray.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\ParseNumbers.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\PasteArguments.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\PlatformID.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\PlatformNotSupportedException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Progress.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Random.cs" />
@@ -915,32 +921,40 @@
     <Compile Include="$(MSBuildThisFileDirectory)System\Numerics\Vector_Operations.cs" />
   </ItemGroup>
   <ItemGroup Condition="$(TargetsWindows)">
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.LookupAccountNameW.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.BCryptGenRandom.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.BCryptGenRandom.GetRandomBytes.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.NTSTATUS.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Crypt32\Interop.CryptProtectMemory.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.BOOL.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.BOOLEAN.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Libraries.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CancelIoEx.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ExpandEnvironmentStrings.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FileAttributes.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FILE_INFO_BY_HANDLE_CLASS.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FileTypes.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FindClose.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FindFirstFileEx.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FlushFileBuffers.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FreeEnvironmentStrings.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetComputerName.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetCPInfo.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetEnvironmentStrings.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetCurrentProcess_IntPtr.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetCurrentDirectory.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetFileAttributesEx.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetFileInformationByHandleEx.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetFileType_SafeHandle.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetFullPathNameW.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetLongPathNameW.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetLogicalDrives.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetSystemDirectoryW.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetSystemInfo.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetTempFileNameW.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetTempPathW.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetVersionExW.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Globalization.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GlobalMemoryStatusEx.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.IsWow64Process_IntPtr.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.LockFile.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.MAX_PATH.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.MEMORY_BASIC_INFORMATION.cs" />
@@ -952,8 +966,8 @@
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ResolveLocaleName.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SECURITY_ATTRIBUTES.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SecurityOptions.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetCurrentDirectory.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetEndOfFile.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetEnvironmentVariable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetThreadErrorMode.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetFilePointerEx.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SYSTEM_INFO.cs" />
@@ -971,9 +985,12 @@
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysAllocStringLen.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysFreeString.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysStringLen.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Secur32\Interop.GetUserNameExW.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Shell32\Interop.SHGetKnownFolderPath.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Internal\IO\File.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFileHandle.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFindHandle.Windows.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebugProvider.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureInfo.Windows.cs" />
@@ -987,12 +1004,14 @@
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\Normalization.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TextInfo.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Guid.Windows.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\IO\DriveInfoInternal.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStreamCompletionSource.Win32.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\Path.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\PathHelper.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\PathInternal.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\DisableMediaInsertionPrompt.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\PasteArguments.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Windows.cs" Condition="'$(TargetsCoreRT)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Security\SafeBSTRHandle.cs" />
@@ -1030,6 +1049,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.LoadString.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.SendMessageTimeout.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.Win32.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Win32.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Win32.cs" />
   </ItemGroup>
@@ -1043,10 +1063,15 @@
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CloseHandle.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Constants.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Errors.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetEnvironmentVariable.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.GetEnvironmentStrings.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FreeEnvironmentStrings.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Mutex.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Semaphore.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetEnvironmentVariable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.EventWaitHandle.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.Variables.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\Win32Marshal.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Mutex.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Semaphore.Windows.cs" />
@@ -1066,15 +1091,23 @@
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Globalization.Native\Interop.ResultCode.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Globalization.Native\Interop.TimeZoneInfo.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Globalization.Native\Interop.Utils.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.Access.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.ChDir.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.Close.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.FLock.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.FSync.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.FTruncate.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.GetCwd.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.GetEUid.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.GetHostName.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.GetPwUid.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.GetRandomBytes.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.GetUnixName.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.GetUnixRelease.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.LockFileRegion.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.LSeek.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.MksTemps.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.MountPoints.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.Open.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.OpenFlags.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.PathConf.cs" />
@@ -1084,12 +1117,14 @@
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.ReadDir.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.ReadLink.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.Stat.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.SysConf.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.SysLog.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.Unlink.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\System.Native\Interop.Write.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Internal\IO\File.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFileHandle.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebugProvider.Unix.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareInfo.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Unix.cs" />
@@ -1101,16 +1136,23 @@
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\Normalization.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TextInfo.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Guid.Unix.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\IO\DriveInfoInternal.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.OSX.cs" Condition="'$(TargetsOSX)' == 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Linux.cs" Condition="'$(TargetsOSX)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\Path.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\IO\PathInternal.Unix.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\IO\PersistedFiles.Unix.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\IO\PersistedFiles.Names.Unix.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\PasteArguments.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Unix.cs" Condition="'$(TargetsCoreRT)' != 'true'" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Unix.cs" />
   </ItemGroup>
+  <ItemGroup Condition="$(TargetsUnix) or '$(EnableWinRT)'=='true'">
+    <Compile Include="$(MSBuildThisFileDirectory)System\Environment.NoRegistry.cs" />
+  </ItemGroup>
   <ItemGroup Condition="'$(FeatureHardwareIntrinsics)' == 'true' AND ('$(Platform)' == 'x64' OR ('$(Platform)' == 'x86' AND '$(TargetsUnix)' != 'true'))">
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Aes.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx.cs" />

+ 21 - 0
netcore/System.Private.CoreLib/shared/System/Environment.NoRegistry.cs

@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Collections;
+using Microsoft.Win32;
+
+namespace System
+{
+    public static partial class Environment
+    {
+        // Systems without the Windows registry pretend that it's always empty.
+
+        private static string GetEnvironmentVariableFromRegistry(string variable, bool fromMachine) => null;
+
+        private static void SetEnvironmentVariableFromRegistry(string variable, string value, bool fromMachine) { }
+
+        private static IDictionary GetEnvironmentVariablesFromRegistry(bool fromMachine) => new Hashtable();
+    }
+}

+ 9 - 11
netcore/System.Private.CoreLib/shared/System/Environment.Unix.cs

@@ -16,17 +16,15 @@ namespace System
 {
     public static partial class Environment
     {
-        internal static readonly bool IsMac = Interop.Sys.GetUnixName() == "OSX";
+        private static readonly bool s_isMac = Interop.Sys.GetUnixName() == "OSX";
         private static Func<string, object> s_directoryCreateDirectory;
 
         private static string CurrentDirectoryCore
         {
-            get { return Interop.Sys.GetCwd(); }
-            set { Interop.CheckIo(Interop.Sys.ChDir(value), value, isDirectory: true); }
+            get => Interop.Sys.GetCwd();
+            set => Interop.CheckIo(Interop.Sys.ChDir(value), value, isDirectory: true);
         }
 
-        public static int ExitCode { get { return EnvironmentAugments.ExitCode; } set { EnvironmentAugments.ExitCode = value; } }
-
         private static string ExpandEnvironmentVariablesCore(string name)
         {
             Span<char> initialBuffer = stackalloc char[128];
@@ -101,7 +99,7 @@ namespace System
                 case SpecialFolder.CommonApplicationData: return "/usr/share";
                 case SpecialFolder.CommonTemplates: return "/usr/share/templates";
             }
-            if (IsMac)
+            if (s_isMac)
             {
                 switch (folder)
                 {
@@ -161,17 +159,17 @@ namespace System
                     return ReadXdgDirectory(home, "XDG_VIDEOS_DIR", "Videos");
 
                 case SpecialFolder.MyMusic:
-                    return IsMac ? Path.Combine(home, "Music") : ReadXdgDirectory(home, "XDG_MUSIC_DIR", "Music");
+                    return s_isMac ? Path.Combine(home, "Music") : ReadXdgDirectory(home, "XDG_MUSIC_DIR", "Music");
                 case SpecialFolder.MyPictures:
-                    return IsMac ? Path.Combine(home, "Pictures") : ReadXdgDirectory(home, "XDG_PICTURES_DIR", "Pictures");
+                    return s_isMac ? Path.Combine(home, "Pictures") : ReadXdgDirectory(home, "XDG_PICTURES_DIR", "Pictures");
                 case SpecialFolder.Fonts:
-                    return IsMac ? Path.Combine(home, "Library", "Fonts") : Path.Combine(home, ".fonts");
+                    return s_isMac ? Path.Combine(home, "Library", "Fonts") : Path.Combine(home, ".fonts");
 
                 case SpecialFolder.Favorites:
-                    if (IsMac) return Path.Combine(home, "Library", "Favorites");
+                    if (s_isMac) return Path.Combine(home, "Library", "Favorites");
                     break;
                 case SpecialFolder.InternetCache:
-                    if (IsMac) return Path.Combine(home, "Library", "Caches");
+                    if (s_isMac) return Path.Combine(home, "Library", "Caches");
                     break;
             }
 

+ 168 - 0
netcore/System.Private.CoreLib/shared/System/Environment.Variables.Windows.cs

@@ -0,0 +1,168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Buffers;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+    public static partial class Environment
+    {
+        private static string GetEnvironmentVariableCore(string variable)
+        {
+            Span<char> buffer = stackalloc char[128]; // a somewhat reasonable default size
+            int requiredSize = Interop.Kernel32.GetEnvironmentVariable(variable, buffer);
+
+            if (requiredSize == 0 && Marshal.GetLastWin32Error() == Interop.Errors.ERROR_ENVVAR_NOT_FOUND)
+            {
+                return null;
+            }
+
+            if (requiredSize <= buffer.Length)
+            {
+                return new string(buffer.Slice(0, requiredSize));
+            }
+
+            char[] chars = ArrayPool<char>.Shared.Rent(requiredSize);
+            try
+            {
+                buffer = chars;
+                requiredSize = Interop.Kernel32.GetEnvironmentVariable(variable, buffer);
+                if ((requiredSize == 0 && Marshal.GetLastWin32Error() == Interop.Errors.ERROR_ENVVAR_NOT_FOUND) ||
+                    requiredSize > buffer.Length)
+                {
+                    return null;
+                }
+
+                return new string(buffer.Slice(0, requiredSize));
+            }
+            finally
+            {
+                ArrayPool<char>.Shared.Return(chars);
+            }
+        }
+
+        private static void SetEnvironmentVariableCore(string variable, string value)
+        {
+            if (!Interop.Kernel32.SetEnvironmentVariable(variable, value))
+            {
+                int errorCode = Marshal.GetLastWin32Error();
+                switch (errorCode)
+                {
+                    case Interop.Errors.ERROR_ENVVAR_NOT_FOUND:
+                        // Allow user to try to clear a environment variable
+                        return;
+
+                    case Interop.Errors.ERROR_FILENAME_EXCED_RANGE:
+                        // The error message from Win32 is "The filename or extension is too long",
+                        // which is not accurate.
+                        throw new ArgumentException(SR.Format(SR.Argument_LongEnvVarValue));
+
+                    case Interop.Errors.ERROR_NOT_ENOUGH_MEMORY:
+                    case Interop.Errors.ERROR_NO_SYSTEM_RESOURCES:
+                        throw new OutOfMemoryException(Interop.Kernel32.GetMessage(errorCode));
+
+                    default:
+                        throw new ArgumentException(Interop.Kernel32.GetMessage(errorCode));
+                }
+            }
+        }
+
+        public static unsafe IDictionary GetEnvironmentVariables()
+        {
+            char* pStrings = Interop.Kernel32.GetEnvironmentStrings();
+            if (pStrings == null)
+            {
+                throw new OutOfMemoryException();
+            }
+
+            try
+            {
+                // 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++;
+                }
+                Span<char> block = new Span<char>(pStrings, (int)(p - pStrings + 1));
+
+                // 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.
+
+                // 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).
+
+                var results = new Hashtable();
+                for (int i = 0; i < block.Length; i++)
+                {
+                    int startKey = i;
+
+                    // Skip to key. On some old OS, the environment block can be corrupted.
+                    // Some will not have '=', so we need to check for '\0'. 
+                    while (block[i] != '=' && block[i] != '\0')
+                    {
+                        i++;
+                    }
+
+                    if (block[i] == '\0')
+                    {
+                        continue;
+                    }
+
+                    // Skip over environment variables starting with '='
+                    if (i - startKey == 0)
+                    {
+                        while (block[i] != 0)
+                        {
+                            i++;
+                        }
+
+                        continue;
+                    }
+
+                    string key = new string(block.Slice(startKey, i - startKey));
+                    i++;  // skip over '='
+
+                    int startValue = i;
+                    while (block[i] != 0)
+                    {
+                        i++; // Read to end of this entry 
+                    }
+
+                    string value = new string(block.Slice(startValue, i - startValue)); // skip over 0 handled by for loop's i++
+                    try
+                    {
+                        results.Add(key, value);
+                    }
+                    catch (ArgumentException)
+                    {
+                        // Throw and catch intentionally to provide non-fatal notification about corrupted environment block
+                    }
+                }
+                return results;
+            }
+            finally
+            {
+                bool success = Interop.Kernel32.FreeEnvironmentStrings(pStrings);
+                Debug.Assert(success);
+            }
+        }
+    }
+}

+ 139 - 1
netcore/System.Private.CoreLib/shared/System/Environment.Win32.cs

@@ -2,18 +2,126 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Collections;
+using System.Diagnostics;
 using System.IO;
-using System.Text;
+using System.Reflection;
 using System.Runtime.InteropServices;
+using System.Text;
+using Internal.Win32;
 
 namespace System
 {
     public static partial class Environment
     {
+        private static string GetEnvironmentVariableFromRegistry(string variable, bool fromMachine)
+        {
+            Debug.Assert(variable != null);
+
+#if FEATURE_APPX
+            if (ApplicationModel.IsUap)
+                return null; // Systems without the Windows registry pretend that it's always empty.
+#endif
+
+            using (RegistryKey environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: false))
+            {
+                return environmentKey?.GetValue(variable) as string;
+            }
+        }
+
+        private static void SetEnvironmentVariableFromRegistry(string variable, string value, bool fromMachine)
+        {
+            Debug.Assert(variable != null);
+
+#if FEATURE_APPX
+            if (ApplicationModel.IsUap)
+                return; // Systems without the Windows registry pretend that it's always empty.
+#endif
+
+            const int MaxUserEnvVariableLength = 255; // User-wide env vars stored in the registry have names limited to 255 chars
+            if (!fromMachine && variable.Length >= MaxUserEnvVariableLength)
+            {
+                throw new ArgumentException(SR.Argument_LongEnvVarValue, nameof(variable));
+            }
+
+            using (RegistryKey environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: true))
+            {
+                if (environmentKey != null)
+                {
+                    if (value == null)
+                    {
+                        environmentKey.DeleteValue(variable, throwOnMissingValue: false);
+                    }
+                    else
+                    {
+                        environmentKey.SetValue(variable, value);
+                    }
+                }
+            }
+
+            // send a WM_SETTINGCHANGE message to all windows
+            IntPtr r = Interop.User32.SendMessageTimeout(new IntPtr(Interop.User32.HWND_BROADCAST), Interop.User32.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero);
+            Debug.Assert(r != IntPtr.Zero, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error());
+        }
+
+        private static IDictionary GetEnvironmentVariablesFromRegistry(bool fromMachine)
+        {
+            var results = new Hashtable();
+#if FEATURE_APPX
+            if (ApplicationModel.IsUap) // Systems without the Windows registry pretend that it's always empty.
+                return results;
+#endif
+
+            using (RegistryKey environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: false))
+            {
+                if (environmentKey != null)
+                {
+                    foreach (string name in environmentKey.GetValueNames())
+                    {
+                        string value = environmentKey.GetValue(name, "").ToString();
+                        try
+                        {
+                            results.Add(name, value);
+                        }
+                        catch (ArgumentException)
+                        {
+                            // Throw and catch intentionally to provide non-fatal notification about corrupted environment block
+                        }
+                    }
+                }
+            }
+
+            return results;
+        }
+
+        private static RegistryKey OpenEnvironmentKeyIfExists(bool fromMachine, bool writable)
+        {
+            RegistryKey baseKey;
+            string keyName;
+
+            if (fromMachine)
+            {
+                baseKey = Registry.LocalMachine;
+                keyName = @"System\CurrentControlSet\Control\Session Manager\Environment";
+            }
+            else
+            {
+                baseKey = Registry.CurrentUser;
+                keyName = "Environment";
+            }
+
+            return baseKey.OpenSubKey(keyName, writable: writable);
+        }
+
         public static string UserName
         {
             get
             {
+#if FEATURE_APPX
+                if (ApplicationModel.IsUap)
+                    return "Windows User";
+#endif
+
                 // 40 should be enough as we're asking for the SAM compatible name (DOMAIN\User).
                 // The max length should be 15 (domain) + 1 (separator) + 20 (name) + null. If for
                 // some reason it isn't, we'll grow the buffer.
@@ -60,6 +168,11 @@ namespace System
         {
             get
             {
+#if FEATURE_APPX
+                if (ApplicationModel.IsUap)
+                    return "Windows Domain";
+#endif
+
                 // See the comment in UserName
                 Span<char> initialBuffer = stackalloc char[40];
                 var builder = new ValueStringBuilder(initialBuffer);
@@ -108,6 +221,11 @@ namespace System
 
         private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOption option)
         {
+#if FEATURE_APPX
+            if (ApplicationModel.IsUap)
+                return WinRTFolderPaths.GetFolderPath(folder, option);
+#endif
+
             // We're using SHGetKnownFolderPath instead of SHGetFolderPath as SHGetFolderPath is
             // capped at MAX_PATH.
             //
@@ -280,5 +398,25 @@ namespace System
 
             return path;
         }
+
+#if FEATURE_APPX
+        private static class WinRTFolderPaths
+        {
+            private static Func<SpecialFolder, SpecialFolderOption, string> s_winRTFolderPathsGetFolderPath;
+
+            public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
+            {
+                if (s_winRTFolderPathsGetFolderPath == null)
+                {
+                    Type winRtFolderPathsType = Type.GetType("System.WinRTFolderPaths, System.Runtime.WindowsRuntime, Version=4.0.14.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", throwOnError: false);
+                    MethodInfo getFolderPathsMethod = winRtFolderPathsType?.GetMethod("GetFolderPath", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, null, new Type[] { typeof(SpecialFolder), typeof(SpecialFolderOption) }, null);
+                    var d = (Func<SpecialFolder, SpecialFolderOption, string>)getFolderPathsMethod?.CreateDelegate(typeof(Func<SpecialFolder, SpecialFolderOption, string>));
+                    s_winRTFolderPathsGetFolderPath = d ?? delegate { return null; };
+                }
+
+                return s_winRTFolderPathsGetFolderPath(folder, option);
+            }
+        }
+#endif
     }
 }

+ 8 - 18
netcore/System.Private.CoreLib/shared/System/Environment.Windows.cs

@@ -3,9 +3,10 @@
 // See the LICENSE file in the project root for more information.
 
 using System.IO;
+using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Text;
-using Internal.Runtime.Augments;
+using Microsoft.Win32;
 
 namespace System
 {
@@ -59,15 +60,13 @@ namespace System
             }
         }
 
-        public static int ExitCode { get { return EnvironmentAugments.ExitCode; } set { EnvironmentAugments.ExitCode = value; } }
-
         private static string ExpandEnvironmentVariablesCore(string name)
         {
             Span<char> initialBuffer = stackalloc char[128];
             var builder = new ValueStringBuilder(initialBuffer);
 
             uint length;
-            while ((length = Interop.Kernel32.ExpandEnvironmentStringsW(name, ref builder.GetPinnableReference(), (uint)builder.Capacity)) > builder.Capacity)
+            while ((length = Interop.Kernel32.ExpandEnvironmentStrings(name, ref builder.GetPinnableReference(), (uint)builder.Capacity)) > builder.Capacity)
             {
                 builder.EnsureCapacity((int)length);
             }
@@ -80,21 +79,12 @@ namespace System
             return builder.ToString();
         }
 
-        private static bool Is64BitOperatingSystemWhen32BitProcess
-            => Interop.Kernel32.IsWow64Process(Interop.Kernel32.GetCurrentProcess(), out bool isWow64) && isWow64;
+        private static bool Is64BitOperatingSystemWhen32BitProcess =>
+            Interop.Kernel32.IsWow64Process(Interop.Kernel32.GetCurrentProcess(), out bool isWow64) && isWow64;
 
-        public static string MachineName
-        {
-            get
-            {
-                string name = Interop.Kernel32.GetComputerName();
-                if (name == null)
-                {
-                    throw new InvalidOperationException(SR.InvalidOperation_ComputerName);
-                }
-                return name;
-            }
-        }
+        public static string MachineName =>
+            Interop.Kernel32.GetComputerName() ??
+            throw new InvalidOperationException(SR.InvalidOperation_ComputerName);
 
         private static readonly unsafe Lazy<OperatingSystem> s_osVersion = new Lazy<OperatingSystem>(() =>
         {

+ 73 - 84
netcore/System.Private.CoreLib/shared/System/Environment.cs

@@ -6,8 +6,6 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics;
 using System.Reflection;
-using System.Runtime.CompilerServices;
-using Internal.Runtime.Augments;
 
 namespace System
 {
@@ -15,157 +13,113 @@ namespace System
     {
         public static string GetEnvironmentVariable(string variable)
         {
-            return EnvironmentAugments.GetEnvironmentVariable(variable);
+            if (variable == null)
+                throw new ArgumentNullException(nameof(variable));
+
+            return GetEnvironmentVariableCore(variable);
         }
 
         public static string GetEnvironmentVariable(string variable, EnvironmentVariableTarget target)
         {
-            return EnvironmentAugments.GetEnvironmentVariable(variable, target);
-        }
+            if (target == EnvironmentVariableTarget.Process)
+                return GetEnvironmentVariable(variable);
 
-        public static IDictionary GetEnvironmentVariables()
-        {
-            // To maintain complete compatibility with prior versions we need to return a Hashtable.
-            // We did ship a prior version of Core with LowLevelDictionary, which does iterate the
-            // same (e.g. yields DictionaryEntry), but it is not a public type.
-            //
-            // While we could pass Hashtable back from CoreCLR the type is also defined here. We only
-            // want to surface the local Hashtable.
-            return EnvironmentAugments.EnumerateEnvironmentVariables().ToHashtable();
+            if (variable == null)
+                throw new ArgumentNullException(nameof(variable));
+
+            bool fromMachine = ValidateAndConvertRegistryTarget(target);
+            return GetEnvironmentVariableFromRegistry(variable, fromMachine);
         }
 
         public static IDictionary GetEnvironmentVariables(EnvironmentVariableTarget target)
         {
-            // See comments in GetEnvironmentVariables()
-            return EnvironmentAugments.EnumerateEnvironmentVariables(target).ToHashtable();
-        }
+            if (target == EnvironmentVariableTarget.Process)
+                return GetEnvironmentVariables();
 
-        private static Hashtable ToHashtable(this IEnumerable<KeyValuePair<string, string>> pairs)
-        {
-            Hashtable hashTable = new Hashtable();
-            foreach (KeyValuePair<string, string> pair in pairs)
-            {
-                try 
-                {
-                    hashTable.Add(pair.Key, pair.Value);                 
-                }
-                catch (ArgumentException)
-                {
-                    // Throw and catch intentionally to provide non-fatal notification about corrupted environment block
-                }
-            }
-            return hashTable;
+            bool fromMachine = ValidateAndConvertRegistryTarget(target);
+            return GetEnvironmentVariablesFromRegistry(fromMachine);
         }
 
         public static void SetEnvironmentVariable(string variable, string value)
         {
-            EnvironmentAugments.SetEnvironmentVariable(variable, value);
+            ValidateVariableAndValue(variable, ref value);
+            SetEnvironmentVariableCore(variable, value);
         }
 
         public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target)
         {
-            EnvironmentAugments.SetEnvironmentVariable(variable, value, target);
-        }
-
-        public static string CommandLine
-        {
-            get
+            if (target == EnvironmentVariableTarget.Process)
             {
-                return PasteArguments.Paste(GetCommandLineArgs(), pasteFirstArgumentUsingArgV0Rules: true);
+                SetEnvironmentVariable(variable, value);
+                return;
             }
+
+            ValidateVariableAndValue(variable, ref value);
+
+            bool fromMachine = ValidateAndConvertRegistryTarget(target);
+            SetEnvironmentVariableFromRegistry(variable, value, fromMachine: fromMachine);
         }
 
+        public static string CommandLine => PasteArguments.Paste(GetCommandLineArgs(), pasteFirstArgumentUsingArgV0Rules: true);
+
         public static string CurrentDirectory
         {
-            get { return CurrentDirectoryCore; }
+            get => CurrentDirectoryCore;
             set
             {
                 if (value == null)
-                {
                     throw new ArgumentNullException(nameof(value));
-                }
 
                 if (value.Length == 0)
-                {
                     throw new ArgumentException(SR.Argument_PathEmpty, nameof(value));
-                }
 
                 CurrentDirectoryCore = value;
             }
         }
 
-        public static int CurrentManagedThreadId => EnvironmentAugments.CurrentManagedThreadId;
-
-        public static void Exit(int exitCode) => EnvironmentAugments.Exit(exitCode);
-        
-        public static void FailFast(string message) => FailFast(message, exception: null);
-
-        public static void FailFast(string message, Exception exception) => EnvironmentAugments.FailFast(message, exception);
-
         public static string ExpandEnvironmentVariables(string name)
         {
             if (name == null)
-            {
                 throw new ArgumentNullException(nameof(name));
-            }
 
             if (name.Length == 0)
-            {
                 return name;
-            }
 
             return ExpandEnvironmentVariablesCore(name);
         }
 
-        public static string[] GetCommandLineArgs() => EnvironmentAugments.GetCommandLineArgs();
+        private static string[] s_commandLineArgs;
+
+        internal static void SetCommandLineArgs(string[] cmdLineArgs) // invoked from VM
+        {
+            s_commandLineArgs = cmdLineArgs;
+        }
 
         public static string GetFolderPath(SpecialFolder folder) => GetFolderPath(folder, SpecialFolderOption.None);
 
         public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option)
         {
             if (!Enum.IsDefined(typeof(SpecialFolder), folder))
-            {
                 throw new ArgumentOutOfRangeException(nameof(folder), folder, SR.Format(SR.Arg_EnumIllegalVal, folder));
-            }
 
             if (option != SpecialFolderOption.None && !Enum.IsDefined(typeof(SpecialFolderOption), option))
-            {
                 throw new ArgumentOutOfRangeException(nameof(option), option, SR.Format(SR.Arg_EnumIllegalVal, option));
-            }
 
             return GetFolderPathCore(folder, option);
         }
 
-        public static bool HasShutdownStarted => EnvironmentAugments.HasShutdownStarted;
-
         public static bool Is64BitProcess => IntPtr.Size == 8;
 
         public static bool Is64BitOperatingSystem => Is64BitProcess || Is64BitOperatingSystemWhen32BitProcess;
 
         public static OperatingSystem OSVersion => s_osVersion.Value;
 
-        public static int ProcessorCount => EnvironmentAugments.ProcessorCount;
-
-        public static string StackTrace
-        {
-            [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts
-            get
-            {
-                return EnvironmentAugments.StackTrace;
-            }
-        }
-
-        public static int TickCount => EnvironmentAugments.TickCount;
-
         public static bool UserInteractive => true;
 
-        public static Version Version
-        {
-            // 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.
-            get { return new Version(4, 0, 30319, 42000); }
-        }
+        // 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.
+        public static Version Version => new Version(4, 0, 30319, 42000);
 
         public static long WorkingSet
         {
@@ -185,9 +139,44 @@ namespace System
                         if (result is long) return (long)result;
                     }
                 }
+
                 // Could not get the current working set.
                 return 0;
             }
         }
+
+        private static bool ValidateAndConvertRegistryTarget(EnvironmentVariableTarget target)
+        {
+            Debug.Assert(target != EnvironmentVariableTarget.Process);
+
+            if (target == EnvironmentVariableTarget.Machine)
+                return true;
+
+            if (target == EnvironmentVariableTarget.User)
+                return false;
+
+            throw new ArgumentOutOfRangeException(nameof(target), target, SR.Format(SR.Arg_EnumIllegalVal, target));
+        }
+
+        private static void ValidateVariableAndValue(string variable, ref string value)
+        {
+            if (variable == null)
+                throw new ArgumentNullException(nameof(variable));
+
+            if (variable.Length == 0)
+                throw new ArgumentException(SR.Argument_StringZeroLength, nameof(variable));
+
+            if (variable[0] == '\0')
+                throw new ArgumentException(SR.Argument_StringFirstCharIsZero, nameof(variable));
+
+            if (variable.Contains('='))
+                throw new ArgumentException(SR.Argument_IllegalEnvVarName, nameof(variable));
+
+            if (string.IsNullOrEmpty(value) || value[0] == '\0')
+            {
+                // Explicitly null out value if it's empty
+                value = null;
+            }
+        }
     }
 }