/// <summary>
        /// Check server response. Return the abstracted context type of response.
        /// </summary>
        private void CheckResponseContexts(
            Smb2CreateContextResponse[] serverCreateContexts,
            out DurableHandleResponseContext durableHandleResponseContext,
            out LeaseResponseContext leaseResponseContext)
        {
            durableHandleResponseContext = DurableHandleResponseContext.NONE;
            leaseResponseContext         = LeaseResponseContext.NONE;

            if (serverCreateContexts != null)
            {
                foreach (Smb2CreateContextResponse response in serverCreateContexts)
                {
                    if (response is Smb2CreateDurableHandleResponse)
                    {
                        durableHandleResponseContext = DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE;
                    }
                    else if (response is Smb2CreateDurableHandleResponseV2)
                    {
                        durableHandleResponseContext = DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2;
                        if ((response as Smb2CreateDurableHandleResponseV2).Flags.HasFlag(CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT))
                        {
                            durableHandleResponseContext = DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2_WITH_PERSISTENT;
                        }
                    }
                    else if (response is Smb2CreateResponseLease)
                    {
                        leaseResponseContext = LeaseResponseContext.SMB2_CREATE_RESPONSE_LEASE;
                    }
                    else if (response is Smb2CreateResponseLeaseV2)
                    {
                        leaseResponseContext = LeaseResponseContext.SMB2_CREATE_RESPONSE_LEASE_V2;
                    }
                }
            }
        }
        /// <summary>
        /// Check server response. Return the abstracted context type of response.
        /// </summary>
        private void CheckResponseContexts(
            Smb2CreateContextResponse[] serverCreateContexts,
            out DurableHandleResponseContext durableHandleResponseContext,
            out LeaseResponseContext leaseResponseContext)
        {
            durableHandleResponseContext = DurableHandleResponseContext.NONE;
            leaseResponseContext = LeaseResponseContext.NONE;

            if (serverCreateContexts != null)
            {
                foreach (Smb2CreateContextResponse response in serverCreateContexts)
                {
                    if (response is Smb2CreateDurableHandleResponse)
                    {
                        durableHandleResponseContext = DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE;
                    }
                    else if (response is Smb2CreateDurableHandleResponseV2)
                    {
                        durableHandleResponseContext = DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2;
                        if ((response as Smb2CreateDurableHandleResponseV2).Flags.HasFlag(CREATE_DURABLE_HANDLE_RESPONSE_V2_Flags.DHANDLE_FLAG_PERSISTENT))
                            durableHandleResponseContext = DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2_WITH_PERSISTENT;
                    }
                    else if (response is Smb2CreateResponseLease)
                    {
                        leaseResponseContext = LeaseResponseContext.SMB2_CREATE_RESPONSE_LEASE;
                    }
                    else if (response is Smb2CreateResponseLeaseV2)
                    {
                        leaseResponseContext = LeaseResponseContext.SMB2_CREATE_RESPONSE_LEASE_V2;
                    }
                }
            }
        }
        public static void OpenResponse(
            ModelSmb2Status status,
            DurableHandleResponseContext durableHandleResponseContext,
            LeaseResponseContext leaseResponseContext,
            HandleConfig c)
        {
            Condition.IsNotNull(Request);

            ModelOpenFileRequest modelOpenFileRequest = ModelHelper.RetrieveOutstandingRequest<ModelOpenFileRequest>(ref Request);

            if (ModelUtility.IsSmb3xFamily(NegotiateDialect)
                && modelOpenFileRequest.durableV1ReconnectContext == DurableV1ReconnectContext.DurableV1ReconnectContextNotExist
                && modelOpenFileRequest.durableV2ReconnectContext == DurableV2ReconnectContext.DurableV2ReconnectContextNotExist)
            {
                ModelHelper.Log(LogType.Requirement,
                    "3.3.5.9: If Connection.Dialect belongs to the SMB 3.x dialect family and " +
                    "the request does not contain SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context, " +
                    "the server MUST look up an existing open in the GlobalOpenTable where Open.FileName matches the file name in the Buffer field of the request. ");
                ModelHelper.Log(LogType.TestInfo,
                    "Connection.Dialect is {0} and the request does not contain SMB2_CREATE_DURABLE_HANDLE_RECONNECT or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context.",
                    NegotiateDialect);

                if (Open != null
                    && !modelOpenFileRequest.isSameClient
                    && Open.IsPersistent
                    && !Open.IsConnectionExisted
                    && !Open.IsBatchOplockExisted
                    && !Open.IsLeaseExisted)
                {
                    ModelHelper.Log(LogType.Requirement,
                        "If an Open entry is found, and if all the following conditions are satisfied, " +
                        "the server MUST fail the request with STATUS_FILE_NOT_AVAILABLE.");
                    ModelHelper.Log(LogType.Requirement, "\tOpen.IsPersistent is TRUE");
                    ModelHelper.Log(LogType.Requirement, "\tOpen.Connection is NULL");
                    ModelHelper.Log(LogType.Requirement, "\tOpen.OplockLevel is not equal to SMB2_OPLOCK_LEVEL_BATCH");
                    ModelHelper.Log(LogType.Requirement, "\tOpen.OplockLevel is not equal to SMB2_OPLOCK_LEVEL_LEASE or Open.Lease.LeaseState does not include SMB2_LEASE_HANDLE_CACHING");

                    ModelHelper.Log(LogType.TestInfo, "The Open is found, and all the conditions are satisfied.");
                    ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                    Condition.IsTrue(status == ModelSmb2Status.STATUS_FILE_NOT_AVAILABLE);
                    return;
                }
            }

            // TD section 3.3.5.9.6: Handling the SMB2_CREATE_DURABLE_HANDLE_REQUEST Create Context
            if (modelOpenFileRequest.durableV1RequestContext == DurableV1RequestContext.DurableV1RequestContextExist)
            {
                if (Handling_SMB2_CREATE_DURABLE_HANDLE_REQUEST_CreateContext(status, modelOpenFileRequest, durableHandleResponseContext, c))
                    return;
            }

            // TD section 3.3.5.9.7: Handling the SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context
            if (modelOpenFileRequest.durableV1ReconnectContext == DurableV1ReconnectContext.DurableV1ReconnectContextExist)
            {
                if (Handling_SMB2_CREATE_DURABLE_HANDLE_RECONNECT_CreateContext(status, modelOpenFileRequest, leaseResponseContext, c))
                    return;
            }

            // TD section 3.3.5.9.10: Handling the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context
            if (modelOpenFileRequest.durableV2RequestContext != DurableV2RequestContext.DurableV2RequestContextNotExist)
            {
                if (Handling_SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2_CreateContext(status, modelOpenFileRequest, durableHandleResponseContext))
                    return;
            }

            // TD section 3.3.5.9.12: Handling the SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 Create Context
            if (modelOpenFileRequest.durableV2ReconnectContext != DurableV2ReconnectContext.DurableV2ReconnectContextNotExist)
            {
                if (Handling_SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2_CreateContext(status, modelOpenFileRequest, leaseResponseContext, c))
                    return;
            }

            Condition.IsTrue(status == Smb2Status.STATUS_SUCCESS);
        }
        /// <summary>
        /// This method is used to verify the SMB2_CREATE_DURABLE_HANDLE_REQUEST Create Context
        /// The client is requesting that the open be marked for durable operation
        /// Cover TD section: 3.3.5.9.6
        /// Return true means the message is handled by this function. 
        /// Return false means the message needs further processing.
        /// </summary>
        private static bool Handling_SMB2_CREATE_DURABLE_HANDLE_REQUEST_CreateContext(
            ModelSmb2Status status,
            ModelOpenFileRequest modelOpenFileRequest,
            DurableHandleResponseContext durableHandleResponseContext,
            HandleConfig c)
        {
            ModelHelper.Log(LogType.Requirement, "3.3.5.9.6: Handling the SMB2_CREATE_DURABLE_HANDLE_REQUEST Create Context");

            if (modelOpenFileRequest.durableV1ReconnectContext == DurableV1ReconnectContext.DurableV1ReconnectContextExist)
            {
                ModelHelper.Log(LogType.Requirement,
                    "If the create request also includes an SMB2_CREATE_DURABLE_HANDLE_RECONNECT create context, " +
                    "the server MUST process the create context as specified in section 3.3.5.9.7 and skip this section.");
                ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_RECONNECT is included.");
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                return false;
            }

            if (modelOpenFileRequest.durableV2RequestContext != DurableV2RequestContext.DurableV2RequestContextNotExist
                || modelOpenFileRequest.durableV2ReconnectContext != DurableV2ReconnectContext.DurableV2ReconnectContextNotExist)
            {
                // Workaround to force SE explorers the platform field.
                Condition.IsTrue(Config.Platform == c.Platform);

                ModelHelper.Log(LogType.Requirement,
                    "If the create request also includes an SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 create context, " +
                    "the server SHOULD<266> fail the create request with STATUS_INVALID_PARAMETER.");

                ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedContext);

                if (modelOpenFileRequest.durableV2RequestContext != DurableV2RequestContext.DurableV2RequestContextNotExist)
                {
                    ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 is included.");
                }
                if (modelOpenFileRequest.durableV2ReconnectContext != DurableV2ReconnectContext.DurableV2ReconnectContextNotExist)
                {
                    ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is included.");
                }

                if (Config.Platform == Platform.WindowsServer2008 || Config.Platform == Platform.WindowsServer2008R2)
                {
                    ModelHelper.Log(LogType.Requirement, "<266> Section 3.3.5.9.6: Windows Vista SP1, Windows 7, Windows Server 2008, and Windows Server 2008 R2 ignore undefined create contexts.");
                    ModelHelper.Log(LogType.TestInfo, "The SUT platform is {0}", Config.Platform);
                    Condition.IsFalse(durableHandleResponseContext == DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE);
                    return false;
                }
                else if (Config.Platform == Platform.NonWindows)
                {
                    ModelHelper.Log(LogType.TestInfo, "The SUT platform is NonWindows, so the server could return other error code.");
                    Condition.IsTrue(status != ModelSmb2Status.STATUS_SUCCESS);
                }
                else
                {
                    ModelHelper.Log(LogType.TestInfo, "The SUT platform is {0}", Config.Platform);
                    Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER);
                }

                return true;
            }

            if (modelOpenFileRequest.oplockLeaseType == OplockLeaseType.NoOplockOrLease)
            {
                ModelHelper.Log(LogType.Requirement,
                    "If the RequestedOplockLevel field in the create request is not set to SMB2_OPLOCK_LEVEL_BATCH and " +
                    "the create request does not include an SMB2_CREATE_REQUEST_LEASE create context with a LeaseState field that includes the SMB2_LEASE_HANDLE_CACHING bit value, " +
                    "the server MUST ignore this create context and skip this section.");
                ModelHelper.Log(LogType.TestInfo, "The create response should not contain SMB2_CREATE_DURABLE_HANDLE_RESPONSE.");
                ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
                Condition.IsFalse(durableHandleResponseContext == DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE);
                return false;
            }

            ModelHelper.Log(LogType.Requirement, "In the \"Response Construction\" phase, the server MUST construct an SMB2_CREATE_DURABLE_HANDLE_RESPONSE response create context");
            ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_RESPONSE should be contained in create response");
            Condition.IsTrue(durableHandleResponseContext == DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE);

            return false;
        }
        /// <summary>
        /// This method is used to verify the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context
        /// Cover TD section: 3.3.5.9.10
        /// Return true means the message is handled by this function. 
        /// Return false means the message needs further processing.        
        /// </summary>
        private static bool Handling_SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2_CreateContext(
            ModelSmb2Status status,
            ModelOpenFileRequest modelOpenFileRequest,
            DurableHandleResponseContext durableHandleResponseContext)
        {
            ModelHelper.Log(LogType.Requirement, "3.3.5.9.10: Handling the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context");

            if (modelOpenFileRequest.durableV1RequestContext == DurableV1RequestContext.DurableV1RequestContextExist
                || modelOpenFileRequest.durableV1ReconnectContext == DurableV1ReconnectContext.DurableV1ReconnectContextExist
                || modelOpenFileRequest.durableV2ReconnectContext != DurableV2ReconnectContext.DurableV2ReconnectContextNotExist)
            {
                ModelHelper.Log(LogType.Requirement,
                    "If the create request also includes an SMB2_CREATE_DURABLE_HANDLE_REQUEST create context, " +
                    "or an SMB2_CREATE_DURABLE_HANDLE_RECONNECT or SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 create context, " +
                    "the server MUST fail the create request with STATUS_INVALID_PARAMETER.");
                ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedContext);

                if (modelOpenFileRequest.durableV1RequestContext == DurableV1RequestContext.DurableV1RequestContextExist)
                    ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_REQUEST is included.");
                if (modelOpenFileRequest.durableV1ReconnectContext == DurableV1ReconnectContext.DurableV1ReconnectContextExist)
                    ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_RECONNECT is included.");
                if (modelOpenFileRequest.durableV2ReconnectContext != DurableV2ReconnectContext.DurableV2ReconnectContextNotExist)
                    ModelHelper.Log(LogType.TestInfo, "SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 is included.");

                Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER);
                return true;
            }

            if (modelOpenFileRequest.durableV2RequestContext == DurableV2RequestContext.DurableV2RequestContextExistWithoutPersistent
                && modelOpenFileRequest.oplockLeaseType == OplockLeaseType.NoOplockOrLease)
            {
                ModelHelper.Log(LogType.Requirement,
                    "If the SMB2_DHANDLE_FLAG_PERSISTENT bit is not set in the Flags field of this create context, " +
                    "if RequestedOplockLevel in the create request is not set to SMB2_OPLOCK_LEVEL_BATCH, " +
                    "and if the create request does not include a SMB2_CREATE_REQUEST_LEASE or SMB2_CREATE_REQUEST_LEASE_V2 create context  " +
                    "with a LeaseState field that includes SMB2_LEASE_HANDLE_CACHING, the server MUST ignore this create context and skip this section.");
                ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. ");
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                Condition.IsTrue(durableHandleResponseContext == DurableHandleResponseContext.NONE);
                return false;
            }

            if (Open != null
                && modelOpenFileRequest.isSameClient
                && modelOpenFileRequest.isSameCreateGuid)
            {
                ModelHelper.Log(LogType.Requirement,
                    "The server MUST locate the Open in GlobalOpenTable where Open.CreateGuid matches the CreateGuid in the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 create context, " +
                    "and Open.ClientGuid matches the ClientGuid of the connection that received this request.");
                ModelHelper.Log(LogType.TestInfo, "The Open is found.");

                ModelHelper.Log(LogType.Requirement,
                    "If an Open is found and the SMB2_FLAGS_REPLAY_OPERATION bit is not set in the SMB2 header, the server MUST fail the request with STATUS_DUPLICATE_OBJECTID.");
                ModelHelper.Log(LogType.TestInfo, "SMB2_FLAGS_REPLAY_OPERATION is not set.");
                ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
                Condition.IsTrue(status == ModelSmb2Status.STATUS_DUPLICATE_OBJECTID);
                return true;
            }

            if (Open == null)
            {
                ModelHelper.Log(LogType.Requirement,
                    "If an Open is not found, the server MUST continue the create process specified in the \"Open Execution\" Phase, and perform the following additional steps:");
                Open = new HandleModelOpen();
                ModelHelper.Log(LogType.Requirement,
                    "In the \"Successful Open Initialization\" phase, the server MUST set Open.IsDurable to TRUE. ");
                Open.IsDurable = true;

                if (modelOpenFileRequest.durableV2RequestContext == DurableV2RequestContext.DurableV2RequestContextExistWithPersistent
                    && Share_IsCA
                    && ServerCapabilities_PersistentBitSet)
                {
                    ModelHelper.Log(LogType.Requirement,
                        "If the SMB2_DHANDLE_FLAG_PERSISTENT bit is set in the Flags field of the request, TreeConnect.Share.IsCA is TRUE, " +
                        "and Connection.ServerCapabilities includes SMB2_GLOBAL_CAP_PERSISTENT_HANDLES, the server MUST set Open.IsPersistent to TRUE.");
                    ModelHelper.Log(LogType.TestInfo, "All the above conditions are met. Open.IsPersistent is set to TRUE.");
                    Open.IsPersistent = true;
                }
            }

            if (modelOpenFileRequest.durableV2RequestContext != DurableV2RequestContext.DurableV2RequestContextExistWithPersistent
                && modelOpenFileRequest.oplockLeaseType == OplockLeaseType.NoOplockOrLease)
            {
                ModelHelper.Log(LogType.Requirement,
                    "The server MUST skip the construction of the SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2 create context " +
                    "if the SMB2_DHANDLE_FLAG_PERSISTENT bit is not set in the Flags field of the request and if neither of the following conditions are met:" +
                    "\tOpen.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH. " + "\tOpen.Lease.LeaseState has SMB2_LEASE_HANDLE_CACHING bit set.");
                ModelHelper.Log(LogType.TestInfo,
                    "All the above conditions are met. " +
                    "So the server skips the construction of the SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2 create context.");
                Condition.IsTrue(durableHandleResponseContext == DurableHandleResponseContext.NONE);
            }
            else
            {
                ModelHelper.Log(LogType.Requirement,
                    "If Open.IsPersistent is TRUE, the server MUST set the SMB2_DHANDLE_FLAG_PERSISTENT bit in the Flags field. ");
                ModelHelper.Log(LogType.TestInfo, "Open.IsPersistent is {0}", Open.IsPersistent);
                if (Open.IsPersistent)
                {
                    Condition.IsTrue(durableHandleResponseContext == DurableHandleResponseContext.SMB2_CREATE_DURABLE_HANDLE_RESPONSE_V2_WITH_PERSISTENT);
                }
            }
            return false;
        }