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)
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
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)
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)
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)
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.")
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
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)
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)
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)
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))
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.")
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)
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)
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)
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)
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)
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
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)
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)
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)
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))
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)
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)
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
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]
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)
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)
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]
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))
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)
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) )
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
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))
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
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)
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]
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)
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)
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)
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))
def test_returns_handle(self): _, library = dist.load() handle = OpenProcess(library.PROCESS_QUERY_INFORMATION, False, os.getpid()) self.assertIsInstance(handle, HANDLE) CloseHandle(handle)
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))
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))
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
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))
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)
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)