コード例 #1
0
        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();
                }
            }
        }