Esempio n. 1
0
        public void Delete_Symlink()
        {
            SetupTests();

            ReparsePoint.Create(SymlinkPath, FirstTargetPath, true, ReparsePoint.LinkType.DirectoryLink);
            ReparsePoint.Delete(SymlinkPath);

            Assert.IsFalse(Directory.Exists(SymlinkPath));
        }
Esempio n. 2
0
        public void Create_And_GetTarget_Symlink()
        {
            SetupTests();

            ReparsePoint.Create(SymlinkPath, FirstTargetPath, true, ReparsePoint.LinkType.DirectoryLink);
            var measuredTargetPath = ReparsePoint.GetTarget(SymlinkPath);

            Assert.AreEqual(FirstTargetPath, measuredTargetPath, true);
        }
Esempio n. 3
0
        protected override void ChangeDirectory(string message = null, Action callback = null, bool refreshCache = false)
        {
            if (CurrentFolder.Type == ItemType.Link)
            {
                var reparsePoint = new ReparsePoint(CurrentFolder.Path);
                var path         = reparsePoint.Target;
                if (path == null)
                {
                    if (reparsePoint.LastError == 5)
                    {
                        try
                        {
                            var cmd = string.Format("/k dir \"{0}\" /AL", Path.Combine(CurrentFolder.Path, ".."));
                            var p   = Process.Start(new ProcessStartInfo("cmd.exe", cmd)
                            {
                                CreateNoWindow         = true,
                                RedirectStandardOutput = true,
                                RedirectStandardError  = true,
                                UseShellExecute        = false
                            });
                            var    r = new Regex(string.Format("{0} \\[(.*?)\\]", Regex.Escape(CurrentFolder.Name)), RegexOptions.IgnoreCase | RegexOptions.Singleline);
                            string line;
                            while ((line = p.StandardOutput.ReadLine()) != null)
                            {
                                var m = r.Match(line);
                                if (!m.Success)
                                {
                                    continue;
                                }
                                path = m.Groups[1].Value;
                                break;
                            }
                            p.Close();
                        }
                        catch
                        {
                            //do nothing if something goes wrong
                        }
                    }

                    if (string.IsNullOrEmpty(path))
                    {
                        WindowManager.ShowMessage(Resx.IOError, reparsePoint.LastError == 5 ? Resx.ReparsePointCannotBeAccessed : Resx.ReparsePointCannotBeResolved);
                        return;
                    }
                }
                var model = FileManager.GetItemInfo(path, ItemType.Directory);
                if (model == null)
                {
                    WindowManager.ShowMessage(Resx.IOError, string.Format(Resx.ItemNotExistsOnPath, path));
                    return;
                }
                CurrentFolder = new FileSystemItemViewModel(model);
            }
            base.ChangeDirectory(message, callback, refreshCache);
        }
        public void ShouldGetTargetPathForJunction()
        {
            var path = IOPath.Combine(Environment.GetEnvironmentVariable("TEMP"), IOPath.GetRandomFileName());

            Directory.CreateDirectory(path);
            var junctionPath = string.Format("{0}+junction", path);

            JunctionPoint.Create(junctionPath, path, true);
            Assert.That(ReparsePoint.GetTarget(junctionPath), Is.EqualTo(path));
        }
Esempio n. 5
0
 /// <summary>
 /// Determines whether the specified path is a symbolic link
 /// </summary>
 /// <param name="path">The path to check</param>
 public static bool IsSymbolicLink(string path)
 {
     if (File.Exists(path) || Directory.Exists(path))
     {
         ReparsePoint p = new ReparsePoint(path);
         return(p.Tag == ReparsePoint.TagType.SymbolicLink);
     }
     else
     {
         throw new DirectoryNotFoundException(String.Format("The item at '{0}' could not be found", path));
     }
 }
        public void ReparsePoints_Empty()
        {
            NtfsFileSystem ntfs = new FileSystemSource().NtfsFileSystem();

            ntfs.CreateDirectory("dir");
            ntfs.SetReparsePoint("dir", new ReparsePoint(12345, new byte[0]));

            ReparsePoint rp = ntfs.GetReparsePoint("dir");

            Assert.AreEqual(12345, rp.Tag);
            Assert.IsNotNull(rp.Content);
            Assert.AreEqual(0, rp.Content.Length);
        }
Esempio n. 7
0
        public void ReparsePoints_NonEmpty()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            ntfs.CreateDirectory("dir");
            ntfs.SetReparsePoint("dir", new ReparsePoint(123, new byte[] { 4, 5, 6 }));

            ReparsePoint rp = ntfs.GetReparsePoint("dir");

            Assert.Equal(123, rp.Tag);
            Assert.NotNull(rp.Content);
            Assert.Equal(3, rp.Content.Length);
        }
Esempio n. 8
0
        public void Copy_Files_From_Symlink()
        {
            SetupTests();

            var originalFiles = Directory.GetFiles(FirstTargetPath).Length;

            ReparsePoint.Create(SymlinkPath, FirstTargetPath, true, ReparsePoint.LinkType.DirectoryLink);
            FileActions.CopyDirectory(SymlinkPath, SecondTargetPath);

            var measuredFiles = Directory.GetFiles(SecondTargetPath).Length;

            Assert.AreEqual(originalFiles, measuredFiles);
        }
        public void TargetExistsTest()
        {
            Helper.DemandTestDriveAvailable(TestDrive);

            Assert.IsTrue(ReparsePoint.TargetExists(@"Y:\ReadTests\Junction"));
            Assert.IsTrue(ReparsePoint.TargetExists(@"Y:\ReadTests\SymbolicLink"));
            Assert.IsTrue(ReparsePoint.TargetExists(@"Y:\ReadTests\Volume"));
            Assert.IsTrue(ReparsePoint.TargetExists(@"Y:\ReadTests\SymbolicLink.txt"));

            Assert.IsFalse(ReparsePoint.TargetExists(@"Y:\ReadTests\Hardlink.txt"));
            Assert.IsFalse(ReparsePoint.TargetExists(@"Y:\ReadTests\Original"));
            Assert.IsFalse(ReparsePoint.TargetExists(@"Y:\ReadTests\Original.txt"));

            Assert.IsFalse(ReparsePoint.TargetExists(@"Y:\ReadTests\NotExists"));
        }
Esempio n. 10
0
        public void Create_And_Move_Symlink()
        {
            SetupTests();

            var originalFiles       = Directory.GetFiles(FirstTargetPath).Length + Directory.GetDirectories(FirstTargetPath).Length;
            var originalTargetFiles = Directory.GetFiles(SecondTargetPath).Length + Directory.GetDirectories(SecondTargetPath).Length;

            ReparsePoint.Create(SymlinkPath, FirstTargetPath, true, ReparsePoint.LinkType.DirectoryLink);
            var doubles = ReparsePoint.Move(SymlinkPath, SecondTargetPath, true, ReparsePoint.LinkType.DirectoryLink);

            var measuredTargetPath = ReparsePoint.GetTarget(SymlinkPath);
            var measuredFiles      = Directory.GetFiles(SecondTargetPath).Length + Directory.GetDirectories(SecondTargetPath).Length;

            Assert.AreEqual(SecondTargetPath, measuredTargetPath, true);
            Assert.AreEqual(originalFiles, measuredFiles - originalTargetFiles + doubles);
        }
Esempio n. 11
0
        /// <summary>
        /// Sets the reparse point data on a file or directory.
        /// </summary>
        /// <param name="path">The file to set the reparse point on.</param>
        /// <param name="reparsePoint">The new reparse point.</param>
        public void SetReparsePoint(string path, ReparsePoint reparsePoint)
        {
            using (new NtfsTransaction())
            {
                DirectoryEntry dirEntry = GetDirectoryEntry(path);
                if (dirEntry == null)
                {
                    throw new FileNotFoundException("File not found", path);
                }
                else
                {
                    File file = GetFile(dirEntry.Reference);

                    NtfsStream stream = file.GetStream(AttributeType.ReparsePoint, null);
                    if (stream != null)
                    {
                        // If there's an existing reparse point, unhook it.
                        using (Stream contentStream = stream.Open(FileAccess.Read))
                        {
                            byte[] oldRpBuffer = Utilities.ReadFully(contentStream, (int)contentStream.Length);
                            ReparsePointRecord rp = new ReparsePointRecord();
                            rp.ReadFrom(oldRpBuffer, 0);
                            _context.ReparsePoints.Remove(rp.Tag, dirEntry.Reference);
                        }
                    }
                    else
                    {
                        stream = file.CreateStream(AttributeType.ReparsePoint, null);
                    }

                    // Set the new content
                    ReparsePointRecord newRp = new ReparsePointRecord();
                    newRp.Tag = (uint)reparsePoint.Tag;
                    newRp.Content = reparsePoint.Content;

                    byte[] contentBuffer = new byte[newRp.Size];
                    newRp.WriteTo(contentBuffer, 0);
                    using (Stream contentStream = stream.Open(FileAccess.ReadWrite))
                    {
                        contentStream.Write(contentBuffer, 0, contentBuffer.Length);
                        contentStream.SetLength(contentBuffer.Length);
                    }

                    // Update the standard information attribute - so it reflects the actual file state
                    NtfsStream stdInfoStream = file.GetStream(AttributeType.StandardInformation, null);
                    StandardInformation si = stdInfoStream.GetContent<StandardInformation>();
                    si.FileAttributes = si.FileAttributes | FileAttributeFlags.ReparsePoint;
                    stdInfoStream.SetContent(si);

                    // Update the directory entry used to open the file, so it's accurate
                    dirEntry.Details.EASizeOrReparsePointTag = newRp.Tag;
                    dirEntry.UpdateFrom(file);

                    // Write attribute changes back to the Master File Table
                    file.UpdateRecordInMft();

                    // Add the reparse point to the index
                    _context.ReparsePoints.Add(newRp.Tag, dirEntry.Reference);
                }
            }
        }
Esempio n. 12
0
 /// <summary>
 /// Sets the reparse point data on a file or directory.
 /// </summary>
 /// <param name="path">The file to set the reparse point on.</param>
 /// <param name="reparsePoint">The new reparse point.</param>
 public void SetReparsePoint(string path, ReparsePoint reparsePoint)
 {
     throw new NotSupportedException();
 }
Esempio n. 13
0
        public FileRecord(byte[] rawBytes, int offset)
        {
            Offset = offset;
            var sig = BitConverter.ToInt32(rawBytes, 0);

            if ((sig != _fileSig) && (sig != _baadSig) && (sig != 0x0))
            {
                Logger.Fatal($"Invalid signature! 0x{sig:X}");
                return;
                //throw new Exception("Invalid signature!");
            }

            if (sig == _baadSig)
            {
                Logger.Warn($"Bad signature at offset 0x{offset:X}");
                return;
            }

            Attributes = new List <Attribute>();

            FixupOffset     = BitConverter.ToInt16(rawBytes, 2);
            FixupEntryCount = BitConverter.ToInt16(rawBytes, 4);

            LogSequenceNumber = BitConverter.ToInt64(rawBytes, 0x8);

            SequenceNumber = BitConverter.ToInt16(rawBytes, 0x10);

            ReferenceCount = BitConverter.ToInt16(rawBytes, 0x12);

            FirstAttributeOffset = BitConverter.ToInt16(rawBytes, 0x14);

            EntryFlags = (EntryFlag)BitConverter.ToInt16(rawBytes, 0x16);

            Logger.Trace($"Entry flags: {EntryFlags}");

            ActualRecordSize = BitConverter.ToInt32(rawBytes, 0x18);

            AllocatedRecordSize = BitConverter.ToInt32(rawBytes, 0x1c);

            var entryBytes = new byte[8];

            Buffer.BlockCopy(rawBytes, 0x20, entryBytes, 0, 8);

            MFTRecordToBaseRecord = new MftEntryInfo(entryBytes);

            FirstAvailableAttribueId = BitConverter.ToInt16(rawBytes, 0x28);

            EntryNumber = BitConverter.ToInt32(rawBytes, 0x2c);

            var fixupExpectedBytes = new byte[2];
            var fixupActual1       = new byte[2];
            var fixupActual2       = new byte[2];

            Buffer.BlockCopy(rawBytes, 0x30, fixupExpectedBytes, 0, 2);
            Buffer.BlockCopy(rawBytes, 0x32, fixupActual1, 0, 2);
            Buffer.BlockCopy(rawBytes, 0x34, fixupActual2, 0, 2);

            //verify this record looks ok based on fixup bytes
            //0x1FE and 0x3fe

            var expectedFixupVal = BitConverter.ToInt16(fixupExpectedBytes, 0);
            var x1FeValue        = BitConverter.ToInt16(rawBytes, 0x1FE);
            var x3FeValue        = BitConverter.ToInt16(rawBytes, 0x3FE);

            if ((x1FeValue != expectedFixupVal) &&
                ((EntryFlags & EntryFlag.FileRecordSegmentInUse) == EntryFlag.FileRecordSegmentInUse))
            {
                Logger.Warn(
                    $"FILE record at offset 0x{offset:X}! Fixup values do not match at 0x1FE. Expected: {expectedFixupVal}, actual: {x1FeValue}, EntryFlags: {EntryFlags}");
            }

            if ((x3FeValue != expectedFixupVal) &&
                ((EntryFlags & EntryFlag.FileRecordSegmentInUse) == EntryFlag.FileRecordSegmentInUse))
            {
                Logger.Warn(
                    $"FILE record at offset 0x{offset:X}! Fixup values do not match at 0x3FE. Expected: {expectedFixupVal}, actual: {x3FeValue}, EntryFlags: {EntryFlags}");
            }

            //header is done, replace fixup bytes with actual bytes
            //0x1fe and 0x3fe should contain fixup bytes

            Buffer.BlockCopy(fixupActual1, 0, rawBytes, 0x1fe, 2);
            Buffer.BlockCopy(fixupActual2, 0, rawBytes, 0x3fe, 2);

            //start attribute processing at FirstAttributeOffset

            var index = (int)FirstAttributeOffset;

            while (index < ActualRecordSize)
            {
                var attrType = BitConverter.ToInt32(rawBytes, index);

                var attrSize = BitConverter.ToInt32(rawBytes, index + 4);

//                Logger.Trace(
//                    $"ActualRecordSize: {ActualRecordSize} attrType: 0x{attrType:X}, size: {attrSize}, index: {index}, offset: 0x{offset:x}, i+o: 0x{index + offset:X}");

                if ((attrSize == 0) || (attrType == -1))
                {
                    index += 8;          //skip -1 type and 0 size

                    if (EntryFlags == 0) //this is a free record
                    {
                        break;
                    }

                    continue;
                }

                var rawAttr = new byte[attrSize];
                Buffer.BlockCopy(rawBytes, index, rawAttr, 0, attrSize);

                switch ((AttributeType)attrType)
                {
                case AttributeType.StandardInformation:
                    var si = new StandardInfo(rawAttr);
                    Attributes.Add(si);

                    SILastAccessedOn    = si.LastAccessedOn;
                    SICreatedOn         = si.CreatedOn;
                    SIRecordModifiedOn  = si.RecordModifiedOn;
                    SIContentModifiedOn = si.ContentModifiedOn;

                    break;

                case AttributeType.FileName:
                    var fi = new FileName(rawAttr);
                    Attributes.Add(fi);

                    if ((fi.FileInfo.NameType & NameTypes.Windows) == NameTypes.Windows)
                    {
                        FName = fi.FileInfo.FileName;
                    }

                    //if (fi.FileInfo.LastAccessedOn.UtcDateTime != SILastAccessedOn.UtcDateTime)
                    //{
                    FNLastAccessedOn = fi.FileInfo.LastAccessedOn;
                    //}

                    //if (fi.FileInfo.CreatedOn.UtcDateTime != SICreatedOn.UtcDateTime)
                    //{
                    FNCreatedOn = fi.FileInfo.CreatedOn;
                    //}

                    //if (fi.FileInfo.RecordModifiedOn.UtcDateTime != SIRecordModifiedOn.UtcDateTime)
                    //{
                    FNRecordModifiedOn = fi.FileInfo.RecordModifiedOn;
                    //}


                    //if (fi.FileInfo.ContentModifiedOn.UtcDateTime != SIContentModifiedOn.UtcDateTime)
                    //{
                    FNContentModifiedOn = fi.FileInfo.ContentModifiedOn;
                    //}


                    break;

                case AttributeType.Data:
                    var data = new Data(rawAttr);
                    Attributes.Add(data);
                    break;

                case AttributeType.IndexAllocation:
                    var ia = new IndexAllocation(rawAttr);
                    Attributes.Add(ia);
                    break;

                case AttributeType.IndexRoot:
                    var ir = new IndexRoot(rawAttr);
                    Attributes.Add(ir);
                    break;

                case AttributeType.Bitmap:
                    var bm = new Bitmap(rawAttr);
                    Attributes.Add(bm);
                    break;

                case AttributeType.VolumeVersionObjectId:
                    var oi = new ObjectId(rawAttr);
                    Attributes.Add(oi);
                    break;

                case AttributeType.SecurityDescriptor:
                    var sd = new SecurityDescriptor(rawAttr);
                    Attributes.Add(sd);

                    break;

                case AttributeType.VolumeName:
                    var vn = new VolumeName(rawAttr);
                    Attributes.Add(vn);
                    break;

                case AttributeType.VolumeInformation:
                    var vi = new VolumeInformation(rawAttr);
                    Attributes.Add(vi);
                    break;

                case AttributeType.LoggedUtilityStream:
                    var lus = new LoggedUtilityStream(rawAttr);
                    Attributes.Add(lus);
                    break;

                case AttributeType.ReparsePoint:
                    var rp = new ReparsePoint(rawAttr);
                    Attributes.Add(rp);
                    break;

                case AttributeType.AttributeList:
                    var al = new AttributeList(rawAttr);
                    Attributes.Add(al);
                    break;

                case AttributeType.Ea:
                    //TODO Finish this
                    var ea = new ExtendedAttribute(rawAttr);
                    Attributes.Add(ea);
                    break;

                case AttributeType.EaInformation:
                    var eai = new ExtendedAttributeInformation(rawAttr);
                    Attributes.Add(eai);
                    break;

                default:
                    Logger.Warn($"Unhandled attribute type! Add me: {(AttributeType) attrType}");
                    throw new Exception($"Add me: {(AttributeType) attrType}");
                    break;
                }

                index += attrSize;
            }

            SlackStartOffset = index;

            //rest is slack. handle here?
            Logger.Trace($"Slack starts at {index} i+o: 0x{index + offset:X}");
        }
Esempio n. 14
0
        /// <summary>
        /// Gets the target of a Symbloic Link or Junction Point
        /// </summary>
        /// <param name="path">The path of the Symbolic link or Junction Point</param>
        /// <returns>Returns the path the Reparse Point points to</returns>
        public static string GetLinkTarget(string path)
        {
            ReparsePoint p = new ReparsePoint(path);

            return(p.Target);
        }
Esempio n. 15
0
        /// <summary>
        /// Determines whether the specified path is a Junction Point
        /// </summary>
        /// <param name="path">The path to check</param>
        public static bool IsJunctionPoint(string path)
        {
            ReparsePoint p = new ReparsePoint(path);

            return(p.Tag == ReparsePoint.TagType.JunctionPoint);
        }
Esempio n. 16
0
        /// <summary>
        /// Validates the directories.
        /// </summary>
        /// <returns><c>true</c> if directories are valid; otherwise <c>false</c>.</returns>
        internal bool ValidateDirectories()
        {
            if (string.IsNullOrEmpty(this.ReferenceDirectory))
            {
                this.Error  = true;
                this.Status = Resources.ErrorNoReferenceDirectory;
                return(false);
            }

            if (string.IsNullOrEmpty(this.TargetDirectory))
            {
                this.Error  = true;
                this.Status = Resources.ErrorNoTargetDirectory;
                return(false);
            }

            // Resolve ReparsePoints
            try
            {
                this.ReferenceDirectory = ReparsePoint.GetTargetDirectory(new DirectoryInfo(this.ReferenceDirectory));
            }
            catch (Exception)
            {
            }

            try
            {
                this.TargetDirectory = ReparsePoint.GetTargetDirectory(new DirectoryInfo(this.TargetDirectory));
            }
            catch (Exception)
            {
            }

            // Normalize paths
            if (!this.ReferenceDirectory.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.OrdinalIgnoreCase))
            {
                this.ReferenceDirectory += Path.DirectorySeparatorChar.ToString();
            }

            if (!this.TargetDirectory.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.OrdinalIgnoreCase))
            {
                this.TargetDirectory += Path.DirectorySeparatorChar.ToString();
            }

            // Compare directories
            if (this.ReferenceDirectory.Equals(this.TargetDirectory, StringComparison.OrdinalIgnoreCase))
            {
                this.Error  = true;
                this.Status = Resources.ErrorReferenceDirectoryEqualsTargetDirectory;
                return(false);
            }

            // Create reference directory
            if (!Directory.Exists(this.ReferenceDirectory))
            {
                if (this.SyncMode.CreateReferenceDirectory)
                {
                    try
                    {
                        Directory.CreateDirectory(this.ReferenceDirectory);
                    }
                    catch (Exception)
                    {
                        this.Error  = true;
                        this.Status = Resources.ErrorReferenceDirectoryCouldNotBeCreated;
                        return(false);
                    }
                }
                else
                {
                    this.Error  = true;
                    this.Status = Resources.ErrorReferenceDirectoryDoesNotExist;
                    return(false);
                }
            }

            // Create target directory
            if (!Directory.Exists(this.TargetDirectory))
            {
                if (this.SyncMode.CreateTargetDirectory)
                {
                    try
                    {
                        Directory.CreateDirectory(this.TargetDirectory);
                    }
                    catch (Exception)
                    {
                        this.Error  = true;
                        this.Status = Resources.ErrorTargetDirectoryCouldNotBeCreated;
                        return(false);
                    }
                }
                else
                {
                    this.Error  = true;
                    this.Status = Resources.ErrorTargetDirectoryDoesNotExist;
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 17
0
        public FileRecord(byte[] rawBytes, int offset)
        {
            Offset = offset;

            var sig = BitConverter.ToInt32(rawBytes, 0);

            switch (sig)
            {
            case FileSig:
                break;

            case BaadSig:
                _logger.Debug($"Bad signature at offset 0x{offset:X}");
                IsBad = true;
                return;

            default:
                //not initialized
                _logger.Debug($"Uninitialized entry (no signature) at offset 0x{offset:X}");
                IsUninitialized = true;
                return;
            }

            _logger.Debug($"Processing FILE record at offset 0x{offset:X}");

            Attributes = new List <Attribute>();

            FixupOffset     = BitConverter.ToInt16(rawBytes, 0x4);
            FixupEntryCount = BitConverter.ToInt16(rawBytes, 0x6);

            //to build fixup info, take FixupEntryCount x 2 bytes as each are 2 bytes long
            var fixupTotalLength = FixupEntryCount * 2;

            var fixupBuffer = new byte[fixupTotalLength];

            Buffer.BlockCopy(rawBytes, FixupOffset, fixupBuffer, 0, fixupTotalLength);

            //pull this early so we can check if its free in our fix up value messages
            EntryFlags = (EntryFlag)BitConverter.ToInt16(rawBytes, 0x16);

            FixupData = new FixupData(fixupBuffer);

            FixupOk = true;

            //fixup verification
            var counter = 512;

            foreach (var bytese in FixupData.FixupActual)
            {
                //adjust the offset to where we need to check
                var fixupOffset = counter - 2;

                var expected = BitConverter.ToInt16(rawBytes, fixupOffset);
                if (expected != FixupData.FixupExpected && EntryFlags != 0x0)
                {
                    FixupOk = false;
                    _logger.Warn(
                        $"Offset: 0x{Offset:X} Entry/seq: 0x{EntryNumber:X}/0x{SequenceNumber:X} Fixup values do not match at 0x{fixupOffset:X}. Expected: 0x{FixupData.FixupExpected:X2}, actual: 0x{expected:X2}");
                }

                //replace fixup expected with actual bytes. bytese has actual replacement values in it.
                Buffer.BlockCopy(bytese, 0, rawBytes, fixupOffset, 2);

                counter += 512;
            }

            LogSequenceNumber = BitConverter.ToInt64(rawBytes, 0x8);

            SequenceNumber = BitConverter.ToUInt16(rawBytes, 0x10);

            ReferenceCount = BitConverter.ToInt16(rawBytes, 0x12);

            FirstAttributeOffset = BitConverter.ToInt16(rawBytes, 0x14);

            ActualRecordSize = BitConverter.ToInt32(rawBytes, 0x18);

            AllocatedRecordSize = BitConverter.ToInt32(rawBytes, 0x1c);

            var entryBytes = new byte[8];

            Buffer.BlockCopy(rawBytes, 0x20, entryBytes, 0, 8);

            MftRecordToBaseRecord = new MftEntryInfo(entryBytes);

            FirstAvailablAttribueId = BitConverter.ToInt16(rawBytes, 0x28);

            EntryNumber = BitConverter.ToUInt32(rawBytes, 0x2c);

            //start attribute processing at FirstAttributeOffset

            var index = (int)FirstAttributeOffset;

            while (index < ActualRecordSize)
            {
                var attrType = (AttributeType)BitConverter.ToInt32(rawBytes, index);

                var attrSize = BitConverter.ToInt32(rawBytes, index + 4);

                if (attrSize == 0 || attrType == AttributeType.EndOfAttributes)
                {
                    index += 8; //skip -1 type and 0 size

                    if (index != ActualRecordSize)
                    {
                        _logger.Warn($"Slack space found in entry/seq: 0x{EntryNumber:X}/0x{SequenceNumber:X}");
                    }

                    //TODO process slack here?
                    break;
                }

                _logger.Debug(
                    $"Found Attribute Type {attrType.ToString()} at absolute offset: 0x{index + offset:X}");

                _logger.Trace(
                    $"ActualRecordSize: 0x{ActualRecordSize:X}, size: 0x{attrSize:X}, index: 0x{index:X}");

                var rawAttr = new byte[attrSize];
                Buffer.BlockCopy(rawBytes, index, rawAttr, 0, attrSize);

                switch (attrType)
                {
                case AttributeType.StandardInformation:
                    var si = new StandardInfo(rawAttr);
                    Attributes.Add(si);
                    break;

                case AttributeType.FileName:
                    var fi = new FileName(rawAttr);
                    Attributes.Add(fi);
                    break;

                case AttributeType.Data:
                    var d = new Data(rawAttr);
                    Attributes.Add(d);
                    break;

                case AttributeType.IndexAllocation:
                    var ia = new IndexAllocation(rawAttr);
                    Attributes.Add(ia);
                    break;

                case AttributeType.IndexRoot:
                    var ir = new IndexRoot(rawAttr);
                    Attributes.Add(ir);
                    break;

                case AttributeType.Bitmap:
                    var bm = new Bitmap(rawAttr);
                    Attributes.Add(bm);
                    break;

                case AttributeType.VolumeVersionObjectId:
                    var oi = new ObjectId_(rawAttr);
                    Attributes.Add(oi);
                    break;

                case AttributeType.SecurityDescriptor:
                    var sd = new SecurityDescriptor(rawAttr);
                    Attributes.Add(sd);
                    break;

                case AttributeType.VolumeName:
                    var vn = new VolumeName(rawAttr);
                    Attributes.Add(vn);
                    break;

                case AttributeType.VolumeInformation:
                    var vi = new VolumeInformation(rawAttr);
                    Attributes.Add(vi);
                    break;

                case AttributeType.LoggedUtilityStream:
                    var lus = new LoggedUtilityStream(rawAttr);
                    Attributes.Add(lus);
                    break;

                case AttributeType.ReparsePoint:
                    try
                    {
                        var rp = new ReparsePoint(rawAttr);
                        Attributes.Add(rp);
                    }
                    catch (Exception)
                    {
                        var l = LogManager.GetLogger("ReparsePoint");

                        l.Error(
                            $"There was an error parsing a ReparsePoint in FILE record at offset 0x{Offset:X}. Please extract via --dd and --do and send to [email protected]");
                    }

                    break;

                case AttributeType.AttributeList:
                    var al = new AttributeList(rawAttr);
                    Attributes.Add(al);
                    break;

                case AttributeType.Ea:
                    var ea = new ExtendedAttribute(rawAttr);
                    Attributes.Add(ea);
                    break;

                case AttributeType.EaInformation:
                    var eai = new ExtendedAttributeInformation(rawAttr);
                    Attributes.Add(eai);
                    break;

                default:
                    throw new Exception($"Add me: {attrType} (0x{attrType:X})");
                }

                index += attrSize;
            }

            //rest is slack. handle here?
            _logger.Trace($"Slack starts at 0x{index:X} Absolute offset: 0x{index + offset:X}");
        }
Esempio n. 18
-36
 /// <summary>
 /// Sets the reparse point data on a file or directory.
 /// </summary>
 /// <param name="path">The file to set the reparse point on.</param>
 /// <param name="reparsePoint">The new reparse point.</param>
 public void SetReparsePoint(string path, ReparsePoint reparsePoint)
 {
     throw new NotSupportedException();
 }