Example #1
0
        private void Parse(PstFileReader reader, ItemDescriptor descriptor, Table table)
        {
            this.reader     = reader;
            this.descriptor = descriptor;
            this.table      = table;

            if (reader.PstFile == null)
            {
                throw new DataStructureException("Parse - reader.PstFile was null");
            }

            if (reader.PstFile.MessageStore == null)
            {
                throw new DataStructureException("Parse - reader.PstFile.MessageStore was null");
            }

            //Compute EntryID
            if (reader.PstFile.MessageStore.RecordKey != null)
            {
                entryId = new byte[24];
                System.Array.Copy(reader.PstFile.MessageStore.RecordKey, 0, entryId, 4, 16);

                byte[] idBytes = BitConverter.GetBytes((uint)descriptor.Id);
                System.Array.Copy(idBytes, 0, entryId, 20, 4);
            }

            if (descriptor != null)
            {
                childrenCount = descriptor.Children.Count;
            }

            if (table.Entries[MapiPropertyTag.PR_DISPLAY_NAME] != null)
            {
                displayName = table.Entries[MapiPropertyTag.PR_DISPLAY_NAME].GetStringValue();
            }

            if (table.Entries[MapiPropertyTag.PR_COMMENT] != null)
            {
                comment = table.Entries[MapiPropertyTag.PR_COMMENT].GetStringValue();
            }

            if (table.Entries[MapiPropertyTag.PR_CONTENT_COUNT] != null)
            {
                itemCount = table.Entries[MapiPropertyTag.PR_CONTENT_COUNT].GetIntegerValue();
            }

            if (table.Entries[MapiPropertyTag.PR_CONTENT_UNREAD] != null)
            {
                unreadItemCount = table.Entries[MapiPropertyTag.PR_CONTENT_UNREAD].GetIntegerValue();
            }

            if (table.Entries[MapiPropertyTag.PR_SUBFOLDERS] != null)
            {
                hasSubFolders = table.Entries[MapiPropertyTag.PR_SUBFOLDERS].GetBooleanValue();
            }

            if (table.Entries[MapiPropertyTag.PR_CONTAINER_CLASS] != null)
            {
                containerClass = table.Entries[MapiPropertyTag.PR_CONTAINER_CLASS].GetStringValue();
            }
        }
        private void Parse(Stream stream, System.Text.Encoding encoding)
        {
            this.encoding = encoding;
            this.stream   = stream;
            this.reader   = new PstFileReader(this, stream);

            uint signature = reader.ReadUInt32();//offset 0

            if (signature != 0x4e444221)
            {
                Close();

                throw new FileFormatException("Invalid file format!");
            }

            uint   crc32            = reader.ReadUInt32(); //offset 4
            ushort contentType      = reader.ReadUInt16(); //offset 8
            ushort dataVersion      = reader.ReadUInt16(); //offset 10
            ushort contentVersion   = reader.ReadUInt16(); //offset 12
            byte   creationPlatform = reader.ReadByte();   //offset 14
            byte   accessPlatform   = reader.ReadByte();   //offset 15
            uint   unknown1         = reader.ReadUInt32(); //offset 16
            uint   unknown2         = reader.ReadUInt32(); //offset 20

            if (dataVersion == 0x0015 || dataVersion == 0x0017)
            {
                is64Bit = true;
            }

            if (!is64Bit)
            {
                //32-bit file
                uint unknown3 = reader.ReadUInt32();         //offset 24
                uint unknown4 = reader.ReadUInt32();         //offset 28
                uint unknown5 = reader.ReadUInt32();         //offset 32

                byte[] unknownArray1 = reader.ReadBytes(32); //offset 36
                byte[] unknownArray2 = reader.ReadBytes(32);
                byte[] unknownArray3 = reader.ReadBytes(32);
                byte[] unknownArray4 = reader.ReadBytes(32);

                uint unknown6 = reader.ReadUInt32();                      //offset 164

                size = reader.ReadInt32();                                //offset 168

                uint lastDataAllocationTableOffset = reader.ReadUInt32(); //offset 172
                uint unknown7 = reader.ReadUInt32();                      //offset 176
                uint unknown8 = reader.ReadUInt32();                      //offset 180

                descriptorIndexBackPointer = reader.ReadUInt32();
                descriptorIndex            = reader.ReadUInt32();
                dataIndexBackPointer       = reader.ReadUInt32();
                dataIndex = reader.ReadUInt32();

                uint   unknown9 = reader.ReadUInt32();                            //offset 200
                byte[] dataAllocationTableMap      = reader.ReadBytes(128);       //offset 204
                byte[] indexNodeAllocationTableMap = reader.ReadBytes(128);       //offset 332
                byte   senitinal = reader.ReadByte();                             //offset 460

                encryptionType = EnumUtil.ParseEncryptionType(reader.ReadByte()); //offset 461

                //AllocationTable dataAllocationTable = new AllocationTable(reader, 17408); //offset 0x4400
                //AllocationTable indexNodeAllocationTable = new AllocationTable(reader, 17920); //offset 0x4600
            }
            else
            {
                //64-bit file
                ulong unknown3 = reader.ReadUInt64();        //offset 24
                ulong unknown4 = reader.ReadUInt64();        //offset 32
                uint  unknown5 = reader.ReadUInt32();        //offset 40

                byte[] unknownArray1 = reader.ReadBytes(32); //offset 36
                byte[] unknownArray2 = reader.ReadBytes(32);
                byte[] unknownArray3 = reader.ReadBytes(32);
                byte[] unknownArray4 = reader.ReadBytes(32);

                uint unknown61 = reader.ReadUInt32();                             //offset 172
                uint unknown62 = reader.ReadUInt32();                             //offset 176
                uint unknown63 = reader.ReadUInt32();                             //offset 180

                size = reader.ReadInt64();                                        //offset 184

                ulong lastDataAllocationTableOffset = reader.ReadUInt64();        //offset 192
                ulong unknown7 = reader.ReadUInt64();                             //offset 200
                ulong unknown8 = reader.ReadUInt64();                             //offset 208

                descriptorIndexBackPointer = reader.ReadUInt64();                 //offset 216
                descriptorIndex            = reader.ReadUInt64();                 //offset 224
                dataIndexBackPointer       = reader.ReadUInt64();                 //offset 232
                dataIndex = reader.ReadUInt64();                                  //offset 240

                uint unknown9  = reader.ReadUInt32();                             //offset 248
                uint unknown10 = reader.ReadUInt32();                             //offset 252

                byte[] dataAllocationTableMap      = reader.ReadBytes(128);       //offset 256
                byte[] indexNodeAllocationTableMap = reader.ReadBytes(128);       //offset 384

                byte senitinal = reader.ReadByte();                               //offset 512

                encryptionType = EnumUtil.ParseEncryptionType(reader.ReadByte()); //offset 513
            }

            descriptorIndexTree = new IndexTree(reader, descriptorIndex);
            descriptorIndexTree.SetParent(); //set parent folder

            dataIndexTree = new IndexTree(reader, dataIndex);

            ulong nameToIdMapId  = 97;
            ulong messageStoreId = 33;
            ulong rootId         = 290;
            ulong mailboxRootId  = 32802; //32802 or 32834

            Table nameToIdMapTable  = null;
            Table messageStoreTable = null;
            Table rootTable         = null;
            Table mailboxRootTable  = null;

            ItemDescriptor nameToIdMapItemDescriptor  = descriptorIndexTree.Nodes.ContainsKey(nameToIdMapId) ? (ItemDescriptor)descriptorIndexTree.Nodes[nameToIdMapId] : null;
            ItemDescriptor messageStoreItemDescriptor = descriptorIndexTree.Nodes.ContainsKey(messageStoreId) ? (ItemDescriptor)descriptorIndexTree.Nodes[messageStoreId] : null;
            ItemDescriptor rootItemDescriptor         = descriptorIndexTree.Nodes.ContainsKey(rootId) ? (ItemDescriptor)descriptorIndexTree.Nodes[rootId] : null;
            ItemDescriptor mailboxRootItemDescriptor  = descriptorIndexTree.Nodes.ContainsKey(mailboxRootId) ? (ItemDescriptor)descriptorIndexTree.Nodes[mailboxRootId] : null;

            if (mailboxRootItemDescriptor == null)
            {
                mailboxRootItemDescriptor = descriptorIndexTree.Nodes.ContainsKey((ulong)32834) ? (ItemDescriptor)descriptorIndexTree.Nodes[(ulong)32834] : null;
            }

            if (nameToIdMapItemDescriptor == null)
            {
                throw new DataStructureException("Unresolvable Data Structure issue with: nameToIdMapItemDescriptor");
            }

            DataStructure nameToIdMapLocalDescriptorListNode = Util.GetLocalDescriptionListNode(reader.PstFile.DataIndexTree, nameToIdMapItemDescriptor.LocalDescriptorListId);
            DataStructure nameToIdMapDataNode = reader.PstFile.DataIndexTree.GetDataStructure(nameToIdMapItemDescriptor.TableId);

            if (nameToIdMapDataNode != null)
            {
                LocalDescriptorList nameToIdMapLocalDescriptorList = Util.GetLocalDescriptorList(reader, nameToIdMapLocalDescriptorListNode);
                nameToIdMapTable = Util.GetTable(reader, nameToIdMapDataNode, nameToIdMapLocalDescriptorList);
            }

            if (messageStoreItemDescriptor == null)
            {
                throw new DataStructureException("Unresolvable Data Structure issue with: messageStoreItemDescriptor");
            }

            DataStructure messageStoreLocalDescriptorListNode = Util.GetLocalDescriptionListNode(reader.PstFile.DataIndexTree, messageStoreItemDescriptor.LocalDescriptorListId);
            DataStructure messageStoreDataNode = reader.PstFile.DataIndexTree.GetDataStructure(messageStoreItemDescriptor.TableId);

            if (messageStoreDataNode != null)
            {
                LocalDescriptorList messageStoreLocalDescriptorList = Util.GetLocalDescriptorList(reader, messageStoreLocalDescriptorListNode);
                messageStoreTable = Util.GetTable(reader, messageStoreDataNode, messageStoreLocalDescriptorList);
            }

            if (rootItemDescriptor == null)
            {
                throw new DataStructureException("Unresolvable Data Structure issue with: rootItemDescriptor");
            }

            DataStructure rootLocalDescriptorListNode = Util.GetLocalDescriptionListNode(reader.PstFile.DataIndexTree, rootItemDescriptor.LocalDescriptorListId);
            DataStructure rootDataNode = reader.PstFile.DataIndexTree.GetDataStructure(rootItemDescriptor.TableId);

            if (rootDataNode != null)
            {
                LocalDescriptorList rootLocalDescriptorList = Util.GetLocalDescriptorList(reader, rootLocalDescriptorListNode);
                rootTable = Util.GetTable(reader, rootDataNode, rootLocalDescriptorList);
            }

            if (mailboxRootItemDescriptor != null)
            {
                DataStructure mailboxRootLocalDescriptorListNode = Util.GetLocalDescriptionListNode(reader.PstFile.DataIndexTree, mailboxRootItemDescriptor.LocalDescriptorListId);
                DataStructure mailboxRootDataNode = reader.PstFile.DataIndexTree.GetDataStructure(mailboxRootItemDescriptor.TableId);

                if (mailboxRootDataNode != null)
                {
                    LocalDescriptorList mailboxRootLocalDescriptorList = Util.GetLocalDescriptorList(reader, mailboxRootLocalDescriptorListNode);
                    mailboxRootTable = Util.GetTable(reader, mailboxRootDataNode, mailboxRootLocalDescriptorList);
                }
            }

            if (nameToIdMapTable != null)
            {
                nameToIdMap = new NameToIdMap(nameToIdMapTable);

                FillNamedIdToTag();
            }

            if (messageStoreTable != null)
            {
                messageStore = new MessageStore(messageStoreTable);
            }

            if (rootTable != null)
            {
                root = new Folder(reader, rootItemDescriptor, rootTable);
            }

            if (mailboxRootItemDescriptor != null && mailboxRootTable != null)
            {
                mailboxRoot = new Folder(reader, mailboxRootItemDescriptor, mailboxRootTable);
            }
        }
Example #3
0
 internal Folder(PstFileReader reader, ItemDescriptor descriptor, Table table)
 {
     Parse(reader, descriptor, table);
 }
Example #4
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);
                }
            }
        }