Exemplo n.º 1
0
        /// <summary>
        /// Verify the response of RopOpenFolder ROP operation.
        /// </summary>
        /// <param name="openFolderResponse">The response of RopOpenFolder operation</param>
        private void VerifyRopOpenFolder(RopOpenFolderResponse openFolderResponse)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R24");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R24
            Site.CaptureRequirementIfAreEqual<uint>(
                Constants.SuccessCode,
                openFolderResponse.ReturnValue,
                24,
                @"[In RopOpenFolder ROP Response Buffer] ReturnValue (4 bytes): The server returns 0x00000000 to indicate success.");
            
            // Add the debug information.
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R9");

            // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R9.
            // The server returns a successful RopOpenFolder response, it indicates that the server opened an existing folder, MS-OXCFOLD_R9 can be captured directly.
            Site.CaptureRequirement(
                9,
                @"[In RopOpenFolder ROP] The RopOpenFolder ROP ([MS-OXCROPS] section 2.2.4.1) opens an existing folder.");

            if (openFolderResponse.IsGhosted != 0)
            {
                Site.Assert.IsNotNull(openFolderResponse.ServerCount, "[In RopOpenFolder Rop response] The ServerCount field should be present when the IsGhosted field is set to a nonzero (TRUE) value.");
                Site.Assert.IsNotNull(openFolderResponse.CheapServerCount, "[In RopOpenFolder Rop response] The CheapServerCount field should be present when the IsGhosted field is set to a nonzero (TRUE) value.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R911, the cheap server count is {0}, the server count is {1}.", openFolderResponse.CheapServerCount, openFolderResponse.ServerCount);

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R911
                Site.CaptureRequirementIfIsTrue(
                    openFolderResponse.CheapServerCount <= openFolderResponse.ServerCount,
                    911,
                    @"[In RopOpenFolder ROP Response Buffer] The value of this field [CheapServerCount] MUST be less than or equal to the value of the ServerCount field.");
                
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCFOLD_R914, the count of strings contained in field Servers is {0}, the ServerCount is {1}.", openFolderResponse.Servers.Length, openFolderResponse.ServerCount);

                bool isVerifiedR914 = false;
                if (openFolderResponse.Servers == null)
                {
                    isVerifiedR914 = openFolderResponse.ServerCount == 0;
                }
                else
                {
                    isVerifiedR914 = openFolderResponse.ServerCount == (ushort)openFolderResponse.Servers.Length;
                }

                // Verify MS-OXCFOLD requirement: MS-OXCFOLD_R914
                Site.CaptureRequirementIfIsTrue(
                    isVerifiedR914,
                    914,
                    @"[In RopOpenFolder ROP Response Buffer] The number of strings contained in this field [Servers] is specified by the ServerCount field.");
            }
        }
        /// <summary>
        /// Log on mailbox with specified user.
        /// </summary>
        /// <param name="testUser">Identify the user to log on to the server.</param>
        public void LogonMailbox(TestUser testUser)
        {
            this.testUser = testUser;
            RopLogonResponse logonResponse = new RopLogonResponse();
            if (testUser == TestUser.TestUser1)
            {
                this.OxoruleAdapter.Connect(ConnectionType.PrivateMailboxServer, this.User1Name, this.User1ESSDN, this.User1Password);

                // Logon to private mailbox.
                this.LogonHandle = this.OxoruleAdapter.RopLogon(LogonType.Mailbox, this.User1ESSDN, out logonResponse);
            }
            else
            {
                this.OxoruleAdapter.Connect(ConnectionType.PrivateMailboxServer, this.User2Name, this.User2ESSDN, this.User2Password);

                // Logon to private mailbox.
                this.LogonHandle = this.OxoruleAdapter.RopLogon(LogonType.Mailbox, this.User2ESSDN, out logonResponse);
            }

            // Get the mailbox's GUID
            this.MailboxGUID = logonResponse.MailboxGuid;

            // Get folder ids.
            this.InboxFolderID = logonResponse.FolderIds[4];
            this.DAFFolderID = logonResponse.FolderIds[1];
            outBoxFolderID = logonResponse.FolderIds[5];
            sentItemsFolderID = logonResponse.FolderIds[6];

            // Open inbox and get inbox folder handle.
            RopOpenFolderResponse openInboxResponse = new RopOpenFolderResponse();
            this.InboxFolderHandle = this.OxoruleAdapter.RopOpenFolder(this.LogonHandle, this.InboxFolderID, out openInboxResponse);

            // Open DAF folder and get daf folder handle.
            RopOpenFolderResponse openDAFResponse = new RopOpenFolderResponse();
            this.DAFFolderHandle = this.OxoruleAdapter.RopOpenFolder(this.LogonHandle, this.DAFFolderID, out openDAFResponse);

            // Open outbox folder and get outbox folder handle.
            RopOpenFolderResponse openOutBoxResponse = new RopOpenFolderResponse();
            outBoxFolderHandle = this.OxoruleAdapter.RopOpenFolder(this.LogonHandle, outBoxFolderID, out openOutBoxResponse);

            // Open sent items folder and get sent items folder handle.
            RopOpenFolderResponse openSentItemsFolderResponse = new RopOpenFolderResponse();
            sentItemsFolderHandle = this.OxoruleAdapter.RopOpenFolder(this.LogonHandle, sentItemsFolderID, out openSentItemsFolderResponse);

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

            // Verify MS-OXORULE requirement: MS-OXORULE_R508.
            // If the DAF folder handle is not zero. It means the DAF has been created.
            Site.CaptureRequirementIfAreNotEqual<ulong>(
                0,
                this.DAFFolderHandle,
                508,
                @"[In Initialization] Prior to any client connecting to a mailbox, the server MUST ensure that the DAF has been created for that mailbox as specified in [MS-OXOSFLD] section 3.1.4.1.");
        }
        /// <summary>
        /// This ROP opens an existing folder in a mailbox.  
        /// </summary>
        /// <param name="handle">The handle to operate</param>
        /// <param name="openFolderResponse">The response of this ROP</param>
        /// <param name="folderId">The identifier of the folder to be opened.</param>
        /// <param name="needVerify">Whether need to verify the response</param>
        /// <returns>The handle of the opened folder</returns>
        private uint RopOpenFolder(uint handle, out RopOpenFolderResponse openFolderResponse, ulong folderId, bool needVerify)
        {
            this.rawDataValue = null;
            this.responseValue = null;
            this.responseSOHsValue = null;

            RopOpenFolderRequest openFolderRequest = new RopOpenFolderRequest()
            {
                RopId = (byte)RopId.RopOpenFolder,
                LogonId = LogonId,
                InputHandleIndex = (byte)HandleIndex.FirstIndex,
                OutputHandleIndex = (byte)HandleIndex.SecondIndex,
                FolderId = folderId,

                // Open an existing folder with None value for OpenModeFlags flag.
                OpenModeFlags = (byte)FolderOpenModeFlags.None
            };

            this.responseSOHsValue = this.ProcessSingleRop(openFolderRequest, handle, ref this.responseValue, ref this.rawDataValue, RopResponseType.SuccessResponse);
            openFolderResponse = (RopOpenFolderResponse)this.responseValue;
            if (needVerify)
            {
                this.Site.Assert.AreEqual((uint)RopResponseType.SuccessResponse, openFolderResponse.ReturnValue, string.Format("RopOpenFolderResponse Failed! Error: 0x{0:X8}", openFolderResponse.ReturnValue));
            }

            return this.responseSOHsValue[0][openFolderResponse.OutputHandleIndex];
        }
        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
        }
        /// <summary>
        /// Clean up the test.
        /// </summary>
        protected override void TestCleanup()
        {
            if (this.isReceiveNewMail == true)
            {
                WebHeaderCollection headers = new WebHeaderCollection();
                MailboxResponseBodyBase response;

                #region Send a valid Connect request type to establish a Session Context with the server.
                ConnectSuccessResponseBody connectResponse = this.ConnectToServer(out headers);
                #endregion

                #region Send an Execute request that incluldes 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;

                ulong folderId;
                RopLogonResponse logonResponse = new RopLogonResponse();
                uint logonHandle = this.ParseLogonResponse(executeSuccessResponse.RopBuffer, out folderId, out logonResponse);
                #endregion

                #region Send an Execute request to open inbox folder.
                RPC_HEADER_EXT[] rpcHeaderExts;
                byte[][] rops;
                uint[][] serverHandleObjectsTables;
                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;

                RopBufferHelper ropBufferHelper = new RopBufferHelper(Site);
                ropBufferHelper.ParseResponseBuffer(executeSuccessResponse.RopBuffer, out rpcHeaderExts, out rops, out serverHandleObjectsTables);
                RopOpenFolderResponse openFolderResponse = new RopOpenFolderResponse();
                openFolderResponse.Deserialize(rops[0], 0);
                 uint folderHandle = serverHandleObjectsTables[0][openFolderResponse.OutputHandleIndex];
                #endregion

                #region Send an Execute request type to hard delete messages in inbox folder.
                RopHardDeleteMessagesAndSubfoldersRequest hardDeleteRequest;
                hardDeleteRequest.RopId = (byte)RopId.RopHardDeleteMessagesAndSubfolders;
                hardDeleteRequest.LogonId = ConstValues.LogonId;

                // Set InputHandleIndex to 0x00, which specifies the location in the Server object handle table
                // where the handle for the input Server object is stored.
                hardDeleteRequest.InputHandleIndex = 0;
                hardDeleteRequest.WantAsynchronous = 0x00; // Synchronously
                hardDeleteRequest.WantDeleteAssociated = 0xFF; // TRUE: delete all messages and subfolders
                ExecuteRequestBody hardDeleteRequestBody = this.InitializeExecuteRequestBody(hardDeleteRequest, folderHandle);
                executeHeaders = AdapterHelper.InitializeHTTPHeader(RequestType.Execute, AdapterHelper.ClientInstance, AdapterHelper.Counter);
                executeSuccessResponse = this.SendExecuteRequest(hardDeleteRequestBody, ref executeHeaders, out metaTags) as ExecuteSuccessResponseBody;
                RopHardDeleteMessagesAndSubfoldersResponse hardDeleteMessagesAndSubfoldersResponse = new RopHardDeleteMessagesAndSubfoldersResponse();
                hardDeleteMessagesAndSubfoldersResponse.Deserialize(rops[0], 0);
                #endregion

                #region Send an Execute request to open sent items folder.
                openFolderRequest = this.OpenFolderRequest(logonResponse.FolderIds[6]);

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

                ropBufferHelper = new RopBufferHelper(Site);
                ropBufferHelper.ParseResponseBuffer(executeSuccessResponse.RopBuffer, out rpcHeaderExts, out rops, out serverHandleObjectsTables);
                openFolderResponse = new RopOpenFolderResponse();
                openFolderResponse.Deserialize(rops[0], 0);
                folderHandle = serverHandleObjectsTables[0][openFolderResponse.OutputHandleIndex];
                #endregion

                #region Send an Execute request type to hard delete messages in sent items folder.
                hardDeleteRequest.RopId = (byte)RopId.RopHardDeleteMessagesAndSubfolders;
                hardDeleteRequest.LogonId = ConstValues.LogonId;

                // Set InputHandleIndex to 0x00, which specifies the location in the Server object handle table
                // where the handle for the input Server object is stored.
                hardDeleteRequest.InputHandleIndex = 0;
                hardDeleteRequest.WantAsynchronous = 0x00; // Synchronously
                hardDeleteRequest.WantDeleteAssociated = 0xFF; // TRUE: delete all messages and subfolders
                hardDeleteRequestBody = this.InitializeExecuteRequestBody(hardDeleteRequest, folderHandle);
                executeHeaders = AdapterHelper.InitializeHTTPHeader(RequestType.Execute, AdapterHelper.ClientInstance, AdapterHelper.Counter);
                executeSuccessResponse = this.SendExecuteRequest(hardDeleteRequestBody, ref executeHeaders, out metaTags) as ExecuteSuccessResponseBody;
                hardDeleteMessagesAndSubfoldersResponse = new RopHardDeleteMessagesAndSubfoldersResponse();
                hardDeleteMessagesAndSubfoldersResponse.Deserialize(rops[0], 0);
                #endregion

                #region Send a Disconnect request to destroy the Session Context.
                this.Adapter.Disconnect(out response);
                #endregion

                this.isReceiveNewMail = false;
            }

            base.TestCleanup();
        }
        /// <summary>
        /// Verify RopOpenFolder Failure Response
        /// </summary>
        /// <param name="ropOpenFolderResponse">The failure response of RopOpenFolder request</param>
        /// <param name="outputHandleIndex">The field of OutputHandleIndex in RopOpenFolder request</param>
        private void VerifyRopOpenFolderFailureResponse(RopOpenFolderResponse ropOpenFolderResponse, byte outputHandleIndex)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R572");

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

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R574
            Site.CaptureRequirementIfAreEqual<byte>(
                (byte)RopId.RopOpenFolder,
                ropOpenFolderResponse.RopId,
                574,
                @"[In RopOpenFolder ROP Failure Response Buffer] RopId (1 byte): For this operation[RopOpenFolder], this field[RopId (1 byte)] is set to 0x02.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R575
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropOpenFolderResponse.OutputHandleIndex.GetType(),
                575,
                @"[In RopOpenFolder ROP Failure Response Buffer] OutputHandleIndex (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R576
            Site.CaptureRequirementIfAreEqual<byte>(
                outputHandleIndex,
                ropOpenFolderResponse.OutputHandleIndex,
                576,
                @"[In RopOpenFolder ROP Failure Response Buffer] OutputHandleIndex (1 byte): This index MUST be set to the value specified in the OutputHandleIndex field in the request.");

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

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

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R579
            Site.CaptureRequirementIfAreNotEqual<uint>(
                SuccessReturnValue,
                ropOpenFolderResponse.ReturnValue,
                579,
                @"[In RopOpenFolder ROP Failure Response Buffer] ReturnValue (4 bytes): For this response[Failure Response], this field[ReturnValue (4 bytes)] is set to a value other than 0x00000000.");
        }
        /// <summary>
        /// Verify RopOpenFolder Success Response
        /// </summary>
        /// <param name="ropOpenFolderResponse">The success response of RopOpenFolder request</param>
        /// <param name="outputHandleIndex">The field of OutputHandleIndex in RopOpenFolder request</param>
        private void VerifyRopOpenFolderSuccessResponse(RopOpenFolderResponse ropOpenFolderResponse, byte outputHandleIndex)
        {
            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R547");

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

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R549
            Site.CaptureRequirementIfAreEqual<byte>(
                (byte)RopId.RopOpenFolder,
                ropOpenFolderResponse.RopId,
                549,
                @"[In RopOpenFolder ROP Success Response Buffer] RopId (1 byte): For this operation[RopOpenFolder], this field[RopId (1 byte)] is set to 0x02.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R550
            Site.CaptureRequirementIfAreEqual<Type>(
                typeof(byte),
                ropOpenFolderResponse.OutputHandleIndex.GetType(),
                550,
                @"[In RopOpenFolder ROP Success Response Buffer] OutputHandleIndex (1 byte): An unsigned integer.");

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

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R551
            Site.CaptureRequirementIfAreEqual<byte>(
                outputHandleIndex,
                ropOpenFolderResponse.OutputHandleIndex,
                551,
                @"[In RopOpenFolder ROP Success Response Buffer] OutputHandleIndex (1 byte): This index MUST be set to the value specified in the OutputHandleIndex field in the request.");

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

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

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

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

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R555,HasRules:{0}", ropOpenFolderResponse.HasRules);

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R555
            // If HasRules is byte type and can be boolean type representation, then verify R555
            bool isVerifyR555 = (typeof(byte) == ropOpenFolderResponse.HasRules.GetType()) &&
                                ((Convert.ToBoolean(ropOpenFolderResponse.HasRules) == true) ||
                                (Convert.ToBoolean(ropOpenFolderResponse.HasRules) == false));

            Site.CaptureRequirementIfIsTrue(
                isVerifyR555,
                555,
                @"[In RopOpenFolder ROP Success Response Buffer] HasRules (1 byte): A Boolean.");

            // Add the debug information
            Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R557,IsGhosted:{0}", ropOpenFolderResponse.IsGhosted);

            // Verify MS-OXCROPS requirement: MS-OXCROPS_R557
            // If IsGhosted is byte type and can be boolean type representation, then verify R557
            bool isVerifyR557 = (typeof(byte) == ropOpenFolderResponse.IsGhosted.GetType()) &&
                                ((Convert.ToBoolean(ropOpenFolderResponse.IsGhosted) == true) ||
                                (Convert.ToBoolean(ropOpenFolderResponse.IsGhosted) == false));

            Site.CaptureRequirementIfIsTrue(
                isVerifyR557,
                557,
                @"[In RopOpenFolder ROP Success Response Buffer] IsGhosted (1 byte): A Boolean.");

            // The field ServerCount,CheapServerCount and Servers are present if IsGhosted is non-zero, and are not present if IsGhosted is zero. 
            if (ropOpenFolderResponse.IsGhosted > 0)
            {
                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R559");

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R559
                Site.CaptureRequirementIfAreEqual<Type>(
                    typeof(ushort),
                    ropOpenFolderResponse.ServerCount.GetType(),
                    559,
                    @"[In RopOpenFolder ROP Success Response Buffer] ServerCount (2 bytes): An unsigned integer .");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R563
                Site.CaptureRequirementIfAreEqual<Type>(
                    typeof(ushort),
                    ropOpenFolderResponse.CheapServerCount.GetType(),
                    563,
                    @"[In RopOpenFolder ROP Success Response Buffer] CheapServerCount (2 bytes): An unsigned integer.");

                // Add the debug information
                Site.Log.Add(LogEntryKind.Debug, "Verify MS-OXCROPS_R567,the length of the Servers is {0}", ropOpenFolderResponse.Servers.Length);

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R567
                // Assume the result is true. If one of List is not null-terminated ASCII string, then false.
                bool isVerifyR567 = true;
                foreach (string s in ropOpenFolderResponse.Servers)
                {
                    byte[] buffer = Encoding.ASCII.GetBytes(s);
                    isVerifyR567 = isVerifyR567 && this.IsNullTerminatedASCIIStr(buffer);

                    // If one of List is not null-terminated ASCII string then break iteration
                    if (!isVerifyR567)
                    {
                        break;
                    }
                }

                Site.CaptureRequirementIfIsTrue(
                    isVerifyR567,
                    567,
                    @"[In RopOpenFolder ROP Success Response Buffer] Servers (variable): A List of null-terminated ASCII strings.");

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

                // Verify MS-OXCROPS requirement: MS-OXCROPS_R570
                Site.CaptureRequirementIfAreEqual<ushort>(
                    (ushort)ropOpenFolderResponse.ServerCount,
                    (ushort)ropOpenFolderResponse.Servers.Length,
                    570,
                    @"[In RopOpenFolder ROP Success Response Buffer] Servers (variable): The number of strings contained in this field is specified by the ServerCount field.");
            }
        }
        /// <summary>
        /// This ROP opens an existing folder in a mailbox.  
        /// </summary>
        /// <param name="handle">Handle to operate.</param>
        /// <param name="folderId">64-bit identifier. This identifier specifies the folder to be opened.</param>
        /// <param name="openFolderResponse">Response of this ROP.</param>
        /// <returns>Handle of the open folder.</returns>
        public uint RopOpenFolder(uint handle, ulong folderId, out RopOpenFolderResponse openFolderResponse)
        {
            this.rawData = null;
            this.response = null;
            this.responseSOHs = null;

            RopOpenFolderRequest openFolderRequest;
            openFolderRequest.RopId = 0x02;
            openFolderRequest.LogonId = 0x0;
            openFolderRequest.InputHandleIndex = 0x0;
            openFolderRequest.OutputHandleIndex = 0x01;

            // Open Inbox here
            openFolderRequest.FolderId = folderId;

            // Opening an existing folder
            openFolderRequest.OpenModeFlags = 0x0;
            this.responseSOHs = this.DoRPCCall(openFolderRequest, handle, ref this.response, ref this.rawData);
            openFolderResponse = (RopOpenFolderResponse)this.response;
            uint openedFolderHandle = this.responseSOHs[0][openFolderResponse.OutputHandleIndex];

            return openedFolderHandle;
        }