ResidentAttributeRecord.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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.IO;
  10. using System.Text;
  11. using Utilities;
  12. namespace DiskAccessLibrary.FileSystems.NTFS
  13. {
  14. public class ResidentAttributeRecord : AttributeRecord
  15. {
  16. public const int HeaderLength = 0x18;
  17. public byte[] Data;
  18. public byte IndexedFlag;
  19. public ResidentAttributeRecord(byte[] buffer, int offset) : base(buffer, offset)
  20. {
  21. uint dataLength = LittleEndianConverter.ToUInt32(buffer, offset + 0x10);
  22. ushort dataOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x14);
  23. IndexedFlag = ByteReader.ReadByte(buffer, offset + 0x16);
  24. if (dataOffset + dataLength > this.StoredRecordLength)
  25. {
  26. throw new InvalidDataException("Corrupt attribute, data outside of attribute record");
  27. }
  28. Data = ByteReader.ReadBytes(buffer, offset + dataOffset, (int)dataLength);
  29. }
  30. public override byte[] GetBytes(int bytesPerCluster)
  31. {
  32. uint length = this.RecordLength;
  33. byte[] buffer = new byte[length];
  34. WriteHeader(buffer, HeaderLength);
  35. uint dataLength = (uint)Data.Length;
  36. ushort dataOffset = (ushort)(HeaderLength + Name.Length * 2);
  37. LittleEndianWriter.WriteUInt32(buffer, 0x10, dataLength);
  38. LittleEndianWriter.WriteUInt16(buffer, 0x14, dataOffset);
  39. ByteWriter.WriteByte(buffer, 0x16, IndexedFlag);
  40. ByteWriter.WriteBytes(buffer, dataOffset, Data);
  41. return buffer;
  42. }
  43. public override byte[] GetData(NTFSVolume volume)
  44. {
  45. return Data;
  46. }
  47. /// <summary>
  48. /// When reading attributes, they may contain additional padding,
  49. /// so we should use StoredRecordLength to advance the buffer position instead.
  50. /// </summary>
  51. public override uint RecordLength
  52. {
  53. get
  54. {
  55. uint length = (uint)(AttributeRecord.AttributeRecordHeaderLength + 8 + Name.Length * 2 + Data.Length);
  56. // Each record is aligned to 8-byte boundary
  57. length = (uint)Math.Ceiling((double)length / 8) * 8;
  58. return length;
  59. }
  60. }
  61. }
  62. }