pywincffi/kernel32/process.py
RESERVED_PIDS = set([0, 4])
def _environment_to_string(environment):
def _text_to_wchar(text):
def module_name(path):
def pid_exists(pid, wait=0):
def GetExitCodeProcess(hProcess):
def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
def GetCurrentProcess():
def GetProcessId(Process):  # pylint: disable=invalid-name
def TerminateProcess(hProcess, uExitCode):
def CreateToolhelp32Snapshot(dwFlags, th32ProcessID):
def CreateProcess(  # pylint: disable=too-many-arguments,too-many-branches
        lpApplicationName=None, lpCommandLine=None, lpProcessAttributes=None,
        lpThreadAttributes=None, bInheritHandles=True, dwCreationFlags=None,
        lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
pywincffi/dev/testutil.py
def mock_library(**attributes):
    """
    Used to replace an attribute the library that :func:`dist.load`
    returns.  Useful for replacing part of the compiled library as part
    of the test.
    """
    ffi, library = dist.load()
    return patch.object(
        dist, "load", lambda: [ffi, LibraryWrapper(library, attributes)])
pywincffi/kernel32/handle.py
def CloseHandle(hObject):
    """
    Closes an open object handle.

    .. seealso::

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

    :type hObject: pywincffi.wintypes.HANDLE or pywincffi.wintypes.SOCKET
    :param hObject:
        The handle object to close.
    """
    input_check("hObject", hObject, (HANDLE, SOCKET))
    _, library = dist.load()

    code = library.CloseHandle(wintype_to_cdata(hObject))
    error_check("CloseHandle", code=code, expected=NON_ZERO)
pywincffi/kernel32/process.py
def TerminateProcess(hProcess, uExitCode):
    """
    Terminates the specified process and all of its threads.

    .. seealso::

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

    :param pywincffi.wintypes.HANDLE hProcess:
        A handle to the process to be terminated.

    :param int uExitCode:
        The exit code of the processes and threads as a result of calling
        this function.
    """
    input_check("hProcess", hProcess, HANDLE)
    input_check("uExitCode", uExitCode, integer_types)
    ffi, library = dist.load()
    code = library.TerminateProcess(
        wintype_to_cdata(hProcess),
        ffi.cast("UINT", uExitCode)
    )
    error_check("TerminateProcess", code=code, expected=NON_ZERO)
pywincffi/wintypes/structures.py
class SECURITY_ATTRIBUTES(CFFICDataWrapper):
    """
    .. seealso::

        https://msdn.microsoft.com/en-us/library/aa379560
    """
    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

    # pylint: disable=missing-docstring
    @property
    def nLength(self):
        return self._cdata.nLength

    # pylint: disable=missing-docstring,no-self-use
    @nLength.setter
    def nLength(self, _):
        # Can't raise AttributeError.
        # CFFICDataWrapper would fall back to setting self._cdata.nLength .
        raise TypeError("SECURITY_ATTRIBUTES.nLength is read-only")
pywincffi/kernel32/process.py
def GetProcessId(Process):  # pylint: disable=invalid-name
    """
    Returns the pid of the process handle provided in ``Process``.

    .. seealso::

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

    :param pywincffi.wintypes.HANDLE Process:
        The handle of the process.

    :return:
        Returns an integer which represents the pid of the given
        process handle.
    """
    input_check("Process", Process, HANDLE)
    _, library = dist.load()
    pid = library.GetProcessId(wintype_to_cdata(Process))
    error_check("GetProcessId")
    return pid
pywincffi/exceptions.py
class InputError(PyWinCFFIError):
    """
    A subclass of :class:`PyWinCFFIError` that's raised when invalid input
    is provided to a function.  Because we're passing inputs to C we have
    to be sure that the input(s) being provided are what we're expecting so
    we fail early and provide better error messages.

    :param str name:
        The name of the parameter being checked.

    :param value:
        The value of the parameter being checked.

    :keyword allowed_types:
        The expected type(s). If provided then the exception's message will
        be tailored to provide information about ``value``'s type and the
        possible input types.

    :keyword allowed_values:
        The expected value(s).  If provided then the exception's message will
        be tailored to provide information about what value(s) were allowed
        for ``value``.

    :keyword ffi:
        If ``value`` is a C object, ``ffi`` is provided and ``allowed_types``
        is provided as well then the provided ``ffi`` instance will be used
        to provide additional context.

    :keyword str message:
        A custom error message.  This will override the default error messages
        which :class:`InputError` would normally generate.  This can be
        helpful if there is a problem with a given input parameter to a
        function but it's unrelated to the type of input.
    """
    def __init__(  # pylint: disable=too-many-arguments
            self, name, value,
            allowed_types=None, allowed_values=None, ffi=None, message=None):
        if allowed_types is not None and allowed_values is not None:
            raise ValueError(
                "Please provide either `allowed_types` or `allowed_values`")

        if (allowed_types is None and allowed_values is None and
                message is None):
            raise ValueError(
                "Please provide `allowed_types`, `allowed_values` or "
                "`message`")

        self.name = name
        self.value = value
        self.allowed_types = allowed_types
        self.allowed_values = allowed_values
        self.message = message

        if self.message is None and self.allowed_types is not None:
            if ffi is None:
                typeof = repr(type(value))
            else:
                try:
                    ffi_exceptions = (TypeError, CDefError, ffi.error)
                except AttributeError:  # pragma: no cover
                    ffi_exceptions = (TypeError, CDefError)

                try:
                    typeof = ffi.typeof(value)
                except ffi_exceptions:
                    typeof = repr(type(value))
                else:
                    typeof = "{classname}(kind={kind}, cname={cname})".format(
                        classname=value.__class__.__name__,
                        kind=repr(typeof.kind), cname=repr(typeof.cname))

            self.message = \
                "Expected type(s) {expected} for {name}. Type of {name} " \
                "is {typeof}.".format(
                    expected=repr(allowed_types), name=repr(name),
                    typeof=typeof)

        elif self.message is None and self.allowed_values is not None:
            self.message = \
                "Expected the value of {name} to be in {values}. Value of " \
                "{name} is {value}.".format(
                    name=repr(name), values=allowed_values, value=repr(value))

        super(InputError, self).__init__(self.message)
pywincffi/kernel32/process.py
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)
pywincffi/kernel32/process.py
def CreateProcess(  # pylint: disable=too-many-arguments,too-many-branches
        lpApplicationName=None, lpCommandLine=None, lpProcessAttributes=None,
        lpThreadAttributes=None, bInheritHandles=True, dwCreationFlags=None,
        lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
    """
    Creates a new process and its primary thread.  The process will be
    created in the same security context as the original process.

    .. seealso::

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

    :keyword pywincffi.wintypes.STARTUPINFO lpStartupInfo:
        See Microsoft's documentation for additional information.

        .. warning::

            The STARTUPINFOEX structure is not currently supported
            for this input.

    :keyword str lpCommandLine:
        The command line to be executed.  The maximum length of this parameter
        is 32768.  If no value is provided for ``lpApplicationName`` then
        the module name portion of ``lpCommandLine`` cannot exceed
        ``MAX_PATH``.

    :keyword str lpApplicationName:
        The name of the module or application to be executed.  This can be
        either the fully qualified path name or a partial name.  The system
        path will not be searched.  If no value is provided for this keyword
        then the input to ``lpCommandLine`` will be used by Windows instead.

    :keyword pywincffi.wintypes.SECUREITY_ATTRIBUTES lpProcessAttributes:
        Determines whether the returned handle to the new process object
        can be inherited by child processes.  By default, the handle cannot be
        inherited.

    :keyword pywincffi.wintypes.SECUREITY_ATTRIBUTES lpThreadAttributes:
        Determines if the returned handle to the new thread object can
        be inherited by child processes.  By default, the thread cannot be
        inherited.

    :keyword bool bInheritHandles:
        If True (the default) the handles inherited by the calling process
        are inherited by the new process.

    :keyword int dwCreationFlags:
        Controls the priority class and creation of the process.  By default
        the process will flag will default to
        ``NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT``

    :keyword dict lpEnvironment:
        The environment for the new process.  By default the the process
        will be created with the same environment as the parent process.

        .. note::

            All keys and values in the environment must be either unicode
            (Python 2) or strings (Python 3).

        .. note::

            This keyword will completely override the current if you wish to
            update the current environment instead then you will need to make
            and update a copy.

        .. warning::

            Excluding certain system environment variables such as ``PATH`` or
            ``SYSTEMROOT`` may result in crashes or unexpected behaviors
            depending on the program being run.


    :keyword str lpCurrentDirectory:
        The full path to the current directory for the process.  If not
         provided then the process will have the same working directory
         as the parent process.

    :raises InputError:
        Raised if ``lpCommandLine`` is too long or there are other input
        problems.

    :rtype: :class:`pywincffi.kernel32.process.CreateProcessResult`
    :return:
        Returns a named tuple containing ``lpCommandLine`` and
        ``lpProcessInformation``.  The ``lpProcessInformation`` will
        be an instance of
        :class:`pywincffi.wintypes.structures.PROCESS_INFORMATION`
    """
    if lpCommandLine is None:
        raise InputError(
            "lpCommandLine", None,
            message="lpCommandLine in call to CreateProcess() may not be "
                    "None.")

    ffi, library = dist.load()

    if len(lpCommandLine) > library.MAX_COMMAND_LINE:
        raise InputError(
            "lpCommandLine", lpCommandLine, text_type,
            message="lpCommandLine's length "
                    "cannot exceed {0}".format(library.MAX_COMMAND_LINE))

    if lpApplicationName is None:
        lpApplicationName = ffi.NULL

        # If lpApplication name is not set then lpCommandLine's
        # module name cannot exceed MAX_PATH.  Rather than letting
        # this hit the Windows API and possibly fail we're check
        # before hand so we can provide a better exception.
        module = module_name(text_type(lpCommandLine))
        if len(module) > library.MAX_PATH:
            raise InputError(
                "lpCommandLine", lpCommandLine, text_type,
                message="lpCommandLine's module name length cannot "
                        "exceed {0} if `lpApplicationName` "
                        "is not set. Module name was {1!r}".format(
                            library.MAX_PATH, module))
    else:
        input_check(
            "lpApplicationName", lpApplicationName, allowed_types=(text_type,))

    input_check(
        "lpProcessAttributes", lpProcessAttributes,
        allowed_types=(SECURITY_ATTRIBUTES, NoneType))
    lpProcessAttributes = wintype_to_cdata(lpProcessAttributes)

    input_check(
        "lpThreadAttributes", lpThreadAttributes,
        allowed_types=(SECURITY_ATTRIBUTES, NoneType))
    lpThreadAttributes = wintype_to_cdata(lpThreadAttributes)

    input_check(
        "bInheritHandles", bInheritHandles, allowed_values=(True, False))

    if dwCreationFlags is None:
        dwCreationFlags = \
            library.NORMAL_PRIORITY_CLASS | library.CREATE_UNICODE_ENVIRONMENT

    input_check(
        "dwCreationFlags", dwCreationFlags, allowed_types=(integer_types, ))

    if lpEnvironment is not None:
        lpEnvironment = _text_to_wchar(_environment_to_string(lpEnvironment))
        dwCreationFlags = dwCreationFlags | library.CREATE_UNICODE_ENVIRONMENT
    else:
        lpEnvironment = ffi.NULL

    if lpCurrentDirectory is not None:
        input_check(
            "lpCurrentDirectory", lpCurrentDirectory,
            allowed_types=(text_type, ))
    else:
        lpCurrentDirectory = ffi.NULL

    if lpStartupInfo is not None:
        # TODO need to add support for STARTUPINFOEX (undocumented)
        input_check(
            "lpStartupInfo", lpStartupInfo, allowed_types=(STARTUPINFO, ))
    else:
        lpStartupInfo = STARTUPINFO()

    lpProcessInformation = PROCESS_INFORMATION()
    code = library.CreateProcess(
        lpApplicationName,
        lpCommandLine,
        lpProcessAttributes,
        lpThreadAttributes,
        bInheritHandles,
        dwCreationFlags,
        lpEnvironment,
        lpCurrentDirectory,
        wintype_to_cdata(lpStartupInfo),
        wintype_to_cdata(lpProcessInformation)
    )
    error_check("CreateProcess", code=code, expected=NON_ZERO)

    return CreateProcessResult(
        lpCommandLine=lpCommandLine,
        lpProcessInformation=lpProcessInformation)
pywincffi/wintypes/structures.py
class STARTUPINFO(CFFICDataWrapper):
    """
    .. seealso::
        https://msdn.microsoft.com/en-us/library/ms686331
    """
    def __init__(self):
        ffi, _ = dist.load()
        super(STARTUPINFO, self).__init__("STARTUPINFO *", ffi)

    @property
    def hStdInput(self):
        """
        Returns a :class:`pywincffi.wintypes.objects.HANDLE` instance
        for the ``hStdInput`` attribute.
        """
        return HANDLE(self._cdata.hStdInput)

    # pylint: disable=missing-docstring
    @hStdInput.setter
    def hStdInput(self, handle):
        if not isinstance(handle, HANDLE):
            raise TypeError("%r must be a HANDLE object" % handle)
        self._cdata.hStdInput = handle._cdata[0]

    @property
    def hStdOutput(self):
        """
        Returns a :class:`pywincffi.wintypes.objects.HANDLE` instance
        for the ``hStdOutput`` attribute.
        """
        return HANDLE(self._cdata.hStdOutput)

    # pylint: disable=missing-docstring
    @hStdOutput.setter
    def hStdOutput(self, handle):
        if not isinstance(handle, HANDLE):
            raise TypeError("%r must be a HANDLE object" % handle)
        self._cdata.hStdOutput = handle._cdata[0]

    @property
    def hStdError(self):
        """
        Returns a :class:`pywincffi.wintypes.objects.HANDLE` instance
        for the ``hStdError`` attribute.
        """
        return HANDLE(self._cdata.hStdError)

    # pylint: disable=missing-docstring
    @hStdError.setter
    def hStdError(self, handle):
        if not isinstance(handle, HANDLE):
            raise TypeError("%r must be a HANDLE object" % handle)
        self._cdata.hStdError = handle._cdata[0]
pywincffi/dev/testutil.py
class TestCase(_TestCase):  # pylint: disable=too-many-public-methods
    """
    A base class for all test cases.  By default the
    core test case just provides some extra functionality.
    """
    # A list of hosts and port to check for internet access on.  If we fail
    # to reach any of the hosts in `INTERNET_HOSTS` on `INTERNET_PORT` then
    # `HAS_INTERNET` will be set to False.
    INTERNET_PORT = 80
    INTERNET_HOSTS = ("github.com", "readthedocs.org", "example.com")
    REQUIRES_INTERNET = False
    HAS_INTERNET = None

    # Class level attributes used to access some specific Windows API
    # functions when testing.  This is kept separate from what `dist.load()`
    # produces so problems in the build don't break parts of the base TestCase.
    ffi = None
    kernel32 = None
    ws2_32 = None

    @classmethod
    def setUpClass(cls):
        # Reset everything back to the default values first.
        cls.ffi = None
        cls.kernel32 = None
        cls.ws2_32 = None
        cls.HAS_INTERNET = None

        # First run and this test case requires internet access.  Determine
        # if we have access to the internet then cache the value.
        if cls.REQUIRES_INTERNET and SharedState.HAS_INTERNET is None:
            original_timeout = socket.getdefaulttimeout()
            socket.setdefaulttimeout(1)

            try:
                for hostname in cls.INTERNET_HOSTS:
                    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    try:
                        sock.connect((hostname, cls.INTERNET_PORT))
                        SharedState.HAS_INTERNET = True
                        break

                    # pylint: disable=broad-except
                    except Exception:  # pragma: no cover
                        pass

                    finally:
                        sock.close()
                else:  # pragma: no cover
                    SharedState.HAS_INTERNET = False
            finally:
                socket.setdefaulttimeout(original_timeout)

        if os.name == "nt" and SharedState.ffi is None:
            try:
                ffi = FFI()
                ffi.set_unicode(True)
                ffi.cdef(dedent("""
                // kernel32 functions
                DWORD GetLastError(void);
                void SetLastError(DWORD);

                // ws2_32 functions
                void WSASetLastError(int);
                int WSAGetLastError(void);
                """))
                SharedState.ffi = ffi
                SharedState.kernel32 = ffi.dlopen("kernel32")
                SharedState.ws2_32 = ffi.dlopen("ws2_32")

            # pylint: disable=broad-except
            except Exception as error:  # pragma: no cover
                if os.name == "nt":
                    SharedState.ffi = error

        cls.HAS_INTERNET = SharedState.HAS_INTERNET
        cls.ffi = SharedState.ffi
        cls.kernel32 = SharedState.kernel32
        cls.ws2_32 = SharedState.ws2_32

    def setUp(self):  # pragma: no cover
        if self.REQUIRES_INTERNET and not self.HAS_INTERNET:
            if os.environ.get("CI"):
                self.fail(
                    "%s requires internet but we do not seem to be "
                    "connected." % self.__class__.__name__)

            self.skipTest("Internet unavailable")

        if os.name != "nt":
            return

        if isinstance(self.ffi, Exception):
            self.fail("FFI module setup failed: %s" % self.ffi)

        self.assertIsNotNone(
            self.kernel32, "setUp() failed: missing kernel32")
        self.assertIsNotNone(
            self.ws2_32, "setUp() failed: missing ws2_32")

        self.addCleanup(self.unhandled_error_check)

        # Always reset the last error to 0 between tests.  This ensures
        # that if an unhandled API error occurs it won't impact the
        # currently running test.  The cleanup step above will ensure that
        # tests that do not exit cleanly will cause a failure.
        self.kernel32.SetLastError(0)
        self.ws2_32.WSASetLastError(0)

    def GetLastError(self):  # pylint: disable=invalid-name
        """
        Returns a tuple containing output from the Windows GetLastError
        function and the associated error message.  The error message will
        be None if GetLastError() returns 0.
        """
        errno = self.kernel32.GetLastError()
        return errno, self.ffi.getwinerror(errno) if errno != 0 else None

    def WSAGetLastError(self):  # pylint: disable=invalid-name
        """
        Returns a tuple containing output from the Windows WSAGetLastError
        function and the associated error message.  The error message will
        be None if WSAGetLastError() returns 0.
        """
        errno = self.ws2_32.WSAGetLastError()
        return errno, self.ffi.getwinerror(errno) if errno != 0 else None

    def WSASetLastError(self, errno):  # pylint: disable=invalid-name
        """Wrapper for WSASetLastError()"""
        self.ws2_32.WSASetLastError(errno)

    def SetLastError(self, errno):  # pylint: disable=invalid-name
        """Wrapper for SetLastError()"""
        self.kernel32.SetLastError(errno)

    def unhandled_error_check(self):
        """
        A cleanup step which ensures that there are not any uncaught API
        errors left over.  Unhandled errors could be a sign of an unhandled
        testing artifact, improper API usage or other problem.  In any case,
        unhandled errors are often a source of test flake.
        """
        # Check for kernel32 errors.
        k32_errno, k32_message = self.GetLastError()
        self.assertEqual(
            k32_errno, 0,
            msg="Unhandled kernel32 error. Errno: %r. Message: %r" % (
                k32_errno, k32_message))

        # Check for ws2_32 errors.
        ws2_errno, ws2_message = self.WSAGetLastError()
        self.assertEqual(
            ws2_errno, 0,
            msg="Unhandled ws2_32 error. Errno: %r. Message: %r" % (
                ws2_errno, ws2_message))

    def _terminate_process(self, process):  # pylint: disable=no-self-use
        """
        Calls terminnate() on ``process`` and ignores any errors produced.
        """
        try:
            process.terminate()

        # pylint: disable=broad-except
        except Exception:  # pragma: no cover
            pass

    def create_python_process(self, command):
        """Creates a Python process that run ``command``"""
        process = subprocess.Popen(
            [sys.executable, "-c", command],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        self.addCleanup(self._terminate_process, process)
        return process

    def random_string(self, length):
        """
        Returns a random string as long as ``length``.  The first character
        will always be a letter.  All other characters will be A-F,
        A-F or 0-9.
        """
        if length < 1:  # pragma: no cover
            self.fail("Length must be at least 1.")

        # First character should always be a letter so the string
        # can be used in object names.
        output = choice(ascii_lowercase)
        length -= 1

        while length:
            length -= 1
            output += choice(ascii_lowercase + ascii_uppercase + "0123456789")

        return output

    def assert_last_error(self, errno):
        """
        This function will assert that the last unhandled error
        was ``errno``.  After the check the last error will be reset to
        zero.

        :param int errno:
            The expected value from GetLastError.
        """
        last_error, _ = self.GetLastError()
        self.assertEqual(last_error, errno)
        self.SetLastError(0)

    def maybe_assert_last_error(self, errno):
        """
        This function is similar to :meth:`assert_last_error` except
        it won't fail if the current error number is already 0.
        """
        last_error, _ = self.GetLastError()
        self.assertIn(last_error, (0, errno))
        self.SetLastError(0)
pywincffi/kernel32/process.py
RESERVED_PIDS = set([0, 4])
def _environment_to_string(environment):
def _text_to_wchar(text):
def module_name(path):
def pid_exists(pid, wait=0):
def GetExitCodeProcess(hProcess):
def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
def GetCurrentProcess():
def GetProcessId(Process):  # pylint: disable=invalid-name
def TerminateProcess(hProcess, uExitCode):
def CreateToolhelp32Snapshot(dwFlags, th32ProcessID):
def CreateProcess(  # pylint: disable=too-many-arguments,too-many-branches
        lpApplicationName=None, lpCommandLine=None, lpProcessAttributes=None,
        lpThreadAttributes=None, bInheritHandles=True, dwCreationFlags=None,
        lpEnvironment=None, lpCurrentDirectory=None, lpStartupInfo=None):
pywincffi/kernel32/process.py
def CreateToolhelp32Snapshot(dwFlags, th32ProcessID):
    """
    Takes a snapshot of the specified processes, as well as the heaps,
    modules, and threads used by these processes.

    .. seealso::

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

    :param int dwFlags:
        The portions of the system to be included in the snapshot.

    :param int th32ProcessID:
        The process identifier of the process to be included in the snapshot.

    :rtype: :class:`pywincffi.wintypes.HANDLE`

    :return:
        If the function succeeds,
        it returns an open handle to the specified snapshot.
    """
    input_check("dwFlags", dwFlags, integer_types)
    input_check("th32ProcessID", th32ProcessID, integer_types)
    ffi, library = dist.load()
    process_list = library.CreateToolhelp32Snapshot(
        ffi.cast("DWORD", dwFlags),
        ffi.cast("DWORD", th32ProcessID)
    )

    if process_list == library.INVALID_HANDLE_VALUE:  # pragma: no cover
        raise WindowsAPIError(
            "CreateToolhelp32Snapshot", "Invalid Handle",
            library.INVALID_HANDLE_VALUE,
            expected_return_code="not {0!r}".format(
                library.INVALID_HANDLE_VALUE))

    error_check("CreateToolhelp32Snapshot")

    return HANDLE(process_list)
pywincffi/kernel32/process.py
def pid_exists(pid, wait=0):
    """
    Returns True if there's a process associated with ``pid``.

    :param int pid:
        The id of the process to check for.

    :keyword int wait:
        An optional keyword that controls how long we tell
        :func:`WaitForSingleObject` to wait on the process.

    :raises ValidationError:
        Raised if there's a problem with the value provided for ``pid``.
    """
    input_check("pid", pid, integer_types)

    # Process IDs which always exist shouldn't need to continue
    # further.
    if pid in RESERVED_PIDS:
        return True

    _, library = dist.load()

    try:
        hProcess = OpenProcess(
            library.PROCESS_QUERY_INFORMATION | library.SYNCHRONIZE,
            False, pid)

    except WindowsAPIError as error:
        # If we can't access the process then it must exist
        # otherwise there would be nothing to access.  We
        # reach this bit of code if the pid in question
        # is owned by another user or the system and
        # the process running this code does not have the
        # rights to query the other process's information.
        if error.errno == library.ERROR_ACCESS_DENIED:
            library.SetLastError(0)
            return True

        # Sometimes the PID we're asking about no longer exists
        # in the stack anywhere so we'll get ERROR_INVALID_PARAMETER
        # so there's not any reason to continue further.
        if error.errno == library.ERROR_INVALID_PARAMETER:
            library.SetLastError(0)
            return False

        raise

    try:
        process_exit_code = GetExitCodeProcess(hProcess)

        # Process may or may not still be running.  If process_exit_code
        # seem to indicate the process is still alive then run one
        # last check to be certain.
        if process_exit_code == library.STILL_ACTIVE:
            wait_result = WaitForSingleObject(hProcess, wait)

            # The process was still running.
            if wait_result == library.WAIT_TIMEOUT:
                return True

            # The process exited while we were waiting
            # on it so it no longer exists.
            elif wait_result == library.WAIT_OBJECT_0:
                return False

            elif wait_result == library.WAIT_ABANDONED:
                raise PyWinCFFINotImplementedError(
                    "An unknown error occurred while running "
                    "pid_exists({0!r}).  It appears that the call to "
                    "WaitForSingleObject may be been terminated.".format(pid))

            else:
                raise PyWinCFFINotImplementedError(
                    "Unhandled result from "
                    "WaitForSingleObject(): {0!r}".format(wait_result))

        return False

    finally:
        CloseHandle(hProcess)
pywincffi/kernel32/process.py
def GetCurrentProcess():
    """
    Returns a handle to the current thread.

    .. seealso::

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

    .. note::

        Calling :func:`pywincffi.kernel32.handle.CloseHandle` on the handle
        produced by this function will produce an exception.

    :returns:
        The :class:`pywincffi.wintypes.HANDLE` to the current process.
    """
    _, library = dist.load()
    return HANDLE(library.GetCurrentProcess())
pywincffi/exceptions.py
class WindowsAPIError(PyWinCFFIError):
    """
    A subclass of :class:`PyWinCFFIError` that's raised when there was a
    problem calling a Windows API function.

    :param str function:
        The Windows API function being called when the error was raised.

    :param str error:
        A string representation of the error message.

    :param int errno:
        An integer representing the error.  This usually represents
        a constant which Windows has produced in response to a problem.

    :keyword int return_code:
        If the return value of a function has been checked the resulting
        code will be set as this value.

    :keyword int expected_return_code:
        The value we expected to receive for ``code``.
    """
    # pylint: disable=too-many-arguments
    def __init__(self, function, error, errno,
                 return_code=None, expected_return_code=None):
        self.function = function
        self.error = error
        self.errno = errno
        self.return_code = return_code
        self.expected_return_code = expected_return_code

        if return_code is None and expected_return_code is None:
            self.message = \
                "Error when calling {0}. Message from Windows API was " \
                "{1!r} (errno: {2}).".format(self.function, self.error, errno)

        elif return_code is not None and expected_return_code is not None:
            self.message = (
                "Error when calling {0}.  Expected to receive {1!r} from {2} "
                "but got {3!r} instead. (error: {4!r})".format(
                    self.function, self.return_code, self.function,
                    self.expected_return_code, self.error
                )
            )

        # Generic implementation which we should probably handle
        # better so throw a warning.
        else:  # pragma: no cover
            warnings.warn(Warning(), "Pre-formatting not available")
            self.message = (
                "Error when calling {0}. (error: {1}, errno: {2}, "
                "return_code: {3!r}, expected_return_code: {4!r})".format(
                    self.function, self.error, self.errno, self.return_code,
                    self.expected_return_code
                )
            )

        super(WindowsAPIError, self).__init__(self.message)

    def __repr__(self):
        return (
            "{0}({1!r}, {2!r}, {3!r}, return_code={4!r}, "
            "expected_return_code={5!r})".format(
                self.__class__.__name__, self.function, self.error,
                self.errno, self.return_code, self.expected_return_code))
pywincffi/wintypes/objects.py
class HANDLE(WrappedObject):
    """
    .. seealso::

        https://msdn.microsoft.com/en-us/library/aa383751
    """
    C_TYPE = "HANDLE[1]"
pywincffi/exceptions.py
class PyWinCFFINotImplementedError(InternalError):
    """
    Raised if we encounter a situation where we can't figure out what
    to do.  The message for this error should contain all the information
    necessary to implement a future work around.
    """
pywincffi/core/dist.py
MODULE_NAME = "_pywincffi"
HEADER_FILES = (
    resource_filename(
        "pywincffi", join("core", "cdefs", "headers", "typedefs.h")),
    resource_filename(
        "pywincffi", join("core", "cdefs", "headers", "constants.h")),
    resource_filename(
        "pywincffi", join("core", "cdefs", "headers", "structs.h")),
    resource_filename(
        "pywincffi", join("core", "cdefs", "headers", "functions.h")))
SOURCE_FILES = (
    resource_filename(
        "pywincffi", join("core", "cdefs", "sources", "main.c")), )
LIBRARIES = ("kernel32", "user32", "Ws2_32")
REGEX_SAL_ANNOTATION = re.compile(
    r"\b(_In_|_Inout_|_Out_|_Outptr_|_Reserved_)(opt_)?\b")
    _RUNTIME_CONSTANTS = dict(
        # Defined here because cffi can't handle negative values
        # in constants yet.
        INVALID_HANDLE_VALUE=-1,

        # The maximum length of the lpCommandLine input to a CreateProcess
        # call:
        #  https://msdn.microsoft.com/en-us/library/ms682425
        # Technically, this is not a Windows constant.  It's something that
        # pywincffi defines for ease of use and to limit the possibility of
        # typos.
        MAX_COMMAND_LINE=32768
    )
class LibraryWrapper(object):  # pylint: disable=too-few-public-methods
class Loader(object):
    def __init__(self, library):
    def __dir__(self):
    def __getattribute__(self, item):
    def __getattr__(self, item):
    def __repr__(self):  # pragma: no cover
    def set(cls, ffi, library):
    def get(cls):
def _import_path(path, module_name=MODULE_NAME):
def _read(*paths):
def _ffi(
        module_name=MODULE_NAME, headers=HEADER_FILES, sources=SOURCE_FILES,
        libraries=LIBRARIES):
def _compile(ffi, tmpdir=None, module_name=MODULE_NAME):
def load():
pywincffi/kernel32/process.py
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]


Question: import ctypes
import os
import shutil
import sys
import time
import tempfile
from textwrap import dedent
from os.path import isfile, basename
from mock import patch
from six import iteritems, text_type
from pywincffi.core import dist
from pywincffi.dev.testutil import TestCase, mock_library
from pywincffi.exceptions import (
    WindowsAPIError, PyWinCFFINotImplementedError, InputError)
from pywincffi.kernel32 import process as k32process
from pywincffi.kernel32 import (
    CloseHandle, OpenProcess, GetCurrentProcess, GetExitCodeProcess,
    GetProcessId, TerminateProcess, CreateToolhelp32Snapshot, CreateProcess,
    pid_exists)
from pywincffi.kernel32.process import (
    CreateProcessResult, _environment_to_string, _text_to_wchar, module_name)
from pywincffi.wintypes import HANDLE, SECURITY_ATTRIBUTES, STARTUPINFO
        # is no longer alive which is why pid_exists() checks
        # for an exit code.  For cases where the process
        # never should have existed however we should
        # expect to get False from pid_exists().  Here
        # we're attempting to do this with something
        # that should probably never exist.
        self.assertFalse(pid_exists(0xFFFFFFFC))

    def test_running_process(self):
        process = self.create_python_process("import time; time.sleep(5)")
        self.assertTrue(
            pid_exists(process.pid))

    def test_process_dies_while_waiting(self):
        # This condition should be very rare because of what the default
        # wait is set to but we check it anyway just in case.
        _, library = dist.load()
        process = self.create_python_process("import time; time.sleep(1)")
        self.assertFalse(pid_exists(process.pid, wait=library.INFINITE))

    def test_returns_false_for_process_with_exit_code_259(self):
        _, library = dist.load()
        process = self.create_python_process(
            "import sys; sys.exit({0})".format(library.STILL_ACTIVE))
        process.communicate()
        self.assertFalse(pid_exists(process.pid))

    def test_raises_unhandled_windows_api_error(self):
        def new_open_process(*args, **kwargs):
            raise WindowsAPIError("", "", 42)

        with patch.object(k32process, "OpenProcess", new_open_process):
            process = \
                self.create_python_process("import time; time.sleep(5)")

            with self.assertRaises(WindowsAPIError):
                self.assertTrue(pid_exists(process.pid))

    def test_raises_not_implemented_for_wait_abandoned(self):
        _, library = dist.load()

        with patch.object(
            k32process, "WaitForSingleObject",
            return_value=library.WAIT_ABANDONED
        ):
            process = \
                self.create_python_process("import time; time.sleep(5)")

            with self.assertRaises(PyWinCFFINotImplementedError):
                self.assertTrue(pid_exists(process.pid))

    def test_raises_not_implemented_for_other_wait_result(self):
        with patch.object(k32process, "WaitForSingleObject", return_value=42):
            process = \
                self.create_python_process("import time; time.sleep(5)")

            with self.assertRaises(PyWinCFFINotImplementedError):
                self.assertTrue(pid_exists(process.pid))

    def test_calls_closehandle(self):
        with patch.object(k32process, "CloseHandle") as mocked:
            process = \
                self.create_python_process("import time; time.sleep(5)")

            self.assertTrue(pid_exists(process.pid))

        self.assertEqual(mocked.call_count, 1)


class TestTerminateProcess(TestCase):
    """
    Tests for :func:`pywincffi.kernel32.TerminateProcess`
    """
    def test_terminates_process(self):
        process = self.create_python_process("import time; time.sleep(5)")
        _, library = dist.load()

        handle = OpenProcess(library.PROCESS_TERMINATE, False, process.pid)
        self.addCleanup(CloseHandle, handle)
        TerminateProcess(handle, 42)
        process.communicate()
        self.assertEqual(process.returncode, 42)


class TestCreateToolhelp32Snapshot(TestCase):
    """
    Tests for :func:`pywincffi.kernel32.CreateToolhelp32Snapshot`
    """
    def test_get_process_list(self):
        _, library = dist.load()

        handle = CreateToolhelp32Snapshot(library.TH32CS_SNAPPROCESS, 0)
        self.addCleanup(CloseHandle, handle)


class TestEnvironmentToString(TestCase):
    """
    Tests for :func:`pywincffi.kernel32.process.environment_to_string`
    """
    def test_non_dict_iteritems(self):
        class NonDictIterItems(object):
            def iteritems(self):
                yield (u"a", u"b")
                yield (u"c", u"d")

        self.assertEqual(
            _environment_to_string(NonDictIterItems()),
            u"a=b\0c=d\0\0")

    def test_non_dict_items(self):
        class NonDictItems(object):
            def items(self):
                yield (u"e", u"f")
                yield (u"g", u"h")

        self.assertEqual(
            _environment_to_string(NonDictItems()),
            u"e=f\0g=h\0\0")

    def test_type_check_for_environment_key(self):

Answer:         with self.assertRaises(InputError):