public FileRecord GetRecord(long index, bool ignoreMagic, bool ignoreBitmap) { if (ignoreBitmap || _bitmap == null || _bitmap.IsPresent(index)) { FileRecord result = _recordCache[index]; if (result != null) { return(result); } if ((index + 1) * _recordLength <= _recordStream.Length) { _recordStream.Position = index * _recordLength; byte[] recordBuffer = Utilities.ReadFully(_recordStream, _recordLength); result = new FileRecord(_bytesPerSector); result.FromBytes(recordBuffer, 0, ignoreMagic); result.LoadedIndex = (uint)index; } else { result = new FileRecord(_bytesPerSector, _recordLength, (uint)index); } _recordCache[index] = result; return(result); } return(null); }
public FileRecord GetBootstrapRecord() { _recordStream.Position = 0; byte[] mftSelfRecordData = Utilities.ReadFully(_recordStream, _recordLength); FileRecord mftSelfRecord = new FileRecord(_bytesPerSector); mftSelfRecord.FromBytes(mftSelfRecordData, 0); _recordCache[MftIndex] = mftSelfRecord; return(mftSelfRecord); }
private bool VerifyMftRecord(byte[] recordData, bool presentInBitmap, int bytesPerSector) { bool ok = true; // // Verify the attributes seem OK... // byte[] tempBuffer = new byte[recordData.Length]; Array.Copy(recordData, tempBuffer, tempBuffer.Length); GenericFixupRecord genericRecord = new GenericFixupRecord(bytesPerSector); genericRecord.FromBytes(tempBuffer, 0); int pos = Utilities.ToUInt16LittleEndian(genericRecord.Content, 0x14); while (Utilities.ToUInt32LittleEndian(genericRecord.Content, pos) != 0xFFFFFFFF) { int attrLen; try { AttributeRecord ar = AttributeRecord.FromBytes(genericRecord.Content, pos, out attrLen); if (attrLen != ar.Size) { ReportError("Attribute size is different to calculated size. AttrId={0}", ar.AttributeId); ok = false; } if (ar.IsNonResident) { NonResidentAttributeRecord nrr = (NonResidentAttributeRecord)ar; if (nrr.DataRuns.Count > 0) { long totalVcn = 0; foreach (var run in nrr.DataRuns) { totalVcn += run.RunLength; } if (totalVcn != nrr.LastVcn - nrr.StartVcn + 1) { ReportError("Declared VCNs doesn't match data runs. AttrId={0}", ar.AttributeId); ok = false; } } } } catch { ReportError("Failure parsing attribute at pos={0}", pos); return(false); } pos += attrLen; } // // Now consider record as a whole // FileRecord record = new FileRecord(bytesPerSector); record.FromBytes(recordData, 0); bool inUse = (record.Flags & FileRecordFlags.InUse) != 0; if (inUse != presentInBitmap) { ReportError("MFT bitmap and record in-use flag don't agree. Mft={0}, Record={1}", presentInBitmap ? "InUse" : "Free", inUse ? "InUse" : "Free"); ok = false; } if (record.Size != record.RealSize) { ReportError("MFT record real size is different to calculated size. Stored in MFT={0}, Calculated={1}", record.RealSize, record.Size); ok = false; } if (Utilities.ToUInt32LittleEndian(recordData, (int)record.RealSize - 8) != uint.MaxValue) { ReportError("MFT record is not correctly terminated with 0xFFFFFFFF"); ok = false; } return(ok); }