From b0a3755b17239dfbb4645ccfdff517ff414efefe Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 29 Aug 2019 14:50:54 -0700 Subject: [PATCH] Minor fix for recursion into OneDrive - Change FindFirstFileEx() to use SafeFindHandle type (#10405) --- .../namespaces/FileSystemProvider.cs | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index c383f9493e..42da77ba19 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -7859,8 +7859,23 @@ namespace Microsoft.PowerShell.Commands FileAttributes dwFlagsAndAttributes, IntPtr hTemplateFile); - [DllImport(PinvokeDllNames.FindFirstFileDllName, EntryPoint = "FindFirstFileExW", SetLastError = true, CharSet = CharSet.Unicode)] - private static extern SafeFileHandle FindFirstFileEx(string lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, ref WIN32_FIND_DATA lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, IntPtr lpSearchFilter, int dwAdditionalFlags); + internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private SafeFindHandle() : base(true) { } + + protected override bool ReleaseHandle() + { + return FindClose(this.handle); + } + + [DllImport(PinvokeDllNames.FindCloseDllName)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool FindClose(IntPtr handle); + } + + // SetLastError is false as the use of this API doesn't not require GetLastError() to be called + [DllImport(PinvokeDllNames.FindFirstFileDllName, EntryPoint = "FindFirstFileExW", SetLastError = false, CharSet = CharSet.Unicode)] + private static extern SafeFindHandle FindFirstFileEx(string lpFileName, FINDEX_INFO_LEVELS fInfoLevelId, ref WIN32_FIND_DATA lpFindFileData, FINDEX_SEARCH_OPS fSearchOp, IntPtr lpSearchFilter, int dwAdditionalFlags); internal enum FINDEX_INFO_LEVELS : uint { @@ -8055,7 +8070,7 @@ namespace Microsoft.PowerShell.Commands } #if !UNIX var data = new WIN32_FIND_DATA(); - using (SafeFileHandle handle = FindFirstFileEx(fileInfo.FullName, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0)) + using (var handle = FindFirstFileEx(fileInfo.FullName, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0)) { // Name surrogates (0x20000000) are reparse points that point to other named entities local to the filesystem (like symlinks) // In the case of OneDrive, they are not surrogates and would be safe to recurse into.