/// <summary> /// Tunnel operations to the shared virtual disk file /// </summary> /// <typeparam name="ResponseT">Type of the operation response</typeparam> /// <param name="isAsyncOperation">Indicate whether the tunnel operation is async or not</param> /// <param name="code">Operation code</param> /// <param name="requestId">A value that uniquely identifies an operation request and response for all requests sent by this client</param> /// <param name="requestStructure">The marshalled tunnel structure of the request</param> /// <param name="responseHeader">Tunnel operation header of the response packet</param> /// <param name="response">Tunnel operation response of the smb2 response packet</param> /// <returns>Status of the smb2 response packet</returns> public uint TunnelOperation <ResponseT>( bool isAsyncOperation, RSVD_TUNNEL_OPERATION_CODE code, ulong requestId, byte[] requestStructure, out SVHDX_TUNNEL_OPERATION_HEADER?responseHeader, out ResponseT?response) where ResponseT : struct { SVHDX_TUNNEL_OPERATION_HEADER header = new SVHDX_TUNNEL_OPERATION_HEADER(); header.OperationCode = code; header.RequestId = requestId; byte[] payload = TypeMarshal.ToBytes(header); if (null != requestStructure) { payload = payload.Concat(requestStructure).ToArray(); } CtlCode_Values ctlCode = isAsyncOperation ? CtlCode_Values.FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST : CtlCode_Values.FSCTL_SVHDX_SYNC_TUNNEL_REQUEST; transport.SendIoctlPayload(ctlCode, payload); uint smb2Status; transport.ExpectIoctlPayload(out smb2Status, out payload); response = null; responseHeader = null; if (smb2Status != Smb2Status.STATUS_SUCCESS) { return(smb2Status); } responseHeader = TypeMarshal.ToStruct <SVHDX_TUNNEL_OPERATION_HEADER>(payload); // If the response does not contain Header only, parse the resonse body. if (responseHeader.Value.Status == 0 && typeof(ResponseT) != typeof(SVHDX_TUNNEL_OPERATION_HEADER)) { response = TypeMarshal.ToStruct <ResponseT>(payload.Skip(Marshal.SizeOf(responseHeader)).ToArray()); } else { // The operation failed, so no response body. // Or the response only contains header, no response body. } return(smb2Status); }
/// <summary> /// Verify the Tunnel Operation Header /// </summary> /// <param name="header">The received Tunnel Operation Header</param> /// <param name="code">The operation code</param> /// <param name="status">The received status</param> /// <param name="requestId">The request ID</param> public void VerifyTunnelOperationHeader(SVHDX_TUNNEL_OPERATION_HEADER header, RSVD_TUNNEL_OPERATION_CODE code, uint status, ulong requestId) { BaseTestSite.Assert.AreEqual( code, header.OperationCode, "Operation code should be {0}, actual is {1}", code, header.OperationCode); BaseTestSite.Assert.AreEqual( status, header.Status, "Status should be {0}, actual is {1}", GetStatus(status), GetStatus(header.Status)); BaseTestSite.Assert.AreEqual( requestId, header.RequestId, "The RequestId should be {0}, actual is {1}", requestId, header.RequestId); }