/// <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."); }