DeleteFileW and RemoveDirectoryW in recent versions of Windows 10 have
been changed to perform a FileDispositionInformationEx with POSIX
semantics and if that fails to retry with FileDispositionInformation.
Unfortunately this is done even for legitimate error codes such as
STATUS_DIRECTORY_NOT_EMPTY.
This means that user mode file systems have to do unnecessary CanDelete
checks even when they support FileDispositionInformationEx. The extra
check incurs extra context switches, and in some cases it may also be
costly to compute (e.g. FUSE).
We optimize this away by storing the status of the last CanDelete check
in the FileDesc and then continue returning the same status code for
all checks for the same FileDesc.
The original WinFsp protocol for shutting down a file system was to issue
an FSP_FSCTL_STOP control code to the fsctl device. This would set the IOQ
to the "stopped" state and would also cancel all active IRP's. Cancelation
of IRP's would sometimes free buffers that may have still been in use by
the user mode file system threads; hence access violation.
To fix this problem a new control code FSP_FSCTL_STOP0 is introduced. The
new file system shutdown protocol is backwards compatible with the original
one and works as follows:
- First the file system process issues an FSP_FSCTL_STOP0 control code which
sets the IOQ to the "stopped" state but does NOT cancel IRP's.
- Then the file system process waits for its dispatcher threads to complete
(see FspFileSystemStopDispatcher).
- Finally the file system process issues an FSP_FSCTL_STOP control code
which stops the (already stopped) IOQ and cancels all IRP's.
During CreateProcess/CreateSection Windows locks the image file (using AcquireFileForNtCreateSection),
gets the image file size and then reads the image file. Unfortunately if the file system (erroneously) reads
past the file size, Windows can bugcheck. This allows a faulty or malicious file system to crash Windows.
This commit adds a check in WinFsp to mitigate this problem.