LockingAndXRequest.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /* Copyright (C) 2014 Tal Aloni <tal.aloni.il@gmail.com>. All rights reserved.
  2. *
  3. * You can redistribute this program and/or modify it under the terms of
  4. * the GNU Lesser Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. */
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Text;
  10. using Utilities;
  11. namespace SMBLibrary.SMB1
  12. {
  13. /// <summary>
  14. /// LOCKING_ANDX_RANGE32 (10-byte)
  15. /// or
  16. /// LOCKING_ANDX_RANGE64 (24-byte )
  17. /// </summary>
  18. public class LockingRange
  19. {
  20. public const int Length32 = 10;
  21. public const int Length64 = 20;
  22. public ushort PID;
  23. public ulong ByteOffset;
  24. public ulong LengthInBytes;
  25. public void Write32(byte[] buffer, ref int offset)
  26. {
  27. LittleEndianWriter.WriteUInt16(buffer, ref offset, this.PID);
  28. LittleEndianWriter.WriteUInt32(buffer, ref offset, (uint)this.ByteOffset);
  29. LittleEndianWriter.WriteUInt32(buffer, ref offset, (uint)this.LengthInBytes);
  30. }
  31. public void Write64(byte[] buffer, ref int offset)
  32. {
  33. LittleEndianWriter.WriteUInt16(buffer, ref offset, this.PID);
  34. offset += 2; // padding
  35. LittleEndianWriter.WriteUInt64(buffer, ref offset, this.ByteOffset);
  36. LittleEndianWriter.WriteUInt64(buffer, ref offset, this.LengthInBytes);
  37. }
  38. public static LockingRange Read32(byte[] buffer, ref int offset)
  39. {
  40. LockingRange entry = new LockingRange();
  41. entry.PID = LittleEndianReader.ReadUInt16(buffer, ref offset);
  42. entry.ByteOffset = LittleEndianReader.ReadUInt32(buffer, ref offset);
  43. entry.LengthInBytes = LittleEndianReader.ReadUInt32(buffer, ref offset);
  44. return entry;
  45. }
  46. public static LockingRange Read64(byte[] buffer, ref int offset)
  47. {
  48. LockingRange entry = new LockingRange();
  49. entry.PID = LittleEndianReader.ReadUInt16(buffer, ref offset);
  50. offset += 2; // padding
  51. entry.ByteOffset = LittleEndianReader.ReadUInt64(buffer, ref offset);
  52. entry.LengthInBytes = LittleEndianReader.ReadUInt64(buffer, ref offset);
  53. return entry;
  54. }
  55. }
  56. /// <summary>
  57. /// SMB_COM_LOCKING_ANDX Request
  58. /// </summary>
  59. public class LockingAndXRequest : SMBAndXCommand
  60. {
  61. public const int ParametersLength = 12;
  62. // Parameters:
  63. public ushort FID;
  64. public LockType TypeOfLock;
  65. public byte NewOpLockLevel;
  66. public uint Timeout;
  67. //ushort NumberOfRequestedUnlocks;
  68. //ushort NumberOfRequestedLocks;
  69. // Data:
  70. public List<LockingRange> Unlocks = new List<LockingRange>();
  71. public List<LockingRange> Locks = new List<LockingRange>();
  72. public LockingAndXRequest() : base()
  73. {
  74. }
  75. public LockingAndXRequest(byte[] buffer, int offset) : base(buffer, offset, false)
  76. {
  77. FID = LittleEndianConverter.ToUInt16(this.SMBParameters, 4);
  78. TypeOfLock = (LockType)ByteReader.ReadByte(this.SMBParameters, 6);
  79. NewOpLockLevel = ByteReader.ReadByte(this.SMBParameters, 7);
  80. Timeout = LittleEndianConverter.ToUInt32(this.SMBParameters, 8);
  81. ushort numberOfRequestedUnlocks = LittleEndianConverter.ToUInt16(this.SMBParameters, 12);
  82. ushort numberOfRequestedLocks = LittleEndianConverter.ToUInt16(this.SMBParameters, 14);
  83. int dataOffset = 0;
  84. if ((TypeOfLock & LockType.LARGE_FILES) > 0)
  85. {
  86. for (int index = 0; index < numberOfRequestedUnlocks; index++)
  87. {
  88. LockingRange entry = LockingRange.Read64(this.SMBData, ref dataOffset);
  89. Unlocks.Add(entry);
  90. }
  91. for (int index = 0; index < numberOfRequestedLocks; index++)
  92. {
  93. LockingRange entry = LockingRange.Read64(this.SMBData, ref dataOffset);
  94. Locks.Add(entry);
  95. }
  96. }
  97. else
  98. {
  99. for (int index = 0; index < numberOfRequestedUnlocks; index++)
  100. {
  101. LockingRange entry = LockingRange.Read32(this.SMBData, ref dataOffset);
  102. Unlocks.Add(entry);
  103. }
  104. for (int index = 0; index < numberOfRequestedLocks; index++)
  105. {
  106. LockingRange entry = LockingRange.Read32(this.SMBData, ref dataOffset);
  107. Locks.Add(entry);
  108. }
  109. }
  110. }
  111. public override byte[] GetBytes(bool isUnicode)
  112. {
  113. this.SMBParameters = new byte[ParametersLength];
  114. LittleEndianWriter.WriteUInt16(this.SMBParameters, 4, FID);
  115. ByteWriter.WriteByte(this.SMBParameters, 6, (byte)TypeOfLock);
  116. ByteWriter.WriteByte(this.SMBParameters, 7, NewOpLockLevel);
  117. LittleEndianWriter.WriteUInt32(this.SMBParameters, 8, Timeout);
  118. LittleEndianWriter.WriteUInt16(this.SMBParameters, 12, (ushort)Unlocks.Count);
  119. LittleEndianWriter.WriteUInt16(this.SMBParameters, 14, (ushort)Locks.Count);
  120. int dataLength;
  121. bool isLargeFile = (TypeOfLock & LockType.LARGE_FILES) > 0;
  122. if (isLargeFile)
  123. {
  124. dataLength = (Unlocks.Count + Locks.Count) * LockingRange.Length64;
  125. }
  126. else
  127. {
  128. dataLength = (Unlocks.Count + Locks.Count) * LockingRange.Length32;
  129. }
  130. int dataOffset = 0;
  131. this.SMBData = new byte[dataLength];
  132. for (int index = 0; index < Unlocks.Count; index++)
  133. {
  134. if (isLargeFile)
  135. {
  136. Unlocks[index].Write64(this.SMBData, ref dataOffset);
  137. }
  138. else
  139. {
  140. Unlocks[index].Write32(this.SMBData, ref dataOffset);
  141. }
  142. }
  143. for (int index = 0; index < Locks.Count; index++)
  144. {
  145. if (isLargeFile)
  146. {
  147. Locks[index].Write64(this.SMBData, ref dataOffset);
  148. }
  149. else
  150. {
  151. Locks[index].Write32(this.SMBData, ref dataOffset);
  152. }
  153. }
  154. return base.GetBytes(isUnicode);
  155. }
  156. public override CommandName CommandName
  157. {
  158. get
  159. {
  160. return CommandName.SMB_COM_LOCKING_ANDX;
  161. }
  162. }
  163. }
  164. }