internal FileIdBothDirectoryInfo(NativeMethods.FileIdBothDirInfo fibdi, string fileName) { CreationTime = DateTime.FromFileTimeUtc(fibdi.CreationTime).ToLocalTime(); LastAccessTime = DateTime.FromFileTimeUtc(fibdi.LastAccessTime).ToLocalTime(); LastWriteTime = DateTime.FromFileTimeUtc(fibdi.LastWriteTime).ToLocalTime(); ChangeTime = DateTime.FromFileTimeUtc(fibdi.ChangeTime).ToLocalTime(); AllocationSize = fibdi.AllocationSize; EndOfFile = fibdi.EndOfFile; ExtendedAttributesSize = fibdi.EaSize; FileAttributes = fibdi.FileAttributes; FileId = fibdi.FileId; FileIndex = fibdi.FileIndex; FileName = fileName; // ShortNameLength is the number of bytes in the short name; since we have a unicode string we must divide that by 2. ShortName = new string(fibdi.ShortName, 0, fibdi.ShortNameLength / 2); }
internal static IEnumerable <FileIdBothDirectoryInfo> EnumerateFileIdBothDirectoryInfoInternal(KernelTransaction transaction, SafeFileHandle safeHandle, string path, FileShare shareMode, bool continueOnException, PathFormat pathFormat) { if (!NativeMethods.IsAtLeastWindowsVista) { throw new PlatformNotSupportedException(Resources.RequiresWindowsVistaOrHigher); } bool callerHandle = safeHandle != null; if (!callerHandle) { if (Utils.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException("path"); } string pathLp = Path.GetExtendedLengthPathInternal(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck); safeHandle = File.CreateFileInternal(transaction, pathLp, ExtendedFileAttributes.BackupSemantics, null, FileMode.Open, FileSystemRights.ReadData, shareMode, true, PathFormat.LongFullPath); } try { if (!NativeMethods.IsValidHandle(safeHandle, Marshal.GetLastWin32Error(), !continueOnException)) { yield break; } // 2014-10-16: Number of returned items depends on the size of the buffer. // That does not seem right, investigate. using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize)) { NativeMethods.IsValidHandle(safeBuffer, Marshal.GetLastWin32Error()); long fileNameOffset = Marshal.OffsetOf(typeof(NativeMethods.FileIdBothDirInfo), "FileName").ToInt64(); while (NativeMethods.GetFileInformationByHandleEx(safeHandle, NativeMethods.FileInfoByHandleClass.FileIdBothDirectoryInfo, safeBuffer.DangerousGetHandle(), NativeMethods.DefaultFileBufferSize)) { // CA2001:AvoidCallingProblematicMethods IntPtr buffer = IntPtr.Zero; bool successRef = false; safeBuffer.DangerousAddRef(ref successRef); // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid. if (successRef) { buffer = safeBuffer.DangerousGetHandle(); } safeBuffer.DangerousRelease(); if (buffer == IntPtr.Zero) { NativeError.ThrowException(Resources.HandleDangerousRef); } // CA2001:AvoidCallingProblematicMethods while (buffer != IntPtr.Zero) { NativeMethods.FileIdBothDirInfo fibdi = Utils.MarshalPtrToStructure <NativeMethods.FileIdBothDirInfo>(0, buffer); string fileName = Marshal.PtrToStringUni(new IntPtr(fileNameOffset + buffer.ToInt64()), (int)(fibdi.FileNameLength / 2)); if (!Utils.IsNullOrWhiteSpace(fileName) && !fileName.Equals(Path.CurrentDirectoryPrefix, StringComparison.OrdinalIgnoreCase) && !fileName.Equals(Path.ParentDirectoryPrefix, StringComparison.OrdinalIgnoreCase)) { yield return(new FileIdBothDirectoryInfo(fibdi, fileName)); } buffer = fibdi.NextEntryOffset == 0 ? IntPtr.Zero : new IntPtr(buffer.ToInt64() + fibdi.NextEntryOffset); } } int lastError = Marshal.GetLastWin32Error(); switch ((uint)lastError) { case Win32Errors.ERROR_SUCCESS: case Win32Errors.ERROR_NO_MORE_FILES: case Win32Errors.ERROR_HANDLE_EOF: yield break; default: NativeError.ThrowException(lastError, path); break; } } } finally { // Handle is ours, dispose. if (!callerHandle && safeHandle != null) { safeHandle.Close(); } } }