Example #1
0
        private void Parse(PstFileReader reader, ulong offset, IndexTree tree)
        {
            // PRGX: make sure offset is valid
            if (offset > (ulong)reader.BaseStream.Length)
            {
                throw new DataStructureException("Parse - offset beyond length of stream");
            }
            reader.BaseStream.Position = (long)offset;

            if (!reader.PstFile.Is64Bit)
            {
                //32bit
                byte[] itemsBuffer = reader.ReadBytes(496);

                this.itemCount        = reader.ReadByte();
                this.maximumItemCount = reader.ReadByte();
                this.itemSize         = reader.ReadByte();
                this.level            = reader.ReadByte();
                this.type             = reader.ReadUInt16();
                this.backPointer      = reader.ReadUInt32();
                this.crc = reader.ReadUInt32();

                if (type == 0x8080 && level > 0)
                {
                    for (int i = 0; i < itemCount; i++)
                    {
                        byte[] itemBuffer = new byte[12];
                        System.Array.Copy(itemsBuffer, i * 12, itemBuffer, 0, 12);

                        DataStructureIndexNodeItem item = new DataStructureIndexNodeItem();

                        item.Id          = BitConverter.ToUInt32(itemBuffer, 0);
                        item.BackPointer = BitConverter.ToUInt32(itemBuffer, 4);
                        item.Offset      = BitConverter.ToUInt32(itemBuffer, 8);

                        items.Add(item);

                        IndexNode childIndexNode = new IndexNode(reader, item.Offset, tree);
                        childIndexNode.Parent = this;

                        this.children.Add(childIndexNode);
                    }
                }
                else if (type == 0x8080 && level == 0)
                {
                    for (int i = 0; i < itemCount; i++)
                    {
                        byte[] itemBuffer = new byte[12];
                        System.Array.Copy(itemsBuffer, i * 12, itemBuffer, 0, 12);

                        DataStructure item = new DataStructure(itemBuffer);

                        item.Id     = BitConverter.ToUInt32(itemBuffer, 0);
                        item.Offset = BitConverter.ToUInt32(itemBuffer, 4);
                        item.Size   = BitConverter.ToUInt16(itemBuffer, 8);
                        item.Flag   = BitConverter.ToUInt16(itemBuffer, 10);

                        items.Add(item);

                        tree.Nodes.Add(item.Id, item);
                    }
                }
                else if (type == 0x8181 && level > 0)
                {
                    for (int i = 0; i < itemCount; i++)
                    {
                        byte[] itemBuffer = new byte[12];
                        System.Array.Copy(itemsBuffer, i * 12, itemBuffer, 0, 12);

                        ItemDescriptorIndexNodeItem item = new ItemDescriptorIndexNodeItem();

                        item.Id          = BitConverter.ToUInt32(itemBuffer, 0);
                        item.BackPointer = BitConverter.ToUInt32(itemBuffer, 4);
                        item.Offset      = BitConverter.ToUInt32(itemBuffer, 8);

                        items.Add(item);

                        IndexNode childIndexNode = new IndexNode(reader, item.Offset, tree);
                        childIndexNode.Parent = this;

                        this.children.Add(childIndexNode);
                    }
                }
                else if (type == 0x8181 && level == 0)
                {
                    for (int i = 0; i < itemCount; i++)
                    {
                        byte[] itemBuffer = new byte[16];
                        System.Array.Copy(itemsBuffer, i * 16, itemBuffer, 0, 16);

                        ItemDescriptor item = new ItemDescriptor();

                        item.Id      = BitConverter.ToUInt32(itemBuffer, 0);
                        item.TableId = BitConverter.ToUInt32(itemBuffer, 4);
                        item.LocalDescriptorListId  = BitConverter.ToUInt32(itemBuffer, 8);
                        item.ParentItemDescriptorId = BitConverter.ToUInt32(itemBuffer, 12);

                        items.Add(item);

                        tree.Nodes.Add(item.Id, item);

                        //root folder is parent to self.
                        if (item.Id == 290)
                        {
                            item.ParentItemDescriptorId = 0;
                        }
                    }
                }
                else
                {
                    throw new ApplicationException("Unknown IndexNode type!");
                }
            }
            else
            {
                //64bit
                byte[] itemsBuffer = reader.ReadBytes(488);

                this.itemCount        = reader.ReadByte();
                this.maximumItemCount = reader.ReadByte();
                this.itemSize         = reader.ReadByte();
                this.level            = reader.ReadByte();
                uint emptyValue = reader.ReadUInt32();
                this.type = reader.ReadUInt16();
                ushort unknow1 = reader.ReadUInt16();
                this.crc         = reader.ReadUInt32();
                this.backPointer = reader.ReadUInt64();

                if (type == 0x8080 && level > 0)
                {
                    for (int i = 0; i < itemCount; i++)
                    {
                        byte[] itemBuffer = new byte[24];
                        System.Array.Copy(itemsBuffer, i * 24, itemBuffer, 0, 24);

                        DataStructureIndexNodeItem item = new DataStructureIndexNodeItem();

                        item.Id          = BitConverter.ToUInt64(itemBuffer, 0);
                        item.BackPointer = BitConverter.ToUInt64(itemBuffer, 8);
                        item.Offset      = BitConverter.ToUInt64(itemBuffer, 16);

                        // PRGX: offset from start of file is only valid when greater than zero
                        if (item.Offset > 0 && item.Offset < (ulong)reader.BaseStream.Length)
                        {
                            items.Add(item);

                            IndexNode childIndexNode = new IndexNode(reader, item.Offset, tree);
                            childIndexNode.Parent = this;

                            this.children.Add(childIndexNode);
                        }
                    }
                }
                else if (type == 0x8080 && level == 0)
                {
                    for (int i = 0; i < itemCount; i++)
                    {
                        byte[] itemBuffer = new byte[24];
                        System.Array.Copy(itemsBuffer, i * 24, itemBuffer, 0, 24);

                        DataStructure item = new DataStructure(itemBuffer);

                        item.Id     = BitConverter.ToUInt64(itemBuffer, 0);
                        item.Offset = BitConverter.ToUInt64(itemBuffer, 8);
                        item.Size   = BitConverter.ToUInt16(itemBuffer, 16);
                        item.Flag   = BitConverter.ToUInt16(itemBuffer, 18);

                        // PRGX: offset from start of file is only valid when greater than zero
                        if (item.Offset > 0 && !tree.Nodes.ContainsKey(item.Id))
                        {
                            items.Add(item);

                            tree.Nodes.Add(item.Id, item);
                        }
                    }
                }
                else if (type == 0x8181 && level > 0)
                {
                    for (int i = 0; i < itemCount; i++)
                    {
                        byte[] itemBuffer = new byte[24];
                        System.Array.Copy(itemsBuffer, i * 24, itemBuffer, 0, 24);

                        ItemDescriptorIndexNodeItem item = new ItemDescriptorIndexNodeItem();

                        item.Id          = BitConverter.ToUInt64(itemBuffer, 0);
                        item.BackPointer = BitConverter.ToUInt64(itemBuffer, 8);
                        item.Offset      = BitConverter.ToUInt64(itemBuffer, 16);

                        // PRGX: offset from start of file is only valid when greater than zero
                        if (item.Offset > 0)
                        {
                            items.Add(item);

                            IndexNode childIndexNode = new IndexNode(reader, item.Offset, tree);
                            childIndexNode.Parent = this;

                            this.children.Add(childIndexNode);
                        }
                    }
                }
                else if ((type == 0x8181 || type == 0x0) && level == 0)
                {
                    for (int i = 0; i < itemCount; i++)
                    {
                        byte[] itemBuffer = new byte[32];
                        System.Array.Copy(itemsBuffer, i * 32, itemBuffer, 0, 32);

                        ItemDescriptor item = new ItemDescriptor();

                        item.Id      = BitConverter.ToUInt64(itemBuffer, 0);
                        item.TableId = BitConverter.ToUInt64(itemBuffer, 8);
                        item.LocalDescriptorListId  = BitConverter.ToUInt64(itemBuffer, 16);
                        item.ParentItemDescriptorId = BitConverter.ToUInt32(itemBuffer, 24);

                        if (item.Id > 0 && !tree.Nodes.ContainsKey(item.Id))
                        {
                            items.Add(item);

                            tree.Nodes.Add(item.Id, item);

                            //root folder is parent to self.
                            if (item.Id == 290)
                            {
                                item.ParentItemDescriptorId = 0;
                            }
                        }
                    }
                }
                else
                {
                    throw new ApplicationException("Unknown IndexNode type: " + type + " level: " + level);
                }
            }
        }
        private void Parse(PstFileReader reader, ulong offset)
        {
            reader.BaseStream.Position = (long)offset;

            root = new IndexNode(reader, offset, this);
        }