Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
Utils.cs1867 linesDownload Raw Back to engine
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Concurrent;6using System.Collections.Generic;7using System.Collections.ObjectModel;8using System.Diagnostics.CodeAnalysis;9using System.Globalization;10using System.IO;11using System.Linq;12using System.Management.Automation.Configuration;13using System.Management.Automation.Internal;14using System.Management.Automation.Remoting;15using System.Management.Automation.Security;16using System.Numerics;17using System.Reflection;18using System.Runtime.InteropServices;19using System.Security;20#if !UNIX21using System.Security.Principal;22#endif23using System.Text;24using System.Threading;25using Microsoft.PowerShell.Commands;26using Microsoft.Win32;27 28using TypeTable = System.Management.Automation.Runspaces.TypeTable;29 30namespace System.Management.Automation31{32    /// <summary>33    /// Helper fns.34    /// </summary>35    internal static class Utils36    {37        /// <summary>38        /// Converts a given double value to BigInteger via Math.Round().39        /// </summary>40        /// <param name="d">The value to convert.</param>41        /// <returns>Returns a BigInteger value equivalent to the input value rounded to nearest integer.</returns>42        internal static BigInteger AsBigInt(this double d) => new BigInteger(Math.Round(d));43 44        internal static bool TryCast(BigInteger value, out byte b)45        {46            if (value < byte.MinValue || value > byte.MaxValue)47            {48                b = 0;49                return false;50            }51 52            b = (byte)value;53            return true;54        }55 56        internal static bool TryCast(BigInteger value, out sbyte sb)57        {58            if (value < sbyte.MinValue || value > sbyte.MaxValue)59            {60                sb = 0;61                return false;62            }63 64            sb = (sbyte)value;65            return true;66        }67 68        internal static bool TryCast(BigInteger value, out short s)69        {70            if (value < short.MinValue || value > short.MaxValue)71            {72                s = 0;73                return false;74            }75 76            s = (short)value;77            return true;78        }79 80        internal static bool TryCast(BigInteger value, out ushort us)81        {82            if (value < ushort.MinValue || value > ushort.MaxValue)83            {84                us = 0;85                return false;86            }87 88            us = (ushort)value;89            return true;90        }91 92        internal static bool TryCast(BigInteger value, out int i)93        {94            if (value < int.MinValue || value > int.MaxValue)95            {96                i = 0;97                return false;98            }99 100            i = (int)value;101            return true;102        }103 104        internal static bool TryCast(BigInteger value, out uint u)105        {106            if (value < uint.MinValue || value > uint.MaxValue)107            {108                u = 0;109                return false;110            }111 112            u = (uint)value;113            return true;114        }115 116        internal static bool TryCast(BigInteger value, out long l)117        {118            if (value < long.MinValue || value > long.MaxValue)119            {120                l = 0;121                return false;122            }123 124            l = (long)value;125            return true;126        }127 128        internal static bool TryCast(BigInteger value, out ulong ul)129        {130            if (value < ulong.MinValue || value > ulong.MaxValue)131            {132                ul = 0;133                return false;134            }135 136            ul = (ulong)value;137            return true;138        }139 140        internal static bool TryCast(BigInteger value, out decimal dm)141        {142            if (value < (BigInteger)decimal.MinValue || (BigInteger)decimal.MaxValue < value)143            {144                dm = 0;145                return false;146            }147 148            dm = (decimal)value;149            return true;150        }151 152        internal static bool TryCast(BigInteger value, out double db)153        {154            if (value < (BigInteger)double.MinValue || (BigInteger)double.MaxValue < value)155            {156                db = 0;157                return false;158            }159 160            db = (double)value;161            return true;162        }163 164        /// <summary>165        /// Parses a given string or ReadOnlySpan&lt;char&gt; to calculate its value as a binary number.166        /// Assumes input has already been sanitized and only contains zeroes (0) or ones (1).167        /// </summary>168        /// <param name="digits">Span or string of binary digits. Assumes all digits are either 1 or 0.</param>169        /// <param name="unsigned">170        /// Whether to treat the number as unsigned. When false, respects established conventions171        /// with sign bits for certain input string lengths.172        /// </param>173        /// <returns>Returns the value of the binary string as a BigInteger.</returns>174        internal static BigInteger ParseBinary(ReadOnlySpan<char> digits, bool unsigned)175        {176            if (!unsigned)177            {178                if (digits[0] == '0')179                {180                    unsigned = true;181                }182                else183                {184                    switch (digits.Length)185                    {186                        // Only accept sign bits at these lengths:187                        case 8: // byte188                        case 16: // short189                        case 32: // int190                        case 64: // long191                        case 96: // decimal192                        case int n when n >= 128: // BigInteger193                            break;194                        default:195                            // If we do not flag these as unsigned, bigint assumes a sign bit for any (8 * n) string length196                            unsigned = true;197                            break;198                    }199                }200            }201 202            // Only use heap allocation for very large numbers203            const int MaxStackAllocation = 512;204 205            // Calculate number of 8-bit bytes needed to hold the input,  rounded up to next whole number.206            int outputByteCount = (digits.Length + 7) / 8;207            Span<byte> outputBytes = outputByteCount <= MaxStackAllocation ? stackalloc byte[outputByteCount] : new byte[outputByteCount];208            int outputByteIndex = outputBytes.Length - 1;209 210            // We need to be prepared for any partial leading bytes, (e.g., 010|00000011|00101100), or cases211            // where we only have less than 8 bits to work with from the beginning.212            //213            // Walk bytes right to left, stepping one whole byte at a time (if there are any whole bytes).214            int byteWalker;215            for (byteWalker = digits.Length - 1; byteWalker >= 7; byteWalker -= 8)216            {217                // Use bit shifts and binary-or to sum the values in each byte.  These calculations will218                // create values higher than a single byte, but the higher bits will be stripped out when cast219                // to byte.220                //221                // The low bits are added in separately to allow us to strip the higher 'noise' bits before we222                // sum the values using binary-or.223                //224                // Simplified representation of logic:     (byte)( (7)|(6)|(5)|(4) ) | ( ( (3)|(2)|(1)|(0) ) & 0b1111 )225                //226                // N.B.: This code has been tested against a straight for loop iterating through the byte, and in no227                // circumstance was it faster or more effective than this unrolled version.228                outputBytes[outputByteIndex--] =229                    (byte)(230                        ((digits[byteWalker - 7] << 7)231                        | (digits[byteWalker - 6] << 6)232                        | (digits[byteWalker - 5] << 5)233                        | (digits[byteWalker - 4] << 4)234                        )235                    | (236                        ((digits[byteWalker - 3] << 3)237                        | (digits[byteWalker - 2] << 2)238                        | (digits[byteWalker - 1] << 1)239                        | (digits[byteWalker])240                        ) & 0b1111241                      )242                    );243            }244 245            // With complete bytes parsed, byteWalker is either at the partial byte start index, or at -1246            if (byteWalker >= 0)247            {248                int currentByteValue = 0;249                for (int i = 0; i <= byteWalker; i++)250                {251                    currentByteValue = (currentByteValue << 1) | (digits[i] - '0');252                }253 254                outputBytes[outputByteIndex] = (byte)currentByteValue;255            }256 257            return new BigInteger(outputBytes, isUnsigned: unsigned, isBigEndian: true);258        }259 260        // From System.Web.Util.HashCodeCombiner261        internal static int CombineHashCodes(int h1, int h2)262        {263            return unchecked(((h1 << 5) + h1) ^ h2);264        }265 266        internal static int CombineHashCodes(int h1, int h2, int h3)267        {268            return CombineHashCodes(CombineHashCodes(h1, h2), h3);269        }270 271        internal static int CombineHashCodes(int h1, int h2, int h3, int h4)272        {273            return CombineHashCodes(CombineHashCodes(h1, h2), CombineHashCodes(h3, h4));274        }275 276        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5)277        {278            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), h5);279        }280 281        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6)282        {283            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6));284        }285 286        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7)287        {288            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7));289        }290 291        internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8)292        {293            return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7, h8));294        }295 296        /// <summary>297        /// Allowed PowerShell Editions.298        /// </summary>299        internal static readonly string[] AllowedEditionValues = { "Desktop", "Core" };300 301        /// <summary>302        /// Helper fn to check byte[] arg for null.303        /// </summary>304        /// <param name="arg"> arg to check </param>305        /// <param name="argName"> name of the arg </param>306        /// <returns> Does not return a value.</returns>307        internal static void CheckKeyArg(byte[] arg, string argName)308        {309            if (arg == null)310            {311                throw PSTraceSource.NewArgumentNullException(argName);312            }313            //314            // we use AES algorithm which supports key315            // lengths of 128, 192 and 256 bits.316            // We throw ArgumentException if the key is317            // of any other length318            //319            else if (!((arg.Length == 16) ||320                       (arg.Length == 24) ||321                       (arg.Length == 32)))322            {323                throw PSTraceSource.NewArgumentException(argName, Serialization.InvalidKeyLength, argName);324            }325        }326 327        /// <summary>328        /// Helper fn to check arg for empty or null.329        /// Throws ArgumentNullException on either condition.330        /// </summary>331        /// <param name="arg"> arg to check </param>332        /// <param name="argName"> name of the arg </param>333        /// <returns> Does not return a value.</returns>334        internal static void CheckArgForNullOrEmpty(string arg, string argName)335        {336            if (arg == null)337            {338                throw PSTraceSource.NewArgumentNullException(argName);339            }340            else if (arg.Length == 0)341            {342                throw PSTraceSource.NewArgumentException(argName);343            }344        }345 346        /// <summary>347        /// Helper fn to check arg for null.348        /// Throws ArgumentNullException on either condition.349        /// </summary>350        /// <param name="arg"> arg to check </param>351        /// <param name="argName"> name of the arg </param>352        /// <returns> Does not return a value.</returns>353        internal static void CheckArgForNull(object arg, string argName)354        {355            if (arg == null)356            {357                throw PSTraceSource.NewArgumentNullException(argName);358            }359        }360 361        /// <summary>362        /// Helper fn to check arg for null.363        /// </summary>364        /// <param name="arg"> arg to check </param>365        /// <param name="argName"> name of the arg </param>366        /// <returns> Does not return a value.</returns>367        internal static void CheckSecureStringArg(SecureString arg, string argName)368        {369            if (arg == null)370            {371                throw PSTraceSource.NewArgumentNullException(argName);372            }373        }374 375        internal static string GetStringFromSecureString(SecureString ss)376        {377            IntPtr p = IntPtr.Zero;378            string s = null;379 380            try381            {382                p = Marshal.SecureStringToCoTaskMemUnicode(ss);383                s = Marshal.PtrToStringUni(p);384            }385            finally386            {387                if (p != IntPtr.Zero)388                {389                    Marshal.ZeroFreeCoTaskMemUnicode(p);390                }391            }392 393            return s;394        }395 396        /// <summary>397        /// Gets TypeTable by querying the ExecutionContext stored in398        /// Thread-Local-Storage. This will return null if ExecutionContext399        /// is not available.400        /// </summary>401        /// <returns></returns>402        internal static TypeTable GetTypeTableFromExecutionContextTLS()403        {404            ExecutionContext ecFromTLS = Runspaces.LocalPipeline.GetExecutionContextFromTLS();405            if (ecFromTLS == null)406            {407                return null;408            }409 410            return ecFromTLS.TypeTable;411        }412 413#if !UNIX414        private static string s_pshome = null;415 416        /// <summary>417        /// Get the application base path of the shell from registry.418        /// </summary>419        internal static string GetApplicationBaseFromRegistry(string shellId)420        {421            bool wantPsHome = (object)shellId == (object)DefaultPowerShellShellID;422            if (wantPsHome && s_pshome != null)423                return s_pshome;424 425            string engineKeyPath = RegistryStrings.MonadRootKeyPath + "\\" +426                PSVersionInfo.RegistryVersionKey + "\\" + RegistryStrings.MonadEngineKey;427 428            using (RegistryKey engineKey = Registry.LocalMachine.OpenSubKey(engineKeyPath))429            {430                if (engineKey != null)431                {432                    var result = engineKey.GetValue(RegistryStrings.MonadEngine_ApplicationBase) as string;433                    result = Environment.ExpandEnvironmentVariables(result);434                    if (wantPsHome)435                        Interlocked.CompareExchange(ref s_pshome, null, result);436 437                    return result;438                }439            }440 441            return null;442        }443 444        private static string s_windowsPowerShellVersion = null;445 446        /// <summary>447        /// Get the Windows PowerShell version from registry.448        /// </summary>449        /// <returns>450        /// String of Windows PowerShell version from registry.451        /// </returns>452        internal static string GetWindowsPowerShellVersionFromRegistry()453        {454            if (!string.IsNullOrEmpty(InternalTestHooks.TestWindowsPowerShellVersionString))455            {456                return InternalTestHooks.TestWindowsPowerShellVersionString;457            }458 459            if (s_windowsPowerShellVersion != null)460            {461                return s_windowsPowerShellVersion;462            }463 464            string engineKeyPath = RegistryStrings.MonadRootKeyPath + "\\" +465                PSVersionInfo.RegistryVersionKey + "\\" + RegistryStrings.MonadEngineKey;466 467            using (RegistryKey engineKey = Registry.LocalMachine.OpenSubKey(engineKeyPath))468            {469                if (engineKey != null)470                {471                    s_windowsPowerShellVersion = engineKey.GetValue(RegistryStrings.MonadEngine_MonadVersion) as string;472                    return s_windowsPowerShellVersion;473                }474            }475 476            return string.Empty;477        }478#endif479 480        internal static string DefaultPowerShellAppBase => GetApplicationBase(DefaultPowerShellShellID);481 482        internal static string GetApplicationBase(string shellId)483        {484            // Use the location of SMA.dll as the application base if it exists,485            // otherwise, use the base directory from `AppContext`.486            var baseDirectory = Path.GetDirectoryName(typeof(PSObject).Assembly.Location);487            if (string.IsNullOrEmpty(baseDirectory))488            {489                // Need to remove any trailing directory separator characters490                baseDirectory = AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar);491            }492 493            return baseDirectory;494        }495 496        private static string[] s_productFolderDirectories;497 498        private static string[] GetProductFolderDirectories()499        {500            if (s_productFolderDirectories == null)501            {502                List<string> baseDirectories = new List<string>();503 504                // Retrieve the application base from the registry505                string appBase = Utils.DefaultPowerShellAppBase;506                if (!string.IsNullOrEmpty(appBase))507                {508                    baseDirectories.Add(appBase);509                }510#if !UNIX511                // Now add the two variations of System32512                baseDirectories.Add(Environment.GetFolderPath(Environment.SpecialFolder.System));513                string systemX86 = Environment.GetFolderPath(Environment.SpecialFolder.SystemX86);514                if (!string.IsNullOrEmpty(systemX86))515                {516                    baseDirectories.Add(systemX86);517                }518#endif519                Interlocked.CompareExchange(ref s_productFolderDirectories, baseDirectories.ToArray(), null);520            }521 522            return s_productFolderDirectories;523        }524 525        /// <summary>526        /// Checks if the filePath represents a file under product folder527        /// ie., PowerShell ApplicationBase or $env:windir\system32 or528        /// $env:windir\syswow64.529        /// </summary>530        /// <returns>531        /// true: if the filePath is under product folder532        /// false: otherwise533        /// </returns>534        internal static bool IsUnderProductFolder(string filePath)535        {536            FileInfo fileInfo = new FileInfo(filePath);537            string filename = fileInfo.FullName;538 539            var productFolderDirectories = GetProductFolderDirectories();540            for (int i = 0; i < productFolderDirectories.Length; i++)541            {542                string applicationBase = productFolderDirectories[i];543                if (filename.StartsWith(applicationBase, StringComparison.OrdinalIgnoreCase))544                    return true;545            }546 547            return false;548        }549 550        /// <summary>551        /// Checks if the current process is using WOW.552        /// </summary>553        internal static bool IsRunningFromSysWOW64()554        {555            return DefaultPowerShellAppBase.Contains("SysWOW64");556        }557 558        /// <summary>559        /// Checks if host machine is WinPE.560        /// </summary>561        internal static bool IsWinPEHost()562        {563#if !UNIX564            RegistryKey winPEKey = null;565 566            try567            {568                // The existence of the following registry confirms that the host machine is a WinPE569                // HKLM\System\CurrentControlSet\Control\MiniNT570                winPEKey = Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\MiniNT");571 572                return winPEKey != null;573            }574            catch (ArgumentException) { }575            catch (SecurityException) { }576            catch (ObjectDisposedException) { }577            finally578            {579                winPEKey?.Dispose();580            }581#endif582            return false;583        }584 585        #region Versioning related methods586 587        /// <summary>588        /// Returns current major version of monad ( that is running ) in a string589        /// format.590        /// </summary>591        /// <returns>String.</returns>592        /// <remarks>593        /// Cannot return a Version object as minor number is a requirement for594        /// version object.595        /// </remarks>596        internal static string GetCurrentMajorVersion()597        {598            return PSVersionInfo.PSVersion.Major.ToString(CultureInfo.InvariantCulture);599        }600 601        /// <summary>602        /// Coverts a string to version format.603        /// If the string is of the format x (ie., no dots), then ".0" is appended604        /// to the string.605        /// Version.TryParse will be used to convert the string to a Version606        /// object.607        /// </summary>608        /// <param name="versionString">String representing version.</param>609        /// <returns>A Version Object.</returns>610        internal static Version StringToVersion(string versionString)611        {612            // max of 1 dot is allowed in version613            if (string.IsNullOrEmpty(versionString))614            {615                return null;616            }617 618            int dotCount = 0;619            foreach (char c in versionString)620            {621                if (c == '.')622                {623                    dotCount++;624                    if (dotCount > 1)625                    {626                        break;627                    }628                }629            }630            // Version.TryParse expects the string to be in format: major.minor[.build[.revision]]631            if (dotCount == 0)632            {633                versionString += ".0";634            }635 636            Version result = null;637            if (Version.TryParse(versionString, out result))638            {639                return result;640            }641 642            return null;643        }644 645        /// <summary>646        /// Checks whether current PowerShell session supports edition specified647        /// by checkEdition.648        /// </summary>649        /// <param name="checkEdition">Edition to check.</param>650        /// <returns>True if supported, false otherwise.</returns>651        internal static bool IsPSEditionSupported(string checkEdition)652        {653            return PSVersionInfo.PSEditionValue.Equals(checkEdition, StringComparison.OrdinalIgnoreCase);654        }655 656        /// <summary>657        /// Check whether the current PowerShell session supports any of the specified editions.658        /// </summary>659        /// <param name="editions">The PowerShell editions to check compatibility with.</param>660        /// <returns>True if the edition is supported by this runtime, false otherwise.</returns>661        internal static bool IsPSEditionSupported(IEnumerable<string> editions)662        {663            string currentPSEdition = PSVersionInfo.PSEditionValue;664            foreach (string edition in editions)665            {666                if (currentPSEdition.Equals(edition, StringComparison.OrdinalIgnoreCase))667                {668                    return true;669                }670            }671 672            return false;673        }674 675        /// <summary>676        /// Checks whether the specified edition value is allowed.677        /// </summary>678        /// <param name="editionValue">Edition value to check.</param>679        /// <returns>True if allowed, false otherwise.</returns>680        internal static bool IsValidPSEditionValue(string editionValue)681        {682            return AllowedEditionValues.Contains(editionValue, StringComparer.OrdinalIgnoreCase);683        }684 685        #endregion686 687        /// <summary>688        /// String representing the Default shellID.689        /// </summary>690        internal const string DefaultPowerShellShellID = "Microsoft.PowerShell";691 692        /// <summary>693        /// This is used to construct the profile path.694        /// </summary>695        internal const string ProductNameForDirectory = "PowerShell";696 697        /// <summary>698        /// WSL introduces a new filesystem path to access the Linux filesystem from Windows, like '\\wsl$\ubuntu'.699        /// </summary>700        internal const string WslRootPath = @"\\wsl$";701 702        /// <summary>703        /// The subdirectory of module paths704        /// e.g. ~\Documents\WindowsPowerShell\Modules and %ProgramFiles%\WindowsPowerShell\Modules.705        /// </summary>706        internal static readonly string ModuleDirectory = Path.Combine(ProductNameForDirectory, "Modules");707 708        internal static readonly ConfigScope[] SystemWideOnlyConfig = new[] { ConfigScope.AllUsers };709        internal static readonly ConfigScope[] CurrentUserOnlyConfig = new[] { ConfigScope.CurrentUser };710        internal static readonly ConfigScope[] SystemWideThenCurrentUserConfig = new[] { ConfigScope.AllUsers, ConfigScope.CurrentUser };711        internal static readonly ConfigScope[] CurrentUserThenSystemWideConfig = new[] { ConfigScope.CurrentUser, ConfigScope.AllUsers };712 713        internal static T GetPolicySetting<T>(ConfigScope[] preferenceOrder) where T : PolicyBase, new()714        {715            T policy = null;716#if !UNIX717            // On Windows, group policy settings from registry take precedence.718            // If the requested policy is not defined in registry, we query the configuration file.719            policy = GetPolicySettingFromGPO<T>(preferenceOrder);720            if (policy != null) { return policy; }721#endif722            policy = GetPolicySettingFromConfigFile<T>(preferenceOrder);723            return policy;724        }725 726        private static readonly ConcurrentDictionary<ConfigScope, PowerShellPolicies> s_cachedPoliciesFromConfigFile =727            new ConcurrentDictionary<ConfigScope, PowerShellPolicies>();728 729        /// <summary>730        /// Get a specific kind of policy setting from the configuration file.731        /// </summary>732        private static T GetPolicySettingFromConfigFile<T>(ConfigScope[] preferenceOrder) where T : PolicyBase, new()733        {734            foreach (ConfigScope scope in preferenceOrder)735            {736                PowerShellPolicies policies;737                if (InternalTestHooks.BypassGroupPolicyCaching)738                {739                    policies = PowerShellConfig.Instance.GetPowerShellPolicies(scope);740                }741                else if (!s_cachedPoliciesFromConfigFile.TryGetValue(scope, out policies))742                {743                    // Use lock here to reduce the contention on accessing the configuration file744                    lock (s_cachedPoliciesFromConfigFile)745                    {746                        policies = s_cachedPoliciesFromConfigFile.GetOrAdd(scope, PowerShellConfig.Instance.GetPowerShellPolicies);747                    }748                }749 750                if (policies != null)751                {752                    PolicyBase result = null;753                    switch (typeof(T).Name)754                    {755                        case nameof(ScriptExecution):756                            result = policies.ScriptExecution;757                            break;758                        case nameof(ScriptBlockLogging):759                            result = policies.ScriptBlockLogging;760                            break;761                        case nameof(ModuleLogging):762                            result = policies.ModuleLogging;763                            break;764                        case nameof(ProtectedEventLogging):765                            result = policies.ProtectedEventLogging;766                            break;767                        case nameof(Transcription):768                            result = policies.Transcription;769                            break;770                        case nameof(UpdatableHelp):771                            result = policies.UpdatableHelp;772                            break;773                        case nameof(ConsoleSessionConfiguration):774                            result = policies.ConsoleSessionConfiguration;775                            break;776                        default:777                            Diagnostics.Assert(false, "Should be unreachable code. Update this switch block when new PowerShell policy types are added.");778                            break;779                    }780 781                    if (result != null) { return (T)result; }782                }783            }784 785            return null;786        }787 788#if !UNIX789        private static readonly Dictionary<string, string> GroupPolicyKeys = new Dictionary<string, string>790        {791            {nameof(ScriptExecution), @"Software\Policies\Microsoft\PowerShellCore"},792            {nameof(ScriptBlockLogging), @"Software\Policies\Microsoft\PowerShellCore\ScriptBlockLogging"},793            {nameof(ModuleLogging), @"Software\Policies\Microsoft\PowerShellCore\ModuleLogging"},794            {nameof(ProtectedEventLogging), @"Software\Policies\Microsoft\Windows\EventLog\ProtectedEventLogging"},795            {nameof(Transcription), @"Software\Policies\Microsoft\PowerShellCore\Transcription"},796            {nameof(UpdatableHelp), @"Software\Policies\Microsoft\PowerShellCore\UpdatableHelp"},797            {nameof(ConsoleSessionConfiguration), @"Software\Policies\Microsoft\PowerShellCore\ConsoleSessionConfiguration"}798        };799 800        private static readonly Dictionary<string, string> WindowsPowershellGroupPolicyKeys = new Dictionary<string, string>801        {802            { nameof(ScriptExecution), @"Software\Policies\Microsoft\Windows\PowerShell" },803            { nameof(ScriptBlockLogging), @"Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" },804            { nameof(ModuleLogging), @"Software\Policies\Microsoft\Windows\PowerShell\ModuleLogging" },805            { nameof(Transcription), @"Software\Policies\Microsoft\Windows\PowerShell\Transcription" },806            { nameof(UpdatableHelp), @"Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp" },807        };808 809        private const string PolicySettingFallbackKey = "UseWindowsPowerShellPolicySetting";810 811        private static readonly ConcurrentDictionary<ConfigScope, ConcurrentDictionary<string, PolicyBase>> s_cachedPoliciesFromRegistry =812            new ConcurrentDictionary<ConfigScope, ConcurrentDictionary<string, PolicyBase>>();813 814        private static readonly Func<ConfigScope, ConcurrentDictionary<string, PolicyBase>> s_subCacheCreationDelegate =815            key => new ConcurrentDictionary<string, PolicyBase>(StringComparer.Ordinal);816 817        /// <summary>818        /// Read policy settings from a registry key into a policy object.819        /// </summary>820        /// <param name="instance">Policy object that will be filled with values from registry.</param>821        /// <param name="instanceType">Type of policy object used.</param>822        /// <param name="gpoKey">Registry key that has policy settings.</param>823        /// <returns>True if any property was successfully set on the policy object.</returns>824        private static bool TrySetPolicySettingsFromRegistryKey(object instance, Type instanceType, RegistryKey gpoKey)825        {826            var properties = instanceType.GetProperties(BindingFlags.Instance | BindingFlags.Public);827            bool isAnyPropertySet = false;828 829            string[] valueNames = gpoKey.GetValueNames();830            string[] subKeyNames = gpoKey.GetSubKeyNames();831            var valueNameSet = valueNames.Length > 0 ? new HashSet<string>(valueNames, StringComparer.OrdinalIgnoreCase) : null;832            var subKeyNameSet = subKeyNames.Length > 0 ? new HashSet<string>(subKeyNames, StringComparer.OrdinalIgnoreCase) : null;833 834            // If there are any values or subkeys in the registry key - read them into the policy instance object835            if ((valueNameSet != null) || (subKeyNameSet != null))836            {837                foreach (var property in properties)838                {839                    string settingName = property.Name;840                    object rawRegistryValue = null;841 842                    // Get the raw value from registry.843                    if (valueNameSet != null && valueNameSet.Contains(settingName))844                    {845                        rawRegistryValue = gpoKey.GetValue(settingName);846                    }847                    else if (subKeyNameSet != null && subKeyNameSet.Contains(settingName))848                    {849                        using (RegistryKey subKey = gpoKey.OpenSubKey(settingName))850                        {851                            if (subKey != null)852                            {853                                rawRegistryValue = subKey.GetValueNames();854                            }855                        }856                    }857 858                    // Get the actual property value based on the property type.859                    // If the final property value is not null, then set the property.860                    if (rawRegistryValue != null)861                    {862                        Type propertyType = property.PropertyType;863                        object propertyValue = null;864 865                        switch (propertyType)866                        {867                            case var _ when propertyType == typeof(bool?):868                                if (rawRegistryValue is int rawIntValue)869                                {870                                    if (rawIntValue == 1)871                                    {872                                        propertyValue = true;873                                    }874                                    else if (rawIntValue == 0)875                                    {876                                        propertyValue = false;877                                    }878                                }879 880                                break;881                            case var _ when propertyType == typeof(string):882                                if (rawRegistryValue is string rawStringValue)883                                {884                                    propertyValue = rawStringValue;885                                }886 887                                break;888                            case var _ when propertyType == typeof(string[]):889                                if (rawRegistryValue is string[] rawStringArrayValue)890                                {891                                    propertyValue = rawStringArrayValue;892                                }893                                else if (rawRegistryValue is string stringValue)894                                {895                                    propertyValue = new string[] { stringValue };896                                }897 898                                break;899                            default:900                                throw System.Management.Automation.Interpreter.Assert.Unreachable;901                        }902 903                        // Set the property if the value is not null904                        if (propertyValue != null)905                        {906                            property.SetValue(instance, propertyValue);907                            isAnyPropertySet = true;908                        }909                    }910                }911            }912 913            return isAnyPropertySet;914        }915 916        /// <summary>917        /// The implementation of fetching a specific kind of policy setting from the given configuration scope.918        /// </summary>919        private static T GetPolicySettingFromGPOImpl<T>(ConfigScope scope) where T : PolicyBase, new()920        {921            Type tType = typeof(T);922            // SystemWide scope means 'LocalMachine' root key when query from registry923            RegistryKey rootKey = (scope == ConfigScope.AllUsers) ? Registry.LocalMachine : Registry.CurrentUser;924 925            GroupPolicyKeys.TryGetValue(tType.Name, out string gpoKeyPath);926            Diagnostics.Assert(gpoKeyPath != null, StringUtil.Format("The GPO registry key path should be pre-defined for {0}", tType.Name));927 928            using (RegistryKey gpoKey = rootKey.OpenSubKey(gpoKeyPath))929            {930                // If the corresponding GPO key doesn't exist, return null931                if (gpoKey == null) { return null; }932 933                // The corresponding GPO key exists, then create an instance of T934                // and populate its properties with the settings935                object tInstance = Activator.CreateInstance(tType, nonPublic: true);936                bool isAnyPropertySet = false;937 938                // if PolicySettingFallbackKey is Not set - use PowerShell Core policy reg key939                if ((int)gpoKey.GetValue(PolicySettingFallbackKey, 0) == 0)940                {941                    isAnyPropertySet = TrySetPolicySettingsFromRegistryKey(tInstance, tType, gpoKey);942                }943                else944                {945                    // when PolicySettingFallbackKey flag is set (REG_DWORD "1") use Windows PS policy reg key946                    WindowsPowershellGroupPolicyKeys.TryGetValue(tType.Name, out string winPowershellGpoKeyPath);947                    Diagnostics.Assert(winPowershellGpoKeyPath != null, StringUtil.Format("The Windows PS GPO registry key path should be pre-defined for {0}", tType.Name));948                    using (RegistryKey winPowershellGpoKey = rootKey.OpenSubKey(winPowershellGpoKeyPath))949                    {950                        // If the corresponding Windows PS GPO key doesn't exist, return null951                        if (winPowershellGpoKey == null) { return null; }952                        isAnyPropertySet = TrySetPolicySettingsFromRegistryKey(tInstance, tType, winPowershellGpoKey);953                    }954                }955 956                // If no property is set, then we consider this policy as undefined957                return isAnyPropertySet ? (T)tInstance : null;958            }959        }960 961        /// <summary>962        /// Get a specific kind of policy setting from the group policy registry key.963        /// </summary>964        private static T GetPolicySettingFromGPO<T>(ConfigScope[] preferenceOrder) where T : PolicyBase, new()965        {966            PolicyBase policy = null;967            string policyName = typeof(T).Name;968 969            foreach (ConfigScope scope in preferenceOrder)970            {971                if (InternalTestHooks.BypassGroupPolicyCaching)972                {973                    policy = GetPolicySettingFromGPOImpl<T>(scope);974                }975                else976                {977                    var subordinateCache = s_cachedPoliciesFromRegistry.GetOrAdd(scope, s_subCacheCreationDelegate);978                    if (!subordinateCache.TryGetValue(policyName, out policy))979                    {980                        policy = subordinateCache.GetOrAdd(policyName, key => GetPolicySettingFromGPOImpl<T>(scope));981                    }982                }983 984                if (policy != null) { return (T)policy; }985            }986 987            return null;988        }989#endif990 991        /// <summary>992        /// Scheduled job module name.993        /// </summary>994        internal const string ScheduledJobModuleName = "PSScheduledJob";995 996        internal static void EnsureModuleLoaded(string module, ExecutionContext context)997        {998            if (context != null && !context.AutoLoadingModuleInProgress.Contains(module))999            {1000                List<PSModuleInfo> loadedModules = context.Modules.GetModules(new string[] { module }, false);1001 1002                if ((loadedModules == null) || (loadedModules.Count == 0))1003                {1004                    CommandInfo commandInfo = new CmdletInfo("Import-Module", typeof(Microsoft.PowerShell.Commands.ImportModuleCommand),1005                                                             null, null, context);1006                    var importModuleCommand = new System.Management.Automation.Runspaces.Command(commandInfo);1007 1008                    context.AutoLoadingModuleInProgress.Add(module);1009 1010                    PowerShell ps = null;1011 1012                    try1013                    {1014                        ps = PowerShell.Create(RunspaceMode.CurrentRunspace)1015                            .AddCommand(importModuleCommand)1016                            .AddParameter("Name", module)1017                            .AddParameter("Scope", StringLiterals.Global)1018                            .AddParameter("ErrorAction", ActionPreference.Ignore)1019                            .AddParameter("WarningAction", ActionPreference.Ignore)1020                            .AddParameter("InformationAction", ActionPreference.Ignore)1021                            .AddParameter("Verbose", false)1022                            .AddParameter("Debug", false)1023                            .AddParameter("PassThru");1024 1025                        ps.Invoke<PSModuleInfo>();1026                    }1027                    catch (Exception)1028                    {1029                        // Call-out to user code, catch-all OK1030                    }1031                    finally1032                    {1033                        context.AutoLoadingModuleInProgress.Remove(module);1034                        ps?.Dispose();1035                    }1036                }1037            }1038        }1039 1040        /// <summary>1041        /// Returns modules (either loaded or in available) that match pattern <paramref name="module"/>.1042        /// Uses Get-Module -ListAvailable cmdlet.1043        /// </summary>1044        /// <param name="module"></param>1045        /// <param name="context"></param>1046        /// <returns>1047        /// List of PSModuleInfo's or Null.1048        /// </returns>1049        internal static List<PSModuleInfo> GetModules(string module, ExecutionContext context)1050        {1051            // first look in the loaded modules and then append the modules from gmo -Listavailable1052            // Reason: gmo -li looks only the PSModulepath. There may be cases where a module1053            // is imported directly from a path (that is not in PSModulePath).1054            List<PSModuleInfo> result = context.Modules.GetModules(new string[] { module }, false);1055 1056            CommandInfo commandInfo = new CmdletInfo("Get-Module", typeof(Microsoft.PowerShell.Commands.GetModuleCommand),1057                                                     null, null, context);1058            var getModuleCommand = new System.Management.Automation.Runspaces.Command(commandInfo);1059 1060            PowerShell ps = null;1061            try1062            {1063                ps = PowerShell.Create(RunspaceMode.CurrentRunspace)1064                        .AddCommand(getModuleCommand)1065                        .AddParameter("Name", module)1066                        .AddParameter("ErrorAction", ActionPreference.Ignore)1067                        .AddParameter("WarningAction", ActionPreference.Ignore)1068                        .AddParameter("Verbose", false)1069                        .AddParameter("Debug", false)1070                        .AddParameter("ListAvailable");1071 1072                Collection<PSModuleInfo> gmoOutPut = ps.Invoke<PSModuleInfo>();1073                if (gmoOutPut != null)1074                {1075                    if (result == null)1076                    {1077                        result = gmoOutPut.ToList<PSModuleInfo>();1078                    }1079                    else1080                    {1081                        result.AddRange(gmoOutPut);1082                    }1083                }1084            }1085            catch (Exception)1086            {1087                // Call-out to user code, catch-all OK1088            }1089            finally1090            {1091                ps?.Dispose();1092            }1093 1094            return result;1095        }1096 1097        /// <summary>1098        /// Returns modules (either loaded or in available) that match FullyQualifiedName <paramref name="fullyQualifiedName"/>.1099        /// Uses Get-Module -ListAvailable cmdlet.1100        /// </summary>1101        /// <param name="fullyQualifiedName"></param>1102        /// <param name="context"></param>1103        /// <returns>1104        /// List of PSModuleInfo's or Null.1105        /// </returns>1106        internal static List<PSModuleInfo> GetModules(ModuleSpecification fullyQualifiedName, ExecutionContext context)1107        {1108            // first look in the loaded modules and then append the modules from gmo -Listavailable1109            // Reason: gmo -li looks only the PSModulepath. There may be cases where a module1110            // is imported directly from a path (that is not in PSModulePath).1111            List<PSModuleInfo> result = context.Modules.GetModules(new[] { fullyQualifiedName }, false);1112            CommandInfo commandInfo = new CmdletInfo("Get-Module", typeof(GetModuleCommand),1113                                                     null, null, context);1114            var getModuleCommand = new Runspaces.Command(commandInfo);1115 1116            PowerShell ps = null;1117            try1118            {1119                ps = PowerShell.Create(RunspaceMode.CurrentRunspace)1120                        .AddCommand(getModuleCommand)1121                        .AddParameter("FullyQualifiedName", fullyQualifiedName)1122                        .AddParameter("ErrorAction", ActionPreference.Ignore)1123                        .AddParameter("WarningAction", ActionPreference.Ignore)1124                        .AddParameter("InformationAction", ActionPreference.Ignore)1125                        .AddParameter("Verbose", false)1126                        .AddParameter("Debug", false)1127                        .AddParameter("ListAvailable");1128 1129                Collection<PSModuleInfo> gmoOutput = ps.Invoke<PSModuleInfo>();1130                if (gmoOutput != null)1131                {1132                    if (result == null)1133                    {1134                        result = gmoOutput.ToList();1135                    }1136                    else1137                    {1138                        // append to result1139                        result.AddRange(gmoOutput);1140                    }1141                }1142            }1143            catch (Exception)1144            {1145                // Call-out to user code, catch-all OK1146            }1147            finally1148            {1149                ps?.Dispose();1150            }1151 1152            return result;1153        }1154 1155#if !UNIX1156        private static bool TryGetWindowsCurrentIdentity(out WindowsIdentity currentIdentity)1157        {1158            try1159            {1160                currentIdentity = WindowsIdentity.GetCurrent();1161            }1162            catch (SecurityException)1163            {1164                currentIdentity = null;1165            }1166 1167            return (currentIdentity != null);1168        }1169 1170        /// <summary>1171        /// Gets the current impersonating Windows identity, if any.1172        /// </summary>1173        /// <param name="impersonatedIdentity">Current impersonated Windows identity or null.</param>1174        /// <returns>True if current identity is impersonated.</returns>1175        internal static bool TryGetWindowsImpersonatedIdentity(out WindowsIdentity impersonatedIdentity)1176        {1177            WindowsIdentity currentIdentity;1178            if (TryGetWindowsCurrentIdentity(out currentIdentity) && (currentIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation))1179            {1180                impersonatedIdentity = currentIdentity;1181                return true;1182            }1183 1184            impersonatedIdentity = null;1185            return false;1186        }1187#endif1188 1189        internal static bool IsAdministrator()1190        {1191            // Porting note: only Windows supports the SecurityPrincipal API of .NET. Due to1192            // advanced privilege models, the correct approach on Unix is to assume the user has1193            // permissions, attempt the task, and error gracefully if the task fails due to1194            // permissions. To fit into PowerShell's existing model of preemptively checking1195            // permissions (which cannot be assumed on Unix), we "assume" the user is an1196            // administrator by returning true, thus nullifying this check on Unix.1197#if UNIX1198            return true;1199#else1200            WindowsIdentity currentIdentity;

Showing the first 1,200 of 1867 lines. Download the file for the rest.