/// <summary>
        /// Gets LongTermIds.
        /// </summary>
        /// <returns>A list of LongTermIds.</returns>
        public List<LongTermId> GetLongTermIds()
        {
            List<LongTermId> idlist = new List<LongTermId>();
            if (this.globset != null && this.globset.GLOBCNTList != null)
            {
                List<GLOBCNT> cntList = this.globset.GLOBCNTList;
                for (int i = 0; i < cntList.Count; i++)
                {
                    LongTermId lid = new LongTermId
                    {
                        DatabaseGuid = this.replguid.ToByteArray(),
                        GlobalCounter = StructureSerializer.Serialize(cntList[i])
                    };
                    idlist.Add(lid);
                }
            }

            return idlist;
        }
        /// <summary>
        /// Initializes a new instance of the FolderReplicaInfo structure.
        /// </summary>
        /// <param name="stream">A FastTransferStream.</param>
        public FolderReplicaInfo(FastTransferStream stream)
        {
            this.Flags = stream.ReadUInt32();
            this.Depth = stream.ReadUInt32();
            this.FolderLongTermId = new LongTermId
            {
                DatabaseGuid = stream.ReadGuid().ToByteArray(),
                GlobalCounter = new byte[6]
            };
            stream.Read(
                this.FolderLongTermId.GlobalCounter,
                0,
                this.FolderLongTermId.GlobalCounter.Length);
            stream.Read(new byte[2], 0, 2);
            this.ServerDNCount = stream.ReadUInt32();
            this.CheapServerDNCount = stream.ReadUInt32();
            this.ServerDNArray = new string[this.ServerDNCount];

            for (int i = 0; i < this.ServerDNCount; i++)
            {
                this.ServerDNArray[i] = stream.ReadString8();
            }
        }
        /// <summary>
        /// Create values for SynchronizationImportHierarchyChange.
        /// </summary>
        /// <param name="serverId">server id.</param>
        /// <param name="folderIdIndex">Folder id index.</param>
        /// <param name="parentFolderHandleIndex">Parent folder handle index.</param>
        /// <param name="folderId">Folder id.</param>
        /// <param name="conflictType">Conflict type </param>
        /// <returns>Return the constructed hierarchy values.</returns>
        private TaggedPropertyValue[] CreateSampleHierarchyValues(int serverId, int folderIdIndex, int parentFolderHandleIndex, out ulong folderId, ConflictTypes conflictType)
        {
            folderId = 0;
            TaggedPropertyValue[] hierarchyValues = new TaggedPropertyValue[6];
            TaggedPropertyValue propertyValue = new TaggedPropertyValue();
            byte[] currentChangeNumber = new byte[6];

            // PidTagParentSourceKey equal to the PidTagSourceKey of the parent folder
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x65E1, 0x0102)
            };

            Sequence<string> propertyTag = new Sequence<string>("PidTagSourceKey");
            this.GetPropertiesSpecific(serverId, parentFolderHandleIndex, propertyTag);
            propertyValue.Value = this.propertyValuesSpecific["PidTagSourceKey"];
            hierarchyValues[0] = propertyValue;

            if (conflictType == ConflictTypes.NONE)
            {
                // Whether the hierarchy already exists.
                if (this.objectIdContainer.ContainsKey(folderIdIndex))
                {
                    // Construct PidTagSourceKey value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E0, 0x0102)
                    };

                    byte[] sampleForPidTagSourceKey = this.propertyValuesSpecific["PidTagSourceKey"];
                    propertyValue.Value = sampleForPidTagSourceKey;
                    hierarchyValues[1] = propertyValue;

                    folderId = this.objectIdContainer[folderIdIndex];

                    // Construct PidTagLastModificationTime value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x3008, 0x0040)
                    };

                    byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                    propertyValue.Value = sampleForPidTagLastModificationTime;
                    hierarchyValues[2] = propertyValue;

                    // Construct PidTagChangeKey value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E2, 0x0102)
                    };

                    byte[] sampleForPidTagChangeKey = this.propertyValuesSpecific["PidTagChangeKey"];

                    // Modify ChangeKey to generate a new ChangeKey.
                    byte[] temp = new byte[4];
                    Array.Copy(sampleForPidTagChangeKey, sampleForPidTagChangeKey.Length - 4, temp, 0, 4);
                    Array.Reverse(temp);
                    int add = BitConverter.ToInt32(temp, 0);

                    // Modify the changeNumber to a newer version.
                    add++;
                    temp = BitConverter.GetBytes(add);
                    Array.Reverse(temp);
                    Array.Copy(temp, 0, sampleForPidTagChangeKey, sampleForPidTagChangeKey.Length - 4, 4);
                    propertyValue.Value = sampleForPidTagChangeKey;
                    hierarchyValues[3] = propertyValue;

                    // Construct PidTagPredecessorChangeList value
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E3, 0x0102)
                    };

                    byte[] sampleForPidTagPredecessorChangeList = new byte[this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length + sampleForPidTagChangeKey.Length];
                    Array.Copy(this.propertyValuesSpecific["PidTagPredecessorChangeList"], 0, sampleForPidTagPredecessorChangeList, 0, this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length);
                    Array.Copy(sampleForPidTagChangeKey, 0, sampleForPidTagPredecessorChangeList, this.propertyValuesSpecific["PidTagPredecessorChangeList"].Length, sampleForPidTagChangeKey.Length);
                    propertyValue.Value = sampleForPidTagPredecessorChangeList;
                    hierarchyValues[4] = propertyValue;
                }
                else if (folderIdIndex == 0)
                {
                    // Get a local id from the id set given by server.
                    byte[] sub = new byte[4];
                    byte[] currentLocalId = this.localId;
                    Array.Copy(currentLocalId, 2, sub, 0, currentLocalId.Length - 2);
                    Array.Reverse(sub);
                    int totalNum = BitConverter.ToInt32(sub, 0);
                    totalNum += this.localIdOffSet;
                    sub = BitConverter.GetBytes(totalNum);
                    Array.Reverse(sub);
                    Array.Copy(sub, 0, currentLocalId, 2, currentLocalId.Length - 2);
                    this.localIdOffSet++;

                    // Construct PidTagSourceKey value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E0, 0x0102)
                    };

                    byte[] sampleForPidTagSourceKey = new byte[24];
                    int length = 0;
                    int index = 0;

                    // The combination of first two bytes indicates the length of value field.
                    length = (short)(this.serverReplicaGuid.ToByteArray().Length + currentLocalId.Length);
                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagSourceKey, 0, sizeof(short));
                    index += sizeof(short);
                    Array.Copy(this.serverReplicaGuid.ToByteArray(), 0, sampleForPidTagSourceKey, index, this.serverReplicaGuid.ToByteArray().Length);
                    index += this.serverReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentLocalId, 0, sampleForPidTagSourceKey, index, currentLocalId.Length);
                    Array.Copy(currentLocalId, 0, currentChangeNumber, 0, currentLocalId.Length);
                    propertyValue.Value = sampleForPidTagSourceKey;
                    hierarchyValues[1] = propertyValue;

                    // Convert long term id to id .
                    LongTermId longTermId = new LongTermId
                    {
                        DatabaseGuid = this.serverReplicaGuid.ToByteArray(),
                        GlobalCounter = currentLocalId
                    };
                    folderId = this.GetIdFromLongTerm(serverId, longTermId);

                    // Construct PidTagLastModificationTime value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x3008, 0x0040)
                    };

                    byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                    propertyValue.Value = sampleForPidTagLastModificationTime;
                    hierarchyValues[2] = propertyValue;

                    // Construct PidTagChangeKey value.
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E2, 0x0102)
                    };

                    byte[] sampleForPidTagChangeKey = new byte[24];
                    index = 0;
                    length = 0;
                    length = (short)GidLength;

                    // The combination of first two bytes indicates the length of value field.
                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagChangeKey, 0, sizeof(short));
                    index += sizeof(short);
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagChangeKey, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagChangeKey, index, currentChangeNumber.Length);
                    propertyValue.Value = sampleForPidTagChangeKey;
                    hierarchyValues[3] = propertyValue;

                    // Construct PidTagPredecessorChangeList value
                    propertyValue = new TaggedPropertyValue
                    {
                        PropertyTag = new PropertyTag(0x65E3, 0x0102)
                    };

                    byte[] sampleForPidTagPredecessorChangeList = new byte[25];
                    index = 0;
                    length = 0;
                    length = (short)(GidLength + 1);
                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                    index += sizeof(short);
                    sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + currentChangeNumber.Length); // 16
                    index += 1;
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagPredecessorChangeList, index, currentChangeNumber.Length);
                    propertyValue.Value = sampleForPidTagPredecessorChangeList;
                    hierarchyValues[4] = propertyValue;
                }
            }
            else
            {
                // Get a local id from the id set given by server.
                byte[] sub = new byte[4];
                byte[] currentLocalId = this.localId;
                Array.Copy(currentLocalId, 2, sub, 0, currentLocalId.Length - 2);
                Array.Reverse(sub);
                int totalNum = BitConverter.ToInt32(sub, 0);
                totalNum += this.localIdOffSet;
                sub = BitConverter.GetBytes(totalNum);
                Array.Reverse(sub);
                Array.Copy(sub, 0, currentLocalId, 2, currentLocalId.Length - 2);
                this.localIdOffSet++;

                // Construct PidTagSourceKey value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E0, 0x0102)
                };

                byte[] sampleForPidTagSourceKey = new byte[24];
                int length = 0;
                int index = 0;

                // The combination of first two bytes indicates the length of value field.
                length = (short)(this.serverReplicaGuid.ToByteArray().Length + currentLocalId.Length);
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagSourceKey, 0, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.serverReplicaGuid.ToByteArray(), 0, sampleForPidTagSourceKey, index, this.serverReplicaGuid.ToByteArray().Length);
                index += this.serverReplicaGuid.ToByteArray().Length;
                Array.Copy(currentLocalId, 0, sampleForPidTagSourceKey, index, currentLocalId.Length);
                Array.Copy(currentLocalId, 0, currentChangeNumber, 0, currentLocalId.Length);
                propertyValue.Value = sampleForPidTagSourceKey;
                hierarchyValues[1] = propertyValue;

                // Convert long term id to id .
                LongTermId longTermId = new LongTermId
                {
                    DatabaseGuid = this.serverReplicaGuid.ToByteArray(),
                    GlobalCounter = currentLocalId
                };
                folderId = this.GetIdFromLongTerm(serverId, longTermId);

                // Construct PidTagLastModificationTime value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x3008, 0x0040)
                };

                byte[] sampleForPidTagLastModificationTime = BitConverter.GetBytes(DateTime.Now.ToFileTimeUtc());
                propertyValue.Value = sampleForPidTagLastModificationTime;
                hierarchyValues[2] = propertyValue;

                // Construct PidTagChangeKey value.
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E2, 0x0102)
                };

                byte[] sampleForPidTagChangeKey = new byte[24];
                index = 0;
                length = 0;
                length = (short)GidLength;

                // The combination of first two bytes indicates the length of value field.
                Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagChangeKey, 0, sizeof(short));
                index += sizeof(short);
                Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagChangeKey, index, this.localReplicaGuid.ToByteArray().Length);
                index += this.localReplicaGuid.ToByteArray().Length;
                Array.Copy(currentChangeNumber, 0, sampleForPidTagChangeKey, index, currentChangeNumber.Length);
                propertyValue.Value = sampleForPidTagChangeKey;
                hierarchyValues[3] = propertyValue;

                // Construct PidTagPredecessorChangeList value
                propertyValue = new TaggedPropertyValue
                {
                    PropertyTag = new PropertyTag(0x65E3, 0x0102)
                };

                byte[] sampleForPidTagPredecessorChangeList;

                if (conflictType == ConflictTypes.AINCLUDEB)
                {
                    sampleForPidTagPredecessorChangeList = new byte[25];
                    index = 0;
                    length = 0;
                    length = (short)(GidLength + 1);

                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                    index += sizeof(short);
                    sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + currentChangeNumber.Length); // 16
                    index += 1;
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagPredecessorChangeList, index, currentChangeNumber.Length);

                    this.lastConflictInfo.PCLB = sampleForPidTagPredecessorChangeList;
                    sampleForPidTagPredecessorChangeList[24] += 1;
                    this.lastConflictInfo.PCLA = sampleForPidTagPredecessorChangeList;
                    this.lastConflictInfo.PCLXFromMath = sampleForPidTagPredecessorChangeList;
                    this.lastConflictInfo.DetectedResult = conflictType;

                    propertyValue.Value = sampleForPidTagPredecessorChangeList;
                    hierarchyValues[4] = propertyValue;
                }
                else if (conflictType == ConflictTypes.BINCLUDEA)
                {
                    sampleForPidTagPredecessorChangeList = new byte[25];
                    index = 0;
                    length = 0;
                    length = (short)(GidLength + 1);

                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                    index += sizeof(short);
                    sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + currentChangeNumber.Length); // 16
                    index += 1;
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagPredecessorChangeList, index, currentChangeNumber.Length);

                    this.lastConflictInfo.PCLB = sampleForPidTagPredecessorChangeList;
                    this.lastConflictInfo.PCLXFromMath = sampleForPidTagPredecessorChangeList;
                    sampleForPidTagPredecessorChangeList[24] -= 1;
                    this.lastConflictInfo.PCLA = sampleForPidTagPredecessorChangeList;
                    this.lastConflictInfo.DetectedResult = conflictType;

                    propertyValue.Value = sampleForPidTagPredecessorChangeList;
                    hierarchyValues[4] = propertyValue;
                }

                if (conflictType == ConflictTypes.CONFLICT)
                {
                    // If the versions from client and server are in conflict, the value of PidTagPredecessorChangeList property in client should not include 
                    // the one in server. And the changelist value in server should not include or be equal to the one in client, which means the changelist value in client 
                    // should be different with server, just like the second example in section 4.6.2.
                    sampleForPidTagPredecessorChangeList = new byte[25];
                    index = 0;
                    length = 0;
                    length = (short)(GidLength + 1);
                    Array.Copy(BitConverter.GetBytes(length), 0, sampleForPidTagPredecessorChangeList, 0, sizeof(short));
                    index += sizeof(short);
                    sampleForPidTagPredecessorChangeList[2] = Convert.ToByte(this.localReplicaGuid.ToByteArray().Length + currentChangeNumber.Length); // 16
                    index += 1;
                    Array.Copy(this.localReplicaGuid.ToByteArray(), 0, sampleForPidTagPredecessorChangeList, index, this.localReplicaGuid.ToByteArray().Length);
                    index += this.localReplicaGuid.ToByteArray().Length;
                    Array.Copy(currentChangeNumber, 0, sampleForPidTagPredecessorChangeList, index, currentChangeNumber.Length);
                    this.lastConflictInfo.PCLB = sampleForPidTagPredecessorChangeList;

                    // The parameter change is used to save the changelist value in client.
                    byte[] change = new byte[48];
                    Array.Copy(BitConverter.GetBytes(46), 0, change, 0, sizeof(short));
                    Array.Copy(sampleForPidTagPredecessorChangeList, 2, change, 2, 23);
                    Array.Copy(BitConverter.GetBytes(22), 0, change, 25, sizeof(short));

                    // Modify the value of PidTagPredecessorChangeList property in client via adding one in GUID field and adding one in GLOBCNT field.
                    byte[] namespaceGuidPartValue = new byte[8];
                    Array.Copy(sampleForPidTagPredecessorChangeList, 10, namespaceGuidPartValue, 2, namespaceGuidPartValue.Length - 2);
                    Array.Reverse(namespaceGuidPartValue);
                    long namespaceGuidPartValueInt = BitConverter.ToInt64(namespaceGuidPartValue, 0);
                    namespaceGuidPartValueInt += 1;
                    namespaceGuidPartValue = BitConverter.GetBytes(namespaceGuidPartValueInt);
                    Array.Reverse(namespaceGuidPartValue);
                    Array.Copy(namespaceGuidPartValue, 2, sampleForPidTagPredecessorChangeList, 10, namespaceGuidPartValue.Length - 2);
                    Array.Copy(sampleForPidTagPredecessorChangeList, 3, change, 26, 22);
                    change[47] += 1;

                    this.lastConflictInfo.PCLA = change;
                    this.lastConflictInfo.PCLXFromMath = change;
                    this.lastConflictInfo.DetectedResult = conflictType;

                    propertyValue.Value = change;
                    hierarchyValues[4] = propertyValue;
                }
            }

            // Construct PidTagDisplayName value.
            propertyValue = new TaggedPropertyValue
            {
                PropertyTag = new PropertyTag(0x3001, 0x001F)
            };

            byte[] sampleForPidTagDisplayName = new byte[Encoding.Unicode.GetByteCount("TestFolder" + "\0")];
            Array.Copy(
                Encoding.Unicode.GetBytes("TestFolder" + "\0"),
                0,
                sampleForPidTagDisplayName,
                0,
                Encoding.Unicode.GetByteCount("TestFolder" + "\0"));
            propertyValue.Value = sampleForPidTagDisplayName;
            hierarchyValues[5] = propertyValue;

            return hierarchyValues;
        }
 /// <summary>
 /// Convert longTermId to id.
 /// </summary>
 /// <param name="serverId">server id.</param>
 /// <param name="longTermId">longTerm id.</param>
 /// <returns>Converted short term id.</returns>
 private ulong GetIdFromLongTerm(int serverId, LongTermId longTermId)
 {
     RopIdFromLongTermIdRequest ropIdFromLongTermRequest = new RopIdFromLongTermIdRequest();
     RopIdFromLongTermIdResponse ropIdFromLongTermResponse = new RopIdFromLongTermIdResponse();
     ropIdFromLongTermRequest.RopId = 0x44;
     ropIdFromLongTermRequest.LogonId = 0x00;
     ropIdFromLongTermRequest.InputHandleIndex = 0x00;
     ropIdFromLongTermRequest.LongTermId = longTermId;
     ropIdFromLongTermResponse = (RopIdFromLongTermIdResponse)this.Process(serverId, ropIdFromLongTermRequest, this.logonHandleOut);
     return ropIdFromLongTermResponse.ObjectId;
 }
        /// <summary>
        /// Identifies that a set of IDs either belongs to deleted messages in the specified folder or will never be used for any messages in the specified folder.
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server.</param>
        /// <param name="folderhandleIndex">A Folder object handle index.</param>
        /// <param name="longTermIdRangeIndex">An array of LongTermIdRange structures defines a range of IDs, which are reported as unused or deleted.</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult SetLocalReplicaMidsetDeleted(int serverId, int folderhandleIndex, Sequence<int> longTermIdRangeIndex)
        {
            // Initialize ROP data.
            RopResult result = RopResult.InvalidParameter;
            uint folderHandle = this.handleContainer[folderhandleIndex];
            LongTermIdRange[] idranges = new LongTermIdRange[longTermIdRangeIndex.Count];

            // Get the Mid need to be deleted.
            for (int i = 0; i < longTermIdRangeIndex.Count; i++)
            {
                LongTermId max = new LongTermId();
                LongTermId min = new LongTermId();

                // Max Mid
                max.DatabaseGuid = this.serverReplicaGuid.ToByteArray();
                max.GlobalCounter = new byte[6];
                Array.Copy(this.localId, 0, max.GlobalCounter, 0, 6);
                byte[] sub = new byte[4];
                Array.Copy(max.GlobalCounter, 2, sub, 0, 4);
                Array.Reverse(sub);
                int num = BitConverter.ToInt32(sub, 0);

                // Make the Mid to the mid to be deleted one.
                num += longTermIdRangeIndex[i];
                sub = BitConverter.GetBytes(num);
                Array.Reverse(sub);
                Array.Copy(sub, 0, max.GlobalCounter, 2, 4);

                // Min Mid
                min.DatabaseGuid = this.serverReplicaGuid.ToByteArray();
                min.GlobalCounter = new byte[6];
                Array.Copy(this.localId, 0, min.GlobalCounter, 0, 6);
                sub = new byte[4];
                Array.Copy(min.GlobalCounter, 2, sub, 0, 4);
                Array.Reverse(sub);
                num = BitConverter.ToInt32(sub, 0);

                // Make the Mid to the mid to be deleted one.
                num += longTermIdRangeIndex[i];
                sub = BitConverter.GetBytes(num);
                Array.Reverse(sub);
                Array.Copy(sub, 0, min.GlobalCounter, 2, 4);

                // ID range data
                idranges[i].MaxLongTermId = max.Serialize();
                idranges[i].MinLongTermId = min.Serialize();
            }

            // Construct the RopGetLocalReplicaIds request.
            RopSetLocalReplicaMidsetDeletedRequest req = new RopSetLocalReplicaMidsetDeletedRequest
            {
                RopId = 0x93
            };
            byte logonId = 0;
            req.LogonId = logonId;
            req.InputHandleIndex = 0;
            req.DataSize = (ushort)((sizeof(byte) * 48 * idranges.Length) + 4);
            req.LongTermIdRangeCount = (uint)idranges.Length;

            // Set idCount, which specifies the number of IDs to reserve,
            req.LongTermIdRanges = idranges;

            // Send request and get response.
            RopSetLocalReplicaMidsetDeletedResponse setLocalReplicaMidsetDeletedResponse = (RopSetLocalReplicaMidsetDeletedResponse)this.Process(serverId, req, folderHandle);
            result = (RopResult)setLocalReplicaMidsetDeletedResponse.ReturnValue;

            if (result == RopResult.Success)
            {
                // Verify ROP SetLocalReplicaMidsetDeleted
                this.VerifyRopSetLocalReplicaMidsetDeleted(setLocalReplicaMidsetDeletedResponse);
            }

            return result;
        }
        /// <summary>
        /// Imports information about moving a message between two existing folders within the same mailbox.
        /// </summary>
        /// <param name="serverId">A 32-bit signed integer represent the Identity of server.</param>
        /// <param name="synchronizationUploadContextHandleIndex">The index of the synchronization upload context configured for collecting changes to the contents of the message move destination folder.</param>
        /// <param name="sourceFolderIdIndex">The index of the source folder id in object id container.</param>
        /// <param name="destinationFolderIdIndex">The index of the destination folder id in object id container.</param>
        /// <param name="sourceMessageIdIndex">The index of source message id in object id container.</param>
        /// <param name="sourceFolderHandleIndex">The index of source folder handle in handleContainer.</param>
        /// <param name="destinationFolderHandleIndex">The index of destination folder handle in handle container.</param>
        /// <param name="inewerClientChange">If the client has a newer message.</param>
        /// <param name="iolderversion">If the server have an older version of a message .</param>
        /// <param name="icnpc">Verify if the change number has been used.</param>
        /// <returns>Indicate the result of this ROP operation.</returns>
        public RopResult SynchronizationImportMessageMove(int serverId, int synchronizationUploadContextHandleIndex, int sourceFolderIdIndex, int destinationFolderIdIndex, int sourceMessageIdIndex, int sourceFolderHandleIndex, int destinationFolderHandleIndex, bool inewerClientChange, out bool iolderversion, out bool icnpc)
        {
            // Initialize return value.
            iolderversion = false;
            icnpc = true;
            RopResult result = RopResult.InvalidParameter;
            uint synchronizationUploadContextHandle = this.handleContainer[synchronizationUploadContextHandleIndex];
            uint sourceFolderHandle = this.handleContainer[sourceFolderHandleIndex];
            ulong sourceFID = this.objectIdContainer[sourceFolderIdIndex];
            ulong sourceMID = this.objectIdContainer[sourceMessageIdIndex];

            // Construct the RopSynchronizationImportMessageMove request. 
            RopSynchronizationImportMessageMoveRequest importMessageMoveRequest = new RopSynchronizationImportMessageMoveRequest
            {
                RopId = 0x78,
                LogonId = 0x00,
                InputHandleIndex = 0x00
            };

            // Get source folder id.
            byte[] fidLongTermId = this.GetLongTermIdByte(serverId, sourceFID);
            importMessageMoveRequest.SourceFolderIdSize = (uint)fidLongTermId.Length;
            byte[] sourceFolderId = new byte[fidLongTermId.Length];
            Array.Copy(fidLongTermId, 0, sourceFolderId, 0, fidLongTermId.Length);
            importMessageMoveRequest.SourceFolderId = sourceFolderId;

            // Get source message id
            byte[] midLongTermId = this.GetLongTermIdByte(serverId, sourceMID);
            importMessageMoveRequest.SourceMessageIdSize = (uint)midLongTermId.Length;
            byte[] sourceMessageId = new byte[midLongTermId.Length];
            Array.Copy(midLongTermId, 0, sourceMessageId, 0, midLongTermId.Length);
            importMessageMoveRequest.SourceMessageId = sourceMessageId;

            // Get destination message id
            byte[] sub = new byte[4];
            byte[] currentLocalId = this.localId;

            // Get local id.
            Array.Copy(currentLocalId, 2, sub, 0, currentLocalId.Length - 2);
            Array.Reverse(sub);
            int tempLocalId = BitConverter.ToInt32(sub, 0);
            tempLocalId += this.localIdOffSet;
            sub = BitConverter.GetBytes(tempLocalId);
            Array.Reverse(sub);
            Array.Copy(sub, 0, currentLocalId, 2, currentLocalId.Length - 2);
            this.localIdOffSet++;
            importMessageMoveRequest.DestinationMessageIdSize = (uint)(this.serverReplicaGuid.ToByteArray().Length + currentLocalId.Length);
            byte[] destinationMessageId = new byte[this.serverReplicaGuid.ToByteArray().Length + currentLocalId.Length];
            Array.Copy(this.serverReplicaGuid.ToByteArray(), 0, destinationMessageId, 0, this.serverReplicaGuid.ToByteArray().Length);
            Array.Copy(currentLocalId, 0, destinationMessageId, this.serverReplicaGuid.ToByteArray().Length, currentLocalId.Length);
            LongTermId longtermid = new LongTermId
            {
                DatabaseGuid = this.serverReplicaGuid.ToByteArray(),
                GlobalCounter = currentLocalId
            };

            // Get Mid from long termid.
            ulong destinationMID = this.GetIdFromLongTerm(serverId, longtermid);
            importMessageMoveRequest.DestinationMessageId = destinationMessageId;

            // Change number
            byte[] tempChangeNumber = this.GetChangeNumber(serverId, sourceMID, sourceFID, sourceFolderHandle);
            importMessageMoveRequest.ChangeNumberSize = (uint)tempChangeNumber.Length;

            // Generate a new change number.
            byte[] tempBytes = new byte[4];
            Array.Copy(tempChangeNumber, tempChangeNumber.Length - 4, tempBytes, 0, 4);
            Array.Reverse(tempBytes);
            int num = BitConverter.ToInt32(tempBytes, 0);
            if (inewerClientChange == false)
            {
                // Make the message version older in client than that in server.
                num--;
                iolderversion = false;
            }
            else
            {
                // Make the message version newer in client than that in server.
                num++;
                iolderversion = true;
            }

            tempBytes = BitConverter.GetBytes(num);
            Array.Reverse(tempBytes);
            Array.Copy(tempBytes, 0, tempChangeNumber, tempChangeNumber.Length - 4, tempBytes.Length);
            importMessageMoveRequest.ChangeNumber = tempChangeNumber;

            // Set the PCL size value.
            importMessageMoveRequest.PredecessorChangeListSize = (uint)(tempChangeNumber.Length + 1);
            importMessageMoveRequest.PredecessorChangeList = new byte[tempChangeNumber.Length + 1];
            importMessageMoveRequest.PredecessorChangeList[0] = (byte)tempChangeNumber.Length;
            Array.Copy(tempChangeNumber, 0, importMessageMoveRequest.PredecessorChangeList, 1, tempChangeNumber.Length);

            // Send request and get response.
            RopSynchronizationImportMessageMoveResponse synchronizationImportMessageMoveResponse = (RopSynchronizationImportMessageMoveResponse)this.Process(serverId, importMessageMoveRequest, synchronizationUploadContextHandle);
            result = (RopResult)synchronizationImportMessageMoveResponse.ReturnValue;

            if (result == RopResult.Success)
            {
                // Verify ROP SynchronizationImportMessageMove
                this.VerifyRopSynchronizationImportMessageMove(synchronizationImportMessageMoveResponse);
                int messageIdIndex = AdapterHelper.GetObjectIdIndex();
                this.objectIdContainer.Add(messageIdIndex, destinationMID);
                icnpc = false;
                this.isNonImportMessageChangeOperation = true;
            }
            else if (result == RopResult.NewerClientChange)
            {
                // Verify ROP SynchronizationImportMessageMove
                this.VerifyRopSynchronizationImportMessageMove(synchronizationImportMessageMoveResponse);
            }

            this.isImportMessageMoveROP = true;

            return result;
        }
        /// <summary>
        /// Get content sync data.
        /// </summary>
        /// <param name="serverID">server id.</param>
        /// <param name="stateIndex">Start index.</param>
        /// <param name="cs">Content sync object</param>
        /// <returns>The AbstractFastTransferStream</returns>
        public AbstractFastTransferStream GetAbstractContentSync(
            int serverID,
            int stateIndex,
            ContentsSync cs)
        {
            AbstractFastTransferStream afts = new AbstractFastTransferStream();
            AbstractContentsSync acs = new AbstractContentsSync
            {
                AbstractDeletion = new AbstractDeletion
                {
                    IdSetDeleted = new Modeling.Set<int>()
                }
            };

            // If the deletion is not null change the AbstractDeletion's field,
            // else do not change the Deletions field of the AbstractContentsSync
            if (cs.Deletions != null)
            {
                // If the deletion is not null the deletion is present.
                acs.AbstractDeletion = new AbstractDeletion
                {
                    IsDeletionPresent = true,
                    IsPidTagIdsetExpiredExist = cs.Deletions.PropList.HasPidTagIdsetExpired,

                    // Check pidtags in the deletions property list.
                    IsPidTagIdsetNoLongerInScopeExist = cs.Deletions.PropList.HasPidTagIdsetNoLongerInScope,
                    IdSetDeleted = new Modeling.Set<int>()
                };

                // Check Idset in the deletion.
                // If the Idset that can be got from PidTagIdsetDeleted value 
                // in the PropList of the deletions is contained in the objectIdContainer
                // add it to the IdsetDeleted field in the AbstractDeletion
                List<ulong> ids = cs.Deletions.IdsetDeleted;
                foreach (int key in this.objectIdContainer.Keys)
                {
                    if (ids.Contains(this.objectIdContainer[key]))
                    {
                        acs.AbstractDeletion.IdSetDeleted =
                             acs.AbstractDeletion.IdSetDeleted.Add(key);
                    }
                }

                this.VerifyMetaTagIdsetDeletedProperty(this.hasExecuteSynchronizationImportDeletes, this.importDelFlag, ids, this.delObjId);
                this.hasExecuteSynchronizationImportDeletes = false;
            }

            // Whether ProgressTotal is present.
            acs.IsprogessTotalPresent = cs.ProgressTotal != null;

            // Whether ReadStateChanges is present.
            acs.IsReadStateChangesExist = cs.ReadStateChanges != null;

            acs.MessageInfo = new Modeling.Set<AbstractMessageChangeInfo>();
            if (cs.MessageChangeTuples != null)
            {
                for (int i = 0; i < cs.MessageChangeTuples.Count; i++)
                {
                    AbstractMessageChangeInfo info = new AbstractMessageChangeInfo();
                    Tuple<ProgressPerMessage, MessageChange> msg = cs.MessageChangeTuples[i];
                    info.IsMessageChangeFull = msg.Item2 is MessageChangeFull;

                    // Whether ProgressPerMessagePresent is present.
                    info.IsProgressPerMessagePresent = msg.Item1 != null;
                    if (msg.Item1 != null)
                    {
                        // If ProgressPerMessagePresent is present,
                        // whether the message followed is a FAI message.
                        info.FollowedFAIMessage = msg.Item1.IsFollowedFAIMessage;
                    }

                    info.IsPidTagChangeNumberExist = msg.Item2.HasPidTagChangeNumber;
                    info.IsPidTagMessageSizeExist = msg.Item2.HasPidTagMessageSize;
                    info.IsPidTagMidExist = msg.Item2.HasPidTagMid;

                    // convert the SourceKey in the messageChangeHeader of the messageChange
                    // to a GID  structure, then use this GID to build a LongTermId,
                    // get the id corresponding to the LongTermId,if the id is maintained in the 
                    // objectIdContainer,find its index, else set the messageIdIndex of the 
                    // AbstractMessageChangeInfo to -1.
                    byte[] buffer = msg.Item2.SourceKey;
                    GID gid = StructureSerializer.Deserialize<GID>(buffer);
                    LongTermId lid = new LongTermId
                    {
                        DatabaseGuid = gid.DatabaseGuid.ToByteArray(),
                        GlobalCounter = gid.GlobalCounter
                    };
                    ulong id = this.GetIdFromLongTerm(serverID, lid);
                    info.MessageIdIndex = -1;
                    foreach (int k in this.objectIdContainer.Keys)
                    {
                        if (this.objectIdContainer[k] == id)
                        {
                            info.MessageIdIndex = k;
                            break;
                        }
                    }

                    // If messageChangeFull, whether its PropList contains PidTagRtfCompressed. 
                    if (msg.Item2 is MessageChangeFull)
                    {
                        info.IsRTFformat = (msg.Item2 as MessageChangeFull).IsRTFFormat;
                    }

                    // Add the AbstractMessageChangeInfo to the MessageInfo of the AbstractContentsSync
                    acs.MessageInfo = acs.MessageInfo.Add(info);
                }

                // if there is  more than 1 messageChange presents.
                // whether their order is in descending order.
                if (cs.MessageChangeTuples.Count > 1)
                {
                    acs.IsSortByLastModificationTime = true;
                    acs.IsSortByMessageDeliveryTime = true;
                    DateTime prev = cs.MessageChangeTuples[0].Item2.LastModificationTime;
                    for (int i = 1; i < cs.MessageChangeTuples.Count; i++)
                    {
                        DateTime curr = cs.MessageChangeTuples[i].Item2.LastModificationTime;

                        // If one is not in descending order.
                        // set flags to false.
                        if (prev < curr)
                        {
                            acs.IsSortByLastModificationTime = false;
                            acs.IsSortByMessageDeliveryTime = false;
                            break;
                        }
                    }

                    // If the OrderByDeliveryTime flag of the SynchronizationExtraFlag field is not set, there is no requirement on the server to return items in a specific order.
                    if (this.isOrderByDeliveryTimeExtraFlagNotSet)
                    {
                        acs.IsSortByLastModificationTime = false;
                        acs.IsSortByMessageDeliveryTime = false;
                    }
                }
            }

            // Get FinalICSState.
            acs.FinalICSState = this.GetAbstractState(serverID, stateIndex, cs.State);
            afts.AbstractContentsSync = acs;
            afts.StreamType = FastTransferStreamType.contentsSync;
            afts.AbstractState = new AbstractState();
            return afts;
        }
        /// <summary>
        /// Deserialize from a stream.
        /// </summary>
        /// <param name="stream">A stream contains serialize.</param>
        /// <param name="size">Must be -1.</param>
        /// <returns>The number of bytes read from the stream.</returns>
        public int Deserialize(System.IO.Stream stream, int size)
        {
            AdapterHelper.Site.Assert.AreEqual(-1, size, "The size value should be -1, but the actual value is {0}.", size);

            int bytesRead = 0;
            this.Flags = StreamHelper.ReadUInt32(stream);
            bytesRead += 4;

            this.Depth = StreamHelper.ReadUInt32(stream);
            bytesRead += 4;

            this.FolderLongTermId = StreamHelper.ReadLongTermId(stream);
            bytesRead += 0x10 + 6 + 2;

            this.ServerDNCount = StreamHelper.ReadUInt32(stream);
            bytesRead += 4;

            this.CheapServerDNCount = StreamHelper.ReadUInt32(stream);
            bytesRead += 4;

            this.ServerDNArray = new string[this.ServerDNCount];
            for (int i = 0; i < this.ServerDNCount; i++)
            {
                this.ServerDNArray[i] = StreamHelper.ReadString8(stream);
            }

            AdapterHelper.Site.Assert.AreEqual(this.ServerDNArray.Length, (int)this.ServerDNCount, "The deserialized serverDN count is not equal to the original server DN count. The expected value of the deserialized server DN is {0}, but the actual value is {1}.", this.ServerDNCount, this.ServerDNArray.Length);

            bytesRead += Common.GetBytesFromMutiUnicodeString(this.ServerDNArray).Length;
            return bytesRead;
        }
        /// <summary>
        /// Read a LongTermId from a stream
        /// and advances the position within the stream by 24.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <returns>The number of bytes read from the stream.</returns>
        public static LongTermId ReadLongTermId(Stream stream)
        {
            LongTermId id = new LongTermId();
            id.DatabaseGuid = StreamHelper.ReadGuid(stream).ToByteArray();

            id.GlobalCounter = new byte[6];
            stream.Read(id.GlobalCounter, 0, 6);
            stream.Read(new byte[2], 0, 2);
            return id;
        }
 /// <summary>
 /// Write  a LongTermId value to a stream
 /// and advances the position within the stream by 24.
 /// </summary>
 /// <param name="stream">The stream.</param>
 /// <param name="id">A LongTermId value.</param>
 /// <returns>The number of bytes written to the stream.</returns>
 public static int WriteLongTermId(Stream stream, LongTermId id)
 { 
     int size = 0;
     size += StreamHelper.WriteGuid(stream, new Guid(id.DatabaseGuid));
     size += StreamHelper.WriteBuffer(stream, id.GlobalCounter);
     size += StreamHelper.WriteBuffer(stream, new byte[2] { 0x00, 0x00 });
     return size;
 }
 /// <summary>
 /// Get the object ID form specified LongTermId.
 /// </summary>
 /// <param name="longTermID">The specified LongTermID.</param>
 /// <param name="logonHandle">The logon handle.</param>
 /// <returns>Return the object ID that mapping with specified LongTermID.</returns>
 protected ulong GetObjectIdFormLongTermID(LongTermId longTermID, uint logonHandle)
 {
     RopIdFromLongTermIdRequest ropIdFromLongTermIdRequest = new RopIdFromLongTermIdRequest()
     {
         RopId = (byte)RopId.RopIdFromLongTermId,
         LogonId = CommonLogonId,
         InputHandleIndex = CommonInputHandleIndex,
         LongTermId = longTermID,
     };
     this.ResponseSOHs = this.MSOXCMSGAdapter.DoRopCall(ropIdFromLongTermIdRequest, logonHandle, ref this.response, ref this.rawData, GetPropertiesFlags.None);
     RopIdFromLongTermIdResponse ropIdFromLongTermIdResponse = (RopIdFromLongTermIdResponse)this.response;
     Site.Assert.AreEqual<uint>(TestSuiteBase.Success, ropIdFromLongTermIdResponse.ReturnValue, "Call RopIdFromLongTermId should be success.");
     return ropIdFromLongTermIdResponse.ObjectId;
 }