Enable recursion into OneDrive (#9509)

This commit is contained in:
Steve Lee 2019-05-06 17:28:00 -07:00 committed by Aditya Patwardhan
parent 346ab8c9d4
commit 1d28144e99

View file

@ -1848,9 +1848,11 @@ namespace Microsoft.PowerShell.Commands
// a) the user has asked to with the -FollowSymLinks switch parameter and
// b) the directory pointed to by the symlink has not already been visited,
// preventing symlink loops.
// c) it is not a name surrogate making it not a symlink
if (tracker == null)
{
if (InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(recursiveDirectory))
if (InternalSymbolicLinkLinkCodeMethods.IsReparsePoint(recursiveDirectory) &&
InternalSymbolicLinkLinkCodeMethods.IsNameSurrogateReparsePoint(recursiveDirectory.FullName))
{
continue;
}
@ -7706,6 +7708,8 @@ namespace Microsoft.PowerShell.Commands
private const string NonInterpretedPathPrefix = @"\??\";
private const int MAX_PATH = 260;
[Flags]
// dwDesiredAccess of CreateFile
internal enum FileDesiredAccess : uint
@ -7846,6 +7850,39 @@ 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 enum FINDEX_INFO_LEVELS : uint
{
FindExInfoStandard = 0x0u,
FindExInfoBasic = 0x1u,
FindExInfoMaxInfoLevel = 0x2u,
}
internal enum FINDEX_SEARCH_OPS : uint
{
FindExSearchNameMatch = 0x0u,
FindExSearchLimitToDirectories = 0x1u,
FindExSearchLimitToDevices = 0x2u,
FindExSearchMaxSearchOp = 0x3u,
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal unsafe struct WIN32_FIND_DATA
{
internal uint dwFileAttributes;
internal System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
internal System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
internal System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
internal uint nFileSizeHigh;
internal uint nFileSizeLow;
internal uint dwReserved0;
internal uint dwReserved1;
internal fixed char cFileName[MAX_PATH];
internal fixed char cAlternateFileName[14];
}
/// <summary>
/// Gets the target of the specified reparse point.
/// </summary>
@ -7993,6 +8030,25 @@ namespace Microsoft.PowerShell.Commands
: Platform.NonWindowsIsSymLink(fileInfo);
}
internal static bool IsNameSurrogateReparsePoint(string filePath)
{
#if !UNIX
var data = new WIN32_FIND_DATA();
using (SafeFileHandle handle = FindFirstFileEx(filePath, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0))
{
// Name surrogates 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.
// This code is equivalent to the IsReparseTagNameSurrogate macro: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-isreparsetagnamesurrogate
if (!handle.IsInvalid && (data.dwReserved0 & 0x20000000) == 0)
{
return false;
}
}
#endif
// true means the reparse point is a symlink
return true;
}
internal static bool WinIsHardLink(FileSystemInfo fileInfo)
{
bool isHardLink = false;