/// <summary>
        /// Do operation to the file from the second client
        /// </summary>
        private void RequestFromSecondClient(RequestType requestFromSecondClient)
        {
            uint status = 0;
            Smb2CreateContextResponse[] contexts;
            switch (requestFromSecondClient)
            {
                case RequestType.ExclusiveLock:
                    // If the open is not created before, create here.
                    if (fileId2.Persistent == 0)
                    {
                        status = secondClient.Create(
                            treeId2,
                            fileName,
                            CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileId2,
                            out contexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            createDisposition: CreateDisposition_Values.FILE_OPEN,
                            checker: (header, response) => { });
                    }

                    // If open is created successfully, then do the specified file operation.
                    // Otherwise, return the status to Model.
                    if (fileId2.Persistent != 0)
                    {
                        status = secondClient.Lock(
                            treeId2,
                            0,
                            fileId2,
                            new LOCK_ELEMENT[]
                            {
                                new LOCK_ELEMENT
                                {
                                    Offset = 0,
                                    Length = (ulong)DEFAULT_WRITE_BUFFER_SIZE_IN_KB * 1024,
                                    Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY
                                }
                            },
                            checker: (header, response) => { });
                    }
                    HandleConflictResult(status);
                    break;
                case RequestType.Lease:
                    if (!testConfig.IsLeasingSupported)
                    {
                        // skip this case if leasing is not supported
                        Site.Assert.Inconclusive("This test case is applicable only when leasing is supported.");
                    }
                    status = secondClient.Create(
                        treeId2,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId2,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                        new Smb2CreateContextRequest[]
                        {
                            new Smb2CreateRequestLease
                            {
                                LeaseKey = Guid.NewGuid(),
                                LeaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING
                            }
                        },
                        createDisposition: CreateDisposition_Values.FILE_OPEN,
                        checker: (header, response) => { });
                    HandleConflictResult(status);
                    break;
                case RequestType.Delete:
                    if (fileId2.Persistent == 0)
                    {
                        status = secondClient.Create(
                            treeId2,
                            fileName,
                            CreateOptions_Values.FILE_DELETE_ON_CLOSE | CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileId2,
                            out contexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            createDisposition: CreateDisposition_Values.FILE_OPEN,
                            checker: (header, response) => { });
                    }

                    if (fileId2.Persistent != 0)
                    {
                        status = secondClient.Close(treeId2, fileId2, checker: (responseHeader, response) => { });
                    }
                    HandleConflictResult(status);
                    break;
                case RequestType.Write:
                    if (fileId2.Persistent == 0)
                    {
                        status = secondClient.Create(
                            treeId2,
                            fileName,
                            CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileId2,
                            out contexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            createDisposition: CreateDisposition_Values.FILE_OPEN,
                            checker: (header, response) => { });
                    }

                    if (fileId2.Persistent != 0)
                    {
                        status = secondClient.Write(
                            treeId2,
                            fileId2,
                            Smb2Utility.CreateRandomString(DEFAULT_WRITE_BUFFER_SIZE_IN_KB),
                            checker: (header, response) => { });
                    }
                    HandleConflictResult(status);
                    break;
                case RequestType.Read:
                    if (fileId2.Persistent == 0)
                    {
                        status = secondClient.Create(
                            treeId2,
                            fileName,
                            CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                            out fileId2,
                            out contexts,
                            RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE,
                            createDisposition: CreateDisposition_Values.FILE_OPEN,
                            checker: (header, response) => { });
                    }

                    if (fileId2.Persistent != 0)
                    {
                        byte[] data;
                        status = secondClient.Read(
                            treeId2,
                            fileId2,
                            0,
                            (uint)DEFAULT_WRITE_BUFFER_SIZE_IN_KB * 1024,
                            out data,
                            checker: (header, response) => { });
                    }
                    HandleConflictResult(status);
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// Do operation to the file from the first client
        /// </summary>
        private void RequestFromFirstClient(RequestType requestFromFirstClient)
        {
            Smb2CreateContextResponse[] contexts;
            switch (requestFromFirstClient)
            {
                case RequestType.ExclusiveLock:
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
                    firstClient.Lock(
                        treeId1,
                        0,
                        fileId1,
                        new LOCK_ELEMENT[]
                        {
                            new LOCK_ELEMENT
                            {
                                Offset = 0,
                                Length = DEFAULT_WRITE_BUFFER_SIZE_IN_KB * 1024,
                                Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY
                            }
                        });
                    break;
                case RequestType.Lease:
                    if (!testConfig.IsLeasingSupported)
                    {
                        // skip this case if leasing is not supported
                        Site.Assert.Inconclusive("This test case is applicable only when leasing is supported.");
                    }
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_LEASE,
                        new Smb2CreateContextRequest[]
                        {
                            new Smb2CreateRequestLease
                            {
                                LeaseKey = Guid.NewGuid(),
                                // [MS-SMB2] 3.3.5.9.8 
                                // If Connection.Dialect belongs to the SMB 3.x dialect family, TreeConnect.Share.Type includes STYPE_CLUSTER_SOFS, 
                                // and if LeaseState includes SMB2_LEASE_READ_CACHING, the server MUST set LeaseState to SMB2_LEASE_READ_CACHING, 
                                // otherwise set LeaseState to SMB2_LEASE_NONE.
                                // The share.type includes STYPE_CLUSTER_SOFS, so only READ_CACHING could be granted even the client applied for other lease.
                                // So the client only applies READ_CACHING here.
                                LeaseState = LeaseStateValues.SMB2_LEASE_READ_CACHING
                            }
                        });
                    break;
                case RequestType.UncommitedDelete:
                case RequestType.Delete:
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_DELETE_ON_CLOSE | CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);

                    // Close to delete the file
                    firstClient.Close(treeId1, fileId1);
                    break;
                case RequestType.Write:
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
                    firstClient.Write(treeId1, fileId1, Smb2Utility.CreateRandomString(DEFAULT_WRITE_BUFFER_SIZE_IN_KB));
                    break;
                case RequestType.Read:
                    firstClient.Create(
                        treeId1,
                        fileName,
                        CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                        out fileId1,
                        out contexts,
                        RequestedOplockLevel_Values.OPLOCK_LEVEL_NONE);
                    byte[] data;
                    firstClient.Read(treeId1, fileId1, 0, (uint)DEFAULT_WRITE_BUFFER_SIZE_IN_KB * 1024, out data);
                    break;
                default:
                    break;
            }
        }
        public void BVT_SMB2Basic_LockAndUnLock()
        {
            uint status;
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            #region From client1 lock a byte range and try to write content to the file within the range
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "From client1 locks a byte range and try to write content to the file within the range.");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start client1 to create a file with sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client1 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client1.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client1.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client1.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId1;
            status = client1.TreeConnect(uncSharePath, out treeId1);
            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fileId1;
            string fileName = Guid.NewGuid().ToString() + ".txt";
            status = client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 writes content to the file created.");
            status = client1.Write(treeId1, fileId1, content);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client1 by sending CLOSE request.");
            client1.Close(treeId1, fileId1);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 sends CREATE request.");
            status = client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            //Construct LOCK_ELEMENT
            LOCK_ELEMENT[] locks = new LOCK_ELEMENT[1];
            uint lockSequence = 0;
            locks[0].Offset = 0;
            locks[0].Length = (ulong)TestConfig.WriteBufferLengthInKb * 1024;
            locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 starts to lock a byte range for file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3})",
                fileName, locks[0].Offset, locks[0].Length, locks[0].Flags.ToString());
            status = client1.Lock(treeId1, lockSequence++, fileId1, locks);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 sends WRITE request to write content to the locking range");
            status = client1.Write(
                treeId1,
                fileId1,
                content,
                checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreNotEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
                    BaseTestSite.CaptureRequirementIfAreEqual(
                        Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                        header.Status,
                        RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                        RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
                });
            #endregion

            #region From client2 to read and write the locking range of the same file after lock
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "From client2 to read and take shared lock on the locking range of the same file after lock");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start client2 to create a file with sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client2 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client2.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client2.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client2.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId2;
            status = client2.TreeConnect(uncSharePath, out treeId2);
            FILEID fileId2;
            status = client2.Create(
                treeId2,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId2,
                out serverCreateContexts);

            string data;
            Random random = new Random();
            uint offset = (uint)random.Next(0, TestConfig.WriteBufferLengthInKb * 1024 - 1);
            uint length = (uint)random.Next(0, (int)(TestConfig.WriteBufferLengthInKb * 1024 - offset));
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends READ request to read a random area in the locking range of file \"{0}\" with offset: {1}, length: {2}",
                fileName, offset, length);
            status = client2.Read(treeId2, fileId2, offset, length, out data);

            //Construct LOCK_ELEMENT
            LOCK_ELEMENT[] locksFromOtherOpen = new LOCK_ELEMENT[1];
            locksFromOtherOpen[0].Offset = offset;
            locksFromOtherOpen[0].Length = (ulong)length;
            locksFromOtherOpen[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 attempts to take a shared lock on random range of file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3})",
                fileName, locksFromOtherOpen[0].Offset, locksFromOtherOpen[0].Length, locksFromOtherOpen[0].Flags.ToString());
            status = client2.Lock(treeId2, lockSequence++, fileId2, locksFromOtherOpen);

            locksFromOtherOpen[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 attempts to unlock the range");
            status = client2.Lock(treeId2, lockSequence++, fileId2, locksFromOtherOpen);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends WRITE request to write a random area in the locking range of file \"{0}\" after lock", fileName);
            status = client2.Write(
                treeId2,
                fileId2,
                content,
                offset,
                checker: (header, response) =>
                {
                    BaseTestSite.Assert.AreNotEqual(
                        Smb2Status.STATUS_SUCCESS,
                        header.Status,
                        "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
                    BaseTestSite.CaptureRequirementIfAreEqual(
                        Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                        header.Status,
                        RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                        RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
                });
            #endregion

            #region From client1 unlock the range
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 unlocks the range");
            locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK;
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Client1 attempts to unlock the range");
            status = client1.Lock(treeId1, lockSequence++, fileId1, locks);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client1 by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client1.Close(treeId1, fileId1);
            client1.TreeDisconnect(treeId1);
            client1.LogOff();
            #endregion

            #region From client2 write content to the previous locking range after unlock
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends WRITE request to write content to the previous locking range after unlock");
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Client2 attempts to write a random area in the locking range of file \"{0}\" after unlock", fileName);
            status = client2.Write(treeId2, fileId2, content, offset);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client2 by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client2.Close(treeId2, fileId2);
            client2.TreeDisconnect(treeId2);
            client2.LogOff();
            #endregion
        }
        public void BVT_SMB2Basic_LockAndUnLock()
        {
            uint   status;
            string content = Smb2Utility.CreateRandomString(TestConfig.WriteBufferLengthInKb);

            #region From client1 lock a byte range and try to write content to the file within the range
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "From client1 locks a byte range and try to write content to the file within the range.");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start client1 to create a file with sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client1 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client1.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client1.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client1.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId1;
            status = client1.TreeConnect(uncSharePath, out treeId1);
            Smb2CreateContextResponse[] serverCreateContexts;
            FILEID fileId1;
            string fileName = Guid.NewGuid().ToString() + ".txt";
            status = client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 writes content to the file created.");
            status = client1.Write(treeId1, fileId1, content);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client1 by sending CLOSE request.");
            client1.Close(treeId1, fileId1);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Client1 sends CREATE request.");
            status = client1.Create(
                treeId1,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId1,
                out serverCreateContexts);

            //Construct LOCK_ELEMENT
            LOCK_ELEMENT[] locks        = new LOCK_ELEMENT[1];
            uint           lockSequence = 0;
            locks[0].Offset = 0;
            locks[0].Length = (ulong)TestConfig.WriteBufferLengthInKb * 1024;
            locks[0].Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 starts to lock a byte range for file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3})",
                fileName, locks[0].Offset, locks[0].Length, locks[0].Flags.ToString());
            status = client1.Lock(treeId1, lockSequence++, fileId1, locks);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 sends WRITE request to write content to the locking range");
            status = client1.Write(
                treeId1,
                fileId1,
                content,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreNotEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
                BaseTestSite.CaptureRequirementIfAreEqual(
                    Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                    header.Status,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
            });
            #endregion

            #region From client2 to read and write the locking range of the same file after lock
            BaseTestSite.Log.Add(
                LogEntryKind.Comment,
                "From client2 to read and take shared lock on the locking range of the same file after lock");

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start client2 to create a file with sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            client2 = new Smb2FunctionalClient(TestConfig.Timeout, TestConfig, BaseTestSite);
            client2.ConnectToServer(TestConfig.UnderlyingTransport, TestConfig.SutComputerName, TestConfig.SutIPAddress);
            status = client2.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled);
            status = client2.SessionSetup(
                TestConfig.DefaultSecurityPackage,
                TestConfig.SutComputerName,
                TestConfig.AccountCredential,
                TestConfig.UseServerGssToken);
            uint treeId2;
            status = client2.TreeConnect(uncSharePath, out treeId2);
            FILEID fileId2;
            status = client2.Create(
                treeId2,
                fileName,
                CreateOptions_Values.FILE_NON_DIRECTORY_FILE,
                out fileId2,
                out serverCreateContexts);

            string data;
            Random random = new Random();
            uint   offset = (uint)random.Next(0, TestConfig.WriteBufferLengthInKb * 1024 - 1);
            uint   length = (uint)random.Next(0, (int)(TestConfig.WriteBufferLengthInKb * 1024 - offset));
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends READ request to read a random area in the locking range of file \"{0}\" with offset: {1}, length: {2}",
                fileName, offset, length);
            status = client2.Read(treeId2, fileId2, offset, length, out data);

            //Construct LOCK_ELEMENT
            LOCK_ELEMENT[] locksFromOtherOpen = new LOCK_ELEMENT[1];
            locksFromOtherOpen[0].Offset = offset;
            locksFromOtherOpen[0].Length = (ulong)length;
            locksFromOtherOpen[0].Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_SHARED_LOCK;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 attempts to take a shared lock on random range of file \"{0}\" with parameters offset:{1}, length:{2}, flags: {3})",
                fileName, locksFromOtherOpen[0].Offset, locksFromOtherOpen[0].Length, locksFromOtherOpen[0].Flags.ToString());
            status = client2.Lock(treeId2, lockSequence++, fileId2, locksFromOtherOpen);

            locksFromOtherOpen[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 attempts to unlock the range");
            status = client2.Lock(treeId2, lockSequence++, fileId2, locksFromOtherOpen);

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends WRITE request to write a random area in the locking range of file \"{0}\" after lock", fileName);
            status = client2.Write(
                treeId2,
                fileId2,
                content,
                offset,
                checker: (header, response) =>
            {
                BaseTestSite.Assert.AreNotEqual(
                    Smb2Status.STATUS_SUCCESS,
                    header.Status,
                    "All opens MUST NOT be allowed to write within the range when SMB2_LOCKFLAG_SHARED_LOCK set, actually server returns {0}.", Smb2Status.GetStatusCode(header.Status));
                BaseTestSite.CaptureRequirementIfAreEqual(
                    Smb2Status.STATUS_FILE_LOCK_CONFLICT,
                    header.Status,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Id,
                    RequirementCategory.STATUS_FILE_LOCK_CONFLICT.Description);
            });
            #endregion

            #region From client1 unlock the range
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client1 unlocks the range");
            locks[0].Flags = LOCK_ELEMENT_Flags_Values.LOCKFLAG_UNLOCK;
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Client1 attempts to unlock the range");
            status = client1.Lock(treeId1, lockSequence++, fileId1, locks);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client1 by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client1.Close(treeId1, fileId1);
            client1.TreeDisconnect(treeId1);
            client1.LogOff();
            #endregion

            #region From client2 write content to the previous locking range after unlock
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Client2 sends WRITE request to write content to the previous locking range after unlock");
            BaseTestSite.Log.Add(
                LogEntryKind.Debug,
                "Client2 attempts to write a random area in the locking range of file \"{0}\" after unlock", fileName);
            status = client2.Write(treeId2, fileId2, content, offset);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down client2 by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            client2.Close(treeId2, fileId2);
            client2.TreeDisconnect(treeId2);
            client2.LogOff();
            #endregion
        }
Esempio n. 5
0
        public void BVT_ResilientHandle_LockSequence()
        {
            #region Check Applicability
            TestConfig.CheckDialect(DialectRevision.Smb21);
            TestConfig.CheckIOCTL(CtlCode_Values.FSCTL_LMR_REQUEST_RESILIENCY);
            TestConfig.CheckCreateContext(CreateContextTypeValue.SMB2_CREATE_DURABLE_HANDLE_RECONNECT);
            #endregion

            Guid clientGuid = Guid.NewGuid();

            #region clientBeforeDisconnection Create a File
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start the first client to create a file by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE.");
            clientBeforeDisconnection.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid);
            clientBeforeDisconnection.SessionSetup(TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            uint treeId;
            clientBeforeDisconnection.TreeConnect(sharePath, out treeId);
            FILEID fileId;
            Smb2CreateContextResponse[] createContextResponse;
            clientBeforeDisconnection.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse);
            #endregion

            #region Request Resilient Handle
            IOCTL_Response IOCTLResponse;
            byte[]         inputInResponse;
            byte[]         outputInResponse;
            Packet_Header  packetHeader;
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The first client sends an IOCTL FSCTL_LMR_REQUEST_RESILLIENCY request.");
            clientBeforeDisconnection.ResiliencyRequest(treeId, fileId, TestConfig.MaxResiliencyTimeoutInSecond * 1000,
                                                        NETWORK_RESILIENCY_REQUEST_SIZE, out packetHeader, out IOCTLResponse, out inputInResponse, out outputInResponse);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends WRITE request.");
            clientBeforeDisconnection.Write(treeId, fileId, "12345678");

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The first client sends Flush request.");
            clientBeforeDisconnection.Flush(treeId, fileId);
            #endregion

            //The LockSequence field of the SMB2 lock request MUST be set to (BucketNumber<< 4) + BucketSequence.
            int  bucketNum    = 1;
            int  bucketSeq    = 1;
            uint lockSequence = (uint)bucketNum << 4 + bucketSeq;

            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "The first client sends LOCK request with LockSequence set to (BucketNumber<< 4) + BucketSequence");
            clientBeforeDisconnection.Lock(treeId,
                                           lockSequence,
                                           fileId,
                                           new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            });

            clientBeforeDisconnection.Disconnect();

            #region clientAfterDisconnection Opens the Previously Created File
            BaseTestSite.Log.Add(
                LogEntryKind.TestStep,
                "Start the second client to reconnect to the file created by the first client by sending the following requests: NEGOTIATE; SESSION_SETUP; TREE_CONNECT; CREATE (with SMB2_CREATE_DURABLE_HANDLE_RECONNECT Create Context).");
            clientAfterDisconnection.Negotiate(TestConfig.RequestDialects, TestConfig.IsSMB1NegotiateEnabled, clientGuid: clientGuid);
            clientAfterDisconnection.ReconnectSessionSetup(clientBeforeDisconnection,
                                                           TestConfig.DefaultSecurityPackage, TestConfig.SutComputerName, TestConfig.AccountCredential, false);
            clientAfterDisconnection.TreeConnect(sharePath, out treeId);
            clientAfterDisconnection.Create(treeId, fileName, CreateOptions_Values.FILE_NON_DIRECTORY_FILE, out fileId, out createContextResponse, RequestedOplockLevel_Values.OPLOCK_LEVEL_BATCH,
                                            new Smb2CreateContextRequest[]
            {
                new Smb2CreateDurableHandleReconnect
                {
                    Data = fileId
                }
            });
            #endregion

            //If the sequence numbers are equal, the server MUST complete the lock/unlock request with success.
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "The second client sends LOCK request with the same LockSequence with the first client.");
            clientAfterDisconnection.Lock(treeId,
                                          lockSequence, //Using same Lock Sequence
                                          fileId,
                                          new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            });

            clientAfterDisconnection.Lock(treeId,
                                          lockSequence + 1, //Using different Lock Sequence
                                          fileId,
                                          new LOCK_ELEMENT[]
            {
                new LOCK_ELEMENT
                {
                    Flags  = LOCK_ELEMENT_Flags_Values.LOCKFLAG_EXCLUSIVE_LOCK | LOCK_ELEMENT_Flags_Values.LOCKFLAG_FAIL_IMMEDIATELY,
                    Offset = 0,
                    Length = 4
                }
            },
                                          (header, response) =>
            {
                BaseTestSite.Assert.AreEqual(
                    Smb2Status.STATUS_LOCK_NOT_GRANTED,
                    header.Status,
                    "If the range being locked is already locked by another open in a way that does not allow this open to take a lock on the range, " +
                    "and if SMB2_LOCKFLAG_FAIL_IMMEDIATELY is set, the server MUST fail the request with STATUS_LOCK_NOT_GRANTED. " +
                    "Actually server returns {0}.",
                    Smb2Status.GetStatusCode(header.Status));
            });

            #region Tear Down Client
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Tear down the second client by sending the following requests: CLOSE; TREE_DISCONNECT; LOG_OFF");
            clientAfterDisconnection.Close(treeId, fileId);
            clientAfterDisconnection.TreeDisconnect(treeId);
            clientAfterDisconnection.LogOff();
            #endregion
        }