DynamicDiskHeader.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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.VHD
  12. {
  13. public class DynamicDiskHeader
  14. {
  15. public const int Length = 1024;
  16. public const string DynamidDiskHeaderCookie = "cxsparse";
  17. public string Cookie; // 8 bytes
  18. public ulong DataOffset; // The documentation says 0xFFFFFFFF, but all programs use 0xFFFFFFFFFFFFFFFF
  19. public ulong TableOffset;
  20. public uint HeaderVersion;
  21. public uint MaxTableEntries;
  22. public uint BlockSize;
  23. //public uint Checksum;
  24. public Guid ParentUniqueID;
  25. public uint ParentTimeStamp;
  26. public uint Reserved;
  27. public string ParentUnicodeName = String.Empty; // 8 bytes
  28. public ParentLocatorEntry ParentLocatorEntry1;
  29. public ParentLocatorEntry ParentLocatorEntry2;
  30. public ParentLocatorEntry ParentLocatorEntry3;
  31. public ParentLocatorEntry ParentLocatorEntry4;
  32. public ParentLocatorEntry ParentLocatorEntry5;
  33. public ParentLocatorEntry ParentLocatorEntry6;
  34. public ParentLocatorEntry ParentLocatorEntry7;
  35. public ParentLocatorEntry ParentLocatorEntry8;
  36. private bool m_isValid = true;
  37. public DynamicDiskHeader()
  38. {
  39. Cookie = DynamidDiskHeaderCookie;
  40. DataOffset = 0xFFFFFFFFFFFFFFFF;
  41. HeaderVersion = 0x00010000;
  42. }
  43. public DynamicDiskHeader(byte[] buffer)
  44. {
  45. Cookie = ByteReader.ReadAnsiString(buffer, 0x00, 8);
  46. DataOffset = BigEndianConverter.ToUInt64(buffer, 0x08);
  47. TableOffset = BigEndianConverter.ToUInt64(buffer, 0x10);
  48. HeaderVersion = BigEndianConverter.ToUInt32(buffer, 0x18);
  49. MaxTableEntries = BigEndianConverter.ToUInt32(buffer, 0x1C);
  50. BlockSize = BigEndianConverter.ToUInt32(buffer, 0x20);
  51. uint checksum = BigEndianConverter.ToUInt32(buffer, 0x24);
  52. ParentUniqueID = BigEndianConverter.ToGuid(buffer, 0x28);
  53. ParentTimeStamp = BigEndianConverter.ToUInt32(buffer, 0x38);
  54. Reserved = BigEndianConverter.ToUInt32(buffer, 0x3C);
  55. ParentUnicodeName = ByteReader.ReadUTF16String(buffer, 0x40, 256).TrimEnd('\0');
  56. ParentLocatorEntry1 = new ParentLocatorEntry(buffer, 0x240);
  57. ParentLocatorEntry2 = new ParentLocatorEntry(buffer, 0x258);
  58. ParentLocatorEntry3 = new ParentLocatorEntry(buffer, 0x270);
  59. ParentLocatorEntry4 = new ParentLocatorEntry(buffer, 0x288);
  60. ParentLocatorEntry5 = new ParentLocatorEntry(buffer, 0x2A0);
  61. ParentLocatorEntry6 = new ParentLocatorEntry(buffer, 0x2B8);
  62. ParentLocatorEntry7 = new ParentLocatorEntry(buffer, 0x2D0);
  63. ParentLocatorEntry8 = new ParentLocatorEntry(buffer, 0x2E8);
  64. byte[] temp = (byte[])buffer.Clone();
  65. BigEndianWriter.WriteInt32(temp, 0x24, 0);
  66. uint expectedChecksum = VHDFooter.CalculateChecksum(temp);
  67. m_isValid = String.Equals(Cookie, DynamidDiskHeaderCookie) && (checksum == expectedChecksum) && (HeaderVersion == 0x00010000);
  68. }
  69. public byte[] GetBytes()
  70. {
  71. byte[] buffer = new byte[Length];
  72. ByteWriter.WriteAnsiString(buffer, 0x00, Cookie, 8);
  73. BigEndianWriter.WriteUInt64(buffer, 0x08, DataOffset);
  74. BigEndianWriter.WriteUInt64(buffer, 0x10, TableOffset);
  75. BigEndianWriter.WriteUInt32(buffer, 0x18, HeaderVersion);
  76. BigEndianWriter.WriteUInt32(buffer, 0x1C, MaxTableEntries);
  77. BigEndianWriter.WriteUInt32(buffer, 0x20, BlockSize);
  78. // We'll write the checksum later
  79. BigEndianWriter.WriteGuidBytes(buffer, 0x28, ParentUniqueID);
  80. BigEndianWriter.WriteUInt32(buffer, 0x38, ParentTimeStamp);
  81. BigEndianWriter.WriteUInt32(buffer, 0x3C, Reserved);
  82. ByteWriter.WriteUTF16String(buffer, 0x40, ParentUnicodeName, 256);
  83. ParentLocatorEntry1.WriteBytes(buffer, 0x240);
  84. ParentLocatorEntry2.WriteBytes(buffer, 0x258);
  85. ParentLocatorEntry3.WriteBytes(buffer, 0x270);
  86. ParentLocatorEntry4.WriteBytes(buffer, 0x288);
  87. ParentLocatorEntry5.WriteBytes(buffer, 0x2A0);
  88. ParentLocatorEntry6.WriteBytes(buffer, 0x2B8);
  89. ParentLocatorEntry7.WriteBytes(buffer, 0x2D0);
  90. ParentLocatorEntry8.WriteBytes(buffer, 0x2E8);
  91. uint checksum = VHDFooter.CalculateChecksum(buffer);
  92. BigEndianWriter.WriteUInt32(buffer, 0x24, checksum);
  93. return buffer;
  94. }
  95. }
  96. }