private void EraseFilesystemObject(Task task, FileSystemObjectTarget target)
 {
     long dataTotal = 0;
        List<string> paths = target.GetPaths(out dataTotal);
        ErasureMethod method = target.Method;
        TaskEventArgs eventArgs = new TaskEventArgs(task);
        SteppedProgressManager progress = new SteppedProgressManager();
        target.Progress = progress;
        task.Progress.Steps.Add(new SteppedProgressManager.Step(progress, 1.0f / task.Targets.Count));
        for (int i = 0; i < paths.Count; ++i)
        {
     ProgressManager step = new ProgressManager();
     progress.Steps.Add(new SteppedProgressManager.Step(step,
      1.0f / paths.Count, S._("Erasing files...")));
     task.OnProgressChanged(target,
      new ProgressChangedEventArgs(step,
       new TaskProgressChangedEventArgs(paths[i], 0, method.Passes)));
     StreamInfo info = new StreamInfo(paths[i]);
     FileSystem fsManager = FileSystemManager.Get(
      VolumeInfo.FromMountpoint(info.DirectoryName));
     if (!info.Exists)
     {
      task.Log.LastSessionEntries.Add(new LogEntry(S._("The file {0} was not erased " +
       "as the file does not exist.", paths[i]), LogLevel.Notice));
      continue;
     }
     bool isReadOnly = false;
     try
     {
      if (isReadOnly = info.IsReadOnly)
       info.IsReadOnly = false;
      if ((info.Attributes & FileAttributes.Compressed) != 0 ||
       (info.Attributes & FileAttributes.Encrypted) != 0 ||
       (info.Attributes & FileAttributes.SparseFile) != 0)
      {
       task.Log.LastSessionEntries.Add(new LogEntry(S._("The file {0} could " +
        "not be erased because the file was either compressed, encrypted or " +
        "a sparse file.", info.FullName), LogLevel.Error));
      }
      fsManager.EraseFileSystemObject(info, method,
       delegate(long lastWritten, long totalData, int currentPass)
       {
        if (currentTask.Canceled)
     throw new OperationCanceledException(S._("The task was cancelled."));
        step.Completed += lastWritten;
        step.Total = totalData;
        task.OnProgressChanged(target,
     new ProgressChangedEventArgs(step,
      new TaskProgressChangedEventArgs(info.FullName, currentPass, method.Passes)));
       });
      FileInfo fileInfo = info.File;
      if (fileInfo != null)
       fsManager.DeleteFile(fileInfo);
      step.Completed = step.Total = 1;
     }
     catch (UnauthorizedAccessException)
     {
      task.Log.LastSessionEntries.Add(new LogEntry(S._("The file {0} could not " +
       "be erased because the file's permissions prevent access to the file.",
       info.FullName), LogLevel.Error));
     }
     catch (FileLoadException)
     {
      if (!ManagerLibrary.Settings.ForceUnlockLockedFiles)
       throw;
      List<System.Diagnostics.Process> processes = new List<System.Diagnostics.Process>();
      foreach (OpenHandle handle in OpenHandle.Items)
       if (handle.Path == paths[i])
        processes.Add(System.Diagnostics.Process.GetProcessById(handle.ProcessId));
      StringBuilder processStr = new StringBuilder();
      foreach (System.Diagnostics.Process process in processes)
       processStr.AppendFormat(System.Globalization.CultureInfo.InvariantCulture,
        "{0}, ", process.MainModule.FileName);
      task.Log.LastSessionEntries.Add(new LogEntry(S._(
       "Could not force closure of file \"{0}\" (locked by {1})",
       paths[i], processStr.ToString().Remove(processStr.Length - 2)), LogLevel.Error));
     }
     finally
     {
      if (isReadOnly && info.Exists && !info.IsReadOnly)
       info.IsReadOnly = isReadOnly;
     }
        }
        if (target is FolderTarget)
        {
     ProgressManager step = new ProgressManager();
     progress.Steps.Add(new SteppedProgressManager.Step(step,
      0.0f, S._("Removing folders...")));
     FolderTarget fldr = (FolderTarget)target;
     FileSystem fsManager = FileSystemManager.Get(VolumeInfo.FromMountpoint(fldr.Path));
     Action<DirectoryInfo> eraseEmptySubFolders = null;
     eraseEmptySubFolders = delegate(DirectoryInfo info)
     {
       foreach (DirectoryInfo subDir in info.GetDirectories())
        eraseEmptySubFolders(subDir);
       task.OnProgressChanged(target,
        new ProgressChangedEventArgs(step,
     new TaskProgressChangedEventArgs(info.FullName, 0, 0)));
       FileSystemInfo[] files = info.GetFileSystemInfos();
       if (files.Length == 0)
        fsManager.DeleteFolder(info);
     };
     eraseEmptySubFolders(new DirectoryInfo(fldr.Path));
     if (fldr.DeleteIfEmpty)
     {
      DirectoryInfo info = new DirectoryInfo(fldr.Path);
      task.OnProgressChanged(target,
       new ProgressChangedEventArgs(step,
        new TaskProgressChangedEventArgs(info.FullName, 0, 0)));
      bool isVolumeRoot = info.Parent == null;
      foreach (VolumeInfo volume in VolumeInfo.Volumes)
       foreach (string mountPoint in volume.MountPoints)
        if (info.FullName == mountPoint)
     isVolumeRoot = true;
      if (!isVolumeRoot && info.Exists && info.GetFiles("*", SearchOption.AllDirectories).Length == 0)
       fsManager.DeleteFolder(info);
     }
        }
        if (target is RecycleBinTarget)
        {
     ProgressManager step = new ProgressManager();
     progress.Steps.Add(new SteppedProgressManager.Step(step,
      0.0f, S._("Emptying recycle bin...")));
     task.OnProgressChanged(target,
      new ProgressChangedEventArgs(step,
       new TaskProgressChangedEventArgs(string.Empty, 0, 0)));
     ShellApi.EmptyRecycleBin(EmptyRecycleBinOptions.NoConfirmation |
      EmptyRecycleBinOptions.NoProgressUI | EmptyRecycleBinOptions.NoSound);
        }
        target.Progress = null;
 }
 private void EraseUnusedSpace(Task task, UnusedSpaceTarget target)
 {
     if (!AdvApi.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 SteppedProgressManager.Step(
     progress, 1.0f / task.Targets.Count));
        if (target.EraseClusterTips)
        {
     ProgressManager tipSearch = new ProgressManager();
     progress.Steps.Add(new SteppedProgressManager.Step(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 SteppedProgressManager.Step(tipProgress, 0.1f,
      S._("Erasing cluster tips...")));
     ClusterTipsEraseProgress eraseProgress =
      delegate(int currentFile, int totalFiles, string currentFilePath)
      {
       tipSearch.Completed = tipSearch.Total;
       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 (Eraser.Util.File.IsCompressed(info.FullName))
      Eraser.Util.File.SetCompression(info.FullName, false);
     ProgressManager mainProgress = new ProgressManager();
     progress.Steps.Add(new SteppedProgressManager.Step(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 + 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.Completed = mainProgress.Total;
     ProgressManager residentProgress = new ProgressManager();
     progress.Steps.Add(new SteppedProgressManager.Step(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.Completed = residentProgress.Total = 1;
        }
        finally
        {
     ProgressManager tempFiles = new ProgressManager();
     progress.Steps.Add(new SteppedProgressManager.Step(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 = 1;
        }
        ProgressManager structureProgress = new ProgressManager();
        progress.Steps.Add(new SteppedProgressManager.Step(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.Completed = structureProgress.Total;
        target.Progress = null;
 }
 private void EraseUnusedSpace(Task task, UnusedSpaceTarget target, TaskProgressManager progress)
 {
     if (!AdvApi.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 (VolumeInfo.FromMountpoint(target.Drive).HasQuota)
     task.Log.LastSessionEntries.Add(new LogEntry(S._("The drive which is having its " +
      "unused space erased has disk quotas active. This will prevent the complete " +
      "erasure of unused space and will pose a security concern"), LogLevel.Warning));
        ErasureMethod method = target.Method;
        DirectoryInfo info = new DirectoryInfo(target.Drive);
        VolumeInfo volInfo = VolumeInfo.FromMountpoint(target.Drive);
        FileSystem fsManager = FileSystemManager.Get(volInfo);
        if (target.EraseClusterTips)
        {
     progress.Event.CurrentTargetStatus = S._("Searching for files' cluster tips...");
     progress.Event.CurrentTargetTotalPasses = method.Passes;
     progress.Event.CurrentItemProgress = -1.0f;
     progress.Event.TimeLeft = new TimeSpan(0, 0, -1);
     ProgressManager tipProgress = new ProgressManager();
     tipProgress.Start();
     ClusterTipsSearchProgress searchProgress = delegate(string path)
      {
       progress.Event.CurrentItemName = path;
       task.OnProgressChanged(progress.Event);
       if (currentTask.Canceled)
        throw new OperationCanceledException(S._("The task was cancelled."));
      };
     ClusterTipsEraseProgress eraseProgress =
      delegate(int currentFile, int totalFiles, string currentFilePath)
      {
       tipProgress.Total = totalFiles;
       tipProgress.Completed = currentFile;
       progress.Event.CurrentTargetStatus = S._("Erasing cluster tips...");
       progress.Event.CurrentItemName = currentFilePath;
       progress.Event.CurrentItemProgress = tipProgress.Progress;
       progress.Event.CurrentTargetProgress = progress.Event.CurrentItemProgress / 10;
       progress.Event.TimeLeft = tipProgress.TimeLeft;
       task.OnProgressChanged(progress.Event);
       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 (Eraser.Util.File.IsCompressed(info.FullName))
      Eraser.Util.File.SetCompression(info.FullName, false);
     progress.Event.CurrentTargetStatus = S._("Erasing unused space...");
     progress.Event.CurrentItemName = target.Drive;
     task.OnProgressChanged(progress.Event);
     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))
      {
       long streamLength = Math.Min(ErasureMethod.FreeSpaceFileUnit,
        volInfo.AvailableFreeSpace);
       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)
        {
     progress.Completed = Math.Min(progress.Total,
      progress.Completed + lastWritten);
     progress.Event.CurrentItemPass = currentPass;
     progress.Event.CurrentItemProgress = progress.Progress;
     if (target.EraseClusterTips)
      progress.Event.CurrentTargetProgress = (float)
       (0.1f + progress.Event.CurrentItemProgress * 0.8f);
     else
      progress.Event.CurrentTargetProgress = (float)
       (progress.Event.CurrentItemProgress * 0.9f);
     progress.Event.TimeLeft = progress.TimeLeft;
     task.OnProgressChanged(progress.Event);
     if (currentTask.Canceled)
      throw new OperationCanceledException(S._("The task was cancelled."));
        }
       );
      }
     }
     progress.Event.CurrentItemName = S._("Old resident file system table files");
     task.OnProgressChanged(progress.Event);
     fsManager.EraseOldFileSystemResidentFiles(volInfo, info, method, null);
        }
        finally
        {
     progress.Event.CurrentTargetStatus = S._("Removing temporary files...");
     task.OnProgressChanged(progress.Event);
     fsManager.DeleteFolder(info);
        }
        progress.Event.CurrentTargetStatus = S._("Erasing unused directory structures...");
        ProgressManager fsEntriesProgress = new ProgressManager();
        fsEntriesProgress.Start();
        fsManager.EraseDirectoryStructures(volInfo,
     delegate(int currentFile, int totalFiles)
     {
      if (currentTask.Canceled)
       throw new OperationCanceledException(S._("The task was cancelled."));
      fsEntriesProgress.Total = totalFiles;
      fsEntriesProgress.Completed = currentFile;
      progress.Event.TimeLeft = fsEntriesProgress.TimeLeft;
      progress.Event.CurrentItemProgress = fsEntriesProgress.Progress;
      progress.Event.CurrentTargetProgress = (float)(
       0.9 + progress.Event.CurrentItemProgress / 10);
      task.OnProgressChanged(progress.Event);
     }
        );
 }