Esempio n. 1
0
        def close(self):
            """Close file.
            """
            if self._handle:
                try:
                    flags = win32pipe.GetNamedPipeInfo(self._handle)[0]
                except:
                    flags = 0

                if flags & win32con.PIPE_SERVER_END:
                    win32pipe.DisconnectNamedPipe(self._handle)
                # TODO: if pipe, need to call FlushFileBuffers?

                def _close_(self, rc, n):
                    win32file.CloseHandle(self._handle)
                    self._overlap = None
                    _AsyncFile._notifier.unregister(self._handle)
                    self._handle = None
                    self._read_result = self._write_result = None
                    self._read_coro = self._write_coro = None
                    self._buflist = []

                if self._overlap.object:
                    self._overlap.object = partial_func(_close_, self)
                    win32file.CancelIo(self._handle)
                else:
                    _close_(self, 0, 0)
Esempio n. 2
0
        def close(self):
            """Similar to 'close' of file descriptor.
            """
            if self._handle:
                try:
                    flags = win32pipe.GetNamedPipeInfo(self._handle)[0]
                except Exception:
                    flags = 0

                if flags & win32con.PIPE_SERVER_END:
                    win32pipe.DisconnectNamedPipe(self._handle)
                # TODO: if pipe, need to call FlushFileBuffers?

                def _close_(rc, n):
                    win32file.CloseHandle(self._handle)
                    self._overlap = None
                    if self._notifier:
                        self._notifier.unregister(self._handle)
                    self._handle = None
                    self._read_result = self._write_result = None
                    self._read_task = self._write_task = None
                    self._buflist = []

                if self._overlap.object:
                    self._overlap.object = _close_
                    win32file.CancelIo(self._handle)
                else:
                    _close_(0, 0)
Esempio n. 3
0
    def connect(self, address):
        win32pipe.WaitNamedPipe(address, self._timeout)
        handle = win32file.CreateFile(
            address, win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0, None,
            win32file.OPEN_EXISTING,
            cSECURITY_ANONYMOUS | cSECURITY_SQOS_PRESENT, 0)
        self.flags = win32pipe.GetNamedPipeInfo(handle)[0]

        self._handle = handle
        self._address = address
Esempio n. 4
0
 def __init__(self,
              name,
              pipe_type='server' or 'client',
              *,
              open_mode=win32pipe.PIPE_ACCESS_DUPLEX
              | win32file.FILE_FLAG_OVERLAPPED,
              pipe_mode=win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_NOWAIT,
              maxinstances=255,
              out_buffer_size=1000000,
              in_buffer_size=1000000,
              default_timeout=50,
              security_attrib=None):
     """An implementation of a file-like python object pipe
     https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150(v=vs.85).aspx"""
     self.pipe_type = pipe_type
     self.name = name
     self.open_mode = open_mode
     self.pipe_mode = pipe_mode
     if pipe_type == 'server':
         self.handle = win32pipe.CreateNamedPipe(
             PIPE_ROOT + name,
             open_mode,  # default PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED
             pipe_mode,  # default PIPE_TYPE_BYTE|PIPE_NOWAIT
             maxinstances,  # default 255
             out_buffer_size,  # default 1000000
             in_buffer_size,  # default 1000000
             default_timeout,  # default 50
             security_attrib  # default None
         )
     elif pipe_type == 'client':
         # it doesn't matter what type of pipe the server is so long as we know the name
         self.handle = win32file.CreateFile(
             PIPE_ROOT + name,
             win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0, None,
             win32file.OPEN_EXISTING, 0, None)
     else:
         raise ValueError('pipe_type', ('server', 'client'))
     self.fd = msvcrt.open_osfhandle(self.handle, 0)
     self.is_connected = False
     self.flags, self.out_buffer_size, self.in_buffer_size, self.maxinstances = win32pipe.GetNamedPipeInfo(
         self.handle)
Esempio n. 5
0
    def connect(self, address):
        win32pipe.WaitNamedPipe(address, self._timeout)
        try:
            handle = win32file.CreateFile(
                address, win32file.GENERIC_READ | win32file.GENERIC_WRITE, 0,
                None, win32file.OPEN_EXISTING,
                cSECURITY_ANONYMOUS | cSECURITY_SQOS_PRESENT, 0)
        except win32pipe.error as e:
            # See Remarks:
            # https://msdn.microsoft.com/en-us/library/aa365800.aspx
            if e.winerror == cERROR_PIPE_BUSY:
                # Another program or thread has grabbed our pipe instance
                # before we got to it. Wait for availability and attempt to
                # connect again.
                win32pipe.WaitNamedPipe(address, RETRY_WAIT_TIMEOUT)
                return self.connect(address)
            raise e

        self.flags = win32pipe.GetNamedPipeInfo(handle)[0]

        self._handle = handle
        self._address = address
Esempio n. 6
0
def getnamedpipeinfo(phandle):
    """ returns pipe's flags, buffer sizes, and max instances
        @return (int, int, int, int)
    """
    return (w32pipe.GetNamedPipeInfo(phandle))
Esempio n. 7
0
def ListNamedPipes() -> Iterator[rdf_client.NamedPipe]:
    """Yields all named pipes available in the system."""
    if platform.system() != "Windows":
        raise RuntimeError(f"Unsupported platform: {platform.system()}")

    # pylint: disable=g-import-not-at-top
    # pytype: disable=import-error
    import ctypes
    import ctypes.wintypes
    import win32api
    import win32file
    import win32pipe
    import winerror
    # pytype: enable=import-error
    # pylint: enable=g-import-not-at-top

    # The `GetNamedPipeHandleState` function provided by the `win32pipe` module is
    # broken (calling it results in invalid function exception). Hence, we need to
    # go to a lower level and use raw Windows API calls to get this information.
    #
    # https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-getnamedpipehandlestatew
    # pytype: disable=module-attr
    GetNamedPipeHandleStateW = ctypes.windll.kernel32.GetNamedPipeHandleStateW  # pylint: disable=invalid-name
    # pytype: enable=module-attr
    GetNamedPipeHandleStateW.argtypes = [
        ctypes.wintypes.HANDLE,
        ctypes.wintypes.LPDWORD,
        ctypes.wintypes.LPDWORD,
        ctypes.wintypes.LPDWORD,
        ctypes.wintypes.LPDWORD,
        ctypes.wintypes.LPWSTR,
        ctypes.wintypes.DWORD,
    ]
    GetNamedPipeHandleStateW.restype = ctypes.wintypes.BOOL

    # For some reason the `GetNamedPipeClientComputerName` function does not exist
    # in `win32pipe`. Hence, we implement a low-level wrapper for Windows API for
    # it ourselves.
    #
    # https://docs.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-getnamedpipeclientcomputernamew
    # pytype: disable=module-attr
    GetNamedPipeClientComputerNameW = ctypes.windll.kernel32.GetNamedPipeClientComputerNameW  # pylint: disable=invalid-name
    # pytype: enable=module-attr
    GetNamedPipeClientComputerNameW.argtypes = [
        ctypes.wintypes.HANDLE,
        ctypes.wintypes.LPWSTR,
        ctypes.wintypes.ULONG,
    ]
    GetNamedPipeClientComputerNameW.restype = ctypes.wintypes.BOOL

    # https://docs.microsoft.com/en-us/windows/win32/ipc/pipe-names
    for name in os.listdir(r"\\.\pipe"):
        pipe = rdf_client.NamedPipe()
        pipe.name = name

        try:
            handle = win32file.CreateFile(f"\\\\.\\pipe\\{name}", 0, 0, None,
                                          win32file.OPEN_EXISTING, 0, None)
        except win32file.error as error:
            # There might be some permission issues. We log the error and skip getting
            # pipe details, but still yield a result with at least the name filled-in.
            logging.error("Cannot open pipe '%s': %s", name, error)
            yield pipe
            continue

        with contextlib.closing(handle):
            try:
                pipe_info = win32pipe.GetNamedPipeInfo(handle)
                flags, in_buffer_size, out_buffer_size, max_instance_count = pipe_info

                pipe.flags = flags
                pipe.in_buffer_size = in_buffer_size
                pipe.out_buffer_size = out_buffer_size
                pipe.max_instance_count = max_instance_count
            except win32pipe.error as error:
                # Getting the information might fail (for whatever reason), but we don't
                # want to fail action execution as other probing calls might succeed.
                logging.error("Failed to get info about pipe '%s': '%s'", name,
                              error)

            try:
                pipe.server_pid = win32pipe.GetNamedPipeServerProcessId(handle)
            except win32pipe.error as error:
                # See similar comment for `GetNamedPipeInfo` for more information.
                message = "Failed to get server pid of pipe '%s': '%s'"
                logging.error(message, name, error)

            try:
                pipe.client_pid = win32pipe.GetNamedPipeClientProcessId(handle)
            except win32pipe.error as error:
                # See similar comment for `GetNamedPipeInfo` for more information.
                message = "Failed to get client pid of pipe '%s': '%s'"
                logging.error(message, name, error)

            cur_instance_count = ctypes.wintypes.DWORD()
            status = GetNamedPipeHandleStateW(
                ctypes.wintypes.HANDLE(int(handle)),
                None,
                ctypes.byref(cur_instance_count),
                None,
                None,
                None,
                0,
            )

            if status == 0:
                # See similar comment for `GetNamedPipeInfo` for more information.
                error = win32api.GetLastError()
                logging.error("Failed to get state of pipe '%s': %s", name,
                              error)
            else:
                pipe.cur_instance_count = cur_instance_count.value

            client_computer_name = (ctypes.wintypes.WCHAR *
                                    _COMPUTER_NAME_MAX_SIZE)()  # pytype: disable=not-callable
            status = GetNamedPipeClientComputerNameW(
                ctypes.wintypes.HANDLE(int(handle)),
                client_computer_name,
                _COMPUTER_NAME_MAX_SIZE,
            )

            if status == 0:
                # See similar comment for `GetNamedPipeInfo` for more information.
                error = win32api.GetLastError()
                # Not being able to get computer name of a local pipe is expected, there
                # is no need to log errors in such cases.
                if error != winerror.ERROR_PIPE_LOCAL:
                    logging.error("Failed to get hostname of pipe '%s': %s",
                                  name, error)
            else:
                pipe.client_computer_name = client_computer_name.value

            yield pipe