Microsoft.Protocols.TestSuites.Common.RopLogonResponse.Deserialize C# (CSharp) Method

Deserialize() public method

Deserialize the ROP response buffer.
public Deserialize ( byte ropBytes, int startIndex ) : int
ropBytes byte ROPs bytes in response.
startIndex int The start index of this ROP.
return int
        public int Deserialize(byte[] ropBytes, int startIndex)
        {
            int index = startIndex;
            this.RopId = ropBytes[index++];
            this.OutputHandleIndex = ropBytes[index++];
            this.ReturnValue = (uint)BitConverter.ToInt32(ropBytes, index);
            index += sizeof(uint);

            // Only success response has below fields
            if (this.ReturnValue == 0)
            {
                this.LogonFlags = ropBytes[index++];
                if ((this.LogonFlags & (byte)TestSuites.Common.LogonFlags.Private) != 0x00)
                {
                    // The length of FolderIds is 13.
                    this.FolderIds = new ulong[13];
                    for (int i = 0; i < 13; i++)
                    {
                        this.FolderIds[i] = (ulong)BitConverter.ToInt64(ropBytes, index);
                        index += sizeof(ulong);
                    }

                    this.ResponseFlags = ropBytes[index++];

                    // Guid holds 16 bytes.
                    this.MailboxGuid = new byte[16];
                    Array.Copy(ropBytes, index, this.MailboxGuid, 0, 16);
                    index += 16;

                    // ReplId holds 16 bits.
                    this.ReplId = new byte[2];
                    Array.Copy(ropBytes, index, this.ReplId, 0, 2);
                    index += 2;

                    // ReplGuid holds 16 bytes.
                    this.ReplGuid = new byte[16];
                    Array.Copy(ropBytes, index, this.ReplGuid, 0, 16);
                    index += 16;
                    index += this.LogonTime.Deserialize(ropBytes, index);
                    this.GwartTime = (ulong)BitConverter.ToInt64(ropBytes, index);
                    index += sizeof(ulong);
                    this.StoreState = (uint)BitConverter.ToInt32(ropBytes, index);
                    index += sizeof(uint);
                }
                else
                {
                    // The length of FolderIds is 13.
                    this.FolderIds = new ulong[13];
                    for (int i = 0; i < 13; i++)
                    {
                        this.FolderIds[i] = (ulong)BitConverter.ToInt64(ropBytes, index);
                        index += sizeof(ulong);
                    }

                    // ReplId holds 16 bits.
                    this.ReplId = new byte[2];
                    Array.Copy(ropBytes, index, this.ReplId, 0, 2);
                    index += 2;

                    // ReplGuid holds 16 bytes.
                    this.ReplGuid = new byte[16];
                    Array.Copy(ropBytes, index, this.ReplGuid, 0, 16);
                    index += 16;

                    // PerUserGuid holds 16 bytes.
                    this.PerUserGuid = new byte[16];
                    Array.Copy(ropBytes, index, this.PerUserGuid, 0, 16);
                    index += 16;
                }
            }
            else if (this.ReturnValue == 0x00000478)
            {
                // Redirect response 0x00000478.
                this.LogonFlags = ropBytes[index++];
                this.ServerNameSize = ropBytes[index++];
                if (this.ServerNameSize > 0)
                {
                    this.ServerName = new byte[this.ServerNameSize];
                    Array.Copy(ropBytes, index, this.ServerName, 0, this.ServerNameSize);
                    index += this.ServerNameSize;
                }
            }

            return index - startIndex;
        }
    }    

Usage Example

        public void MSOXCMAPIHTTP_S01_TC08_ExecuteRequestType()
        {
            this.CheckMapiHttpIsSupported();
            WebHeaderCollection headers = new WebHeaderCollection();

            #region Send a valid Connect request type to establish a Session Context with the server.
            ConnectSuccessResponseBody connectResponse = this.ConnectToServer(out headers);
            Site.Assert.AreEqual<uint>(0, connectResponse.StatusCode, "The server should return a Status 0 in X-ResponseCode header if client connect to server succeeded.");
            #endregion

            #region Send an Execute request that includes Logon ROP to server.
            WebHeaderCollection executeHeaders = AdapterHelper.InitializeHTTPHeader(RequestType.Execute, AdapterHelper.ClientInstance, AdapterHelper.Counter);

            ExecuteRequestBody requestBody = this.InitializeExecuteRequestBody(this.GetRopLogonRequest());
            List<string> metaTags = new List<string>();
            ExecuteSuccessResponseBody executeSuccessResponse = this.SendExecuteRequest(requestBody, ref executeHeaders, out metaTags) as ExecuteSuccessResponseBody;

            #region Capture code
            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1134");

            // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1134
            // According to the Open Specification, the server must respond immediately to a request while the request is being queued and the initial response includes the PROCESSING meta-tag.
            // So MS-OXCMAPIHTTP_R1134 can be verified if the first meta-tag is PROCESSING.
            this.Site.CaptureRequirementIfAreEqual<string>(
                "PROCESSING",
                metaTags[0],
                1134,
                @"[In Response Meta-Tags] PROCESSING: The server has queued the request to be processed.");

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

            // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1136
            // According to the Open Specification, the final response must include the DONE meta-tag. And the response body is parsed according to the description of this requirement.
            // So if the last meta-tag is DONE and code can reach here, MS-OXCMAPIHTTP_R1136 can be verified.
            this.Site.CaptureRequirementIfAreEqual<string>(
                "DONE",
                metaTags[metaTags.Count - 1],
                1136,
                @"[In Response Meta-Tags] DONE: The server has completed the processing of the request and additional response headers and the response body follow the DONE meta-tag.");

            // Add the debug information
            this.Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCMAPIHTTP_R1266. The header value of Transfer-Encoding is {0} and Content-Length is {1}.", executeHeaders["Transfer-Encoding"], executeHeaders["Content-Length"]);

            // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1266
            bool isVerifiedR1266 = string.IsNullOrEmpty(executeHeaders["Content-Length"]) && executeHeaders["Transfer-Encoding"].ToLower() == "chunked".ToLower();

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR1266,
                2227,
                @"[In Responding to All Request Type Requests] If the server is using the ""chunked"" transfer coding, it MUST flush this to the client (being careful to make sure it disables any internal Nagle algorithms, as described in [RFC896], that might attempt to buffer response data).");

            // Add the debug information
            this.Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXCMAPIHTTP_R1230. The first meta-Tag is {0}, the value of header Transfer-Encoding is {1}.",
                metaTags[0],
                executeHeaders["Transfer-Encoding"]);

            // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1230
            // Because the server will spend some time to process the Logon request. So the entire response is not readily available.
            // The first meta tag is not "DONE" indicates the server is processing the request and not done.
            bool isVerifiedR1230 = metaTags[0] != "DONE" && executeHeaders["Transfer-Encoding"].ToLower() == "chunked".ToLower();

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR1230,
                1230,
                @"[In Responding to All Request Type Requests] If the entire response is not readily available, the server MUST use the Transfer-Encoding header, as specified in section 2.2.3.2.5, with a value of ""chunked"".");
            
            // R1230 ensures that the "chunked" transfer encoding is used and server can return data to the client while the request is still being processed.
            this.Site.CaptureRequirement(
                1174,
                @"[In Handling a Chunked Response] By using ""chunked"" transfer encoding, the server is able to return data to the client while the request is still being processed.");

            // R1230 ensures that the "chunked" transfer encoding is used and a positive connection between the server and client is established.
            this.Site.CaptureRequirement(
                1173,
                @"[In Handling a Chunked Response] To facilitate a positive connection between the server and client, the server uses the Transfer-Encoding header, as specified in section 2.2.3.2.5, with ""chunked"" transfer encoding, as specified in [RFC2616].");

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

            // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R1244
            // The X-ResponseCode header is parsed after the DONE meta-tag, and Execute request type response body is parsed after the header X-ResponseCode. 
            // So if the last meta-tag is DONE and code can reach here, this requirement can be verified.
            this.Site.CaptureRequirementIfAreEqual<string>(
                metaTags[metaTags.Count - 1],
                "DONE",
                1244,
                @"[In Responding to All Request Type Requests] After the server finishes processing the request it finishes with the DONE meta-tag, as specified in section 2.2.7; followed by any additional response headers.");

            #endregion
            #endregion

            #region Send an Execute request to open one folder to check the logon operation succeeds.
            RPC_HEADER_EXT[] rpcHeaderExts;
            byte[][] rops;
            uint[][] serverHandleObjectsTables;

            RopBufferHelper ropBufferHelper = new RopBufferHelper(Site);
            ropBufferHelper.ParseResponseBuffer(executeSuccessResponse.RopBuffer, out rpcHeaderExts, out rops, out serverHandleObjectsTables);
            RopLogonResponse logonResponse = new RopLogonResponse();
            logonResponse.Deserialize(rops[0], 0);
            uint logonHandle = serverHandleObjectsTables[0][logonResponse.OutputHandleIndex];

            RopOpenFolderRequest openFolderRequest = this.OpenFolderRequest(logonResponse.FolderIds[4]);

            ExecuteRequestBody openFolderRequestBody = this.InitializeExecuteRequestBody(openFolderRequest, logonHandle);
            executeHeaders = AdapterHelper.InitializeHTTPHeader(RequestType.Execute, AdapterHelper.ClientInstance, AdapterHelper.Counter);
            executeSuccessResponse = this.SendExecuteRequest(openFolderRequestBody, ref executeHeaders, out metaTags) as ExecuteSuccessResponseBody;

            Site.Assert.AreEqual<uint>((uint)0, executeSuccessResponse.StatusCode, "Execute method should succeed.");
            ropBufferHelper.ParseResponseBuffer(executeSuccessResponse.RopBuffer, out rpcHeaderExts, out rops, out serverHandleObjectsTables);
            RopOpenFolderResponse openFolderResponse = new RopOpenFolderResponse();
            openFolderResponse.Deserialize(rops[0], 0);

            // Add the debug information
            this.Site.Log.Add(
                LogEntryKind.Debug,
                "Verify MS-OXCMAPIHTTP_R226. The error code of Execute request type is {0}, the return value of RopOpenFolder is {1}.",
                executeSuccessResponse.ErrorCode,
                openFolderResponse.ReturnValue);

            // Verify MS-OXCMAPIHTTP requirement: MS-OXCMAPIHTTP_R226
            // If the return value of RopOpenFolder is 0, it indicates that the Logon handle is valid, so the Execute request type can be used to send the remote operation requests.
            bool isVerifiedR226 = executeSuccessResponse.ErrorCode == 0 && openFolderResponse.ReturnValue == 0;

            this.Site.CaptureRequirementIfIsTrue(
                isVerifiedR226,
                226,
                @"[In Execute Request Type] The Execute request type is used by the client to send remote operation requests to the server.");
            #endregion

            #region Send a Disconnect request to destroy the Session Context.
            MailboxResponseBodyBase response;
            this.Adapter.Disconnect(out response);
            #endregion
        }
All Usage Examples Of Microsoft.Protocols.TestSuites.Common.RopLogonResponse::Deserialize
RopLogonResponse