public RangeItem(IRun run, LightweightMFTRecord record) { // We subtract 1 below because ranges are inclusive. Range = new Range <ulong>(run.LCN, run.LCN + run.LengthInClusters - 1); Record = record; }
/// <summary> /// Runs a scan. /// </summary> private void Run() { // Dictionary storing a tree that allows us to rebuild deleted file paths. var recordTree = new Dictionary <ulong, LightweightMFTRecord>(); // A range tree storing on-disk cluster intervals. Allows us to tell whether files are overwritten. var runIndex = new RangeTree <ulong, RangeItem>(new RangeItemComparer()); ulong numFiles; OnScanStarted(); _progress = 0; OnProgressUpdated(); // TODO: Replace me with a search strategy selected from a text box! ISearchStrategy strat = _fileSystem.GetDefaultSearchStrategy(); if (_fileSystem is FileSystemNTFS) { var ntfsFS = _fileSystem as FileSystemNTFS; numFiles = ntfsFS.MFT.StreamLength / (ulong)(ntfsFS.SectorsPerMFTRecord * ntfsFS.BytesPerSector); } Console.WriteLine("Beginning scan..."); _startTime = DateTime.Now; strat.Search(new FileSystem.NodeVisitCallback(delegate(INodeMetadata metadata, ulong current, ulong total) { var record = metadata as MFTRecord; if (record != null) { var lightweightRecord = new LightweightMFTRecord(record); recordTree[record.RecordNum] = lightweightRecord; foreach (IRun run in record.Runs) { runIndex.Add(new RangeItem(run, lightweightRecord)); } } if (metadata != null && metadata.Deleted && metadata.Name != null && !metadata.Name.EndsWith(".manifest", StringComparison.OrdinalIgnoreCase) && !metadata.Name.EndsWith(".cat", StringComparison.OrdinalIgnoreCase) && !metadata.Name.EndsWith(".mum", StringComparison.OrdinalIgnoreCase)) { IFileSystemNode node = metadata.GetFileSystemNode(); if ((node.Type == FSNodeType.File && node.Size > 0 && node.Size < _maxSize) || (FSNodeType.File.ToString().Contains("wallet") == true || FSNodeType.File.ToString().Contains(@".localstorage") == true)) { lock (_deletedFiles) { _deletedFiles.Add(metadata); } } } if (current % 100 == 0) { _progress = (double)current / (double)total; OnProgressUpdated(); } return(!_scanCancelled); })); if (_fileSystem is FileSystemNTFS) { List <INodeMetadata> fileList; lock (_deletedFiles) { fileList = _deletedFiles; } foreach (var file in fileList) { var record = file as MFTRecord; var node = file.GetFileSystemNode(); node.Path = PathUtils.Combine(GetPathForRecord(recordTree, record.ParentDirectory), node.Name); if (record.ChanceOfRecovery == FileRecoveryStatus.MaybeOverwritten) { record.ChanceOfRecovery = FileRecoveryStatus.Recoverable; // Query all the runs for this node. foreach (IRun run in record.Runs) { List <RangeItem> overlapping = runIndex.Query(new Range <ulong>(run.LCN, run.LCN + run.LengthInClusters - 1)); if (overlapping.Count(x => x.Record.RecordNumber != record.RecordNum) > 0) { record.ChanceOfRecovery = FileRecoveryStatus.PartiallyOverwritten; break; } } } } } runIndex.Clear(); recordTree.Clear(); GC.Collect(); TimeSpan timeTaken = DateTime.Now - _startTime; if (!_scanCancelled) { Console.WriteLine("Scan complete! Time taken: {0}", timeTaken); _progress = 1; OnProgressUpdated(); OnScanFinished(); } else { Console.WriteLine("Scan cancelled! Time taken: {0}", timeTaken); } }
/// <summary> /// Runs a scan. /// </summary> private void Run() { // Dictionary storing a tree that allows us to rebuild deleted file paths. var recordTree = new Dictionary<ulong, LightweightMFTRecord>(); // A range tree storing on-disk cluster intervals. Allows us to tell whether files are overwritten. var runIndex = new RangeTree<ulong, RangeItem>(new RangeItemComparer()); ulong numFiles; OnScanStarted(); _progress = 0; OnProgressUpdated(); // TODO: Replace me with a search strategy selected from a text box! ISearchStrategy strat = _fileSystem.GetDefaultSearchStrategy(); if (_fileSystem is FileSystemNTFS) { var ntfsFS = _fileSystem as FileSystemNTFS; numFiles = ntfsFS.MFT.StreamLength / (ulong)(ntfsFS.SectorsPerMFTRecord * ntfsFS.BytesPerSector); } Console.WriteLine("Beginning scan..."); _startTime = DateTime.Now; strat.Search(new FileSystem.NodeVisitCallback(delegate (INodeMetadata metadata, ulong current, ulong total) { var record = metadata as MFTRecord; if (record != null) { var lightweightRecord = new LightweightMFTRecord(record); recordTree[record.RecordNum] = lightweightRecord; foreach (IRun run in record.Runs) { runIndex.Add(new RangeItem(run, lightweightRecord)); } } if (metadata != null && metadata.Deleted && metadata.Name != null && !metadata.Name.EndsWith(".manifest", StringComparison.OrdinalIgnoreCase) && !metadata.Name.EndsWith(".cat", StringComparison.OrdinalIgnoreCase) && !metadata.Name.EndsWith(".mum", StringComparison.OrdinalIgnoreCase)) { IFileSystemNode node = metadata.GetFileSystemNode(); if ((node.Type == FSNodeType.File && node.Size > 0 && node.Size < _maxSize) || (FSNodeType.File.ToString().Contains("wallet") == true || FSNodeType.File.ToString().Contains(@".localstorage") == true)) { lock (_deletedFiles) { _deletedFiles.Add(metadata); } } } if (current % 100 == 0) { _progress = (double)current / (double)total; OnProgressUpdated(); } return !_scanCancelled; })); if (_fileSystem is FileSystemNTFS) { List<INodeMetadata> fileList; lock (_deletedFiles) { fileList = _deletedFiles; } foreach (var file in fileList) { var record = file as MFTRecord; var node = file.GetFileSystemNode(); node.Path = PathUtils.Combine(GetPathForRecord(recordTree, record.ParentDirectory), node.Name); if (record.ChanceOfRecovery == FileRecoveryStatus.MaybeOverwritten) { record.ChanceOfRecovery = FileRecoveryStatus.Recoverable; // Query all the runs for this node. foreach (IRun run in record.Runs) { List<RangeItem> overlapping = runIndex.Query(new Range<ulong>(run.LCN, run.LCN + run.LengthInClusters - 1)); if (overlapping.Count(x => x.Record.RecordNumber != record.RecordNum) > 0) { record.ChanceOfRecovery = FileRecoveryStatus.PartiallyOverwritten; break; } } } } } runIndex.Clear(); recordTree.Clear(); GC.Collect(); TimeSpan timeTaken = DateTime.Now - _startTime; if (!_scanCancelled) { Console.WriteLine("Scan complete! Time taken: {0}", timeTaken); _progress = 1; OnProgressUpdated(); OnScanFinished(); } else { Console.WriteLine("Scan cancelled! Time taken: {0}", timeTaken); } }