internal IndexAllocation(NonResident header, string volume) { // Headers Name = (ATTR_TYPE)header.commonHeader.ATTRType; NameString = header.NameString; NonResident = header.commonHeader.NonResident; AttributeId = header.commonHeader.Id; // Get IndexAllocation Bytes byte[] bytes = header.GetBytes(volume); // Instantiate empty IndexEntry List List<IndexEntry> indexEntryList = new List<IndexEntry>(); // Iterate through IndexBlocks (4096 bytes in size) for (int offset = 0; offset < bytes.Length; offset += 4096) { // Detemine size of Update Sequence ushort usOffset = BitConverter.ToUInt16(bytes, offset + 0x04); ushort usSize = BitConverter.ToUInt16(bytes, offset + 0x06); int indexBlockSize = usOffset + (usSize * 2); if (indexBlockSize == 0) { break; } IndexBlock.ApplyFixup(ref bytes, offset); // Instantiate IndexBlock Object (Header) IndexBlock indexBlock = new IndexBlock(NativeMethods.GetSubArray(bytes, (uint)offset, (uint)indexBlockSize)); // Create byte array for IndexEntry object // 0x18 represents the offset of the EntryOffset value, so it must be added on byte[] indexEntryBytes = NativeMethods.GetSubArray(bytes, (uint)offset + indexBlock.EntryOffset + 0x18, indexBlock.TotalEntrySize); int entryOffset = 0; do { // Instantiate an IndexEntry Object IndexEntry indexEntry = new IndexEntry(NativeMethods.GetSubArray(indexEntryBytes, (uint)entryOffset, BitConverter.ToUInt16(indexEntryBytes, entryOffset + 0x08))); entryOffset += indexEntry.Size; // Check if entry is the last in the Entry array if (indexEntry.Flags == 0x02 || indexEntry.Flags == 0x03) { break; } // Add IndexEntry Object to list indexEntryList.Add(indexEntry); }while(entryOffset < indexEntryBytes.Length); } Entries = indexEntryList.ToArray(); }
public static IndexEntry[] GetInstances(string path) { string[] paths = path.TrimEnd('\\').Split('\\'); // Determine Volume Name string volume = @"\\.\" + paths[0]; // Test volume path NativeMethods.getVolumeName(ref volume); int index = -1; List<IndexEntry> indexEntryList = new List<IndexEntry>(); for (int i = 0; i < paths.Length; i++) { if (index == -1) { index = 5; } else { bool match = false; foreach (IndexEntry entry in indexEntryList) { if (entry.Entry.Filename.ToUpper() == paths[i].ToUpper()) { index = (int)entry.RecordNumber; match = true; } } if (!(match)) { throw new Exception("Path " + path + " not found."); } } FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, index), volume); indexEntryList.Clear(); if (record.Directory) { foreach (Attr attr in record.Attribute) { if (attr.Name == Attr.ATTR_TYPE.INDEX_ROOT) { try { foreach (IndexEntry entry in (attr as IndexRoot).Entries) { if (entry.Entry.Namespace != 0x02) { StringBuilder sb = new StringBuilder(); sb.Append(path.TrimEnd('\\')); sb.Append("\\"); sb.Append(entry.Filename); entry.FullName = sb.ToString(); indexEntryList.Add(entry); } } } catch { return null; } } else if (attr.Name == Attr.ATTR_TYPE.INDEX_ALLOCATION) { // Get INDEX_ALLOCATION bytes IndexAllocation IA = new IndexAllocation(attr as NonResident, volume); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); foreach (IndexEntry entry in IA.Entries) { if (entry.Entry.Namespace != 0x02) { StringBuilder sb = new StringBuilder(); sb.Append(path.TrimEnd('\\')); sb.Append("\\"); sb.Append(entry.Filename); entry.FullName = sb.ToString(); indexEntryList.Add(entry); } } } } } else { IndexEntry[] indexArray = new IndexEntry[1]; indexArray[0] = new IndexEntry(record); return indexArray; } } return indexEntryList.ToArray(); }
internal IndexRoot(ResidentHeader header, byte[] attrBytes, string attrName) { #region ResidentHeader // Get ResidentHeader (includes Common Header) Name = (ATTR_TYPE)header.commonHeader.ATTRType; NameString = attrName; NonResident = header.commonHeader.NonResident; AttributeId = header.commonHeader.Id; #endregion ResidentHeader #region IndexRoot // IndexRoot AttributeType = (ATTR_TYPE)BitConverter.ToUInt32(attrBytes, 0x00); CollationSortingRule = BitConverter.ToUInt32(attrBytes, 0x04); IndexSize = BitConverter.ToUInt32(attrBytes, 0x08); ClustersPerIndexRecord = attrBytes[0x0C]; #endregion IndexRoot #region IndexHeader // IndexHeader StartOffset = (BitConverter.ToUInt32(attrBytes, 0x10) + 0x10); // Add 0x10 bytes to start offset to account for its offset TotalSize = BitConverter.ToUInt32(attrBytes, 0x14); AllocatedSize = BitConverter.ToUInt32(attrBytes, 0x18); Flags = ((INDEX_ROOT_FLAGS)BitConverter.ToUInt32(attrBytes, 0x1C)); #endregion IndexHeader #region IndexEntryArray if(TotalSize > StartOffset){ // IndexEntry[] byte[] EntryBytes = NativeMethods.GetSubArray(attrBytes, StartOffset, TotalSize - StartOffset); // Iterate through IndexEntry object int indexEntryOffset = 0; if (AttributeType == ATTR_TYPE.FILE_NAME) { // Instantiate empty IndexEntry List List<IndexEntry> entryList = new List<IndexEntry>(); while (indexEntryOffset < (EntryBytes.Length - 0x10)) { // Creat byte array representing IndexEntry Object int indexEntrySizeOffset = indexEntryOffset + 0x08; // Instantiate an IndexEntry Object IndexEntry indexEntry = new IndexEntry(NativeMethods.GetSubArray(EntryBytes, (uint)indexEntryOffset, (uint)BitConverter.ToUInt16(EntryBytes, indexEntrySizeOffset))); // Add IndexEntry Object to FileName List entryList.Add(indexEntry); // Increment indexEntryOffset indexEntryOffset += indexEntry.Size; } Entries = entryList.ToArray(); } } #endregion IndexEntryArray }