public void SetExternalProperty(PropertyID propertyID, PropertyTypeName propertyType, byte[] propertyBytes)
        {
            PropertyContextRecord record = GetRecordByPropertyID(propertyID);

            if (record != null)
            {
                if (record.wPropType != propertyType)
                {
                    throw new InvalidPropertyException("Property type mismatch");
                }

                if (record.IsExternal)
                {
                    HeapOrNodeID newHeapOrNodeID = NodeStorageHelper.StoreExternalProperty(this.File, this.Heap, ref m_subnodeBTree, record.HeapOrNodeID, propertyBytes);
                    if (record.HeapOrNodeID.Value != newHeapOrNodeID.Value)
                    {
                        record.HeapOrNodeID = newHeapOrNodeID;
                        UpdateRecord(record);
                    }
                }
                else
                {
                    // old record is not external but new record is, this should never happen.
                    throw new InvalidPropertyException("Old record should be external but is not");
                }
            }
            else // old record does not exist
            {
                record = new PropertyContextRecord();
                record.HeapOrNodeID = NodeStorageHelper.StoreExternalProperty(this.File, this.Heap, ref m_subnodeBTree, propertyBytes);
                record.wPropId      = propertyID;
                record.wPropType    = propertyType;
                AddRecord(record);
            }
        }
        public bool IsCellInUse(int rowIndex, PropertyID propertyID, PropertyTypeName propertyType)
        {
            int columnIndex = GetColumnIndexByPropertyTag(propertyID, propertyType);
            TableColumnDescriptor columnDescriptor = m_tcInfo.rgTCOLDESC[columnIndex];

            byte[] rowBytes = GetRowBytes(rowIndex);
            return(IsCellInUse(columnDescriptor, rowBytes));
        }
 /// <returns>True if property column was added</returns>
 public bool AddPropertyColumnIfNotExist(PropertyID propertyID, PropertyTypeName propertyTypeName)
 {
     if (!ContainsPropertyColumn(propertyID, propertyTypeName))
     {
         AddPropertyColumn(propertyID, propertyTypeName);
         return(true);
     }
     return(false);
 }
Example #4
0
        public void RemoveProperty(int rowIndex, PropertyName propertyName, PropertyTypeName propertyType)
        {
            Nullable <PropertyID> propertyID = m_map.GetIDFromName(propertyName);

            if (propertyID.HasValue)
            {
                RemoveProperty(rowIndex, propertyID.Value, propertyType);
            }
        }
Example #5
0
        public int FindColumnIndexByPropertyTag(PropertyName propertyName, PropertyTypeName propertyType)
        {
            Nullable <PropertyID> propertyID = m_map.GetIDFromName(propertyName);

            if (propertyID.HasValue)
            {
                return(FindColumnIndexByPropertyTag(propertyID.Value, propertyType));
            }
            return(-1);
        }
Example #6
0
 public PropertyContextRecord(byte[] buffer, int offset)
 {
     wPropId     = (PropertyID)LittleEndianConverter.ToUInt16(buffer, offset + 0);
     wPropType   = (PropertyTypeName)LittleEndianConverter.ToUInt16(buffer, offset + 2);
     dwValueHnid = LittleEndianConverter.ToUInt32(buffer, offset + 4);
     if (!IsPropertyStoredInternally(wPropType))
     {
         HeapOrNodeID = new HeapOrNodeID(buffer, offset + 4);
     }
 }
        public int GetColumnIndexByPropertyTag(PropertyID propertyID, PropertyTypeName propertyType)
        {
            int columnIndex = FindColumnIndexByPropertyTag(propertyID, propertyType);

            if (columnIndex == -1)
            {
                throw new Exception(String.Format("Column {0} does not belong to table", GetPropertyIDString((ushort)propertyID)));
            }
            return(columnIndex);
        }
Example #8
0
        public bool ContainsPropertyColumn(PropertyName propertyName, PropertyTypeName propertyType)
        {
            Nullable <PropertyID> propertyID = m_map.GetIDFromName(propertyName);

            if (propertyID.HasValue)
            {
                return(ContainsPropertyColumn(propertyID.Value, propertyType));
            }
            return(false);
        }
        public void RemoveProperty(int rowIndex, PropertyID propertyID, PropertyTypeName propertyType)
        {
            int columnIndex = GetColumnIndexByPropertyTag(propertyID, propertyType);
            TableColumnDescriptor columnDescriptor = m_tcInfo.rgTCOLDESC[columnIndex];

            if (columnDescriptor.IsStoredExternally)
            {
                RemoveExternalProperty(rowIndex, columnIndex);
            }
            byte[] rowBytes = GetRowBytes(rowIndex);
            UpdateCellExistenceBlock(columnDescriptor, rowBytes, false);
            SetRowBytes(rowIndex, rowBytes);
        }
 public int FindColumnIndexByPropertyTag(PropertyID propertyID, PropertyTypeName propertyType)
 {
     for (int index = 0; index < m_tcInfo.rgTCOLDESC.Count; index++)
     {
         TableColumnDescriptor descriptor = m_tcInfo.rgTCOLDESC[index];
         if (descriptor.PropertyID == propertyID &&
             descriptor.PropertyType == propertyType)
         {
             return(index);
         }
     }
     return(-1);
 }
Example #11
0
 public static bool IsPropertyStoredInternally(PropertyTypeName wPropType)
 {
     // if wPropType is fixed and <= 4 bytes, then dwValueHnid is either NID or HID
     if (wPropType == PropertyTypeName.PtypBoolean ||
         wPropType == PropertyTypeName.PtypInteger16 ||
         wPropType == PropertyTypeName.PtypInteger32 ||
         wPropType == PropertyTypeName.PtypFloating32 ||
         wPropType == PropertyTypeName.PtypErrorCode)
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
Example #12
0
 public static bool IsPropertyStoredExternally(PropertyTypeName wPropType)
 {
     // if wPropType is fixed and <= 8 bytes then it's internal, otherwise dwValueHnid is either NID or HID
     if (wPropType == PropertyTypeName.PtypString ||
         wPropType == PropertyTypeName.PtypString8 ||
         wPropType == PropertyTypeName.PtypBinary ||
         wPropType == PropertyTypeName.PtypObject ||
         wPropType == PropertyTypeName.PtypGuid ||
         wPropType == PropertyTypeName.PtypMultiString)
     {
         return(true);
     }
     else
     {
         return(false);
     }
 }
        public static int GetPropertyDataLength(PropertyTypeName propertyType)
        {
            switch (propertyType)
            {
            case PropertyTypeName.PtypBoolean:
                return(1);

            case PropertyTypeName.PtypInteger16:
                return(2);

            case PropertyTypeName.PtypTime:
                return(8);

            default:
                return(4);
            }
        }
        public void SetInternalProperty(PropertyID propertyID, PropertyTypeName propertyType, uint propertyValue)
        {
            PropertyContextRecord oldRecord = GetRecordByPropertyID(propertyID);

            if (oldRecord == null)
            {
                PropertyContextRecord record = new PropertyContextRecord();
                record.wPropId     = propertyID;
                record.wPropType   = propertyType;
                record.dwValueHnid = propertyValue;
                this.AddRecord(record);
            }
            else
            {
                oldRecord.dwValueHnid = propertyValue;
                this.UpdateRecord(oldRecord);
            }
        }
        public bool ContainsPropertyColumn(PropertyID propertyID, PropertyTypeName propertyTypeName)
        {
            int index = FindColumnIndexByPropertyTag(propertyID, propertyTypeName);

            return(index >= 0);
        }
Example #16
0
        public static void RopOpenStreamWithDifferentPropertyType(
            ObjectToOperate objectToOperate,
            PropertyTypeName propertyType,
            out CPRPTErrorCode error)
        {
            Condition.IsTrue(isInitialized);
            Condition.IsTrue(globalObj != ServerObjectType.Logon);
            Condition.IfThen(globalObj == ServerObjectType.Message || globalObj == ServerObjectType.Attachment, propertyType == PropertyTypeName.PtypBinary || propertyType == PropertyTypeName.PtypString || propertyType == PropertyTypeName.PtypObject);

            if (objectToOperate == ObjectToOperate.FirstObject)
            {
                Condition.IfThen(globalObj == ServerObjectType.Folder, propertyType == PropertyTypeName.PtypBinary);
            }
            else if (objectToOperate == ObjectToOperate.FifthObject)
            {
                Condition.IfThen(globalObj == ServerObjectType.Folder, propertyType == PropertyTypeName.PtypBinary || propertyType == PropertyTypeName.PtypString);
            }

            // openFlag and error is designed for negative test case.
            error = CPRPTErrorCode.None;            
            if (globalObj == ServerObjectType.Attachment && propertyType == PropertyTypeName.PtypBinary)
            {
                ModelHelper.CaptureRequirement(
                    25502,
                    @"[In RopOpenStream ROP] Single-valued PtypBinary type properties ([MS-OXCDATA] section 2.11.1) is supported for Attachment objects.");
            }

            if (globalObj == ServerObjectType.Attachment && propertyType == PropertyTypeName.PtypObject)
            {
                ModelHelper.CaptureRequirement(
                    25503,
                    @"[In RopOpenStream ROP] Single-valued PtypObject type properties ([MS-OXCDATA] section 2.11.1) is supported for Attachment objects.");
            }

            if (globalObj == ServerObjectType.Message && propertyType == PropertyTypeName.PtypBinary)
            {
                ModelHelper.CaptureRequirement(
                   25506,
                   @"[In RopOpenStream ROP] Single-valued PtypBinary type properties ([MS-OXCDATA] section 2.11.1) is supported for Message objects.");
            }

            if (globalObj == ServerObjectType.Message && propertyType == PropertyTypeName.PtypObject)
            {
                ModelHelper.CaptureRequirement(
                   25507,
                   @"[In RopOpenStream ROP] Single-valued PtypObject type properties ([MS-OXCDATA] section 2.11.1) is supported for Message objects.");
            }

            if (globalObj == ServerObjectType.Message && propertyType == PropertyTypeName.PtypString)
            {
                ModelHelper.CaptureRequirement(
                   25509,
                   @"[In RopOpenStream ROP] Single-valued PtypString type properties ([MS-OXCDATA] section 2.11.1) is supported for Message objects.");
            }

            if (globalObj == ServerObjectType.Attachment && propertyType == PropertyTypeName.PtypString)
            {
                if (requirementContainer[25505])
                {
                    ModelHelper.CaptureRequirement(
                        25505,
                        @"[In RopOpenStream ROP] Single-valued PtypString type properties ([MS-OXCDATA] section 2.11.1) is supported for Attachment objects.");
                }
                else
                {
                    error = CPRPTErrorCode.NotSupported;
                }            
            }
        }
        /// <summary>
        /// For discovery purposes
        /// </summary>
        public List <string> ListTable()
        {
            List <string> result = new List <string>();

            result.Add("Number of Columns: " + this.ColumnCount);
            for (int index = 0; index < m_tcInfo.rgTCOLDESC.Count; index++)
            {
                TableColumnDescriptor descriptor = m_tcInfo.rgTCOLDESC[index];
                result.Add(String.Format("Column {0}, Property Type: {1}, PropertyName: {2}, Data Length: {3}, Offset: {4}, iBit: {5}", index, descriptor.PropertyType, GetPropertyIDString((ushort)descriptor.PropertyID), descriptor.cbData, descriptor.ibData, descriptor.iBit));
            }

            result.Add("Number of Rows: " + m_rowIndex.Count);
            result.Add("4-byte entries length: " + (m_tcInfo.rgib[TableContextInfo.TCI_4b]));
            result.Add("2-byte entries length: " + (m_tcInfo.rgib[TableContextInfo.TCI_2b] - m_tcInfo.rgib[TableContextInfo.TCI_4b]));
            result.Add("1-byte entries length: " + (m_tcInfo.rgib[TableContextInfo.TCI_1b] - m_tcInfo.rgib[TableContextInfo.TCI_2b]));
            result.Add("Row length (net): " + m_tcInfo.rgib[TableContextInfo.TCI_1b]);
            result.Add("Row length: " + this.RowLength);
            for (int rowIndex = 0; rowIndex < m_rowIndex.Count; rowIndex++)
            {
                result.Add("--------------------------------------------------------------------------------");
                result.Add("Row ID: " + m_rowIndex[rowIndex].dwRowID);
                result.Add("Data Length: " + m_rowIndex[rowIndex].DataLength);
                result.Add("Row Index: " + m_rowIndex[rowIndex].dwRowIndex);
                for (int columnIndex = 0; columnIndex < m_tcInfo.rgTCOLDESC.Count; columnIndex++)
                {
                    TableColumnDescriptor descriptor   = m_tcInfo.rgTCOLDESC[columnIndex];
                    PropertyTypeName      propertyType = descriptor.PropertyType;
                    PropertyID            propertyID   = descriptor.PropertyID;
                    string value;
                    if (IsCellInUse(rowIndex, propertyID, propertyType))
                    {
                        if (propertyType == PropertyTypeName.PtypBoolean)
                        {
                            bool boolValue = GetBooleanProperty(rowIndex, propertyID).Value;
                            value = boolValue.ToString();
                        }
                        else if (propertyType == PropertyTypeName.PtypInteger16)
                        {
                            value = GetInt16Property(rowIndex, propertyID).ToString() + " (Int16)";
                        }
                        else if (propertyType == PropertyTypeName.PtypInteger32)
                        {
                            value = GetInt32Property(rowIndex, propertyID).ToString();
                        }
                        else if (propertyType == PropertyTypeName.PtypInteger64)
                        {
                            value = GetInt64Property(rowIndex, propertyID).ToString() + " (Int64)";
                        }
                        else if (propertyType == PropertyTypeName.PtypTime)
                        {
                            value = GetDateTimeProperty(rowIndex, propertyID).ToString();
                        }
                        else if (propertyType == PropertyTypeName.PtypString)
                        {
                            value = GetStringProperty(rowIndex, propertyID);
                        }
                        else if (propertyType == PropertyTypeName.PtypBinary)
                        {
                            value = StringHelper.GetByteArrayString(GetBytesProperty(rowIndex, propertyID));
                        }
                        else
                        {
                            value = "-" + propertyType.ToString();
                        }
                    }
                    else
                    {
                        value = "(Unused)";
                    }

                    result.Add(GetPropertyIDString((ushort)propertyID) + ": " + value);
                }
            }

            return(result);
        }
        /// <summary>
        /// This method is used to open a different type of properties as a Stream object, enabling the client to perform various streaming operations on the property. 
        /// </summary>
        /// <param name="obj">Specifies which object will be operated.</param>
        /// <param name="propertyType">Specifies which type of property will be operated.</param>
        /// <param name="error">Returned error code.</param>
        public void RopOpenStreamWithDifferentPropertyType(ObjectToOperate obj, PropertyTypeName propertyType, out CPRPTErrorCode error)
        {
            #region Initialize properties and parameter
            error = CPRPTErrorCode.None;
            TaggedPropertyValue propertyTag = this.GetTaggedPropertyTag(obj);

            uint handle = 0;
            switch (this.cprptCurrentType)
            {
                case ServerObjectType.Folder:
                    int index = obj == ObjectToOperate.FifthObject ? (int)ObjectToOperate.FirstObject : (int)obj;
                    handle = cprptFolderHandle[index];
                    break;
                case ServerObjectType.Message:
                    handle = cprptMessageHandle[(int)obj];
                    break;
                case ServerObjectType.Attachment:
                    handle = cprptAttachmentHandle[(int)obj];
                    break;
                default:
                    break;
            }

            byte openModeFlags = ConstValues.OpenModeFlagsCreate;
            propertyTag.PropertyTag.PropertyType = (ushort)propertyType;

            if (this.cprptCurrentType != ServerObjectType.Folder)
            {
                propertyTag.PropertyTag.PropertyId++;
            }
            else
            {
                if (obj == ObjectToOperate.FifthObject)
                {
                    switch (propertyType)
                    {
                        case PropertyTypeName.PtypBinary:
                            propertyTag.PropertyTag.PropertyId = 0x0e09;
                            propertyTag.PropertyTag.PropertyType = 0x0102;
                            break;
                        case PropertyTypeName.PtypString:
                            propertyTag.PropertyTag.PropertyId = 0x3001;
                            propertyTag.PropertyTag.PropertyType = 0x001f;
                            break;
                        default:
                            break;
                    }

                    openModeFlags = ConstValues.OpenModeFlagsReadOnly;
                }
                else
                {
                    // Set PTagRulesData property for Folder object
                    propertyTag.PropertyTag.PropertyId = ushort.Parse(Common.GetConfigurationPropertyValue("FolderPropertyID2", this.Site));
                }
            }

            error = CPRPTErrorCode.Other;

            #endregion
            RopOpenStreamResponse openStreamResponse;
            uint openHandle = this.RopOpenStream(handle, out openStreamResponse, propertyTag.PropertyTag, openModeFlags, false);

            error = (CPRPTErrorCode)openStreamResponse.ReturnValue;

            #region Write stream to verify having write permission
            if (this.cprptCurrentType == ServerObjectType.Message)
            {
                RopWriteStreamResponse writeStreamResponse = this.RopWriteStream(openHandle, WriteData, false);
                this.RopCommitStream(openHandle, false);

                this.VerifyRopWriteStreamWithCreatePermission(writeStreamResponse);
            }
            #endregion
        }
        /// <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();
        }
Example #20
0
        /// <returns>True if property column was added</returns>
        public bool AddPropertyColumnIfNotExist(PropertyName propertyName, PropertyTypeName propertyType)
        {
            PropertyID propertyID = m_map.ObtainIDFromName(propertyName);

            return(AddPropertyColumnIfNotExist(propertyID, propertyType));
        }
Example #21
0
        protected override void Execute(NativeActivityContext context)
        {
            var prModel = new PropertyModel(PropertyName.Get(context), PropertyTypeName.Get(context), Description.Get(context), RequiresInitialization.Get(context), MarkRequiredInBuilder.Get(context));

            ((ClassModel)context.Properties.Find("ClassModel")).AddProperty(prModel);
        }