// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Management.Automation.Internal;
using System.Management.Automation.Remoting;
using System.Management.Automation.Runspaces;
using System.Security.Principal;
using System.Threading;
using Dbg = System.Management.Automation.Diagnostics;
namespace System.Management.Automation
{
///
/// This class wraps a PowerShell object. It is used to function
/// as a server side powershell.
///
internal class ServerPowerShellDriver
{
#region Private Members
private bool _extraPowerShellAlreadyScheduled;
// extra PowerShell at the server to be run after localPowerShell
private PowerShell _extraPowerShell;
// output buffer for the local PowerShell that is associated with this powershell driver
// associated with this powershell data structure handler object to handle all communications with the client
private PSDataCollection _localPowerShellOutput;
// if the remaining data has been sent to the client before sending state information
private bool[] _datasent = new bool[2];
// sync object for synchronizing sending data to client
private object _syncObject = new object();
// there is no input when this driver was created
private bool _noInput;
private bool _addToHistory;
// the server remote host instance
// associated with this powershell
private ServerRemoteHost _remoteHost;
#if !CORECLR
// No ApartmentState In CoreCLR
// apartment state for this powershell
private ApartmentState apartmentState;
#endif
// Handles nested invocation of PS drivers.
private IRSPDriverInvoke _psDriverInvoker;
#endregion Private Members
#region Constructors
#if !CORECLR
///
/// Default constructor for creating ServerPowerShellDrivers.
///
/// Decoded powershell object.
/// Extra pipeline to be run after completes.
/// Whether there is input for this powershell.
/// The client powershell id.
/// The client runspacepool id.
/// runspace pool driver
/// which is creating this powershell driver
/// Apartment state for this powershell.
/// host info using which the host for
/// this powershell will be constructed
/// Serialization options for the streams in this powershell.
///
/// true if the command is to be added to history list of the runspace. false, otherwise.
///
///
/// If not null, this Runspace will be used to invoke Powershell.
/// If null, the RunspacePool pointed by will be used.
///
internal ServerPowerShellDriver(PowerShell powershell, PowerShell extraPowerShell, bool noInput, Guid clientPowerShellId,
Guid clientRunspacePoolId, ServerRunspacePoolDriver runspacePoolDriver,
ApartmentState apartmentState, HostInfo hostInfo, RemoteStreamOptions streamOptions,
bool addToHistory, Runspace rsToUse)
: this(powershell, extraPowerShell, noInput, clientPowerShellId, clientRunspacePoolId, runspacePoolDriver,
apartmentState, hostInfo, streamOptions, addToHistory, rsToUse, null)
{
}
#else
///
/// Default constructor for creating ServerPowerShellDrivers.
///
/// Decoded powershell object.
/// Extra pipeline to be run after completes.
/// Whether there is input for this powershell.
/// The client powershell id.
/// The client runspacepool id.
/// runspace pool driver
/// which is creating this powershell driver
/// host info using which the host for
/// this powershell will be constructed
/// Serialization options for the streams in this powershell.
///
/// true if the command is to be added to history list of the runspace. false, otherwise.
///
///
/// If not null, this Runspace will be used to invoke Powershell.
/// If null, the RunspacePool pointed by will be used.
///
internal ServerPowerShellDriver(PowerShell powershell, PowerShell extraPowerShell, bool noInput, Guid clientPowerShellId,
Guid clientRunspacePoolId, ServerRunspacePoolDriver runspacePoolDriver,
HostInfo hostInfo, RemoteStreamOptions streamOptions,
bool addToHistory, Runspace rsToUse)
: this(powershell, extraPowerShell, noInput, clientPowerShellId, clientRunspacePoolId, runspacePoolDriver,
hostInfo, streamOptions, addToHistory, rsToUse, null)
{
}
#endif
#if CORECLR
///
/// Default constructor for creating ServerPowerShellDrivers.
///
/// Decoded powershell object.
/// Extra pipeline to be run after completes.
/// Whether there is input for this powershell.
/// The client powershell id.
/// The client runspacepool id.
/// runspace pool driver
/// which is creating this powershell driver
/// host info using which the host for
/// this powershell will be constructed
/// Serialization options for the streams in this powershell.
///
/// true if the command is to be added to history list of the runspace. false, otherwise.
///
///
/// If not null, this Runspace will be used to invoke Powershell.
/// If null, the RunspacePool pointed by will be used.
///
///
/// If not null, this is used as another source of output sent to the client.
///
internal ServerPowerShellDriver(PowerShell powershell, PowerShell extraPowerShell, bool noInput, Guid clientPowerShellId,
Guid clientRunspacePoolId, ServerRunspacePoolDriver runspacePoolDriver,
HostInfo hostInfo, RemoteStreamOptions streamOptions,
bool addToHistory, Runspace rsToUse, PSDataCollection output)
#else
///
/// Default constructor for creating ServerPowerShellDrivers.
///
/// Decoded powershell object.
/// Extra pipeline to be run after completes.
/// Whether there is input for this powershell.
/// The client powershell id.
/// The client runspacepool id.
/// runspace pool driver
/// which is creating this powershell driver
/// Apartment state for this powershell.
/// host info using which the host for
/// this powershell will be constructed
/// Serialization options for the streams in this powershell.
///
/// true if the command is to be added to history list of the runspace. false, otherwise.
///
///
/// If not null, this Runspace will be used to invoke Powershell.
/// If null, the RunspacePool pointed by will be used.
///
///
/// If not null, this is used as another source of output sent to the client.
///
internal ServerPowerShellDriver(PowerShell powershell, PowerShell extraPowerShell, bool noInput, Guid clientPowerShellId,
Guid clientRunspacePoolId, ServerRunspacePoolDriver runspacePoolDriver,
ApartmentState apartmentState, HostInfo hostInfo, RemoteStreamOptions streamOptions,
bool addToHistory, Runspace rsToUse, PSDataCollection output)
#endif
{
InstanceId = clientPowerShellId;
RunspacePoolId = clientRunspacePoolId;
RemoteStreamOptions = streamOptions;
#if !CORECLR // No ApartmentState In CoreCLR
this.apartmentState = apartmentState;
#endif
LocalPowerShell = powershell;
_extraPowerShell = extraPowerShell;
_localPowerShellOutput = new PSDataCollection();
_noInput = noInput;
_addToHistory = addToHistory;
_psDriverInvoker = runspacePoolDriver;
DataStructureHandler = runspacePoolDriver.DataStructureHandler.CreatePowerShellDataStructureHandler(clientPowerShellId, clientRunspacePoolId, RemoteStreamOptions, LocalPowerShell);
_remoteHost = DataStructureHandler.GetHostAssociatedWithPowerShell(hostInfo, runspacePoolDriver.ServerRemoteHost);
if (!noInput)
{
InputCollection = new PSDataCollection