private void CheckSnapshotExisted(ref ulong requestId, RsvdClient client, System.Guid snapshotId)
        {
            SetFile_InformationType       setFileInforType = SetFile_InformationType.SvhdxSetFileInformationTypeSnapshotEntry;
            Snapshot_Type                 snapshotType     = Snapshot_Type.SvhdxSnapshotTypeVM;
            SVHDX_TUNNEL_OPERATION_HEADER?header;
            SVHDX_TUNNEL_VHDSET_FILE_QUERY_INFORMATION_SNAPSHOT_ENTRY_RESPONSE?snapshotEntryResponse;

            byte[] payload = client.CreateTunnelGetVHDSetFileInfoRequest(
                setFileInforType,
                snapshotType,
                snapshotId);
            uint status = client.TunnelOperation <SVHDX_TUNNEL_VHDSET_FILE_QUERY_INFORMATION_SNAPSHOT_ENTRY_RESPONSE>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_VHDSET_QUERY_INFORMATION,
                requestId,
                payload,
                out header,
                out snapshotEntryResponse);

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));

            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_VHDSET_QUERY_INFORMATION, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, requestId++);
        }
        /// <summary>
        /// Delete the existing snapshots for the VHD set file
        /// </summary>
        /// <param name="requestId">Tunnel operation request id</param>
        /// <param name="snapshotId">The snapshot id to be deleted</param>
        /// <param name="rsvdClient">The instance of rsvd client. NULL stands for the default client</param>
        public void DeleteSnapshot(ref ulong requestId, Guid snapshotId, RsvdClient rsvdClient = null)
        {
            if (rsvdClient == null)
            {
                rsvdClient = this.client;
            }

            SVHDX_TUNNEL_OPERATION_HEADER?       header;
            SVHDX_TUNNEL_DELETE_SNAPSHOT_REQUEST deleteRequest = new SVHDX_TUNNEL_DELETE_SNAPSHOT_REQUEST();

            deleteRequest.SnapshotId       = snapshotId;
            deleteRequest.PersistReference = PersistReference_Flags.PersistReferenceFalse;
            deleteRequest.SnapshotType     = Snapshot_Type.SvhdxSnapshotTypeVM;
            byte[] payload = rsvdClient.CreateTunnelMetaOperationDeleteSnapshotRequest(deleteRequest);
            SVHDX_TUNNEL_OPERATION_HEADER?deleteResponse;
            uint status = rsvdClient.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                false,
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_DELETE_SNAPSHOT,
                requestId,
                payload,
                out header,
                out deleteResponse);

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));

            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_DELETE_SNAPSHOT, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, requestId++);
        }
        private void SendAndReceiveSCSICommand(RsvdClient rsvdClient, byte cdbLength, byte[] cdbBuffer, byte[] dataBuffer, out byte scsiStatus)
        {
            SVHDX_TUNNEL_OPERATION_HEADER?header;
            SVHDX_TUNNEL_SCSI_RESPONSE?   response;

            byte[] payload = rsvdClient.CreateTunnelScsiRequest(
                RsvdConst.SVHDX_TUNNEL_SCSI_REQUEST_LENGTH,
                cdbLength,
                (byte)RsvdConst.RSVD_SCSI_SENSE_BUFFER_SIZE,
                false,
                SRB_FLAGS.SRB_FLAGS_DATA_OUT,
                (byte)dataBuffer.Length,
                cdbBuffer,
                dataBuffer);

            uint status = rsvdClient.TunnelOperation <SVHDX_TUNNEL_SCSI_RESPONSE>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_SCSI_OPERATION,
                ++RequestIdentifier,
                payload,
                out header,
                out response);

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_SCSI_OPERATION, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);
            VerifyFieldInResponse("DataIn", false, response.Value.DataIn); // the CDB buffer specified is to receive data from the server.
            VerifyFieldInResponse("Length", 36, response.Value.Length);    // the size of the SVHDX_TUNNEL_SCSI_REQUEST structure excluding the DataBuffer field; This field MUST be set to 36.

            scsiStatus = response.Value.ScsiStatus;
        }
        /// <summary>
        /// Create snapshot for the VHD set file
        /// </summary>
        /// <param name="requestId">Tunnel operation request id</param>
        /// <param name="rsvdClient">The instance of rsvd client. NULL stands for the default client</param>
        /// <returns>Return a snapshot id</returns>
        public Guid CreateSnapshot(ref ulong requestId, RsvdClient rsvdClient = null)
        {
            if (rsvdClient == null)
            {
                rsvdClient = this.client;
            }

            SVHDX_META_OPERATION_START_REQUEST startRequest = new SVHDX_META_OPERATION_START_REQUEST();

            startRequest.TransactionId = System.Guid.NewGuid();
            startRequest.OperationType = Operation_Type.SvhdxMetaOperationTypeCreateSnapshot;
            startRequest.Padding       = new byte[4];
            SVHDX_META_OPERATION_CREATE_SNAPSHOT createsnapshot = new SVHDX_META_OPERATION_CREATE_SNAPSHOT();

            createsnapshot.SnapshotType          = Snapshot_Type.SvhdxSnapshotTypeVM;
            createsnapshot.Flags                 = Snapshot_Flags.SVHDX_SNAPSHOT_DISK_FLAG_ENABLE_CHANGE_TRACKING;
            createsnapshot.Stage1                = Stage_Values.SvhdxSnapshotStageInitialize;
            createsnapshot.Stage2                = Stage_Values.SvhdxSnapshotStageInvalid;
            createsnapshot.Stage3                = Stage_Values.SvhdxSnapshotStageInvalid;
            createsnapshot.Stage4                = Stage_Values.SvhdxSnapshotStageInvalid;
            createsnapshot.Stage5                = Stage_Values.SvhdxSnapshotStageInvalid;
            createsnapshot.Stage6                = Stage_Values.SvhdxSnapshotStageInvalid;
            createsnapshot.SnapshotId            = System.Guid.NewGuid();
            createsnapshot.ParametersPayloadSize = (uint)0x00000000;
            createsnapshot.Padding               = new byte[24];
            byte[] payload = rsvdClient.CreateTunnelMetaOperationStartCreateSnapshotRequest(
                startRequest,
                createsnapshot);

            SVHDX_TUNNEL_OPERATION_HEADER?header;
            SVHDX_TUNNEL_OPERATION_HEADER?response;
            //For RSVD_TUNNEL_META_OPERATION_START operation code, the IOCTL code should be FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST
            uint status = rsvdClient.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                true,
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START,
                requestId++,
                payload,
                out header,
                out response);

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));

            createsnapshot.Flags  = Snapshot_Flags.SVHDX_SNAPSHOT_FLAG_ZERO;
            createsnapshot.Stage1 = Stage_Values.SvhdxSnapshotStageBlockIO;
            createsnapshot.Stage2 = Stage_Values.SvhdxSnapshotStageSwitchObjectStore;
            createsnapshot.Stage3 = Stage_Values.SvhdxSnapshotStageUnblockIO;
            createsnapshot.Stage4 = Stage_Values.SvhdxSnapshotStageFinalize;
            createsnapshot.Stage5 = Stage_Values.SvhdxSnapshotStageInvalid;
            createsnapshot.Stage6 = Stage_Values.SvhdxSnapshotStageInvalid;
            payload = rsvdClient.CreateTunnelMetaOperationStartCreateSnapshotRequest(
                startRequest,
                createsnapshot);

            //For RSVD_TUNNEL_META_OPERATION_START operation code, the IOCTL code should be FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST
            status = rsvdClient.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                true,
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START,
                requestId++,
                payload,
                out header,
                out response);
            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));

            SetFile_InformationType setFileInforType = SetFile_InformationType.SvhdxSetFileInformationTypeSnapshotEntry;
            Snapshot_Type           snapshotType     = Snapshot_Type.SvhdxSnapshotTypeVM;
            SVHDX_TUNNEL_VHDSET_FILE_QUERY_INFORMATION_SNAPSHOT_ENTRY_RESPONSE?snapshotEntryResponse;

            payload = client.CreateTunnelGetVHDSetFileInfoRequest(
                setFileInforType,
                snapshotType,
                createsnapshot.SnapshotId);
            status = client.TunnelOperation <SVHDX_TUNNEL_VHDSET_FILE_QUERY_INFORMATION_SNAPSHOT_ENTRY_RESPONSE>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_VHDSET_QUERY_INFORMATION,
                requestId++,
                payload,
                out header,
                out snapshotEntryResponse);
            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));

            return(createsnapshot.SnapshotId);
        }
        private void SendAndReceiveSCSICommand(RsvdClient rsvdClient, byte cdbLength, byte[] cdbBuffer, byte[] dataBuffer, out byte scsiStatus)
        {
            SVHDX_TUNNEL_OPERATION_HEADER? header;
            SVHDX_TUNNEL_SCSI_RESPONSE? response;

            byte[] payload = rsvdClient.CreateTunnelScsiRequest(
                RsvdConst.SVHDX_TUNNEL_SCSI_REQUEST_LENGTH,
                cdbLength,
                (byte)RsvdConst.RSVD_SCSI_SENSE_BUFFER_SIZE,
                false,
                SRB_FLAGS.SRB_FLAGS_DATA_OUT,
                (byte)dataBuffer.Length,
                cdbBuffer,
                dataBuffer);

            uint status = rsvdClient.TunnelOperation<SVHDX_TUNNEL_SCSI_RESPONSE>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_SCSI_OPERATION,
                ++RequestIdentifier,
                payload,
                out header,
                out response);
            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_SCSI_OPERATION, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);
            VerifyFieldInResponse("DataIn", false, response.Value.DataIn); // the CDB buffer specified is to receive data from the server.
            VerifyFieldInResponse("Length", 36, response.Value.Length);// the size of the SVHDX_TUNNEL_SCSI_REQUEST structure excluding the DataBuffer field; This field MUST be set to 36.

            scsiStatus = response.Value.ScsiStatus;
        }
        private void CheckSnapshotExisted(ref ulong requestId, RsvdClient client, System.Guid snapshotId)
        {
            SetFile_InformationType setFileInforType = SetFile_InformationType.SvhdxSetFileInformationTypeSnapshotEntry;
            Snapshot_Type snapshotType = Snapshot_Type.SvhdxSnapshotTypeVM;
            SVHDX_TUNNEL_OPERATION_HEADER? header;
            SVHDX_TUNNEL_VHDSET_FILE_QUERY_INFORMATION_SNAPSHOT_ENTRY_RESPONSE? snapshotEntryResponse;
            byte[] payload = client.CreateTunnelGetVHDSetFileInfoRequest(
                setFileInforType,
                snapshotType,
                snapshotId);
            uint status = client.TunnelOperation<SVHDX_TUNNEL_VHDSET_FILE_QUERY_INFORMATION_SNAPSHOT_ENTRY_RESPONSE>(
                false,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_VHDSET_QUERY_INFORMATION,
                requestId,
                payload,
                out header,
                out snapshotEntryResponse);
            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));

            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_VHDSET_QUERY_INFORMATION, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, requestId++);
        }
        protected void CreateSnapshot(Guid snapshotId)
        {
            SVHDX_META_OPERATION_START_REQUEST startRequest = new SVHDX_META_OPERATION_START_REQUEST();

            startRequest.TransactionId = Guid.NewGuid();
            startRequest.OperationType = Operation_Type.SvhdxMetaOperationTypeCreateSnapshot;
            SVHDX_META_OPERATION_CREATE_SNAPSHOT createsnapshot = new SVHDX_META_OPERATION_CREATE_SNAPSHOT();

            createsnapshot.SnapshotType          = Snapshot_Type.SvhdxSnapshotTypeVM;
            createsnapshot.Flags                 = Snapshot_Flags.SVHDX_SNAPSHOT_DISK_FLAG_ENABLE_CHANGE_TRACKING;
            createsnapshot.Stage1                = Stage_Values.SvhdxSnapshotStageInitialize;
            createsnapshot.SnapshotId            = snapshotId;
            createsnapshot.ParametersPayloadSize = (uint)0x00000000;
            createsnapshot.Padding               = new byte[24];
            byte[] payload = client.CreateTunnelMetaOperationStartCreateSnapshotRequest(
                startRequest,
                createsnapshot);
            SVHDX_TUNNEL_OPERATION_HEADER?header;
            SVHDX_TUNNEL_OPERATION_HEADER?response;
            //For RSVD_TUNNEL_META_OPERATION_START operation code, the IOCTL code should be FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST
            uint status = client.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                true,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START,
                ++RequestIdentifier,
                payload,
                out header,
                out response);

            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);

            // Add spaces in the beginning of the log to be align with the last test step. Since the steps in this function are only sub steps.
            BaseTestSite.Log.Add(LogEntryKind.TestStep, "	Client sends the second tunnel operation SVHDX_META_OPERATION_START_REQUEST to create a snapshot and expects success.");
            createsnapshot.Flags  = Snapshot_Flags.SVHDX_SNAPSHOT_FLAG_ZERO;
            createsnapshot.Stage1 = Stage_Values.SvhdxSnapshotStageBlockIO;
            createsnapshot.Stage2 = Stage_Values.SvhdxSnapshotStageSwitchObjectStore;
            createsnapshot.Stage3 = Stage_Values.SvhdxSnapshotStageUnblockIO;
            createsnapshot.Stage4 = Stage_Values.SvhdxSnapshotStageFinalize;
            payload = client.CreateTunnelMetaOperationStartCreateSnapshotRequest(
                startRequest,
                createsnapshot);
            //For RSVD_TUNNEL_META_OPERATION_START operation code, the IOCTL code should be FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST
            status = client.TunnelOperation <SVHDX_TUNNEL_OPERATION_HEADER>(
                true,//true for Async operation, false for non-async operation
                RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START,
                ++RequestIdentifier,
                payload,
                out header,
                out response);
            BaseTestSite.Assert.AreEqual(
                (uint)Smb2Status.STATUS_SUCCESS,
                status,
                "Ioctl should succeed, actual status: {0}",
                GetStatus(status));
            VerifyTunnelOperationHeader(header.Value, RSVD_TUNNEL_OPERATION_CODE.RSVD_TUNNEL_META_OPERATION_START, (uint)RsvdStatus.STATUS_SVHDX_SUCCESS, RequestIdentifier);

            BaseTestSite.Log.Add(LogEntryKind.TestStep, "   Verify the snapshot has been created after the operation.");

            DoUntilSucceed(
                () => CheckSnapshotExisted(snapshotId),
                TestConfig.Timeout,
                "Retry getting the snapshot to make sure it has been created until succeed within timeout span");
        }