Example #1
0
def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
    """
    Opens an existing local process object.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms684320

    :param int dwDesiredAccess:
        The required access to the process object.

    :param bool bInheritHandle:
        Enables or disable handle inheritance for child processes.

    :param int dwProcessId:
        The id of the local process to be opened.

    :returns:
        Returns a :class:`pywincffi.wintypes.HANDLE` to the opened process.
        This value can be used by other functions such as
        :func:`TerminateProcess`.
    """
    input_check("dwDesiredAccess", dwDesiredAccess, integer_types)
    input_check("bInheritHandle", bInheritHandle, bool)
    input_check("dwProcessId", dwProcessId, integer_types)
    ffi, library = dist.load()

    handle = library.OpenProcess(
        ffi.cast("DWORD", dwDesiredAccess),
        ffi.cast("BOOL", bInheritHandle),
        ffi.cast("DWORD", dwProcessId)
    )
    error_check("OpenProcess")
    return HANDLE(handle)
Example #2
0
def WaitForSingleObject(hHandle, dwMilliseconds):
    """
    Waits for the specified object to be in a signaled state
    or for ``dwMiliseconds`` to elapse.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms687032

    :param pywincffi.wintypes.HANDLE hHandle:
        The handle to wait on.

    :param int dwMilliseconds:
        The time-out interval.
    """
    input_check("hHandle", hHandle, HANDLE)
    input_check("dwMilliseconds", dwMilliseconds, integer_types)

    ffi, library = dist.load()
    result = library.WaitForSingleObject(
        wintype_to_cdata(hHandle), ffi.cast("DWORD", dwMilliseconds)
    )

    if result == library.WAIT_FAILED:
        raise WindowsAPIError(
            "WaitForSingleObject", "Wait Failed", ffi.getwinerror()[-1],
            return_code=result, expected_return_code="not %s" % result)

    error_check("WaitForSingleObject")

    return result
Example #3
0
def error_check(function, code=None, expected=None):
    """
    Checks the results of a return code against an expected result.  If
    a code is not provided we'll use :func:`ffi.getwinerror` to retrieve
    the code.

    :param str function:
        The Windows API function being called.

    :keyword int code:
        An explicit code to compare against.

    :keyword int expected:
        The code we expect to have as a result of a successful
        call.  This can also be passed ``pywincffi.core.checks.NON_ZERO``
        if ``code`` can be anything but zero.

    :raises pywincffi.exceptions.WindowsAPIError:
        Raised if we receive an unexpected result from a Windows API call
    """
    ffi, _ = dist.load()
    errno, error_message = ffi.getwinerror()

    if code is not None:
        if expected == NON_ZERO and code == 0:
            raise WindowsAPIError(
                function, error_message, errno,
                return_code=code, expected_return_code=expected)
        return

    if errno != 0:
        raise WindowsAPIError(
            function, error_message, errno, return_code=code,
            expected_return_code=expected)
Example #4
0
def SetHandleInformation(hObject, dwMask, dwFlags):
    """
    Sets properties of an object handle.

    .. seealso::

        https://msdn.microsoft.com/en-us/ms724935

    :param pywincffi.wintypes.HANDLE hObject:
        A handle to an object whose information is to be set.

    :param int dwMask:
        A mask that specifies the bit flags to be changed.

    :param int dwFlags:
        Set of bit flags that specifies properties of ``hObject``.
    """
    input_check("hObject", hObject, HANDLE)
    input_check("dwMask", dwMask, integer_types)
    input_check("dwFlags", dwFlags, integer_types)
    ffi, library = dist.load()

    code = library.SetHandleInformation(
        wintype_to_cdata(hObject),
        ffi.cast("DWORD", dwMask),
        ffi.cast("DWORD", dwFlags)
    )
    error_check("SetHandleInformation", code=code, expected=Enums.NON_ZERO)
Example #5
0
    def test_dwCreationFlags_CREATE_NO_WINDOW(self):
        """
        If we call CreateProcess() with dwCreationFlags set and
        pass in an environmnet, internally it must internally add
        CREATE_UNICODE_ENVIRONMENT to dwCreationFlags.  Otherwise it
        will fail due to an invalid parameter.
        """
        _, library = dist.load()

        env = {}
        for key, val in iteritems(os.environ):
            if isinstance(key, bytes):
                key = key.decode(sys.getfilesystemencoding())
            if isinstance(val, bytes):
                val = val.decode(sys.getfilesystemencoding())
            env[key] = val

        process = CreateProcess(
            lpCommandLine=u"{0} -c \"\"".format(sys.executable),
            lpApplicationName=None,
            lpProcessAttributes=None,
            lpThreadAttributes=None,
            bInheritHandles=True,
            dwCreationFlags=library.CREATE_NO_WINDOW,
            lpEnvironment=env,
            lpCurrentDirectory=None,
            lpStartupInfo=None
        )
        self.assertIsInstance(process, CreateProcessResult)
        self.addCleanup(self.cleanup_process, process)
    def test_type_check_on_pHandles_input_not_list(self):
        _, library = dist.load()
        e1 = CreateEvent(True, False)
        self.addCleanup(CloseHandle, e1)

        with self.assertRaises(InputError):
            MsgWaitForMultipleObjects(e1, False, 0, library.QS_ALLEVENTS)
Example #7
0
    def test_clear_error(self):
        ffi, library = dist.load()

        # Try to find a COM device, skip the test if we can't
        # find one.  The 'maximum' comes from here:
        #   https://support.microsoft.com/en-us/kb/100111
        found_com_device = False
        for i in range(256):
            try:
                handle = CreateFile(
                    u"\\\\.\\COM%d" % i,
                    library.GENERIC_READ | library.GENERIC_WRITE,
                    dwCreationDisposition=library.OPEN_EXISTING,
                    dwShareMode=0
                )
                found_com_device = True
                self.addCleanup(CloseHandle, handle)
                ClearCommError(handle)
                break
            except WindowsAPIError:
                code, _ = ffi.getwinerror()
                if code != library.ERROR_FILE_NOT_FOUND:
                    self.fail("Unexpected Windows API error: %s" % code)
                self.SetLastError(0)  # cleanup after the failure

        if not found_com_device:
            self.skipTest("No COM devices present.")
Example #8
0
    def test_compiled(self):
        # Python 3.5 changes the behavior of None in sys.modules. So
        # long as other Python versions pass, skipping this should
        # be ok.
        if sys.version_info[0:2] >= (3, 5):
            self.skipTest("Python 3.5 not suppoted in this test")

        # Setting _pywincffi to None in sys.modules will force
        # 'import _pywincffi' to fail forcing load() to
        # compile the module.
        sys.modules[MODULE_NAME] = None

        with patch.object(dist, "_compile") as mocked:
            load()

        mocked.assert_called_once()
def WaitForSingleObject(hHandle, dwMilliseconds):
    """
    Waits for the specified object to be in a signaled state
    or for ``dwMiliseconds`` to elapse.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms687032

    :param pywincffi.wintypes.HANDLE hHandle:
        The handle to wait on.

    :param int dwMilliseconds:
        The time-out interval.
    """
    input_check("hHandle", hHandle, HANDLE)
    input_check("dwMilliseconds", dwMilliseconds, integer_types)

    ffi, library = dist.load()
    result = library.WaitForSingleObject(wintype_to_cdata(hHandle),
                                         ffi.cast("DWORD", dwMilliseconds))

    if result == library.WAIT_FAILED:
        raise WindowsAPIError("WaitForSingleObject",
                              "Wait Failed",
                              ffi.getwinerror()[-1],
                              return_code=result,
                              expected_return_code="not %s" % result)

    error_check("WaitForSingleObject")

    return result
Example #10
0
    def test_mode_message_fails(self):
        _, lib = dist.load()
        # should fail: anonymous pipes are byte oriented
        with self.assertRaises(WindowsAPIError):
            self._set_mode(lib.PIPE_READMODE_MESSAGE)

        self.assert_last_error(lib.ERROR_INVALID_PARAMETER)
Example #11
0
 def test_create_console(self):
     _, library = dist.load()
     handle = CreateConsoleScreenBuffer(
         library.GENERIC_READ | library.GENERIC_WRITE,
         None, lpSecurityAttributes=None, dwFlags=None,
     )
     self.addCleanup(CloseHandle, handle)
Example #12
0
    def test_collect_data_timeout_fail(self):
        # should fail: only supported with named pipes
        with self.assertRaises(WindowsAPIError):
            self._set_collect_data_timeout(500)

        _, library = dist.load()
        self.assert_last_error(library.ERROR_INVALID_PARAMETER)
Example #13
0
    def test_lpCommandLine_length_max_command_line(self):
        with mock_library(CreateProcess=self.NoOpCreateProcess):
            _, library = dist.load()

            match = ".*cannot exceed %s.*" % library.MAX_COMMAND_LINE
            with self.assertRaisesRegex(InputError, match):
                CreateProcess(u" " * (library.MAX_COMMAND_LINE + 1))
Example #14
0
    def test_clear_error(self):
        ffi, library = dist.load()

        # Try to find a COM device, skip the test if we can't
        # find one.  The 'maximum' comes from here:
        #   https://support.microsoft.com/en-us/kb/100111
        found_com_device = False
        for i in range(256):
            try:
                handle = CreateFile(
                    u"\\\\.\\COM%d" % i,
                    library.GENERIC_READ | library.GENERIC_WRITE,
                    dwCreationDisposition=library.OPEN_EXISTING,
                    dwShareMode=0)
                found_com_device = True
                self.addCleanup(CloseHandle, handle)
                ClearCommError(handle)
                break
            except WindowsAPIError:
                code, _ = ffi.getwinerror()
                if code != library.ERROR_FILE_NOT_FOUND:
                    self.fail("Unexpected Windows API error: %s" % code)
                self.SetLastError(0)  # cleanup after the failure

        if not found_com_device:
            self.skipTest("No COM devices present.")
Example #15
0
 def test_get_handle_info_stdin(self):
     _, library = dist.load()
     stdin_handle = GetStdHandle(library.STD_INPUT_HANDLE)
     handle_flags = GetHandleInformation(stdin_handle)
     inherit = handle_flags & library.HANDLE_FLAG_INHERIT
     expected = (0, library.HANDLE_FLAG_INHERIT)
     self.assertIn(inherit, expected)
Example #16
0
    def test_resets_event(self):
        handle = CreateEvent(bManualReset=True, bInitialState=True)
        self.addCleanup(CloseHandle, handle)
        ResetEvent(handle)

        _, library = dist.load()
        self.assertEqual(WaitForSingleObject(handle, 0), library.WAIT_TIMEOUT)
Example #17
0
    def test_declares_proper_cname(self):
        class INT(WrappedObject):
            C_TYPE = "int[1]"

        ffi, _ = dist.load()
        int_ = INT()
        self.assertEqual(ffi.typeof(int_._cdata).cname, INT.C_TYPE)
Example #18
0
 def test_signaled(self):
     handle = CreateEvent(bManualReset=True, bInitialState=False)
     self.addCleanup(CloseHandle, handle)
     _, library = dist.load()
     SetEvent(handle)
     self.assertEqual(
         WaitForSingleObject(handle, 0), library.WAIT_OBJECT_0)
Example #19
0
    def test_handle_is_valid(self):
        _, library = dist.load()
        handle = OpenProcess(
            library.PROCESS_QUERY_INFORMATION, False, os.getpid())

        # If the handle were invalid, this would fail.
        CloseHandle(handle)
Example #20
0
def WSAEnumNetworkEvents(socket, hEventObject=None):
    """
    Discovers occurrences of network events on the indicated ``socket``, clears
    internal events and optionally resets event objects.

    .. seealso::
        https://msdn.microsoft.com/en-us/ms741572

    :param pywincffi.wintypes.objects.SOCKET socket:
        The socket object to enumerate events for.

    :keyword pywincffi.wintypes.objects.WSAEVENT hEventObject:
        An optional handle identify an associated event object
        to be reset.

    :rtype: :class:`pywincffi.wintypes.structures.LPWSANETWORKEVENTS`
    :return:
    """
    input_check("socket", socket, allowed_types=(SOCKET, ))

    ffi, library = dist.load()
    if hEventObject is not None:
        input_check("hEventObject", hEventObject, allowed_types=(WSAEVENT, ))
        hEventObject = wintype_to_cdata(hEventObject)
    else:
        hEventObject = ffi.NULL

    lpNetworkEvents = LPWSANETWORKEVENTS()
    code = library.WSAEnumNetworkEvents(wintype_to_cdata(socket), hEventObject,
                                        wintype_to_cdata(lpNetworkEvents))
    error_check("WSAEnumNetworkEvents", code=code, expected=0)

    return lpNetworkEvents
Example #21
0
def GetStdHandle(nStdHandle):
    """
    Retrieves a handle to the specified standard
    device (standard input, standard output, or standard error).

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms683231

    :param int nStdHandle:
        The standard device to retrieve.

    :rtype: pywincffi.wintypes.HANDLE
    :return:
        Returns a handle to the standard device retrieved.
    """
    _, library = dist.load()
    input_check("nStdHandle", nStdHandle,
                allowed_values=(library.STD_INPUT_HANDLE,
                                library.STD_OUTPUT_HANDLE,
                                library.STD_ERROR_HANDLE))

    handle = library.GetStdHandle(nStdHandle)

    if handle == library.INVALID_HANDLE_VALUE:  # pragma: no cover
        raise WindowsAPIError(
            "GetStdHandle", "Invalid Handle", library.INVALID_HANDLE_VALUE,
            expected_return_code="not %r" % library.INVALID_HANDLE_VALUE)

    return HANDLE(handle)
    def test_type_check_on_pHandles_input_not_list(self):
        _, library = dist.load()
        e1 = CreateEvent(True, False)
        self.addCleanup(CloseHandle, e1)

        with self.assertRaises(InputError):
            MsgWaitForMultipleObjects(e1, False, 0, library.QS_ALLEVENTS)
Example #23
0
def SetConsoleTextAttribute(hConsoleOutput, wAttributes):
    """
    Sets the attributes of characters written to a console buffer.

    .. seealso::

        https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute

    :param pywincffi.wintypes.HANDLE hConsoleOutput:
        A handle to the console screen buffer. The handle must have the
        ``GENERIC_READ`` access right.

    :param int wAttributes:
        The character attribute(s) to set.
    """
    input_check("hConsoleOutput", hConsoleOutput, HANDLE)
    input_check("wAttributes", wAttributes, integer_types)
    ffi, library = dist.load()
    # raise Exception(type(wAttributes))
    # info = ffi.new("PCHAR_INFO")
    code = library.SetConsoleTextAttribute(
        wintype_to_cdata(hConsoleOutput),
        ffi.cast("ATOM", wAttributes)
    )
    error_check("SetConsoleTextAttribute", code=code, expected=NON_ZERO)
Example #24
0
def CreateEvent(
        bManualReset, bInitialState, lpEventAttributes=None, lpName=None):
    """
    Creates or opens an named or unnamed event object.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms682396

    :param bool bManualReset:
        If True then this function will create a manual reset
        event which must be manually reset with :func:`ResetEvent`.  Refer
        to the msdn documentation for full information.

    :param bool bInitialState:
        If True the initial state will be 'signaled'.

    :keyword :class:`pywincffi.wintypes.SECURITY_ATTRIBUTES` lpEventAttributes:
        If not provided then, by default, the handle cannot be inherited
        by a subprocess.

    :keyword str lpName:
        Type is ``unicode`` on Python 2, ``str`` on Python 3.
        The optional case-sensitive name of the event.  If not provided then
        the event will be created without an explicit name.

    :returns:
        Returns a :class:`pywincffi.wintypes.HANDLE` to the event. If an event
        by the given name already exists then it will be returned instead of
        creating a new event.
    """
    input_check("bManualReset", bManualReset, bool)
    input_check("bInitialState", bInitialState, bool)

    ffi, library = dist.load()

    if lpName is None:
        lpName = ffi.NULL
    else:
        input_check("lpName", lpName, text_type)

    input_check(
        "lpEventAttributes", lpEventAttributes,
        allowed_types=(SECURITY_ATTRIBUTES, NoneType)
    )

    handle = library.CreateEvent(
        wintype_to_cdata(lpEventAttributes),
        ffi.cast("BOOL", bManualReset),
        ffi.cast("BOOL", bInitialState),
        lpName
    )

    try:
        error_check("CreateEvent")
    except WindowsAPIError as error:
        if error.errno != library.ERROR_ALREADY_EXISTS:
            raise

    return HANDLE(handle)
Example #25
0
    def test_lpCommandLine_length_max_command_line(self):
        with mock_library(CreateProcess=self.NoOpCreateProcess):
            _, library = dist.load()

            match = ".*cannot exceed %s.*" % library.MAX_COMMAND_LINE
            with self.assertRaisesRegex(InputError, match):
                CreateProcess(u" " * (library.MAX_COMMAND_LINE + 1))
Example #26
0
def OpenEvent(dwDesiredAccess, bInheritHandle, lpName):
    """
    Opens an existing named event.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms684305

    :param int dwDesiredAccess:
        The access desired for the event object.

    :param bool bInheritHandle:
    :param str lpName:
        Type is ``unicode`` on Python 2, ``str`` on Python 3.

    :return:
        Returns a :class:`pywincffi.wintypes.HANDLE` to the event.
    """
    input_check("dwDesiredAccess", dwDesiredAccess, integer_types)
    input_check("bInheritHandle", bInheritHandle, bool)
    input_check("lpName", lpName, text_type)

    ffi, library = dist.load()

    handle = library.OpenEvent(
        ffi.cast("DWORD", dwDesiredAccess),
        ffi.cast("BOOL", bInheritHandle),
        lpName
    )
    error_check("OpenEvent")
    return HANDLE(handle)
Example #27
0
    def test_resets_event(self):
        handle = CreateEvent(True, True)
        self.addCleanup(CloseHandle, handle)
        ResetEvent(handle)

        _, library = dist.load()
        self.assertEqual(WaitForSingleObject(handle, 0), library.WAIT_TIMEOUT)
Example #28
0
def ClearCommError(hFile):
    """
    Retrieves information about a communications error and reports the
    current status of a communications device.

    .. seealso::

        https://msdn.microsoft.com/en-us/aa363180

    :param pywincffi.wintypes.HANDLE hFile:
        A handle to the communications device, typically created by
        :func:`CreateFile`

    :rtype: tuple
    :return:
        Returns a two element tuple containing the ``lpErrors`` and
        ``lpStat`` result objects.

            * ``lpErrors`` - Contains the mast indicating the type of error
            * ``lpStat`` - A ``COMSTAT`` structure which contains the device's
               information.
    """
    input_check("hFile", hFile, HANDLE)

    ffi, library = dist.load()

    lpErrors = ffi.new("LPDWORD")
    lpStat = ffi.new("LPCOMSTAT")
    code = library.ClearCommError(wintype_to_cdata(hFile), lpErrors, lpStat)
    error_check("ClearCommError", code=code, expected=Enums.NON_ZERO)

    # TODO: Build Python instance of COMSTAT here!
    return lpErrors, lpStat
Example #29
0
def GetExitCodeProcess(hProcess):
    """
    Retrieves the exit code of the given process handle.  To retrieve
    a process handle use :func:`OpenProcess`.

    .. warning::

        You may want to use :func:`process_exit_code` instead of this
        function if you're just checking to see if a process has
        exited at all.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms683189

    :param pywincffi.wintypes.HANDLE hProcess:
        The handle of the process to retrieve the exit code for.

    :returns:
        Returns the exit code of the requested process if one
        can be found.
    """
    input_check("hProcess", hProcess, HANDLE)

    ffi, library = dist.load()
    lpExitCode = ffi.new("LPDWORD")
    code = library.GetExitCodeProcess(wintype_to_cdata(hProcess), lpExitCode)
    error_check("GetExitCodeProcess", code=code, expected=Enums.NON_ZERO)
    return lpExitCode[0]
Example #30
0
def OpenEvent(dwDesiredAccess, bInheritHandle, lpName):
    """
    Opens an existing named event.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms684305

    :param int dwDesiredAccess:
        The access desired for the event object.

    :param bool bInheritHandle:
    :param str lpName:
        Type is ``unicode`` on Python 2, ``str`` on Python 3.

    :return:
        Returns a :class:`pywincffi.wintypes.HANDLE` to the event.
    """
    input_check("dwDesiredAccess", dwDesiredAccess, integer_types)
    input_check("bInheritHandle", bInheritHandle, bool)
    input_check("lpName", lpName, text_type)

    ffi, library = dist.load()

    handle = library.OpenEvent(ffi.cast("DWORD", dwDesiredAccess),
                               ffi.cast("BOOL", bInheritHandle), lpName)
    error_check("OpenEvent")
    return HANDLE(handle)
Example #31
0
    def test_handle_is_valid(self):
        _, library = dist.load()
        handle = OpenProcess(
            library.PROCESS_QUERY_INFORMATION, False, os.getpid())

        # If the handle were invalid, this would fail.
        CloseHandle(handle)
Example #32
0
def WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite=None, lpOverlapped=None):
    """
    Writes data to ``hFile`` which may be an I/O device for file.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/aa365747

    :param pywincffi.wintypes.HANDLE hFile:
        The handle to write to.

    :type lpBuffer: str/bytes
    :param lpBuffer:
        Type is ``str`` on Python 2, ``bytes`` on Python 3.
        The data to be written to the file or device.

    :keyword int nNumberOfBytesToWrite:
        The number of bytes to be written.  Defaults to len(lpBuffer).

    :keyword pywincffi.wintypes.OVERLAPPED lpOverlapped:
        See Microsoft's documentation for intended usage and below for
        an example.

        >>> from pywincffi.core import dist
        >>> from pywincffi.kernel32 import WriteFile, CreateEvent
        >>> from pywincffi.wintypes import OVERLAPPED
        >>> hEvent = CreateEvent(...)
        >>> lpOverlapped = OVERLAPPED()
        >>> lpOverlapped.hEvent = hEvent
        >>> bytes_written = WriteFile(
        ...     hFile, "Hello world", lpOverlapped=lpOverlapped)

    :returns:
        Returns the number of bytes written.
    """
    ffi, library = dist.load()

    input_check("hFile", hFile, HANDLE)
    input_check("lpBuffer", lpBuffer, binary_type)
    input_check(
        "lpOverlapped", lpOverlapped,
        allowed_types=(NoneType, OVERLAPPED)
    )

    if nNumberOfBytesToWrite is None:
        nNumberOfBytesToWrite = len(lpBuffer)
    else:
        input_check(
            "nNumberOfBytesToWrite", nNumberOfBytesToWrite,
            integer_types
        )

    bytes_written = ffi.new("LPDWORD")
    code = library.WriteFile(
        wintype_to_cdata(hFile), lpBuffer, nNumberOfBytesToWrite,
        bytes_written, wintype_to_cdata(lpOverlapped)
    )
    error_check("WriteFile", code=code, expected=Enums.NON_ZERO)

    return bytes_written[0]
Example #33
0
def handle_from_file(file_):
    """
    Converts a standard Python file object into a :class:`HANDLE` object.

    .. warning::

        This function is mainly intended for internal use.  Passing in a file
        object with an invalid file descriptor may crash your interpreter.

    :param file file_:
        The Python file object to convert to a :class:`HANDLE` object.

    :raises InputError:
        Raised if ``file_`` does not appear to be a file object or is currently
        closed.

    :rtype: :class:`HANDLE`
    """
    try:
        fileno = file_.fileno()
    except AttributeError:
        raise InputError("file_",
                         file_,
                         allowed_types=None,
                         message="Expected a file like object for `file_`")
    except ValueError:
        raise InputError(
            "file_",
            file_,
            allowed_types=None,
            message="Expected an open file like object for `file_`")
    else:
        _, library = dist.load()
        return HANDLE(library.handle_from_fd(fileno))
Example #34
0
 def test_get_handle_info_stdin(self):
     _, library = dist.load()
     stdin_handle = GetStdHandle(library.STD_INPUT_HANDLE)
     handle_flags = GetHandleInformation(stdin_handle)
     inherit = handle_flags & library.HANDLE_FLAG_INHERIT
     expected = (0, library.HANDLE_FLAG_INHERIT)
     self.assertIn(inherit, expected)
Example #35
0
 def __repr__(self):
     ffi, _ = dist.load()
     return "<%s 0x%x at 0x%x>" % (
         self.__class__.__name__,
         int(ffi.cast("intptr_t", self._cdata[0])),
         id(self)
     )
Example #36
0
def wintype_to_cdata(wintype):
    """
    Returns the underlying CFFI cdata object or ffi.NULL if wintype is None.
    Used internally in API wrappers to "convert" pywincffi's Python types to
    the required CFFI cdata objects when calling CFFI functions. Example:

    >>> from pywincffi.core import dist
    >>> from pywincffi.kernel32 import CreateEvent
    >>> from pywincffi.wintypes import wintype_to_cdata
    >>> ffi, lib = dist.load()
    >>> # Get an event HANDLE, using the wrapper: it's a Python HANDLE object.
    >>> hEvent = CreateEvent(False, False)
    >>> # Call ResetEvent directly without going through the wrapper:
    >>> hEvent_cdata = wintype_to_cdata(hEvent)
    >>> result = lib.ResetEvent(hEvent_cdata)

    :param wintype:
        A type derived from :class:`pywincffi.core.typesbase.CFFICDataWrapper`

    :return:
        The underlying CFFI <cdata> object, or ffi.NULL if wintype is None.
    """
    ffi, _ = dist.load()
    if wintype is None:
        return ffi.NULL
    elif isinstance(wintype, (SOCKET, HANDLE, WSAEVENT)):
        return wintype._cdata[0]
    else:
        return wintype._cdata
Example #37
0
def handle_from_file(file_):
    """
    Converts a standard Python file object into a :class:`HANDLE` object.

    .. warning::

        This function is mainly intended for internal use.  Passing in a file
        object with an invalid file descriptor may crash your interpreter.

    :param file file_:
        The Python file object to convert to a :class:`HANDLE` object.

    :raises InputError:
        Raised if ``file_`` does not appear to be a file object or is currently
        closed.

    :rtype: :class:`HANDLE`
    """
    try:
        fileno = file_.fileno()
    except AttributeError:
        raise InputError(
            "file_", file_, allowed_types=None,
            message="Expected a file like object for `file_`")
    except ValueError:
        raise InputError(
            "file_", file_, allowed_types=None,
            message="Expected an open file like object for `file_`")
    else:
        _, library = dist.load()
        return HANDLE(library.handle_from_fd(fileno))
Example #38
0
def wintype_to_cdata(wintype):
    """
    Returns the underlying CFFI cdata object or ffi.NULL if wintype is None.
    Used internally in API wrappers to "convert" pywincffi's Python types to
    the required CFFI cdata objects when calling CFFI functions. Example:

    >>> from pywincffi.core import dist
    >>> from pywincffi.kernel32 import CreateEvent
    >>> from pywincffi.wintypes import wintype_to_cdata
    >>> ffi, lib = dist.load()
    >>> # Get an event HANDLE, using the wrapper: it's a Python HANDLE object.
    >>> hEvent = CreateEvent(bManualReset=False, bInitialState=False)
    >>> # Call ResetEvent directly without going through the wrapper:
    >>> hEvent_cdata = wintype_to_cdata(hEvent)
    >>> result = lib.ResetEvent(hEvent_cdata)

    :param wintype:
        A type derived from :class:`pywincffi.core.typesbase.CFFICDataWrapper`

    :return:
        The underlying CFFI <cdata> object, or ffi.NULL if wintype is None.
    """
    ffi, _ = dist.load()
    if wintype is None:
        return ffi.NULL

    if isinstance(wintype, (SOCKET, HANDLE, WSAEVENT)):
        return wintype._cdata[0]

    return wintype._cdata
Example #39
0
def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
    """
    Opens an existing local process object.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms684320

    :param int dwDesiredAccess:
        The required access to the process object.

    :param bool bInheritHandle:
        Enables or disable handle inheritance for child processes.

    :param int dwProcessId:
        The id of the local process to be opened.

    :returns:
        Returns a :class:`pywincffi.wintypes.HANDLE` to the opened process.
        This value can be used by other functions such as
        :func:`TerminateProcess`.
    """
    input_check("dwDesiredAccess", dwDesiredAccess, integer_types)
    input_check("bInheritHandle", bInheritHandle, bool)
    input_check("dwProcessId", dwProcessId, integer_types)
    ffi, library = dist.load()

    handle = library.OpenProcess(ffi.cast("DWORD", dwDesiredAccess),
                                 ffi.cast("BOOL", bInheritHandle),
                                 ffi.cast("DWORD", dwProcessId))
    error_check("OpenProcess")
    return HANDLE(handle)
Example #40
0
def GetExitCodeProcess(hProcess):
    """
    Retrieves the exit code of the given process handle.  To retrieve
    a process handle use :func:`OpenProcess`.

    .. warning::

        You may want to use :func:`process_exit_code` instead of this
        function if you're just checking to see if a process has
        exited at all.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms683189

    :param pywincffi.wintypes.HANDLE hProcess:
        The handle of the process to retrieve the exit code for.

    :returns:
        Returns the exit code of the requested process if one
        can be found.
    """
    input_check("hProcess", hProcess, HANDLE)

    ffi, library = dist.load()
    lpExitCode = ffi.new("LPDWORD")
    code = library.GetExitCodeProcess(wintype_to_cdata(hProcess), lpExitCode)
    error_check("GetExitCodeProcess", code=code, expected=NON_ZERO)
    return lpExitCode[0]
Example #41
0
def SetNamedPipeHandleState(hNamedPipe,
                            lpMode=None,
                            lpMaxCollectionCount=None,
                            lpCollectDataTimeout=None):
    """
    Sets the read and blocking mode of the specified ``hNamedPipe``.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/aa365787

    :param pywincffi.wintypes.HANDLE hNamedPipe:
        A handle to the named pipe instance.

    :keyword int lpMode:
        The new pipe mode which is a combination of read mode:

            * ``PIPE_READMODE_BYTE``
            * ``PIPE_READMODE_MESSAGE``

        And a wait-mode flag:

            * ``PIPE_WAIT``
            * ``PIPE_NOWAIT``

    :keyword int lpMaxCollectionCount:
        The maximum number of bytes collected.

    :keyword int lpCollectDataTimeout:
        The maximum time, in milliseconds, that can pass before a
        remote named pipe transfers information
    """
    input_check("hNamedPipe", hNamedPipe, HANDLE)
    ffi, library = dist.load()

    if lpMode is None:
        lpMode = ffi.NULL
    else:
        input_check("lpMode", lpMode, integer_types)
        lpMode = ffi.new("LPDWORD", lpMode)

    if lpMaxCollectionCount is None:
        lpMaxCollectionCount = ffi.NULL
    else:
        input_check("lpMaxCollectionCount", lpMaxCollectionCount,
                    integer_types)
        lpMaxCollectionCount = ffi.new("LPDWORD", lpMaxCollectionCount)

    if lpCollectDataTimeout is None:
        lpCollectDataTimeout = ffi.NULL
    else:
        input_check("lpCollectDataTimeout", lpCollectDataTimeout,
                    integer_types)
        lpCollectDataTimeout = ffi.new("LPDWORD", lpCollectDataTimeout)

    code = library.SetNamedPipeHandleState(wintype_to_cdata(hNamedPipe),
                                           lpMode, lpMaxCollectionCount,
                                           lpCollectDataTimeout)
    error_check("SetNamedPipeHandleState", code=code, expected=NON_ZERO)
Example #42
0
def LockFileEx(hFile,
               dwFlags,
               nNumberOfBytesToLockLow,
               nNumberOfBytesToLockHigh,
               lpOverlapped=None):
    """
    Locks ``hFile`` for exclusive access by the calling process.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/aa365203

    :param pywincffi.wintypes.HANDLE hFile:
        The handle to the file to lock.  This handle must have been
        created with either the ``GENERIC_READ`` or ``GENERIC_WRITE``
        right.

    :param int dwFlags:
        One or more of the following flags:

            * ``LOCKFILE_EXCLUSIVE_LOCK`` - Request an exclusive lock.
            * ``LOCKFILE_FAIL_IMMEDIATELY`` - Return immediately if the lock
              could not be acquired.  Otherwise :func:`LockFileEx` will wait.

    :param int nNumberOfBytesToLockLow:
        The start of the byte range to lock.

    :param int nNumberOfBytesToLockHigh:
        The end of the byte range to lock.

    :keyword pywincffi.wintypes.OVERLAPPED lpOverlapped:
        The underlying Windows API requires lpOverlapped, which acts both
        an input argument and may contain results after calling. If None is
        provided, a throw-away zero-filled instance will be created to
        support such call. See Microsoft's documentation for intended usage.
    """
    input_check("hFile", hFile, HANDLE)
    input_check("dwFlags", dwFlags, integer_types)
    input_check("nNumberOfBytesToLockLow", nNumberOfBytesToLockLow,
                integer_types)
    input_check("nNumberOfBytesToLockHigh", nNumberOfBytesToLockHigh,
                integer_types)

    ffi, library = dist.load()

    if lpOverlapped is None:
        # Required by Windows API, create a throw-away zero-filled instance.
        lpOverlapped = OVERLAPPED()
    else:
        input_check("lpOverlapped", lpOverlapped, allowed_types=OVERLAPPED)

    code = library.LockFileEx(
        wintype_to_cdata(hFile),
        ffi.cast("DWORD", dwFlags),
        ffi.cast("DWORD", 0),  # "_Reserveved_"
        ffi.cast("DWORD", nNumberOfBytesToLockLow),
        ffi.cast("DWORD", nNumberOfBytesToLockHigh),
        wintype_to_cdata(lpOverlapped))
    error_check("LockFileEx", code=code, expected=NON_ZERO)
Example #43
0
    def test_process_still_active(self):
        process = self.create_python_process("import time; time.sleep(5)")
        pid = process.pid

        _, library = dist.load()
        hProcess = OpenProcess(library.PROCESS_QUERY_INFORMATION, False, pid)
        self.addCleanup(CloseHandle, hProcess)
        self.assertEqual(GetExitCodeProcess(hProcess), library.STILL_ACTIVE)
Example #44
0
 def test_message_allowed_types_type_of_failure(self):
     ffi, _ = dist.load()
     error = InputError("", 1, ffi=ffi, allowed_types=(int,))
     name = "type" if PY2 else "class"
     self.assertEqual(
         error.message,
         "Expected type(s) (<%s 'int'>,) for ''. Type of '' is "
         "<%s 'int'>." % (name, name))
Example #45
0
    def test_returns_handle(self):
        _, library = dist.load()

        handle = OpenProcess(library.PROCESS_QUERY_INFORMATION, False,
                             os.getpid())

        self.assertIsInstance(handle, HANDLE)
        CloseHandle(handle)
Example #46
0
    def test_lpCommandLine_length_max_path(self):
        with mock_library(CreateProcess=self.NoOpCreateProcess):
            _, library = dist.load()

            match = ".*cannot exceed %s.*" % library.MAX_PATH
            with self.assertRaisesRegex(InputError, match):
                CreateProcess(u"'%s' arg1" %
                              self.random_string(library.MAX_PATH + 1))
Example #47
0
    def test_lpCommandLine_length_max_path(self):
        with mock_library(CreateProcess=self.NoOpCreateProcess):
            _, library = dist.load()

            match = ".*cannot exceed %s.*" % library.MAX_PATH
            with self.assertRaisesRegex(InputError, match):
                CreateProcess(
                    u"'%s' arg1" % self.random_string(library.MAX_PATH + 1))
Example #48
0
 def __init__(self):
     ffi, _ = dist.load()
     super(SECURITY_ATTRIBUTES, self).__init__(
         "SECURITY_ATTRIBUTES*",
         ffi,
     )
     self._cdata.nLength = ffi.sizeof(self._cdata)
     self.lpSecurityDescriptor = ffi.NULL
Example #49
0
 def test_message_allowed_types_type_of_failure(self):
     ffi, _ = dist.load()
     error = InputError("", 1, ffi=ffi, allowed_types=(int, ))
     name = "type" if PY2 else "class"
     self.assertEqual(
         error.message,
         "Expected type(s) (<%s 'int'>,) for ''. Type of '' is "
         "<%s 'int'>." % (name, name))
Example #50
0
def LockFileEx(
        hFile, dwFlags, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh,
        lpOverlapped=None):
    """
    Locks ``hFile`` for exclusive access by the calling process.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/aa365203

    :param pywincffi.wintypes.HANDLE hFile:
        The handle to the file to lock.  This handle must have been
        created with either the ``GENERIC_READ`` or ``GENERIC_WRITE``
        right.

    :param int dwFlags:
        One or more of the following flags:

            * ``LOCKFILE_EXCLUSIVE_LOCK`` - Request an exclusive lock.
            * ``LOCKFILE_FAIL_IMMEDIATELY`` - Return immediately if the lock
              could not be acquired.  Otherwise :func:`LockFileEx` will wait.

    :param int nNumberOfBytesToLockLow:
        The start of the byte range to lock.

    :param int nNumberOfBytesToLockHigh:
        The end of the byte range to lock.

    :keyword pywincffi.wintypes.OVERLAPPED lpOverlapped:
        The underlying Windows API requires lpOverlapped, which acts both
        an input argument and may contain results after calling. If None is
        provided, a throw-away zero-filled instance will be created to
        support such call. See Microsoft's documentation for intended usage.
    """
    input_check("hFile", hFile, HANDLE)
    input_check("dwFlags", dwFlags, integer_types)
    input_check(
        "nNumberOfBytesToLockLow", nNumberOfBytesToLockLow, integer_types)
    input_check(
        "nNumberOfBytesToLockHigh", nNumberOfBytesToLockHigh, integer_types)

    ffi, library = dist.load()

    if lpOverlapped is None:
        # Required by Windows API, create a throw-away zero-filled instance.
        lpOverlapped = OVERLAPPED()
    else:
        input_check("lpOverlapped", lpOverlapped, allowed_types=OVERLAPPED)

    code = library.LockFileEx(
        wintype_to_cdata(hFile),
        ffi.cast("DWORD", dwFlags),
        ffi.cast("DWORD", 0),  # "_Reserveved_"
        ffi.cast("DWORD", nNumberOfBytesToLockLow),
        ffi.cast("DWORD", nNumberOfBytesToLockHigh),
        wintype_to_cdata(lpOverlapped)
    )
    error_check("LockFileEx", code=code, expected=NON_ZERO)
Example #51
0
def CreateEvent(bManualReset,
                bInitialState,
                lpEventAttributes=None,
                lpName=None):
    """
    Creates or opens an named or unnamed event object.

    .. seealso::

        https://msdn.microsoft.com/en-us/library/ms682396

    :param bool bManualReset:
        If True then this function will create a manual reset
        event which must be manually reset with :func:`ResetEvent`.  Refer
        to the msdn documentation for full information.

    :param bool bInitialState:
        If True the initial state will be 'signaled'.

    :keyword :class:`pywincffi.wintypes.SECURITY_ATTRIBUTES` lpEventAttributes:
        If not provided then, by default, the handle cannot be inherited
        by a subprocess.

    :keyword str lpName:
        Type is ``unicode`` on Python 2, ``str`` on Python 3.
        The optional case-sensitive name of the event.  If not provided then
        the event will be created without an explicit name.

    :returns:
        Returns a :class:`pywincffi.wintypes.HANDLE` to the event. If an event
        by the given name already exists then it will be returned instead of
        creating a new event.
    """
    input_check("bManualReset", bManualReset, bool)
    input_check("bInitialState", bInitialState, bool)

    ffi, library = dist.load()

    if lpName is None:
        lpName = ffi.NULL
    else:
        input_check("lpName", lpName, text_type)

    input_check("lpEventAttributes",
                lpEventAttributes,
                allowed_types=(SECURITY_ATTRIBUTES, NoneType))

    handle = library.CreateEvent(wintype_to_cdata(lpEventAttributes),
                                 ffi.cast("BOOL", bManualReset),
                                 ffi.cast("BOOL", bInitialState), lpName)

    try:
        error_check("CreateEvent")
    except WindowsAPIError as error:
        if error.errno != library.ERROR_ALREADY_EXISTS:
            raise

    return HANDLE(handle)