// This code is derived from jcifs smb client library // Ported by J. Arturo // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA using SharpCifs.Util; using SharpCifs.Util.Sharpen; namespace SharpCifs.Smb { internal abstract class AndXServerMessageBlock : ServerMessageBlock { private const int AndxCommandOffset = 1; private const int AndxReservedOffset = 2; private const int AndxOffsetOffset = 3; private byte _andxCommand = unchecked(unchecked(0xFF)); private int _andxOffset; internal ServerMessageBlock Andx; public AndXServerMessageBlock() { } internal AndXServerMessageBlock(ServerMessageBlock andx) { if (andx != null) { this.Andx = andx; _andxCommand = andx.Command; } } internal virtual int GetBatchLimit(byte command) { return 0; } internal override int Encode(byte[] dst, int dstIndex) { int start = HeaderStart = dstIndex; dstIndex += WriteHeaderWireFormat(dst, dstIndex); dstIndex += WriteAndXWireFormat(dst, dstIndex); Length = dstIndex - start; if (Digest != null) { Digest.Sign(dst, HeaderStart, Length, this, Response); } return Length; } internal override int Decode(byte[] buffer, int bufferIndex) { int start = HeaderStart = bufferIndex; bufferIndex += ReadHeaderWireFormat(buffer, bufferIndex); bufferIndex += ReadAndXWireFormat(buffer, bufferIndex); Length = bufferIndex - start; return Length; } internal virtual int WriteAndXWireFormat(byte[] dst, int dstIndex) { int start = dstIndex; WordCount = WriteParameterWordsWireFormat(dst, start + AndxOffsetOffset + 2); WordCount += 4; // for command, reserved, and offset dstIndex += WordCount + 1; WordCount /= 2; dst[start] = unchecked((byte)(WordCount & unchecked(0xFF))); ByteCount = WriteBytesWireFormat(dst, dstIndex + 2); dst[dstIndex++] = unchecked((byte)(ByteCount & unchecked(0xFF))); dst[dstIndex++] = unchecked((byte)((ByteCount >> 8) & unchecked(0xFF))); dstIndex += ByteCount; if (Andx == null || SmbConstants.UseBatching == false || BatchLevel >= GetBatchLimit(Andx.Command )) { _andxCommand = unchecked(unchecked(0xFF)); Andx = null; dst[start + AndxCommandOffset] = unchecked(unchecked(0xFF)); dst[start + AndxReservedOffset] = unchecked(unchecked(0x00)); // dst[start + ANDX_OFFSET_OFFSET] = (byte)0x00; // dst[start + ANDX_OFFSET_OFFSET + 1] = (byte)0x00; dst[start + AndxOffsetOffset] = unchecked(unchecked(0xde)); dst[start + AndxOffsetOffset + 1] = unchecked(unchecked(0xde)); // andx not used; return return dstIndex - start; } Andx.BatchLevel = BatchLevel + 1; dst[start + AndxCommandOffset] = _andxCommand; dst[start + AndxReservedOffset] = unchecked(unchecked(0x00)); _andxOffset = dstIndex - HeaderStart; WriteInt2(_andxOffset, dst, start + AndxOffsetOffset); Andx.UseUnicode = UseUnicode; if (Andx is AndXServerMessageBlock) { Andx.Uid = Uid; dstIndex += ((AndXServerMessageBlock)Andx).WriteAndXWireFormat(dst, dstIndex ); } else { // the andx smb is not of type andx so lets just write it here and // were done. int andxStart = dstIndex; Andx.WordCount = Andx.WriteParameterWordsWireFormat(dst, dstIndex); dstIndex += Andx.WordCount + 1; Andx.WordCount /= 2; dst[andxStart] = unchecked((byte)(Andx.WordCount & unchecked(0xFF))); Andx.ByteCount = Andx.WriteBytesWireFormat(dst, dstIndex + 2); dst[dstIndex++] = unchecked((byte)(Andx.ByteCount & unchecked(0xFF))); dst[dstIndex++] = unchecked((byte)((Andx.ByteCount >> 8) & unchecked(0xFF) )); dstIndex += Andx.ByteCount; } return dstIndex - start; } internal virtual int ReadAndXWireFormat(byte[] buffer, int bufferIndex) { int start = bufferIndex; WordCount = buffer[bufferIndex++]; if (WordCount != 0) { _andxCommand = buffer[bufferIndex]; _andxOffset = ReadInt2(buffer, bufferIndex + 2); if (_andxOffset == 0) { _andxCommand = unchecked(unchecked(0xFF)); } if (WordCount > 2) { ReadParameterWordsWireFormat(buffer, bufferIndex + 4); if (Command == SmbComNtCreateAndx && ((SmbComNtCreateAndXResponse)this).IsExtended) { WordCount += 8; } } bufferIndex = start + 1 + (WordCount * 2); } ByteCount = ReadInt2(buffer, bufferIndex); bufferIndex += 2; if (ByteCount != 0) { int n; n = ReadBytesWireFormat(buffer, bufferIndex); bufferIndex += ByteCount; } if (ErrorCode != 0 || _andxCommand == unchecked(unchecked(0xFF))) { _andxCommand = unchecked(unchecked(0xFF)); Andx = null; } else { if (Andx == null) { _andxCommand = unchecked(unchecked(0xFF)); throw new RuntimeException("no andx command supplied with response"); } bufferIndex = HeaderStart + _andxOffset; Andx.HeaderStart = HeaderStart; Andx.Command = _andxCommand; Andx.ErrorCode = ErrorCode; Andx.Flags = Flags; Andx.Flags2 = Flags2; Andx.Tid = Tid; Andx.Pid = Pid; Andx.Uid = Uid; Andx.Mid = Mid; Andx.UseUnicode = UseUnicode; if (Andx is AndXServerMessageBlock) { bufferIndex += ((AndXServerMessageBlock)Andx).ReadAndXWireFormat(buffer , bufferIndex); } else { buffer[bufferIndex++] = unchecked((byte)(Andx.WordCount & unchecked(0xFF)) ); if (Andx.WordCount != 0) { if (Andx.WordCount > 2) { bufferIndex += Andx.ReadParameterWordsWireFormat(buffer, bufferIndex); } } Andx.ByteCount = ReadInt2(buffer, bufferIndex); bufferIndex += 2; if (Andx.ByteCount != 0) { Andx.ReadBytesWireFormat(buffer, bufferIndex); bufferIndex += Andx.ByteCount; } } Andx.Received = true; } return bufferIndex - start; } public override string ToString() { return base.ToString() + ",andxCommand=0x" + Hexdump.ToHexString(_andxCommand , 2) + ",andxOffset=" + _andxOffset; } } }