Reputation: 35
I am trying to list a directory with FindFirstFileW and FindNextFileW in python using ctypes. The FindFirstFileW is successful but FindNextFileW or FindClose results in OSError: exception: access violation writing 0xFFFFFFFFB8093F80
This is the code:
def assert_success(success):
if not success:
raise AssertionError(FormatError())
def assert_handle(handle):
if handle == INVALID_HANDLE_VALUE:
raise AssertionError(FormatError())
def FindFirstFileW(lpFileName):
wfd = WIN32_FIND_DATAW()
handle = windll.kernel32.FindFirstFileW(lpFileName, byref(wfd))
assert_handle(handle)
return handle, wfd
def FindNextFileW(handle):
wfd = WIN32_FIND_DATAW()
success = windll.kernel32.FindNextFileW(handle, byref(wfd))
assert_success(success)
return wfd
def FindClose(handle):
success = windll.kernel32.FindClose(handle)
assert_success(success)
return success
handle, wfd = FindFirstFileW('C:\\Windows\\*')
print(wfd.cFileName)
wfd = FindNextFileW(handle)
print(wfd.cFileName)
FindClose(handle)
Upvotes: 0
Views: 530
Reputation: 178399
You haven't set .argtypes
and .restype
appropriately for the functions being used. ctypes
assumes return values are c_int
for example, but handles are 64-bit on 64-bit Python and getting truncated to 32 bits. Plus you get the added benefit of type checking your calls since ctypes
knows what the parameter types are supposed to be.
Also recommend .errcheck
for automatically checking return values:
Try this:
from ctypes import *
from ctypes import wintypes as w
INVALID_HANDLE_VALUE = w.HANDLE(-1).value
ERROR_NO_MORE_FILES = 18
def boolcheck(result,func,args):
if not result:
raise WinError(get_last_error())
return None
# return True if more files
# return False if no more files
# raise exception for other reasons
def nomorecheck(result,func,args):
if not result and get_last_error() != ERROR_NO_MORE_FILES:
raise WinError(get_last_error())
return result
def handlecheck(result,func,args):
if result == INVALID_HANDLE_VALUE:
raise WinError(get_last_error())
return result
dll = WinDLL('kernel32',use_last_error=True)
dll.FindFirstFileW.argtypes = w.LPCWSTR,w.LPWIN32_FIND_DATAW
dll.FindFirstFileW.restype = w.HANDLE
dll.FindFirstFileW.errcheck = handlecheck
dll.FindNextFileW.argtypes = w.HANDLE,w.LPWIN32_FIND_DATAW
dll.FindNextFileW.restype = w.BOOL
dll.FindClose.errcheck = nomorecheck
dll.FindClose.argtypes = w.HANDLE,
dll.FindClose.restype = w.BOOL
dll.FindClose.errcheck = boolcheck
def find_files(directory):
wfd = w.WIN32_FIND_DATAW()
handle = dll.FindFirstFileW(directory, byref(wfd))
yield wfd.cFileName
while dll.FindNextFileW(handle, byref(wfd)):
yield wfd.cFileName
dll.FindClose(handle)
for file in find_files(r'c:\windows\*'):
print(file)
Upvotes: 1