Changeset 2189
- Timestamp:
- 6/18/2010 2:36:03 PM (3 years ago)
- Location:
- trunk/eraser
- Files:
-
- 3 edited
-
Eraser.DefaultPlugins/FileSystems/Fat.cs (modified) (1 diff)
-
Eraser.Util/NtfsApi.cs (modified) (1 diff)
-
Eraser.Util/VolumeInfo.cs (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/eraser/Eraser.DefaultPlugins/FileSystems/Fat.cs
r2157 r2189 89 89 try 90 90 { 91 using (VolumeLock volumeLock = info.LockVolume(stream))91 while (eraseQueue.Count != 0) 92 92 { 93 while (eraseQueue.Count != 0) 94 { 95 if (callback != null) 96 callback(directoriesCleaned, directoriesCleaned + eraseQueue.Count); 93 if (callback != null) 94 callback(directoriesCleaned, directoriesCleaned + eraseQueue.Count); 97 95 98 FatDirectoryBase currentDir = api.LoadDirectory(eraseQueue[0].FullName);99 eraseQueue.RemoveAt(0);96 FatDirectoryBase currentDir = api.LoadDirectory(eraseQueue[0].FullName); 97 eraseQueue.RemoveAt(0); 100 98 101 //Queue the subfolders in this directory102 foreach (KeyValuePair<string, FatDirectoryEntry> entry in currentDir.Items)103 if (entry.Value.EntryType == FatDirectoryEntryType.Directory)104 {105 //Check that we don't have the same cluster queued twice (e.g. for106 //long/8.3 file names)107 if (eraseQueueClusters.Contains(entry.Value.Cluster))108 continue;99 //Queue the subfolders in this directory 100 foreach (KeyValuePair<string, FatDirectoryEntry> entry in currentDir.Items) 101 if (entry.Value.EntryType == FatDirectoryEntryType.Directory) 102 { 103 //Check that we don't have the same cluster queued twice (e.g. for 104 //long/8.3 file names) 105 if (eraseQueueClusters.Contains(entry.Value.Cluster)) 106 continue; 109 107 110 eraseQueueClusters.Add(entry.Value.Cluster);111 eraseQueue.Add(entry.Value);112 }108 eraseQueueClusters.Add(entry.Value.Cluster); 109 eraseQueue.Add(entry.Value); 110 } 113 111 114 currentDir.ClearDeletedEntries(); 115 ++directoriesCleaned; 116 } 112 currentDir.ClearDeletedEntries(); 113 ++directoriesCleaned; 117 114 } 118 115 } -
trunk/eraser/Eraser.Util/NtfsApi.cs
r1873 r2189 69 69 internal static NativeMethods.NTFS_VOLUME_DATA_BUFFER? GetNtfsVolumeData(VolumeInfo volume) 70 70 { 71 using (SafeFileHandle volumeHandle = volume.OpenHandle( 72 FileAccess.Read, FileShare.ReadWrite, FileOptions.None)) 71 using (FileStream stream = volume.Open(FileAccess.Read, FileShare.ReadWrite, 72 FileOptions.None)) 73 using (SafeFileHandle handle = stream.SafeFileHandle) 73 74 { 74 if (volumeHandle.IsInvalid)75 return null;76 77 75 uint resultSize = 0; 78 76 NativeMethods.NTFS_VOLUME_DATA_BUFFER volumeData = 79 77 new NativeMethods.NTFS_VOLUME_DATA_BUFFER(); 80 if (NativeMethods.DeviceIoControl( volumeHandle,78 if (NativeMethods.DeviceIoControl(handle, 81 79 NativeMethods.FSCTL_GET_NTFS_VOLUME_DATA, IntPtr.Zero, 0, out volumeData, 82 80 (uint)Marshal.SizeOf(volumeData), out resultSize, IntPtr.Zero)) -
trunk/eraser/Eraser.Util/VolumeInfo.cs
r2187 r2189 635 635 public FileStream Open(FileAccess access, FileShare share, FileOptions options) 636 636 { 637 SafeFileHandle handle = OpenHandle(access, share, options); 638 639 //Check that the handle is valid 640 if (handle.IsInvalid) 641 { 642 int errorCode = Marshal.GetLastWin32Error(); 643 handle.Close(); 644 throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); 645 } 646 647 //Return the FileStream 648 return new FileStream(handle, access); 649 } 650 651 internal SafeFileHandle OpenHandle(FileAccess access, FileShare share, FileOptions options) 637 return new VolumeStream(this, OpenHandle(access, share, options), access); 638 } 639 640 private SafeFileHandle OpenHandle(FileAccess access, FileShare share, FileOptions options) 652 641 { 653 642 //Access mode … … 669 658 } 670 659 671 internalSafeFileHandle OpenHandle(uint access, FileShare share, FileOptions options)660 private SafeFileHandle OpenHandle(uint access, FileShare share, FileOptions options) 672 661 { 673 662 //Sharing mode … … 683 672 if (openPath.Length > 0 && openPath[openPath.Length - 1] == '\\') 684 673 openPath = openPath.Remove(openPath.Length - 1); 685 return NativeMethods.CreateFile(openPath, access, (uint)share, IntPtr.Zero, 686 (uint)FileMode.Open, (uint)options, IntPtr.Zero); 674 675 SafeFileHandle result = NativeMethods.CreateFile(openPath, access, (uint)share, 676 IntPtr.Zero, (uint)FileMode.Open, (uint)options, IntPtr.Zero); 677 678 //Check that the handle is valid 679 if (result.IsInvalid) 680 { 681 int errorCode = Marshal.GetLastWin32Error(); 682 result.Close(); 683 throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); 684 } 685 686 return result; 687 687 } 688 688 … … 739 739 return VolumeId.GetHashCode(); 740 740 } 741 742 public VolumeLock LockVolume(FileStream stream)743 {744 return new VolumeLock(stream);745 }746 741 } 747 742 748 public sealed class VolumeLock : IDisposable743 public class VolumeStream : FileStream 749 744 { 750 internal VolumeLock(FileStream stream) 751 { 745 internal VolumeStream(VolumeInfo volume, SafeFileHandle handle, FileAccess access) 746 : base(handle, access) 747 { 748 Volume = volume; 749 Access = access; 750 751 if (Access == FileAccess.Write || Access == FileAccess.ReadWrite) 752 LockVolume(); 753 } 754 755 protected override void Dispose(bool disposing) 756 { 757 if (Access == FileAccess.Write || Access == FileAccess.ReadWrite) 758 UnlockVolume(); 759 base.Dispose(disposing); 760 } 761 762 public override void SetLength(long value) 763 { 764 throw new InvalidOperationException(); 765 } 766 767 public override long Length 768 { 769 get 770 { 771 if (IsLocked) 772 return LengthCache; 773 return Volume.TotalSize; 774 } 775 } 776 777 /// <summary> 778 /// Temporarily stores the length of the disk while the disk is locked. 779 /// </summary> 780 private long LengthCache; 781 782 private void LockVolume() 783 { 784 LengthCache = Length; 752 785 uint result = 0; 753 for (int i = 0; !NativeMethods.DeviceIoControl( stream.SafeFileHandle,786 for (int i = 0; !NativeMethods.DeviceIoControl(SafeFileHandle, 754 787 NativeMethods.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 755 788 0, out result, IntPtr.Zero); ++i) … … 760 793 } 761 794 762 Stream = stream; 763 } 764 765 ~VolumeLock() 766 { 767 Dispose(false); 768 } 769 770 public void Dispose() 771 { 772 Dispose(true); 773 GC.SuppressFinalize(this); 774 } 775 776 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "disposing")] 777 private void Dispose(bool disposing) 778 { 779 if (Stream == null) 780 return; 781 795 IsLocked = true; 796 } 797 798 private void UnlockVolume() 799 { 782 800 //Flush the contents of the buffer to disk since after we unlock the volume 783 801 //we can no longer write to the volume. 784 Stream.Flush();802 Flush(); 785 803 786 804 uint result = 0; 787 if (!NativeMethods.DeviceIoControl(Stream.SafeFileHandle, 788 NativeMethods.FSCTL_UNLOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 789 0, out result, IntPtr.Zero)) 805 if (!NativeMethods.DeviceIoControl(SafeFileHandle, NativeMethods.FSCTL_UNLOCK_VOLUME, 806 IntPtr.Zero, 0, IntPtr.Zero, 0, out result, IntPtr.Zero)) 790 807 { 791 808 throw new IOException("Could not unlock volume."); 792 809 } 793 810 794 //Set the stream to null so that we won't run this function again. 795 Stream = null; 796 } 797 798 private FileStream Stream; 811 LengthCache = 0; 812 IsLocked = false; 813 } 814 815 /// <summary> 816 /// Reflects whether the current handle has exclusive access to the volume. 817 /// </summary> 818 private bool IsLocked; 819 820 /// <summary> 821 /// The <see cref="VolumeInfo"/> object this stream is encapsulating. 822 /// </summary> 823 private VolumeInfo Volume; 824 825 /// <summary> 826 /// The access parameter for this stream. 827 /// </summary> 828 private FileAccess Access; 799 829 } 800 830
Note: See TracChangeset
for help on using the changeset viewer.
