VolumeRecord.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  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 DiskAccessLibrary.LogicalDiskManager
  12. {
  13. public enum PartitionType : byte
  14. {
  15. RAW = 0x06, // RAW and FAT16 are both 0x06
  16. FAT16 = 0x06,
  17. NTFS = 0x07,
  18. FAT32 = 0x0B,
  19. }
  20. public class VolumeRecord : DatabaseRecord
  21. {
  22. public string VolumeTypeString = String.Empty; // "gen" or "raid5"
  23. public string DisableDriverLetterAssignmentString = String.Empty; // Disable driver letter assignment: "8000000000000000"
  24. public string StateString = "ACTIVE"; // "ACTIVE", "SYNC"
  25. public ReadPolicyName ReadPolicy;
  26. public uint VolumeNumber; // start at 5 and unused numbers are reused (new volumes are set to 0xFFFFFFFF)
  27. public VolumeFlags VolumeFlags;
  28. public uint NumberOfComponents;
  29. public ulong CommitTransactionID;
  30. public ulong UnknownTransactionID; // Not always set, and when it does, it's smaller than CommitTransactionID
  31. public ulong SizeLBA; // PaddedVarULong, Number of logical sectors
  32. // 4 Zeros
  33. public PartitionType PartitionType;
  34. public Guid VolumeGuid;
  35. public ulong UnknownID1;
  36. public ulong UnknownID2;
  37. public ulong ColumnSizeLBA; // PaddedVarULong, this is either the column size or the size of the first extent
  38. public string MountHint = String.Empty;
  39. public VolumeRecord()
  40. {
  41. this.RecordRevision = 5;
  42. this.RecordType = RecordType.Volume;
  43. }
  44. public VolumeRecord(List<DatabaseRecordFragment> fragments) : base(fragments)
  45. {
  46. // Data begins at 0x10 (VBLK header is at 0x00)
  47. int offset = 0x00; // relative to Data
  48. ReadCommonFields(this.Data, ref offset);
  49. if (RecordRevision != 5)
  50. {
  51. throw new NotImplementedException("Unsupported record revision");
  52. }
  53. VolumeTypeString = ReadVarString(this.Data, ref offset);
  54. DisableDriverLetterAssignmentString = ReadVarString(this.Data, ref offset);
  55. StateString = ByteReader.ReadAnsiString(this.Data, ref offset, 14).Trim('\0');
  56. ReadPolicy = (ReadPolicyName)ByteReader.ReadByte(this.Data, ref offset);
  57. VolumeNumber = ReadVarUInt(this.Data, ref offset);
  58. VolumeFlags = (VolumeFlags)BigEndianReader.ReadUInt32(this.Data, ref offset);
  59. NumberOfComponents = ReadVarUInt(this.Data, ref offset);
  60. CommitTransactionID = BigEndianReader.ReadUInt64(this.Data, ref offset);
  61. UnknownTransactionID = BigEndianReader.ReadUInt64(this.Data, ref offset);
  62. SizeLBA = ReadVarULong(this.Data, ref offset);
  63. offset += 4;
  64. PartitionType = (PartitionType)ByteReader.ReadByte(this.Data, ref offset);
  65. VolumeGuid = BigEndianReader.ReadGuidBytes(this.Data, ref offset);
  66. if (HasUnknownID1Flag)
  67. {
  68. UnknownID1 = ReadVarULong(this.Data, ref offset);
  69. }
  70. if (HasUnknownID2Flag)
  71. {
  72. UnknownID2 = ReadVarULong(this.Data, ref offset);
  73. }
  74. if (HasColumnSizeFlag)
  75. {
  76. ColumnSizeLBA = ReadVarULong(this.Data, ref offset);
  77. }
  78. if (HasMountHintFlag)
  79. {
  80. MountHint = ReadVarString(this.Data, ref offset);
  81. }
  82. }
  83. public override byte[] GetDataBytes()
  84. {
  85. int dataLength = 64; // fixed length components
  86. dataLength += VarULongSize(VolumeId);
  87. dataLength += Name.Length + 1;
  88. dataLength += VolumeTypeString.Length + 1;
  89. dataLength += DisableDriverLetterAssignmentString.Length + 1;
  90. dataLength += VarUIntSize(VolumeNumber);
  91. dataLength += VarUIntSize(NumberOfComponents);
  92. dataLength += PaddedVarULongSize(SizeLBA);
  93. if (HasUnknownID1Flag)
  94. {
  95. dataLength += VarULongSize(UnknownID1);
  96. }
  97. if (HasUnknownID2Flag)
  98. {
  99. dataLength += VarULongSize(UnknownID2);
  100. }
  101. if (HasColumnSizeFlag)
  102. {
  103. dataLength += PaddedVarULongSize(ColumnSizeLBA);
  104. }
  105. if (HasMountHintFlag)
  106. {
  107. dataLength += MountHint.Length + 1;
  108. }
  109. byte[] data = new byte[dataLength];
  110. int offset = 0x00;
  111. WriteCommonFields(data, ref offset);
  112. WriteVarString(data, ref offset, VolumeTypeString);
  113. WriteVarString(data, ref offset, DisableDriverLetterAssignmentString);
  114. ByteWriter.WriteAnsiString(data, ref offset, StateString, 14);
  115. ByteWriter.WriteByte(data, ref offset, (byte)ReadPolicy);
  116. WriteVarUInt(data, ref offset, VolumeNumber);
  117. BigEndianWriter.WriteUInt32(data, ref offset, (uint)VolumeFlags);
  118. WriteVarUInt(data, ref offset, NumberOfComponents);
  119. BigEndianWriter.WriteUInt64(data, ref offset, CommitTransactionID);
  120. BigEndianWriter.WriteUInt64(data, ref offset, UnknownTransactionID);
  121. WritePaddedVarULong(data, ref offset, SizeLBA);
  122. offset += 4;
  123. ByteWriter.WriteByte(data, ref offset, (byte)PartitionType);
  124. BigEndianWriter.WriteGuidBytes(data, ref offset, VolumeGuid);
  125. if (HasUnknownID1Flag)
  126. {
  127. WriteVarULong(data, ref offset, UnknownID1);
  128. }
  129. if (HasUnknownID2Flag)
  130. {
  131. WriteVarULong(data, ref offset, UnknownID2);
  132. }
  133. if (HasColumnSizeFlag)
  134. {
  135. WritePaddedVarULong(data, ref offset, ColumnSizeLBA);
  136. }
  137. if (HasMountHintFlag)
  138. {
  139. WriteVarString(data, ref offset, MountHint);
  140. }
  141. return data;
  142. }
  143. public ulong VolumeId
  144. {
  145. get
  146. {
  147. return this.Id;
  148. }
  149. }
  150. public bool HasUnknownID1Flag
  151. {
  152. get
  153. {
  154. return (Flags & 0x08) != 0;
  155. }
  156. }
  157. public bool HasUnknownID2Flag
  158. {
  159. get
  160. {
  161. return (Flags & 0x20) != 0;
  162. }
  163. }
  164. public bool HasColumnSizeFlag
  165. {
  166. get
  167. {
  168. return (Flags & 0x80) != 0;
  169. }
  170. }
  171. public bool HasMountHintFlag
  172. {
  173. get
  174. {
  175. return (Flags & 0x02) != 0;
  176. }
  177. }
  178. }
  179. }