public static void RopResetTableResponse(TableRopType ropType, bool isPreviousDataReset)
        {
            if (isPreviousDataReset)
            {
                switch (ropType)
                {
                    // The previous restriction is reset
                    case TableRopType.RESTRICT:
                        {
                            ModelHelper.CaptureRequirement(555, @"[In Processing RopResetTable] The RopResetTable ROP MUST remove the restriction previously applied to the table using RopRestrict ROP ([MS-OXCROPS] section 2.2.5.3) (if any).");
                            ModelHelper.CaptureRequirement(556, @"[In Processing RopResetTable] The table MUST afterwards appear as if the RopRestrict ROP had never been sent on it; that is, as if it had no restriction (all rows MUST be present).");
                            break;
                        }

                    // The cursor position is reset
                    case TableRopType.MOVECURSOR:
                        {
                            ModelHelper.CaptureRequirement(561, @"[In Processing RopResetTable] The RopResetTable ROP MUST move the cursor to the beginning of the table.");
                            break;
                        }

                    // The created bookmark is invalidated
                    case TableRopType.CREATEBOOKMARK:
                        {
                            break;
                        }

                    default:
                        break;
                }
            }
        }
        public static void RopQueryRowsResponse(QueryRowsFlags queryRowFlags, bool isForwardRead, bool isZeroRow, TableRopType ropType, bool isCorrectRowCount, bool isCursorPositionChanged, bool isLatestRopData, bool isLastSuccessRopData, BookmarkType queryRowOrigin, bool isRequestCountTooLarger)
        {
            // If the NoAdvance flag (0x01) is set in the QueryRowsFlags field, the server MUST NOT change the position of the cursor.
            if (queryRowFlags == QueryRowsFlags.NoAdvance)
            {
                Condition.IsTrue(!isCursorPositionChanged);
                ModelHelper.CaptureRequirement(470, @"[In Processing RopQueryRows] If the NoAdvance flag (0x01) is set in the QueryRowsFlags field, the server MUST NOT change the position of the cursor.");
                if (queryRowOrigin == BookmarkType.BOOKMARK_BEGINNING)
                {
                    ModelHelper.CaptureRequirement(27, @"[In Predefined Bookmarks] When the Predefined Bookmarks is BOOKMARK_BEGINNING with value 0x00 means points to the beginning position of the table, or the first row.");
                }
            }

            // Test RopSetColumns MUST be sent on the table prior to sending RopQueryRows
            bool latestSetColumnFlag = false;
            setColumnsFlags.TryGetValue((uint)setColumnsFlags.Count, out latestSetColumnFlag);
            if (latestSetColumnFlag)
            {
                Condition.IsTrue(isCorrectRowCount);

                // If the ForwardRead field is TRUE, RopQueryRows MUST return the rows beginning at the origin, reading forward.
                if (isForwardRead)
                {
                    // In the Test Suite, the origin is beginning, and if the enough row is true, 
                    // the RowCount rows will be queried from table. Also, here it only verify whether the correct row count 
                    // is returned, because for the details of the table row, it can't be verified.
                    ModelHelper.CaptureRequirement(468, @"[In Processing RopQueryRows] If rows are returned by the RopQueryRows ROP and the ForwardRead field is set to ""TRUE"" (0x01), the RopQueryRows ROP returns the rows beginning at the position pointed to by the Origin field, reading forward.");
                }
                else
                { 
                    Condition.IsTrue((requirementContainer[896] && !requirementContainer[897]) || (!requirementContainer[896] && requirementContainer[897]));

                    // if there are no more rows to return and the ForwardRead field in the ROP request is set to "false",
                    // Exchange 2007 will set the Origin field to "BOOKMARK_BEGINNING".
                    if (requirementContainer[896] && isRequestCountTooLarger)
                    {
                        Condition.IsTrue(queryRowOrigin == BookmarkType.BOOKMARK_BEGINNING);
                        ModelHelper.CaptureRequirement(896, @"[In Appendix A: Product Behavior] Implementation does set the Origin field to ""BOOKMARK_BEGINNING"", if there are no more rows to return and the ForwardRead field in the ROP request is set to ""FALSE"". (Exchange Server 2007 follows this behavior.)");
                    }

                    // if there are no more rows to return and the ForwardRead field in the ROP request is set to "false",
                    // Exchange 2010 and above will set the Origin field to "BOOKMARK_END".
                    if (requirementContainer[897] && isRequestCountTooLarger)
                    {
                        Condition.IsTrue(queryRowOrigin == BookmarkType.BOOKMARK_END);
                        ModelHelper.CaptureRequirement(897, @"[In Appendix A: Product Behavior] Implementation does set the Origin field to ""BOOKMARK_END"", if there are no more rows to return and the ForwardRead field in the ROP request is set to ""FALSE"". (<25> Section 3.2.5.5: Exchange 2010, Exchange 2013, and Exchange 2016 set the Origin field to ""BOOKMARK_END"".)");
                    }

                    // When ForwardRead in request is false, if the correct row count is returned, this requirement can be verified.
                    ModelHelper.CaptureRequirement(469, @"[In Processing RopQueryRows] If it [ForeardRead] is set to ""FALSE"" (0x00), the server returns the rows starting at the number of rows equal to the value of the RowCount field before the position pointed to by the Origin field, such that the rows returned are those between the value of the Origin field minus the value of the RowCount field and the position pointed to by the Origin field.");
                }

                // If the RopRestrict ROP has not been issued, the RowData field MUST include all rows.
                bool isLastestRestrictFlags = false;
                restrictFlags.TryGetValue((uint)restrictFlags.Count, out isLastestRestrictFlags);
                
                if (!isLastestRestrictFlags)
                {
                    ModelHelper.CaptureRequirement(118, @"[In RopQueryRows ROP Response Buffer] If the RopRestrict ROP has not been issued, the RowData field MUST include all rows.");
                }

                // When correct row count is returned and the returned row count is zero, the R467 is verified. 
                if (isZeroRow)
                {
                    ModelHelper.CaptureRequirement(467, @"[In Processing RopQueryRows] This ROP MUST only send zero rows when there are no more rows in the table.");
                }
            }

            ModelHelper.CaptureRequirement(462, @"[In Processing RopQueryRows] When a RopQueryRows ROP request ([MS-OXCROPS] section 2.2.5.4) is sent, the server MUST send the rows from the table starting at the current cursor position.");

            // If there are no more rows to return, the Origin field will be set to BOOKMARK_END if the ForwardRead field in the ROP request is set to true.
            if (isCursorPositionChanged && isForwardRead && queryRowOrigin == BookmarkType.BOOKMARK_END)
            {
                ModelHelper.CaptureRequirement(29, @"[In Predefined Bookmarks] When the Predefined Bookmarks is BOOKMARK_END with value 0x02 means points to the ending position of the table, or the location after the last row.");
                ModelHelper.CaptureRequirement(725, @"[In Processing RopQueryRows] If there are no more rows to return and the ForwardRead field in the ROP request is set to ""TRUE"", then the Origin field is set to ""BOOKMARK_END"".");
            }

            if (!isRequestCountTooLarger && isForwardRead && isCursorPositionChanged)
            {
                Condition.IsTrue(queryRowOrigin == BookmarkType.BOOKMARK_CURRENT);
                ModelHelper.CaptureRequirement(28, @"[In Predefined Bookmarks] When the Predefined Bookmarks is BOOKMARK_CURRENT with value 0x01 means points to the current position of the table, or the current row.");
                ModelHelper.CaptureRequirement(726, @"[In Processing RopQueryRows] Otherwise,[If there are more rows to return] it [Origin] will be set to ""BOOKMARK_CURRENT"".");
            }

            // Below is to parse the data queried
            switch (ropType)
            {
                // Query rows is called after a SetColumn request
                case TableRopType.SETCOLUMNS:
                    {
                        ParseQueryRowsAfterSetColumns(isLatestRopData, isLastSuccessRopData);
                        break;
                    }

                // Query rows is called after sort table request
                case TableRopType.SORTTABLE:
                    {
                        ParseQueryRowsAfterSortTable(isLatestRopData, isLastSuccessRopData);
                        break;
                    }

                // Query rows is called after restrict table request
                case TableRopType.RESTRICT:
                    {
                        ParseQueryRowsAfterRestrict(isLatestRopData, isLastSuccessRopData);
                        break;
                    }

                // If no above operation, query rows must return all rows, the parameter bIsLatestRopData is used to identify whether all row data is returned
                default:
                    {
                        break;
                    }
            }
        }
        /// <summary>
        /// This method is used to seek row for a table
        /// </summary>
        /// <param name="origin">Identify the origin position</param>
        /// <param name="forwardSeek">Identify whether to seek row forward</param>
        /// <param name="wantRowMovedCountout">Identify whether to return the actual moved row number</param>
        /// <param name="enoughRow">Identify whether there is enough row to seek</param>
        /// <returns>Table ROP return value</returns>
        public TableRopReturnValues RopSeekRow(BookmarkType origin, bool forwardSeek, bool wantRowMovedCountout, bool enoughRow)
        {
            uint tempRowCount = this.GetRowsCount(forwardSeek); // Gets the number of rows from current location to begin row or last row.

            RopSeekRowRequest seekRowRequest = new RopSeekRowRequest();
            RopSeekRowResponse seekRowResponse;

            seekRowRequest.RopId = 0x18;
            seekRowRequest.LogonId = 0x00;
            seekRowRequest.InputHandleIndex = 0x00;
            seekRowRequest.Origin = (byte)origin;

            if (origin == BookmarkType.BOOKMARK_BEGINNING)
            {
                if (forwardSeek)
                {
                    if (enoughRow)
                    {
                        seekRowRequest.RowCount = (int)this.rowCount;
                    }
                    else
                    {
                        // Identify there is not enough row to forward seek.
                        seekRowRequest.RowCount = (int)(this.rowCount + 1);
                    }
                }
                else
                {
                    if (enoughRow)
                    {
                        seekRowRequest.RowCount = 0;
                    }
                    else
                    {
                        seekRowRequest.RowCount = -1; // Identify there is not enough row to backward seek when the location is beginning.
                    }
                }
            }
            else if (origin == BookmarkType.BOOKMARK_END)
            {
                if (forwardSeek)
                {
                    if (enoughRow)
                    {
                        seekRowRequest.RowCount = 0;
                    }
                    else
                    {
                        seekRowRequest.RowCount = 1;
                    }
                }
                else
                {
                    if (enoughRow)
                    {
                        seekRowRequest.RowCount = -(int)this.rowCount;
                    }
                    else
                    {
                        seekRowRequest.RowCount = -(int)(this.rowCount + 1);
                    }
                }
            }
            else
            {
                if (forwardSeek)
                {
                    if (enoughRow)
                    {
                        seekRowRequest.RowCount = (int)tempRowCount;
                    }
                    else
                    {
                        seekRowRequest.RowCount = (int)(tempRowCount + 1);
                    }
                }
                else
                {
                    if (enoughRow)
                    {
                        seekRowRequest.RowCount = -(int)tempRowCount;
                    }
                    else
                    {
                        seekRowRequest.RowCount = -(int)(tempRowCount + 1);
                    }
                }
            }

            seekRowRequest.WantRowMovedCount = Convert.ToByte(wantRowMovedCountout);

            this.rowCountInSeekRowRequest = seekRowRequest.RowCount;

            this.DoSingleCallROP(seekRowRequest, this.tableHandle, ref this.response, ref this.rawData);
            seekRowResponse = (RopSeekRowResponse)this.response;

            this.ropType = TableRopType.MOVECURSOR;
            bool hasSoughtLess = false;
            bool isActualRowsCount = false;
            if (wantRowMovedCountout)
            {
                hasSoughtLess = Convert.ToBoolean(seekRowResponse.HasSoughtLess);
                if (origin == BookmarkType.BOOKMARK_BEGINNING)
                {
                    if (forwardSeek)
                    {
                        isActualRowsCount = seekRowResponse.RowsSought == this.rowCount;
                    }
                    else
                    {
                        isActualRowsCount = seekRowResponse.RowsSought == 0;
                    }
                }

                if (origin == BookmarkType.BOOKMARK_END)
                {
                    if (forwardSeek)
                    {
                        isActualRowsCount = seekRowResponse.RowsSought == 0;
                    }
                    else
                    {
                        isActualRowsCount = seekRowResponse.RowsSought == -this.rowCount;
                    }
                }

                if (origin == BookmarkType.BOOKMARK_CURRENT)
                {
                    isActualRowsCount = System.Math.Abs(seekRowResponse.RowsSought) == tempRowCount;
                }
            }
            else
            {
                hasSoughtLess = true;
                isActualRowsCount = true;
            }

            if (this.RopSeekRowResponse != null)
            {
                this.RopSeekRowResponse(wantRowMovedCountout, enoughRow, hasSoughtLess, isActualRowsCount);
            }

            return (TableRopReturnValues)seekRowResponse.ReturnValue;
        }
        /// <summary>
        /// This method is used to restrict for a table
        /// </summary>
        /// <param name="reqId">Identify the request ID</param>
        /// <param name="validHandle">Identify whether the InputHandleIndex is valid, this is used to trigger the error code in Restrict</param>
        /// <param name="newRestrict">A identify whether new restriction is required</param>
        /// <param name="isRestrictAsynchronous">Indicate whether RopRestrict Rop is to be performed asynchronously</param>
        /// <returns>Table ROP return value</returns>
        public TableRopReturnValues RopRestrict(uint reqId, bool validHandle, bool newRestrict, bool isRestrictAsynchronous)
        {
            RopRestrictRequest restrictRequest;
            RopRestrictResponse restrictResponse;

            restrictRequest.RopId = 0x14;
            restrictRequest.LogonId = 0x00;
            restrictRequest.InputHandleIndex = (byte)0x00; 
            if (isRestrictAsynchronous)
            {
                restrictRequest.RestrictFlags = 0x01; // Async
            }
            else
            {
                restrictRequest.RestrictFlags = 0x00; // Sync
            }

            this.globalIsRestrictAsynchronous = isRestrictAsynchronous;
            byte[] data;
            if (this.tableType == TableType.CONTENT_TABLE)
            {
                if (!newRestrict && this.sign)
                {
                    byte[] tempData = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("Sender1Name", this.Site) + "\0");
                    data = new byte[tempData.Length + 13];
                    int index = 0;
                    data[index++] = 0x03;
                    data[index++] = 0x02;
                    data[index++] = 0x00;
                    data[index++] = 0x04;
                    data[index++] = 0x00;
                    data[index++] = 0x1f;
                    data[index++] = 0x00;
                    data[index++] = 0x1a;
                    data[index++] = 0x0c;
                    data[index++] = 0x1f;
                    data[index++] = 0x00;
                    data[index++] = 0x1a;
                    data[index++] = 0x0c;
                    Array.Copy(tempData, 0, data, index, tempData.Length);

                    this.latestRestrict = RestrictFlag.SenderIsTest1Restrict;
                }
                else
                {
                    byte[] tempData = Encoding.Unicode.GetBytes(Common.GetConfigurationPropertyValue("Sender2Name", this.Site) + "\0");
                    data = new byte[tempData.Length + 13];
                    int index = 0;
                    data[index++] = 0x03;
                    data[index++] = 0x02;
                    data[index++] = 0x00;
                    data[index++] = 0x04;
                    data[index++] = 0x00;
                    data[index++] = 0x1f;
                    data[index++] = 0x00;
                    data[index++] = 0x1a;
                    data[index++] = 0x0c;
                    data[index++] = 0x1f;
                    data[index++] = 0x00;
                    data[index++] = 0x1a;
                    data[index++] = 0x0c;
                    Array.Copy(tempData, 0, data, index, tempData.Length);

                    this.latestRestrict = RestrictFlag.SenderIsTest2Restriction;
                }

                this.sign = this.sign == !newRestrict;
            }
            else if (this.tableType == TableType.HIERARCHY_TABLE || this.tableType == TableType.RULES_TABLE)
            {
                data = AdapterHelper.GenerateValidRestrictData(this.Site, this.tableType);
            }
            else
            {
                data = null;
            }

            restrictRequest.RestrictionDataSize = data == null ? (ushort)0 : (ushort)data.Length;
            restrictRequest.RestrictionData = data;

            uint inputObjHandle;
            if (validHandle)
            {
                inputObjHandle = this.tableHandle;
            }
            else
            {
                inputObjHandle = 0xFFFFFFFF; // Cause the request failed when set to invalid handle
            }

            this.DoSingleCallROP(restrictRequest, inputObjHandle, ref this.response, ref this.rawData);
            restrictResponse = (RopRestrictResponse)this.response;

            this.ropType = TableRopType.RESTRICT;

            if ((TableRopReturnValues)restrictResponse.ReturnValue == TableRopReturnValues.success)
            {
                this.latestSuccessRestrict = this.latestRestrict;

                this.GetRowsCount(false);
            }

            // If the RopRestrict ROP is not complete (the returned TableStatus is set to 0x0E), wait for the RopGetStatus ROP to return TableStatus set 0x00 (which indicates the RopRestrict ROP is complete).
            if ((TableRopReturnValues)restrictResponse.ReturnValue == TableRopReturnValues.success && isRestrictAsynchronous && (TableStatus)restrictResponse.TableStatus == TableStatus.TblstatRestricting)
            {
                int getStatusRetryCount = int.Parse(Common.GetConfigurationPropertyValue("RetryCount", this.Site));
                RopGetStatusResponse getStatusResponse = new RopGetStatusResponse();
                while (getStatusRetryCount >= 0)
                {
                    Thread.Sleep(this.waitTime);
                    TableStatus tableStatus;
                    this.RopGetStatus(out tableStatus);
                    if (tableStatus == TableStatus.TblstatComplete)
                    {
                        break;
                    }

                    getStatusRetryCount--;
                }

                if (getStatusRetryCount < 0)
                {
                    Site.Assert.Fail("The RopRestrict ROP should complete!");
                }

                this.VerifyAsynchronousROPComplete(getStatusResponse);
            }

            return (TableRopReturnValues)restrictResponse.ReturnValue;
        }
        /// <summary>
        /// This method is used to sort table
        /// </summary>
        /// <param name="reqId">Identify the request ID</param>
        /// <param name="validHandle">Identify whether the InputHandleIndex is valid, this is used to trigger the error code in sort table</param>
        /// <param name="multipleSortOrders">Indicate whether the sort order array contains more than one SortOrder structure</param>
        /// <param name="isMaximumCategory">Indicate whether the sort order array contains a SortOrder structure with the order set to MaximumCategory</param>
        /// <param name="allSortOrdersUsedAsCategory">Identify whether all sort orders used as category</param>
        /// <param name="allCategoryExpanded">Identify whether all categories are expanded</param>
        /// <param name="newOrder">Identify whether to change the current sort order</param>
        /// <param name="isSortTableAsynchronous">Indicate whether RopSortTable Rop is to be performed asynchronously</param>
        /// <returns>Table ROP return value</returns>
        public TableRopReturnValues RopSortTable(uint reqId, bool validHandle, bool multipleSortOrders, bool isMaximumCategory, bool allSortOrdersUsedAsCategory, bool allCategoryExpanded, bool newOrder, bool isSortTableAsynchronous)
        {
            RopSortTableRequest sortTableRequest;
            RopSortTableResponse sortTableResponse;
            SortOrder[] sortOrders;

            if (!newOrder && this.sign)
            {
                sortOrders = this.CreateSampleSortOrdersAscending(multipleSortOrders, isMaximumCategory);
            }
            else
            {
                sortOrders = this.CreateSampleSortOrdersDescending(multipleSortOrders);
            }

            this.sign = this.sign == !newOrder;
            this.latestSortOrder = sortOrders[0].Order == 0x00 ? SortOrderFlag.SortOrderASC : SortOrderFlag.SortOrderDESC;
            sortTableRequest.RopId = 0x13;
            sortTableRequest.LogonId = 0x00;
            sortTableRequest.InputHandleIndex = (byte)0x00; 
            this.areAllSortOrdersUsedAsCategory = allSortOrdersUsedAsCategory;
            this.areAllCategoryExpanded = allCategoryExpanded;
            this.areMultipleSortOrders = multipleSortOrders;
            sortTableRequest.SortOrderCount = (ushort)sortOrders.Length;
            if (allSortOrdersUsedAsCategory)
            {
                sortTableRequest.CategoryCount = (ushort)sortOrders.Length;
                if (allCategoryExpanded)
                {
                    sortTableRequest.ExpandedCount = (ushort)sortOrders.Length; // All rows expanded
                }
                else
                {
                    sortTableRequest.ExpandedCount = (ushort)(sortOrders.Length - 1); // Not all rows expanded
                }
            }
            else
            {
                sortTableRequest.CategoryCount = (ushort)(sortOrders.Length - 1);
                if (allCategoryExpanded)
                {
                    sortTableRequest.ExpandedCount = (ushort)(sortOrders.Length - 1); // All rows expanded
                }
                else
                {
                    sortTableRequest.ExpandedCount = 0;
                }
            }

            sortTableRequest.SortOrders = sortOrders;
            if (isSortTableAsynchronous)
            {
                sortTableRequest.SortTableFlags = 0x01; // Async
            }
            else
            {
                sortTableRequest.SortTableFlags = 0x00; // Sync
            }

            uint inputObjHandle;
            if (validHandle)
            {
                inputObjHandle = this.tableHandle;
            }
            else
            {
                inputObjHandle = 0xFFFFFFFF; // Cause the request failed when set to invalid handle
            }

            this.globalIsSortTableAsynchronous = isSortTableAsynchronous;
            this.DoSingleCallROP(sortTableRequest, inputObjHandle, ref this.response, ref this.rawData);
            sortTableResponse = (RopSortTableResponse)this.response;

            this.ropType = TableRopType.SORTTABLE;

            if ((TableRopReturnValues)sortTableResponse.ReturnValue == TableRopReturnValues.success)
            {
                this.latestSuccessSortOrder = this.latestSortOrder;
                if (sortTableRequest.ExpandedCount != 0)
                {
                    this.isExpanded = true; // The first header row is expanded when the request succeeds.
                }

                this.GetRowsCount(false); // Update the field rowCount
            }

            // If the RopSortTable ROP is not complete (the returned TableStatus is set to 0x09), wait for the RopGetStatus ROP to return TableStatus set 0x00 (which indicates the RopSortTable ROP is complete).
            if ((TableRopReturnValues)sortTableResponse.ReturnValue == TableRopReturnValues.success && isSortTableAsynchronous && (TableStatus)sortTableResponse.TableStatus == TableStatus.TblstatSorting)
            {
                int getStatusRetryCount = int.Parse(Common.GetConfigurationPropertyValue("RetryCount", this.Site));
                RopGetStatusResponse getStatusResponse = new RopGetStatusResponse();
                while (getStatusRetryCount >= 0)
                {
                    Thread.Sleep(this.waitTime);
                    TableStatus tableStatus;
                    this.RopGetStatus(out tableStatus);
                    if (tableStatus == TableStatus.TblstatComplete)
                    {
                        break;
                    }

                    getStatusRetryCount--;
                }

                if (getStatusRetryCount < 0)
                {
                    Site.Assert.Fail("The RopSortTable ROP should complete!");
                }

                this.VerifyAsynchronousROPComplete(getStatusResponse);
            }

            return (TableRopReturnValues)sortTableResponse.ReturnValue;
        }
        /// <summary>
        /// This method is used to SetColumns for a table
        /// </summary>
        /// <param name="reqId">Identify the request ID</param>
        /// <param name="invalidPropertyTag">Indicate whether there are invalid property tags in the column set </param>
        /// <param name="newColumnSet">Indicate whether to change the current column set with new one</param>
        /// <param name="isSetColumnsAsynchronous">Indicate whether RopsetColumns Rop is to be performed asynchronously</param>
        /// <returns>Table ROP return value</returns>
        public TableRopReturnValues RopSetColumns(uint reqId, bool invalidPropertyTag, bool newColumnSet, bool isSetColumnsAsynchronous)
        {
            RopSetColumnsRequest setColumnsRequest;
            RopSetColumnsResponse setColumnsResponse;
            PropertyTag[] propertyTags;

            if (invalidPropertyTag)
            {
                propertyTags = this.CreateInvalidContentsTablePropertyTags();
            }
            else
            {
                switch (this.tableType)
                {
                    case TableType.CONTENT_TABLE:
                        if (!newColumnSet && this.sign)
                        {
                            propertyTags = this.CreateSampleContentsTablePropertyTags();
                        }
                        else
                        {
                            propertyTags = this.CreateSampleContentsTablePropertyTagsWithNoError();
                        }

                        break;
                    case TableType.HIERARCHY_TABLE:
                        propertyTags = this.CreateSampleHierarchyTablePropertyTags();
                        break;
                    case TableType.RULES_TABLE:
                        propertyTags = this.CreateRulesTablePropertyTags();
                        break;
                    default:
                        propertyTags = this.CreateSampleContentsTablePropertyTags();
                        break;
                }

                this.sign = this.sign == !newColumnSet;
            }

            setColumnsRequest.RopId = 0x12;
            setColumnsRequest.LogonId = 0x00;
            setColumnsRequest.InputHandleIndex = 0x00;
            setColumnsRequest.PropertyTagCount = (ushort)propertyTags.Length;
            setColumnsRequest.PropertyTags = propertyTags;
            if (isSetColumnsAsynchronous)
            {
                setColumnsRequest.SetColumnsFlags = 0x01; // Async
            }
            else
            {
                setColumnsRequest.SetColumnsFlags = 0x00; // Sync
            }

            this.globalIsSetColumnsAsynchronous = isSetColumnsAsynchronous;
            this.DoSingleCallROP(setColumnsRequest, this.tableHandle, ref this.response, ref this.rawData);
            setColumnsResponse = (RopSetColumnsResponse)this.response;

            this.ropType = TableRopType.SETCOLUMNS;
            this.latestPropertyTags = propertyTags;
            if ((TableRopReturnValues)setColumnsResponse.ReturnValue == TableRopReturnValues.success)
            {
                this.latestSuccessPropertyTages = propertyTags;
            }

            // If the RopSetColumns ROP is not complete (the returned TableStatus is set to 0x0B), wait for the RopGetStatus ROP to return TableStatus set 0x00 (which indicates the RopSetColumns ROP is complete).
            if ((TableRopReturnValues)setColumnsResponse.ReturnValue == TableRopReturnValues.success && isSetColumnsAsynchronous && (TableStatus)setColumnsResponse.TableStatus == TableStatus.TblstatSettingCols)
            {
                int getStatusRetryCount = int.Parse(Common.GetConfigurationPropertyValue("RetryCount", this.Site));
                RopGetStatusResponse getStatusResponse = new RopGetStatusResponse();
                while (getStatusRetryCount >= 0)
                {
                    Thread.Sleep(this.waitTime);
                    TableStatus tableStatus;
                    this.RopGetStatus(out tableStatus);
                    if (tableStatus == TableStatus.TblstatComplete)
                    {
                        break;
                    }

                    getStatusRetryCount--;
                }

                if (getStatusRetryCount < 0)
                {
                    Site.Assert.Fail("The RopSetColumns ROP should complete!");
                }

                this.VerifyAsynchronousROPComplete(getStatusResponse);
            }

            return (TableRopReturnValues)setColumnsResponse.ReturnValue;
        }
        /// <summary>
        /// This method is used to create bookmark for a table
        /// </summary>
        /// <returns>Table ROP return value</returns>
        public TableRopReturnValues RopCreateBookmark()
        {
            this.userDefinedBookmarkPosition = this.GetRowsCount(false);

            RopCreateBookmarkRequest createBookmarkRequest;
            RopCreateBookmarkResponse createBookmarkResponse;

            createBookmarkRequest.RopId = 0x1B;
            createBookmarkRequest.LogonId = 0x00;
            createBookmarkRequest.InputHandleIndex = 0x00;

            this.DoSingleCallROP(createBookmarkRequest, this.tableHandle, ref this.response, ref this.rawData);
            createBookmarkResponse = (RopCreateBookmarkResponse)this.response;

            this.ropType = TableRopType.CREATEBOOKMARK;
            this.userDefinedBookmark = createBookmarkResponse.Bookmark;
            this.userDefinedBookmarkSize = createBookmarkResponse.BookmarkSize;

            return (TableRopReturnValues)createBookmarkResponse.ReturnValue;
        }