public void WriteToPage(byte[] buffer, ulong fileOffset) { if (ptype == PageTypeName.ptypeBBT || ptype == PageTypeName.ptypeNBT || ptype == PageTypeName.ptypeDL) { wSig = BlockTrailer.ComputeSignature(fileOffset, bid.Value); } else { wSig = 0; // AMap, PMap, FMap, and FPMap pages have a special convention where their BID is assigned the same value as their IB bid = new BlockID(fileOffset); } dwCRC = PSTCRCCalculation.ComputeCRC(buffer, OffsetFromPageStart); int offset = OffsetFromPageStart; buffer[offset + 0] = (byte)ptype; buffer[offset + 1] = (byte)ptype; LittleEndianWriter.WriteUInt16(buffer, offset + 2, wSig); LittleEndianWriter.WriteUInt32(buffer, offset + 4, dwCRC); LittleEndianWriter.WriteUInt64(buffer, offset + 8, bid.Value); }
public void WriteBytes(byte[] buffer, int dataLength, int offset, ulong fileOffset) { wSig = ComputeSignature(fileOffset, bid.Value); // CRC is only calculated on the raw data (i.e. excluding BlockTrailer and padding) dwCRC = PSTCRCCalculation.ComputeCRC(buffer, dataLength); LittleEndianWriter.WriteUInt16(buffer, offset + 0, cb); LittleEndianWriter.WriteUInt16(buffer, offset + 2, wSig); LittleEndianWriter.WriteUInt32(buffer, offset + 4, dwCRC); LittleEndianWriter.WriteUInt64(buffer, offset + 8, bid.Value); }
public PSTHeader(byte[] buffer) { dwMagic = ByteReader.ReadAnsiString(buffer, 0, 4); CRCPartial = LittleEndianConverter.ToUInt32(buffer, 4); wMagicClient = ByteReader.ReadAnsiString(buffer, 8, 2); wVer = LittleEndianConverter.ToUInt16(buffer, 10); wVerClient = LittleEndianConverter.ToUInt16(buffer, 12); bPlatformCreate = buffer[14]; bPlatformAccess = buffer[15]; dwReserved1 = LittleEndianConverter.ToUInt32(buffer, 16); dwReserved2 = LittleEndianConverter.ToUInt32(buffer, 20); // bidUnused - which is not necessarily zeroed out bidUnused = new BlockID(buffer, 24); bidNextP = new BlockID(buffer, 32); dwUnique = LittleEndianConverter.ToUInt32(buffer, 40); int position = 44; for (int index = 0; index < 32; index++) { rgnid[index] = LittleEndianConverter.ToUInt32(buffer, position); position += 4; } root = new RootStructure(buffer, 180); dwAlign = LittleEndianConverter.ToUInt32(buffer, 252); Array.Copy(buffer, 256, rgbFM, 0, 128); Array.Copy(buffer, 384, rgbFP, 0, 128); bSentinel = buffer[512]; bCryptMethod = (bCryptMethodName)buffer[513]; bidNextB = new BlockID(buffer, 516); dwCRCFull = LittleEndianConverter.ToUInt32(buffer, 524); Array.Copy(buffer, 528, rgbReserved2, 0, 3); bReserved = buffer[531]; Array.Copy(buffer, 532, rgbReserved3, 0, 32); uint partial = PSTCRCCalculation.ComputeCRC(buffer, 8, 471); if (partial != CRCPartial) { throw new InvalidChecksumException(); } uint full = PSTCRCCalculation.ComputeCRC(buffer, 8, 516); if (full != dwCRCFull) { throw new InvalidChecksumException(); } }
public static BTreePage ReadFromStream(Stream stream, BlockRef blockRef) { long offset = (long)blockRef.ib; stream.Seek(offset, SeekOrigin.Begin); byte[] buffer = new byte[Length]; stream.Read(buffer, 0, Length); PageTypeName ptype = (PageTypeName)buffer[PageTrailer.OffsetFromPageStart + 0]; BTreePage page; byte cLevel = buffer[491]; if (cLevel > 0) { // If cLevel is greater than 0, then each entry in the array is of type BTENTRY. page = new BTreeIndexPage(buffer); } else { // If cLevel is 0, then each entry is either of type BBTENTRY or NBTENTRY, depending on the ptype of the page. if (ptype == PageTypeName.ptypeBBT) { page = new BlockBTreeLeafPage(buffer); } else if (ptype == PageTypeName.ptypeNBT) { page = new NodeBTreeLeafPage(buffer); } else { throw new ArgumentException("BTreePage has incorrect ptype"); } } page.Offset = (ulong)blockRef.ib; if (blockRef.bid.Value != page.BlockID.Value) { throw new InvalidBlockIDException(); } uint crc = PSTCRCCalculation.ComputeCRC(buffer, PageTrailer.OffsetFromPageStart); if (page.pageTrailer.dwCRC != crc) { throw new InvalidChecksumException(); } uint signature = BlockTrailer.ComputeSignature(blockRef.ib, blockRef.bid.Value); if (page.pageTrailer.wSig != signature) { throw new InvalidChecksumException(); } return(page); }
public byte[] GetBytes(WriterCompatibilityMode writerCompatibilityMode) { byte[] buffer = new byte[HeaderLength]; ByteWriter.WriteAnsiString(buffer, 0, dwMagic, 4); // update CRCPartial later ByteWriter.WriteAnsiString(buffer, 8, wMagicClient, 2); LittleEndianWriter.WriteUInt16(buffer, 10, wVer); LittleEndianWriter.WriteUInt16(buffer, 12, wVerClient); buffer[14] = bPlatformCreate; buffer[15] = bPlatformAccess; LittleEndianWriter.WriteUInt32(buffer, 16, dwReserved1); LittleEndianWriter.WriteUInt32(buffer, 20, dwReserved2); bidUnused.WriteBytes(buffer, 24); bidNextP.WriteBytes(buffer, 32); LittleEndianWriter.WriteUInt32(buffer, 40, dwUnique); int position = 44; for (int index = 0; index < 32; index++) { LittleEndianWriter.WriteUInt32(buffer, position, rgnid[index]); position += 4; } root.WriteBytes(buffer, 180, writerCompatibilityMode); LittleEndianWriter.WriteUInt32(buffer, 252, dwAlign); Array.Copy(rgbFM, 0, buffer, 256, 128); Array.Copy(rgbFP, 0, buffer, 384, 128); buffer[512] = bSentinel; buffer[513] = (byte)bCryptMethod; bidNextB.WriteBytes(buffer, 516); // update dwCRCFull later // ullReserved // dwReserved Array.Copy(rgbReserved2, 0, buffer, 528, 3); buffer[531] = bReserved; Array.Copy(rgbReserved3, 0, buffer, 532, 32); CRCPartial = PSTCRCCalculation.ComputeCRC(buffer, 8, 471); dwCRCFull = PSTCRCCalculation.ComputeCRC(buffer, 8, 516); LittleEndianWriter.WriteUInt32(buffer, 4, CRCPartial); LittleEndianWriter.WriteUInt32(buffer, 524, dwCRCFull); return(buffer); }
public override byte[] GetBytes(ulong fileOffset) { if (rgDListPageEnt.Count > MaxNumberOfEntries) { throw new Exception("Density list contains too many entries"); } byte[] buffer = new byte[Length]; buffer[0] = bFlags; buffer[1] = (byte)rgDListPageEnt.Count; LittleEndianWriter.WriteUInt32(buffer, 4, ulCurrentPage); int offset = 8; foreach (DensityListPageEntry entry in rgDListPageEnt) { entry.WriteBytes(buffer, offset); offset += DensityListPageEntry.Length; } pageTrailer.dwCRC = PSTCRCCalculation.ComputeCRC(buffer, Length - PageTrailer.Length); pageTrailer.WriteToPage(buffer, fileOffset); return(buffer); }
public static Block ReadFromStream(Stream stream, BlockRef blockRef, int dataLength, bCryptMethodName bCryptMethod) { long offset = (long)blockRef.ib; int totalLength = GetTotalBlockLength(dataLength); stream.Seek(offset, SeekOrigin.Begin); byte[] buffer = new byte[totalLength]; stream.Read(buffer, 0, totalLength); BlockTrailer trailer = BlockTrailer.ReadFromEndOfBuffer(buffer); Block block; if (trailer.bid.Internal) { // XBlock or XXBlock byte btype = buffer[0]; byte cLevel = buffer[1]; if (btype == (byte)BlockType.XBlock && cLevel == 0x01) { // XBLOCK block = new XBlock(buffer); } else if (btype == (byte)BlockType.XXBlock && cLevel == 0x02) { // XXBLOCK block = new XXBlock(buffer); } else if (btype == (byte)BlockType.SLBLOCK && cLevel == 0x00) { // SLBLock block = new SubnodeLeafBlock(buffer); } else if (btype == (byte)BlockType.SIBLOCK && cLevel == 0x01) { // SIBLock block = new SubnodeIntermediateBlock(buffer); } else { throw new Exception("Internal block, but not XBLOCK, XXBlock, SLBLOCK or SIBLOCK"); } } else { block = new DataBlock(buffer, bCryptMethod); } // See question 3 at: // http://social.msdn.microsoft.com/Forums/en-CA/os_binaryfile/thread/923f5964-4a89-4811-86c2-06a553c34510 // However, so far all tests suggest that there should be no problem to use BlockID.Value for both arguments if (blockRef.bid.LookupValue != block.BlockID.LookupValue) { throw new InvalidBlockIDException(); } if (dataLength != trailer.cb) { throw new Exception("Invalid block length"); } uint crc = PSTCRCCalculation.ComputeCRC(buffer, dataLength); if (block.BlockTrailer.dwCRC != crc) { throw new InvalidChecksumException(); } uint signature = BlockTrailer.ComputeSignature(blockRef.ib, blockRef.bid.Value); if (block.BlockTrailer.wSig != signature) { throw new InvalidChecksumException(); } return(block); }