Example #1
0
        public DataBlock(byte[] buffer, bCryptMethodName bCryptMethod) : base(buffer)
        {
            m_bCryptMethod = bCryptMethod;
            Data           = new byte[BlockTrailer.cb];
            Array.Copy(buffer, Data, BlockTrailer.cb);

            // DataBlock's data may be decoded
            Data = GetDecodedData();
        }
Example #2
0
        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();
            }
        }
Example #3
0
 // Data tree root is either a single data block, or an XBlock / XXBlock
 public DataTree(PSTFile file, Block rootBlock) : base(file)
 {
     m_bCryptMethod = file.Header.bCryptMethod;
     m_rootBlock    = rootBlock;
 }
Example #4
0
        private Block m_rootBlock; // can be DataBlock, XBlock or XXBlock (or null [if we deleted the data tree])

        /// <summary>
        /// Create new data tree
        /// </summary>
        public DataTree(PSTFile file) : base(file)
        {
            m_bCryptMethod = file.Header.bCryptMethod;
            m_rootBlock    = new DataBlock(m_bCryptMethod);
            AddBlock(m_rootBlock);
        }
Example #5
0
 public DataBlock(bCryptMethodName bCryptMethod)
 {
     m_bCryptMethod = bCryptMethod;
 }
Example #6
0
        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);
        }