/// <summary>
        /// decode the batched request packet
        /// </summary>
        /// <param name="channel">the channel of bytes to read</param>
        /// <param name="request">the request of the response.</param>
        /// <param name="smbBatchedResponse">the batched response</param>
        /// <returns>the consumed length of batched response packet</returns>
        protected virtual int DecodeBatchedRequest(
            Channel channel,
            SmbPacket request, SmbBatchedResponsePacket smbBatchedResponse)
        {
            int batchedConsumedLength = 0;

            batchedConsumedLength += smbBatchedResponse.ReadAndxFromChannel(request, channel);

            return(batchedConsumedLength);
        }
 /// <summary>
 /// Deep copy constructor.
 /// </summary>
 protected SmbBatchedResponsePacket(SmbBatchedResponsePacket packet)
     : base(packet)
 {
     lock (packet)
     {
         if (packet.AndxPacket != null)
         {
             this.andxPacket = packet.AndxPacket.Clone() as SmbPacket;
         }
     }
 }
 /// <summary>
 /// Deep copy constructor.
 /// </summary>
 protected SmbBatchedResponsePacket(SmbBatchedResponsePacket packet)
     : base(packet)
 {
     lock (packet)
     {
         if (packet.AndxPacket != null)
         {
             this.andxPacket = packet.AndxPacket.Clone() as SmbPacket;
         }
     }
 }
        /// <summary>
        /// to read the andx packet from the channel
        /// </summary>
        /// <param name="smbRequest">the request of the response.</param>
        /// <param name="channel">the channel started with the SmbParameters of the andx.</param>
        /// <returns>the size in bytes of the SmbParameters, SmbData and andx if existed of the andx.</returns>
        internal int ReadAndxFromChannel(SmbPacket smbRequest, Channel channel)
        {
            int consumedLen = 0;

            if (this.AndxCommand != SmbCommand.SMB_COM_NO_ANDX_COMMAND)
            {
                SmbHeader andxHeader = this.SmbHeader;
                andxHeader.Command        = this.AndxCommand;
                andxHeader.Protocol       = CifsMessageUtils.SMB_PROTOCOL_ANDXPACKET;
                this.andxPacket           = CifsMessageUtils.CreateSmbResponsePacket(smbRequest, andxHeader, channel);
                this.andxPacket.SmbHeader = andxHeader;
                consumedLen += this.andxPacket.ReadParametersFromChannel(channel);
                consumedLen += this.andxPacket.ReadDataFromChannel(channel);
                SmbBatchedResponsePacket batchedResponse = this.andxPacket as SmbBatchedResponsePacket;
                if (batchedResponse != null)
                {
                    consumedLen += batchedResponse.ReadAndxFromChannel(smbRequest, channel);
                }
            }
            return(consumedLen);
        }
        /// <summary>
        /// decode the batched request packet
        /// </summary>
        /// <param name="channel">the channel of bytes to read</param>
        /// <param name="request">the request of the response.</param>
        /// <param name="smbBatchedResponse">the batched response</param>
        /// <returns>the consumed length of batched response packet</returns>
        protected override int DecodeBatchedRequest(
            Channel channel,
            SmbPacket request, SmbBatchedResponsePacket smbBatchedResponse)
        {
            int result = base.DecodeBatchedRequest(channel, request, smbBatchedResponse);

            for (SmbBatchedResponsePacket currentPacket = smbBatchedResponse;
                currentPacket != null && currentPacket.AndxPacket != null;
                currentPacket = currentPacket.AndxPacket as SmbBatchedResponsePacket)
            {
                SmbPacket andxPacket = currentPacket.AndxPacket;

                // create the smb packet
                object smbParameters = ObjectUtility.GetFieldValue(currentPacket, "smbParameters");
                if (smbParameters != null)
                {
                    SmbHeader smbHeader = smbBatchedResponse.SmbHeader;
                    smbHeader.Command = (SmbCommand)ObjectUtility.GetFieldValue(smbParameters, "AndXCommand");
                    andxPacket = CreateSmbResponsePacket(null, smbHeader, null);
                }

                // convert from cifs packet to smb packet
                if (andxPacket != null)
                {
                    Type smbPacketType = andxPacket.GetType();
                    andxPacket = ObjectUtility.CreateInstance(
                        smbPacketType.Module.FullyQualifiedName,
                        smbPacketType.FullName,
                        new object[] { currentPacket.AndxPacket }) as SmbPacket;
                }

                currentPacket.AndxPacket = andxPacket;
            }

            return result;
        }
        /// <summary>
        /// decode packet from bytes
        /// </summary>
        /// <param name="connectId">the connection identity.</param>
        /// <param name="messageBytes">bytes contains packet</param>
        /// <param name="consumedLength">the bytes length which are consumed when decode.</param>
        /// <returns>the decoded packet from the bytes array. if failed, return null.</returns>
        protected SmbPacket DecodeSmbResponseFromBytes(
            int connectId,
            byte[] messageBytes,
            out int consumedLength)
        {
            consumedLength = 0;
            SmbPacket smbRequest  = null;
            SmbPacket smbResponse = null;

            using (MemoryStream memoryStream = new MemoryStream(messageBytes, true))
            {
                using (Channel channel = new Channel(null, memoryStream))
                {
                    // read raw response:
                    Collection <SmbPacket> outstandingRequests = this.clientContext.GetOutstandingRequests(connectId);
                    if (outstandingRequests != null && outstandingRequests.Count > 0)
                    {
                        SmbReadRawRequestPacket readRawRequest = outstandingRequests[0] as SmbReadRawRequestPacket;
                        if (readRawRequest != null)
                        {
                            SmbReadRawResponsePacket readRawResponse = this.CreateSmbResponsePacket(
                                readRawRequest, readRawRequest.SmbHeader, channel) as SmbReadRawResponsePacket;
                            if (readRawResponse != null)
                            {
                                byte[] rawData = new byte[messageBytes.Length];
                                Array.Copy(messageBytes, rawData, rawData.Length);
                                readRawResponse.RawData = rawData;
                                consumedLength          = rawData.Length;
                                return(readRawResponse);
                            }
                            else
                            {
                                // discard the none-parsable data silently:
                                consumedLength = messageBytes.Length;
                                return(null);
                            }
                        }
                        else
                        {
                            // No SmbReadRawResponsePacket sent, so the response should not be SmbReadRawResponsePacket.
                            // and do nothing here.
                        }
                    }

                    // read smb header and new SmbPacket:
                    if (channel.Stream.Position < channel.Stream.Length &&
                        messageBytes.Length >= CifsMessageUtils.GetSize <SmbHeader>(new SmbHeader()))
                    {
                        SmbHeader smbHeader = channel.Read <SmbHeader>();
                        smbRequest      = this.clientContext.GetOutstandingRequest(connectId, smbHeader.Mid);
                        smbResponse     = this.CreateSmbResponsePacket(smbRequest, smbHeader, channel);
                        consumedLength += smbResponse.HeaderSize;
                    }
                    else
                    {
                        // The data in the channel is less than the size of SmbHeader. consume nothing and return null:
                        consumedLength = 0;
                        return(null);
                    }

                    // read SmbParameters:
                    consumedLength += smbResponse.ReadParametersFromChannel(channel);

                    // read SmbData:
                    consumedLength += smbResponse.ReadDataFromChannel(channel);

                    // read andx:
                    SmbBatchedResponsePacket smbBatchedResponse = smbResponse as SmbBatchedResponsePacket;
                    if (smbRequest != null && smbBatchedResponse != null)
                    {
                        consumedLength += DecodeBatchedRequest(channel, smbRequest, smbBatchedResponse);
                    }

                    // handle the difference of protocol implementation:
                    SmbWriteAndCloseResponsePacket writeAndCloseResponse = smbResponse as SmbWriteAndCloseResponsePacket;
                    if (writeAndCloseResponse != null)
                    {
                        if (this.clientConfig.IsWriteAndCloseResponseExtraPadding)
                        {
                            // Windows NT Server appends three NULL bytes to this message, following the ByteCount field.
                            // These three bytes are not message data and can safely be discarded.
                            const int PaddingLength = 3;
                            writeAndCloseResponse.PaddingBytes = channel.ReadBytes(PaddingLength);
                            consumedLength += PaddingLength;
                        }
                    }
                }
            }
            return(smbResponse);
        }
        /// <summary>
        /// decode the batched request packet
        /// </summary>
        /// <param name="channel">the channel of bytes to read</param>
        /// <param name="request">the request of the response.</param>
        /// <param name="smbBatchedResponse">the batched response</param>
        /// <returns>the consumed length of batched response packet</returns>
        protected virtual int DecodeBatchedRequest(
            Channel channel,
            SmbPacket request, SmbBatchedResponsePacket smbBatchedResponse)
        {
            int batchedConsumedLength = 0;

            batchedConsumedLength += smbBatchedResponse.ReadAndxFromChannel(request, channel);

            return batchedConsumedLength;
        }