예제 #1
0
 public ModelReplayCreateRequest(ModelReplayChannel channel,
                                 ReplayModelSwitchChannelType switchChannelType,
                                 ReplayModelChannelSequenceType channelSequence,
                                 ReplayModelDurableHandle modelDurableHandle,
                                 ReplayModelRequestedOplockLevel requestedOplockLevel,
                                 ReplayModelFileName fileName,
                                 ReplayModelCreateGuid createGuid,
                                 ReplayModelFileAttributes fileAttributes,
                                 ReplayModelCreateDisposition createDisposition,
                                 ReplayModelLeaseState leaseState,
                                 ReplayModelSetReplayFlag isSetReplayFlag,
                                 ReplayModelLeaseKey leaseKey)
     : base(0)
 {
     this.channel              = channel;
     this.switchChannelType    = switchChannelType;
     this.channelSequence      = channelSequence;
     this.modelDurableHandle   = modelDurableHandle;
     this.requestedOplockLevel = requestedOplockLevel;
     this.fileName             = fileName;
     this.createGuid           = createGuid;
     this.fileAttributes       = fileAttributes;
     this.createDisposition    = createDisposition;
     this.leaseState           = leaseState;
     this.isSetReplayFlag      = isSetReplayFlag;
     this.leaseKey             = leaseKey;
 }
예제 #2
0
 public ModelReplayFileOperationRequest(ModelReplayChannel channel,
                                        ReplayModelSwitchChannelType switchChannelType,
                                        ModelDialectRevision maxSmbVersionClientSupported,
                                        ReplayModelRequestCommand requestCommand,
                                        ReplayModelChannelSequenceType channelSequence,
                                        ReplayModelSetReplayFlag isSetReplayFlag,
                                        ReplayModelRequestCommandParameters requestCommandParameters
                                        )
     : base(0)
 {
     this.channel                  = channel;
     this.switchChannelType        = switchChannelType;
     this.requestCommand           = requestCommand;
     this.channelSequence          = channelSequence;
     this.isSetReplayFlag          = isSetReplayFlag;
     this.requestCommandParameters = requestCommandParameters;
 }
        private void FillChannelSequence(Smb2FunctionalClient client, ReplayModelChannelSequenceType channelSequence)
        {
            switch (channelSequence)
            {
            case ReplayModelChannelSequenceType.ChannelSequenceIncrementOne:
                client.SessionChannelSequence = 1;
                break;

            case ReplayModelChannelSequenceType.ChannelSequenceBoundaryValid:
                client.SessionChannelSequence = 0x7FFF;
                break;

            case ReplayModelChannelSequenceType.InvalidChannelSequence:
                client.SessionChannelSequence = 0x8000;
                break;

            default:
                break;
            }
        }
 public ModelReplayFileOperationRequest(ModelReplayChannel channel,
     ReplayModelSwitchChannelType switchChannelType,
     ModelDialectRevision maxSmbVersionClientSupported,
     ReplayModelRequestCommand requestCommand,
     ReplayModelChannelSequenceType channelSequence,
     ReplayModelSetReplayFlag isSetReplayFlag,
     ReplayModelRequestCommandParameters requestCommandParameters
     )
     : base(0)
 {
     this.channel = channel;
     this.switchChannelType = switchChannelType;
     this.requestCommand = requestCommand;
     this.channelSequence = channelSequence;
     this.isSetReplayFlag = isSetReplayFlag;
     this.requestCommandParameters = requestCommandParameters;
 }
 public ModelReplayCreateRequest(ModelReplayChannel channel,
     ReplayModelSwitchChannelType switchChannelType,
     ReplayModelChannelSequenceType channelSequence,
     ReplayModelDurableHandle modelDurableHandle,
     ReplayModelRequestedOplockLevel requestedOplockLevel,
     ReplayModelFileName fileName,
     ReplayModelCreateGuid createGuid,
     ReplayModelFileAttributes fileAttributes,
     ReplayModelCreateDisposition createDisposition,
     ReplayModelLeaseState leaseState,
     ReplayModelSetReplayFlag isSetReplayFlag,
     ReplayModelLeaseKey leaseKey)
     : base(0)
 {
     this.channel = channel;
     this.switchChannelType = switchChannelType;
     this.channelSequence = channelSequence;
     this.modelDurableHandle = modelDurableHandle;
     this.requestedOplockLevel = requestedOplockLevel;
     this.fileName = fileName;
     this.createGuid = createGuid;
     this.fileAttributes = fileAttributes;
     this.createDisposition = createDisposition;
     this.leaseState = leaseState;
     this.isSetReplayFlag = isSetReplayFlag;
     this.leaseKey = leaseKey;
 }
        public void FileOperationRequest(
            ReplayModelSwitchChannelType switchChannelType,
            ModelDialectRevision maxSmbVersionClientSupported,
            ReplayModelRequestCommand requestCommand,
            ReplayModelChannelSequenceType channelSequence,
            ReplayModelSetReplayFlag isReplay,
            ReplayModelRequestCommandParameters requestCommandParameters)
        {
            if (requestCommand == ReplayModelRequestCommand.IoCtl)
            {
                testConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            }

            uint status = Smb2Status.STATUS_SUCCESS;
            Smb2FunctionalClient client = null;

            #region Switch channel
            switch (switchChannelType)
            {
            case ReplayModelSwitchChannelType.MainChannel:
                if (smb2ClientMainChannel == null)
                {
                    InitializeMainChannel(
                        maxSmbVersionClientSupported,
                        clientGuidMainChannel,
                        ReplayModelShareType.NonCAShare,
                        out treeIdMainChannel);

                    #region Create
                    Smb2CreateContextResponse[] serverCreateContexts = null;

                    status = smb2ClientMainChannel.Create(
                        treeIdMainChannel,
                        fileNameMainChannel,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileIdMainChannel,
                        out serverCreateContexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                        null,
                        shareAccess: ShareAccess_Values.NONE);
                    #endregion
                }
                client = smb2ClientMainChannel;
                break;

            case ReplayModelSwitchChannelType.AlternativeChannelWithMainChannel:
                InitializeAlternativeChannel(
                    clientGuidMainChannel,
                    treeIdMainChannel);
                client = smb2ClientAlternativeChannel;
                break;

            case ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel:
                InitializeAlternativeChannel(
                    clientGuidMainChannel,
                    treeIdMainChannel);
                smb2ClientMainChannel.Disconnect();
                smb2ClientMainChannel = null;
                client = smb2ClientAlternativeChannel;
                break;

            case ReplayModelSwitchChannelType.MainChannelWithAlternativeChannel:
                InitializeAlternativeChannel(
                    clientGuidMainChannel,
                    treeIdMainChannel);
                client = smb2ClientMainChannel;
                break;

            default:
                Site.Assume.Fail("Unknown ReplayModelSwitchChannelType {0}.", switchChannelType);
                break;
            }
            #endregion

            #region Prepare data for read
            if (switchChannelType == ReplayModelSwitchChannelType.MainChannel && !prepared && requestCommand == ReplayModelRequestCommand.Read)
            {
                status = smb2ClientMainChannel.Write(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    writeContent);
            }
            #endregion

            FillChannelSequence(client, channelSequence);

            if (requestCommand == ReplayModelRequestCommand.Write)
            {
                #region Write
                status = client.Write(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? writeContent : Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb),
                    checker: (header, response) =>
                {
                },
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.SetInfo)
            {
                #region SetInfo
                if (requestCommandParameters == ReplayModelRequestCommandParameters.AlternativeParameters)
                {
                    endOfFileInformation.EndOfFile = 512;
                }
                byte[] buffer = TypeMarshal.ToBytes <FileEndOfFileInformation>(endOfFileInformation);

                status = client.SetFileAttributes(
                    treeIdMainChannel,
                    (byte)FileInformationClasses.FileEndOfFileInformation,
                    fileIdMainChannel,
                    buffer,
                    checker: (header, response) =>
                {
                },
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.IoCtl)
            {
                #region IOCtl
                Packet_Header  ioCtlHeader;
                IOCTL_Response ioCtlResponse;
                byte[]         inputInResponse;
                byte[]         outputInResponse;
                status = client.ResiliencyRequest(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    (uint)(requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? 0 : 2000),
                    (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)),
                    out ioCtlHeader,
                    out ioCtlResponse,
                    out inputInResponse,
                    out outputInResponse,
                    checker: (header, response) =>
                {
                    // do nothing, skip the exception
                }
                    );
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.Read)
            {
                #region Read
                string data;
                status = client.Read(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    0,
                    requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? (uint)testConfig.WriteBufferLengthInKb * 1024 : 512,
                    out data,
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }

            FileOperationResponse((ModelSmb2Status)status, replayConfig);
        }
        public void CreateRequest(
            ModelDialectRevision maxSmbVersionClientSupported,
            ReplayModelShareType shareType,
            ReplayModelClientSupportPersistent isClientSupportPersistent,
            ReplayModelSwitchChannelType switchChannelType,
            ReplayModelChannelSequenceType channelSequence,
            ReplayModelSetReplayFlag isSetReplayFlag,
            ReplayModelDurableHandle modelDurableHandle,
            ReplayModelRequestedOplockLevel requestedOplockLevel,
            ReplayModelLeaseState leaseState,
            ReplayModelFileName fileName,
            ReplayModelCreateGuid createGuid,
            ReplayModelFileAttributes fileAttributes,
            ReplayModelCreateDisposition createDisposition,
            ReplayModelLeaseKey leaseKey)
        {
            Smb2FunctionalClient client = null;

            switch (switchChannelType)
            {
            case ReplayModelSwitchChannelType.MainChannel:
            {
                if (smb2ClientMainChannel == null)
                {
                    InitializeMainChannel(maxSmbVersionClientSupported, clientGuidMainChannel, shareType,
                                          out treeIdMainChannel, false,
                                          isClientSupportPersistent == ReplayModelClientSupportPersistent.ClientSupportPersistent);
                }
                break;
            }

            case ReplayModelSwitchChannelType.ReconnectMainChannel:
            {
                Site.Assume.IsNotNull(smb2ClientMainChannel, "Main channel is expected to exist.");
                smb2ClientMainChannel.Disconnect();
                smb2ClientMainChannel = null;
                InitializeMainChannel(maxSmbVersionClientSupported, clientGuidMainChannel, shareType,
                                      out treeIdMainChannel, true,
                                      isClientSupportPersistent == ReplayModelClientSupportPersistent.ClientSupportPersistent);
                break;
            }

            default:     //AlternativeChannelWithMainChannel, AlternativeChannelWithDisconnectMainChannel, MainChannelWithAlternativeChannel
            {
                InitializeAlternativeChannel(
                    clientGuidMainChannel,
                    treeIdMainChannel,
                    isClientSupportPersistent == ReplayModelClientSupportPersistent.ClientSupportPersistent);

                if (switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel)
                {
                    smb2ClientMainChannel.Disconnect();
                    smb2ClientMainChannel = null;
                }
                break;
            }
            }

            if (switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel ||
                switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithMainChannel)
            {
                client = smb2ClientAlternativeChannel;
            }
            else
            {
                client = smb2ClientMainChannel;
            }

            Smb2CreateContextRequest[]  contexts;
            RequestedOplockLevel_Values oplockLevel;
            LeaseStateValues            requestLeaseState;

            FillParameters(leaseState,
                           requestedOplockLevel,
                           modelDurableHandle,
                           createGuid == ReplayModelCreateGuid.DefaultCreateGuid ? createGuidMainChannel : Guid.NewGuid(),
                           leaseKey == ReplayModelLeaseKey.DefaultLeaseKey ? leaseKeyMainChannel : Guid.NewGuid(),
                           out requestLeaseState,
                           out oplockLevel,
                           out contexts);

            FillChannelSequence(client, channelSequence);

            Smb2CreateContextResponse[] serverCreateContexts;
            ulong createRequestId;

            client.CreateRequest(
                treeIdMainChannel,
                fileName == ReplayModelFileName.DefaultFileName ? fileNameMainChannel : Guid.NewGuid().ToString(),
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                (isSetReplayFlag == ReplayModelSetReplayFlag.WithReplayFlag ? Packet_Header_Flags_Values.FLAGS_REPLAY_OPERATION : Packet_Header_Flags_Values.NONE) | (testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE),
                out createRequestId,
                oplockLevel,
                contexts,
                createDisposition: createDisposition == ReplayModelCreateDisposition.DefaultCreateDisposition ? CreateDisposition_Values.FILE_OPEN_IF : CreateDisposition_Values.FILE_OVERWRITE_IF,
                fileAttributes: fileAttributes == ReplayModelFileAttributes.DefaultFileAttributes ? File_Attributes.NONE : File_Attributes.FILE_ATTRIBUTE_TEMPORARY
                );

            uint status = client.CreateResponse(
                createRequestId,
                out fileIdMainChannel,
                out serverCreateContexts,
                checker: (header, response) =>
            {
            }
                );

            CreateResponse(
                (ModelSmb2Status)status,
                ConvertHandle(serverCreateContexts),
                replayConfig);
        }
        public static void CreateRequest(
            ModelDialectRevision maxSmbVersionClientSupported,
            ReplayModelShareType shareType,
            ReplayModelClientSupportPersistent clientPersistentCapability,
            ReplayModelSwitchChannelType switchChannelType,
            ReplayModelChannelSequenceType channelSequence,
            ReplayModelSetReplayFlag isSetReplayFlag,
            ReplayModelDurableHandle modelDurableHandle,
            ReplayModelRequestedOplockLevel requestedOplockLevel,
            ReplayModelLeaseState leaseState,
            ReplayModelFileName fileName,
            ReplayModelCreateGuid createGuid,
            ReplayModelFileAttributes fileAttributes,
            ReplayModelCreateDisposition createDisposition,
            ReplayModelLeaseKey leaseKey)
        {
            Condition.IsTrue(State == ModelState.Connected || State == ModelState.Initialized);
            Condition.IsNull(Request);

            Combination.NWise(2, maxSmbVersionClientSupported, shareType, clientPersistentCapability, switchChannelType, channelSequence, isSetReplayFlag, modelDurableHandle,
                requestedOplockLevel, leaseState, fileName, createGuid, fileAttributes, createDisposition, leaseKey);

            Combination.Isolated(channelSequence == ReplayModelChannelSequenceType.InvalidChannelSequence);
            Combination.Isolated(channelSequence == ReplayModelChannelSequenceType.ChannelSequenceBoundaryValid);

            //No lease for non durable handle 
            Condition.IfThen(modelDurableHandle == ReplayModelDurableHandle.NormalHandle,
                requestedOplockLevel != ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 &&
                requestedOplockLevel != ReplayModelRequestedOplockLevel.OplockLevelLeaseV2);

            //No lease state or lease key(default) if not requesting lease
            Condition.IfThen(
                requestedOplockLevel != ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 &&
                requestedOplockLevel != ReplayModelRequestedOplockLevel.OplockLevelLeaseV2,
                leaseState == ReplayModelLeaseState.LeaseStateIsNone && leaseKey == ReplayModelLeaseKey.DefaultLeaseKey);

            //Ensure valid lease state if requesting lease
            Condition.IfThen(
                requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 ||
                requestedOplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV2,
                leaseState != ReplayModelLeaseState.LeaseStateIsNone);

            if (State == ModelState.Initialized)
            {
                Condition.IsTrue(switchChannelType == ReplayModelSwitchChannelType.MainChannel);

                DialectRevision negotiateDialect = ModelHelper.DetermineNegotiateDialect(maxSmbVersionClientSupported,
                    Config.MaxSmbVersionSupported);

                MainChannel = new ModelReplayChannel(negotiateDialect, shareType,
                    clientPersistentCapability == ReplayModelClientSupportPersistent.ClientSupportPersistent);
            }
            else // There's already an open exist
            {
                //Open eixsts
                Condition.IsTrue(Open != null);

                // Ensure same dialect
                Condition.IsTrue(ModelUtility.GetDialectRevision(maxSmbVersionClientSupported) == MainChannel.Connection_NegotiateDialect);

                // Ensure connect to same share
                Condition.IsTrue(shareType == MainChannel.Connection_Session_TreeConnect_Share_IsCA);

                switch (switchChannelType)
                {
                    case ReplayModelSwitchChannelType.MainChannel:
                    {
                        Condition.IsTrue((clientPersistentCapability ==
                                          ReplayModelClientSupportPersistent.ClientSupportPersistent) ==
                                         MainChannel.Connection_ClientCapabilities_SupportPersistent);
                        break;
                    }
                    case ReplayModelSwitchChannelType.ReconnectMainChannel:
                    {
                        MainChannel.Connection_ClientCapabilities_SupportPersistent =
                            (clientPersistentCapability == ReplayModelClientSupportPersistent.ClientSupportPersistent);
                        break;
                    }
                    case ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel:
                    case ReplayModelSwitchChannelType.AlternativeChannelWithMainChannel:
                    case ReplayModelSwitchChannelType.MainChannelWithAlternativeChannel:
                    {
                        AlternativeChannel = new ModelReplayChannel(MainChannel.Connection_NegotiateDialect, shareType,
                            clientPersistentCapability == ReplayModelClientSupportPersistent.ClientSupportPersistent);
                        break;
                    }
                }

                #region Handle state changes when there's connection lost or reconnection
                if (switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel ||
                    switchChannelType == ReplayModelSwitchChannelType.ReconnectMainChannel)
                {
                    bool isPreserved = false;

                    ModelHelper.Log(
                        LogType.Requirement,
                        "3.3.7.1: The server MUST iterate over the Session.OpenTable and determine whether each Open is to be preserved for reconnect." +
                        " If any of the following conditions is satisfied, it indicates that the Open is to be preserved for reconnect");
                    ModelHelper.Log(
                        LogType.TestInfo,
                        "Open.OplockLevel is {0}, Open.OplockState is {1}, Open.IsDurable {2}", Open.OplockLevel,
                        Open.OplockStateIsHeld ? "Held" : "not Held", Open.IsDurable);
                    if (Open.Lease != null)
                    {
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "LeaseState is {0}", Open.Lease.LeaseState);
                    }

                    if (switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel)
                    {
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "TD does not states the open is preserved when multi channels exist.");
                        isPreserved = true;
                    }
                    else if (Open.OplockLevel == ReplayModelRequestedOplockLevel.OplockLevelBatch &&
                             Open.OplockStateIsHeld &&
                             Open.IsDurable) // Open.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "Open.OplockLevel is equal to SMB2_OPLOCK_LEVEL_BATCH and Open.OplockState is equal to Held, and Open.IsDurable is TRUE");

                        isPreserved = true;

                        ModelHelper.Log(
                            LogType.TestInfo,
                            "Open is to be preserved for reconnect");
                    }
                    else if (((Open.OplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV1 ||
                               Open.OplockLevel == ReplayModelRequestedOplockLevel.OplockLevelLeaseV2) && 
                              Open.Lease != null &&
                              Open.Lease.LeaseState == ReplayModelLeaseState.LeaseStateIncludeH &&
                              Open.OplockStateIsHeld &&
                              Open.IsDurable)) // Open.OplockLevel is equal to SMB2_OPLOCK_LEVEL_LEASE and contains SMB2_LEASE_HANDLE_CACHING
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "Open.OplockLevel is equal to SMB2_OPLOCK_LEVEL_LEASE, Lease.LeaseState contains SMB2_LEASE_HANDLE_CACHING," +
                            " Open.OplockState is equal to Held, and Open.IsDurable is TRUE.");

                        isPreserved = true;

                        ModelHelper.Log(
                            LogType.TestInfo,
                            "Open is to be preserved for reconnect");
                    }
                    // "The server supports leasing and Open.IsResilient is TRUE" covered by resilient model

                    if (isPreserved)
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "If the Open is to be preserved for reconnect, perform the following actions:");
                        ModelHelper.Log(
                            LogType.Requirement,
                            "Set Open.Connection to NULL");
                        //Skip requirement for resilient handle which covered by resilient model

                        Open.ConnectionIsNotNull = false;
                    }
                    else
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "If the Open is not to be preserved for reconnect, the server MUST close the Open as specified in section 3.3.4.17");

                        LastOpen = Open;
                        Open = null;

                        ModelHelper.Log(
                            LogType.TestInfo,
                            "Open is set to NULL");
                    }
                }
                #endregion

            }

            ModelReplayChannel channel = GetChannel(switchChannelType);

            ModelReplayCreateRequest replayCreateRequest = 
                new ModelReplayCreateRequest(channel, switchChannelType, channelSequence, modelDurableHandle, requestedOplockLevel, fileName,
                    createGuid, fileAttributes, createDisposition, leaseState, isSetReplayFlag, leaseKey);

            Request = replayCreateRequest;
            State = ModelState.Connected;
        }
        /// <summary>
        /// 3.3.4.1 Sending Any Outgoing Message
        /// </summary>
        /// <param name="requestCommand">Request command.</param>
        /// <param name="negotiateDialect">Negotiated dialect.</param>
        /// <param name="channelSequence">Session channel sequence.</param>
        private static void PostCheckChannelSequence(
            ReplayModelRequestCommand requestCommand,
            DialectRevision negotiateDialect,
            ReplayModelChannelSequenceType channelSequence)
        {
            //TODO: TD does not mention this
            if (requestCommand == ReplayModelRequestCommand.Create)
            {
                ModelHelper.Log(
                    LogType.TestInfo,
                    "If the command request does not include FileId, this section MUST be skipped");
                ModelHelper.Log(
                    LogType.TestInfo,
                    "Connection.Dialect is {0}, request command is {1}", negotiateDialect, requestCommand);

                return;
            }

            if (channelSequence == ReplayModelChannelSequenceType.DefaultChannelSequence)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.4.1: For the command requests which include FileId, if Connection.Dialect belongs to the SMB 3.x dialect family and ChannelSequence is equal to Open.ChannelSequence," +
                    " the server MUST decrement Open.OutstandingRequestCount by 1. ");

                Open.OutstandingRequestCount -= 1;

                ModelHelper.Log(
                    LogType.TestInfo,
                    "Open.OutstandingRequestCount is {0} after decrement", Open.OutstandingRequestCount);
            }
            else
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.4.1: Otherwise, the server MUST decrement Open.OutstandingPreRequestCount by 1. ");

                Open.OutstandingPreRequestCount -= 1;

                ModelHelper.Log(
                    LogType.TestInfo,
                    "Open.OutstandingPreRequestCount is {0} after decrement", Open.OutstandingPreRequestCount);
            }
        }
        /// <summary>
        /// Handle session channel sequence after receiving request.
        /// 3.3.5.2.10   Verifying the Channel Sequence Number
        /// </summary>
        /// <param name="requestCommand">Request command.</param>
        /// <param name="negotiateDialect">Negotiated dialect.</param>
        /// <param name="channelSequence">Session channel sequence.</param>
        /// <param name="isSetReplayFlag">Indicates whether a replay flag is set or not.</param>
        /// <param name="status">The status that server returns.</param>
        /// <returns></returns>
        private static bool PreCheckChannelSequence(
            ReplayModelRequestCommand requestCommand,
            DialectRevision negotiateDialect,
            ref ReplayModelChannelSequenceType channelSequence,
            bool isSetReplayFlag,
            ModelSmb2Status status)
        {
            if (negotiateDialect == DialectRevision.Smb2002 || negotiateDialect == DialectRevision.Smb21 ||
                requestCommand == ReplayModelRequestCommand.Create)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.2.10: If Connection.Dialect is equal to \"2.002\" or \"2.100\", or the command request does not include FileId," +
                    " this section MUST be skipped");
                ModelHelper.Log(
                    LogType.TestInfo,
                    "Connection.Dialect is {0}. The request command is {1}", negotiateDialect, requestCommand);
                ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                return true;
            }

            if (!isSetReplayFlag)
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.2.10: If the SMB2_FLAGS_REPLAY_OPERATION bit is not set in the Flags field of the SMB2 Header:");
                ModelHelper.Log(LogType.TestTag, TestTag.UnexpectedFields);

                if (channelSequence == ReplayModelChannelSequenceType.DefaultChannelSequence)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "If ChannelSequence in the SMB2 Header is equal to Open.ChannelSequence, the server MUST increment Open.OutstandingRequestCount by 1.");

                    Open.OutstandingRequestCount += 1;

                    ModelHelper.Log(
                        LogType.TestInfo,
                        "Open.OutstandingRequestCount is {0} after increment", Open.OutstandingRequestCount);
                }
                else if (channelSequence == ReplayModelChannelSequenceType.ChannelSequenceIncrementOne ||
                          channelSequence == ReplayModelChannelSequenceType.ChannelSequenceBoundaryValid)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "Otherwise, if the unsigned difference using 16-bit arithmetic between ChannelSequence and Open.ChannelSequence is less than or equal to 0x7FFF," +
                        " the server MUST increment Open.OutstandingPreRequestCount by Open.OutstandingRequestCount, and MUST set Open.OutstandingRequestCount to 1." +
                        " The server MUST set Open.ChannelSequence to ChannelSequence in the SMB2 Header");
                    ModelHelper.Log(
                        LogType.TestInfo,
                        "ChannelSequence is {0}", channelSequence);

                    Open.OutstandingPreRequestCount += Open.OutstandingRequestCount;
                    Open.OutstandingRequestCount = 1;
                    channelSequence = ReplayModelChannelSequenceType.DefaultChannelSequence;

                    ModelHelper.Log(
                        LogType.TestInfo,
                        "Open.OutstandingPreRequestCount is {0} after increment by Open.OutstandingRequestCount with value {1}",
                        Open.OutstandingPreRequestCount, Open.OutstandingRequestCount);
                }
                else
                {
                    if (requestCommand == ReplayModelRequestCommand.Write ||
                        requestCommand == ReplayModelRequestCommand.SetInfo ||
                        requestCommand == ReplayModelRequestCommand.IoCtl)
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "Otherwise, the server MUST fail SMB2 WRITE, SET_INFO, and IOCTL requests with STATUS_FILE_NOT_AVAILABLE");
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "requestCommand is {0}", requestCommand);

                        Condition.IsTrue(status == ModelSmb2Status.STATUS_FILE_NOT_AVAILABLE);
                        return false;
                    }
                }
            }
            else
            {
                ModelHelper.Log(
                    LogType.Requirement,
                    "3.3.5.2.10: If the SMB2_FLAGS_REPLAY_OPERATION bit is set in the Flags field of the SMB2 Header:");

                if (channelSequence == ReplayModelChannelSequenceType.DefaultChannelSequence)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "If ChannelSequence in the SMB2 Header is equal to Open.ChannelSequence and the following:");

                    if (Open.OutstandingPreRequestCount == 0)
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "If ChannelSequence in the SMB2 Header is equal to Open.ChannelSequence and Open.OutstandingPreRequestCount is equal to zero, the server MUST increment Open.OutstandingRequestCount by 1");

                        Open.OutstandingRequestCount += 1;

                        ModelHelper.Log(
                            LogType.TestInfo,
                            "Open.OutstandingRequestCount is {0} after increment", Open.OutstandingRequestCount);
                    }
                }
                else if ((channelSequence == ReplayModelChannelSequenceType.ChannelSequenceIncrementOne ||
                          channelSequence == ReplayModelChannelSequenceType.ChannelSequenceBoundaryValid) &&
                         Open.OutstandingPreRequestCount == 0)
                {
                    ModelHelper.Log(
                        LogType.Requirement,
                        "Otherwise, if the unsigned difference using 16-bit arithmetic between ChannelSequence and Open.ChannelSequence is less than or equal to 0x7FFF and Open.OutstandingPreRequestCount is equal to zero," +
                        " the server MUST increment Open.OutstandingPreRequestCount by Open.OutstandingRequestCount and MUST set Open.OutstandingRequestCount to 1." +
                        " The server MUST set Open.ChannelSequence to ChannelSequence in the SMB2 Header.");

                    Open.OutstandingPreRequestCount += Open.OutstandingRequestCount;
                    Open.OutstandingRequestCount = 1;
                    channelSequence = ReplayModelChannelSequenceType.DefaultChannelSequence;

                    ModelHelper.Log(
                        LogType.TestInfo,
                        "Open.OutstandingPreRequestCount is {0} after increment by Open.OutstandingRequestCount with value {1}",
                        Open.OutstandingPreRequestCount, Open.OutstandingRequestCount);
                }
                else
                {
                    if (requestCommand == ReplayModelRequestCommand.Write ||
                        requestCommand == ReplayModelRequestCommand.SetInfo ||
                        requestCommand == ReplayModelRequestCommand.IoCtl)
                    {
                        ModelHelper.Log(
                            LogType.Requirement,
                            "Otherwise, the server MUST fail SMB2 WRITE, SET_INFO, and IOCTL requests with STATUS_FILE_NOT_AVAILABLE");
                        ModelHelper.Log(
                            LogType.TestInfo,
                            "requestCommand is {0}", requestCommand);
                        ModelHelper.Log(LogType.TestTag, TestTag.Compatibility);
                        Condition.IsTrue(status == ModelSmb2Status.STATUS_FILE_NOT_AVAILABLE);
                        return false;
                    }
                }
            }

            return true;
        }
        public static void FileOperationRequest(
            ReplayModelSwitchChannelType switchChannelType,
            ModelDialectRevision maxSmbVersionClientSupported,
            ReplayModelRequestCommand requestCommand,
            ReplayModelChannelSequenceType channelSequence,
            ReplayModelSetReplayFlag isSetReplayFlag,
            ReplayModelRequestCommandParameters requestCommandParameters)
        {
            Condition.IsNull(Request);
            Condition.IfThen(ModelRequestCommand != ReplayModelRequestCommand.NoRequest, ModelRequestCommand == requestCommand);
            Condition.IsTrue(requestCommand != ReplayModelRequestCommand.Create && requestCommand != ReplayModelRequestCommand.NoRequest);
            Condition.IsTrue(switchChannelType != ReplayModelSwitchChannelType.ReconnectMainChannel);

            Combination.NWise(2, switchChannelType, maxSmbVersionClientSupported, requestCommand, channelSequence, isSetReplayFlag, 
                requestCommandParameters);
            
            ModelReplayChannel channel = null;
            if (State == ModelState.Initialized)
            {
                Condition.IsTrue(switchChannelType == ReplayModelSwitchChannelType.MainChannel);
                Condition.IsTrue(requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters);

                MainChannel =
                    new ModelReplayChannel(ModelHelper.DetermineNegotiateDialect(maxSmbVersionClientSupported,
                        Config.MaxSmbVersionSupported));

                Open = new ReplayOpen();
                channel = MainChannel;
            }
            else
            {
                Condition.IsNotNull(MainChannel);
                Condition.IsNotNull(Open);
                Condition.IsTrue(maxSmbVersionClientSupported == ModelUtility.GetModelDialectRevision(MainChannel.Connection_NegotiateDialect));

                if (switchChannelType == ReplayModelSwitchChannelType.MainChannel)
                {
                    channel = MainChannel;
                }
                else
                {
                    AlternativeChannel = new ModelReplayChannel(MainChannel.Connection_NegotiateDialect);
                    channel = AlternativeChannel;
                }
            }

            ModelReplayFileOperationRequest operationRequest = new ModelReplayFileOperationRequest(channel, switchChannelType, 
                maxSmbVersionClientSupported, requestCommand, channelSequence, isSetReplayFlag, requestCommandParameters);

            Request = operationRequest;

            State = ModelState.Connected;
        }
        public void CreateRequest(
            ModelDialectRevision maxSmbVersionClientSupported,
            ReplayModelShareType shareType,
            ReplayModelClientSupportPersistent isClientSupportPersistent,
            ReplayModelSwitchChannelType switchChannelType,
            ReplayModelChannelSequenceType channelSequence,
            ReplayModelSetReplayFlag isSetReplayFlag,
            ReplayModelDurableHandle modelDurableHandle,
            ReplayModelRequestedOplockLevel requestedOplockLevel,
            ReplayModelLeaseState leaseState,
            ReplayModelFileName fileName,
            ReplayModelCreateGuid createGuid,
            ReplayModelFileAttributes fileAttributes,
            ReplayModelCreateDisposition createDisposition,
            ReplayModelLeaseKey leaseKey)
        {
            Smb2FunctionalClient client = null;

            switch (switchChannelType)
            {
                case ReplayModelSwitchChannelType.MainChannel:
                {
                    if (smb2ClientMainChannel == null)
                    {
                        InitializeMainChannel(maxSmbVersionClientSupported, clientGuidMainChannel, shareType,
                            out treeIdMainChannel, false,
                            isClientSupportPersistent == ReplayModelClientSupportPersistent.ClientSupportPersistent);
                    }
                    break;
                }
                case ReplayModelSwitchChannelType.ReconnectMainChannel:
                {
                    Site.Assume.IsNotNull(smb2ClientMainChannel, "Main channel is expected to exist.");
                    smb2ClientMainChannel.Disconnect();
                    smb2ClientMainChannel = null;
                    InitializeMainChannel(maxSmbVersionClientSupported, clientGuidMainChannel, shareType,
                        out treeIdMainChannel, true,
                        isClientSupportPersistent == ReplayModelClientSupportPersistent.ClientSupportPersistent);
                    break;
                }
                default: //AlternativeChannelWithMainChannel, AlternativeChannelWithDisconnectMainChannel, MainChannelWithAlternativeChannel
                {
                    InitializeAlternativeChannel(
                        clientGuidMainChannel,
                        treeIdMainChannel,
                        isClientSupportPersistent == ReplayModelClientSupportPersistent.ClientSupportPersistent);

                    if (switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel)
                    {
                        smb2ClientMainChannel.Disconnect();
                        smb2ClientMainChannel = null;
                    }
                    break;
                }
            }

            if (switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel ||
                switchChannelType == ReplayModelSwitchChannelType.AlternativeChannelWithMainChannel)
            {
                client = smb2ClientAlternativeChannel;
            }
            else
            {
                client = smb2ClientMainChannel;
            }

            Smb2CreateContextRequest[] contexts;
            RequestedOplockLevel_Values oplockLevel;
            LeaseStateValues requestLeaseState;

            FillParameters(leaseState,
                requestedOplockLevel,
                modelDurableHandle,
                createGuid == ReplayModelCreateGuid.DefaultCreateGuid ? createGuidMainChannel : Guid.NewGuid(),
                leaseKey == ReplayModelLeaseKey.DefaultLeaseKey ? leaseKeyMainChannel : Guid.NewGuid(),
                out requestLeaseState,
                out oplockLevel,
                out contexts);

            FillChannelSequence(client, channelSequence);

            Smb2CreateContextResponse[] serverCreateContexts;
            ulong createRequestId;
            client.CreateRequest(
                    treeIdMainChannel,
                    fileName == ReplayModelFileName.DefaultFileName ? fileNameMainChannel : Guid.NewGuid().ToString(),
                    CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                    (isSetReplayFlag == ReplayModelSetReplayFlag.WithReplayFlag ? Packet_Header_Flags_Values.FLAGS_REPLAY_OPERATION : Packet_Header_Flags_Values.NONE) | (testConfig.SendSignedRequest ? Packet_Header_Flags_Values.FLAGS_SIGNED : Packet_Header_Flags_Values.NONE),
                    out createRequestId,
                    oplockLevel,
                    contexts,
                    createDisposition: createDisposition == ReplayModelCreateDisposition.DefaultCreateDisposition ? CreateDisposition_Values.FILE_OPEN_IF : CreateDisposition_Values.FILE_OVERWRITE_IF,
                    fileAttributes: fileAttributes == ReplayModelFileAttributes.DefaultFileAttributes ? File_Attributes.NONE : File_Attributes.FILE_ATTRIBUTE_TEMPORARY
                 );

            uint status = client.CreateResponse(
                    createRequestId,
                    out fileIdMainChannel,
                    out serverCreateContexts,
                    checker: (header, response) =>
                    {
                    }
                 );

            CreateResponse(
                (ModelSmb2Status)status,
                ConvertHandle(serverCreateContexts),
                replayConfig);
        }
 private void FillChannelSequence(Smb2FunctionalClient client, ReplayModelChannelSequenceType channelSequence)
 {
     switch (channelSequence)
     {
         case ReplayModelChannelSequenceType.ChannelSequenceIncrementOne:
             client.SessionChannelSequence = 1;
             break;
         case ReplayModelChannelSequenceType.ChannelSequenceBoundaryValid:
             client.SessionChannelSequence = 0x7FFF;
             break;
         case ReplayModelChannelSequenceType.InvalidChannelSequence:
             client.SessionChannelSequence = 0x8000;
             break;
         default:
             break;
     }
 }
        public void FileOperationRequest(
            ReplayModelSwitchChannelType switchChannelType,
            ModelDialectRevision maxSmbVersionClientSupported,
            ReplayModelRequestCommand requestCommand,
            ReplayModelChannelSequenceType channelSequence,
            ReplayModelSetReplayFlag isReplay,
            ReplayModelRequestCommandParameters requestCommandParameters)
        {
            if (requestCommand == ReplayModelRequestCommand.IoCtl)
            {
                testConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            }

            uint status = Smb2Status.STATUS_SUCCESS;
            Smb2FunctionalClient client = null;

            #region Switch channel
            switch (switchChannelType)
            {
                case ReplayModelSwitchChannelType.MainChannel:
                    if (smb2ClientMainChannel == null)
                    {
                        InitializeMainChannel(
                            maxSmbVersionClientSupported,
                            clientGuidMainChannel,
                            ReplayModelShareType.NonCAShare,
                            out treeIdMainChannel);

                        #region Create
                        Smb2CreateContextResponse[] serverCreateContexts = null;

                        status = smb2ClientMainChannel.Create(
                            treeIdMainChannel,
                            fileNameMainChannel,
                            CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileIdMainChannel,
                            out serverCreateContexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            null,
                            shareAccess: ShareAccess_Values.NONE);
                        #endregion
                    }
                    client = smb2ClientMainChannel;
                    break;
                case ReplayModelSwitchChannelType.AlternativeChannelWithMainChannel:
                    InitializeAlternativeChannel(
                        clientGuidMainChannel,
                        treeIdMainChannel);
                    client = smb2ClientAlternativeChannel;
                    break;
                case ReplayModelSwitchChannelType.AlternativeChannelWithDisconnectMainChannel:
                    InitializeAlternativeChannel(
                        clientGuidMainChannel,
                        treeIdMainChannel);
                    smb2ClientMainChannel.Disconnect();
                    smb2ClientMainChannel = null;
                    client = smb2ClientAlternativeChannel;
                    break;
                case ReplayModelSwitchChannelType.MainChannelWithAlternativeChannel:
                    InitializeAlternativeChannel(
                        clientGuidMainChannel,
                        treeIdMainChannel);
                    client = smb2ClientMainChannel;
                    break;
                default:
                    Site.Assume.Fail("Unknown ReplayModelSwitchChannelType {0}.", switchChannelType);
                    break;
            }
            #endregion

            #region Prepare data for read
            if (switchChannelType == ReplayModelSwitchChannelType.MainChannel && !prepared && requestCommand == ReplayModelRequestCommand.Read)
            {
                status = smb2ClientMainChannel.Write(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    writeContent);
            }
            #endregion

            FillChannelSequence(client, channelSequence);

            if (requestCommand == ReplayModelRequestCommand.Write)
            {
                #region Write
                status = client.Write(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? writeContent : Smb2Utility.CreateRandomString(testConfig.WriteBufferLengthInKb),
                    checker: (header, response) =>
                    {
                    },
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.SetInfo)
            {
                #region SetInfo
                if (requestCommandParameters == ReplayModelRequestCommandParameters.AlternativeParameters)
                {
                    endOfFileInformation.EndOfFile = 512;
                }
                byte[] buffer = TypeMarshal.ToBytes<FileEndOfFileInformation>(endOfFileInformation);

                status = client.SetFileAttributes(
                    treeIdMainChannel,
                    (byte)FileInformationClasses.FileEndOfFileInformation,
                    fileIdMainChannel,
                    buffer,
                    checker: (header, response) =>
                    {
                    },
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.IoCtl)
            {
                #region IOCtl
                Packet_Header ioCtlHeader;
                IOCTL_Response ioCtlResponse;
                byte[] inputInResponse;
                byte[] outputInResponse;
                status = client.ResiliencyRequest(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    (uint)(requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? 0 : 2000),
                    (uint)Marshal.SizeOf(typeof(NETWORK_RESILIENCY_Request)),
                    out ioCtlHeader,
                    out ioCtlResponse,
                    out inputInResponse,
                    out outputInResponse,
                    checker: (header, response) =>
                    {
                        // do nothing, skip the exception
                    }
                    );
                #endregion
            }
            else if (requestCommand == ReplayModelRequestCommand.Read)
            {
                #region Read
                string data;
                status = client.Read(
                    treeIdMainChannel,
                    fileIdMainChannel,
                    0,
                    requestCommandParameters == ReplayModelRequestCommandParameters.DefaultParameters ? (uint)testConfig.WriteBufferLengthInKb * 1024 : 512,
                    out data,
                    isReplay: isReplay == ReplayModelSetReplayFlag.WithReplayFlag);
                #endregion
            }

            FileOperationResponse((ModelSmb2Status)status, replayConfig);
        }