Ejemplo n.º 1
0
    def test_lpStartupInfo_input_handling(self):
        with mock_library(CreateProcess=self.NoOpCreateProcess):
            with self.assertRaises(InputError):
                CreateProcess(text_type(sys.executable),
                              lpApplicationName=None,
                              lpProcessAttributes=None,
                              lpThreadAttributes=None,
                              bInheritHandles=True,
                              dwCreationFlags=None,
                              lpEnvironment=None,
                              lpCurrentDirectory=None,
                              lpStartupInfo=1)

            CreateProcess(text_type(sys.executable),
                          lpApplicationName=None,
                          lpProcessAttributes=None,
                          lpThreadAttributes=None,
                          bInheritHandles=True,
                          dwCreationFlags=None,
                          lpEnvironment=None,
                          lpCurrentDirectory=None,
                          lpStartupInfo=STARTUPINFO())
Ejemplo n.º 2
0
def CreateProcess(  # pylint: disable=too-many-arguments,too-many-branches
        lpCommandLine,
        lpApplicationName=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

    :param 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 pywincffi.wintypes.STARTUPINFO lpStartupInfo:
        See Microsoft's documentation for additional information.

        .. warning::

            The STARTUPINFOEX structure is not currently supported
            for this input.

    :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`
    """
    ffi, library = dist.load()

    if len(lpCommandLine) > library.MAX_COMMAND_LINE:
        raise InputError("lpCommandLine",
                         lpCommandLine,
                         text_type,
                         message="lpCommandLine's length "
                         "cannot exceed %s" % 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 %s if `lpApplicationName` "
                "is not set. Module name was %r" % (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))
    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)
Ejemplo n.º 3
0
 def test_hStdError_error(self):
     info = STARTUPINFO()
     with self.assertRaises(TypeError):
         info.hStdError = 1
Ejemplo n.º 4
0
 def test_hStdError_set(self):
     info = STARTUPINFO()
     handle = HANDLE()
     info.hStdError = handle
     self.assertEqual(info.hStdError, handle)
Ejemplo n.º 5
0
 def test_hStdOutput_set(self):
     info = STARTUPINFO()
     handle = HANDLE()
     info.hStdOutput = handle
     self.assertEqual(info.hStdOutput, handle)
Ejemplo n.º 6
0
 def test_hStdError_get(self):
     info = STARTUPINFO()
     self.assertIsInstance(info.hStdError, HANDLE)
Ejemplo n.º 7
0
 def test_hStdOutput_get(self):
     info = STARTUPINFO()
     self.assertIsInstance(info.hStdOutput, HANDLE)
Ejemplo n.º 8
0
 def test_hStdError_error(self):
     info = STARTUPINFO()
     with self.assertRaises(TypeError):
         info.hStdError = 1
Ejemplo n.º 9
0
 def test_hStdError_set(self):
     info = STARTUPINFO()
     handle = HANDLE()
     info.hStdError = handle
     self.assertEqual(info.hStdError, handle)
Ejemplo n.º 10
0
 def test_hStdOutput_set(self):
     info = STARTUPINFO()
     handle = HANDLE()
     info.hStdOutput = handle
     self.assertEqual(info.hStdOutput, handle)