From 4c5ede020eb9f18e6826312cf14a5e1426e340d0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Apr 2026 15:58:11 +0000 Subject: [PATCH 1/5] Use DisableMediaInsertionPrompt.Create() and NativeMemory for FileSystemEnumerator buffer Agent-Logs-Url: https://github.com/teo-tsirpanis/dotnet-runtime/sessions/233c35f2-6fa4-4409-b093-93f4a80a0598 Co-authored-by: teo-tsirpanis <12659251+teo-tsirpanis@users.noreply.github.com> --- .../FileSystemEnumerator.Windows.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) 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 5fa91fdd9483e6..9abfb50de43f25 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 @@ -31,7 +31,7 @@ public abstract unsafe partial class FileSystemEnumerator : CriticalFin private Interop.NtDll.FILE_FULL_DIR_INFORMATION* _entry; private TResult? _current; - private IntPtr _buffer; + private void* _buffer; private int _bufferLength; private IntPtr _directoryHandle; private string? _currentPath; @@ -43,7 +43,7 @@ private void Init() // We'll only suppress the media insertion prompt on the topmost directory as that is the // most likely scenario and we don't want to take the perf hit for large enumerations. // (We weren't consistent with how we handled this historically.) - using (default(DisableMediaInsertionPrompt)) + using (DisableMediaInsertionPrompt.Create()) { // We need to initialize the directory handle up front to ensure // we immediately throw IO exceptions for missing directory/etc. @@ -61,9 +61,9 @@ private void Init() try { // NtQueryDirectoryFile needs its buffer to be 64bit aligned to work - // successfully with FileFullDirectoryInformation on ARM32. AllocHGlobal - // will return pointers aligned as such, new byte[] does not. - _buffer = Marshal.AllocHGlobal(_bufferLength); + // successfully with FileFullDirectoryInformation on ARM32. AlignedAlloc + // guarantees the required alignment, new byte[] does not. + _buffer = NativeMemory.AlignedAlloc((nuint)_bufferLength, sizeof(ulong)); } catch { @@ -89,7 +89,7 @@ private bool GetData() ApcRoutine: IntPtr.Zero, ApcContext: IntPtr.Zero, IoStatusBlock: &statusBlock, - FileInformation: _buffer, + FileInformation: (IntPtr)_buffer, Length: (uint)_bufferLength, FileInformationClass: Interop.NtDll.FILE_INFORMATION_CLASS.FileFullDirectoryInformation, ReturnSingleEntry: Interop.BOOLEAN.FALSE, @@ -308,12 +308,12 @@ private void InternalDispose(bool disposing) _pending = null; } - if (_buffer != default) + if (_buffer != null) { - Marshal.FreeHGlobal(_buffer); + NativeMemory.Free(_buffer); } - _buffer = default; + _buffer = null; } } From e7fbfe4ee975b04ebd307f6829d6e1663a5c6ec2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 4 Apr 2026 16:08:27 +0000 Subject: [PATCH 2/5] Change NtQueryDirectoryFile FileInformation param to void* and remove cast Agent-Logs-Url: https://github.com/teo-tsirpanis/dotnet-runtime/sessions/c20f57ce-bd4d-4583-90a1-c799d80ee39e Co-authored-by: teo-tsirpanis <12659251+teo-tsirpanis@users.noreply.github.com> --- .../src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs | 2 +- .../src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs index fbbf8b967102c4..a282208fb7a026 100644 --- a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs +++ b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs @@ -17,7 +17,7 @@ public static unsafe partial int NtQueryDirectoryFile( IntPtr ApcRoutine, IntPtr ApcContext, IO_STATUS_BLOCK* IoStatusBlock, - IntPtr FileInformation, + void* FileInformation, uint Length, FILE_INFORMATION_CLASS FileInformationClass, BOOLEAN ReturnSingleEntry, 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 f1d9b256709382..5da3375215ad8f 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 @@ -155,7 +155,7 @@ private bool GetData() ApcRoutine: IntPtr.Zero, ApcContext: IntPtr.Zero, IoStatusBlock: &statusBlock, - FileInformation: (IntPtr)_buffer, + FileInformation: _buffer, Length: (uint)_bufferLength, FileInformationClass: Interop.NtDll.FILE_INFORMATION_CLASS.FileFullDirectoryInformation, ReturnSingleEntry: Interop.BOOLEAN.FALSE, From c32fda7fab5696193359adba8cae88d59dfbdc8a Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Sat, 4 Apr 2026 19:10:24 +0300 Subject: [PATCH 3/5] Use `AlignedFree`. --- .../src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5da3375215ad8f..addfb41ca758d3 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 @@ -383,7 +383,7 @@ private void InternalDispose(bool disposing) if (_buffer != null) { - NativeMemory.Free(_buffer); + NativeMemory.AlignedFree(_buffer); } _buffer = null; From add6fb945489fb433bd271bf07c99d663432fe86 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Wed, 15 Apr 2026 02:27:24 +0300 Subject: [PATCH 4/5] Simplify comment. --- .../src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 addfb41ca758d3..dca890cb36175b 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 @@ -107,8 +107,7 @@ private void Init() try { // NtQueryDirectoryFile needs its buffer to be 64bit aligned to work - // successfully with FileFullDirectoryInformation on ARM32. AlignedAlloc - // guarantees the required alignment, new byte[] does not. + // successfully with FileFullDirectoryInformation. _buffer = NativeMemory.AlignedAlloc((nuint)_bufferLength, sizeof(ulong)); } catch From 567dacdda9f2fc7b65576203789ac94e117cfbe9 Mon Sep 17 00:00:00 2001 From: Theodore Tsirpanis Date: Thu, 16 Apr 2026 01:25:51 +0300 Subject: [PATCH 5/5] Address PR feedback. --- .../FileSystemEnumerator.Windows.cs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) 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 dca890cb36175b..6068334754ac9f 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 @@ -86,17 +86,11 @@ internal FileSystemEnumerator(string directory, bool isNormalized, EnumerationOp private void Init() { - // We'll only suppress the media insertion prompt on the topmost directory as that is the - // most likely scenario and we don't want to take the perf hit for large enumerations. - // (We weren't consistent with how we handled this historically.) - using (DisableMediaInsertionPrompt.Create()) - { - // We need to initialize the directory handle up front to ensure - // we immediately throw IO exceptions for missing directory/etc. - _directoryHandle = CreateDirectoryHandle(_rootDirectory); - if (_directoryHandle == IntPtr.Zero) - _lastEntryFound = true; - } + // We need to initialize the directory handle up front to ensure + // we immediately throw IO exceptions for missing directory/etc. + _directoryHandle = CreateDirectoryHandle(_rootDirectory); + if (_directoryHandle == IntPtr.Zero) + _lastEntryFound = true; _currentPath = _rootDirectory; @@ -108,6 +102,8 @@ private void Init() { // NtQueryDirectoryFile needs its buffer to be 64bit aligned to work // successfully with FileFullDirectoryInformation. + // From https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_full_dir_information: + // "This structure must be aligned on a LONGLONG (8-byte) boundary." _buffer = NativeMemory.AlignedAlloc((nuint)_bufferLength, sizeof(ulong)); } catch