internal override void ParseAttributeNonResidentBody(INTFSInfo ntfsInfo) { byte[] data = NtfsUtils.ReadFragments(ntfsInfo, NonResidentHeader.Fragments); List <IndexAllocationChunk> indexes = new List <IndexAllocationChunk>(); List <IndexEntry> entries = new List <IndexEntry>(); // Parse for (int i = 0; i < NonResidentHeader.Fragments.Length; i++) { for (int j = 0; j < NonResidentHeader.Fragments[i].Clusters; j++) { int offset = (int)((NonResidentHeader.Fragments[i].StartingVCN - NonResidentHeader.Fragments[0].StartingVCN) * ntfsInfo.BytesPrCluster + j * ntfsInfo.BytesPrCluster); if (!IndexAllocationChunk.IsIndexAllocationChunk(data, offset)) { continue; } IndexAllocationChunk index = IndexAllocationChunk.ParseBody(ntfsInfo, data, offset); indexes.Add(index); entries.AddRange(index.Entries); } } Indexes = indexes.ToArray(); Entries = entries.ToArray(); }
internal override void ParseAttributeResidentBody(byte[] data, int maxLength, int offset) { base.ParseAttributeResidentBody(data, maxLength, offset); // Debug.Assert(maxLength >= 48); TimeCreated = NtfsUtils.FromWinFileTime(data, offset); TimeModified = NtfsUtils.FromWinFileTime(data, offset + 8); TimeMftModified = NtfsUtils.FromWinFileTime(data, offset + 16); TimeAccessed = NtfsUtils.FromWinFileTime(data, offset + 24); DosPermissions = (FileAttributes)BitConverter.ToInt32(data, offset + 32); MaxmiumVersions = BitConverter.ToUInt32(data, offset + 36); VersionNumber = BitConverter.ToUInt32(data, offset + 40); ClassId = BitConverter.ToUInt32(data, offset + 44); // The below fields are for version 3.0+ if (NonResidentFlag == ResidentFlag.Resident && ResidentHeader.ContentLength >= 72) { // Debug.Assert(maxLength >= 72); OwnerId = BitConverter.ToUInt32(data, offset + 48); SecurityId = BitConverter.ToUInt32(data, offset + 52); QuotaCharged = BitConverter.ToUInt64(data, offset + 56); USN = BitConverter.ToUInt64(data, offset + 64); } }
internal static NtfsFileEntry CreateEntry(NTFSWrapper ntfsWrapper, uint fileId, AttributeFileName fileName = null) { if (fileName == null) { // Dig up a preferred name FileRecord tmpRecord = ntfsWrapper.ReadMFTRecord(fileId); fileName = NtfsUtils.GetPreferredDisplayName(tmpRecord); } NtfsFileEntry entry = ntfsWrapper.FileCache.Get(fileId, fileName.FileName.GetHashCode()); if (entry != null) { Debug.WriteLine("Got from cache: " + fileId + ":" + fileName.Id); return(entry); } // Create it FileRecord record = ntfsWrapper.ReadMFTRecord(fileId); if (record.Flags.HasFlag(FileEntryFlags.Directory)) { entry = new NtfsDirectory(ntfsWrapper, record, fileName); } else { entry = new NtfsFile(ntfsWrapper, record, fileName); } ntfsWrapper.FileCache.Set(fileId, fileName.Id, entry); return(entry); }
internal override void ParseAttributeNonResidentBody(INTFSInfo ntfsInfo) { base.ParseAttributeNonResidentBody(ntfsInfo); // Get all chunks byte[] data = NtfsUtils.ReadFragments(ntfsInfo, NonResidentHeader.Fragments); // Parse Debug.Assert(data.Length >= 8); List <ExtendedAttribute> extendedAttributes = new List <ExtendedAttribute>(); int pointer = 0; while (pointer + 8 <= data.Length) // 8 is the minimum size of an ExtendedAttribute { if (ExtendedAttribute.GetSize(data, pointer) <= 0) { break; } ExtendedAttribute ea = ExtendedAttribute.ParseData(data, (int)NonResidentHeader.ContentSize, pointer); extendedAttributes.Add(ea); pointer += ea.Size; } ExtendedAttributes = extendedAttributes.ToArray(); }
public static FileRecord Parse(byte[] data, int offset, ushort bytesPrSector, uint sectors) { uint length = bytesPrSector * sectors; Debug.Assert(data.Length - offset >= length); Debug.Assert(length >= 50); Debug.Assert(bytesPrSector % 512 == 0 && bytesPrSector > 0); Debug.Assert(sectors > 0); FileRecord res = new FileRecord(); Debug.Assert(res != null); //if (res == null) //{ // return null; //} res.Signature = Encoding.ASCII.GetString(data, offset + 0, 4); Debug.Assert(res.Signature == "FILE"); res.OffsetToUSN = BitConverter.ToUInt16(data, offset + 4); res.USNSizeWords = BitConverter.ToUInt16(data, offset + 6); res.LogFileUSN = BitConverter.ToUInt64(data, offset + 8); res.SequenceNumber = BitConverter.ToUInt16(data, offset + 16); res.HardlinkCount = BitConverter.ToInt16(data, offset + 18); res.OffsetToFirstAttribute = BitConverter.ToUInt16(data, offset + 20); res.Flags = (FileEntryFlags)BitConverter.ToUInt16(data, offset + 22); res.SizeOfFileRecord = BitConverter.ToUInt32(data, offset + 24); res.SizeOfFileRecordAllocated = BitConverter.ToUInt32(data, offset + 28); res.BaseFile = new FileReference(BitConverter.ToUInt64(data, offset + 32)); res.NextFreeAttributeId = BitConverter.ToUInt16(data, offset + 40); // Two unused bytes here res.MFTNumber = BitConverter.ToUInt32(data, offset + 44); res.USNNumber = new byte[2]; Array.Copy(data, offset + res.OffsetToUSN, res.USNNumber, 0, 2); Debug.Assert(data.Length - offset >= res.OffsetToUSN + 2 + res.USNSizeWords * 2); res.USNData = new byte[res.USNSizeWords * 2 - 2]; Array.Copy(data, offset + res.OffsetToUSN + 2, res.USNData, 0, res.USNData.Length); res.FileReference = new FileReference(res.MFTNumber, res.SequenceNumber); // Apply the USN Path NtfsUtils.ApplyUSNPatch(data, offset, sectors, bytesPrSector, res.USNNumber, res.USNData); res._attributes = new List <Attribute>(); res._externalAttributes = new List <Attribute>(); // Parse attributes res.ParseAttributes(data, res.SizeOfFileRecord - res.OffsetToFirstAttribute, offset + res.OffsetToFirstAttribute); return(res); }
public static IndexAllocationChunk ParseBody(Ntfs ntfsInfo, byte[] data, int offset) { // Debug.Assert(data.Length >= 36); IndexAllocationChunk res = new IndexAllocationChunk(); // Parse res.Signature = Encoding.ASCII.GetString(data, offset + 0, 4); // Debug.Assert(res.Signature == "INDX"); res.OffsetToUSN = BitConverter.ToUInt16(data, offset + 4); res.USNSizeWords = BitConverter.ToUInt16(data, offset + 6); res.LogFileUSN = BitConverter.ToUInt64(data, offset + 8); res.VCNInIndexAllocation = BitConverter.ToUInt64(data, offset + 16); res.OffsetToFirstIndex = BitConverter.ToUInt32(data, offset + 24); res.SizeOfIndexTotal = BitConverter.ToUInt32(data, offset + 28); res.SizeOfIndexAllocated = BitConverter.ToUInt32(data, offset + 32); res.HasChildren = data[36]; // Debug.Assert(data.Length >= offset + res.OffsetToUSN + 2 + res.USNSizeWords * 2); res.USNNumber = new byte[2]; Array.Copy(data, offset + res.OffsetToUSN, res.USNNumber, 0, 2); res.USNData = new byte[res.USNSizeWords * 2 - 2]; Array.Copy(data, offset + res.OffsetToUSN + 2, res.USNData, 0, res.USNData.Length); // Patch USN Data NtfsUtils.ApplyUSNPatch(data, offset, (res.SizeOfIndexAllocated + 24) / ntfsInfo.BytesPerSector, (ushort)ntfsInfo.BytesPerSector, res.USNNumber, res.USNData); // Debug.Assert(offset + res.SizeOfIndexTotal <= data.Length); // Parse entries List <IndexEntry> entries = new List <IndexEntry>(); int pointer = offset + (int)(res.OffsetToFirstIndex + 24); // Offset is relative to 0x18 while (pointer <= offset + res.SizeOfIndexTotal + 24) { IndexEntry entry = IndexEntry.ParseData(data, offset + (int)res.SizeOfIndexTotal - pointer + 24, pointer); if ((entry.Flags & MFTIndexEntryFlags.LastEntry) != 0) { break; } entries.Add(entry); pointer += entry.Size; } res.Entries = entries; return(res); }
internal override void ParseAttributeNonResidentBody(INTFSInfo ntfsInfo) { base.ParseAttributeNonResidentBody(ntfsInfo); // Get all chunks byte[] data = NtfsUtils.ReadFragments(ntfsInfo, NonResidentHeader.Fragments); // Parse Bitfield = new BitArray(data); }
internal static NtfsFileEntry CreateEntry(Ntfs ntfs, uint fileId, AttributeFileName fileName = null) { var record = ntfs.ReadMftRecord(fileId); if (fileName == null) { fileName = NtfsUtils.GetPreferredDisplayName(record); } if ((record.Flags & FileEntryFlags.Directory) != 0) { return(new NtfsDirectory(ntfs, record, fileName)); } return(new NtfsFile(ntfs, record, fileName)); }
public string BuildFileName(FileRecord record, string rootName = null) { // Get filename (and prefer the non-8dot3 variant) AttributeFileName fileName = NtfsUtils.GetPreferredDisplayName(record); if (fileName == null) { throw new NullReferenceException("Record has no FileName attribute"); } string path = fileName.FileName; if (record.Flags.HasFlag(FileEntryFlags.Directory)) { path += '\\'; } // Continue till we hit SpecialMFTFiles.RootDir FileRecord parentRecord; do { // Get parent parentRecord = ReadMFTRecord(fileName.ParentDirectory.FileId); if (parentRecord == null) { throw new NullReferenceException("A parent record was null"); } fileName = NtfsUtils.GetPreferredDisplayName(parentRecord); if (fileName == null) { throw new NullReferenceException("A parent record had no Filename attribute"); } if (parentRecord.FileReference.FileId == (uint)SpecialMFTFiles.RootDir) { path = rootName + '\\' + path; break; } path = fileName.FileName + '\\' + path; }while (true); return(path); }
internal override void ParseAttributeResidentBody(byte[] data, int maxLength, int offset) { base.ParseAttributeResidentBody(data, maxLength, offset); ParentDirectory = new FileReference(BitConverter.ToUInt64(data, offset)); CTime = NtfsUtils.FromWinFileTime(data, offset + 8); ATime = NtfsUtils.FromWinFileTime(data, offset + 16); MTime = NtfsUtils.FromWinFileTime(data, offset + 24); RTime = NtfsUtils.FromWinFileTime(data, offset + 32); AllocatedSize = BitConverter.ToUInt64(data, offset + 40); RealSize = BitConverter.ToUInt64(data, offset + 48); FileFlags = (FileAttributes)BitConverter.ToInt32(data, offset + 56); ReservedEAsReparse = BitConverter.ToUInt32(data, offset + 60); FilenameLength = data[offset + 64]; FilenameNamespace = (FileNamespace)data[offset + 65]; Debug.Assert(maxLength >= 66 + FilenameLength * 2); FileName = Encoding.Unicode.GetString(data, offset + 66, FilenameLength * 2); }
internal override void ParseAttributeNonResidentBody(RawDisk disk) { base.ParseAttributeNonResidentBody(disk); // Get all chunks byte[] data = NtfsUtils.ReadFragments(disk, NonResidentHeader.Fragments); // Parse List <AttributeListItem> results = new List <AttributeListItem>(); int pointer = 0; int contentSize = (int)NonResidentHeader.ContentSize; while (pointer + 26 <= contentSize) // 26 is the smallest possible MFTAttributeListItem { AttributeListItem item = AttributeListItem.ParseListItem(data, data.Length - pointer, pointer); if (item.Type == AttributeType.EndOfAttributes) { break; } if (item.Length == 0) { break; } results.Add(item); pointer += item.Length; } Debug.Assert(pointer == contentSize); Items = results.ToArray(); }