private void EraseUnusedSpace(Task task, UnusedSpaceTarget target) { if (!Security.IsAdministrator()) { if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version >= new Version(6, 0)) { throw new UnauthorizedAccessException(S._("The program does not have the " + "required permissions to erase the unused space on disk. Run the program " + "as an administrator and retry the operation.")); } else throw new UnauthorizedAccessException(S._("The program does not have the " + "required permissions to erase the unused space on disk.")); } if (SystemRestore.GetInstances().Count != 0) { task.Log.LastSessionEntries.Add(new LogEntry(S._("The drive {0} has System " + "Restore or Volume Shadow Copies enabled. This may allow copies of files " + "stored on the disk to be recovered and pose a security concern.", target.Drive), LogLevel.Warning)); } if (VolumeInfo.FromMountPoint(target.Drive).HasQuota) task.Log.LastSessionEntries.Add(new LogEntry(S._("The drive {0} has disk quotas " + "active. This will prevent the complete erasure of unused space and may pose " + "a security concern.", target.Drive), LogLevel.Warning)); ErasureMethod method = target.Method; DirectoryInfo info = new DirectoryInfo(target.Drive); VolumeInfo volInfo = VolumeInfo.FromMountPoint(target.Drive); FileSystem fsManager = FileSystemManager.Get(volInfo); SteppedProgressManager progress = new SteppedProgressManager(); target.Progress = progress; task.Progress.Steps.Add(new SteppedProgressManagerStep( progress, 1.0f / task.Targets.Count)); if (target.EraseClusterTips) { ProgressManager tipSearch = new ProgressManager(); progress.Steps.Add(new SteppedProgressManagerStep(tipSearch, 0.0f, S._("Searching for files' cluster tips..."))); tipSearch.Total = 1; ClusterTipsSearchProgress searchProgress = delegate(string path) { if (currentTask.Canceled) throw new OperationCanceledException(S._("The task was cancelled.")); task.OnProgressChanged(target, new ProgressChangedEventArgs(tipSearch, new TaskProgressChangedEventArgs(path, 0, 0))); }; ProgressManager tipProgress = new ProgressManager(); progress.Steps.Add(new SteppedProgressManagerStep(tipProgress, 0.1f, S._("Erasing cluster tips..."))); ClusterTipsEraseProgress eraseProgress = delegate(int currentFile, int totalFiles, string currentFilePath) { tipSearch.MarkComplete(); tipProgress.Total = totalFiles; tipProgress.Completed = currentFile; task.OnProgressChanged(target, new ProgressChangedEventArgs(tipProgress, new TaskProgressChangedEventArgs(currentFilePath, 0, 0))); if (currentTask.Canceled) throw new OperationCanceledException(S._("The task was cancelled.")); }; fsManager.EraseClusterTips(VolumeInfo.FromMountPoint(target.Drive), method, task.Log, searchProgress, eraseProgress); } info = info.CreateSubdirectory(Path.GetFileName( FileSystem.GenerateRandomFileName(info, 18))); try { if (info.IsCompressed()) info.Uncompress(); ProgressManager mainProgress = new ProgressManager(); progress.Steps.Add(new SteppedProgressManagerStep(mainProgress, target.EraseClusterTips ? 0.8f : 0.9f, S._("Erasing unused space..."))); while (volInfo.AvailableFreeSpace > 0) { string currFile = FileSystem.GenerateRandomFileName(info, 18); using (FileStream stream = new FileStream(currFile, FileMode.CreateNew, FileAccess.Write, FileShare.None, 8, FileOptions.WriteThrough)) { mainProgress.Total = mainProgress.Completed + method.CalculateEraseDataSize(null, volInfo.AvailableFreeSpace); long streamLength = Math.Min(ErasureMethod.FreeSpaceFileUnit, mainProgress.Total); while (true) try { stream.SetLength(streamLength); break; } catch (IOException) { if (streamLength > volInfo.ClusterSize) streamLength -= volInfo.ClusterSize; else throw; } method.Erase(stream, long.MaxValue, PrngManager.GetInstance(ManagerLibrary.Settings.ActivePrng), delegate(long lastWritten, long totalData, int currentPass) { mainProgress.Completed += lastWritten; task.OnProgressChanged(target, new ProgressChangedEventArgs(mainProgress, new TaskProgressChangedEventArgs(target.Drive, currentPass, method.Passes))); if (currentTask.Canceled) throw new OperationCanceledException(S._("The task was cancelled.")); } ); } } mainProgress.MarkComplete(); ProgressManager residentProgress = new ProgressManager(); progress.Steps.Add(new SteppedProgressManagerStep(residentProgress, 0.05f, S._("Old resident file system table files"))); fsManager.EraseOldFileSystemResidentFiles(volInfo, info, method, delegate(int currentFile, int totalFiles) { residentProgress.Completed = currentFile; residentProgress.Total = totalFiles; task.OnProgressChanged(target, new ProgressChangedEventArgs(residentProgress, new TaskProgressChangedEventArgs(string.Empty, 0, 0))); if (currentTask.Canceled) throw new OperationCanceledException(S._("The task was cancelled.")); } ); residentProgress.MarkComplete(); } finally { ProgressManager tempFiles = new ProgressManager(); progress.Steps.Add(new SteppedProgressManagerStep(tempFiles, 0.0f, S._("Removing temporary files..."))); task.OnProgressChanged(target, new ProgressChangedEventArgs(tempFiles, new TaskProgressChangedEventArgs(string.Empty, 0, 0))); fsManager.DeleteFolder(info); tempFiles.Completed = tempFiles.Total; } ProgressManager structureProgress = new ProgressManager(); progress.Steps.Add(new SteppedProgressManagerStep(structureProgress, 0.05f, S._("Erasing unused directory structures..."))); fsManager.EraseDirectoryStructures(volInfo, delegate(int currentFile, int totalFiles) { if (currentTask.Canceled) throw new OperationCanceledException(S._("The task was cancelled.")); structureProgress.Total = totalFiles; structureProgress.Completed = currentFile; task.OnProgressChanged(target, new ProgressChangedEventArgs(structureProgress, new TaskProgressChangedEventArgs(string.Empty, 0, 0))); } ); structureProgress.MarkComplete(); target.Progress = null; }