private void Main() { while (thread.ThreadState != ThreadState.AbortRequested) { Task task = null; lock (tasksLock) { while (scheduledTasks.Count != 0) if (scheduledTasks.Values[0].Count == 0) { scheduledTasks.RemoveAt(0); } else { if (scheduledTasks.Keys[0] <= DateTime.Now) { List<Task> tasks = scheduledTasks.Values[0]; task = tasks[0]; tasks.RemoveAt(0); } if (task == null) { for (int i = 0; i < scheduledTasks.Count; ) if (scheduledTasks.Values[i].Count == 0) scheduledTasks.RemoveAt(i); else ++i; } break; } } if (task != null) { currentTask = task; try { KernelApi.SetThreadExecutionState(ThreadExecutionState.Continuous | ThreadExecutionState.SystemRequired); task.Canceled = false; task.OnTaskStarted(new TaskEventArgs(task)); OnTaskProcessing(new TaskEventArgs(task)); task.Log.Entries.NewSession(); TaskProgressManager progress = new TaskProgressManager(task); foreach (ErasureTarget target in task.Targets) try { progress.Event.CurrentTarget = target; ++progress.Event.CurrentTargetIndex; UnusedSpaceTarget unusedSpaceTarget = target as UnusedSpaceTarget; FileSystemObjectTarget fileSystemObjectTarget = target as FileSystemObjectTarget; if (unusedSpaceTarget != null) EraseUnusedSpace(task, unusedSpaceTarget, progress); else if (fileSystemObjectTarget != null) EraseFilesystemObject(task, fileSystemObjectTarget, progress); else throw new ArgumentException(S._("Unknown erasure target.")); } catch (FatalException) { throw; } catch (OperationCanceledException) { throw; } catch (Exception e) { task.Log.LastSessionEntries.Add(new LogEntry(e.Message, LogLevel.Error)); } } catch (FatalException e) { task.Log.LastSessionEntries.Add(new LogEntry(e.Message, LogLevel.Fatal)); } catch (OperationCanceledException e) { task.Log.LastSessionEntries.Add(new LogEntry(e.Message, LogLevel.Fatal)); } catch (Exception e) { task.Log.LastSessionEntries.Add(new LogEntry(e.Message, LogLevel.Error)); } finally { KernelApi.SetThreadExecutionState(ThreadExecutionState.Continuous); if (task.Schedule is RecurringSchedule) ((RecurringSchedule)task.Schedule).Reschedule(DateTime.Now); if (task.Schedule == Schedule.RunOnRestart) task.Schedule = Schedule.RunNow; task.OnTaskFinished(new TaskEventArgs(task)); OnTaskProcessed(new TaskEventArgs(task)); currentTask = null; } } schedulerInterrupt.WaitOne(30000, false); } }
private void EraseFilesystemObject(Task task, FileSystemObjectTarget target, TaskProgressManager progress) { long dataTotal = 0; List<string> paths = target.GetPaths(out dataTotal); ErasureMethod method = target.Method; dataTotal = method.CalculateEraseDataSize(paths, dataTotal); progress.Event.CurrentTargetStatus = S._("Erasing files..."); for (int i = 0; i < paths.Count; ++i) { progress.Event.CurrentTargetProgress = i / (float)paths.Count; progress.Event.CurrentTarget = target; progress.Event.CurrentItemName = paths[i]; progress.Event.CurrentItemProgress = 0; progress.Event.CurrentTargetTotalPasses = method.Passes; task.OnProgressChanged(progress.Event); 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)); } long itemWritten = 0; fsManager.EraseFileSystemObject(info, method, delegate(long lastWritten, long totalData, int currentPass) { dataTotal -= lastWritten; progress.Completed += lastWritten; progress.Event.CurrentItemPass = currentPass; progress.Event.CurrentItemProgress = (float) ((itemWritten += lastWritten) / (float)totalData); progress.Event.CurrentTargetProgress = (i + progress.Event.CurrentItemProgress) / (float)paths.Count; progress.Event.TimeLeft = progress.TimeLeft; task.OnProgressChanged(progress.Event); if (currentTask.Canceled) throw new OperationCanceledException(S._("The task was cancelled.")); }); FileInfo fileInfo = info.File; if (fileInfo != null) fsManager.DeleteFile(fileInfo); } 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) { progress.Event.CurrentTargetStatus = S._("Removing folders..."); FolderTarget fldr = (FolderTarget)target; FileSystem fsManager = FileSystemManager.Get(VolumeInfo.FromMountpoint(fldr.Path)); FolderEraseDelegate eraseEmptySubFolders = null; eraseEmptySubFolders = delegate(DirectoryInfo info) { foreach (DirectoryInfo subDir in info.GetDirectories()) eraseEmptySubFolders(subDir); progress.Event.CurrentItemName = info.FullName; task.OnProgressChanged(progress.Event); 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); progress.Event.CurrentItemName = info.FullName; task.OnProgressChanged(progress.Event); 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) { progress.Event.CurrentTargetStatus = S._("Emptying recycle bin..."); task.OnProgressChanged(progress.Event); ShellApi.EmptyRecycleBin(EmptyRecycleBinOptions.NoConfirmation | EmptyRecycleBinOptions.NoProgressUI | EmptyRecycleBinOptions.NoSound); } }
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); } ); }
public void Load() { LoadData(); taskProgressManager = gameObject.AddComponent <TaskProgressManager>(); taskProgressManager.Init(); }