/* Copyright (C) 2008-2016 Peter Palotas, Jeffrey Jangli, Alexandr Normuradov * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Security; using System.Text; namespace Alphaleonis.Win32.Filesystem { public static partial class File { #region EnumerateHardlinks /// [AlphaFS] Creates an enumeration of all the hard links to the specified . /// The name of the file. /// Indicates the format of the path parameter(s). /// An enumerable collection of of all the hard links to the specified [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hardlinks")] [SecurityCritical] public static IEnumerable EnumerateHardlinks(string path, PathFormat pathFormat) { return EnumerateHardlinksCore(null, path, pathFormat); } /// [AlphaFS] Creates an enumeration of all the hard links to the specified . /// The name of the file. /// An enumerable collection of of all the hard links to the specified [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hardlinks")] [SecurityCritical] public static IEnumerable EnumerateHardlinks(string path) { return EnumerateHardlinksCore(null, path, PathFormat.RelativePath); } /// [AlphaFS] Creates an enumeration of all the hard links to the specified . /// The transaction. /// The name of the file. /// Indicates the format of the path parameter(s). /// An enumerable collection of of all the hard links to the specified [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hardlinks")] [SecurityCritical] public static IEnumerable EnumerateHardlinksTransacted(KernelTransaction transaction, string path, PathFormat pathFormat) { return EnumerateHardlinksCore(transaction, path, pathFormat); } /// [AlphaFS] Creates an enumeration of all the hard links to the specified . /// The transaction. /// The name of the file. /// An enumerable collection of of all the hard links to the specified [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Hardlinks")] [SecurityCritical] public static IEnumerable EnumerateHardlinksTransacted(KernelTransaction transaction, string path) { return EnumerateHardlinksCore(transaction, path, PathFormat.RelativePath); } #endregion // EnumerateHardlinks #region Internal Methods /// [AlphaFS] Creates an enumeration of all the hard links to the specified . /// /// The transaction. /// The name of the file. /// Indicates the format of the path parameter(s). /// An enumerable collection of of all the hard links to the specified internal static IEnumerable EnumerateHardlinksCore(KernelTransaction transaction, string path, PathFormat pathFormat) { if (!NativeMethods.IsAtLeastWindowsVista) throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher); string pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck); // Default buffer length, will be extended if needed, although this should not happen. uint length = NativeMethods.MaxPathUnicode; StringBuilder builder = new StringBuilder((int)length); getFindFirstFileName: using (SafeFindFileHandle handle = transaction == null // FindFirstFileName() / FindFirstFileNameTransacted() // In the ANSI version of this function, the name is limited to MAX_PATH characters. // To extend this limit to 32,767 wide characters, call the Unicode version of the function and prepend "\\?\" to the path. // 2013-01-13: MSDN does not confirm LongPath usage but a Unicode version of this function exists. ? NativeMethods.FindFirstFileName(pathLp, 0, out length, builder) : NativeMethods.FindFirstFileNameTransacted(pathLp, 0, out length, builder, transaction.SafeHandle)) { int lastError = Marshal.GetLastWin32Error(); if (handle.IsInvalid) { handle.Close(); switch ((uint) lastError) { case Win32Errors.ERROR_MORE_DATA: builder = new StringBuilder((int) length); goto getFindFirstFileName; default: // If the function fails, the return value is INVALID_HANDLE_VALUE. NativeError.ThrowException(lastError, pathLp); break; } } yield return builder.ToString(); //length = NativeMethods.MaxPathUnicode; //builder = new StringBuilder((int)length); do { while (!NativeMethods.FindNextFileName(handle, out length, builder)) { lastError = Marshal.GetLastWin32Error(); switch ((uint) lastError) { // We've reached the end of the enumeration. case Win32Errors.ERROR_HANDLE_EOF: yield break; case Win32Errors.ERROR_MORE_DATA: builder = new StringBuilder((int) length); continue; default: //If the function fails, the return value is zero (0). NativeError.ThrowException(lastError); break; } } yield return builder.ToString(); } while (true); } } #endregion // Internal Methods } }