source: branches/eraser6/CodeReview/Eraser.Manager/Task.cs @ 1777

Revision 1777, 26.8 KB checked in by lowjoel, 5 years ago (diff)

Redesigned the Logger paradigm -- instead of a dealing with a logger object to do any form of logging, we have a static Logger class which code can log to, and define log targets to receive those logs. Also included is a LogSession? class which sets the log target for the current thread or for a few threads. Addresses #320: Logging improvements

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
RevLine 
[1359]1/*
2 * $Id$
[1681]3 * Copyright 2008-2010 The Eraser Project
[1359]4 * Original Author: Joel Low <lowjoel@users.sourceforge.net>
5 * Modified By:
6 *
7 * This file is part of Eraser.
8 *
9 * Eraser is free software: you can redistribute it and/or modify it under the
10 * terms of the GNU General Public License as published by the Free Software
11 * Foundation, either version 3 of the License, or (at your option) any later
12 * version.
13 *
14 * Eraser is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 *
18 * A copy of the GNU General Public License can be found at
19 * <http://www.gnu.org/licenses/>.
20 */
21
22using System;
23using System.Collections.Generic;
24using System.Text;
25using System.IO;
26using System.Text.RegularExpressions;
27using System.Runtime.Serialization;
28using System.Security.Permissions;
29using System.Threading;
30
[1572]31using Eraser.Util;
[1709]32using Eraser.Util.ExtensionMethods;
[1572]33
[1359]34namespace Eraser.Manager
35{
36    /// <summary>
37    /// Deals with an erase task.
38    /// </summary>
39    [Serializable]
40    public class Task : ISerializable
41    {
42        #region Serialization code
43        protected Task(SerializationInfo info, StreamingContext context)
44        {
45            Name = (string)info.GetValue("Name", typeof(string));
46            Executor = context.Context as Executor;
47            Targets = (ErasureTargetsCollection)info.GetValue("Targets", typeof(ErasureTargetsCollection));
48            Targets.Owner = this;
[1777]49            Log = (List<LogSink>)info.GetValue("Log", typeof(List<LogSink>));
[1359]50            Canceled = false;
51
52            Schedule schedule = (Schedule)info.GetValue("Schedule", typeof(Schedule));
53            if (schedule.GetType() == Schedule.RunManually.GetType())
54                Schedule = Schedule.RunManually;
55            else if (schedule.GetType() == Schedule.RunNow.GetType())
56                Schedule = Schedule.RunNow;
57            else if (schedule.GetType() == Schedule.RunOnRestart.GetType())
58                Schedule = Schedule.RunOnRestart;
59            else if (schedule is RecurringSchedule)
60                Schedule = schedule;
61            else
62                throw new InvalidDataException(S._("An invalid type was found when loading " +
63                    "the task schedule"));
64        }
65
66        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
67        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
68        {
69            info.AddValue("Name", Name);
70            info.AddValue("Schedule", Schedule);
71            info.AddValue("Targets", Targets);
72            info.AddValue("Log", Log);
73        }
74        #endregion
75
76        /// <summary>
77        /// Constructor.
78        /// </summary>
79        public Task()
80        {
81            Name = string.Empty;
82            Targets = new ErasureTargetsCollection(this);
83            Schedule = Schedule.RunNow;
84            Canceled = false;
[1777]85            Log = new List<LogSink>();
[1359]86        }
87
88        /// <summary>
89        /// Cancels the task from running, or, if the task is queued for running,
90        /// removes the task from the queue.
91        /// </summary>
92        public void Cancel()
93        {
94            Executor.UnqueueTask(this);
95            Canceled = true;
96        }
97
98        /// <summary>
99        /// The Executor object which is managing this task.
100        /// </summary>
101        public Executor Executor { get; internal set; }
102
103        /// <summary>
104        /// The name for this task. This is just an opaque value for the user to
105        /// recognize the task.
106        /// </summary>
107        public string Name { get; set; }
108
109        /// <summary>
110        /// The name of the task, used for display in UI elements.
111        /// </summary>
112        public string UIText
113        {
114            get
115            {
116                //Simple case, the task name was given by the user.
117                if (Name.Length != 0)
118                    return Name;
119
120                string result = string.Empty;
[1497]121                if (Targets.Count < 5)
122                {
[1359]123                    //Simpler case, small set of data.
124                    foreach (ErasureTarget tgt in Targets)
125                        result += tgt.UIText + ", ";
[1497]126
127                    return result.Remove(result.Length - 2);
128                }
[1359]129                else
[1497]130                {
[1359]131                    //Ok, we've quite a few entries, get the first, the mid and the end.
[1497]132                    result = Targets[0].UIText + ", ";
133                    result += Targets[Targets.Count / 2].UIText + ", ";
134                    result += Targets[Targets.Count - 1].UIText;
135
[1498]136                    return S._("{0} and {1} other targets", result, Targets.Count - 3);
[1497]137                }
[1359]138            }
139        }
140
141        /// <summary>
142        /// Gets the status of the task - whether it is being executed.
143        /// </summary>
144        public bool Executing { get; private set; }
145
146        /// <summary>
147        /// Gets whether this task is currently queued to run. This is true only
148        /// if the queue it is in is an explicit request, i.e will run when the
149        /// executor is idle.
150        /// </summary>
151        public bool Queued
152        {
153            get
154            {
155                return Executor.IsTaskQueued(this);
156            }
157        }
158
159        /// <summary>
160        /// Gets whether the task has been cancelled from execution.
161        /// </summary>
162        public bool Canceled
163        {
[1515]164            get;
165            internal set;
[1359]166        }
167
168        /// <summary>
169        /// The set of data to erase when this task is executed.
170        /// </summary>
171        public ErasureTargetsCollection Targets { get; private set; }
172
173        /// <summary>
174        /// The schedule for running the task.
175        /// </summary>
176        public Schedule Schedule
177        {
178            get
179            {
180                return schedule;
181            }
182            set
183            {
184                if (value.Owner != null)
[1767]185                    throw new ArgumentException("The schedule provided can only " +
186                        "belong to one task at a time");
[1359]187
188                if (schedule is RecurringSchedule)
189                    ((RecurringSchedule)schedule).Owner = null;
190                schedule = value;
191                if (schedule is RecurringSchedule)
192                    ((RecurringSchedule)schedule).Owner = this;
193                OnTaskEdited();
194            }
195        }
196
197        /// <summary>
198        /// The log entries which this task has accumulated.
199        /// </summary>
[1777]200        public List<LogSink> Log { get; private set; }
[1359]201
[1515]202        /// <summary>
203        /// The progress manager object which manages the progress of this task.
204        /// </summary>
205        public SteppedProgressManager Progress
206        {
207            get
208            {
209                if (!Executing)
210                    throw new InvalidOperationException("The progress of an erasure can only " +
211                        "be queried when the task is being executed.");
212
213                return progress;
214            }
215            private set
216            {
217                progress = value;
218            }
219        }
220
[1359]221        private Schedule schedule;
[1515]222        private SteppedProgressManager progress;
[1359]223
224        #region Events
225        /// <summary>
226        /// The task has been edited.
227        /// </summary>
[1765]228        public EventHandler TaskEdited { get; set; }
[1359]229
230        /// <summary>
231        /// The start of the execution of a task.
232        /// </summary>
[1765]233        public EventHandler TaskStarted { get; set; }
[1359]234
235        /// <summary>
236        /// The event object holding all event handlers.
237        /// </summary>
[1515]238        public EventHandler<ProgressChangedEventArgs> ProgressChanged { get; set; }
[1359]239
240        /// <summary>
241        /// The completion of the execution of a task.
242        /// </summary>
[1765]243        public EventHandler TaskFinished { get; set; }
[1359]244
245        /// <summary>
246        /// Broadcasts the task edited event.
247        /// </summary>
248        internal void OnTaskEdited()
249        {
250            if (TaskEdited != null)
[1765]251                TaskEdited(this, EventArgs.Empty);
[1359]252        }
253
254        /// <summary>
255        /// Broadcasts the task execution start event.
256        /// </summary>
[1765]257        internal void OnTaskStarted()
[1359]258        {
259            if (TaskStarted != null)
[1765]260                TaskStarted(this, EventArgs.Empty);
[1359]261            Executing = true;
[1515]262            Progress = new SteppedProgressManager();
[1359]263        }
264
265        /// <summary>
[1515]266        /// Broadcasts a ProgressChanged event. The sender will be the erasure target
267        /// which broadcast this event; e.UserState will contain extra information
268        /// about the progress which is stored as a TaskProgressChangedEventArgs
269        /// object.
[1359]270        /// </summary>
[1515]271        /// <param name="sender">The <see cref="ErasureTarget"/> which is reporting
272        /// progress.</param>
[1359]273        /// <param name="e">The new progress value.</param>
[1515]274        /// <exception cref="ArgumentException">e.UserState must be of the type
275        /// <see cref="TaskProgressEventargs"/></exception>
276        /// <exception cref="ArgumentNullException">Both sender and e cannot be null.</exception>
277        internal void OnProgressChanged(ErasureTarget sender, ProgressChangedEventArgs e)
[1359]278        {
[1515]279            if (sender == null)
280                throw new ArgumentNullException("sender");
281            if (e == null)
282                throw new ArgumentNullException("sender");
283            if (e.UserState.GetType() != typeof(TaskProgressChangedEventArgs))
284                throw new ArgumentException("The Task.OnProgressChanged event expects a " +
285                    "TaskProgressEventArgs argument for the ProgressChangedEventArgs' UserState " +
286                    "object.", "e");
287
[1359]288            if (ProgressChanged != null)
[1515]289                ProgressChanged(sender, e);
[1359]290        }
291
292        /// <summary>
293        /// Broadcasts the task execution completion event.
294        /// </summary>
[1765]295        internal void OnTaskFinished()
[1359]296        {
297            if (TaskFinished != null)
[1765]298                TaskFinished(this, EventArgs.Empty);
[1359]299            Executing = false;
[1515]300            Progress = null;
[1359]301        }
302        #endregion
303    }
304
305    /// <summary>
306    /// Represents a generic target of erasure
307    /// </summary>
308    [Serializable]
309    public abstract class ErasureTarget : ISerializable
310    {
311        #region Serialization code
312        protected ErasureTarget(SerializationInfo info, StreamingContext context)
313        {
314            Guid methodGuid = (Guid)info.GetValue("Method", typeof(Guid));
315            if (methodGuid == Guid.Empty)
316                method = ErasureMethodManager.Default;
317            else
318                method = ErasureMethodManager.GetInstance(methodGuid);
319        }
320
321        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
322        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
323        {
324            info.AddValue("Method", method.Guid);
325        }
326        #endregion
327
328        /// <summary>
329        /// Constructor.
330        /// </summary>
331        protected ErasureTarget()
332        {
333        }
334
335        /// <summary>
336        /// The method used for erasing the file. If the variable is equal to
337        /// ErasureMethodManager.Default then the default is queried for the
338        /// task type. Check the <see cref="MethodDefined"/> property to see if
339        /// this variable was set on deliberately or if the result of the get
340        /// call is from the inferred default.
341        /// </summary>
342        public virtual ErasureMethod Method
343        {
344            get
345            {
[1374]346                return method;
[1359]347            }
348            set
349            {
350                method = value;
351                MethodDefined = method != ErasureMethodManager.Default;
352            }
353        }
354
355        /// <summary>
356        /// Checks whether a method has been selected for this target. This is
357        /// because the Method property will return non-default erasure methods
358        /// only.
359        /// </summary>
360        public bool MethodDefined { get; private set; }
361
362        /// <summary>
363        /// The task which owns this target.
364        /// </summary>
365        public Task Task { get; internal set; }
366
367        /// <summary>
368        /// Retrieves the text to display representing this task.
369        /// </summary>
370        public abstract string UIText
371        {
372            get;
373        }
374
375        /// <summary>
376        /// Retrieves the amount of data that needs to be written in order to
377        /// complete the erasure.
378        /// </summary>
379        public abstract long TotalData
380        {
381            get;
382        }
383
384        /// <summary>
385        /// Erasure method to use for the target.
386        /// </summary>
387        private ErasureMethod method;
[1515]388
389        /// <summary>
390        /// The progress of this target.
391        /// </summary>
392        public ProgressManagerBase Progress
393        {
394            get;
395            internal set;
396        }
[1359]397    }
398
399    /// <summary>
400    /// Class representing a tangible object (file/folder) to be erased.
401    /// </summary>
402    [Serializable]
403    public abstract class FileSystemObjectTarget : ErasureTarget
404    {
405        #region Serialization code
406        protected FileSystemObjectTarget(SerializationInfo info, StreamingContext context)
407            : base(info, context)
408        {
409            Path = (string)info.GetValue("Path", typeof(string));
410        }
411
412        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
413        public override void GetObjectData(SerializationInfo info, StreamingContext context)
414        {
415            base.GetObjectData(info, context);
416            info.AddValue("Path", Path);
417        }
418        #endregion
419
420        /// <summary>
421        /// Constructor.
422        /// </summary>
423        protected FileSystemObjectTarget()
424            : base()
425        {
426            Method = ErasureMethodManager.Default;
427        }
428
429        /// <summary>
430        /// Retrieves the list of files/folders to erase as a list.
431        /// </summary>
432        /// <param name="totalSize">Returns the total size in bytes of the
433        /// items.</param>
434        /// <returns>A list containing the paths to all the files to be erased.</returns>
435        internal abstract List<string> GetPaths(out long totalSize);
436
437        /// <summary>
438        /// Adds ADSes of the given file to the list.
439        /// </summary>
440        /// <param name="list">The list to add the ADS paths to.</param>
441        /// <param name="file">The file to look for ADSes</param>
442        protected void GetPathADSes(ICollection<string> list, out long totalSize, string file)
443        {
444            totalSize = 0;
445
446            try
447            {
448                //Get the ADS names
[1709]449                IList<string> adses = new FileInfo(file).GetADSes();
[1359]450
451                //Then prepend the path.
452                foreach (string adsName in adses)
453                {
454                    string adsPath = file + ':' + adsName;
455                    list.Add(adsPath);
[1745]456                    StreamInfo info = new StreamInfo(adsPath);
[1359]457                    totalSize += info.Length;
458                }
459            }
[1576]460            catch (IOException)
[1359]461            {
[1576]462                if (System.Runtime.InteropServices.Marshal.GetLastWin32Error() ==
463                    Win32ErrorCode.SharingViolation)
464                {
465                    //The system cannot open the file, try to force the file handle to close.
466                    if (!ManagerLibrary.Settings.ForceUnlockLockedFiles)
467                        throw;
468
469                    foreach (OpenHandle handle in OpenHandle.Items)
470                        if (handle.Path == file && handle.Close())
471                        {
472                            GetPathADSes(list, out totalSize, file);
473                            return;
474                        }
475                }
476                else
[1359]477                    throw;
478            }
479            catch (UnauthorizedAccessException e)
480            {
481                //The system cannot read the file, assume no ADSes for lack of
482                //more information.
[1777]483                Logger.Log(e.Message, LogLevel.Error);
[1359]484            }
485        }
486
487        /// <summary>
488        /// The path to the file or folder referred to by this object.
489        /// </summary>
490        public string Path { get; set; }
491
492        public sealed override ErasureMethod Method
493        {
494            get
495            {
496                if (base.MethodDefined)
497                    return base.Method;
498                return ErasureMethodManager.GetInstance(
499                    ManagerLibrary.Settings.DefaultFileErasureMethod);
500            }
501            set
502            {
503                base.Method = value;
504            }
505        }
506
507        public override string UIText
508        {
[1701]509            get
510            {
511                string fileName = System.IO.Path.GetFileName(Path);
512                string directoryName = System.IO.Path.GetDirectoryName(Path);
513                return string.IsNullOrEmpty(fileName) ? 
514                        (string.IsNullOrEmpty(directoryName) ? Path : directoryName)
515                    : fileName;
516            }
[1359]517        }
518
519        public override long TotalData
520        {
521            get
522            {
523                long totalSize = 0;
524                List<string> paths = GetPaths(out totalSize);
525                return Method.CalculateEraseDataSize(paths, totalSize);
526            }
527        }
528    }
529
530    /// <summary>
531    /// Class representing a unused space erase.
532    /// </summary>
533    [Serializable]
534    public class UnusedSpaceTarget : ErasureTarget
535    {
536        #region Serialization code
537        protected UnusedSpaceTarget(SerializationInfo info, StreamingContext context)
538            : base(info, context)
539        {
540            Drive = (string)info.GetValue("Drive", typeof(string));
541            EraseClusterTips = (bool)info.GetValue("EraseClusterTips", typeof(bool));
542        }
543
544        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
545        public override void GetObjectData(SerializationInfo info, StreamingContext context)
546        {
547            base.GetObjectData(info, context);
548            info.AddValue("Drive", Drive);
549            info.AddValue("EraseClusterTips", EraseClusterTips);
550        }
551        #endregion
552
553        /// <summary>
554        /// Constructor.
555        /// </summary>
556        public UnusedSpaceTarget()
557            : base()
558        {
559            Method = ErasureMethodManager.Default;
560        }
561
562        public override sealed ErasureMethod Method
563        {
564            get
565            {
566                if (base.MethodDefined)
567                    return base.Method;
568                return ErasureMethodManager.GetInstance(
569                    ManagerLibrary.Settings.DefaultUnusedSpaceErasureMethod);
570            }
571            set
572            {
573                base.Method = value;
574            }
575        }
576
577        public override string UIText
578        {
579            get { return S._("Unused disk space ({0})", Drive); }
580        }
581
582        public override long TotalData
583        {
584            get
585            {
[1595]586                VolumeInfo info = VolumeInfo.FromMountPoint(Drive);
[1359]587                return Method.CalculateEraseDataSize(null, info.AvailableFreeSpace);
588            }
589        }
590
591        /// <summary>
592        /// The drive to erase
593        /// </summary>
594        public string Drive { get; set; }
595
596        /// <summary>
597        /// Whether cluster tips should be erased.
598        /// </summary>
599        public bool EraseClusterTips { get; set; }
600    }
601
602    /// <summary>
603    /// Class representing a file to be erased.
604    /// </summary>
605    [Serializable]
606    public class FileTarget : FileSystemObjectTarget
607    {
608        #region Serialization code
609        protected FileTarget(SerializationInfo info, StreamingContext context)
610            : base(info, context)
611        {
612        }
613        #endregion
614
615        /// <summary>
616        /// Constructor.
617        /// </summary>
618        public FileTarget()
619        {
620        }
621
622        internal override List<string> GetPaths(out long totalSize)
623        {
624            totalSize = 0;
625            List<string> result = new List<string>();
626            FileInfo fileInfo = new FileInfo(Path);
627
628            if (fileInfo.Exists)
629            {
630                GetPathADSes(result, out totalSize, Path);
631                totalSize += fileInfo.Length;
632            }
633
634            result.Add(Path);
635            return result;
636        }
637    }
638
639    /// <summary>
640    /// Represents a folder and its files which are to be erased.
641    /// </summary>
642    [Serializable]
643    public class FolderTarget : FileSystemObjectTarget
644    {
645        #region Serialization code
646        protected FolderTarget(SerializationInfo info, StreamingContext context)
647            : base(info, context)
648        {
649            IncludeMask = (string)info.GetValue("IncludeMask", typeof(string));
650            ExcludeMask = (string)info.GetValue("ExcludeMask", typeof(string));
651            DeleteIfEmpty = (bool)info.GetValue("DeleteIfEmpty", typeof(bool));
652        }
653
654        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
655        public override void GetObjectData(SerializationInfo info, StreamingContext context)
656        {
657            base.GetObjectData(info, context);
658            info.AddValue("IncludeMask", IncludeMask);
659            info.AddValue("ExcludeMask", ExcludeMask);
660            info.AddValue("DeleteIfEmpty", DeleteIfEmpty);
661        }
662        #endregion
663
664        /// <summary>
665        /// Constructor.
666        /// </summary>
667        public FolderTarget()
668        {
669            IncludeMask = string.Empty;
670            ExcludeMask = string.Empty;
671            DeleteIfEmpty = true;
672        }
673
674        internal override List<string> GetPaths(out long totalSize)
675        {
676            //Get a list to hold all the resulting paths.
677            List<string> result = new List<string>();
678
679            //Open the root of the search, including every file matching the pattern
680            DirectoryInfo dir = new DirectoryInfo(Path);
681
682            //List recursively all the files which match the include pattern.
683            FileInfo[] files = GetFiles(dir);
684
685            //Then exclude each file and finalize the list and total file size
686            totalSize = 0;
687            if (ExcludeMask.Length != 0)
688            {
689                string regex = Regex.Escape(ExcludeMask).Replace("\\*", ".*").
690                    Replace("\\?", ".");
691                Regex excludePattern = new Regex(regex, RegexOptions.IgnoreCase);
692                foreach (FileInfo file in files)
[1745]693                    if (file.Exists &&
694                        (file.Attributes & FileAttributes.ReparsePoint) == 0 &&
[1359]695                        excludePattern.Matches(file.FullName).Count == 0)
696                    {
697                        totalSize += file.Length;
698                        GetPathADSes(result, out totalSize, file.FullName);
699                        result.Add(file.FullName);
700                    }
701            }
702            else
703                foreach (FileInfo file in files)
704                {
[1745]705                    if (!file.Exists || (file.Attributes & FileAttributes.ReparsePoint) != 0)
[1359]706                        continue;
707
708                    //Get the size of the file and its ADSes
709                    totalSize += file.Length;
710                    long adsesSize = 0;
711                    GetPathADSes(result, out adsesSize, file.FullName);
712                    totalSize += adsesSize;
713
714                    //Append this file to the list of files to erase.
715                    result.Add(file.FullName);
716                }
717
718            //Return the filtered list.
719            return result;
720        }
721
722        /// <summary>
723        /// Gets all files in the provided directory.
724        /// </summary>
725        /// <param name="info">The directory to look files in.</param>
726        /// <returns>A list of files found in the directory matching the IncludeMask
727        /// property.</returns>
728        private FileInfo[] GetFiles(DirectoryInfo info)
729        {
730            List<FileInfo> result = new List<FileInfo>();
731            if (info.Exists)
732            {
[1681]733                try
734                {
735                    foreach (DirectoryInfo dir in info.GetDirectories())
[1359]736                        result.AddRange(GetFiles(dir));
737
[1681]738                    if (IncludeMask.Length == 0)
739                        result.AddRange(info.GetFiles());
740                    else
741                        result.AddRange(info.GetFiles(IncludeMask, SearchOption.TopDirectoryOnly));
742                }
743                catch (UnauthorizedAccessException e)
744                {
[1777]745                    Logger.Log(S._("Could not erase files and subfolders in {0} because {1}",
746                        info.FullName, e.Message), LogLevel.Error);
[1681]747                }
[1359]748            }
749
750            return result.ToArray();
751        }
752
753        /// <summary>
754        /// A wildcard expression stating the condition for the set of files to include.
755        /// The include mask is applied before the exclude mask is applied. If this value
756        /// is empty, all files and folders within the folder specified is included.
757        /// </summary>
758        public string IncludeMask { get; set; }
759
760        /// <summary>
761        /// A wildcard expression stating the condition for removing files from the set
762        /// of included files. If this value is omitted, all files and folders extracted
763        /// by the inclusion mask is erased.
764        /// </summary>
765        public string ExcludeMask { get; set; }
766
767        /// <summary>
768        /// Determines if Eraser should delete the folder after the erase process.
769        /// </summary>
770        public bool DeleteIfEmpty { get; set; }
771    }
772
773    [Serializable]
774    public class RecycleBinTarget : FileSystemObjectTarget
775    {
776        #region Serialization code
777        protected RecycleBinTarget(SerializationInfo info, StreamingContext context)
778            : base(info, context)
779        {
780        }
781        #endregion
782
783        public RecycleBinTarget()
784        {
785        }
786
787        internal override List<string> GetPaths(out long totalSize)
788        {
789            totalSize = 0;
790            List<string> result = new List<string>();
791            string[] rootDirectory = new string[] {
792                    "$RECYCLE.BIN",
793                    "RECYCLER"
794                };
795
796            foreach (DriveInfo drive in DriveInfo.GetDrives())
797            {
798                foreach (string rootDir in rootDirectory)
799                {
800                    DirectoryInfo dir = new DirectoryInfo(
801                        System.IO.Path.Combine(
802                            System.IO.Path.Combine(drive.Name, rootDir),
803                            System.Security.Principal.WindowsIdentity.GetCurrent().
804                                User.ToString()));
805                    if (!dir.Exists)
806                        continue;
807
[1745]808                    GetRecyclerFiles(dir, result, ref totalSize);
[1359]809                }
810            }
811
812            return result;
813        }
814
815        /// <summary>
816        /// Retrieves all files within this folder, without exclusions.
817        /// </summary>
818        /// <param name="info">The DirectoryInfo object representing the folder to traverse.</param>
819        /// <param name="paths">The list of files to store path information in.</param>
820        /// <param name="totalSize">Receives the total size of the files.</param>
[1745]821        private void GetRecyclerFiles(DirectoryInfo info, List<string> paths,
[1359]822            ref long totalSize)
823        {
824            try
825            {
[1745]826                foreach (FileInfo fileInfo in info.GetFiles())
[1359]827                {
[1745]828                    if (!fileInfo.Exists || (fileInfo.Attributes & FileAttributes.ReparsePoint) != 0)
829                        continue;
830
831                    totalSize += fileInfo.Length;
832                    GetPathADSes(paths, out totalSize, fileInfo.FullName);
833                    paths.Add(fileInfo.FullName);
[1359]834                }
[1745]835
836                foreach (DirectoryInfo directoryInfo in info.GetDirectories())
837                    if ((directoryInfo.Attributes & FileAttributes.ReparsePoint) == 0)
838                        GetRecyclerFiles(directoryInfo, paths, ref totalSize);
[1359]839            }
840            catch (UnauthorizedAccessException e)
841            {
[1777]842                Logger.Log(e.Message, LogLevel.Error);
[1359]843            }
844        }
845
846        /// <summary>
847        /// Retrieves the text to display representing this task.
848        /// </summary>
849        public override string UIText
850        {
851            get
852            {
853                return S._("Recycle Bin");
854            }
855        }
856    }
857
858    /// <summary>
859    /// Maintains a collection of erasure targets.
860    /// </summary>
861    [Serializable]
[1528]862    public class ErasureTargetsCollection : IList<ErasureTarget>, ISerializable
[1359]863    {
864        #region Constructors
865        internal ErasureTargetsCollection(Task owner)
866        {
867            this.list = new List<ErasureTarget>();
868            this.owner = owner;
869        }
870
871        internal ErasureTargetsCollection(Task owner, int capacity)
872            : this(owner)
873        {
874            list.Capacity = capacity;
875        }
876
877        internal ErasureTargetsCollection(Task owner, IEnumerable<ErasureTarget> targets)
878            : this(owner)
879        {
880            list.AddRange(targets);
881        }
882        #endregion
883
884        #region Serialization Code
885        protected ErasureTargetsCollection(SerializationInfo info, StreamingContext context)
886        {
887            list = (List<ErasureTarget>)info.GetValue("list", typeof(List<ErasureTarget>));
888        }
889
890        [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
891        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
892        {
893            info.AddValue("list", list);
894        }
895        #endregion
896
897        #region IEnumerable<ErasureTarget> Members
898        public IEnumerator<ErasureTarget> GetEnumerator()
899        {
900            return list.GetEnumerator();
901        }
902        #endregion
903
904        #region IEnumerable Members
905        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
906        {
907            return GetEnumerator();
908        }
909        #endregion
910
911        #region ICollection<ErasureTarget> Members
912        public void Add(ErasureTarget item)
913        {
914            item.Task = owner;
915            list.Add(item);
916        }
917
918        public void Clear()
919        {
920            foreach (ErasureTarget item in list)
921                Remove(item);
922        }
923
924        public bool Contains(ErasureTarget item)
925        {
926            return list.Contains(item);
927        }
928
929        public void CopyTo(ErasureTarget[] array, int arrayIndex)
930        {
931            list.CopyTo(array, arrayIndex);
932        }
933
934        public int Count
935        {
936            get
937            {
938                return list.Count;
939            }
940        }
941
942        public bool IsReadOnly
943        {
944            get
945            {
946                return false;
947            }
948        }
949
950        public bool Remove(ErasureTarget item)
951        {
952            int index = list.IndexOf(item);
953            if (index < 0)
954                return false;
955
956            RemoveAt(index);
957            return true;
958        }
959        #endregion
960
961        #region IList<ErasureTarget> Members
962        public int IndexOf(ErasureTarget item)
963        {
964            return list.IndexOf(item);
965        }
966
967        public void Insert(int index, ErasureTarget item)
968        {
969            item.Task = owner;
970            list.Insert(index, item);
971        }
972
973        public void RemoveAt(int index)
974        {
975            list.RemoveAt(index);
976        }
977
978        public ErasureTarget this[int index]
979        {
980            get
981            {
982                return list[index];
983            }
984            set
985            {
986                list[index] = value;
987            }
988        }
989        #endregion
990
991        /// <summary>
992        /// The owner of this list of targets.
993        /// </summary>
994        public Task Owner
995        {
996            get
997            {
998                return owner;
999            }
1000            internal set
1001            {
1002                owner = value;
1003                foreach (ErasureTarget target in list)
1004                    target.Task = owner;
1005            }
1006        }
1007
1008        /// <summary>
1009        /// The owner of this list of targets. All targets added to this list
1010        /// will have the owner set to this object.
1011        /// </summary>
1012        private Task owner;
1013
1014        /// <summary>
1015        /// The list bring the data store behind this object.
1016        /// </summary>
1017        private List<ErasureTarget> list;
1018    }
1019
1020    /// <summary>
1021    /// A base event class for all event arguments involving a task.
1022    /// </summary>
1023    public class TaskEventArgs : EventArgs
1024    {
1025        /// <summary>
1026        /// Constructor.
1027        /// </summary>
1028        /// <param name="task">The task being referred to by this event.</param>
1029        public TaskEventArgs(Task task)
1030        {
1031            Task = task;
1032        }
1033
1034        /// <summary>
1035        /// The executing task.
1036        /// </summary>
1037        public Task Task { get; private set; }
1038    }
1039
1040    /// <summary>
[1515]1041    /// Stores extra information in the <see cref="ProgressChangedEventArgs"/>
1042    /// structure that is not conveyed in the ProgressManagerBase classes.
[1359]1043    /// </summary>
[1515]1044    public class TaskProgressChangedEventArgs
[1359]1045    {
1046        /// <summary>
1047        /// Constructor.
1048        /// </summary>
[1515]1049        /// <param name="itemName">The item whose erasure progress is being erased.</param>
1050        /// <param name="itemPass">The current pass number for this item.</param>
1051        /// <param name="itemTotalPasses">The total number of passes to complete erasure
1052        /// of this item.</param>
1053        public TaskProgressChangedEventArgs(string itemName, int itemPass,
1054            int itemTotalPasses)
[1359]1055        {
[1515]1056            ItemName = itemName;
1057            ItemPass = itemPass;
1058            ItemTotalPasses = itemTotalPasses;
[1359]1059        }
1060
1061        /// <summary>
[1515]1062        /// The file name of the item being erased.
[1359]1063        /// </summary>
[1515]1064        public string ItemName { get; private set; }
[1359]1065
1066        /// <summary>
[1515]1067        /// The pass number of a multi-pass erasure method.
[1359]1068        /// </summary>
[1515]1069        public int ItemPass { get; private set; }
[1359]1070
1071        /// <summary>
1072        /// The total number of passes to complete before this erasure method is
1073        /// completed.
1074        /// </summary>
[1515]1075        public int ItemTotalPasses { get; private set; }
[1359]1076    }
[1022]1077}
Note: See TracBrowser for help on using the repository browser.