public void ReadConfig(out ReplayServerConfig c)
        {
            writeContent = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);

            c = new ReplayServerConfig
            {
                MaxSmbVersionSupported      = ModelUtility.GetModelDialectRevision(testConfig.MaxSmbVersionSupported),
                IsDirectoryLeasingSupported = testConfig.IsDirectoryLeasingSupported,
                IsLeasingSupported          = testConfig.IsLeasingSupported,
                IsPersistentHandleSupported = testConfig.IsPersistentHandlesSupported,
                TreeConnect_Share_Type_Include_STYPE_CLUSTER_SOFS = Boolean.Parse(testConfig.GetProperty("ShareTypeInclude_STYPE_CLUSTER_SOFS")),
                Platform = testConfig.Platform,
            };

            replayConfig = c;

            testConfig.CheckDialect(DialectRevision.Smb30);

            Site.Log.Add(LogEntryKind.Debug, c.ToString());
        }
        public static void CreateResponse(
            ModelSmb2Status status,
            ReplayModelDurableHandle durableHandleResponse,
            ReplayServerConfig c)
        {
            Condition.IsTrue(State == ModelState.Connected);
            Condition.IsNotNull(Request);

            ModelReplayCreateRequest createRequest = ModelHelper.RetrieveOutstandingRequest<ModelReplayCreateRequest>(ref Request);

            bool openIsFound = false;

            if (PreCheckChannelSequence(ReplayModelRequestCommand.Create, createRequest.channel.Connection_NegotiateDialect, ref createRequest.channelSequence,
                createRequest.isSetReplayFlag == ReplayModelSetReplayFlag.WithReplayFlag, status))
            {
                do
                {
                    if (createRequest.switchChannelType == ReplayModelSwitchChannelType.ReconnectMainChannel && 
                        LastOpen != null &&
                        LastOpen.IsPersistent &&
                        LastOpen.Lease.LeaseState == ReplayModelLeaseState.LeaseStateNotIncludeH &&
                        createRequest.fileName == ReplayModelFileName.DefaultFileName &&
                        createRequest.leaseState == ReplayModelLeaseState.LeaseStateIncludeH &&
                        createRequest.leaseKey == ReplayModelLeaseKey.DefaultLeaseKey)
                    {
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "SwitchChannelType is {0}, LastOpen is NOT null, LastOpen is persistent, LastOpen.Lease is {1}",
                            createRequest.switchChannelType, LastOpen.Lease.LeaseState);
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "Parameters in create request is fileName {0}, leaseState {1}, leaseKey {2}", createRequest.fileName, createRequest.leaseState, createRequest.leaseKey);
                        ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_SHARING_VIOLATION);
                        break;
                    }

                    #region 3.3.6.1 Handle Oplock Break Acknowledgment Timer Event

                    if (createRequest.switchChannelType == ReplayModelSwitchChannelType.ReconnectMainChannel ||
                        createRequest.switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel)
                    {
                        //TODO: More comments
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "When switchChannelType == AlternativeChannelWithDisconnectMainChannel or switchChannelType == ReconnectMainChannel (i.e. experiencing connection drop)," +
                            " the server will send oplock/lease break notification to the client, but currently test cases do not send acknowledgement request, so the oplock break acknowledgment timer always expires.");
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "createRequest.switchChannelType is {0}", createRequest.switchChannelType);
                        ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);

                        if (Open != null &&
                            Open.Lease != null &&
                            Open.IsPersistent &&
                            createRequest.fileName == ReplayModelFileName.DefaultFileName)
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.6.1: When the oplock break acknowledgment timer expires, the server MUST scan for oplock breaks that have not been acknowledged by the client within the configured time." +
                                " It does this by enumerating all opens in the GlobalOpenTable. For each open, if Open.OplockState is Breaking and Open.OplockTimeout is earlier than the current time," +
                                " the server MUST acknowledge the oplock break to the underlying object store represented by Open.LocalOpen, set Open.OplockLevel to SMB2_OPLOCK_LEVEL_NONE, and set Open.OplockState to None");

                            Open.OplockLevel = ReplayModelRequestedOplockLevel.OplockLevelNone;

                            ModelHelper.Log(
                                LogType.Requirement,
                                "For each lease, if Lease.Breaking is TRUE and Lease.LeaseBreakTimeout is earlier than the current time," +
                                " the server MUST acknowledge the lease break to the underlying object store represented by the opens in Lease.LeaseOpens, and set Lease.LeaseState to NONE");

                            Open.Lease.LeaseState = ReplayModelLeaseState.LeaseStateIsNone;

                            if (createRequest.createGuid == ReplayModelCreateGuid.DefaultCreateGuid)
                            {
                                Open.ConnectionIsNotNull = true;
                            }
                            else
                            {
                                LastOpen = Open;
                                Open = null;
                            }
                        }
                    }

                    #endregion

                    if (createRequest.fileName == ReplayModelFileName.DefaultFileName &&
                        Open != null &&
                        Open.IsPersistent &&
                        !Open.ConnectionIsNotNull &&
                        Open.OplockLevel != ReplayModelRequestedOplockLevel.OplockLevelBatch &&
                        ((Open.OplockLevel != ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 &&
                          Open.OplockLevel != ReplayModelRequestedOplockLevel.OplockLevelLeaseV2) ||
                         (Open.Lease != null && Open.Lease.LeaseState != ReplayModelLeaseState.LeaseStateIncludeH)))
                    {
                        // Replay will always use 3.x family
                        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. 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,
                            "Connection.Dialect is {0}, Open is found from GlobalOpenTable, Open.IsPersistent is {1}, Open.Connection is{2}NULL, Open.OplockLevel is {3}, Open.Lease.LeaseState is {4}",
                            createRequest.channel.Connection_NegotiateDialect, Open.IsPersistent,
                            Open.ConnectionIsNotNull ? " NOT " : " ", Open.OplockLevel, Open.Lease.LeaseState);

                        ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedContext);
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_FILE_NOT_AVAILABLE);
                        break;
                    }

                    Condition.IsTrue(Config == c);
                    Condition.IsTrue(Config.TreeConnect_Share_Type_Include_STYPE_CLUSTER_SOFS == c.TreeConnect_Share_Type_Include_STYPE_CLUSTER_SOFS);

                    if (Config.TreeConnect_Share_Type_Include_STYPE_CLUSTER_SOFS &&
                        createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelBatch)
                    {
                        // Replay will always use 3.x family
                        ModelHelper.Log(
                            LogType.Requirement,
                            "3.3.5.9: If Connection.Dialect belongs to the SMB 3.x dialect family TreeConnect.Share.Type includes STYPE_CLUSTER_SOFS" +
                            " and the RequestedOplockLevel is SMB2_OPLOCK_LEVEL_BATCH, the server MUST set RequestedOplockLevel to SMB2_OPLOCK_LEVEL_II");
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "Connection.Dialect is {0}, TreeConnect.Share.Type includes STYPE_CLUSTER_SOFS and the RequestedOplockLevel is SMB2_OPLOCK_LEVEL_BATCH",
                            createRequest.channel.Connection_NegotiateDialect);

                        createRequest.requestedOplockLevel = ReplayModelRequestedOplockLevel.OplockLevelII;
                    }

                    #region Handle Lease 3.3.5.9.8 and 3.3.5.9.11

                    if (Open != null)
                    {
                        if (Open.Lease != null &&
                            (createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 ||
                             createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV2) &&
                            createRequest.leaseKey == ReplayModelLeaseKey.DefaultLeaseKey &&
                            createRequest.fileName != ReplayModelFileName.DefaultFileName)
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.8: The server MUST attempt to locate a Lease by performing a lookup in the LeaseTable.LeaseList using the LeaseKey" +
                                " in the SMB2_CREATE_REQUEST_LEASE as the lookup key. If a lease is found but Lease.Filename does not match the file name for the incoming request," +
                                " the request MUST be failed with STATUS_INVALID_PARAMETER");
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.11: The server MUST attempt to locate a Lease by performing a lookup in the LeaseTable.LeaseList using the LeaseKey" +
                                " in the SMB2_CREATE_REQUEST_LEASE_V2 as the lookup key. If a lease is found but Lease.Filename does not match the file name for the incoming request," +
                                " the request MUST be failed with STATUS_INVALID_PARAMETER");

                            ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
                            Condition.IsTrue(status == ModelSmb2Status.STATUS_INVALID_PARAMETER);
                            break;
                        }

                        // At this point, execution of create continues as described in 3.3.5.9 until the Oplock Acquisition phase.
                    }

                    #endregion

                    #region 3.3.5.9.10   Handling the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context

                    if (createRequest.modelDurableHandle == ReplayModelDurableHandle.DurableHandleV2 || 
                        createRequest.modelDurableHandle == ReplayModelDurableHandle.DurableHandleV2Persistent)
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "3.3.5.9.10: Handling the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context");
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "createRequest.modelDurableHandle is {0}", createRequest.modelDurableHandle);

                        bool hasLeaseCreateContext =
                            (createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 ||
                            createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV2);

                        ModelHelper.Log(
                            LogType.TestInfo,
                            "createRequest.requestedOplockLevel is {0}", createRequest.requestedOplockLevel);

                        if (createRequest.modelDurableHandle == ReplayModelDurableHandle.DurableHandleV2 &&
                            createRequest.requestedOplockLevel != ReplayModelRequestedOplockLevel.OplockLevelBatch &&
                            !((createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 ||
                               createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV2) &&
                              createRequest.leaseState == ReplayModelLeaseState.LeaseStateIncludeH))
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.10: 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.TestTag, TestTag.Compatibility);
                            break;
                        }

                        // If ClientGuid is different, alternative channel cannot be create.
                        if (Open != null)
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.10: 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");

                            openIsFound = (createRequest.createGuid == ReplayModelCreateGuid.DefaultCreateGuid && Open.CreateGuidIsNotNull);

                            ModelHelper.Log(
                                LogType.TestInfo,
                                "Open is not NULL and Open could{0}be located", openIsFound ? " " : " not ");
                        }

                        if (!openIsFound)
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.10: 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:");
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.10: The server MUST set Open.CreateGuid to the CreateGuid in SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2.");

                            if (Open != null)
                            {
                                LastOpen = Open;
                            }

                            Open = new ReplayOpen();

                            ModelHelper.Log(
                                LogType.Requirement,
                                "In the \"Successful Open Initialization\" phase, the server MUST set Open.IsDurable to TRUE." +
                                " The server MUST also set Open.DurableOwner to a security descriptor accessible only by the user represented by Open.Session.SecurityContext.");

                            Open.IsDurable = true;

                            ModelHelper.Log(LogType.TestInfo, "Open.IsDurable is set to TRUE");

                            if ( createRequest.modelDurableHandle == ReplayModelDurableHandle.DurableHandleV2Persistent &&
                                createRequest.channel.Connection_Session_TreeConnect_Share_IsCA == ReplayModelShareType.CAShare &&
                                createRequest.channel.Connection_ClientCapabilities_SupportPersistent) // assume connection dialect always 3.x
                            {
                                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.");

                                Open.IsPersistent = true;

                                ModelHelper.Log(LogType.TestInfo, "Open.IsPersistent is set to {0}", Open.IsPersistent);
                            }

                            // 3.3.5.9.8   Handling the SMB2_CREATE_REQUEST_LEASE Create Context
                            // 3.3.5.9.11  Handling the SMB2_CREATE_REQUEST_LEASE_V2 Create Context
                            if (createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 ||
                                createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV2)
                            {
                                ModelHelper.Log(
                                    LogType.TestInfo,
                                    "Requested OplockLevel is {0}, Open.leaseState is {1}", createRequest.requestedOplockLevel, createRequest.leaseState);

                                Open.Lease = new ReplayLease(createRequest.leaseState);
                            }
                        }
                        else // Open is found
                        {
                            if (createRequest.isSetReplayFlag == ReplayModelSetReplayFlag.WithoutReplayFlag)
                            {
                                ModelHelper.Log(
                                    LogType.Requirement,
                                    "3.3.5.9.10: 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.Requirement,
                                    "Open is found and SMB2_FLAGS_REPLAY_OPERATION bit is not set in the SMB2 header");

                                ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
                                Condition.IsTrue(status == ModelSmb2Status.STATUS_DUPLICATE_OBJECTID);
                                break;
                            }

                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.10: If an Open is found and the SMB2_FLAGS_REPLAY_OPERATION bit is set in the SMB2 header, the server MUST verify the following:");

                            if (!Open.IsDurable ||
                                (Open.Lease == null && hasLeaseCreateContext) || 
                                (Open.Lease != null && !hasLeaseCreateContext) || // Open is NOT NULL but request does not have lease context
                                (Open.Lease != null && hasLeaseCreateContext &&
                                 createRequest.leaseKey != ReplayModelLeaseKey.DefaultLeaseKey))
                            {
                                ModelHelper.Log(
                                    LogType.Requirement,
                                    "The server MUST fail the create request with STATUS_ACCESS_DENIED in the following cases:");
                                ModelHelper.Log(
                                    LogType.Requirement,
                                    "\tOpen.IsDurable is FALSE");
                                // "Open.DurableOwner is not the user represented by Open.Session.SecurityContext." not covered
                                ModelHelper.Log(
                                    LogType.Requirement,
                                    "\tIf Open.Lease is not NULL and Open.Lease.LeaseKey is not equal to the LeaseKey specified in the SMB2_CREATE_REQUEST_LEASE or SMB2_CREATE_REQUEST_LEASE_V2 Create Context");

                                if (!Open.IsDurable)
                                {
                                    ModelHelper.Log(
                                        LogType.TestInfo,
                                        "Open.IsDurable is FALSE");
                                }
                                else if (Open.Lease == null && hasLeaseCreateContext)
                                {
                                    ModelHelper.Log(
                                        LogType.TestInfo,
                                        "Open.Lease is NULL but request has lease context");
                                }
                                else if (Open.Lease != null && !hasLeaseCreateContext)
                                {
                                    ModelHelper.Log(
                                        LogType.TestInfo,
                                        "Open is NOT NULL but request does not have lease context");
                                }
                                else
                                {
                                    ModelHelper.Log(
                                        LogType.TestInfo,
                                        "If Open.Lease is not NULL and Open.Lease.LeaseKey is not equal to the LeaseKey specified in the request");
                                }

                                ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);
                                Condition.IsTrue(status == ModelSmb2Status.STATUS_ACCESS_DENIED);
                                break;
                            }

                            if (createRequest.fileAttributes != ReplayModelFileAttributes.DefaultFileAttributes)
                            {
                                ModelHelper.Log(
                                    LogType.Requirement,
                                    "If Open.FileAttributes does not match the FileAttributes field of the SMB2 CREATE request, the server MUST fail the request with STATUS_INVALID_PARAMETER.");

                                break;
                            }

                            if (createRequest.createDisposition != ReplayModelCreateDisposition.DefaultCreateDisposition)
                            {
                                ModelHelper.Log(
                                    LogType.Requirement,
                                    "If Open.CreateDisposition does not match the CreateDisposition field of the SMB2 CREATE request, the server MUST fail the request with STATUS_INVALID_PARAMETER");
                            }

                            if (Open.IsPersistent && createRequest.modelDurableHandle != ReplayModelDurableHandle.DurableHandleV2Persistent)
                            {
                                ModelHelper.Log(
                                    LogType.Requirement,
                                    "If Open.IsPersistent is TRUE and the SMB2_DHANDLE_FLAG_PERSISTENT bit is not set in the Flags field of the SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 Create Context, the server MUST fail the request with STATUS_INVALID_PARAMETER");
                            }
                        }

                        if (createRequest.modelDurableHandle == ReplayModelDurableHandle.DurableHandleV2 &&
                            Open.OplockLevel != ReplayModelRequestedOplockLevel.OplockLevelBatch && (
                                !hasLeaseCreateContext || (
                                    hasLeaseCreateContext && (
                                        Open.Lease.LeaseState == ReplayModelLeaseState.LeaseStateIsNone ||
                                        Open.Lease.LeaseState == ReplayModelLeaseState.LeaseStateNotIncludeH
                                        )
                                    )
                                )
                            )
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.10: 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:");
                            ModelHelper.Log(
                                LogType.Requirement,
                                "Open.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH");
                            ModelHelper.Log(
                                LogType.Requirement,
                                "Open.Lease.LeaseState has SMB2_LEASE_HANDLE_CACHING bit set");
                            // Handle normal open
                            break;
                        }

                        if (createRequest.modelDurableHandle == ReplayModelDurableHandle.DurableHandleV2Persistent &&
                            createRequest.requestedOplockLevel != ReplayModelRequestedOplockLevel.OplockLevelBatch && (
                                !hasLeaseCreateContext || (
                                    hasLeaseCreateContext && (
                                        createRequest.leaseState == ReplayModelLeaseState.LeaseStateIsNone ||
                                        createRequest.leaseState == ReplayModelLeaseState.LeaseStateNotIncludeH
                                        )
                                    )
                                )
                            )
                        {
                            // Handle normal open
                            break;
                        }

                        #region Handle Lease

                        if (Open != null)
                        {
                            if ((createRequest.requestedOplockLevel ==
                                 ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 ||
                                 createRequest.requestedOplockLevel ==
                                 ReplayModelRequestedOplockLevel.OplockLevelLeaseV2) && Open.Lease != null &&
                                Open.Lease.LeaseState == ReplayModelLeaseState.LeaseStateNotIncludeH &&
                                createRequest.leaseState == ReplayModelLeaseState.LeaseStateIncludeH)
                            {
                                ModelHelper.Log(
                                    LogType.Requirement,
                                    "3.3.5.9.8 & 3.3.5.9.11: If the lease state requested is a superset of Lease.LeaseState and Lease.Breaking is FALSE," +
                                    " the server MUST request promotion of the lease state from the underlying object store to the new caching state.");

                                ModelHelper.Log(
                                    LogType.TestInfo,
                                    "Assume that Lease.Breaking is FALSE as no lease break happens");

                                Open.Lease.LeaseState = ReplayModelLeaseState.LeaseStateIncludeH;

                                ModelHelper.Log(
                                    LogType.TestInfo,
                                    "Open.Lease.LeaseState is {0}", Open.Lease.LeaseState);
                            }
                        }

                        #endregion

                        ModelHelper.Log(
                            LogType.Requirement,
                            "3.3.5.9.10: The server MUST construct the create response from Open, as specified in the \"Response Construction\" phase," +
                            " with the following additional steps, and send the response to client");

                        if (createRequest.modelDurableHandle == ReplayModelDurableHandle.DurableHandleV2 &&
                            (Open.OplockLevel == ReplayModelRequestedOplockLevel.OplockLevelBatch ||
                             (Open.Lease != null && Open.Lease.LeaseState != ReplayModelLeaseState.LeaseStateIncludeH)))
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.10: 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:");
                            ModelHelper.Log(
                                LogType.Requirement,
                                "Open.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH");
                            ModelHelper.Log(
                                LogType.Requirement,
                                "Open.Lease.LeaseState has SMB2_LEASE_HANDLE_CACHING bit set");

                            Condition.IsTrue(durableHandleResponse == ReplayModelDurableHandle.NormalHandle);
                            break;
                        }

                        if (Open.IsPersistent)
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.10: 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 TRUE");

                            Condition.IsTrue(durableHandleResponse == ReplayModelDurableHandle.DurableHandleV2Persistent);
                            Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS);
                        }
                        else
                        {
                            ModelHelper.Log(
                                LogType.TestInfo,
                                "Open.IsPersistent is FALSE");

                            Condition.IsTrue(status == ModelSmb2Status.STATUS_SUCCESS);
                        }
                    }

                    #endregion

                } while (false);

                // Create an open
                if (status == ModelSmb2Status.STATUS_SUCCESS && Open == null)
                {
                    Open = new ReplayOpen();
                }

                if (createRequest.modelDurableHandle == ReplayModelDurableHandle.DurableHandleV1)
                {
                    if (!(createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelBatch ||
                          ((createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 ||
                            createRequest.requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV2) && 
                           createRequest.leaseState == ReplayModelLeaseState.LeaseStateIncludeH)))
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "3.3.5.9.6: 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,
                            "RequestedOplockLevel is {0}, LeaseState is {1}", createRequest.requestedOplockLevel,
                            createRequest.leaseState);

                        Condition.IsFalse(durableHandleResponse == ReplayModelDurableHandle.DurableHandleV1);
                    }
                    else
                    {
                        if (Open != null)
                        {
                            ModelHelper.Log(
                                LogType.Requirement,
                                "3.3.5.9.6 In the \"Successful Open Initialization\" phase, the server MUST set Open.IsDurable to TRUE.");

                            Open.IsDurable = true;

                            ModelHelper.Log(
                                LogType.TestInfo,
                                "Open.IsDurable is set to TRUE");
                        }
                    }
                }
            }

            // 3.3.4.1 Sending Any Outgoing Message
            PostCheckChannelSequence(ReplayModelRequestCommand.Create, createRequest.channel.Connection_NegotiateDialect,
                createRequest.channelSequence);

            Condition.IfThen(status != ModelSmb2Status.STATUS_SUCCESS, durableHandleResponse == ReplayModelDurableHandle.NormalHandle);
        }
        public static void FileOperationResponse(ModelSmb2Status status, ReplayServerConfig c)
        {
            Condition.IsTrue(State == ModelState.Connected);

            Condition.IsTrue(Config == c);

            Condition.IsNotNull(Request);

            ModelReplayFileOperationRequest operationRequest = ModelHelper.RetrieveOutstandingRequest<ModelReplayFileOperationRequest>(ref Request);

            // 3.3.5.2.10 Verifying the Channel Sequence Number
            PreCheckChannelSequence(operationRequest.requestCommand,
                operationRequest.channel.Connection_NegotiateDialect,
                ref operationRequest.channelSequence,
                operationRequest.isSetReplayFlag == ReplayModelSetReplayFlag.WithReplayFlag,
                status);

            // 3.3.4.1 Sending Any Outgoing Message
            PostCheckChannelSequence(operationRequest.requestCommand,
                operationRequest.channel.Connection_NegotiateDialect,
                operationRequest.channelSequence);
        }
        public static void ReadConfigReturn(ReplayServerConfig c)
        {
            Condition.IsTrue(State == ModelState.Uninitialized);
            Condition.IsNotNull(c);

            Config = c;

            Open = null;
            LastOpen = null;
            MainChannel = null;
            AlternativeChannel = null;
            ModelRequestCommand = ReplayModelRequestCommand.NoRequest;

            State = ModelState.Initialized;
        }
        public void ReadConfig(out ReplayServerConfig c)
        {
            writeContent = Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb);

            c = new ReplayServerConfig
            {
                MaxSmbVersionSupported = ModelUtility.GetModelDialectRevision(testConfig.MaxSmbVersionSupported),
                IsDirectoryLeasingSupported = testConfig.IsDirectoryLeasingSupported,
                IsLeasingSupported = testConfig.IsLeasingSupported,
                IsPersistentHandleSupported = testConfig.IsPersistentHandlesSupported,
                TreeConnect_Share_Type_Include_STYPE_CLUSTER_SOFS = Boolean.Parse(testConfig.GetProperty("ShareTypeInclude_STYPE_CLUSTER_SOFS")),
                Platform = testConfig.Platform,
            };

            replayConfig = c;

            testConfig.CheckDialect(DialectRevision.Smb30);

            Site.Log.Add(LogEntryKind.Debug, c.ToString());
        }