Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes308downloads
SessionStateFunctionAPIs.cs792 linesDownload Raw Back to engine
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Management.Automation.Language;7using System.Management.Automation.Runspaces;8using System.Management.Automation.Security;9 10using Dbg = System.Management.Automation.Diagnostics;11 12namespace System.Management.Automation13{14    /// <summary>15    /// Holds the state of a Monad Shell session.16    /// </summary>17    internal sealed partial class SessionStateInternal18    {19        #region Functions20 21        /// <summary>22        /// Add an new SessionState function entry to this session state object...23        /// </summary>24        /// <param name="entry">The entry to add.</param>25        internal void AddSessionStateEntry(SessionStateFunctionEntry entry)26        {27            ScriptBlock sb = entry.ScriptBlock.Clone();28 29            FunctionInfo fn = this.SetFunction(entry.Name, sb, null, entry.Options, false, CommandOrigin.Internal, this.ExecutionContext, entry.HelpFile, true);30            fn.Visibility = entry.Visibility;31            fn.Module = entry.Module;32            fn.ScriptBlock.LanguageMode = entry.ScriptBlock.LanguageMode ?? PSLanguageMode.FullLanguage;33        }34 35        /// <summary>36        /// Gets a flattened view of the functions that are visible using37        /// the current scope as a reference and filtering the functions in38        /// the other scopes based on the scoping rules.39        /// </summary>40        /// <returns>41        /// An IDictionary representing the visible functions.42        /// </returns>43        internal IDictionary<string, FunctionInfo> GetFunctionTable()44        {45            SessionStateScopeEnumerator scopeEnumerator =46                new SessionStateScopeEnumerator(_currentScope);47 48            Dictionary<string, FunctionInfo> result =49                new Dictionary<string, FunctionInfo>(StringComparer.OrdinalIgnoreCase);50 51            foreach (SessionStateScope scope in scopeEnumerator)52            {53                foreach (FunctionInfo entry in scope.FunctionTable.Values)54                {55                    if (!result.ContainsKey(entry.Name))56                    {57                        result.Add(entry.Name, entry);58                    }59                }60            }61 62            return result;63        }64 65        /// <summary>66        /// Gets an IEnumerable for the function table for a given scope.67        /// </summary>68        /// <param name="scopeID">69        /// A scope identifier that is either one of the "special" scopes like70        /// "global", "script", "local", or "private, or a numeric ID of a relative scope71        /// to the current scope.72        /// </param>73        /// <exception cref="ArgumentException">74        /// If <paramref name="scopeID"/> is less than zero, or not75        /// a number and not "script", "global", "local", or "private"76        /// </exception>77        /// <exception cref="ArgumentOutOfRangeException">78        /// If <paramref name="scopeID"/> is less than zero or greater than the number of currently79        /// active scopes.80        /// </exception>81        internal IDictionary<string, FunctionInfo> GetFunctionTableAtScope(string scopeID)82        {83            Dictionary<string, FunctionInfo> result =84                new Dictionary<string, FunctionInfo>(StringComparer.OrdinalIgnoreCase);85 86            SessionStateScope scope = GetScopeByID(scopeID);87 88            foreach (FunctionInfo entry in scope.FunctionTable.Values)89            {90                // Make sure the function/filter isn't private or if it is that the current91                // scope is the same scope the alias was retrieved from.92 93                if ((entry.Options & ScopedItemOptions.Private) == 0 ||94                    scope == _currentScope)95                {96                    result.Add(entry.Name, entry);97                }98            }99 100            return result;101        }102 103        /// <summary>104        /// List of functions/filters to export from this session state object...105        /// </summary>106        internal List<FunctionInfo> ExportedFunctions { get; } = new List<FunctionInfo>();107 108        internal bool UseExportList { get; set; } = false;109 110        /// <summary>111        /// Set to true when module functions are being explicitly exported using Export-ModuleMember.112        /// </summary>113        internal bool FunctionsExported { get; set; }114 115        /// <summary>116        /// Set to true when any processed module functions are being explicitly exported using '*' wildcard.117        /// </summary>118        internal bool FunctionsExportedWithWildcard119        {120            get121            {122                return _functionsExportedWithWildcard;123            }124 125            set126            {127                Dbg.Assert((value), "This property should never be set/reset to false");128                if (value)129                {130                    _functionsExportedWithWildcard = value;131                }132            }133        }134 135        private bool _functionsExportedWithWildcard;136 137        /// <summary>138        /// Set to true if module loading is performed under a manifest that explicitly exports functions (no wildcards)139        /// </summary>140        internal bool ManifestWithExplicitFunctionExport { get; set; }141 142        /// <summary>143        /// Get a functions out of session state.144        /// </summary>145        /// <param name="name">146        /// name of function to look up147        /// </param>148        /// <param name="origin">149        /// Origin of the command that called this API...150        /// </param>151        /// <returns>152        /// The value of the specified function.153        /// </returns>154        /// <exception cref="ArgumentException">155        /// If <paramref name="name"/> is null or empty.156        /// </exception>157        internal FunctionInfo GetFunction(string name, CommandOrigin origin)158        {159            if (string.IsNullOrEmpty(name))160            {161                throw PSTraceSource.NewArgumentException(nameof(name));162            }163 164            FunctionInfo result = null;165 166            FunctionLookupPath lookupPath = new FunctionLookupPath(name);167 168            FunctionScopeItemSearcher searcher =169                new FunctionScopeItemSearcher(this, lookupPath, origin);170 171            if (searcher.MoveNext())172            {173                result = ((IEnumerator<FunctionInfo>)searcher).Current;174            }175 176            return (IsFunctionVisibleInDebugger(result, origin)) ? result : null;177        }178 179        private bool IsFunctionVisibleInDebugger(FunctionInfo fnInfo, CommandOrigin origin)180        {181            // Ensure the returned function item is not exposed across language boundaries when in182            // a debugger breakpoint or nested prompt.183            // A debugger breakpoint/nested prompt has access to all current scoped functions.184            // This includes both running commands from the prompt or via a debugger Action scriptblock.185 186            // Early out.187            // Always allow built-in functions needed for command line debugging.188            if (this.ExecutionContext.LanguageMode == PSLanguageMode.FullLanguage ||189                (fnInfo == null) ||190                (fnInfo.Name.Equals("prompt", StringComparison.OrdinalIgnoreCase)) ||191                (fnInfo.Name.Equals("TabExpansion2", StringComparison.OrdinalIgnoreCase)) ||192                (fnInfo.Name.Equals("Clear-Host", StringComparison.Ordinal)))193            {194                return true;195            }196 197            // Check both InNestedPrompt and Debugger.InBreakpoint to ensure we don't miss a case.198            // Function is not visible if function and context language modes are different.199            var runspace = this.ExecutionContext.CurrentRunspace;200            if ((runspace != null) &&201                (runspace.InNestedPrompt || (runspace.Debugger?.InBreakpoint == true)) &&202                (fnInfo.DefiningLanguageMode.HasValue && (fnInfo.DefiningLanguageMode != this.ExecutionContext.LanguageMode)))203            {204                return false;205            }206 207            return true;208        }209 210        /// <summary>211        /// Get a functions out of session state.212        /// </summary>213        /// <param name="name">214        /// name of function to look up215        /// </param>216        /// <returns>217        /// The value of the specified function.218        /// </returns>219        /// <exception cref="ArgumentException">220        /// If <paramref name="name"/> is null or empty.221        /// </exception>222        internal FunctionInfo GetFunction(string name)223        {224            return GetFunction(name, CommandOrigin.Internal);225        }226 227        private static IEnumerable<string> GetFunctionAliases(IParameterMetadataProvider ipmp)228        {229            if (ipmp == null || ipmp.Body.ParamBlock == null)230                yield break;231 232            var attributes = ipmp.Body.ParamBlock.Attributes;233            foreach (var attributeAst in attributes)234            {235                var attributeType = attributeAst.TypeName.GetReflectionAttributeType();236                if (attributeType == typeof(AliasAttribute))237                {238                    var cvv = new ConstantValueVisitor { AttributeArgument = true };239                    for (int i = 0; i < attributeAst.PositionalArguments.Count; i++)240                    {241                        yield return Compiler.s_attrArgToStringConverter.Target(Compiler.s_attrArgToStringConverter,242                            attributeAst.PositionalArguments[i].Accept(cvv));243                    }244                }245            }246        }247 248        /// <summary>249        /// Set a function in the current scope of session state.250        /// </summary>251        /// <param name="name">252        /// The name of the function to set.253        /// </param>254        /// <param name="function">255        /// The new value of the function being set.256        /// </param>257        /// <param name="origin">258        /// Origin of the caller of this API259        /// </param>260        /// <exception cref="ArgumentException">261        /// If <paramref name="name"/> is null or empty.262        /// </exception>263        /// <exception cref="ArgumentNullException">264        /// If <paramref name="function"/> is null.265        /// </exception>266        /// <exception cref="SessionStateUnauthorizedAccessException">267        /// If the function is read-only or constant.268        /// </exception>269        internal FunctionInfo SetFunctionRaw(270            string name,271            ScriptBlock function,272            CommandOrigin origin)273        {274            if (string.IsNullOrEmpty(name))275            {276                throw PSTraceSource.NewArgumentException(nameof(name));277            }278 279            if (function == null)280            {281                throw PSTraceSource.NewArgumentNullException(nameof(function));282            }283 284            string originalName = name;285 286            FunctionLookupPath path = new FunctionLookupPath(name);287            name = path.UnqualifiedPath;288 289            if (string.IsNullOrEmpty(name))290            {291                SessionStateException exception =292                    new SessionStateException(293                        originalName,294                        SessionStateCategory.Function,295                        "ScopedFunctionMustHaveName",296                        SessionStateStrings.ScopedFunctionMustHaveName,297                        ErrorCategory.InvalidArgument);298 299                throw exception;300            }301 302            ScopedItemOptions options = ScopedItemOptions.None;303            if (path.IsPrivate)304            {305                options |= ScopedItemOptions.Private;306            }307 308            FunctionScopeItemSearcher searcher =309                new FunctionScopeItemSearcher(310                    this,311                    path,312                    origin);313 314            var functionInfo = searcher.InitialScope.SetFunction(name, function, null, options, false, origin, ExecutionContext);315 316            foreach (var aliasName in GetFunctionAliases(function.Ast as IParameterMetadataProvider))317            {318                searcher.InitialScope.SetAliasValue(aliasName, name, ExecutionContext, false, origin);319            }320 321            return functionInfo;322        }323 324        /// <summary>325        /// Set a function in the current scope of session state.326        /// </summary>327        /// <param name="name">328        /// The name of the function to set.329        /// </param>330        /// <param name="function">331        /// The new value of the function being set.332        /// </param>333        /// <param name="originalFunction">334        /// The original function (if any) from which the ScriptBlock is derived.335        /// </param>336        /// <param name="options">337        /// The options to set on the function.338        /// </param>339        /// <param name="force">340        /// If true, the function will be set even if its ReadOnly.341        /// </param>342        /// <param name="origin">343        /// Origin of the caller of this API344        /// </param>345        /// <exception cref="ArgumentException">346        /// If <paramref name="name"/> is null or empty.347        /// </exception>348        /// <exception cref="ArgumentNullException">349        /// If <paramref name="function"/> is null.350        /// </exception>351        /// <exception cref="SessionStateUnauthorizedAccessException">352        /// If the function is read-only or constant.353        /// </exception>354        internal FunctionInfo SetFunction(355            string name,356            ScriptBlock function,357            FunctionInfo originalFunction,358            ScopedItemOptions options,359            bool force,360            CommandOrigin origin)361        {362            return SetFunction(name, function, originalFunction, options, force, origin, ExecutionContext, null);363        }364 365        /// <summary>366        /// Set a function in the current scope of session state.367        /// </summary>368        /// <param name="name">369        /// The name of the function to set.370        /// </param>371        /// <param name="function">372        /// The new value of the function being set.373        /// </param>374        /// <param name="originalFunction">375        /// The original function (if any) from which the ScriptBlock is derived.376        /// </param>377        /// <param name="options">378        /// The options to set on the function.379        /// </param>380        /// <param name="force">381        /// If true, the function will be set even if its ReadOnly.382        /// </param>383        /// <param name="origin">384        /// Origin of the caller of this API385        /// </param>386        /// <param name="helpFile">387        /// The name of the help file associated with the function.388        /// </param>389        /// <exception cref="ArgumentException">390        /// If <paramref name="name"/> is null or empty.391        /// </exception>392        /// <exception cref="ArgumentNullException">393        /// If <paramref name="function"/> is null.394        /// </exception>395        /// <exception cref="SessionStateUnauthorizedAccessException">396        /// If the function is read-only or constant.397        /// </exception>398        internal FunctionInfo SetFunction(399            string name,400            ScriptBlock function,401            FunctionInfo originalFunction,402            ScopedItemOptions options,403            bool force,404            CommandOrigin origin,405            string helpFile)406        {407            return SetFunction(name, function, originalFunction, options, force, origin, ExecutionContext, helpFile, false);408        }409 410        /// <summary>411        /// Set a function in the current scope of session state.412        /// </summary>413        /// <param name="name">414        /// The name of the function to set.415        /// </param>416        /// <param name="function">417        /// The new value of the function being set.418        /// </param>419        /// <param name="originalFunction">420        /// The original function (if any) from which the ScriptBlock is derived.421        /// </param>422        /// <param name="options">423        /// The options to set on the function.424        /// </param>425        /// <param name="force">426        /// If true, the function will be set even if its ReadOnly.427        /// </param>428        /// <param name="origin">429        /// Origin of the caller of this API430        /// </param>431        /// <param name="context">432        /// The execution context for the function.433        /// </param>434        /// <param name="helpFile">435        /// The name of the help file associated with the function.436        /// </param>437        /// <exception cref="ArgumentException">438        /// If <paramref name="name"/> is null or empty.439        /// </exception>440        /// <exception cref="ArgumentNullException">441        /// If <paramref name="function"/> is null.442        /// </exception>443        /// <exception cref="SessionStateUnauthorizedAccessException">444        /// If the function is read-only or constant.445        /// </exception>446        internal FunctionInfo SetFunction(447            string name,448            ScriptBlock function,449            FunctionInfo originalFunction,450            ScopedItemOptions options,451            bool force,452            CommandOrigin origin,453            ExecutionContext context,454            string helpFile)455        {456            return SetFunction(name, function, originalFunction, options, force, origin, context, helpFile, false);457        }458 459        /// <summary>460        /// Set a function in the current scope of session state.461        /// </summary>462        /// <param name="name">463        /// The name of the function to set.464        /// </param>465        /// <param name="function">466        /// The new value of the function being set.467        /// </param>468        /// <param name="originalFunction">469        /// The original function (if any) from which the ScriptBlock is derived.470        /// </param>471        /// <param name="options">472        /// The options to set on the function.473        /// </param>474        /// <param name="force">475        /// If true, the function will be set even if its ReadOnly.476        /// </param>477        /// <param name="origin">478        /// Origin of the caller of this API479        /// </param>480        /// <param name="context">481        /// The execution context for the function.482        /// </param>483        /// <param name="helpFile">484        /// The name of the help file associated with the function.485        /// </param>486        /// <param name="isPreValidated">487        /// Set to true if it is a regular function (meaning, we do not need to check if the script contains JobDefinition Attribute and then process it)488        /// </param>489        /// <exception cref="ArgumentException">490        /// If <paramref name="name"/> is null or empty.491        /// </exception>492        /// <exception cref="ArgumentNullException">493        /// If <paramref name="function"/> is null.494        /// </exception>495        /// <exception cref="SessionStateUnauthorizedAccessException">496        /// If the function is read-only or constant.497        /// </exception>498        internal FunctionInfo SetFunction(499            string name,500            ScriptBlock function,501            FunctionInfo originalFunction,502            ScopedItemOptions options,503            bool force,504            CommandOrigin origin,505            ExecutionContext context,506            string helpFile,507            bool isPreValidated)508        {509            if (string.IsNullOrEmpty(name))510            {511                throw PSTraceSource.NewArgumentException(nameof(name));512            }513 514            if (function == null)515            {516                throw PSTraceSource.NewArgumentNullException(nameof(function));517            }518 519            string originalName = name;520 521            FunctionLookupPath path = new FunctionLookupPath(name);522            name = path.UnqualifiedPath;523 524            if (string.IsNullOrEmpty(name))525            {526                SessionStateException exception =527                    new SessionStateException(528                        originalName,529                        SessionStateCategory.Function,530                        "ScopedFunctionMustHaveName",531                        SessionStateStrings.ScopedFunctionMustHaveName,532                        ErrorCategory.InvalidArgument);533 534                throw exception;535            }536 537            if (path.IsPrivate)538            {539                options |= ScopedItemOptions.Private;540            }541 542            FunctionScopeItemSearcher searcher =543                new FunctionScopeItemSearcher(544                    this,545                    path,546                    origin);547 548            return searcher.InitialScope.SetFunction(name, function, originalFunction, options, force, origin, context, helpFile);549        }550 551        /// <summary>552        /// Set a function in the current scope of session state.553        /// </summary>554        /// <param name="name">555        /// The name of the function to set.556        /// </param>557        /// <param name="function">558        /// The new value of the function being set.559        /// </param>560        /// <param name="originalFunction">561        /// The original function (if any) from which the ScriptBlock is derived.562        /// </param>563        /// <param name="force">564        /// If true, the function will be set even if its ReadOnly.565        /// </param>566        /// <param name="origin">567        /// The origin of the caller568        /// </param>569        /// <exception cref="ArgumentException">570        /// If <paramref name="name"/> is null or empty.571        /// or572        /// If <paramref name="function"/> is not a <see cref="FilterInfo">FilterInfo</see>573        /// or <see cref="FunctionInfo">FunctionInfo</see>574        /// </exception>575        /// <exception cref="ArgumentNullException">576        /// If <paramref name="function"/> is null.577        /// </exception>578        /// <exception cref="SessionStateUnauthorizedAccessException">579        /// If the function is read-only or constant.580        /// </exception>581        internal FunctionInfo SetFunction(582            string name,583            ScriptBlock function,584            FunctionInfo originalFunction,585            bool force,586            CommandOrigin origin)587        {588            if (string.IsNullOrEmpty(name))589            {590                throw PSTraceSource.NewArgumentException(nameof(name));591            }592 593            if (function == null)594            {595                throw PSTraceSource.NewArgumentNullException(nameof(function));596            }597 598            string originalName = name;599 600            FunctionLookupPath path = new FunctionLookupPath(name);601            name = path.UnqualifiedPath;602 603            if (string.IsNullOrEmpty(name))604            {605                SessionStateException exception =606                    new SessionStateException(607                        originalName,608                        SessionStateCategory.Function,609                        "ScopedFunctionMustHaveName",610                        SessionStateStrings.ScopedFunctionMustHaveName,611                        ErrorCategory.InvalidArgument);612 613                throw exception;614            }615 616            ScopedItemOptions options = ScopedItemOptions.None;617            if (path.IsPrivate)618            {619                options |= ScopedItemOptions.Private;620            }621 622            FunctionScopeItemSearcher searcher =623                new FunctionScopeItemSearcher(624                    this,625                    path,626                    origin);627 628            FunctionInfo result = null;629 630            SessionStateScope scope = searcher.InitialScope;631 632            if (searcher.MoveNext())633            {634                scope = searcher.CurrentLookupScope;635                name = searcher.Name;636 637                if (path.IsPrivate)638                {639                    // Need to add the Private flag640                    FunctionInfo existingFunction = scope.GetFunction(name);641                    options |= existingFunction.Options;642                    result = scope.SetFunction(name, function, originalFunction, options, force, origin, ExecutionContext);643                }644                else645                {646                    result = scope.SetFunction(name, function, force, origin, ExecutionContext);647                }648            }649            else650            {651                if (path.IsPrivate)652                {653                    result = scope.SetFunction(name, function, originalFunction, options, force, origin, ExecutionContext);654                }655                else656                {657                    result = scope.SetFunction(name, function, force, origin, ExecutionContext);658                }659            }660 661            return result;662        }663 664        /// <summary>665        /// Set a function in the current scope of session state.666        ///667        /// BUGBUG: this overload is preserved because a lot of tests use reflection to668        /// call it. The tests should be fixed and this API eventually removed.669        /// </summary>670        /// <param name="name">671        /// The name of the function to set.672        /// </param>673        /// <param name="function">674        /// The new value of the function being set.675        /// </param>676        /// <param name="force">677        /// If true, the function will be set even if its ReadOnly.678        /// </param>679        /// <exception cref="ArgumentException">680        /// If <paramref name="name"/> is null or empty.681        /// or682        /// If <paramref name="function"/> is not a <see cref="FilterInfo">FilterInfo</see>683        /// or <see cref="FunctionInfo">FunctionInfo</see>684        /// </exception>685        /// <exception cref="ArgumentNullException">686        /// If <paramref name="function"/> is null.687        /// </exception>688        /// <exception cref="SessionStateUnauthorizedAccessException">689        /// If the function is read-only or constant.690        /// </exception>691        internal FunctionInfo SetFunction(string name, ScriptBlock function, bool force)692        {693            return SetFunction(name, function, null, force, CommandOrigin.Internal);694        }695 696        /// <summary>697        /// Removes a function from the function table.698        /// </summary>699        /// <param name="name">700        /// The name of the function to remove.701        /// </param>702        /// <param name="origin">703        /// THe origin of the caller of this API704        /// </param>705        /// <param name="force">706        /// If true, the function is removed even if it is ReadOnly.707        /// </param>708        /// <exception cref="ArgumentException">709        /// If <paramref name="name"/> is null or empty.710        /// </exception>711        /// <exception cref="SessionStateUnauthorizedAccessException">712        /// If the function is constant.713        /// </exception>714        internal void RemoveFunction(string name, bool force, CommandOrigin origin)715        {716            if (string.IsNullOrEmpty(name))717            {718                throw PSTraceSource.NewArgumentException(nameof(name));719            }720 721            // Use the scope enumerator to find an existing function722 723            SessionStateScope scope = _currentScope;724 725            FunctionLookupPath path = new FunctionLookupPath(name);726 727            FunctionScopeItemSearcher searcher =728                new FunctionScopeItemSearcher(729                    this,730                    path,731                    origin);732 733            if (searcher.MoveNext())734            {735                scope = searcher.CurrentLookupScope;736            }737 738            scope.RemoveFunction(name, force);739        }740 741        /// <summary>742        /// Removes a function from the function table.743        /// </summary>744        /// <param name="name">745        /// The name of the function to remove.746        /// </param>747        /// <param name="force">748        /// If true, the function is removed even if it is ReadOnly.749        /// </param>750        /// <exception cref="ArgumentException">751        /// If <paramref name="name"/> is null or empty.752        /// </exception>753        /// <exception cref="SessionStateUnauthorizedAccessException">754        /// If the function is constant.755        /// </exception>756        internal void RemoveFunction(string name, bool force)757        {758            RemoveFunction(name, force, CommandOrigin.Internal);759        }760 761        /// <summary>762        /// Removes a function from the function table763        /// if the function was imported from the given module.764        ///765        /// BUGBUG: This is only used by the implicit remoting functions...766        /// </summary>767        /// <param name="name">768        /// The name of the function to remove.769        /// </param>770        /// <param name="module">771        /// Module the function might be imported from.772        /// </param>773        /// <exception cref="SessionStateUnauthorizedAccessException">774        /// If the function is constant.775        /// </exception>776        internal void RemoveFunction(string name, PSModuleInfo module)777        {778            Dbg.Assert(module != null, "Caller should verify that module parameter is not null");779 780            FunctionInfo func = GetFunction(name) as FunctionInfo;781            if (func != null && func.ScriptBlock != null782                && func.ScriptBlock.File != null783                && func.ScriptBlock.File.Equals(module.Path, StringComparison.OrdinalIgnoreCase))784            {785                RemoveFunction(name, true);786            }787        }788 789        #endregion Functions790    }791}792