Source code for pywincffi.kernel32.file

"""
Files
-----

A module containing common Windows file functions for working with files.
"""

from six import integer_types, text_type, binary_type

from pywincffi.core import dist
from pywincffi.core.checks import NON_ZERO, input_check, error_check, NoneType
from pywincffi.exceptions import WindowsAPIError
from pywincffi.wintypes import (
    SECURITY_ATTRIBUTES, OVERLAPPED, HANDLE, wintype_to_cdata
)


[docs]def CreateFile( # pylint: disable=too-many-arguments lpFileName, dwDesiredAccess, dwShareMode=None, lpSecurityAttributes=None, dwCreationDisposition=None, dwFlagsAndAttributes=None, hTemplateFile=None): """ Creates or opens a file or other I/O device. Default values are provided for some of the default arguments for CreateFile() so its behavior is close to Pythons :func:`open` function. .. seealso:: https://msdn.microsoft.com/en-us/library/aa363858 https://msdn.microsoft.com/en-us/library/gg258116 :param str lpFileName: Type is ``unicode`` on Python 2, ``str`` on Python 3. The path to the file or device being created or opened. :param int dwDesiredAccess: The requested access to the file or device. Microsoft's documentation has extensive notes on this parameter in the seealso links above. :keyword int dwShareMode: Access and sharing rights to the handle being created. If not provided with an explicit value, ``FILE_SHARE_READ`` will be used which will other open operations or process to continue to read from the file. :keyword pywincffi.wintypes.SECURITY_ATTRIBUTES lpSecurityAttributes: See Microsoft's documentation for more detailed information. :keyword int dwCreationDisposition: Action to take when the file or device does not exist. If not provided with an explicit value, ``CREATE_ALWAYS`` will be used which means existing files will be overwritten. :keyword int dwFlagsAndAttributes: The file or device attributes and flags. If not provided an explict value, ``FILE_ATTRIBUTE_NORMAL`` will be used giving the handle essentially no special attributes. :keyword pywincffi.wintypes.HANDLE hTemplateFile: A handle to a template file with the ``GENERIC_READ`` access right. See Microsoft's documentation for more information. If not provided an explicit value, ``NULL`` will be used instead. :return: The file :class:`pywincffi.wintypes.HANDLE` created by ``CreateFile``. """ _, library = dist.load() if dwShareMode is None: dwShareMode = library.FILE_SHARE_READ if dwCreationDisposition is None: dwCreationDisposition = library.CREATE_ALWAYS if dwFlagsAndAttributes is None: dwFlagsAndAttributes = library.FILE_ATTRIBUTE_NORMAL input_check("lpFileName", lpFileName, text_type) input_check("dwDesiredAccess", dwDesiredAccess, integer_types) input_check("dwShareMode", dwShareMode, integer_types) input_check( "lpSecurityAttributes", lpSecurityAttributes, allowed_types=(NoneType, SECURITY_ATTRIBUTES) ) input_check( "dwCreationDisposition", dwCreationDisposition, allowed_values=( library.CREATE_ALWAYS, library.CREATE_NEW, library.OPEN_ALWAYS, library.OPEN_EXISTING, library.TRUNCATE_EXISTING ) ) input_check("dwFlagsAndAttributes", dwFlagsAndAttributes, integer_types) input_check("hTemplateFile", hTemplateFile, (NoneType, HANDLE)) handle = library.CreateFile( lpFileName, dwDesiredAccess, dwShareMode, wintype_to_cdata(lpSecurityAttributes), dwCreationDisposition, dwFlagsAndAttributes, wintype_to_cdata(hTemplateFile) ) try: error_check("CreateFile") except WindowsAPIError as error: # ERROR_ALREADY_EXISTS may be a normal condition depending # on the creation disposition. if (dwCreationDisposition == library.CREATE_ALWAYS and error.errno == library.ERROR_ALREADY_EXISTS): return HANDLE(handle) raise return HANDLE(handle)
[docs]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) ) expected = NON_ZERO if lpOverlapped is None else 0 error_check("WriteFile", code=code, expected=expected) return bytes_written[0]
[docs]def FlushFileBuffers(hFile): """ Flushes the buffer of the specified file to disk. .. seealso:: https://msdn.microsoft.com/en-us/library/aa364439 :param pywincffi.wintypes.HANDLE hFile: The handle to flush to disk. """ input_check("hFile", hFile, HANDLE) _, library = dist.load() code = library.FlushFileBuffers(wintype_to_cdata(hFile)) error_check("FlushFileBuffers", code=code, expected=NON_ZERO)
[docs]def ReadFile(hFile, nNumberOfBytesToRead, lpOverlapped=None): """ Read the specified number of bytes from ``hFile``. .. seealso:: https://msdn.microsoft.com/en-us/library/aa365467 :param pywincffi.wintypes.HANDLE hFile: The handle to read from. :param int nNumberOfBytesToRead: The number of bytes to read from ``hFile`` :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 ReadFile, CreateEvent >>> from pywincffi.wintypes import OVERLAPPED >>> hEvent = CreateEvent(...) >>> lpOverlapped = OVERLAPPED() >>> lpOverlapped.hEvent = hEvent >>> read_data = ReadFile( # read 12 bytes from hFile ... hFile, 12, lpOverlapped=lpOverlapped) :returns: Returns the binary data read from ``hFile`` Type is ``str`` on Python 2, ``bytes`` on Python 3. """ ffi, library = dist.load() input_check("hFile", hFile, HANDLE) input_check("nNumberOfBytesToRead", nNumberOfBytesToRead, integer_types) input_check( "lpOverlapped", lpOverlapped, allowed_types=(NoneType, OVERLAPPED) ) lpBuffer = ffi.new("char []", nNumberOfBytesToRead) bytes_read = ffi.new("LPDWORD") code = library.ReadFile( wintype_to_cdata(hFile), lpBuffer, nNumberOfBytesToRead, bytes_read, wintype_to_cdata(lpOverlapped) ) error_check("ReadFile", code=code, expected=NON_ZERO) return ffi.unpack(lpBuffer, bytes_read[0])
[docs]def MoveFileEx(lpExistingFileName, lpNewFileName, dwFlags=None): """ Moves an existing file or directory, including its children, see the MSDN documentation for full options. .. seealso:: https://msdn.microsoft.com/en-us/library/aa365240 :param str lpExistingFileName: Type is ``unicode`` on Python 2, ``str`` on Python 3. Name of the file or directory to perform the operation on. :param str lpNewFileName: Type is ``unicode`` on Python 2, ``str`` on Python 3. Optional new name of the path or directory. This value may be ``None``. :keyword int dwFlags: Parameters which control the operation of :func:`MoveFileEx`. See the MSDN documentation for full details. By default ``MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH`` is used. """ ffi, library = dist.load() if dwFlags is None: dwFlags = \ library.MOVEFILE_REPLACE_EXISTING | library.MOVEFILE_WRITE_THROUGH input_check("lpExistingFileName", lpExistingFileName, text_type) input_check("dwFlags", dwFlags, integer_types) if lpNewFileName is not None: input_check("lpNewFileName", lpNewFileName, text_type) else: lpNewFileName = ffi.NULL code = library.MoveFileEx( lpExistingFileName, lpNewFileName, ffi.cast("DWORD", dwFlags) ) error_check("MoveFileEx", code=code, expected=NON_ZERO)
[docs]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)
[docs]def UnlockFileEx( hFile, nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh, lpOverlapped=None): """ Unlocks a region in the specified file. .. seealso:: https://msdn.microsoft.com/en-us/library/aa365716 :param pywincffi.wintypes.HANDLE hFile: The handle to the file to unlock. This handle must have been created with either the ``GENERIC_READ`` or ``GENERIC_WRITE`` right. :param int nNumberOfBytesToUnlockLow: The start of the byte range to unlock. :param int nNumberOfBytesToUnlockHigh: The end of the byte range to unlock. :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( "nNumberOfBytesToUnlockLow", nNumberOfBytesToUnlockLow, integer_types) input_check( "nNumberOfBytesToUnlockHigh", nNumberOfBytesToUnlockHigh, 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.UnlockFileEx( wintype_to_cdata(hFile), ffi.cast("DWORD", 0), # "_Reserveved_" ffi.cast("DWORD", nNumberOfBytesToUnlockLow), ffi.cast("DWORD", nNumberOfBytesToUnlockHigh), wintype_to_cdata(lpOverlapped) ) error_check("UnlockFileEx", code=code, expected=NON_ZERO)
[docs]def GetTempPath(): """ Retrieves the path of the directory designated for temporary files. .. seealso:: https://msdn.microsoft.com/en-us/aa364992 :returns: Returns a string containing the value produced by the underlying C function. """ ffi, library = dist.load() lpBuffer = ffi.new("TCHAR[{}]".format(library.MAX_PATH + 1)) code = library.GetTempPath(library.MAX_PATH + 1, lpBuffer) error_check("GetTempPath", code=code, expected=NON_ZERO) return ffi.string(lpBuffer)