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(); } } }
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); } } }
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); } }
/// <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(); }