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); } }
internal Folder(PstFileReader reader, ItemDescriptor descriptor, Table table) { Parse(reader, descriptor, table); }
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); } } }