/// <summary>
        /// Parses a response with multiple ROPs. In this scenario, the response is designed as only containing two ROPs: RopSetColumn and RopQueryRows.
        /// </summary>
        /// <param name="rgbOutput">The raw data that contains the ROP response payload</param>
        /// <returns>The ROP response list which contains RopSetColumnResponse and RopQueryRawResponse</returns>
        private List<IDeserializable> ParseMultipleRopsResponse(byte[] rgbOutput)
        {
            int parseByteLength = 0;
            List<IDeserializable> multipleRopsResponse = new List<IDeserializable>();
            RPC_HEADER_EXT rpcHeader = new RPC_HEADER_EXT
            {
                Version = BitConverter.ToUInt16(rgbOutput, parseByteLength)
            };

            // Parse RPC_HEADER_EXT structure
            parseByteLength += sizeof(short);
            rpcHeader.Flags = BitConverter.ToUInt16(rgbOutput, parseByteLength);
            parseByteLength += sizeof(short);
            rpcHeader.Size = BitConverter.ToUInt16(rgbOutput, parseByteLength);
            parseByteLength += sizeof(short);
            rpcHeader.SizeActual = BitConverter.ToUInt16(rgbOutput, parseByteLength);
            parseByteLength += sizeof(short);

            // Passed 2 bytes which is size of ROP response.
            parseByteLength += sizeof(short);

            // Parse RopSetColumns response
            RopSetColumnsResponse setColumnsResponse = new RopSetColumnsResponse();
            parseByteLength += setColumnsResponse.Deserialize(rgbOutput, parseByteLength);

            // Parse RopQueryRows response
            RopQueryRowsResponse queryRowsResponse = new RopQueryRowsResponse();
            parseByteLength += queryRowsResponse.Deserialize(rgbOutput, parseByteLength);

            multipleRopsResponse.Add(setColumnsResponse);
            multipleRopsResponse.Add(queryRowsResponse);

            return multipleRopsResponse;
        }
        /// <summary>
        /// Verify RopSetColumns Failure Response
        /// </summary>
        /// <param name="ropSetColumnsResponse">The failure response of RopSetColumns request</param>
        /// <param name="inputHandleIndex">The field of InputHandleIndex in RopSetColumns request</param>
        private void VerifyRopSetColumnsFailureResponse(RopSetColumnsResponse ropSetColumnsResponse, byte inputHandleIndex)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1074");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1074
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropSetColumnsResponse.RopId.GetType(),
                1074,
                @"[In RopSetColumns ROP Failure Response Buffer] RopId (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1076
            Site.CaptureRequirementIfAreEqual<byte>(
                (byte)RopId.RopSetColumns,
                ropSetColumnsResponse.RopId,
                1076,
                @"[In RopSetColumns ROP Failure Response Buffer] RopId (1 byte): For this operation[RopSetColumns], this field[RopId (1 byte)] is set to 0x12.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1077
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropSetColumnsResponse.InputHandleIndex.GetType(),
                1077,
                @"[In RopSetColumns ROP Failure Response Buffer] InputHandleIndex (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1078
            Site.CaptureRequirementIfAreEqual<byte>(
                inputHandleIndex,
                ropSetColumnsResponse.InputHandleIndex,
                1078,
                @"[In RopSetColumns ROP Failure Response Buffer] InputHandleIndex (1 byte): This index MUST be set to the value specified in the InputHandleIndex field in the request.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1079
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(uint),
                ropSetColumnsResponse.ReturnValue.GetType(),
                1079,
                @"[In RopSetColumns ROP Failure Response Buffer] ReturnValue (4 bytes): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1081
            Site.CaptureRequirementIfAreNotEqual<uint>(
                SuccessReturnValue,
                ropSetColumnsResponse.ReturnValue,
                1081,
                @"[In RopSetColumns ROP Failure Response Buffer] ReturnValue (4 bytes): For this response[Failure Response], this field is set to a value other than 0x00000000.");
        }
        /// <summary>
        /// Verify RopSetColumns Response
        /// </summary>
        /// <param name="setColumnsResponse">RopSetColumnsResponse structure data that needs verification</param>
        private void VerifyRopSetColumnsResponse(RopSetColumnsResponse setColumnsResponse)
        {
            this.VerifyRPCLayerRequirement();

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

            // Verify MS-OXCTABL requirement: MS-OXCTABL_R54
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                setColumnsResponse.TableStatus.GetType(),
                54,
                @"[In RopSetColumns ROP Response Buffer] TableStatus (1 byte): An enumeration that indicates the status of asynchronous operations being performed on the table.<4>");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R55: the current table status is {0}", setColumnsResponse.TableStatus);

            // Verify MS-OXCTABL requirement: MS-OXCTABL_R55
            bool isVerifyR55 = (setColumnsResponse.TableStatus == 0x00) ||
                               (setColumnsResponse.TableStatus == 0x09) ||
                               (setColumnsResponse.TableStatus == 0x0A) ||
                               (setColumnsResponse.TableStatus == 0x0B) ||
                               (setColumnsResponse.TableStatus == 0x0D) ||
                               (setColumnsResponse.TableStatus == 0x0E) ||
                               (setColumnsResponse.TableStatus == 0x0F);

            Site.CaptureRequirementIfIsTrue(
                isVerifyR55,
                55,
                @"[In RopSetColumns ROP Response Buffer] It [TableStatus] MUST have one of the table status values [0x00,0x09,0x0A,0x0B,0x0D,0x0E,0x0F] that are specified in section 2.2.2.1.3.");

            // Table Status is TBLSTAT_COMPLETE with value 0x00 means no operations are in progress.
            if ((TableRopReturnValues)setColumnsResponse.ReturnValue == TableRopReturnValues.success && !this.globalIsSetColumnsAsynchronous)
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R33");

                // Verify MS-OXCTABL requirement: MS-OXCTABL_R33
                Site.CaptureRequirementIfAreEqual(
                    0x00,
                    setColumnsResponse.TableStatus,
                    33,
                    @"[In TableStatus] When the Table Status is TBLSTAT_COMPLETE with value 0x00 means no operations are in progress.");

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

                // Verify MS-OXCTABL requirement: MS-OXCTABL_R43
                Site.CaptureRequirementIfAreEqual(
                    0x00,
                    setColumnsResponse.TableStatus,
                    43,
                    @"[In Asynchronous Flags] When TBL_ASYNC value is 0x00,the server will perform the operation synchronously.");
            }

            if (this.globalIsSetColumnsAsynchronous)
            {
                if (Common.IsRequirementEnabled(817, this.Site))
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R817");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R817
                    Site.CaptureRequirementIfAreEqual(
                        0x0B,
                        setColumnsResponse.TableStatus,
                        817,
                        @"[In Appendix A: Product Behavior] When the Table Status returned by the implementation is TBLSTAT_SETTING_COLS with value 0x0B, it means that a RopSetColumns ROP is in progress. (Microsoft Exchange Server 2007 follows this behavior.)");
                }

                if (Common.IsRequirementEnabled(42, this.Site))
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R42");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R42
                    Site.CaptureRequirementIfAreEqual(
                        0x0B,
                        setColumnsResponse.TableStatus,
                        42,
                        @"[In Appendix A: Product Behavior] When TBL_ASYNC value is 0x01,the implementation performs the ROP asynchronously. (Microsoft Exchange Server 2007 follows this behavior.)");
                }

                // The requirement 812 can not be verified in the environments that cannot support asynchronous.
                if (Common.IsRequirementEnabled(812, this.Site))
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R812");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R812
                    Site.CaptureRequirementIfAreEqual(
                        0x00,
                        setColumnsResponse.TableStatus,
                        812,
                        @"[In Appendix A: Product Behavior] If the implementation does not honor requests to perform operations asynchronously, it will return Table Status ""TBLSTAT_COMPLETE"" with value 0x00 when asynchronous flags is set to 0x01. (Microsoft Exchange Server 2010 and above follow this behavior.)");
                }

                // If the client requests that the server perform a RopSetColumns ROP request asynchronously, the server does not perform the operation synchronously and return "TBLSTAT_COMPLETE" in the TableStatus field of the ROP response buffer
                if (Common.IsRequirementEnabled(795, this.Site))
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R795");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R795
                    Site.CaptureRequirementIfAreNotEqual(
                        0x00,
                        setColumnsResponse.TableStatus,
                        795,
                        @"[In Appendix A: Product Behavior] If the client requests that the implementation perform a RopSetColumns ([MS-OXCROPS] section 2.2.5.1) ROP request asynchronously, it does not perform the operation synchronously and not return ""TBLSTAT_COMPLETE"" in the TableStatus field of the ROP response buffer. (Microsoft Exchange Server 2007 follows this behavior.)");
                }

                // If the client requests that the server perform a RopSetColumns ([MS-OXCROPS] section 2.2.5.1) ROP request asynchronously, the server does perform the operation synchronously and return "TBLSTAT_COMPLETE" in the TableStatus field of the ROP response buffer
                if (Common.IsRequirementEnabled(796, this.Site))
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R796");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R796
                    Site.CaptureRequirementIfAreEqual(
                        0x00,
                        setColumnsResponse.TableStatus,
                        796,
                        @"[In Appendix A: Product Behavior] If the client requests that the implementation perform a RopSetColumns ([MS-OXCROPS] section 2.2.5.1) ROP request asynchronously, it does perform the operation synchronously and return ""TBLSTAT_COMPLETE"" in the TableStatus field of the ROP response buffer. ( <20> Section 3.2.5.1: Exchange 2010, Exchange 2013, and Exchange 2016 do not support asynchronous operations on tables and ignore the TABL_ASYNC flags, as described in section 2.2.2.1.4.)");
                }

                // If the TBL_ASYNC bit of the SetColumnsFlags field is set, the server can execute the ROP as a table-asynchronous ROP
                // In asynchronous ROP, the TableStatus field in response is not TBLSTAT_COMPLETE.
                if (Common.IsRequirementEnabled(793, this.Site))
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R793");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R793
                    Site.CaptureRequirementIfAreNotEqual(
                        0x00,
                        setColumnsResponse.TableStatus,
                        793,
                        @"[In Appendix A: Product Behavior] If the TBL_ASYNC bit of the SetColumnsFlags field is set, the implementation can execute the ROP as a table-asynchronous ROP, as specified in section 3.2.5.1. (Microsoft Exchange Server 2007 follows this behavior.)");
                }

                if (Common.IsRequirementEnabled(770, this.Site))
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R770");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R770
                    Site.CaptureRequirementIfAreEqual(
                        0x00,
                        setColumnsResponse.TableStatus,
                        770,
                        @"[In Appendix A: Product Behavior] Implementation does return Table Status ""TBLSTAT_COMPLETE"" with value 0x00 when asynchronous flags is set to 0x01 in a RopSetColumns ROP on tables. (<3> Section 2.2.2.2.1: Exchange 2010, Exchange 2013, and Exchange 2016 will return Table Status ""TBLSTAT_COMPLETE"" with value 0x00 when asynchronous flags is set to 0x01 in a RopSetColumns ROP on tables.)");
                }

                // Here it can partially verify MS-OXCTABL requirement: MS-OXCTABL_418
                // if the server executes the ROP asynchronously, the server return "TBLSTAT_SETTING_COLS" in the TableStatus field of the ROP response buffer and do the work asynchronously.
                if (Common.IsRequirementEnabled(418, this.Site))
                {
                    // Add the debug information
                    Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCTABL_R418");

                    // Verify MS-OXCTABL requirement: MS-OXCTABL_R418
                    Site.CaptureRequirementIfAreEqual(
                        0x0B,
                        setColumnsResponse.TableStatus,
                        418,
                        @"[In Appendix A: Product Behavior] However, if the implementation executes the ROP asynchronously, it return ""TBLSTAT_SORTING"", ""TBLSTAT_SETTING_COLS"", or ""TBLSTAT_RESTRICTING"" (depending on the ROP performed) in the TableStatus field of the ROP response buffer and do the work asynchronously. (Microsoft Exchange Server 2007 follows this behavior.)");
                }
            }
        }
        /// <summary>
        /// Verify RopSetColumns Success Response
        /// </summary>
        /// <param name="ropSetColumnsResponse">The success response of RopSetColumns request</param>
        /// <param name="inputHandleIndex">The field of InputHandleIndex in RopSetColumns request</param>
        private void VerifyRopSetColumnsSuccessResponse(RopSetColumnsResponse ropSetColumnsResponse, byte inputHandleIndex)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1063");

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1063
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropSetColumnsResponse.RopId.GetType(),
                1063,
                @"[In RopSetColumns ROP Success Response Buffer] RopId (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1065
            Site.CaptureRequirementIfAreEqual<byte>(
                (byte)RopId.RopSetColumns,
                ropSetColumnsResponse.RopId,
                1065,
                @"[In RopSetColumns ROP Success Response Buffer] RopId (1 byte): For this operation[RopSetColumns], this field[RopId (1 byte)] is set to 0x12.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1066
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropSetColumnsResponse.InputHandleIndex.GetType(),
                1066,
                @"[In RopSetColumns ROP Success Response Buffer] InputHandleIndex (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1067
            Site.CaptureRequirementIfAreEqual<byte>(
                inputHandleIndex,
                ropSetColumnsResponse.InputHandleIndex,
                1067,
                @"[In RopSetColumns ROP Success Response Buffer] InputHandleIndex (1 byte): This index MUST be set to the value specified in the InputHandleIndex field in the request.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1068
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(uint),
                ropSetColumnsResponse.ReturnValue.GetType(),
                1068,
                @"[In RopSetColumns ROP Success Response Buffer] ReturnValue (4 bytes): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1070
            Site.CaptureRequirementIfAreEqual<uint>(
                SuccessReturnValue,
                ropSetColumnsResponse.ReturnValue,
                1070,
                @"[In RopSetColumns ROP Success Response Buffer] ReturnValue (4 bytes): For this response[Success Response], this field is set to 0x00000000.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1071
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropSetColumnsResponse.TableStatus.GetType(),
                1071,
                @"[In RopSetColumns ROP Success Response Buffer] TableStatus (1 byte): An enumeration.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R1072,TableStatus:{0}", ropSetColumnsResponse.TableStatus);

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R1072
            bool isVerifyR1072 = ((ropSetColumnsResponse.TableStatus & ((byte)TableStatus.TblstatComplete)) == ((byte)TableStatus.TblstatComplete))
                                 || ((ropSetColumnsResponse.TableStatus & ((byte)TableStatus.TblstatSorting)) == ((byte)TableStatus.TblstatSorting))
                                 || ((ropSetColumnsResponse.TableStatus & ((byte)TableStatus.TblstatSortError)) == ((byte)TableStatus.TblstatSortError))
                                 || ((ropSetColumnsResponse.TableStatus & ((byte)TableStatus.TblstatSettingCols)) == ((byte)TableStatus.TblstatSettingCols))
                                 || ((ropSetColumnsResponse.TableStatus & ((byte)TableStatus.TblstatSetColError)) == ((byte)TableStatus.TblstatSetColError))
                                 || ((ropSetColumnsResponse.TableStatus & ((byte)TableStatus.TblstatRestricting)) == ((byte)TableStatus.TblstatRestricting))
                                 || ((ropSetColumnsResponse.TableStatus & ((byte)TableStatus.TblstatRestrictError)) == ((byte)TableStatus.TblstatRestrictError));

            Site.CaptureRequirementIfIsTrue(
                isVerifyR1072,
                1072,
                @"[In RopSetColumns ROP Success Response Buffer] TableStatus (1 byte): The possible values[the value of TBLSTAT_COMPLETE is 0x00, the value of TBLSTAT_SORTING is 0x09, the value of TBLSTAT_SORT_ERROR is 0x0A, the value of TBLSTAT_SETTING_COLS is 0x0B, the value of TBLSTAT_SETCOL_ERROR is 0x0D, the value of TBLSTAT_RESTRICTING is 0x0E and the value of TBLSTAT_RESTRICT_ERROR is 0x0F] for this enumeration are specified in [MS-OXCTABL] section 2.2.2.1.3.");
        }