public string ToString(bool formatted) { var b = new StringBuilder(); string fmt = formatted ? " " : ""; b.AppendLine("XvdMiscInfo:"); b.AppendLineSpace(fmt + $"Page Count: 0x{Header.NumberOfHashedPages:X}"); b.AppendLineSpace(fmt + $"Embedded XVD Offset: 0x{EmbeddedXvdOffset:X}"); b.AppendLineSpace(fmt + $"MDU Offset: 0x{MduOffset:X}"); b.AppendLineSpace(fmt + $"HashTree Offset: 0x{HashTreeOffset:X}"); b.AppendLineSpace(fmt + $"User Data Offset: 0x{UserDataOffset:X}"); b.AppendLineSpace(fmt + $"XVC Data Offset: 0x{XvcInfoOffset:X}"); b.AppendLineSpace(fmt + $"Dynamic Header Offset: 0x{DynamicHeaderOffset:X}"); b.AppendLineSpace(fmt + $"Drive Data Offset: 0x{DriveDataOffset:X}"); if (IsDataIntegrityEnabled) { b.AppendLineSpace(fmt + $"Hash Tree Page Count: 0x{HashTreePageCount:X}"); b.AppendLineSpace(fmt + $"Hash Tree Levels: 0x{HashTreeLevels:X}"); b.AppendLineSpace(fmt + $"Hash Tree Valid: {HashTreeValid}"); if (!DisableDataHashChecking) { b.AppendLineSpace(fmt + $"Data Hash Tree Valid: {DataHashTreeValid}"); } } if (IsXvcFile) { b.AppendLineSpace(fmt + $"XVC Data Hash Valid: {XvcDataHashValid}"); } b.AppendLine(); b.Append(Header.ToString(formatted)); if (IsXvcFile && XvcInfo.ContentID != null) { b.AppendLine(); bool xvcKeyFound = GetXvcKey(0, out var decryptKey); if (xvcKeyFound) { b.AppendLine($"Decrypt key for xvc keyslot 0: {decryptKey.ToHexString()}"); b.AppendLine("(key is wrong though until the obfuscation/encryption on it is figured out)"); b.AppendLine(); } b.AppendLine(XvcInfo.ToString(formatted)); } if (RegionHeaders != null) { for (int i = 0; i < RegionHeaders.Count; i++) { b.AppendLine(); string presenceInfo = ""; if (RegionPresenceInfo != null && RegionPresenceInfo.Count > i) { var presenceFlags = RegionPresenceInfo[i]; presenceInfo = " ("; presenceInfo += (presenceFlags.HasFlag(XvcRegionPresenceInfo.IsPresent) ? "present" : "not present") + ", "; presenceInfo += presenceFlags.HasFlag(XvcRegionPresenceInfo.IsAvailable) ? "available" : "unavailable"; if (((int)presenceFlags & 0xF0) != 0) { presenceInfo += $", on disc {(int)presenceFlags >> 4}"; } presenceInfo += ")"; } b.AppendLine($"Region {i}{presenceInfo}"); b.Append(RegionHeaders[i].ToString(formatted)); } } if (UpdateSegments != null && UpdateSegments.Count > 0) { // have to add segments to a seperate List so we can store the index of them... var segments = new List <Tuple <int, XvcUpdateSegment> >(); for (int i = 0; i < UpdateSegments.Count; i++) { if (UpdateSegments[i].Hash == 0) { break; } segments.Add(Tuple.Create(i, UpdateSegments[i])); } b.AppendLine(); b.AppendLine("Update Segments:"); b.AppendLine(); b.AppendLine(segments.ToStringTable( new[] { "Id", "PageNum (Offset)", "Hash" }, a => a.Item1, a => $"0x{a.Item2.PageNum:X} (0x{XvdMath.PageNumberToOffset(a.Item2.PageNum):X})", a => $"0x{a.Item2.Hash:X}")); } if (RegionSpecifiers != null && RegionSpecifiers.Count > 0) { // have to add specifiers to a seperate List so we can store the index of them... var specs = new List <Tuple <int, XvcRegionSpecifier> >(); for (int i = 0; i < RegionSpecifiers.Count; i++) { specs.Add(Tuple.Create(i, RegionSpecifiers[i])); } b.AppendLine(); b.AppendLine("Region Specifiers:"); b.AppendLine(); b.AppendLine(specs.ToStringTable( new[] { "Id", "RegionId", "Key", "Value" }, a => a.Item1, a => $"0x{a.Item2.RegionId:X}", a => a.Item2.Key, a => a.Item2.Value)); } if (!IsEncrypted) { b.AppendLine(); try { b.Append(Filesystem.ToString(formatted)); } catch (Exception e) { b.AppendLine($"Failed to get XvdFilesystem info, error: {e}"); } } else { b.AppendLine($"Cannot get XvdFilesystem from encrypted package"); } return(b.ToString()); }
public string ToString(bool formatted) { var b = new StringBuilder(); string fmt = formatted ? " " : ""; b.AppendLine("XvdMiscInfo:"); b.AppendLineSpace(fmt + "Block Count: 0x" + XvdDataBlockCount.ToString("X")); if (Header.EmbeddedXVDLength > 0) { b.AppendLineSpace(fmt + "Embedded XVD Offset: 0x3000"); } if (Header.UserDataLength > 0) { b.AppendLineSpace(fmt + "User Data Offset: 0x" + UserDataOffset.ToString("X")); } b.AppendLineSpace(fmt + "XVD Data Offset: 0x" + DataOffset.ToString("X")); if (IsDataIntegrityEnabled) { b.AppendLineSpace(fmt + "Hash Tree Block Count: 0x" + HashTreeBlockCount.ToString("X")); b.AppendLineSpace(fmt + "Hash Tree Levels: 0x" + HashTreeLevels.ToString("X")); b.AppendLineSpace(fmt + "Hash Tree Valid: " + (HashTreeValid ? "true" : "false")); if (!DisableDataHashChecking) { b.AppendLineSpace(fmt + "Data Hash Tree Valid: " + (DataHashTreeValid ? "true" : "false")); } } if (IsXvcFile) { b.AppendLineSpace(fmt + "XVC Data Hash Valid: " + (XvcDataHashValid ? "true" : "false")); } b.AppendLine(); b.Append(Header.ToString(formatted)); if (XvcInfo.ContentID == null) { return(b.ToString()); } b.AppendLine(); if (formatted) { byte[] decryptKey; string licenseFile = GetXvcKey(0, out decryptKey); if (!String.IsNullOrEmpty(licenseFile)) { if (licenseFile != "testsigned") { b.AppendLine("Decrypt key from license file " + licenseFile + " (key is wrong though until the obfuscation/encryption on it is figured out)"); } else { b.AppendLine("Decrypt key for test-signed package:"); } b.AppendLine(decryptKey.ToHexString()); b.AppendLine(); } } b.AppendLine(XvcInfo.ToString(formatted)); if (RegionHeaders != null) { for (int i = 0; i < RegionHeaders.Count; i++) { b.AppendLine(); b.AppendLine("Region " + i); b.Append(RegionHeaders[i].ToString(formatted)); } } if (RegionHeaders != null) { for (int i = 0; i < UpdateSegments.Count; i++) { if (UpdateSegments[i].Unknown1 == 0) { break; } b.AppendLine(); b.AppendLine("Update Segment " + i); b.Append(UpdateSegments[i].ToString(formatted)); } } return(b.ToString()); }