This class represents a row of properties
Inheritance: Node
Beispiel #1
0
        /// <summary>
        /// Parse bytes in context into a PropertyRowSetNode
        /// </summary>
        /// <param name="context">The value of Context</param>
        public override void Parse(Context context)
        {
            // No PropertyRowNode to parse
            if (this.count <= 0)
            {
                return;
            }

            // Clear PropretyRows list to store parsing result
            context.PropertyRows.Clear();

            // Parse PropertyRow one by one
            for (int i = 0; i < this.count; i++)
            {
                if (context.IsEnd())
                {
                    throw new ParseException("End prematurely");
                }

                PropertyRow propertyRow = new PropertyRow();
                propertyRow.Parse(context);
                context.PropertyRows.Add(propertyRow);
            }

            // Assign parsing result to PropertyRows
            this.propertyRows = context.PropertyRows;
        }
Beispiel #2
0
        /// <summary>
        /// Deserialize the ROP response buffer.
        /// </summary>
        /// <param name="ropBytes">ROPs bytes in response.</param>
        /// <param name="startIndex">The start index of this ROP.</param>
        /// <returns>The size of response buffer structure.</returns>
        public int Deserialize(byte[] ropBytes, int startIndex)
        {
            int index = startIndex;

            this.RopId            = ropBytes[index++];
            this.InputHandleIndex = ropBytes[index++];
            this.ReturnValue      = BitConverter.ToUInt32(ropBytes, index);
            index += sizeof(uint);

            // Only success response has below fields
            if (this.ReturnValue == 0)
            {
                // Parse RowData
                // Add RowData bytes into Context
                Context.Instance.PropertyBytes = ropBytes;
                Context.Instance.CurIndex      = index;

                // Allocate PropretyRowSetNode to parse RowData
                this.RowData = new PropertyRow();

                // Set row count
                this.RowData.Parse(Context.Instance);

                // Context.Instance.CurIndex indicates the already deserialized bytes' index
                index = Context.Instance.CurIndex;
            }
            else
            {
                this.RowData = null;
            }

            return(index - startIndex);
        }
        /// <summary>
        /// Parse bytes in context into a PropertyRowSetNode
        /// </summary>
        /// <param name="context">The value of Context</param>
        public override void Parse(Context context)
        {
            // No PropertyRowNode to parse
            if (this.count <= 0)
            {
                return;
            }

            // Clear PropretyRows list to store parsing result
            context.PropertyRows.Clear();

            // Parse PropertyRow one by one
            for (int i = 0; i < this.count; i++)
            {
                if (context.IsEnd())
                {
                    throw new ParseException("End prematurely");
                }

                PropertyRow propertyRow = new PropertyRow();
                propertyRow.Parse(context);
                context.PropertyRows.Add(propertyRow);
            }

            // Assign parsing result to PropertyRows
            this.propertyRows = context.PropertyRows;
        }
Beispiel #4
0
        /// <summary>
        /// Initialize the instance.
        /// </summary>
        public void Init()
        {
            this.propertyBytes = null;

            this.curProperty    = null;
            this.curPropertyRow = null;
            this.curIndex       = 0;

            this.properties   = new List <Property>();
            this.propertyRows = new List <PropertyRow>();
        }
        /// <summary>
        /// This method creates Sample RecipientColumns and Sample RecipientRows.
        /// </summary>
        /// <param name="recipientColumns">Sample RecipientColumns</param>
        /// <param name="recipientRows">Sample RecipientRows</param>
        protected void CreateSampleRecipientColumnsAndRecipientRows(out PropertyTag[] recipientColumns, out ModifyRecipientRow[] recipientRows)
        {
            // Step 1: Create Sample RecipientColumns.
            #region recipientColumns

            // The following sample data is from MS-OXCMSG 4.7.1.
            PropertyTag[] sampleRecipientColumns = new PropertyTag[12];
            sampleRecipientColumns[0] = this.propertyDictionary[PropertyNames.PidTagObjectType];
            sampleRecipientColumns[1] = this.propertyDictionary[PropertyNames.PidTagDisplayType];
            sampleRecipientColumns[2] = this.propertyDictionary[PropertyNames.PidTagAddressBookDisplayNamePrintable];
            sampleRecipientColumns[3] = this.propertyDictionary[PropertyNames.PidTagSmtpAddress];
            sampleRecipientColumns[4] = this.propertyDictionary[PropertyNames.PidTagSendInternetEncoding];
            sampleRecipientColumns[5] = this.propertyDictionary[PropertyNames.PidTagDisplayTypeEx];
            sampleRecipientColumns[6] = this.propertyDictionary[PropertyNames.PidTagRecipientDisplayName];
            sampleRecipientColumns[7] = this.propertyDictionary[PropertyNames.PidTagRecipientFlags];
            sampleRecipientColumns[8] = this.propertyDictionary[PropertyNames.PidTagRecipientTrackStatus];
            sampleRecipientColumns[9] = this.propertyDictionary[PropertyNames.PidTagRecipientResourceState];
            sampleRecipientColumns[10] = this.propertyDictionary[PropertyNames.PidTagRecipientOrder];
            sampleRecipientColumns[11] = this.propertyDictionary[PropertyNames.PidTagRecipientEntryId];
            recipientColumns = sampleRecipientColumns;

            #endregion

            // Step 2: Configure a StandardPropertyRow: propertyRow.
            #region Configure a StandardPropertyRow: propertyRow, data is from Page 62 of MS-OXCMSG

            PropertyValue[] propertyValueArray = new PropertyValue[12];
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValueArray[i] = new PropertyValue();
            }

            // PidTagObjectType
            propertyValueArray[0].Value = BitConverter.GetBytes(0x00000006);

            // PidTagDisplayType
            propertyValueArray[1].Value = BitConverter.GetBytes(0x00000000);

            // PidTa7BitDisplayName
            propertyValueArray[2].Value = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("EmailAlias", this.Site) + "\0");

            // PidTagSmtpAddress
            propertyValueArray[3].Value = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("EmailAlias", this.Site) + "@" + Common.GetConfigurationPropertyValue("Domain", this.Site) + "\0");

            // PidTagSendInternetEncoding
            propertyValueArray[4].Value = BitConverter.GetBytes(0x00000000);

            // PidTagDisplayTypeEx
            propertyValueArray[5].Value = BitConverter.GetBytes(0x40000000);

            // PidTagRecipientDisplayName
            propertyValueArray[6].Value = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("EmailAlias", this.Site) + "\0");

            // PidTagRecipientFlags
            propertyValueArray[7].Value = BitConverter.GetBytes(0x00000001);

            // PidTagRecipientTrackStatus
            propertyValueArray[8].Value = BitConverter.GetBytes(0x00000000);

            // PidTagRecipientResourceState
            propertyValueArray[9].Value = BitConverter.GetBytes(0x00000000);

            // PidTagRecipientOrder
            propertyValueArray[10].Value = BitConverter.GetBytes(0x00000000);

            // The following sample data (0x007c and the subsequent 124(0x7c) binary)
            // is copied from Page 62 of MS-OXCMSG
            byte[] sampleData = 
            { 
                0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xa7, 0x40, 0xc8,
                0xc0, 0x42, 0x10, 0x1a, 0xb4, 0xb9, 0x08, 0x00, 0x2b, 0x2f,
                0xe1, 0x82, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x2f, 0x6f, 0x3d, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x4f,
                0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f,
                0x6e, 0x2f, 0x6f, 0x75, 0x3d, 0x45, 0x78, 0x63, 0x68, 0x61,
                0x6e, 0x67, 0x65, 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69,
                0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x47,
                0x72, 0x6f, 0x75, 0x70, 0x20, 0x28, 0x46, 0x59, 0x44, 0x49,
                0x42, 0x4f, 0x48, 0x46, 0x32, 0x33, 0x53, 0x50, 0x44, 0x4c,
                0x54, 0x29, 0x2f, 0x63, 0x6e, 0x3d, 0x52, 0x65, 0x63, 0x69,
                0x70, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6e, 0x3d,
                0x75, 0x73, 0x65, 0x72, 0x32, 0x00 
            };

            // PidTagRecipientEntryId
            propertyValueArray[11].Value = sampleData;

            List<PropertyValue> propertyValues = new List<PropertyValue>();
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValues.Add(propertyValueArray[i]);
            }

            PropertyRow propertyRow = new PropertyRow
            {
                Flag = (byte)PropertyRowFlag.FlaggedPropertyRow,
                PropertyValues = propertyValues
            };

            // For propertyRow.Flag
            int tempLengthForTest = 1;
            foreach (PropertyValue pv in propertyRow.PropertyValues)
            {
                tempLengthForTest = tempLengthForTest + pv.Value.Length;
            }

            #endregion

            // Step 3: Create Sample RecipientRows.
            #region recipientRows

            RecipientRow recipientRow = new RecipientRow
            {
                // 0101 1001 0000 0110 S,D, Type=SMTP,I,U,E
                RecipientFlags = (ushort)(
                    RecipientFlags.SMTP
                    | RecipientFlags.S
                    | RecipientFlags.D
                    | RecipientFlags.I
                    | RecipientFlags.U
                    | RecipientFlags.E),

                // Set DisplayName, which specifies the Email Address of the recipient, as specified in [MS-OXCDATA].
                // This field is present because D is Set.
                DisplayName = Encoding.Unicode.GetBytes(TestSuiteBase.DisplayNameAndCommentForNonSearchFolder + "\0"),

                // Set EmailAddress, which specifies the Email Address of the recipient,
                // as specified in [MS-OXCDATA].
                EmailAddress =
                    Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("EmailAlias", this.Site) + "@" +
                                              Common.GetConfigurationPropertyValue("Domain", this.Site) + "\0"),

                // Set SimpleDisplayName, which specifies the Email Address of the recipient,
                // as specified in [MS-OXCDATA].
                SimpleDisplayName =
                    Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("EmailAlias", this.Site) + "\0"),

                // Set RecipientColumnCount, which specifies the number of columns from the RecipientColumns field
                // that are included in RecipientProperties, as specified in [MS-OXCDATA].
                RecipientColumnCount = RecipientColumnCount,
                RecipientProperties = propertyRow
            };
            ModifyRecipientRow modifyRecipientRow = new ModifyRecipientRow
            {
                RowId = RowId, // Set RowId, which value specifies the ID of the recipient.
                RecipientType = (byte)RecipientType.PrimaryRecipient,
                RecipientRowSize = (ushort)recipientRow.Size(), // Set RecipientRowSize, which specifies the size of the RecipientRow field.
                RecptRow = recipientRow.Serialize()
            };
            ModifyRecipientRow[] sampleModifyRecipientRows = new ModifyRecipientRow[1];
            sampleModifyRecipientRows[0] = modifyRecipientRow;
            recipientRows = sampleModifyRecipientRows;

            #endregion
        }
        /// <summary>
        /// Get the bytes value of one property from a list of properties.
        /// </summary>
        /// <param name="propertyName">The property need to get value.</param>
        /// <param name="propertyRow">The property row.</param>
        /// <param name="propertyTags">The properties tags.</param>
        /// <returns>The bytes value of the property.</returns>
        private byte[] GetPropertyFromList(PropertyId propertyName, PropertyRow propertyRow, PropertyTag[] propertyTags)
        {
            byte[] value = new byte[0];
            TaggedPropertyValue[] allProperties = null;
            if (propertyRow != null && propertyRow.PropertyValues != null && propertyRow.PropertyValues.Count > 0)
            {
                allProperties = new TaggedPropertyValue[propertyTags.Length];
                for (int i = 0; i < propertyTags.Length; i++)
                {
                    allProperties[i] = new TaggedPropertyValue
                    {
                        PropertyTag = propertyTags[i],
                        Value = propertyRow.PropertyValues[i].Value
                    };
                }
            }

            foreach (TaggedPropertyValue taggedValue in allProperties)
            {
                if (taggedValue.PropertyTag.PropertyId == (ushort)propertyName)
                {
                    value = taggedValue.Value;
                    break;
                }
            }

            return value;
        }
        /// <summary>
        /// Generate recipientColumns value and recipientRows value.
        /// </summary>
        /// <param name="recipientColumns">recipientColumns value.</param>
        /// <param name="recipientRows">recipientRows value.</param>
        private void CreateSampleRecipientColumnsAndRecipientRows(out PropertyTag[] recipientColumns, out ModifyRecipientRow[] recipientRows)
        {
            PropertyTag[] sampleRecipientColumns = new PropertyTag[12];
            PropertyTag tag;

            // PidTagObjectType
            tag.PropertyId = 0x0ffe;

            // PtypInteger32
            tag.PropertyType = 0x0003;
            sampleRecipientColumns[0] = tag;

            // PidTagDisplayType
            tag.PropertyId = 0x3900;

            // PtypInteger32
            tag.PropertyType = 0x0003;
            sampleRecipientColumns[1] = tag;

            // PidTagAddressBookDisplayNamePrintable
            tag.PropertyId = 0x39ff;

            // PtypString
            tag.PropertyType = 0x001f;
            sampleRecipientColumns[2] = tag;

            // PidTagSmtpAddress
            tag.PropertyId = 0x39fe;

            // PtypString
            tag.PropertyType = 0x001f;
            sampleRecipientColumns[3] = tag;

            // PidTagSendInternetEncoding
            tag.PropertyId = 0x3a71;

            // PtypInteger32
            tag.PropertyType = 0x0003;
            sampleRecipientColumns[4] = tag;

            // PidTagDisplayTypeEx
            tag.PropertyId = 0x3905;

            // PtypInteger32
            tag.PropertyType = 0x0003;
            sampleRecipientColumns[5] = tag;

            // PidTagRecipientDisplayName
            tag.PropertyId = 0x5ff6;
            tag.PropertyType = 0x001f; // PtypString
            sampleRecipientColumns[6] = tag;

            // PidTagRecipientFlags
            tag.PropertyId = 0x5ffd;

            // PtypInteger32
            tag.PropertyType = 0x0003;
            sampleRecipientColumns[7] = tag;

            // PidTagRecipientTrackStatus
            tag.PropertyId = 0x5fff;

            // PtypInteger32
            tag.PropertyType = 0x0003;
            sampleRecipientColumns[8] = tag;

            // PidTagRecipientResourceState
            tag.PropertyId = 0x5fde;

            // PtypInteger32
            tag.PropertyType = 0x0003;
            sampleRecipientColumns[9] = tag;

            // PidTagRecipientOrder
            tag.PropertyId = 0x5fdf;

            // PtypInteger32
            tag.PropertyType = 0x0003;
            sampleRecipientColumns[10] = tag;

            // PidTagRecipientEntryId
            tag.PropertyId = 0x5ff7;

            // PtypBinary
            tag.PropertyType = 0x0102;
            sampleRecipientColumns[11] = tag;

            recipientColumns = sampleRecipientColumns;

            PropertyValue[] propertyValueArray = new PropertyValue[12];
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValueArray[i] = new PropertyValue();
            }

            propertyValueArray[0].Value = BitConverter.GetBytes(0x00000006); // PidTagObjectType
            propertyValueArray[1].Value = BitConverter.GetBytes(0x00000000); // PidTagDisplayType
            propertyValueArray[2].Value = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("AdminUserName", this.Site) + "\0"); // PidTa7BitDisplayName
            propertyValueArray[3].Value = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("AdminUserName", this.Site) + "@" + Common.GetConfigurationPropertyValue("Domain", this.Site) + "\0"); // PidTagSmtpAddress
            propertyValueArray[4].Value = BitConverter.GetBytes(0x00000000); // PidTagSendInternetEncoding
            propertyValueArray[5].Value = BitConverter.GetBytes(0x40000000); // PidTagDisplayTypeEx
            propertyValueArray[6].Value = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("AdminUserName", this.Site) + "\0"); // PidTagRecipientDisplayName
            propertyValueArray[7].Value = BitConverter.GetBytes(0x00000001); // PidTagRecipientFlags
            propertyValueArray[8].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientTrackStatus
            propertyValueArray[9].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientResourceState
            propertyValueArray[10].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientOrder

            // EntryId of administrator 
            byte[] sampleData = ConvertStringToBytes(@"0x79,0x00,0x00,0x00,0x00,0x00,0xDC,0xA7,0x40,0xC8,0xC0,0x42
                                                           ,0x10,0x1A,0xB4,0xB9,0x08,0x00,0x2B,0x2F,0xE1,0x82
                                                           ,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2F,0x6F
                                                           ,0x3D,0x63,0x6F,0x6E,0x74,0x6F,0x73,0x6F,0x2F,0x6F
                                                           ,0x75,0x3D,0x45,0x78,0x63,0x68,0x61,0x6E,0x67,0x65
                                                           ,0x20,0x41,0x64,0x6D,0x69,0x6E,0x69,0x73,0x74,0x72
                                                           ,0x61,0x74,0x69,0x76,0x65,0x20,0x47,0x72,0x6F,0x75
                                                           ,0x70,0x20,0x28,0x46,0x59,0x44,0x49,0x42,0x4F,0x48
                                                           ,0x46,0x32,0x33,0x53,0x50,0x44,0x4C,0x54,0x29,0x2F
                                                           ,0x63,0x6E,0x3D,0x52,0x65,0x63,0x69,0x70,0x69,0x65
                                                           ,0x6E,0x74,0x73,0x2F,0x63,0x6E,0x3D,0x41,0x64,0x6D
                                                           ,0x69,0x6E,0x69,0x73,0x74,0x72,0x61,0x74,0x6F,0x72
                                                           ,0x00");
            propertyValueArray[11].Value = sampleData;

            List<PropertyValue> propertyValues = new List<PropertyValue>();
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValues.Add(propertyValueArray[i]);
            }

            PropertyRow propertyRow = new PropertyRow
            {
                Flag = 0x00,
                PropertyValues = propertyValues
            };

            // For propertyRow.Flag.
            int tempLengthForTest = 1;
            foreach (PropertyValue pv in propertyRow.PropertyValues)
            {
                tempLengthForTest = tempLengthForTest + pv.Value.Length;
            }

            RecipientRow recipientRow = new RecipientRow
            {
                RecipientFlags = 0x065B,

                // Present because D is Set.
                DisplayName = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("AdminUserName", this.Site) + "\0"),
                EmailAddress = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("AdminUserName", this.Site) + "@" +
                                              Common.GetConfigurationPropertyValue("Domain", this.Site) + "\0"),
                SimpleDisplayName = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("AdminUserName", this.Site) + "\0"),

                // Matches ColummnCount.
                RecipientColumnCount = 0x000C,
                RecipientProperties = propertyRow
            };

            ModifyRecipientRow modifyRecipientRow = new ModifyRecipientRow
            {
                // Primary Recipient.
                RowId = 0x00000000,
                RecipientType = 0x01,
                RecipientRowSize = (ushort)recipientRow.Size(),

                // Bytes in the following RecipientRow.
                RecptRow = recipientRow.Serialize()
            };

            ModifyRecipientRow[] sampleModifyRecipientRows = new ModifyRecipientRow[1];
            sampleModifyRecipientRows[0] = modifyRecipientRow;
            recipientRows = sampleModifyRecipientRows;
        }
        /// <summary>
        /// Create Recipient Array 
        /// </summary>
        /// <param name="recipientColumns">Recipient Columns </param>
        /// <param name="recipientRows">Recipient Rows</param>
        private void CreateRecipientColumnsAndRecipientRows(out PropertyTag[] recipientColumns, out ModifyRecipientRow[] recipientRows)
        {
            #region recipientColumns

            // The following sample data is from MS-OXCMSG
            PropertyTag[] sampleRecipientColumns = new PropertyTag[12];
            PropertyTag tag;

            // PidTagObjectType
            tag.PropertyId = 0x0ffe;
            tag.PropertyType = 0x0003; // PtypInteger32
            sampleRecipientColumns[0] = tag;

            // PidTagDisplayType
            tag.PropertyId = 0x3900;
            tag.PropertyType = 0x0003; // PtypInteger32
            sampleRecipientColumns[1] = tag;

            // PidTagAddressBookDisplayNamePrintable
            tag.PropertyId = 0x39ff;
            tag.PropertyType = 0x001f; // PtypString
            sampleRecipientColumns[2] = tag;

            // PidTagSmtpAddress
            tag.PropertyId = 0x39fe;
            tag.PropertyType = 0x001f; // PtypString
            sampleRecipientColumns[3] = tag;

            // PidTagSendInternetEncoding
            tag.PropertyId = 0x3a71;
            tag.PropertyType = 0x0003; // PtypInteger32
            sampleRecipientColumns[4] = tag;

            // PidTagDisplayTypeEx
            tag.PropertyId = 0x3905;
            tag.PropertyType = 0x0003; // PtypInteger32
            sampleRecipientColumns[5] = tag;

            // PidTagRecipientDisplayName
            tag.PropertyId = 0x5ff6;
            tag.PropertyType = 0x001f; // PtypString
            sampleRecipientColumns[6] = tag;

            // PidTagRecipientFlags
            tag.PropertyId = 0x5ffd;
            tag.PropertyType = 0x0003; // PtypInteger32
            sampleRecipientColumns[7] = tag;

            // PidTagRecipientTrackStatus
            tag.PropertyId = 0x5fff;
            tag.PropertyType = 0x0003; // PtypInteger32
            sampleRecipientColumns[8] = tag;

            // PidTagRecipientResourceState
            tag.PropertyId = 0x5fde;
            tag.PropertyType = 0x0003; // PtypInteger32
            sampleRecipientColumns[9] = tag;

            // PidTagRecipientOrder
            tag.PropertyId = 0x5fdf;
            tag.PropertyType = 0x0003; // PtypInteger32
            sampleRecipientColumns[10] = tag;

            // PidTagRecipientEntryId
            tag.PropertyId = 0x5ff7;
            tag.PropertyType = 0x0102; // PtypBinary
            sampleRecipientColumns[11] = tag;

            recipientColumns = sampleRecipientColumns;
            #endregion

            #region Configure a StandardPropertyRow: propertyRow, data is from Page 62 of MS-OXCMSG

            PropertyValue[] propertyValueArray = new PropertyValue[12];
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValueArray[i] = new PropertyValue();
            }

            propertyValueArray[0].Value = BitConverter.GetBytes(0x00000006); // PidTagObjectType
            propertyValueArray[1].Value = BitConverter.GetBytes(0x00000000); // PidTagDisplayType
            propertyValueArray[2].Value = Encoding.Unicode.GetBytes(UserName + TestSuiteBase.NullTerminatorString); // PidTa7BitDisplayName
            string domainName = Common.GetConfigurationPropertyValue("Domain", this.Site);
            propertyValueArray[3].Value = Encoding.Unicode.GetBytes(UserName + TestSuiteBase.At + domainName + TestSuiteBase.NullTerminatorString); // PidTagSmtpAddress
            propertyValueArray[4].Value = BitConverter.GetBytes(0x00000000); // PidTagSendInternetEncoding
            propertyValueArray[5].Value = BitConverter.GetBytes(0x40000000); // PidTagDisplayTypeEx
            propertyValueArray[6].Value = Encoding.Unicode.GetBytes(UserName + TestSuiteBase.NullTerminatorString); // PidTagRecipientDisplayName
            propertyValueArray[7].Value = BitConverter.GetBytes(0x00000001); // PidTagRecipientFlags
            propertyValueArray[8].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientTrackStatus
            propertyValueArray[9].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientResourceState
            propertyValueArray[10].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientOrder

            // The following sample data (0x007c and the subsequent 124(0x7c) binary) 
            byte[] sampleData = 
            {
                0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xa7, 0x40,
                0xc8, 0xc0, 0x42, 0x10, 0x1a, 0xb4, 0xb9, 0x08, 0x00, 0x2b, 0x2f, 0xe1, 0x82, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x6f, 0x3d, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x4f, 0x72,
                0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x75, 0x3d, 0x45, 0x78,
                0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72,
                0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x28, 0x46, 0x59, 0x44,
                0x49, 0x42, 0x4f, 0x48, 0x46, 0x32, 0x33, 0x53, 0x50, 0x44, 0x4c, 0x54, 0x29, 0x2f, 0x63, 0x6e,
                0x3d, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6e, 0x3d, 0x75,
                0x73, 0x65, 0x72, 0x32, 0x00
            };
            propertyValueArray[11].Value = sampleData; // PidTagRecipientEntryId

            List<PropertyValue> propertyValues = new List<PropertyValue>();
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValues.Add(propertyValueArray[i]);
            }

            PropertyRow propertyRow = new PropertyRow
            {
                Flag = 0x01, PropertyValues = propertyValues
            };
            #endregion

            RecipientRow recipientRow = new RecipientRow
            {
                RecipientFlags = 0x065B,
                DisplayName = Encoding.Unicode.GetBytes(UserName + TestSuiteBase.NullTerminatorString),
                EmailAddress = Encoding.Unicode.GetBytes(UserName + TestSuiteBase.At + domainName + TestSuiteBase.NullTerminatorString),
                SimpleDisplayName = Encoding.Unicode.GetBytes(UserName + TestSuiteBase.NullTerminatorString),
                RecipientColumnCount = 0x000C,
                RecipientProperties = propertyRow
            };

            ModifyRecipientRow modifyRecipientRow = new ModifyRecipientRow
            {
                RowId = 0x00000000,
                RecipientType = (byte)RecipientType.PrimaryRecipient,
                RecipientRowSize = (ushort)recipientRow.Size(),
                RecptRow = recipientRow.Serialize()
            };

            ModifyRecipientRow[] sampleModifyRecipientRows = new ModifyRecipientRow[3];
            sampleModifyRecipientRows[0] = modifyRecipientRow;

            // Test add second recipient 
            ModifyRecipientRow testmodifyRecipientRow = new ModifyRecipientRow
            {
                RowId = 0x0000001,
                RecipientType = (byte)RecipientType.PrimaryRecipient,
                RecipientRowSize = (ushort)recipientRow.Size(),
                RecptRow = recipientRow.Serialize()
            };
            sampleModifyRecipientRows[1] = testmodifyRecipientRow;

            ModifyRecipientRow test2modifyRecipientRow = new ModifyRecipientRow
            {
                RowId = 0x0000002,
                RecipientType = (byte)RecipientType.PrimaryRecipient,
                RecipientRowSize = (ushort)recipientRow.Size(),
                RecptRow = recipientRow.Serialize()
            };
            sampleModifyRecipientRows[2] = test2modifyRecipientRow;

            recipientRows = sampleModifyRecipientRows;
        }
        /// <summary>
        /// Verify PropertyRow Structure
        /// </summary>
        /// <param name="propertyRow">PropertyRow Structure returned by the RopFindRow or RopQueryRows ROPs</param>
        private void VerifyPropertyRowStructure(PropertyRow propertyRow)
        {
            // Since the returned PropertyRow Structure can be parsed correctly, the following requirement can be verified.
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R65");

            // Verify MS-OXCDATA requirement: MS-OXCDATA_R65
            Site.CaptureRequirement(
                "MS-OXCDATA",
                65,
                @"[In PropertyRow Structures] For the RopFindRow, RopGetReceiveFolderTable, and RopQueryRows ROPs, property values are returned in the order of the properties in the table, set by a prior call to a RopSetColumns ROP request ([MS-OXCROPS] section 2.2.5.1).");

            // The flag with value 0x00 means the structure is StandardPropertyRow, and 0x01 means the structure is FlaggedPropertyRow Structure
            if (propertyRow.Flag == 0)
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R72");

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R72
                Site.CaptureRequirementIfAreEqual<Type>(
                    typeof(byte),
                    propertyRow.Flag.GetType(),
                    "MS-OXCDATA",
                    72,
                    @"[In StandardPropertyRow Structure] Flag (1 byte): An unsigned integer."); 

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R79");

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R79
                Site.CaptureRequirement(
                    "MS-OXCDATA",
                    79,
                    @"[In FlaggedPropertyRow Structure] Flag (1 byte): Otherwise [when PtypUnspecified was not used in the ROP request and the ROP response includes a type], this value MUST be set to 0x00.");

                int i = 0;
                uint value = 0;
                bool hasErrorPropertyValue = false;
                for (; i < propertyRow.PropertyValues.Count; i++)
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R75: the structure type of the property is {0}", propertyRow.PropertyValues[i].GetType());
                    bool isVerifyR75 = propertyRow.PropertyValues[i].GetType() == typeof(PropertyValue) || propertyRow.PropertyValues[i].GetType() == typeof(PropertyValue) || propertyRow.PropertyValues[i].GetType() == typeof(TypedPropertyValue);

                    // Verify MS-OXCDATA requirement: MS-OXCDATA_R75
                    Site.CaptureRequirementIfIsTrue(
                        isVerifyR75,
                        "MS-OXCDATA",
                        75,
                        @"[In StandardPropertyRow Structure] ValueArray (variable): At each position of the array, the structure will either be a PropertyValue structure, as specified in section 2.11.2.1, "
                        + "if the type of the corresponding property tag was specified, or a TypedPropertyValue structure, as specified in section 2.11.3, if the type of the corresponding property tag was PtypUnspecified (section 2.11.1).");

                    if (propertyRow.PropertyValues[i].Value.Length == 4)
                    {
                        value = BitConverter.ToUInt32(propertyRow.PropertyValues[i].Value, 0);
                        if (value == 0x8004010F || value == 0x80040302 || value == 0x80040303 || value == 0x80040304)
                        {
                            hasErrorPropertyValue = true;
                            break;
                        }
                    }

                    value = 0;
                }

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R73{0}", hasErrorPropertyValue ? string.Format(": No.{0} property value is not correct and the value is {1}", i, value) : string.Empty);

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R73
                bool isVerifyR73 = hasErrorPropertyValue;
                Site.CaptureRequirementIfIsFalse(
                    isVerifyR73,
                    "MS-OXCDATA",
                    73,
                    @"[In StandardPropertyRow Structure] Flag (1 byte): This value MUST be set to 0x00 to indicate that all property values are present and without error.");
            }
            else if (propertyRow.Flag == 1)
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R76");

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R76
                Site.CaptureRequirementIfAreEqual<Type>(
                    typeof(byte),
                    propertyRow.Flag.GetType(),
                    "MS-OXCDATA",
                    76,
                    @"[In FlaggedPropertyRow Structure] Flag (1 byte): An unsigned integer."); 

                int i = 0;
                uint value = 0;
                bool hasErrorPropertyValue = false;
                for (; i < propertyRow.PropertyValues.Count; i++)
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R81: the structure type of the property is {0}", propertyRow.PropertyValues[i].GetType());
                    bool isVerifyR81 = propertyRow.PropertyValues[i].GetType() == typeof(FlaggedPropertyValue) || propertyRow.PropertyValues[i].GetType() == typeof(FlaggedPropertyValueWithType);
                    
                    // Verify MS-OXCDATA requirement: MS-OXCDATA_R81
                    Site.CaptureRequirementIfIsTrue(
                        isVerifyR81,
                        "MS-OXCDATA",
                        81,
                        @"[In FlaggedPropertyRow Structure] ValueArray (variable): At each position of the array, the structure will be either a FlaggedPropertyValue structure, as specified in section 2.11.5, "
                        + "if the type of the corresponding property tag was previously specified or a FlaggedPropertyValueWithType structure, as specified in section 2.11.6, if the type of the corresponding property tag was PtypUnspecified.");

                    if (propertyRow.PropertyValues[i].Value.Length == 4)
                    {
                        value = BitConverter.ToUInt32(propertyRow.PropertyValues[i].Value, 0);
                        if (value == 0x8004010F || value == 0x80040302 || value == 0x80040303 || value == 0x80040304)
                        {
                            hasErrorPropertyValue = true;
                            break;
                        }
                    }

                    value = 0;
                }

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCDATA_R77{0}", hasErrorPropertyValue ? string.Empty : "There is no property which contains error value!");

                // Verify MS-OXCDATA requirement: MS-OXCDATA_R77
                bool isVerifyR77 = hasErrorPropertyValue;
                Site.CaptureRequirementIfIsTrue(
                    isVerifyR77,
                    "MS-OXCDATA",
                    77,
                    @"[In FlaggedPropertyRow Structure] Flag (1 byte): This value [Flag] MUST be set to 0x01 to indicate that there are errors or some property values are missing.");
            }
            else
            {
                Site.Assert.Fail("The value of the flag field is expected to be set to 0x00 or 0x01, but the current value is {0}", propertyRow.Flag);
            }
        }
        /// <summary>
        /// Deserialize the ROP response buffer.
        /// </summary>
        /// <param name="ropBytes">ROPs bytes in response.</param>
        /// <param name="startIndex">The start index of this ROP.</param>
        /// <returns>The size of response buffer structure.</returns>
        public int Deserialize(byte[] ropBytes, int startIndex)
        {
            int index = startIndex;
            this.RopId = ropBytes[index++];
            this.InputHandleIndex = ropBytes[index++];
            this.ReturnValue = (uint)BitConverter.ToInt32(ropBytes, index);
            index += sizeof(uint);

            // Only success response has below fields
            if (this.ReturnValue == 0)
            {
                this.RowNoLongerVisible = ropBytes[index++];
                this.HasRowData = ropBytes[index++];
                if (this.HasRowData != 0)
                {
                    // Parse RowData
                    // Add RowData bytes into Context
                    Context.Instance.PropertyBytes = ropBytes;
                    Context.Instance.CurIndex = index;

                    // Allocate PropretyRowSetNode to parse RowData
                    this.RowData = new PropertyRow();

                    // Set row count
                    this.RowData.Parse(Context.Instance);

                    // Context.Instance.CurIndex indicates the already deserialized bytes' index
                    index = Context.Instance.CurIndex;
                }
            }

            return index - startIndex;
        }
        /// <summary>
        /// Submit a message to the server
        /// </summary>
        /// <param name="mailTo">The user name of the recipient</param>
        /// <param name="mailToUserDN">The userDN of the recipient</param>
        /// <param name="subject">The subject of the mail</param>
        /// <param name="addedProperties">The added properties of the mail</param>
        /// <returns>Return code of the message delivering</returns>
        public uint DeliverMessageToTriggerRule(string mailTo, string mailToUserDN, string subject, TaggedPropertyValue[] addedProperties)
        {
            RopCreateMessageResponse createMsgRes;
            uint msgHandle = this.OxoruleAdapter.RopCreateMessage(outBoxFolderHandle, outBoxFolderID, 0, out createMsgRes);
            TaggedPropertyValue[] clientSpecificProperties = new TaggedPropertyValue[1];
            clientSpecificProperties[0] = new TaggedPropertyValue();
            PropertyTag propertyTag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagSubject,
                PropertyType = (ushort)PropertyType.PtypString
            };
            clientSpecificProperties[0].PropertyTag = propertyTag;
            clientSpecificProperties[0].Value = Encoding.Unicode.GetBytes(subject + "\0");
            this.OxoruleAdapter.RopSetProperties(msgHandle, clientSpecificProperties);
            if (addedProperties != null && addedProperties.Length > 0)
            {
                this.OxoruleAdapter.RopSetProperties(msgHandle, addedProperties);
            }

            #region recipientColumns,  PropertyTag[] sampleRecipientColumns
            // The following sample data is from MS-OXCMSG 4.7.1
            PropertyTag[] sampleRecipientColumns = new PropertyTag[12];
            PropertyTag tag = new PropertyTag
            {
                PropertyId = (ushort)PropertyId.PidTagObjectType,
                PropertyType = (ushort)PropertyType.PtypInteger32
            };

            // PidTagObjectType
            sampleRecipientColumns[0] = tag;

            // PidTagDisplayType
            tag.PropertyId = (ushort)PropertyId.PidTagDisplayType;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            sampleRecipientColumns[1] = tag;

            // PidTagAddressBookDisplayNamePrintable
            tag.PropertyId = (ushort)PropertyId.PidTagAddressBookDisplayNamePrintable;
            tag.PropertyType = (ushort)PropertyType.PtypString;
            sampleRecipientColumns[2] = tag;

            // PidTagSmtpAddress
            tag.PropertyId = (ushort)PropertyId.PidTagSmtpAddress;
            tag.PropertyType = (ushort)PropertyType.PtypString;
            sampleRecipientColumns[3] = tag;

            // PidTagSendInternetEncoding
            tag.PropertyId = (ushort)PropertyId.PidTagSendInternetEncoding;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            sampleRecipientColumns[4] = tag;

            // PidTagDisplayTypeEx
            tag.PropertyId = (ushort)PropertyId.PidTagDisplayTypeEx;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            sampleRecipientColumns[5] = tag;

            // PidTagRecipientDisplayName
            tag.PropertyId = (ushort)PropertyId.PidTagRecipientDisplayName;
            tag.PropertyType = (ushort)PropertyType.PtypString;
            sampleRecipientColumns[6] = tag;

            // PidTagRecipientFlags
            tag.PropertyId = (ushort)PropertyId.PidTagRecipientFlags;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            sampleRecipientColumns[7] = tag;

            // PidTagRecipientTrackStatus
            tag.PropertyId = (ushort)PropertyId.PidTagRecipientTrackStatus;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            sampleRecipientColumns[8] = tag;

            // PidTagRecipientResourceState
            tag.PropertyId = (ushort)PropertyId.PidTagRecipientResourceState;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            sampleRecipientColumns[9] = tag;

            // PidTagRecipientOrder
            tag.PropertyId = (ushort)PropertyId.PidTagRecipientOrder;
            tag.PropertyType = (ushort)PropertyType.PtypInteger32;
            sampleRecipientColumns[10] = tag;

            // PidTagRecipientEntryId
            tag.PropertyId = (ushort)PropertyId.PidTagRecipientEntryId;
            tag.PropertyType = (ushort)PropertyType.PtypBinary;
            sampleRecipientColumns[11] = tag;
            #endregion

            #region Configure a StandardPropertyRow: propertyRow
            PropertyValue[] propertyValueArray = new PropertyValue[12];
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValueArray[i] = new PropertyValue();
            }

            // PidTagObjectType
            propertyValueArray[0].Value = BitConverter.GetBytes(0x00000006);

            // PidTagDisplayType
            propertyValueArray[1].Value = BitConverter.GetBytes(0x00000000);

            // PidTagAddressBookDisplayNamePrintable
            propertyValueArray[2].Value = Encoding.Unicode.GetBytes(mailTo + "\0");

            // PidTagSmtpAddress
            propertyValueArray[3].Value = Encoding.Unicode.GetBytes(mailTo + "@" + this.Domain + "\0");

            // PidTagSendInternetEncoding
            propertyValueArray[4].Value = BitConverter.GetBytes(0x00000000);

            // PidTagDisplayTypeEx
            propertyValueArray[5].Value = BitConverter.GetBytes(0x40000000);

            // PidTagRecipientDisplayName
            propertyValueArray[6].Value = Encoding.Unicode.GetBytes(mailTo + "\0");

            // PidTagRecipientFlags
            propertyValueArray[7].Value = BitConverter.GetBytes(0x00000001);

            // PidTagRecipientTrackStatus
            propertyValueArray[8].Value = BitConverter.GetBytes(0x00000000);

            // PidTagRecipientResourceState
            propertyValueArray[9].Value = BitConverter.GetBytes(0x00000000);

            // PidTagRecipientOrder
            propertyValueArray[10].Value = BitConverter.GetBytes(0x00000000);

            AddressBookEntryID addressBookEntryID = new AddressBookEntryID(mailToUserDN);
            propertyValueArray[11].Value = Common.AddInt16LengthBeforeBinaryArray(addressBookEntryID.Serialize());

            List<PropertyValue> propertyValues = new List<PropertyValue>();
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValues.Add(propertyValueArray[i]);
            }

            PropertyRow propertyRow = new PropertyRow
            {
                Flag = 0x01,
                PropertyValues = propertyValues
            };
            #endregion

            RecipientRow recipientRow = new RecipientRow
            {
                RecipientFlags = 0x065B,
                DisplayName = Encoding.Unicode.GetBytes(mailTo + "\0"),
                EmailAddress = Encoding.Unicode.GetBytes(mailTo + "@" + this.Domain + "\0"),
                SimpleDisplayName = Encoding.Unicode.GetBytes(mailTo + "\0"),
                RecipientColumnCount = 0x000C,
                RecipientProperties = propertyRow
            };

            ModifyRecipientRow modifyRecipientRow = new ModifyRecipientRow
            {
                RowId = 0x00000000,
                RecipientType = 0x01,
                RecipientRowSize = (ushort)recipientRow.Size(),
                RecptRow = recipientRow.Serialize()
            };

            ModifyRecipientRow[] sampleModifyRecipientRows = new ModifyRecipientRow[1];
            sampleModifyRecipientRows[0] = modifyRecipientRow;
            this.OxoruleAdapter.RopModifyRecipients(msgHandle, sampleRecipientColumns, sampleModifyRecipientRows);
            this.OxoruleAdapter.RopSaveChangesMessage(msgHandle);
            RopSubmitMessageResponse submitMsgRes = this.OxoruleAdapter.RopSubmitMessage(msgHandle, 0);
            return submitMsgRes.ReturnValue;
        }
        /// <summary>
        /// Deserialize the response buffer.
        /// </summary>
        /// <param name="ropBytes">Bytes in response.</param>
        /// <param name="startIndex">The start index of this structure.</param>
        /// <returns>The size of response buffer structure.</returns>
        public int Deserialize(byte[] ropBytes, int startIndex)
        {
            int index = startIndex;

            this.size = 0;

            this.RecipientFlags = (ushort)BitConverter.ToInt16(ropBytes, index);
            index += sizeof(ushort);

            bool tflag, dflag, eflag, oflag, iflag, uflag;
            int  recipientTye = 0;

            tflag = dflag = eflag = oflag = iflag = uflag = false;

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.T) > 0)
            {
                tflag = true;
            }

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.D) > 0)
            {
                dflag = true;
            }

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.E) > 0)
            {
                eflag = true;
            }

            recipientTye = this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.PersonalDistributionList2;
            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.O) > 0)
            {
                oflag = true;
            }

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.I) > 0)
            {
                iflag = true;
            }

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.U) > 0)
            {
                uflag = true;
            }

            switch (recipientTye)
            {
            case (ushort)TestSuites.Common.RecipientFlags.X500DN:
                this.AddressPrfixUsed = ropBytes[index++];
                this.DisplayType      = ropBytes[index++];

                int  bytesLen = 0;
                bool isFound  = false;

                // Find the string with '\0' end
                for (int i = index; i < ropBytes.Length; i++)
                {
                    bytesLen++;
                    if (ropBytes[i] == 0)
                    {
                        isFound = true;
                        break;
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    X500DN = new byte[bytesLen];
                    Array.Copy(ropBytes, index, X500DN, 0, bytesLen - 1);
                    index += bytesLen;
                }

                break;

            case (ushort)TestSuites.Common.RecipientFlags.PersonalDistributionList1:
            case (ushort)TestSuites.Common.RecipientFlags.PersonalDistributionList2:
                this.EntryIdSize = (ushort)BitConverter.ToInt16(ropBytes, index);
                index           += 2;
                this.EntryId     = new byte[this.EntryIdSize];
                Array.Copy(ropBytes, index, this.EntryId, 0, this.EntryIdSize);
                index += this.EntryIdSize;

                this.SearchKeySize = (ushort)BitConverter.ToInt16(ropBytes, index);
                index         += 2;
                this.SearchKey = new byte[this.SearchKeySize];
                Array.Copy(ropBytes, index, this.SearchKey, 0, this.SearchKeySize);
                index += this.SearchKeySize;

                break;

            case (ushort)TestSuites.Common.RecipientFlags.None:
                if (oflag == true)
                {
                    bytesLen = 0;
                    isFound  = false;

                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }

                    if (!isFound)
                    {
                        throw new ParseException("String too long or not found");
                    }
                    else
                    {
                        this.AddressType = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.AddressType, 0, bytesLen - 1);
                        index += bytesLen;
                    }
                }

                break;
            }

            if (eflag == true)
            {
                int  bytesLen = 0;
                bool isFound  = false;
                if (uflag == true)
                {
                    for (int i = index; i < ropBytes.Length; i += 2)
                    {
                        bytesLen += 2;
                        if ((ropBytes[i] == 0) && (ropBytes[i + 1] == 0))
                        {
                            isFound = true;
                            break;
                        }
                    }
                }
                else
                {
                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    this.EmailAddress = new byte[bytesLen];
                    Array.Copy(ropBytes, index, this.EmailAddress, 0, bytesLen - 1);
                    index += bytesLen;
                }
            }

            if (dflag == true)
            {
                int  bytesLen = 0;
                bool isFound  = false;
                if (uflag == true)
                {
                    for (int i = index; i < ropBytes.Length; i += 2)
                    {
                        bytesLen += 2;
                        if ((ropBytes[i] == 0) && (ropBytes[i + 1] == 0))
                        {
                            isFound = true;
                            break;
                        }
                    }
                }
                else
                {
                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    if (uflag == true)
                    {
                        this.DisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.DisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                    else
                    {
                        this.DisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.DisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                }
            }

            if (iflag == true)
            {
                int  bytesLen = 0;
                bool isFound  = false;
                if (uflag == true)
                {
                    for (int i = index; i < ropBytes.Length; i += 2)
                    {
                        bytesLen += 2;
                        if ((ropBytes[i] == 0) && (ropBytes[i + 1] == 0))
                        {
                            isFound = true;
                            break;
                        }
                    }
                }
                else
                {
                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    if (uflag == true)
                    {
                        this.SimpleDisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.SimpleDisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                    else
                    {
                        this.SimpleDisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.SimpleDisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                }
            }

            if (tflag == true)
            {
                int  bytesLen = 0;
                bool isFound  = false;
                if (uflag == true)
                {
                    for (int i = index; i < ropBytes.Length; i += 2)
                    {
                        bytesLen += 2;
                        if ((ropBytes[i] == 0) && (ropBytes[i + 1] == 0))
                        {
                            isFound = true;
                            break;
                        }
                    }
                }
                else
                {
                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    if (uflag == true)
                    {
                        this.TransmittableDisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.TransmittableDisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                    else
                    {
                        this.TransmittableDisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.TransmittableDisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                }
            }

            this.RecipientColumnCount = (ushort)BitConverter.ToInt16(ropBytes, index);
            index += sizeof(ushort);
            Context.Instance.PropertyBytes = ropBytes;
            Context.Instance.CurIndex      = index;
            this.RecipientProperties       = new PropertyRow();
            this.RecipientProperties.Parse(Context.Instance);

            index                 = Context.Instance.CurIndex;
            this.size             = index - startIndex;
            this.serializedBuffer = new byte[this.size];
            Array.Copy(ropBytes, startIndex, this.serializedBuffer, 0, this.size);

            return(index - startIndex);
        }
        /// <summary>
        /// Deserialize the response buffer.
        /// </summary>
        /// <param name="ropBytes">Bytes in response.</param>
        /// <param name="startIndex">The start index of this structure.</param>
        /// <returns>The size of response buffer structure.</returns>
        public int Deserialize(byte[] ropBytes, int startIndex)
        {
            int index = startIndex;
            this.size = 0;

            this.RecipientFlags = (ushort)BitConverter.ToInt16(ropBytes, index);
            index += sizeof(ushort);

            bool tflag, dflag, eflag, oflag, iflag, uflag;
            int recipientTye = 0;
            tflag = dflag = eflag = oflag = iflag = uflag = false;

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.T) > 0)
            {
                tflag = true;
            }

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.D) > 0)
            {
                dflag = true;
            }

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.E) > 0)
            {
                eflag = true;
            }

            recipientTye = this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.PersonalDistributionList2;
            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.O) > 0)
            {
                oflag = true;
            }

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.I) > 0)
            {
                iflag = true;
            }

            if ((this.RecipientFlags & (ushort)TestSuites.Common.RecipientFlags.U) > 0)
            {
                uflag = true;
            }
          
            switch (recipientTye)
            {
                case (ushort)TestSuites.Common.RecipientFlags.X500DN:
                    this.AddressPrfixUsed = ropBytes[index++];
                    this.DisplayType = ropBytes[index++];

                    int bytesLen = 0;
                    bool isFound = false;

                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }  
                    }

                    if (!isFound)
                    {
                        throw new ParseException("String too long or not found");
                    }
                    else
                    {
                        X500DN = new byte[bytesLen];
                        Array.Copy(ropBytes, index, X500DN, 0, bytesLen - 1);
                        index += bytesLen;
                    }

                    break;
                case (ushort)TestSuites.Common.RecipientFlags.PersonalDistributionList1:
                case (ushort)TestSuites.Common.RecipientFlags.PersonalDistributionList2:
                    this.EntryIdSize = (ushort)BitConverter.ToInt16(ropBytes, index);
                    index += 2;
                    this.EntryId = new byte[this.EntryIdSize];
                    Array.Copy(ropBytes, index, this.EntryId, 0, this.EntryIdSize);
                    index += this.EntryIdSize;

                    this.SearchKeySize = (ushort)BitConverter.ToInt16(ropBytes, index);
                    index += 2;
                    this.SearchKey = new byte[this.SearchKeySize];
                    Array.Copy(ropBytes, index, this.SearchKey, 0, this.SearchKeySize);
                    index += this.SearchKeySize;

                    break;
                case (ushort)TestSuites.Common.RecipientFlags.None:
                    if (oflag == true)
                    {
                        bytesLen = 0;
                        isFound = false;

                        // Find the string with '\0' end
                        for (int i = index; i < ropBytes.Length; i++)
                        {
                            bytesLen++;
                            if (ropBytes[i] == 0)
                            {
                                isFound = true;
                                break;
                            }
                        }

                        if (!isFound)
                        {
                            throw new ParseException("String too long or not found");
                        }
                        else
                        {
                            this.AddressType = new byte[bytesLen];
                            Array.Copy(ropBytes, index, this.AddressType, 0, bytesLen - 1);
                            index += bytesLen;
                        } 
                    }

                    break;
            }

            if (eflag == true)
            {
                int bytesLen = 0;
                bool isFound = false;
                if (uflag == true)
                {
                    for (int i = index; i < ropBytes.Length; i += 2)
                    {
                        bytesLen += 2;
                        if ((ropBytes[i] == 0) && (ropBytes[i + 1] == 0))
                        {
                            isFound = true;
                            break;
                        }
                    }
                }
                else
                {
                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    this.EmailAddress = new byte[bytesLen];
                    Array.Copy(ropBytes, index, this.EmailAddress, 0, bytesLen - 1);
                    index += bytesLen;
                }  
            }

            if (dflag == true)
            {
                int bytesLen = 0;
                bool isFound = false;
                if (uflag == true)
                {
                    for (int i = index; i < ropBytes.Length; i += 2)
                    {
                        bytesLen += 2;
                        if ((ropBytes[i] == 0) && (ropBytes[i + 1] == 0))
                        {
                            isFound = true;
                            break;
                        }
                    }
                }
                else
                {
                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    if (uflag == true)
                    {
                        this.DisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.DisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                    else
                    {
                        this.DisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.DisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                }  
            }

            if (iflag == true)
            {
                int bytesLen = 0;
                bool isFound = false;
                if (uflag == true)
                {
                    for (int i = index; i < ropBytes.Length; i += 2)
                    {
                        bytesLen += 2;
                        if ((ropBytes[i] == 0) && (ropBytes[i + 1] == 0))
                        {
                            isFound = true;
                            break;
                        }
                    }
                }
                else
                {
                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    if (uflag == true)
                    {
                        this.SimpleDisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.SimpleDisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                    else
                    {
                        this.SimpleDisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.SimpleDisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                }   
            }

            if (tflag == true)
            {
                int bytesLen = 0;
                bool isFound = false;
                if (uflag == true)
                {
                    for (int i = index; i < ropBytes.Length; i += 2)
                    {
                        bytesLen += 2;
                        if ((ropBytes[i] == 0) && (ropBytes[i + 1] == 0))
                        {
                            isFound = true;
                            break;
                        }
                    }
                }
                else
                {
                    // Find the string with '\0' end
                    for (int i = index; i < ropBytes.Length; i++)
                    {
                        bytesLen++;
                        if (ropBytes[i] == 0)
                        {
                            isFound = true;
                            break;
                        }
                    }
                }

                if (!isFound)
                {
                    throw new ParseException("String too long or not found");
                }
                else
                {
                    if (uflag == true)
                    {
                        this.TransmittableDisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.TransmittableDisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                    else
                    {
                        this.TransmittableDisplayName = new byte[bytesLen];
                        Array.Copy(ropBytes, index, this.TransmittableDisplayName, 0, bytesLen);
                        index += bytesLen;
                    }
                } 
            }

            this.RecipientColumnCount = (ushort)BitConverter.ToInt16(ropBytes, index);
            index += sizeof(ushort);
            Context.Instance.PropertyBytes = ropBytes;
            Context.Instance.CurIndex = index;
            this.RecipientProperties = new PropertyRow();
            this.RecipientProperties.Parse(Context.Instance);
            
            index = Context.Instance.CurIndex;
            this.size = index - startIndex;
            this.serializedBuffer = new byte[this.size];
            Array.Copy(ropBytes, startIndex, this.serializedBuffer, 0, this.size);

            return index - startIndex;
        }
        /// <summary>
        /// Create RecipientColumns
        /// </summary>
        /// <param name="name">Recipient name</param>
        /// <returns>Return PropertyRow</returns>
        protected PropertyRow CreateRecipientColumns(string name)
        {
            // Based on above recipient columns, an ARRAY of ModifyRecipientRow is created.
            // The following sample data is from MS-OXCMSG 4.7.1
            #region Configure a StandardPropertyRow: propertyRow, data is from Page 62 of MS-OXCMSG

            PropertyValue[] propertyValueArray = new PropertyValue[12];

            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValueArray[i] = new PropertyValue();
            }

            propertyValueArray[0].Value = BitConverter.GetBytes(0x00000006); // PidTagObjectType
            propertyValueArray[1].Value = BitConverter.GetBytes(0x00000000); // PidTagDisplayType
            propertyValueArray[2].Value = Common.GetBytesFromUnicodeString(name); // PidTa7BitDisplayName
            string domainName = Common.GetConfigurationPropertyValue("Domain", this.Site);
            propertyValueArray[3].Value = Common.GetBytesFromUnicodeString(string.Format("{0}{1}{2}", name, TestSuiteBase.At, domainName)); // PidTagSmtpAddress
            propertyValueArray[4].Value = BitConverter.GetBytes(0x00000000); // PidTagSendInternetEncoding
            propertyValueArray[5].Value = BitConverter.GetBytes(0x40000000); // PidTagDisplayTypeEx
            propertyValueArray[6].Value = Common.GetBytesFromUnicodeString(PrefixOfDisplayName + name); // PidTagRecipientDisplayName
            propertyValueArray[7].Value = BitConverter.GetBytes(0x00000001); // PidTagRecipientFlags
            propertyValueArray[8].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientTrackStatus
            propertyValueArray[9].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientResourceState
            propertyValueArray[10].Value = BitConverter.GetBytes(0x00000000); // PidTagRecipientOrder

            // The following sample data (0x007c and the subsequent 124(0x7c) binary)
            byte[] sampleData = 
            {
                0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0xa7, 0x40,
                0xc8, 0xc0, 0x42, 0x10, 0x1a, 0xb4, 0xb9, 0x08, 0x00, 0x2b, 0x2f, 0xe1, 0x82, 0x01, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x6f, 0x3d, 0x46, 0x69, 0x72, 0x73, 0x74, 0x20, 0x4f, 0x72,
                0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6f, 0x75, 0x3d, 0x45, 0x78,
                0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72,
                0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x20, 0x28, 0x46, 0x59, 0x44,
                0x49, 0x42, 0x4f, 0x48, 0x46, 0x32, 0x33, 0x53, 0x50, 0x44, 0x4c, 0x54, 0x29, 0x2f, 0x63, 0x6e,
                0x3d, 0x52, 0x65, 0x63, 0x69, 0x70, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x63, 0x6e, 0x3d, 0x75,
                0x73, 0x65, 0x72, 0x32, 0x00
            };
            propertyValueArray[11].Value = sampleData; // PidTagRecipientEntryId

            List<PropertyValue> propertyValues = new List<PropertyValue>();
            for (int i = 0; i < propertyValueArray.Length; i++)
            {
                propertyValues.Add(propertyValueArray[i]);
            }

            PropertyRow propertyRow = new PropertyRow
            {
                Flag = 0x01, PropertyValues = propertyValues
            };

            #endregion
            return propertyRow;
        }