[python-win32] win32api.FindFiles hangs (was COM registration hangs up: 32 bit Python 3.7 on 64 bit Win 7)

eryk sun eryksun at gmail.com
Wed Dec 19 18:33:09 EST 2018


On 12/18/18, Boylan, Ross <Ross.Boylan at ucsf.edu> wrote:
> BTW, I installed Visual Studio and wrote a little C++ program that exercised
> FindNextFile.  It failed in exactly the same way (returns same filename
> forever if on a network drive and search spec has the exact file name), but
> only when run from the original machine.

The find-file handle returned by FindFirstFile[Ex] and used by
FindNextFile is a pointer to a structure that includes the directory
handle, a pointer to a 4 KiB file-record buffer (unless the caller
requests FIND_FIRST_EX_LARGE_FETCH, which uses a 64 KiB buffer), and a
pointer to the current entry's offset in the buffer. The buffer gets
filled via the native system call NtQueryDirectoryFile[Ex]. The
NextEntryOffset field of each variable-sized entry is used to traverse
the buffer. The offset value is 0 in the last record.

As the FindNextFile calls traverse the buffer, the current-entry
pointer is updated for the next call. At the final entry, the pointer
gets reset back to the base address. In this case, the next
FindNextFile call will scan in a new batch of file records via
NtQueryDirectoryFile[Ex]. This continues until the system call returns
STATUS_NO_MORE_FILES (0x80000006), in which case FindNextFile fails
with the last error set to ERROR_NO_MORE_FILES (18). This is the
normal way a directory scan is completed.

Here's my guess about what's going wrong in your case.

NtQueryDirectoryFile[Ex] can fail with STATUS_BUFFER_OVERFLOW
(0x80000005) if the buffer isn't large enough for a complete entry. In
practice this shouldn't occur because the buffers used by
FindFirstFile[Ex] and FindNextFile are large enough for at least one
complete entry. We might have a filesystem that, on subsequent calls,
stores a partial last entry in the buffer and fails with
STATUS_BUFFER_OVERFLOW. FindNextFile handles this case by forgetting
the partial entry, which it does by setting the NextEntryOffset field
to 0 in the previous entry, if any. Then, even if there's only a
single entry, it continues past the overflow error to return the
current entry. When NtQueryDirectoryFile[Ex] is called again, it
should resume at the entry that was partially returned in the previous
call. But if it was only a single entry, and the buffer-overflow was
due to a bug in the device stack, then we'll scan the same entry again
with the same buffer-overflow error, and we're stuck in an infinite
loop.

Probably this bug is due to a filter driver in the device stack,
rather than the filesystem driver.


More information about the python-win32 mailing list