/// <summary>
 /// Initializes a new instance of the NtfsFileSystemChecker class.
 /// </summary>
 /// <param name="diskData">The file system to check</param>
 public NtfsFileSystemChecker(Stream diskData)
 {
     SnapshotStream protectiveStream = new SnapshotStream(diskData, Ownership.None);
     protectiveStream.Snapshot();
     protectiveStream.Freeze();
     _target = protectiveStream;
 }
 /// <summary>
 /// Initializes a new instance of the NtfsFileSystemChecker class.
 /// </summary>
 /// <param name="diskData">The file system to check.</param>
 public NtfsFileSystemChecker(Stream diskData)
 {
     SnapshotStream protectiveStream = new SnapshotStream(diskData, Ownership.None);
     protectiveStream.Snapshot();
     protectiveStream.Freeze();
     _target = protectiveStream;
 }
        /// <summary>
        /// Saves or updates the current snapshot for a given aggregate
        /// </summary>
        /// <typeparam name="T">Type of snapshot</typeparam>
        /// <param name="snapshot">Snapshot instance</param>
        public void SaveSnapshot <T>(Snapshot <T> snapshot)
        {
            var snapshotStream = new SnapshotStream
            {
                AggregateRootId = snapshot.AggregateRootId.AsGuid,
                Version         = snapshot.Version,
                DateCreated     = DateTime.UtcNow,
                SnapshotType    = typeof(T).Name,
                SnapshotData    = JsonConvert.SerializeObject(snapshot.Data, SerializerSettings)
            };

            GetRepository().InsertSnapshot(snapshotStream);
        }
Beispiel #4
0
        private void ReplayLog()
        {
            _freeSpace.Reserve((long)_header.LogOffset, _header.LogLength);

            _logicalStream = _fileStream;

            // If log is empty, skip.
            if (_header.LogGuid == Guid.Empty)
            {
                return;
            }

            LogSequence activeLogSequence = FindActiveLogSequence();

            if (activeLogSequence == null || activeLogSequence.Count == 0)
            {
                throw new IOException("Unable to replay VHDX log, suspected corrupt VHDX file");
            }

            if (activeLogSequence.Head.FlushedFileOffset > (ulong)_logicalStream.Length)
            {
                throw new IOException("truncated VHDX file found while replaying log");
            }

            if (activeLogSequence.Count > 1 || !activeLogSequence.Head.IsEmpty)
            {
                // However, have seen VHDX with a non-empty log with no data to replay.  These are
                // 'safe' to open.
                if (!_fileStream.CanWrite)
                {
                    SnapshotStream replayStream = new SnapshotStream(_fileStream, Ownership.None);
                    replayStream.Snapshot();
                    _logicalStream = replayStream;
                }
                foreach (LogEntry logEntry in activeLogSequence)
                {
                    if (logEntry.LogGuid != _header.LogGuid)
                    {
                        throw new IOException("Invalid log entry in VHDX log, suspected currupt VHDX file");
                    }
                    if (logEntry.IsEmpty)
                    {
                        continue;
                    }
                    logEntry.Replay(_logicalStream);
                }
                _logicalStream.Seek((long)activeLogSequence.Head.LastFileOffset, SeekOrigin.Begin);
            }
        }
Beispiel #5
0
        public DdrPs2FileDataTableChunk GetBound(Stream stream)
        {
            var cache       = new CachedStream(stream);
            var cacheReader = new BinaryReader(cache);

            var entryCount = cacheReader.ReadInt32();
            var offsets    = Enumerable.Range(0, entryCount).Select(x => cacheReader.ReadInt32()).ToArray();
            var lengths    = Enumerable.Range(0, entryCount).Select(x => cacheReader.ReadInt32()).ToArray();
            var entries    = offsets.Select((e, i) => (Offset: e, Length: lengths[i])).OrderBy(x => x.Offset).ToArray();
            var max        = entries.Last().Use(x => x.Length + x.Offset);

            cache.Rewind();
            var snapshot = new SnapshotStream(cache);

            snapshot.TryRead(new byte[max], 0, max);
            return(new DdrPs2FileDataTableChunk
            {
                Data = snapshot.ToArray(),
                HasHeaders = false
            });
        }
Beispiel #6
0
        protected override void DoRun()
        {
            using (VirtualDisk inDisk = VirtualDisk.OpenDisk(_inFile.Value, FileAccess.Read, UserName, Password))
            {
                VirtualDiskParameters diskParams = inDisk.Parameters;
                diskParams.AdapterType = AdapterType;

                VirtualDiskTypeInfo diskTypeInfo = VirtualDisk.GetDiskType(OutputDiskType, OutputDiskVariant);
                if (diskTypeInfo.DeterministicGeometry)
                {
                    diskParams.Geometry = diskTypeInfo.CalcGeometry(diskParams.Capacity);
                }

                if (_translation.IsPresent && _translation.EnumValue != GeometryTranslation.None)
                {
                    diskParams.BiosGeometry = diskParams.Geometry.TranslateToBios(diskParams.Capacity, _translation.EnumValue);
                }
                else if (!inDisk.DiskTypeInfo.PreservesBiosGeometry)
                {
                    // In case the BIOS geometry was just a default, it's better to override based on the physical geometry
                    // of the new disk.
                    diskParams.BiosGeometry = Geometry.MakeBiosSafe(diskParams.Geometry, diskParams.Capacity);
                }

                using (VirtualDisk outDisk = VirtualDisk.CreateDisk(OutputDiskType, OutputDiskVariant, _outFile.Value, diskParams, UserName, Password))
                {
                    if (outDisk.Capacity < inDisk.Capacity)
                    {
                        Console.WriteLine("ERROR: The output disk is smaller than the input disk, conversion aborted");
                    }

                    SparseStream contentStream = inDisk.Content;

                    if (_translation.IsPresent && _translation.EnumValue != GeometryTranslation.None)
                    {
                        SnapshotStream ssStream = new SnapshotStream(contentStream, Ownership.None);
                        ssStream.Snapshot();

                        UpdateBiosGeometry(ssStream, inDisk.BiosGeometry, diskParams.BiosGeometry);

                        contentStream = ssStream;
                    }

                    StreamPump pump = new StreamPump()
                    {
                        InputStream  = contentStream,
                        OutputStream = outDisk.Content,
                        SparseCopy   = !_wipe.IsPresent
                    };

                    if (!Quiet)
                    {
                        long totalBytes = contentStream.Length;
                        if (!_wipe.IsPresent)
                        {
                            totalBytes = 0;
                            foreach (var se in contentStream.Extents)
                            {
                                totalBytes += se.Length;
                            }
                        }

                        DateTime now = DateTime.Now;
                        pump.ProgressEvent += (o, e) => { ShowProgress("Progress", totalBytes, now, o, e); };
                    }

                    pump.Run();
                }
            }
        }
        protected override void DoRun()
        {
            if (!IsAdministrator())
            {
                Console.WriteLine("\nThis utility must be run as an administrator!\n");
                Environment.Exit(1);
            }

            DiskImageBuilder builder = DiskImageBuilder.GetBuilder(OutputDiskType, OutputDiskVariant);

            builder.GenericAdapterType = AdapterType;

            string[] sourceVolume = _volumes.Values;

            uint diskNumber;

            List <CloneVolume> cloneVolumes = GatherVolumes(sourceVolume, out diskNumber);


            if (!Quiet)
            {
                Console.WriteLine("Inspecting Disk...");
            }

            // Construct a stream representing the contents of the cloned disk.
            BiosPartitionedDiskBuilder contentBuilder;
            Geometry biosGeometry;
            Geometry ideGeometry;
            long     capacity;

            using (Disk disk = new Disk(diskNumber))
            {
                contentBuilder = new BiosPartitionedDiskBuilder(disk);
                biosGeometry   = disk.BiosGeometry;
                ideGeometry    = disk.Geometry;
                capacity       = disk.Capacity;
            }

            // Preserve the IDE (aka Physical) geometry
            builder.Geometry = ideGeometry;

            // Translate the BIOS (aka Logical) geometry
            GeometryTranslation translation = _translation.EnumValue;

            if (builder.PreservesBiosGeometry && translation == GeometryTranslation.Auto)
            {
                // If the new format preserves BIOS geometry, then take no action if asked for 'auto'
                builder.BiosGeometry = biosGeometry;
                translation          = GeometryTranslation.None;
            }
            else
            {
                builder.BiosGeometry = ideGeometry.TranslateToBios(0, translation);
            }

            if (translation != GeometryTranslation.None)
            {
                contentBuilder.UpdateBiosGeometry(builder.BiosGeometry);
            }


            IVssBackupComponents backupCmpnts;
            int status;

            if (Marshal.SizeOf(typeof(IntPtr)) == 4)
            {
                status = NativeMethods.CreateVssBackupComponents(out backupCmpnts);
            }
            else
            {
                status = NativeMethods.CreateVssBackupComponents64(out backupCmpnts);
            }


            Guid snapshotSetId = CreateSnapshotSet(cloneVolumes, backupCmpnts);

            if (!Quiet)
            {
                Console.Write("Copying Disk...");
            }


            foreach (var sv in cloneVolumes)
            {
                Volume sourceVol = new Volume(sv.SnapshotProperties.SnapshotDeviceObject, sv.SourceExtent.ExtentLength);

                SnapshotStream rawVolStream = new SnapshotStream(sourceVol.Content, Ownership.None);
                rawVolStream.Snapshot();

                byte[] volBitmap;
                int    clusterSize;
                using (NtfsFileSystem ntfs = new NtfsFileSystem(rawVolStream))
                {
                    ntfs.NtfsOptions.HideSystemFiles = false;
                    ntfs.NtfsOptions.HideHiddenFiles = false;
                    ntfs.NtfsOptions.HideMetafiles   = false;

                    // Remove VSS snapshot files (can be very large)
                    foreach (string filePath in ntfs.GetFiles(@"\System Volume Information", "*{3808876B-C176-4e48-B7AE-04046E6CC752}"))
                    {
                        ntfs.DeleteFile(filePath);
                    }

                    // Remove the page file
                    if (ntfs.FileExists(@"\Pagefile.sys"))
                    {
                        ntfs.DeleteFile(@"\Pagefile.sys");
                    }

                    // Remove the hibernation file
                    if (ntfs.FileExists(@"\hiberfil.sys"))
                    {
                        ntfs.DeleteFile(@"\hiberfil.sys");
                    }

                    using (Stream bitmapStream = ntfs.OpenFile(@"$Bitmap", FileMode.Open))
                    {
                        volBitmap = new byte[bitmapStream.Length];

                        int totalRead = 0;
                        int numRead   = bitmapStream.Read(volBitmap, 0, volBitmap.Length - totalRead);
                        while (numRead > 0)
                        {
                            totalRead += numRead;
                            numRead    = bitmapStream.Read(volBitmap, totalRead, volBitmap.Length - totalRead);
                        }
                    }

                    clusterSize = (int)ntfs.ClusterSize;

                    if (translation != GeometryTranslation.None)
                    {
                        ntfs.UpdateBiosGeometry(builder.BiosGeometry);
                    }
                }

                List <StreamExtent> extents          = new List <StreamExtent>(BitmapToRanges(volBitmap, clusterSize));
                SparseStream        partSourceStream = SparseStream.FromStream(rawVolStream, Ownership.None, extents);

                for (int i = 0; i < contentBuilder.PartitionTable.Partitions.Count; ++i)
                {
                    var part = contentBuilder.PartitionTable.Partitions[i];
                    if (part.FirstSector * 512 == sv.SourceExtent.StartingOffset)
                    {
                        contentBuilder.SetPartitionContent(i, partSourceStream);
                    }
                }
            }
            SparseStream contentStream = contentBuilder.Build();


            // Write out the disk images
            string dir  = Path.GetDirectoryName(_destDisk.Value);
            string file = Path.GetFileNameWithoutExtension(_destDisk.Value);

            builder.Content = contentStream;
            DiskImageFileSpecification[] fileSpecs = builder.Build(file);

            for (int i = 0; i < fileSpecs.Length; ++i)
            {
                // Construct the destination file path from the directory of the primary file.
                string outputPath = Path.Combine(dir, fileSpecs[i].Name);

                // Force the primary file to the be one from the command-line.
                if (i == 0)
                {
                    outputPath = _destDisk.Value;
                }

                using (SparseStream vhdStream = fileSpecs[i].OpenStream())
                    using (FileStream fs = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite))
                    {
                        StreamPump pump = new StreamPump()
                        {
                            InputStream  = vhdStream,
                            OutputStream = fs,
                        };

                        long totalBytes = 0;
                        foreach (var se in vhdStream.Extents)
                        {
                            totalBytes += se.Length;
                        }

                        if (!Quiet)
                        {
                            Console.WriteLine();
                            DateTime now = DateTime.Now;
                            pump.ProgressEvent += (o, e) => { ShowProgress(fileSpecs[i].Name, totalBytes, now, o, e); };
                        }

                        pump.Run();

                        if (!Quiet)
                        {
                            Console.WriteLine();
                        }
                    }
            }


            // Complete - tidy up
            CallAsyncMethod(backupCmpnts.BackupComplete);

            long numDeleteFailed;
            Guid deleteFailed;

            backupCmpnts.DeleteSnapshots(snapshotSetId, 2 /*VSS_OBJECT_SNAPSHOT_SET*/, true, out numDeleteFailed, out deleteFailed);

            Marshal.ReleaseComObject(backupCmpnts);
        }
Beispiel #8
0
 public void InsertSnapshot(SnapshotStream snapshot)
 {
     EnsureContext();
     _context.SnapshotStreams.Add(snapshot);
     _context.SaveChanges();
 }
Beispiel #9
0
        public DdrPs2FileDataTableChunk GetUnbound(Stream stream)
        {
            var cache       = new CachedStream(stream);
            var cacheReader = new BinaryReader(cache);

            using var snapshot = new SnapshotStream(cache);
            var snapshotReader = new BinaryReader(snapshot);
            var firstFile      = snapshotReader.ReadInt32();
            var tableSize      = firstFile / 4 * 4;
            var table          = Enumerable.Range(0, firstFile / 4).Select(_ => snapshotReader.ReadInt32()).ToArray();
            var skip           = firstFile - tableSize;
            int index;

            if (skip > 0)
            {
                snapshotReader.ReadBytes(skip);
            }

            for (index = 1; index < table.Length; index++)
            {
                if (table[index] < table[index - 1])
                {
                    break;
                }
            }

            // Warning: big heckin' hack.
            // We're looking for a TCB table, which puts headers on all the file entries.
            // There's no way to tell easily outside of this function, so...

            var prevPosition = cache.Position;

            cache.Position = table[0];
            var headTest0 = cacheReader.ReadInt32();
            var headTest1 = cacheReader.ReadInt32();
            var headTest2 = cacheReader.ReadInt32();

            var hasHeaders = headTest0 > 0 && headTest1 > 0 && headTest2 > 0 &&
                             headTest2 > headTest1 && headTest1 > headTest0 &&
                             (headTest0 & 0x3) == 0 &&
                             ((headTest0 | headTest1 | headTest2) >> 24) == 0;

            cache.Position = prevPosition;
            var desiredPosition = table[index - 1];

            snapshotReader.ReadBytes((int)(desiredPosition - prevPosition));

            if (hasHeaders)
            {
                snapshotReader.ReadBytes(0xC);
            }

            try
            {
                _bemaniLzDecoder.Decode(snapshot);
            }
            catch (Exception)
            {
                return(null);
            }

            return(new DdrPs2FileDataTableChunk
            {
                Data = snapshot.ToArray(),
                HasHeaders = hasHeaders
            });
        }