Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
MiscOps.cs3752 linesDownload Raw Back to Operations
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Collections.Specialized;8using System.Globalization;9using System.IO;10using System.Linq;11using System.Management.Automation.Host;12using System.Management.Automation.Internal;13using System.Management.Automation.Internal.Host;14using System.Management.Automation.Language;15using System.Management.Automation.Runspaces;16using System.Management.Automation.Security;17using System.Numerics;18using System.Reflection;19using System.Runtime.CompilerServices;20using System.Text.RegularExpressions;21 22using Microsoft.PowerShell.Commands;23using Microsoft.PowerShell.Commands.Internal.Format;24 25// ReSharper disable UnusedMember.Global26 27namespace System.Management.Automation28{29    internal static class PipelineOps30    {31        private static CommandProcessorBase AddCommand(PipelineProcessor pipe,32                                                       CommandParameterInternal[] commandElements,33                                                       CommandBaseAst commandBaseAst,34                                                       CommandRedirection[] redirections,35                                                       ExecutionContext context)36        {37            var commandAst = commandBaseAst as CommandAst;38            var invocationToken = commandAst != null ? commandAst.InvocationOperator : TokenKind.Unknown;39            bool dotSource = invocationToken == TokenKind.Dot;40            SessionStateInternal commandSessionState = null;41            int commandIndex = 0;42 43            Diagnostics.Assert(commandElements[0].ArgumentSpecified && !commandElements[0].ParameterNameSpecified,44                "Compiler will pass first parameter as an argument.");45            var mi = PSObject.Base(commandElements[0].ArgumentValue) as PSModuleInfo;46            if (mi != null)47            {48                if (mi.ModuleType == ModuleType.Binary && mi.SessionState == null)49                {50                    throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException),51                        null, "CantInvokeInBinaryModule", ParserStrings.CantInvokeInBinaryModule, mi.Name);52                }53                else if (mi.SessionState == null)54                {55                    throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException),56                        null, "CantInvokeInNonImportedModule", ParserStrings.CantInvokeInNonImportedModule, mi.Name);57                }58                else if ((invocationToken == TokenKind.Ampersand || invocationToken == TokenKind.Dot) && mi.LanguageMode != context.LanguageMode)59                {60                    if (SystemPolicy.GetSystemLockdownPolicy() != SystemEnforcementMode.Audit)61                    {62                        // Disallow FullLanguage "& (Get-Module MyModule) MyPrivateFn" from ConstrainedLanguage because it always63                        // runs "internal" origin and so has access to all functions, including non-exported functions.64                        // Otherwise we end up leaking non-exported functions that run in FullLanguage.65                        throw InterpreterError.NewInterpreterException(null, typeof(RuntimeException), null,66                            "CantInvokeCallOperatorAcrossLanguageBoundaries", ParserStrings.CantInvokeCallOperatorAcrossLanguageBoundaries);67                    }68 69                    // In audit mode, report but don't enforce.70                    SystemPolicy.LogWDACAuditMessage(71                        context: context,72                        title: ParserStrings.WDACParserModuleScopeCallOperatorLogTitle,73                        message: ParserStrings.WDACParserModuleScopeCallOperatorLogMessage,74                        fqid: "ModuleScopeCallOperatorNotAllowed",75                        dropIntoDebugger: true);76                }77 78                commandSessionState = mi.SessionState.Internal;79                commandIndex += 1;80            }81 82            object command;83            IScriptExtent commandExtent;84            var cpiCommand = commandElements[commandIndex];85            if (cpiCommand.ParameterNameSpecified)86            {87                command = cpiCommand.ParameterText;88                commandExtent = cpiCommand.ParameterExtent;89                if (cpiCommand.ArgumentSpecified)90                {91                    // BUG: we've seen something like:92                    //     & (gmo Module) -foo: bar93                    // The command is -foo:, and bar is an argument, but both are in commandElements[commandIndex],94                    // so we won't add 'bar' as an argument.95                }96            }97            else98            {99                command = PSObject.Base(cpiCommand.ArgumentValue);100                commandExtent = cpiCommand.ArgumentExtent;101            }102 103            string invocationName = (dotSource) ? "." : invocationToken == TokenKind.Ampersand ? "&" : null;104            CommandProcessorBase commandProcessor;105            var scriptBlock = command as ScriptBlock;106            if (scriptBlock != null)107            {108                commandProcessor = CommandDiscovery.CreateCommandProcessorForScript(scriptBlock, context, !dotSource, commandSessionState);109            }110            else111            {112                var commandInfo = command as CommandInfo;113                if (commandInfo != null)114                {115                    commandProcessor = context.CommandDiscovery.LookupCommandProcessor(commandInfo, context.EngineSessionState.CurrentScope.ScopeOrigin, !dotSource, commandSessionState);116                }117                else118                {119                    var commandName = command as string ?? PSObject.ToStringParser(context, command);120                    invocationName ??= commandName;121 122                    if (string.IsNullOrEmpty(commandName))123                    {124                        throw InterpreterError.NewInterpreterException(125                            command,126                            typeof(RuntimeException),127                            commandExtent,128                            "BadExpression",129                            ParserStrings.BadExpression,130                            dotSource ? "." : "&");131                    }132 133                    try134                    {135                        // See if we need to resolve the command in a different session state136                        // as will be the case with modules...137                        // BUGBUG - this can be cleaned up by fixing the overload on execution context (but not easily.)138                        if (commandSessionState != null)139                        {140                            SessionStateInternal oldSessionState = context.EngineSessionState;141                            try142                            {143                                context.EngineSessionState = commandSessionState;144                                commandProcessor = context.CreateCommand(commandName, dotSource);145                            }146                            finally147                            {148                                context.EngineSessionState = oldSessionState;149                            }150                        }151                        else152                        {153                            commandProcessor = context.CreateCommand(commandName, dotSource);154                        }155                    }156                    catch (RuntimeException rte)157                    {158                        // CreateCommand doesn't have the context to set InvocationInfo properly159                        // so we'll do it here instead...160                        if (rte.ErrorRecord.InvocationInfo == null)161                        {162                            InvocationInfo invocationInfo = new InvocationInfo(null, commandExtent, context)163                            { InvocationName = invocationName };164                            rte.ErrorRecord.SetInvocationInfo(invocationInfo);165                        }166 167                        throw;168                    }169                }170            }171 172            InternalCommand cmd = commandProcessor.Command;173            commandProcessor.UseLocalScope = !dotSource &&174                                             (cmd is ScriptCommand || cmd is PSScriptCmdlet);175 176            bool isNativeCommand = commandProcessor is NativeCommandProcessor;177 178            for (int i = commandIndex + 1; i < commandElements.Length; ++i)179            {180                var cpi = commandElements[i];181 182                if (cpi.ParameterNameSpecified)183                {184                    // Skip adding the special -- parameter unless we're invoking a native command.185                    if (cpi.ParameterName.Equals("-", StringComparison.OrdinalIgnoreCase) && !isNativeCommand)186                    {187                        continue;188                    }189                }190 191                if (cpi.ArgumentToBeSplatted)192                {193                    foreach (var splattedCpi in Splat(cpi.ArgumentValue, cpi.ArgumentAst))194                    {195                        commandProcessor.AddParameter(splattedCpi);196                    }197                }198                else199                {200                    commandProcessor.AddParameter(cpi);201                }202            }203 204            string helpTarget;205            HelpCategory helpCategory;206            if (commandProcessor.IsHelpRequested(out helpTarget, out helpCategory))207            {208                commandProcessor = CommandProcessorBase.CreateGetHelpCommandProcessor(context, helpTarget, helpCategory);209            }210 211            commandProcessor.Command.InvocationExtent = commandBaseAst.Extent;212            commandProcessor.Command.MyInvocation.ScriptPosition = commandBaseAst.Extent;213            commandProcessor.Command.MyInvocation.InvocationName = invocationName;214 215            pipe.Add(commandProcessor);216 217            bool redirectedError = false;218            bool redirectedWarning = false;219            bool redirectedVerbose = false;220            bool redirectedDebug = false;221            bool redirectedInformation = false;222            if (redirections != null)223            {224                if (isNativeCommand)225                {226                    foreach (CommandRedirection redirection in redirections)227                    {228                        if (redirection is MergingRedirection)229                        {230                            redirection.Bind(pipe, commandProcessor, context);231                        }232                    }233                }234 235                foreach (CommandRedirection redirection in redirections)236                {237                    if (!isNativeCommand || redirection is not MergingRedirection)238                    {239                        redirection.Bind(pipe, commandProcessor, context);240                    }241 242                    switch (redirection.FromStream)243                    {244                        case RedirectionStream.Error:245                            redirectedError = true;246                            break;247 248                        case RedirectionStream.Warning:249                            redirectedWarning = true;250                            break;251 252                        case RedirectionStream.Verbose:253                            redirectedVerbose = true;254                            break;255 256                        case RedirectionStream.Debug:257                            redirectedDebug = true;258                            break;259 260                        case RedirectionStream.Information:261                            redirectedInformation = true;262                            break;263 264                        case RedirectionStream.All:265                            redirectedError = true;266                            redirectedWarning = true;267                            redirectedVerbose = true;268                            redirectedDebug = true;269                            redirectedInformation = true;270                            break;271                    }272                }273            }274 275            // Pipe redirection can also be specified via the ExecutionContext pipes.276            if (!redirectedError)277            {278                if (context.ShellFunctionErrorOutputPipe != null)279                {280                    commandProcessor.CommandRuntime.ErrorOutputPipe = context.ShellFunctionErrorOutputPipe;281                }282                else283                {284                    commandProcessor.CommandRuntime.ErrorOutputPipe.ExternalWriter = context.ExternalErrorOutput;285                }286            }287 288            if (!redirectedWarning && (context.ExpressionWarningOutputPipe != null))289            {290                commandProcessor.CommandRuntime.WarningOutputPipe = context.ExpressionWarningOutputPipe;291                redirectedWarning = true;292            }293 294            if (!redirectedVerbose && (context.ExpressionVerboseOutputPipe != null))295            {296                commandProcessor.CommandRuntime.VerboseOutputPipe = context.ExpressionVerboseOutputPipe;297                redirectedVerbose = true;298            }299 300            if (!redirectedDebug && (context.ExpressionDebugOutputPipe != null))301            {302                commandProcessor.CommandRuntime.DebugOutputPipe = context.ExpressionDebugOutputPipe;303                redirectedDebug = true;304            }305 306            if (!redirectedInformation && (context.ExpressionInformationOutputPipe != null))307            {308                commandProcessor.CommandRuntime.InformationOutputPipe = context.ExpressionInformationOutputPipe;309                redirectedInformation = true;310            }311 312            // Warning, Verbose, Debug should pick up any redirection information from its parent command runtime object.313            if (context.CurrentCommandProcessor != null && context.CurrentCommandProcessor.CommandRuntime != null)314            {315                if (!redirectedWarning &&316                    context.CurrentCommandProcessor.CommandRuntime.WarningOutputPipe != null)317                {318                    commandProcessor.CommandRuntime.WarningOutputPipe = context.CurrentCommandProcessor.CommandRuntime.WarningOutputPipe;319                }320 321                if (!redirectedVerbose &&322                    context.CurrentCommandProcessor.CommandRuntime.VerboseOutputPipe != null)323                {324                    commandProcessor.CommandRuntime.VerboseOutputPipe = context.CurrentCommandProcessor.CommandRuntime.VerboseOutputPipe;325                }326 327                if (!redirectedDebug &&328                    context.CurrentCommandProcessor.CommandRuntime.DebugOutputPipe != null)329                {330                    commandProcessor.CommandRuntime.DebugOutputPipe = context.CurrentCommandProcessor.CommandRuntime.DebugOutputPipe;331                }332 333                if (!redirectedInformation &&334                    context.CurrentCommandProcessor.CommandRuntime.InformationOutputPipe != null)335                {336                    commandProcessor.CommandRuntime.InformationOutputPipe = context.CurrentCommandProcessor.CommandRuntime.InformationOutputPipe;337                }338            }339 340            return commandProcessor;341        }342 343        internal static IEnumerable<CommandParameterInternal> Splat(object splattedValue, Ast splatAst)344        {345            splattedValue = PSObject.Base(splattedValue);346 347            var markUntrustedData = false;348            if (ExecutionContext.HasEverUsedConstrainedLanguage)349            {350                // If the value to be splatted is untrusted, then make sure sub-values held by it are351                // also marked as untrusted.352                markUntrustedData = ExecutionContext.IsMarkedAsUntrusted(splattedValue);353            }354 355            IDictionary splattedTable = splattedValue as IDictionary;356            if (splattedTable != null)357            {358                foreach (DictionaryEntry de in splattedTable)359                {360                    string parameterName = de.Key.ToString();361                    object parameterValue = de.Value;362                    string parameterText = GetParameterText(parameterName);363 364                    if (markUntrustedData)365                    {366                        ExecutionContext.MarkObjectAsUntrusted(parameterValue);367                    }368 369                    yield return CommandParameterInternal.CreateParameterWithArgument(370                        parameterAst: splatAst,371                        parameterName: parameterName,372                        parameterText: parameterText,373                        argumentAst: splatAst,374                        value: parameterValue,375                        spaceAfterParameter: false,376                        fromSplatting: true);377                }378            }379            else380            {381                IEnumerable enumerableValue = splattedValue as IEnumerable;382                if (enumerableValue != null)383                {384                    foreach (object obj in enumerableValue)385                    {386                        if (markUntrustedData)387                        {388                            ExecutionContext.MarkObjectAsUntrusted(obj);389                        }390 391                        yield return SplatEnumerableElement(obj, splatAst);392                    }393                }394                else395                {396                    yield return SplatEnumerableElement(splattedValue, splatAst);397                }398            }399        }400 401        private static CommandParameterInternal SplatEnumerableElement(object splattedArgument, Ast splatAst)402        {403            var psObject = splattedArgument as PSObject;404            if (psObject != null)405            {406                var prop = psObject.Properties[ScriptParameterBinderController.NotePropertyNameForSplattingParametersInArgs];407                var baseObj = psObject.BaseObject;408                if (prop != null && prop.Value is string && baseObj is string)409                {410                    return CommandParameterInternal.CreateParameter((string)prop.Value, (string)baseObj, splatAst);411                }412            }413 414            return CommandParameterInternal.CreateArgument(splattedArgument, splatAst);415        }416 417        private static string GetParameterText(string parameterName)418        {419            Diagnostics.Assert(parameterName != null, "caller makes sure the parameterName is not null");420            int endPosition = parameterName.Length;421            while ((endPosition > 0) && char.IsWhiteSpace(parameterName[endPosition - 1]))422            {423                endPosition--;424            }425 426            if (endPosition == 0 || parameterName[endPosition - 1] == ':')427            {428                return "-" + parameterName;429            }430 431            string parameterText;432            if (endPosition == parameterName.Length)433            {434                parameterText = "-" + parameterName + ":";435            }436            else437            {438                string whitespaces = parameterName.Substring(endPosition);439                parameterText = string.Concat("-", parameterName.AsSpan(0, endPosition), ":", whitespaces);440            }441 442            return parameterText;443        }444 445        internal static void InvokePipeline(object input,446                                            bool ignoreInput,447                                            CommandParameterInternal[][] pipeElements,448                                            CommandBaseAst[] pipeElementAsts,449                                            CommandRedirection[][] commandRedirections,450                                            FunctionContext funcContext)451        {452            PipelineProcessor pipelineProcessor = new PipelineProcessor();453            ExecutionContext context = funcContext._executionContext;454            Pipe outputPipe = funcContext._outputPipe;455 456            try457            {458                context.Events?.ProcessPendingActions();459 460                if (input == AutomationNull.Value && !ignoreInput)461                {462                    // We have seen something like:463                    //    $e | measure-object464                    // And $e is AutomationNull.Value.  We want to ensure465                    // measure-object runs w/o sending anything through the pipe,466                    // so we'll turn the pipe into Out-Null | ...467                    // This cleanly avoids any problems with the pipeline processing468                    // code dealing with null/AutomationNull input going directly to469                    // the first command (e.g. Measure-Object).470                    AddNoopCommandProcessor(pipelineProcessor, context);471                }472 473                CommandProcessorBase commandProcessor = null;474                CommandRedirection[] commandRedirection = null;475 476                for (int i = 0; i < pipeElements.Length; i++)477                {478                    commandRedirection = commandRedirections?[i];479                    commandProcessor = AddCommand(pipelineProcessor, pipeElements[i], pipeElementAsts[i],480                                                  commandRedirection, context);481                }482 483                var cmdletInfo = commandProcessor?.CommandInfo as CmdletInfo;484                if (cmdletInfo?.ImplementingType == typeof(OutNullCommand))485                {486                    var commandsCount = pipelineProcessor.Commands.Count;487                    if (commandsCount == 1)488                    {489                        // Out-Null is the only command, bail without running anything490                        return;491                    }492 493                    // Out-Null is the last command, rewrite command before Out-Null to a null pipe, but494                    // only if it didn't redirect anything, e.g. `Get-Stuff > o.txt | Out-Null`495                    var nextToLastCommand = pipelineProcessor.Commands[commandsCount - 2];496                    if (!nextToLastCommand.CommandRuntime.OutputPipe.IsRedirected)497                    {498                        pipelineProcessor.Commands.RemoveAt(commandsCount - 1);499                        commandProcessor = nextToLastCommand;500                        nextToLastCommand.CommandRuntime.OutputPipe = new Pipe { NullPipe = true };501                    }502                }503 504                if (commandProcessor != null && !commandProcessor.CommandRuntime.OutputPipe.IsRedirected)505                {506                    pipelineProcessor.LinkPipelineSuccessOutput(outputPipe ?? new Pipe(new List<object>()));507 508                    // Fix up merge redirection bindings on last command processor.509                    if (commandRedirection != null)510                    {511                        foreach (CommandRedirection redirection in commandRedirection)512                        {513                            if (redirection is MergingRedirection)514                            {515                                redirection.Bind(pipelineProcessor, commandProcessor, context);516                            }517                        }518                    }519                }520 521                context.PushPipelineProcessor(pipelineProcessor);522                try523                {524                    pipelineProcessor.SynchronousExecuteEnumerate(input);525                }526                finally527                {528                    context.PopPipelineProcessor(false);529                }530            }531            finally532            {533                context.QuestionMarkVariableValue = !pipelineProcessor.ExecutionFailed;534                pipelineProcessor.Dispose();535            }536        }537 538        internal static void InvokePipelineInBackground(539                                            PipelineBaseAst pipelineAst,540                                            FunctionContext funcContext)541        {542            PipelineProcessor pipelineProcessor = new PipelineProcessor();543            ExecutionContext context = funcContext._executionContext;544            Pipe outputPipe = funcContext._outputPipe;545 546            try547            {548                context.Events?.ProcessPendingActions();549 550                CommandProcessorBase commandProcessor = null;551 552                // For background jobs rewrite the pipeline as a Start-Job command553                var scriptblockBodyString = pipelineAst.Extent.Text;554                var pipelineOffset = pipelineAst.Extent.StartOffset;555                var variables = pipelineAst.FindAll(static x => x is VariableExpressionAst, true);556 557                // Minimize allocations by initializing the stringbuilder to the size of the source string + space for ${using:} * 2558                System.Text.StringBuilder updatedScriptblock = new System.Text.StringBuilder(scriptblockBodyString.Length + 18);559                int position = 0;560 561                // Prefix variables in the scriptblock with $using:562                foreach (var v in variables)563                {564                    var variableName = ((VariableExpressionAst)v).VariablePath.UserPath;565 566                    // Skip variables that don't exist567                    if (funcContext._executionContext.EngineSessionState.GetVariable(variableName) == null)568                    {569                        continue;570                    }571 572                    // Skip PowerShell magic variables573                    if (!Regex.Match(574                            variableName,575                            "^(global:){0,1}(PID|PSVersionTable|PSEdition|PSHOME|HOST|TRUE|FALSE|NULL)$",576                            RegexOptions.IgnoreCase | RegexOptions.CultureInvariant).Success)577                    {578                        updatedScriptblock.Append(scriptblockBodyString.AsSpan(position, v.Extent.StartOffset - pipelineOffset - position));579                        updatedScriptblock.Append("${using:");580                        updatedScriptblock.Append(CodeGeneration.EscapeVariableName(variableName));581                        updatedScriptblock.Append('}');582                        position = v.Extent.EndOffset - pipelineOffset;583                    }584                }585 586                updatedScriptblock.Append(scriptblockBodyString.AsSpan(position));587                var sb = ScriptBlock.Create(updatedScriptblock.ToString());588                var commandInfo = new CmdletInfo("Start-Job", typeof(StartJobCommand));589                commandProcessor = context.CommandDiscovery.LookupCommandProcessor(commandInfo, CommandOrigin.Internal, false, context.EngineSessionState);590 591                var workingDirectoryParameter = CommandParameterInternal.CreateParameterWithArgument(592                    parameterAst: pipelineAst,593                    parameterName: "WorkingDirectory",594                    parameterText: null,595                    argumentAst: pipelineAst,596                    value: context.SessionState.Path.CurrentLocation.Path,597                    spaceAfterParameter: false);598 599                var scriptBlockParameter = CommandParameterInternal.CreateParameterWithArgument(600                    parameterAst: pipelineAst,601                    parameterName: "ScriptBlock",602                    parameterText: null,603                    argumentAst: pipelineAst,604                    value: sb,605                    spaceAfterParameter: false);606 607                commandProcessor.AddParameter(workingDirectoryParameter);608                commandProcessor.AddParameter(scriptBlockParameter);609                pipelineProcessor.Add(commandProcessor);610                pipelineProcessor.LinkPipelineSuccessOutput(outputPipe ?? new Pipe(new List<object>()));611 612                context.PushPipelineProcessor(pipelineProcessor);613                try614                {615                    pipelineProcessor.SynchronousExecuteEnumerate(AutomationNull.Value);616                }617                finally618                {619                    context.PopPipelineProcessor(false);620                }621            }622            finally623            {624                context.QuestionMarkVariableValue = !pipelineProcessor.ExecutionFailed;625                pipelineProcessor.Dispose();626            }627        }628 629        private static void AddNoopCommandProcessor(PipelineProcessor pipelineProcessor, ExecutionContext context)630        {631            var commandInfo = new CmdletInfo("Out-Null", typeof(OutNullCommand));632            var commandProcessor = context.CommandDiscovery.LookupCommandProcessor(commandInfo,633                                                                                   context.EngineSessionState.CurrentScope.ScopeOrigin,634                                                                                   useLocalScope: false,635                                                                                   sessionState: null);636            pipelineProcessor.Add(commandProcessor);637        }638 639        internal static object CheckAutomationNullInCommandArgument(object obj)640        {641            if (obj == AutomationNull.Value)642            {643                return null;644            }645 646            var objAsArray = obj as object[];647            return objAsArray != null ? CheckAutomationNullInCommandArgumentArray(objAsArray) : obj;648        }649 650        internal static object[] CheckAutomationNullInCommandArgumentArray(object[] objArray)651        {652            if (objArray != null)653            {654                for (int i = 0; i < objArray.Length; ++i)655                {656                    if (objArray[i] == AutomationNull.Value)657                    {658                        objArray[i] = null;659                    }660                }661            }662 663            return objArray;664        }665 666        internal static SteppablePipeline GetSteppablePipeline(PipelineAst pipelineAst, CommandOrigin commandOrigin, ScriptBlock scriptBlock, object[] args)667        {668            var pipelineProcessor = new PipelineProcessor();669            var commandTuples = new List<Tuple<CommandAst, List<CommandParameterInternal>, List<CommandRedirection>>>();670 671            ExecutionContext context = LocalPipeline.GetExecutionContextFromTLS();672            if (context == null)673            {674                // If ExecutionContext from TLS is null then we are not in powershell engine thread.675                string scriptText = scriptBlock.ToString();676                scriptText = ErrorCategoryInfo.Ellipsize(CultureInfo.CurrentUICulture, scriptText);677 678                PSInvalidOperationException e = PSTraceSource.NewInvalidOperationException(679                    ParserStrings.GetSteppablePipelineFromWrongThread,680                    scriptText);681 682                e.SetErrorId("GetSteppablePipelineFromWrongThread");683                throw e;684            }685 686            // We try binding the parameter when following conditions are satisfied:687            //   * Arguments are provided688            //   * The ScriptBlock has parameters689            // If the script block has no parameter, RuntimeDefinedParameters.Data will be set to RuntimeDefinedParameterDictionary.EmptyParameterArray690            bool useParameter = (args != null && args.Length > 0) &&691                                scriptBlock.RuntimeDefinedParameters.Data !=692                                RuntimeDefinedParameterDictionary.EmptyParameterArray;693            try694            {695                if (useParameter)696                {697                    // If any parameters are used, we create a new scope and bind the parameters.698 699                    var newScope = context.EngineSessionState.NewScope(false);700                    context.EngineSessionState.CurrentScope = newScope;701                    context.EngineSessionState.CurrentScope.ScopeOrigin = CommandOrigin.Internal;702 703                    var locals = MutableTuple.MakeTuple(Compiler.DottedLocalsTupleType,704                                                        Compiler.DottedLocalsNameIndexMap);705                    object[] remainingArgs =706                        ScriptBlock.BindArgumentsForScriptblockInvoke(707                            (RuntimeDefinedParameter[])scriptBlock.RuntimeDefinedParameters.Data,708                            args, context, false, null, locals);709                    locals.SetAutomaticVariable(AutomaticVariable.Args, remainingArgs, context);710                    newScope.LocalsTuple = locals;711                }712 713                // GetSteppablePipeline() is called on an arbitrary script block with the intention714                // of invoking it. So the trustworthiness is defined by the trustworthiness of the715                // script block's language mode.716                bool isTrusted = scriptBlock.LanguageMode == PSLanguageMode.FullLanguage;717                if (scriptBlock.LanguageMode == PSLanguageMode.ConstrainedLanguage718                    && SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Audit)719                {720                    // In audit mode, report but don't enforce.721                    isTrusted = true;722                    SystemPolicy.LogWDACAuditMessage(723                        context: context,724                        title: ParserStrings.WDACGetSteppablePipelineLogTitle,725                        message: ParserStrings.WDACGetSteppablePipelineLogMessage,726                        fqid: "GetSteppablePipelineMayFail",727                        dropIntoDebugger: true);728                }729 730                foreach (var commandAst in pipelineAst.PipelineElements.Cast<CommandAst>())731                {732                    var commandParameters = new List<CommandParameterInternal>();733                    foreach (var commandElement in commandAst.CommandElements)734                    {735                        var commandParameterAst = commandElement as CommandParameterAst;736                        if (commandParameterAst != null)737                        {738                            commandParameters.Add(GetCommandParameter(commandParameterAst, isTrusted, context));739                            continue;740                        }741 742                        var exprAst = (ExpressionAst)commandElement;743                        var argument = Compiler.GetExpressionValue(exprAst, isTrusted, context);744                        var splatting = exprAst is VariableExpressionAst && ((VariableExpressionAst)exprAst).Splatted;745                        commandParameters.Add(CommandParameterInternal.CreateArgument(argument, exprAst, splatting));746                    }747 748                    var redirections = new List<CommandRedirection>();749                    foreach (var redirection in commandAst.Redirections)750                    {751                        redirections.Add(GetCommandRedirection(redirection, isTrusted, context));752                    }753 754                    commandTuples.Add(Tuple.Create(commandAst, commandParameters, redirections));755                }756            }757            finally758            {759                if (useParameter)760                {761                    context.EngineSessionState.RemoveScope(context.EngineSessionState.CurrentScope);762                }763            }764 765            foreach (var commandTuple in commandTuples)766            {767                var commandProcessor = AddCommand(pipelineProcessor, commandTuple.Item2.ToArray(), commandTuple.Item1, commandTuple.Item3.ToArray(), context);768                commandProcessor.Command.CommandOriginInternal = commandOrigin;769                commandProcessor.CommandScope.ScopeOrigin = commandOrigin;770                commandProcessor.Command.MyInvocation.CommandOrigin = commandOrigin;771 772                // For nicer error reporting, we want to make it look like errors in the steppable pipeline point back to773                // the caller of the proxy.  We don't want errors pointing to the script block created in the proxy.774                // Here we assume (in a safe way) that GetSteppablePipeline is called from script.  If that isn't the case,775                // we won't crash, but the error reporting might be a little misleading.776                var callStack = context.Debugger.GetCallStack().ToArray();777                if (callStack.Length > 0 && Regex.IsMatch(callStack[0].Position.Text, "GetSteppablePipeline", RegexOptions.IgnoreCase))778                {779                    var myInvocation = commandProcessor.Command.MyInvocation;780                    myInvocation.InvocationName = callStack[0].InvocationInfo.InvocationName;781                    if (callStack.Length > 1)782                    {783                        var displayPosition = callStack[1].Position;784                        if (displayPosition != null && displayPosition != PositionUtilities.EmptyExtent)785                        {786                            myInvocation.DisplayScriptPosition = displayPosition;787                        }788                    }789                }790 791                // Set the data stream merge properties based on ExecutionContext.792                if (context.CurrentCommandProcessor != null && context.CurrentCommandProcessor.CommandRuntime != null)793                {794                    commandProcessor.CommandRuntime.SetMergeFromRuntime(context.CurrentCommandProcessor.CommandRuntime);795                }796            }797 798            return new SteppablePipeline(context, pipelineProcessor);799        }800 801        private static CommandParameterInternal GetCommandParameter(CommandParameterAst commandParameterAst, bool isTrusted, ExecutionContext context)802        {803            var argumentAst = commandParameterAst.Argument;804            var errorPos = commandParameterAst.ErrorPosition;805 806            if (argumentAst == null)807            {808                return CommandParameterInternal.CreateParameter(commandParameterAst.ParameterName, errorPos.Text, commandParameterAst);809            }810 811            object argumentValue = Compiler.GetExpressionValue(argumentAst, isTrusted, context);812            bool spaceAfterParameter = errorPos.EndLineNumber != argumentAst.Extent.StartLineNumber ||813                                       errorPos.EndColumnNumber != argumentAst.Extent.StartColumnNumber;814            return CommandParameterInternal.CreateParameterWithArgument(commandParameterAst, commandParameterAst.ParameterName,815                                                                        errorPos.Text, argumentAst, argumentValue,816                                                                        spaceAfterParameter);817        }818 819        private static CommandRedirection GetCommandRedirection(RedirectionAst redirectionAst, bool isTrusted, ExecutionContext context)820        {821            var fileRedirection = redirectionAst as FileRedirectionAst;822            if (fileRedirection != null)823            {824                object fileName = Compiler.GetExpressionValue(fileRedirection.Location, isTrusted, context);825                return new FileRedirection(fileRedirection.FromStream, fileRedirection.Append, fileName.ToString());826            }827 828            var mergingRedirectionAst = (MergingRedirectionAst)redirectionAst;829            return new MergingRedirection(mergingRedirectionAst.FromStream, mergingRedirectionAst.ToStream);830        }831 832        internal static object PipelineResult(List<object> resultList)833        {834            var resultCount = resultList.Count;835            if (resultCount == 0)836            {837                return AutomationNull.Value;838            }839 840            var result = resultCount == 1 ? resultList[0] : resultList.ToArray();841            // Clear the array list so that we don't write the results of the pipe when flushing the pipe.842            resultList.Clear();843            return result;844        }845 846        internal static void FlushPipe(Pipe oldPipe, List<object> resultList)847        {848            for (int i = 0; i < resultList.Count; i++)849            {850                oldPipe.Add(resultList[i]);851            }852        }853 854        internal static void ClearPipe(List<object> resultList)855        {856            resultList.Clear();857        }858 859        internal static ExitException GetExitException(object exitCodeObj)860        {861            int exitCode = 0;862 863            try864            {865                if (!LanguagePrimitives.IsNull(exitCodeObj))866                {867                    exitCode = ParserOps.ConvertTo<int>(exitCodeObj, PositionUtilities.EmptyExtent);868                }869            }870            catch (Exception) // ignore non-severe exceptions871            {872            }873 874            return new ExitException(exitCode);875        }876 877        internal static void CheckForInterrupts(ExecutionContext context)878        {879            context.Events?.ProcessPendingActions();880 881            if (context.CurrentPipelineStopping)882            {883                throw new PipelineStoppedException();884            }885        }886 887        // This is to work around a DLR problem with gotos in try/catch to the end of a lambda.888        internal static void Nop() { }889    }890 891    #region Redirections892 893    internal abstract class CommandRedirection894    {895        protected CommandRedirection(RedirectionStream from)896        {897            this.FromStream = from;898        }899 900        internal RedirectionStream FromStream { get; }901 902        internal abstract void Bind(PipelineProcessor pipelineProcessor, CommandProcessorBase commandProcessor, ExecutionContext context);903 904        internal void UnbindForExpression(FunctionContext funcContext, Pipe[] pipes)905        {906            if (pipes == null)907            {908                // The pipes can be null if there was an exception (ideally we'd just call unbind909                // from a fault, but that isn't supported in a clr dynamic method.910                return;911            }912 913            var context = funcContext._executionContext;914            switch (FromStream)915            {916                case RedirectionStream.All:917                    funcContext._outputPipe = pipes[(int)RedirectionStream.Output];918                    context.ShellFunctionErrorOutputPipe = pipes[(int)RedirectionStream.Error];919                    context.ExpressionWarningOutputPipe = pipes[(int)RedirectionStream.Warning];920                    context.ExpressionVerboseOutputPipe = pipes[(int)RedirectionStream.Verbose];921                    context.ExpressionDebugOutputPipe = pipes[(int)RedirectionStream.Debug];922                    context.ExpressionInformationOutputPipe = pipes[(int)RedirectionStream.Information];923                    break;924                case RedirectionStream.Output:925                    funcContext._outputPipe = pipes[(int)RedirectionStream.Output];926                    break;927                case RedirectionStream.Error:928                    context.ShellFunctionErrorOutputPipe = pipes[(int)FromStream];929                    break;930                case RedirectionStream.Warning:931                    context.ExpressionWarningOutputPipe = pipes[(int)FromStream];932                    break;933                case RedirectionStream.Verbose:934                    context.ExpressionVerboseOutputPipe = pipes[(int)FromStream];935                    break;936                case RedirectionStream.Debug:937                    context.ExpressionDebugOutputPipe = pipes[(int)FromStream];938                    break;939                case RedirectionStream.Information:940                    context.ExpressionInformationOutputPipe = pipes[(int)FromStream];941                    break;942            }943        }944    }945 946    internal class MergingRedirection : CommandRedirection947    {948        internal MergingRedirection(RedirectionStream from, RedirectionStream to)949            : base(from)950        {951            if (to != RedirectionStream.Output)952            {953                throw InterpreterError.NewInterpreterException(to, typeof(ArgumentException),954                                               null, "RedirectionStreamCanOnlyMergeToOutputStream",955                                               ParserStrings.RedirectionStreamCanOnlyMergeToOutputStream);956            }957 958            // this.ToStream = to;959        }960 961        public override string ToString()962        {963            return FromStream == RedirectionStream.All964                       ? "*>&1"965                       : string.Create(CultureInfo.InvariantCulture, $"{(int)FromStream}>&1");966        }967 968        // private RedirectionStream ToStream { get; set; }969 970        // Handle merging redirections for commands, like:971        //   dir 2>&1972        // A more realistic example:973        //   dir 2>&1 > out974        internal override void Bind(PipelineProcessor pipelineProcessor, CommandProcessorBase commandProcessor, ExecutionContext context)975        {976            Pipe pipe = commandProcessor.CommandRuntime.OutputPipe;977 978            switch (FromStream)979            {980                case RedirectionStream.All:981                    commandProcessor.CommandRuntime.ErrorMergeTo = MshCommandRuntime.MergeDataStream.Output;982                    commandProcessor.CommandRuntime.WarningOutputPipe = pipe;983                    commandProcessor.CommandRuntime.VerboseOutputPipe = pipe;984                    commandProcessor.CommandRuntime.DebugOutputPipe = pipe;985                    commandProcessor.CommandRuntime.InformationOutputPipe = pipe;986                    break;987                case RedirectionStream.Output:988                    break;989                case RedirectionStream.Error:990                    commandProcessor.CommandRuntime.ErrorMergeTo = MshCommandRuntime.MergeDataStream.Output;991                    break;992                case RedirectionStream.Warning:993                    commandProcessor.CommandRuntime.WarningOutputPipe = pipe;994                    break;995                case RedirectionStream.Verbose:996                    commandProcessor.CommandRuntime.VerboseOutputPipe = pipe;997                    break;998                case RedirectionStream.Debug:999                    commandProcessor.CommandRuntime.DebugOutputPipe = pipe;1000                    break;1001                case RedirectionStream.Information:1002                    commandProcessor.CommandRuntime.InformationOutputPipe = pipe;1003                    break;1004            }1005        }1006 1007        // Handle merging redirections for expressions, like:1008        //   $(write-error) 2>&11009        // A more realistic example:1010        //   $(write-error) 2>&1 > out1011        internal Pipe[] BindForExpression(ExecutionContext context, FunctionContext funcContext)1012        {1013            Pipe[] oldPipes = new Pipe[(int)RedirectionStream.Information + 1];1014            Pipe pipe = funcContext._outputPipe;1015 1016            // We set the redirection pipe directly in Context because there is no command processor1017            // (which indirectly does the same thing as this code.)1018 1019            switch (FromStream)1020            {1021                case RedirectionStream.All:1022                    oldPipes[(int)RedirectionStream.Output] = funcContext._outputPipe;1023                    oldPipes[(int)RedirectionStream.Error] = context.ShellFunctionErrorOutputPipe;1024                    context.ShellFunctionErrorOutputPipe = pipe;1025                    oldPipes[(int)RedirectionStream.Warning] = context.ExpressionWarningOutputPipe;1026                    context.ExpressionWarningOutputPipe = pipe;1027                    oldPipes[(int)RedirectionStream.Verbose] = context.ExpressionVerboseOutputPipe;1028                    context.ExpressionVerboseOutputPipe = pipe;1029                    oldPipes[(int)RedirectionStream.Debug] = context.ExpressionDebugOutputPipe;1030                    context.ExpressionDebugOutputPipe = pipe;1031                    oldPipes[(int)RedirectionStream.Information] = context.ExpressionInformationOutputPipe;1032                    context.ExpressionInformationOutputPipe = pipe;1033                    break;1034                case RedirectionStream.Output:1035                    oldPipes[(int)RedirectionStream.Output] = funcContext._outputPipe;1036                    break;1037                case RedirectionStream.Error:1038                    oldPipes[(int)FromStream] = context.ShellFunctionErrorOutputPipe;1039                    context.ShellFunctionErrorOutputPipe = pipe;1040                    break;1041                case RedirectionStream.Warning:1042                    oldPipes[(int)FromStream] = context.ExpressionWarningOutputPipe;1043                    context.ExpressionWarningOutputPipe = pipe;1044                    break;1045                case RedirectionStream.Verbose:1046                    oldPipes[(int)FromStream] = context.ExpressionVerboseOutputPipe;1047                    context.ExpressionVerboseOutputPipe = pipe;1048                    break;1049                case RedirectionStream.Debug:1050                    oldPipes[(int)FromStream] = context.ExpressionDebugOutputPipe;1051                    context.ExpressionDebugOutputPipe = pipe;1052                    break;1053                case RedirectionStream.Information:1054                    oldPipes[(int)FromStream] = context.ExpressionInformationOutputPipe;1055                    context.ExpressionInformationOutputPipe = pipe;1056                    break;1057            }1058 1059            return oldPipes;1060        }1061    }1062 1063    internal class FileRedirection : CommandRedirection, IDisposable1064    {1065        internal FileRedirection(RedirectionStream from, bool appending, string file)1066            : base(from)1067        {1068            this.File = file;1069            this.Appending = appending;1070        }1071 1072        public override string ToString()1073        {1074            return string.Format(1075                CultureInfo.InvariantCulture,1076                "{0}> {1}",1077                FromStream == RedirectionStream.All1078                    ? "*"1079                    : ((int)FromStream).ToString(CultureInfo.InvariantCulture),1080                File);1081        }1082 1083        internal string File { get; }1084 1085        internal bool Appending { get; }1086 1087        private PipelineProcessor PipelineProcessor { get; set; }1088 1089        // Handle binding file redirection for commands, like:1090        //    dir > out1091        internal override void Bind(PipelineProcessor pipelineProcessor, CommandProcessorBase commandProcessor, ExecutionContext context)1092        {1093            // Check first to see if File is a variable path. If so, we'll not create the FileBytePipe1094            bool redirectToVariable = false;1095 1096            context.SessionState.Path.GetUnresolvedProviderPathFromPSPath(File, out ProviderInfo p, out _);1097            if (p != null && p.NameEquals(context.ProviderNames.Variable))1098            {1099                redirectToVariable = true;1100            }1101 1102            if (commandProcessor is NativeCommandProcessor nativeCommand1103                && nativeCommand.CommandRuntime.ErrorMergeTo is not MshCommandRuntime.MergeDataStream.Output1104                && FromStream is RedirectionStream.Output1105                && !string.IsNullOrWhiteSpace(File)1106                && !redirectToVariable)1107            {1108                nativeCommand.StdOutDestination = FileBytePipe.Create(File, Appending);1109                return;1110            }1111 1112            Pipe pipe = GetRedirectionPipe(context, pipelineProcessor);1113 1114            switch (FromStream)1115            {1116                case RedirectionStream.All:1117                    // Since a temp output pipe is going to be used, we should pass along the error and warning variable list.1118                    // Normally, context.CurrentCommandProcessor will not be null. But in legacy DRTs from ParserTest.cs,1119                    // a scriptblock may be invoked through 'DoInvokeReturnAsIs' using .NET reflection. In that case,1120                    // context.CurrentCommandProcessor will be null. We don't try passing along variable lists in such case.1121                    context.CurrentCommandProcessor?.CommandRuntime.OutputPipe.SetVariableListForTemporaryPipe(pipe);1122 1123                    commandProcessor.CommandRuntime.OutputPipe = pipe;1124                    commandProcessor.CommandRuntime.ErrorOutputPipe = pipe;1125                    commandProcessor.CommandRuntime.WarningOutputPipe = pipe;1126                    commandProcessor.CommandRuntime.VerboseOutputPipe = pipe;1127                    commandProcessor.CommandRuntime.DebugOutputPipe = pipe;1128                    commandProcessor.CommandRuntime.InformationOutputPipe = pipe;1129                    break;1130                case RedirectionStream.Output:1131                    // Since a temp output pipe is going to be used, we should pass along the error and warning variable list.1132                    context.CurrentCommandProcessor?.CommandRuntime.OutputPipe.SetVariableListForTemporaryPipe(pipe);1133 1134                    commandProcessor.CommandRuntime.OutputPipe = pipe;1135                    break;1136                case RedirectionStream.Error:1137                    commandProcessor.CommandRuntime.ErrorOutputPipe = pipe;1138                    break;1139                case RedirectionStream.Warning:1140                    commandProcessor.CommandRuntime.WarningOutputPipe = pipe;1141                    break;1142                case RedirectionStream.Verbose:1143                    commandProcessor.CommandRuntime.VerboseOutputPipe = pipe;1144                    break;1145                case RedirectionStream.Debug:1146                    commandProcessor.CommandRuntime.DebugOutputPipe = pipe;1147                    break;1148                case RedirectionStream.Information:1149                    commandProcessor.CommandRuntime.InformationOutputPipe = pipe;1150                    break;1151            }1152        }1153 1154        // Handle binding file redirections for expressions, like:1155        //     $(write-error blah) 2> out1156        internal Pipe[] BindForExpression(FunctionContext funcContext)1157        {1158            var context = funcContext._executionContext;1159            // GetRedirectionPipe can throw if the filename specified can't be written to.  In that case,1160            // oldPipes is null, and when unbinding, there is nothing to do.1161            Pipe pipe = GetRedirectionPipe(context, null);1162            var oldPipes = new Pipe[(int)RedirectionStream.Information + 1];1163 1164            switch (FromStream)1165            {1166                case RedirectionStream.All:1167                    oldPipes[(int)RedirectionStream.Output] = funcContext._outputPipe;1168                    oldPipes[(int)RedirectionStream.Error] = context.ShellFunctionErrorOutputPipe;1169                    oldPipes[(int)RedirectionStream.Warning] = context.ExpressionWarningOutputPipe;1170                    oldPipes[(int)RedirectionStream.Verbose] = context.ExpressionVerboseOutputPipe;1171                    oldPipes[(int)RedirectionStream.Debug] = context.ExpressionDebugOutputPipe;1172                    oldPipes[(int)RedirectionStream.Information] = context.ExpressionInformationOutputPipe;1173 1174                    // Since a temp output pipe is going to be used, we should pass along the error and warning variable list.1175                    funcContext._outputPipe.SetVariableListForTemporaryPipe(pipe);1176                    funcContext._outputPipe = pipe;1177                    context.ShellFunctionErrorOutputPipe = pipe;1178                    context.ExpressionWarningOutputPipe = pipe;1179                    context.ExpressionVerboseOutputPipe = pipe;1180                    context.ExpressionDebugOutputPipe = pipe;1181                    context.ExpressionInformationOutputPipe = pipe;1182                    break;1183                case RedirectionStream.Output:1184                    oldPipes[(int)RedirectionStream.Output] = funcContext._outputPipe;1185                    // Since a temp output pipe is going to be used, we should pass along the error and warning variable list.1186                    funcContext._outputPipe.SetVariableListForTemporaryPipe(pipe);1187                    funcContext._outputPipe = pipe;1188                    break;1189                case RedirectionStream.Error:1190                    oldPipes[(int)FromStream] = context.ShellFunctionErrorOutputPipe;1191                    context.ShellFunctionErrorOutputPipe = pipe;1192                    break;1193                case RedirectionStream.Warning:1194                    oldPipes[(int)FromStream] = context.ExpressionWarningOutputPipe;1195                    context.ExpressionWarningOutputPipe = pipe;1196                    break;1197                case RedirectionStream.Verbose:1198                    oldPipes[(int)FromStream] = context.ExpressionVerboseOutputPipe;1199                    context.ExpressionVerboseOutputPipe = pipe;1200                    break;

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