I was trying to create a new file using ctypes
in python. The file gets created and I am able to write in to it. The problem starts when I try to read from this file. It gives me an invalid file handle error. Anyone might know why this is the case.
The following is the code I used:
from ctypes import *
def CreateFile(file_name='',data=''):
file_handler=windll.Kernel32.CreateFileA(file_name,0x10000000,0,None,4,0x80,None)
pointer_to_written_data=c_int(0)
windll.Kernel32.WriteFile(file_handler,data,len(data),byref(pointer_to_written_data),None)
windll.Kernel32.CloseHandle(file_handler)
return
def ReadAFile(file_name=''):
file_handler=windll.Kernel32.CreateFileA(file_name,0x10000000,0,None,4,0x80,None)
data=create_string_buffer(4096)
pointer_to_read_data=c_int(0)
if(windll.Kernel32.ReadFile(file_handler,byref(data),1024,byref(pointer_to_read_data),None)==0):
print "Failed"
print windll.Kernel32.GetLastError()
windll.Kernel32.CloseHandle(file_handler)
print data.value
return
CreateFile("sample.txt","This is a test file!!")
ReadAFile("sample.txt")
Your code works as is after the CloseHandle
edit.
When you weren't closing the file handle in CreateFile()
, the file open in ReadAFile
failed because the file was already open. You didn't check the error so your call to ReadFile
failed. Now that the code is edited to have the CloseHandle
in CreateFile
, it works. Note you may need to close and re-open your IDE as it may keep a handle open to the file until you kill the process since it was a handle leak (I had that issue).
I also find in ctypes that being explicit and defining argtypes
, restype
, and errcheck
is useful. errcheck
especially, since code will throw an error and you don't have to check return values for failure.
Note: Original Python 2 code edited for Python 3 and updated to use Unicode Win32 APIs. See edit history for original.
import ctypes as ct
import ctypes.wintypes as w
INVALID_HANDLE_VALUE = w.HANDLE(-1).value
GENERIC_ALL = 0x10000000
OPEN_ALWAYS = 4
FILE_ATTRIBUTE_NORMAL = 0x80
kernel32 = ct.WinDLL('kernel32', use_last_error=True)
CreateFileW = kernel32.CreateFileW
WriteFile = kernel32.WriteFile
ReadFile = kernel32.ReadFile
CloseHandle = kernel32.CloseHandle
def validate_handle(result, func, args):
if result == INVALID_HANDLE_VALUE:
raise ct.WinError(get_last_error())
return result
def validate_bool(result, func, args):
if not result:
raise ct.WinError(get_last_error())
CreateFileW.argtypes = w.LPCWSTR, w.DWORD, w.DWORD, ct.c_void_p, w.DWORD, w.DWORD, w.HANDLE
CreateFileW.restype = w.HANDLE
CreateFileW.errcheck = validate_handle
WriteFile.argtypes = w.HANDLE, ct.c_void_p, w.DWORD, w.LPDWORD, ct.c_void_p
WriteFile.restype = w.BOOL
WriteFile.errcheck = validate_bool
ReadFile.argtypes = w.HANDLE, w.LPVOID, w.DWORD, w.LPDWORD, ct.c_void_p
ReadFile.restype = w.BOOL
ReadFile.errcheck = validate_bool
CloseHandle.argtypes = w.HANDLE,
CloseHandle.restype = w.BOOL
CloseHandle.errcheck = validate_bool
def CreateFile(file_name='', data=''):
file_handler = CreateFileW(file_name, GENERIC_ALL, 0, None, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, None)
written = w.DWORD()
try:
WriteFile(file_handler, data, len(data) * ct.sizeof(w.WCHAR), ct.byref(written), None)
finally:
CloseHandle(file_handler)
def ReadAFile(file_name=''):
file_handler = CreateFileW(file_name, GENERIC_ALL, 0, None, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, None)
data = ct.create_unicode_buffer(4096)
read = w.DWORD()
try:
ReadFile(file_handler, ct.byref(data), 1024, ct.byref(read), None)
finally:
CloseHandle(file_handler)
print(data.value)
CreateFile('sample.txt', 'This is a test file!!')
ReadAFile('sample.txt')