From 1b8879b105351c526951648655b7dafbf5516165 Mon Sep 17 00:00:00 2001 From: Jeff Handley Date: Sat, 4 Jul 2026 03:31:21 -0400 Subject: [PATCH] Fall back to unfiltered enumeration on STATUS_OBJECT_NAME_NOT_FOUND (Windows) In FileSystemEnumerator.GetData() on Windows, when the first filtered NtQueryDirectoryFile call returns STATUS_OBJECT_NAME_NOT_FOUND, re-issue the query with no FileName filter and RestartScan, reverting to enumerate-all-then-filter for that directory. Some file system drivers (notably the Azure App Service run-from-package zip mount) report a zero-match filtered query with this status; the unfiltered retry lets the managed matching produce the empty result instead of throwing FileNotFoundException. Alternative approach for #130134. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../FileSystemEnumerator.Windows.cs | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs index 6adbe5732a6d07..e9b6af48b55d9e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs @@ -161,6 +161,26 @@ private bool GetData() ReturnSingleEntry: Interop.BOOLEAN.FALSE, FileName: fileNamePtr, RestartScan: Interop.BOOLEAN.FALSE); + + // Some file system drivers don't handle the OS-level FileName filter the way NTFS does and report a + // zero-match first call as STATUS_OBJECT_NAME_NOT_FOUND (notably the Azure App Service run-from-package + // zip mount). Rather than special-casing each such status, fall back to the original behavior for this + // directory: re-run the query without the filter and let the managed matching (which always runs) filter. + if (fileNamePtr != null && (uint)status == Interop.StatusOptions.STATUS_OBJECT_NAME_NOT_FOUND) + { + status = Interop.NtDll.NtQueryDirectoryFile( + FileHandle: _directoryHandle, + Event: IntPtr.Zero, + ApcRoutine: IntPtr.Zero, + ApcContext: IntPtr.Zero, + IoStatusBlock: &statusBlock, + FileInformation: _buffer, + Length: (uint)_bufferLength, + FileInformationClass: Interop.NtDll.FILE_INFORMATION_CLASS.FileFullDirectoryInformation, + ReturnSingleEntry: Interop.BOOLEAN.FALSE, + FileName: null, + RestartScan: Interop.BOOLEAN.TRUE); + } } switch ((uint)status)