Пример #1
0
        public Subnode GetObjectProperty(PropertyID propertyID)
        {
            PtypObjectRecord objRecord = GetObjectRecordProperty(propertyID);
            Subnode          subnode   = m_subnodeBTree.GetSubnode(objRecord.Nid);

            return(subnode);
        }
 public static byte[] GetExternalPropertyBytes(HeapOnNode heap, SubnodeBTree subnodeBTree, HeapOrNodeID heapOrNodeID)
 {
     if (heapOrNodeID.IsEmpty)
     {
         return(new byte[0]);
     }
     else if (heapOrNodeID.IsHeapID)
     {
         byte[] result = heap.GetHeapItem(heapOrNodeID.HeapID);
         return(result);
     }
     else
     {
         // indicates that the item is stored in the subnode block, and the NID is the local NID under the subnode
         Subnode subnode = subnodeBTree.GetSubnode(heapOrNodeID.NodeID);
         if (subnode != null)
         {
             if (subnode.DataTree == null)
             {
                 return(new byte[0]);
             }
             else
             {
                 return(subnode.DataTree.GetData());
             }
         }
         else
         {
             throw new MissingSubnodeException();
         }
     }
 }
Пример #3
0
        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);
            }
        }
 public static void RemoveExternalProperty(HeapOnNode heap, SubnodeBTree subnodeBTree, HeapOrNodeID heapOrNodeID)
 {
     if (!heapOrNodeID.IsEmpty)
     {
         if (heapOrNodeID.IsHeapID)
         {
             heap.RemoveItemFromHeap(heapOrNodeID.HeapID);
         }
         else
         {
             DataTree dataTree = subnodeBTree.GetSubnode(heapOrNodeID.NodeID).DataTree;
             dataTree.Delete();
             subnodeBTree.DeleteSubnodeEntry(heapOrNodeID.NodeID);
         }
     }
 }
Пример #5
0
        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);
            }
        }
Пример #6
0
        /// <summary>
        /// Add column to an empty table context.
        /// If this is a Contents Table, the caller should call UpdateMessage() afterwards.
        /// Similarly, for attachment table, the caller should call UpdateAttachment().
        /// </summary>
        public void AddPropertyColumn(PropertyID propertyID, PropertyTypeName propertyType)
        {
            TableColumnDescriptor newColumnDescriptor = new TableColumnDescriptor();

            newColumnDescriptor.PropertyID   = propertyID;
            newColumnDescriptor.PropertyType = propertyType;
            newColumnDescriptor.iBit         = (byte)m_tcInfo.ColumnCount;
            newColumnDescriptor.cbData       = (byte)GetPropertyDataLength(propertyType);

            // Set the ibData:
            // http://social.msdn.microsoft.com/Forums/en-US/os_binaryfile/thread/a5f9c653-40f5-4638-85d3-00c54607d984/
            // PidTagLtpRowId and PidTagLtpRowVer must not be relocated
            if (newColumnDescriptor.DataLengthGroup == TableContextInfo.TCI_4b)
            {
                newColumnDescriptor.ibData = m_tcInfo.rgib[TableContextInfo.TCI_4b];
            }
            else if (newColumnDescriptor.DataLengthGroup == TableContextInfo.TCI_2b)
            {
                newColumnDescriptor.ibData = m_tcInfo.rgib[TableContextInfo.TCI_2b];
            }
            else
            {
                newColumnDescriptor.ibData = m_tcInfo.rgib[TableContextInfo.TCI_1b];
            }

            // We call GetRedistributedRows() before adding the new column:
            List <byte[]> rows = GetRedistributedRows(newColumnDescriptor.ibData, newColumnDescriptor.cbData);

            // add the new column
            m_tcInfo.rgTCOLDESC.Add(newColumnDescriptor);

            // redistribute column descriptions
            ushort offset = (ushort)(newColumnDescriptor.ibData + newColumnDescriptor.cbData);

            for (int groupIndex = newColumnDescriptor.DataLengthGroup + 1; groupIndex < 3; groupIndex++)
            {
                for (int index = 0; index < m_tcInfo.rgTCOLDESC.Count; index++)
                {
                    TableColumnDescriptor descriptor = m_tcInfo.rgTCOLDESC[index];

                    if (groupIndex == descriptor.DataLengthGroup)
                    {
                        // changes to descriptor will be saved when calling UpdateTableContextInfo()
                        descriptor.ibData = offset;
                        offset           += descriptor.cbData;
                    }
                }
            }

            // update the group ending offset
            m_tcInfo.UpdateDataLayout();
            m_rowsPerBlock = (int)Math.Floor((double)DataBlock.MaximumDataLength / RowLength);

            // Update the rows data
            if (!m_tcInfo.hnidRows.IsEmpty)
            {
                if (m_tcInfo.hnidRows.IsHeapID)
                {
                    m_heap.RemoveItemFromHeap(m_tcInfo.hnidRows.HeapID);
                    CreateSubnodeForRows();
                }
                else
                {
                    if (m_subnodeRows == null)
                    {
                        m_subnodeRows = m_subnodeBTree.GetSubnode(m_tcInfo.hnidRows.NodeID);
                    }
                    m_subnodeRows.Delete(); // this will set the subnode data-tree to null
                    // New data tree will be created when the first row will be added
                    m_subnodeBTree.UpdateSubnodeEntry(m_tcInfo.hnidRows.NodeID, null, null);
                }

                for (int index = 0; index < rows.Count; index++)
                {
                    AddRowToSubnode(index, rows[index]);
                }
            }

            UpdateTableContextInfo();
        }