private Guid GetPropertySetGuid(int indexHint)
        {
            if (indexHint == 0)
            {
                return(Guid.Empty);
            }
            else if (indexHint == 1)
            {
                return(PropertySetGuid.PS_MAPI);
            }
            else if (indexHint == 2)
            {
                return(PropertySetGuid.PS_PUBLIC_STRINGS);
            }
            else
            {
                int propertySetGuidIndex = indexHint - 3;
                if (PropertySetGuidStreamCache == null)
                {
                    PSTNode node = m_file.GetNode((uint)InternalNodeName.NID_NAME_TO_ID_MAP);
                    PropertySetGuidStreamCache = node.PC.GetBytesProperty(PropertyID.PidTagNameidStreamGuid);
                }

                int  offset = propertySetGuidIndex * 16;
                Guid guid   = LittleEndianConverter.ToGuid(PropertySetGuidStreamCache, offset);
                return(guid);
            }
        }
Beispiel #2
0
        public static PSTFolder GetFolder(PSTNode node)
        {
            if (node.NodeID.nidType == NodeTypeName.NID_TYPE_NORMAL_FOLDER)
            {
                PropertyContext pc = node.PC;
                if (pc != null)
                {
                    string             containerClass = pc.GetStringProperty(PropertyID.PidTagContainerClass);
                    FolderItemTypeName itemType       = GetItemType(containerClass);
                    switch (itemType)
                    {
                    case FolderItemTypeName.Appointment:
                        return(new CalendarFolder(node));

                    case FolderItemTypeName.Note:
                        return(new MailFolder(node));

                    default:
                        return(new PSTFolder(node));
                    }
                }
                else
                {
                    throw new Exception("PC is null");
                }
            }
            else
            {
                throw new Exception("Node ID does not belong to a folder");
            }
        }
        /// <returns>short PropertyID used to store the property</returns>
        public PropertyID AddToMap(PropertyLongID propertyLongID, Guid propertySetGuid)
        {
            PSTNode node = m_file.GetNode((uint)InternalNodeName.NID_NAME_TO_ID_MAP);

            int wGuid = GetPropertySetGuidIndexHint(propertySetGuid);

            if (wGuid == -1)
            {
                wGuid = 3 + AddPropertySetGuid(node, propertySetGuid);
            }

            byte[] oldBuffer     = node.PC.GetBytesProperty(PropertyID.PidTagNameidStreamEntry);
            int    propertyIndex = oldBuffer.Length / 8;

            NameID nameID = new NameID(propertyLongID, (ushort)wGuid, (ushort)propertyIndex);

            byte[] newBuffer = new byte[oldBuffer.Length + 8];
            Array.Copy(oldBuffer, newBuffer, oldBuffer.Length);
            nameID.WriteBytes(newBuffer, oldBuffer.Length);
            node.PC.SetBytesProperty(PropertyID.PidTagNameidStreamEntry, newBuffer);

            AddPropertyToHashBucket(node, nameID);
            node.SaveChanges();

            PropertyID propertyID = (PropertyID)(nameID.PropertyShortID);

            m_map.Add(new PropertyName(propertyLongID, propertySetGuid), (ushort)propertyID);
            return(propertyID);
        }
        public static MessageObject CreateNewMessage(PSTFile file, FolderItemTypeName folderItemType, NodeID parentNodeID, Guid searchKey)
        {
            // [MS-PST] The following properties must be present in any valid Message object PC:
            PropertyContext pc = PropertyContext.CreateNewPropertyContext(file);

            pc.SetStringProperty(PropertyID.PidTagMessageClass, GetMessageClass(folderItemType));

            pc.SetInt32Property(PropertyID.PidTagMessageFlags, 0);
            pc.SetInt32Property(PropertyID.PidTagMessageStatus, 0);
            pc.SetDateTimeProperty(PropertyID.PidTagCreationTime, DateTime.UtcNow);
            pc.SetDateTimeProperty(PropertyID.PidTagLastModificationTime, DateTime.UtcNow);
            pc.SetDateTimeProperty(PropertyID.PidTagClientSubmitTime, DateTime.UtcNow);
            pc.SetDateTimeProperty(PropertyID.PidTagMessageDeliveryTime, DateTime.UtcNow);
            byte[] conversationIndex = ConversationIndexHeader.GenerateNewConversationIndex().GetBytes();
            pc.SetBytesProperty(PropertyID.PidTagConversationIndex, conversationIndex);

            // PidTagSearchKey is apparently a GUID
            pc.SetBytesProperty(PropertyID.PidTagSearchKey, LittleEndianConverter.GetBytes(searchKey));

            pc.SaveChanges();

            NodeID pcNodeID = file.Header.AllocateNextNodeID(NodeTypeName.NID_TYPE_NORMAL_MESSAGE);

            file.NodeBTree.InsertNodeEntry(pcNodeID, pc.DataTree, pc.SubnodeBTree, parentNodeID);

            // NOTE: According to [MS-PST], A Recipient Table MUST exist for any Message object,
            //       However, in practice even outlook itself does not always create it.
            PSTNode       pcNode  = new PSTNode(file, pcNodeID, pc.DataTree, pc.SubnodeBTree);
            MessageObject message = new MessageObject(pcNode);

            return(message);
        }
        public bool ContainsNode(NodeID nodeID)
        {
            if (m_data == null)
            {
                PSTNode node = m_file.GetNode((uint)InternalNodeName.NID_SEARCH_DOMAIN_OBJECT);
                if (node.DataTree == null)
                {
                    m_data = new byte[0];
                }
                else
                {
                    m_data = node.DataTree.GetData();
                }
            }

            int nodeCount = m_data.Length / 4;

            for (int index = 0; index < nodeCount; index++)
            {
                uint currentNodeID = LittleEndianConverter.ToUInt32(m_data, index * 4);
                if (currentNodeID == nodeID.Value)
                {
                    return(true);
                }
            }
            return(false);
        }
Beispiel #6
0
 public NamedTableContext GetContentsTable()
 {
     if (m_contentsTable == null)
     {
         PSTNode node = GetContentsTableNode();
         m_contentsTable = node.NamedTableContext;
     }
     return(m_contentsTable);
 }
 public RecurringAppointment(PSTNode node) : base(node)
 {
     this.Recurring = true;
     byte[] bytes = PC.GetBytesProperty(PropertyNames.PidLidAppointmentRecur);
     if (bytes != null)
     {
         ReadRecurrencePattern(bytes);
     }
 }
        public void CreateAttachmentTableIfNotExist()
        {
            CreateSubnodeBTreeIfNotExist();
            Subnode subnode = SubnodeBTree.GetSubnode((uint)InternalNodeName.NID_ATTACHMENT_TABLE);

            if (subnode == null)
            {
                PSTNode template = this.File.GetNode(InternalNodeName.NID_ATTACHMENT_TABLE);
                NodeID  nodeID   = new NodeID((uint)InternalNodeName.NID_ATTACHMENT_TABLE);
                SubnodeBTree.InsertSubnodeEntry(nodeID, template.DataTree, null);
                File.BlockBTree.IncrementBlockEntryReferenceCount(template.DataTree.RootBlock.BlockID);
            }
        }
Beispiel #9
0
        public static Note GetNote(PSTFile file, NodeID nodeID)
        {
            PSTNode node            = file.GetNode(nodeID);
            NamedPropertyContext pc = node.PC;

            if (pc != null)
            {
                return(new Note(node));
            }
            else
            {
                return(null);
            }
        }
Beispiel #10
0
        // http://social.msdn.microsoft.com/Forums/en-US/os_binaryfile/thread/a5f9c653-40f5-4638-85d3-00c54607d984/
        // For the following types, search the SDO for the NIDs of the old and new parent folders.
        // If either of the NIDs is contained in the SDO, enqueue the SUD
        private void QueueSearchUpdateDescriptor(SearchUpdateDescriptor sud)
        {
            if (m_node == null)
            {
                m_node = m_file.GetNode((uint)InternalNodeName.NID_SEARCH_MANAGEMENT_QUEUE);
            }

            if (m_node.DataTree == null)
            {
                m_node.DataTree = new DataTree(m_file);
            }

            m_node.DataTree.AppendData(sud.GetBytes());
        }
        public void CreateRecipientsTableIfNotExist()
        {
            CreateSubnodeBTreeIfNotExist();
            Subnode subnode = SubnodeBTree.GetSubnode((uint)InternalNodeName.NID_RECIPIENT_TABLE);

            if (subnode == null)
            {
                PSTNode template = this.File.GetNode(InternalNodeName.NID_RECIPIENT_TABLE);
                NodeID  nodeID   = new NodeID((uint)InternalNodeName.NID_RECIPIENT_TABLE);
                SubnodeBTree.InsertSubnodeEntry(nodeID, template.DataTree, null);
                File.BlockBTree.IncrementBlockEntryReferenceCount(template.DataTree.RootBlock.BlockID);

                this.RecipientsTable.AddPropertyColumnIfNotExist(PropertyID.PidTagRecipientDisplayName, PropertyTypeName.PtypString);
                this.RecipientsTable.AddPropertyColumnIfNotExist(PropertyID.PidTagRecipientEntryId, PropertyTypeName.PtypBinary);
                this.RecipientsTable.AddPropertyColumnIfNotExist(PropertyID.PidTagRecipientFlags, PropertyTypeName.PtypInteger32);
                this.RecipientsTable.AddPropertyColumnIfNotExist(PropertyID.PidTagRecipientTrackStatus, PropertyTypeName.PtypInteger32);
            }
        }
Beispiel #12
0
 public static PSTFolder GetFolder(PSTFile file, NodeID nodeID)
 {
     if (nodeID.nidType == NodeTypeName.NID_TYPE_NORMAL_FOLDER)
     {
         PSTNode node = file.GetNode(nodeID);
         if (node != null)
         {
             return(GetFolder(node));
         }
         else
         {
             return(null);
         }
     }
     else
     {
         throw new Exception("Node ID does not belong to a folder");
     }
 }
Beispiel #13
0
        /// <summary>
        /// Caller must update its hierarchy table to include the new child
        /// </summary>
        public static PSTFolder CreateNewFolder(PSTFile file, string folderName, FolderItemTypeName folderItemType, NodeID parentNodeID)
        {
            // create the normal folder node
            PropertyContext pc = PropertyContext.CreateNewPropertyContext(file);

            pc.SetStringProperty(PropertyID.PidTagDisplayName, folderName);
            pc.SetInt32Property(PropertyID.PidTagContentCount, 0);
            pc.SetInt32Property(PropertyID.PidTagContentUnreadCount, 0);
            pc.SetBooleanProperty(PropertyID.PidTagSubfolders, false);
            pc.SetStringProperty(PropertyID.PidTagContainerClass, GetContainerClass(folderItemType));
            pc.SaveChanges();

            NodeID pcNodeID = file.Header.AllocateNextFolderNodeID();

            file.NodeBTree.InsertNodeEntry(pcNodeID, pc.DataTree, pc.SubnodeBTree, parentNodeID);
            PSTNode pcNode = new PSTNode(file, pcNodeID, pc.DataTree, pc.SubnodeBTree);

            // There is no need to create a new empty TC, we can simply point to the appropriate template
            // and only update the reference to another data tree during modification
            PSTNode hierarchyTableTemplateNode = file.GetNode(InternalNodeName.NID_HIERARCHY_TABLE_TEMPLATE);
            NodeID  hierarchyTableNodeID       = new NodeID(NodeTypeName.NID_TYPE_HIERARCHY_TABLE, pcNodeID.nidIndex);

            file.NodeBTree.InsertNodeEntry(hierarchyTableNodeID, hierarchyTableTemplateNode.DataTree, null, new NodeID(0));
            file.BlockBTree.IncrementBlockEntryReferenceCount(hierarchyTableTemplateNode.DataTree.RootBlock.BlockID);

            PSTNode contentsTableTemplateNode = file.GetNode(InternalNodeName.NID_CONTENTS_TABLE_TEMPLATE);
            NodeID  contentsTableNodeID       = new NodeID(NodeTypeName.NID_TYPE_CONTENTS_TABLE, pcNodeID.nidIndex);

            file.NodeBTree.InsertNodeEntry(contentsTableNodeID, contentsTableTemplateNode.DataTree, null, new NodeID(0));
            file.BlockBTree.IncrementBlockEntryReferenceCount(contentsTableTemplateNode.DataTree.RootBlock.BlockID);

            PSTNode associatedContentsTableTemplateNode = file.GetNode(InternalNodeName.NID_ASSOC_CONTENTS_TABLE_TEMPLATE);
            NodeID  associatedContentsTableNodeID       = new NodeID(NodeTypeName.NID_TYPE_ASSOC_CONTENTS_TABLE, pcNodeID.nidIndex);

            file.NodeBTree.InsertNodeEntry(associatedContentsTableNodeID, associatedContentsTableTemplateNode.DataTree, null, new NodeID(0));
            file.BlockBTree.IncrementBlockEntryReferenceCount(associatedContentsTableTemplateNode.DataTree.RootBlock.BlockID);

            PSTFolder folder = PSTFolder.GetFolder(pcNode);

            return(folder);
        }
        private int GetPropertySetGuidIndex(Guid propertySetGuid)
        {
            PSTNode node = m_file.GetNode((uint)InternalNodeName.NID_NAME_TO_ID_MAP);

            byte[] buffer = node.PC.GetBytesProperty(PropertyID.PidTagNameidStreamGuid);
            if (buffer.Length % 16 > 0)
            {
                throw new InvalidPropertyException("Invalid NameidStreamGuid");
            }

            for (int index = 0; index < buffer.Length; index += 16)
            {
                Guid guid = LittleEndianConverter.ToGuid(buffer, index);
                if (guid == propertySetGuid)
                {
                    return(index / 16);
                }
            }

            return(-1);
        }
        public static Appointment GetAppointment(PSTFile file, NodeID nodeID)
        {
            PSTNode node            = file.GetNode(nodeID);
            NamedPropertyContext pc = node.PC;

            if (pc != null)
            {
                bool recurring = pc.GetBooleanProperty(PropertyNames.PidLidRecurring, false);
                if (recurring)
                {
                    return(new RecurringAppointment(node));
                }
                else
                {
                    return(new SingleAppointment(node));
                }
            }
            else
            {
                return(null);
            }
        }
        public void FillMap()
        {
            m_map = new Dictionary <PropertyName, ushort>();
            PSTNode node = m_file.GetNode((uint)InternalNodeName.NID_NAME_TO_ID_MAP);

            byte[] buffer = node.PC.GetBytesProperty(PropertyID.PidTagNameidStreamEntry);
            if (buffer.Length % 8 > 0)
            {
                throw new InvalidPropertyException("Invalid NameidStreamEntry");
            }

            for (int index = 0; index < buffer.Length; index += 8)
            {
                NameID nameID = new NameID(buffer, index);
                if (!nameID.IsStringIdentifier)
                {
                    ushort         propertyShortID = nameID.PropertyShortID;
                    PropertyLongID propertyLongID  = (PropertyLongID)nameID.dwPropertyID;
                    Guid           propertySetGuid = GetPropertySetGuid(nameID.wGuid);

                    m_map.Add(new PropertyName(propertyLongID, propertySetGuid), propertyShortID);
                }
            }
        }
Beispiel #17
0
 public PSTNode(PSTNode node) : base(node.File, node.DataTree, node.SubnodeBTree)
 {
     m_nodeID = node.NodeID;
 }
        public static TableContext GetAssociatedContentsTableTemplate(PSTFile file)
        {
            PSTNode node = file.GetNode(InternalNodeName.NID_ASSOC_CONTENTS_TABLE_TEMPLATE);

            return(node.TableContext);
        }
Beispiel #19
0
 public SingleAppointment(PSTNode node) : base(node)
 {
     this.Recurring = false;
     //this.IsRecurring = false;
 }
Beispiel #20
0
        public PSTNode GetNode(NodeID nodeID)
        {
            PSTNode node = PSTNode.GetPSTNode(this, nodeID);

            return(node);
        }
        public static TableContext GetHierarchyTableTemplate(PSTFile file)
        {
            PSTNode node = file.GetNode(InternalNodeName.NID_HIERARCHY_TABLE_TEMPLATE);

            return(node.TableContext);
        }
Beispiel #22
0
 public MailFolder(PSTNode node) : base(node)
 {
 }
Beispiel #23
0
 protected Note(PSTNode node) : base(node)
 {
 }
 protected Appointment(PSTNode node) : base(node)
 {
 }
Beispiel #25
0
        public TableContext GetAssociatedContentsTable()
        {
            PSTNode node = GetAssociatedContentsTableNode();

            return(node.TableContext);
        }
Beispiel #26
0
        private NamedTableContext m_contentsTable; // We use it for buffering purposes

        public PSTFolder(PSTNode node) : base(node)
        {
        }
        public static MessageObject GetMessage(PSTFile file, NodeID nodeID)
        {
            PSTNode node = file.GetNode(nodeID);

            return(new MessageObject(node));
        }
Beispiel #28
0
        public TableContext GetHierarchyTable()
        {
            PSTNode node = GetHierarchyTableNode();

            return(node.TableContext);
        }
        private RecipientsTable m_recipientsTable; // for buffering purposes

        public MessageObject(PSTNode node) : base(node)
        {
        }
Beispiel #30
0
 public CalendarFolder(PSTNode node) : base(node)
 {
 }