public void FsCtl_RefsStreamSnapshotManagement_QueryDeltas_AccessDenied_LacksReadAttribute()
        {
            string fileName;
            ushort snapshotNameLength;

            byte[]     snapshotNameBytes;
            FileAccess fileAccess = FileAccess.GENERIC_WRITE | FileAccess.FILE_WRITE_DATA | FileAccess.FILE_WRITE_ATTRIBUTES;

            PrepareSnapshotQueryDeltas(out fileName, out snapshotNameLength, out snapshotNameBytes, fileAccess);

            REFS_STREAM_SNAPSHOT_QUERY_DELTAS_INPUT_BUFFER refsStreamSnapshotQueryDeltasInputBuffer = GetQueryDeltasInputBuffer();

            byte[] queryDetalsInputBuffer       = TypeMarshal.ToBytes(refsStreamSnapshotQueryDeltasInputBuffer);
            ushort queryDetalsInputBufferLength = (ushort)queryDetalsInputBuffer.Length;

            byte[] nameAndInputBuffer = new byte[snapshotNameLength + queryDetalsInputBufferLength];
            Buffer.BlockCopy(snapshotNameBytes, 0, nameAndInputBuffer, 0, snapshotNameLength);
            Buffer.BlockCopy(queryDetalsInputBuffer, 0, nameAndInputBuffer, snapshotNameLength, queryDetalsInputBufferLength);
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_QUERY_DELTAS,
                                                snapshotNameLength: snapshotNameLength, operationInputBufferLength: queryDetalsInputBufferLength, nameAndInputBuffer: nameAndInputBuffer);
            uint outputBufferSize = this.fsaAdapter.transBufferSize;

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.ACCESS_DENIED, outputBufferSize, fileAccess, fileName);
        }
        public void FsCtl_RefsStreamSnapshotManagement_InvalidParameter_SnapshotNameLengthNotALIGN()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_CREATE, (ushort)Test_Lengths.NOT_ALIGN, (ushort)Test_Lengths.NOT_ALIGN);

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.INVALID_PARAMETER);
        }
        public void BVT_FsCtl_RefsStreamSnapshotManagement_Create_IsSupported()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_CREATE);

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.SUCCESS);
        }
        public void BVT_FsCtl_RefsStreamSnapshotManagement_Invalid_IsSupported()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_INVALID);

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.INVALID_PARAMETER);
        }
        public void FsCtl_RefsStreamSnapshotManagement_List_InvalidParameter_OutputBufferSizeZero()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_LIST);

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.INVALID_PARAMETER);
        }
        public void FsCtl_RefsStreamSnapshotManagement_BufferTooSmall_OperationInputBufferLengthNotZero()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_CREATE,
                                                snapshotNameLength: (ushort)Test_Lengths.ALIGN_HALF, operationInputBufferLength: (ushort)Test_Lengths.ALIGN_HALF);

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.BUFFER_TOO_SMALL);
        }
        public void BVT_FsCtl_RefsStreamSnapshotManagement_List_IsSupported()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_LIST);
            uint outputBufferSize = this.fsaAdapter.transBufferSize;

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.SUCCESS, outputBufferSize);
        }
        public void FsCtl_RefsStreamSnapshotManagement_Create_AccessDenied_LacksWriteAttribute()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_CREATE);
            FileAccess fileAccess = FileAccess.GENERIC_READ | FileAccess.FILE_READ_DATA | FileAccess.FILE_READ_ATTRIBUTES;

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.ACCESS_DENIED, fileAccess: fileAccess);
        }
        public void FsCtl_RefsStreamSnapshotManagement_Create_InvalidParameter_OutputBufferSizeNotZero()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_CREATE);
            uint outputBufferSize = this.fsaAdapter.transBufferSize;

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.INVALID_PARAMETER, outputBufferSize);
        }
        public void FsCtl_RefsStreamSnapshotManagement_List_AccessDenied_LacksReadAttribute()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_LIST);
            uint       outputBufferSize = this.fsaAdapter.transBufferSize;
            FileAccess fileAccess       = FileAccess.GENERIC_WRITE | FileAccess.FILE_WRITE_DATA | FileAccess.FILE_WRITE_ATTRIBUTES;

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.ACCESS_DENIED, outputBufferSize, fileAccess);
        }
        public void FsCtl_RefsStreamSnapshotManagement_List_InvalidParameter_SnapshortNameLengthZero()
        {
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_LIST,
                                                snapshotNameLength: (ushort)Test_Lengths.ZERO, operationInputBufferLength: (ushort)Test_Lengths.ALIGN);
            uint outputBufferSize = this.fsaAdapter.transBufferSize;

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.INVALID_PARAMETER, outputBufferSize);
        }
        public void FsCtl_RefsStreamSnapshotManagement_QueryDeltas_InvalidParameter_SnapshotNameLengthZero()
        {
            REFS_STREAM_SNAPSHOT_QUERY_DELTAS_INPUT_BUFFER refsStreamSnapshotQueryDeltasInputBuffer = GetQueryDeltasInputBuffer();

            byte[] queryDetalsInputBuffer       = TypeMarshal.ToBytes(refsStreamSnapshotQueryDeltasInputBuffer);
            ushort queryDetalsInputBufferLength = (ushort)queryDetalsInputBuffer.Length;

            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_QUERY_DELTAS,
                                                snapshotNameLength: (ushort)Test_Lengths.ZERO, operationInputBufferLength: queryDetalsInputBufferLength, nameAndInputBuffer: queryDetalsInputBuffer);
            uint outputBufferSize = this.fsaAdapter.transBufferSize;

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.INVALID_PARAMETER, outputBufferSize);
        }
        public REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER GetRefsStreamSnapshotManagement(
            RefsStreamSnapshotOperation_Values operation_Values,
            ushort snapshotNameStringLength   = (ushort)Test_Lengths.ALIGN,
            ushort snapshotNameLength         = (ushort)Test_Lengths.ALIGN,
            ushort operationInputBufferLength = (ushort)Test_Lengths.ZERO,
            byte[] nameAndInputBuffer         = null
            )
        {
            string snapshotName = fsaAdapter.ComposeRandomFileName(snapshotNameStringLength);

            nameAndInputBuffer = nameAndInputBuffer == null?Encoding.ASCII.GetBytes(snapshotName) : nameAndInputBuffer;

            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput = new REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER();

            refsStreamSnapshotManagementInput.SnapshotNameLength         = snapshotNameLength;
            refsStreamSnapshotManagementInput.Operation                  = operation_Values;
            refsStreamSnapshotManagementInput.OperationInputBufferLength = operationInputBufferLength;
            refsStreamSnapshotManagementInput.NameAndInputBuffer         = nameAndInputBuffer;
            refsStreamSnapshotManagementInput.Reserved = Guid.Empty.ToByteArray();
            return(refsStreamSnapshotManagementInput);
        }
        public void FsCtl_RefsStreamSnapshotManagement_QueryDeltas_InvalidParameter_OutputBufferSizeZero()
        {
            string fileName;
            ushort snapshotNameLength;

            byte[] snapshotNameBytes;
            PrepareSnapshotQueryDeltas(out fileName, out snapshotNameLength, out snapshotNameBytes);

            REFS_STREAM_SNAPSHOT_QUERY_DELTAS_INPUT_BUFFER refsStreamSnapshotQueryDeltasInputBuffer = GetQueryDeltasInputBuffer();

            byte[] queryDetalsInputBuffer       = TypeMarshal.ToBytes(refsStreamSnapshotQueryDeltasInputBuffer);
            ushort queryDetalsInputBufferLength = (ushort)queryDetalsInputBuffer.Length;

            byte[] nameAndInputBuffer = new byte[snapshotNameLength + queryDetalsInputBufferLength];
            Buffer.BlockCopy(snapshotNameBytes, 0, nameAndInputBuffer, 0, snapshotNameLength);
            Buffer.BlockCopy(queryDetalsInputBuffer, 0, nameAndInputBuffer, snapshotNameLength, queryDetalsInputBufferLength);
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_QUERY_DELTAS,
                                                snapshotNameLength: snapshotNameLength, operationInputBufferLength: queryDetalsInputBufferLength, nameAndInputBuffer: nameAndInputBuffer);

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.INVALID_PARAMETER, fileName: fileName);
        }
        public void BVT_FsCtl_RefsStreamSnapshotManagement_Query_Deltas_IsSupported()
        {
            string fileName;
            ushort snapshotNameLength;

            byte[] snapshotNameBytes;
            PrepareSnapshotQueryDeltas(out fileName, out snapshotNameLength, out snapshotNameBytes);

            REFS_STREAM_SNAPSHOT_QUERY_DELTAS_INPUT_BUFFER refsStreamSnapshotQueryDeltasInputBuffer = GetQueryDeltasInputBuffer();

            byte[] queryDetalsInputBuffer       = TypeMarshal.ToBytes(refsStreamSnapshotQueryDeltasInputBuffer);
            ushort queryDetalsInputBufferLength = (ushort)queryDetalsInputBuffer.Length;

            byte[] nameAndInputBuffer = new byte[snapshotNameLength + queryDetalsInputBufferLength];
            Buffer.BlockCopy(snapshotNameBytes, 0, nameAndInputBuffer, 0, snapshotNameLength);
            Buffer.BlockCopy(queryDetalsInputBuffer, 0, nameAndInputBuffer, snapshotNameLength, queryDetalsInputBufferLength);
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput =
                GetRefsStreamSnapshotManagement(RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_QUERY_DELTAS,
                                                snapshotNameLength: snapshotNameLength, operationInputBufferLength: queryDetalsInputBufferLength, nameAndInputBuffer: nameAndInputBuffer);
            uint outputBufferSize = this.fsaAdapter.transBufferSize;

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.SUCCESS, outputBufferSize, fileName: fileName);
        }
        public void PrepareSnapshotQueryDeltas(
            out string fileName,
            out ushort snapshotNameLength,
            out byte[] snapshotNameBytes,
            FileAccess fileAccess = FileAccess.GENERIC_READ | FileAccess.GENERIC_WRITE | FileAccess.FILE_WRITE_DATA | FileAccess.FILE_WRITE_ATTRIBUTES
            )
        {
            fileName = this.fsaAdapter.ComposeRandomFileName((int)Test_Lengths.ALIGN);
            string snapshotName = fsaAdapter.ComposeRandomFileName((int)Test_Lengths.ALIGN);

            snapshotNameBytes = Encoding.ASCII.GetBytes(snapshotName);

            //Create snapshot
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput = GetRefsStreamSnapshotManagement(
                RefsStreamSnapshotOperation_Values.REFS_STREAM_SNAPSHOT_OPERATION_CREATE,
                (ushort)Test_Lengths.ALIGN, (ushort)Test_Lengths.ALIGN,
                nameAndInputBuffer: snapshotNameBytes);

            Fsctl_Refs_Stream_Snapshot_Management(refsStreamSnapshotManagementInput, MessageStatus.SUCCESS, fileAccess: fileAccess, fileName: fileName);

            //Prepare to Query Deltas
            snapshotNameLength = (ushort)snapshotNameBytes.Length;
        }
        public void Fsctl_Refs_Stream_Snapshot_Management(
            REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER refsStreamSnapshotManagementInput,
            MessageStatus expectedStatus,
            uint outputBufferSize = 0,
            FileAccess fileAccess = FileAccess.GENERIC_READ | FileAccess.GENERIC_WRITE | FileAccess.FILE_WRITE_DATA | FileAccess.FILE_WRITE_ATTRIBUTES,
            string fileName       = ""
            )
        {
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "Test case steps:");
            MessageStatus status;

            fileName = fileName == "" ? this.fsaAdapter.ComposeRandomFileName((int)Test_Lengths.ALIGN) : fileName;

            //Step 1: Create file
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "1. Create Data File.");
            status = this.fsaAdapter.CreateFile(
                fileName,
                FileAttribute.NORMAL,
                CreateOptions.NON_DIRECTORY_FILE,
                fileAccess,
                ShareAccess.FILE_SHARE_READ | ShareAccess.FILE_SHARE_WRITE,
                CreateDisposition.OPEN_IF);
            this.fsaAdapter.AssertAreEqual(this.Manager, MessageStatus.SUCCESS, status,
                                           "Create file must be successful.");

            //Step 2: FSCTL request with FSCTL_REFS_STREAM_SNAPSHOT_MANAGEMENT
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "2. FSCTL request with FSCTL_REFS_STREAM_SNAPSHOT_MANAGEMENT.");
            status = this.fsaAdapter.FsCtlRefsStreamSnapshotManagement(refsStreamSnapshotManagementInput, outputBufferSize, out _, out _);

            //Step 3: Verify test result
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "3. Verify returned NTStatus code.");

            //MS-SMB2 <352> Windows 10 v21H1 and later and Windows Server 2022 and later allow the additional CtlCode value,
            //as specified in [MS-FSCC].
            if (this.fsaAdapter.TestConfig.Platform < Platform.WindowsServer2022)
            {
                this.fsaAdapter.AssertAreEqual(this.Manager, MessageStatus.NOT_SUPPORTED, status,
                                               "The operation as requested is not supported, or the file system does not support snapshot operations.");
            }
            else if (this.fsaAdapter.IsStreamSnapshotManagementImplemented == false)
            {
                this.fsaAdapter.AssertAreEqual(this.Manager, MessageStatus.INVALID_DEVICE_REQUEST, status,
                                               "If the object store does not implement this functionality, the operation MUST be failed with STATUS_INVALID_DEVICE_REQUEST.");
            }
            else if (expectedStatus == MessageStatus.INVALID_PARAMETER)
            {
                this.fsaAdapter.AssertAreEqual(this.Manager, MessageStatus.INVALID_PARAMETER, status,
                                               "One of the parameters to the request is incorrect.");
            }
            else if (expectedStatus == MessageStatus.BUFFER_TOO_SMALL)
            {
                this.fsaAdapter.AssertAreEqual(this.Manager, MessageStatus.BUFFER_TOO_SMALL, status,
                                               "If the length of the input buffer is less than FIELD_OFFSET(REFS_STREAM_SNAPSHOT_MANAGEMENT_INPUT_BUFFER)");
            }
            else if (expectedStatus == MessageStatus.ACCESS_DENIED)
            {
                this.fsaAdapter.AssertAreEqual(this.Manager, MessageStatus.ACCESS_DENIED, status,
                                               "The Open lacks required FILE_READ_ATTRIBUTES or (FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA) access");
            }
            else
            {
                this.fsaAdapter.AssertAreEqual(this.Manager, MessageStatus.SUCCESS, status, "Status set to STATUS_SUCCESS.");
            }
        }