diff --git a/BinaryObjectScanner.Wrappers/AACSMediaKeyBlock.cs b/BinaryObjectScanner.Wrappers/AACSMediaKeyBlock.cs index 611026bb..09f28ffa 100644 --- a/BinaryObjectScanner.Wrappers/AACSMediaKeyBlock.cs +++ b/BinaryObjectScanner.Wrappers/AACSMediaKeyBlock.cs @@ -21,7 +21,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.AACS.Record[] Records => _model.Records; #else - public SabreTools.Models.AACS.Record?[] Records => _model.Records; + public SabreTools.Models.AACS.Record?[]? Records => _model.Records; #endif #endregion @@ -58,7 +58,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// An AACS media key block wrapper on success, null on failure +#if NET48 public static AACSMediaKeyBlock Create(byte[] data, int offset) +#else + public static AACSMediaKeyBlock? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -78,7 +82,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// An AACS media key block wrapper on success, null on failure +#if NET48 public static AACSMediaKeyBlock Create(Stream data) +#else + public static AACSMediaKeyBlock? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -141,7 +149,7 @@ namespace BinaryObjectScanner.Wrappers { case SabreTools.Models.AACS.RecordType.EndOfMediaKeyBlock: var eomkb = record as SabreTools.Models.AACS.EndOfMediaKeyBlockRecord; - builder.AppendLine($" Signature data: {BitConverter.ToString(eomkb.SignatureData ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" Signature data: {(eomkb.SignatureData == null ? "[NULL]" : BitConverter.ToString(eomkb.SignatureData).Replace('-', ' '))}"); break; case SabreTools.Models.AACS.RecordType.ExplicitSubsetDifference: @@ -177,7 +185,7 @@ namespace BinaryObjectScanner.Wrappers for (int j = 0; j < mkd.MediaKeyData.Length; j++) { var mk = mkd.MediaKeyData[j]; - builder.AppendLine($" Media key {j}: {BitConverter.ToString(mk ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" Media key {j}: {(mk == null ? "[NULL]" : BitConverter.ToString(mk).Replace('-', ' '))}"); } } break; @@ -236,7 +244,7 @@ namespace BinaryObjectScanner.Wrappers var ef = block.EntryFields[k]; builder.AppendLine($" Entry {k}"); builder.AppendLine($" Range: {ef.Range} (0x{ef.Range:X})"); - builder.AppendLine($" Drive ID: {BitConverter.ToString(ef.DriveID ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" Drive ID: {(ef.DriveID == null ? "[NULL]" : BitConverter.ToString(ef.DriveID).Replace('-', ' '))}"); } } } @@ -272,7 +280,7 @@ namespace BinaryObjectScanner.Wrappers var ef = block.EntryFields[k]; builder.AppendLine($" Entry {k}"); builder.AppendLine($" Range: {ef.Range} (0x{ef.Range:X})"); - builder.AppendLine($" Host ID: {BitConverter.ToString(ef.HostID ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" Host ID: {(ef.HostID == null ? "[NULL]" : BitConverter.ToString(ef.HostID).Replace('-', ' '))}"); } } } @@ -281,7 +289,7 @@ namespace BinaryObjectScanner.Wrappers case SabreTools.Models.AACS.RecordType.VerifyMediaKey: var vmk = record as SabreTools.Models.AACS.VerifyMediaKeyRecord; - builder.AppendLine($" Ciphertext value: {BitConverter.ToString(vmk.CiphertextValue ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" Ciphertext value: {(vmk.CiphertextValue == null ? "[NULL]" : BitConverter.ToString(vmk.CiphertextValue).Replace('-', ' '))}"); break; case SabreTools.Models.AACS.RecordType.Copyright: diff --git a/BinaryObjectScanner.Wrappers/BDPlusSVM.cs b/BinaryObjectScanner.Wrappers/BDPlusSVM.cs index 13c46ed4..c49c55e0 100644 --- a/BinaryObjectScanner.Wrappers/BDPlusSVM.cs +++ b/BinaryObjectScanner.Wrappers/BDPlusSVM.cs @@ -16,10 +16,18 @@ namespace BinaryObjectScanner.Wrappers #region Pass-Through Properties /// +#if NET48 public string Signature => _model.Signature; +#else + public string? Signature => _model.Signature; +#endif /// +#if NET48 public byte[] Unknown1 => _model.Unknown1; +#else + public byte[]? Unknown1 => _model.Unknown1; +#endif /// public ushort Year => _model.Year; @@ -31,13 +39,21 @@ namespace BinaryObjectScanner.Wrappers public byte Day => _model.Day; /// +#if NET48 public byte[] Unknown2 => _model.Unknown2; +#else + public byte[]? Unknown2 => _model.Unknown2; +#endif /// public uint Length => _model.Length; /// +#if NET48 public byte[] Data => _model.Data; +#else + public byte[]? Data => _model.Data; +#endif #endregion @@ -71,7 +87,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// A BD+ SVM wrapper on success, null on failure +#if NET48 public static BDPlusSVM Create(byte[] data, int offset) +#else + public static BDPlusSVM? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -91,7 +111,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A BD+ SVM wrapper on success, null on failure +#if NET48 public static BDPlusSVM Create(Stream data) +#else + public static BDPlusSVM? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -138,13 +162,13 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(" SVM Information:"); builder.AppendLine(" -------------------------"); builder.AppendLine($" Signature: {Signature}"); - builder.AppendLine($" Unknown 1: {BitConverter.ToString(Unknown1).Replace('-', ' ')}"); + builder.AppendLine($" Unknown 1: {(Unknown1 == null ? "[NULL]" : BitConverter.ToString(Unknown1).Replace('-', ' '))}"); builder.AppendLine($" Year: {Year} (0x{Year:X})"); builder.AppendLine($" Month: {Month} (0x{Month:X})"); builder.AppendLine($" Day: {Day} (0x{Day:X})"); - builder.AppendLine($" Unknown 2: {BitConverter.ToString(Unknown2).Replace('-', ' ')}"); + builder.AppendLine($" Unknown 2: {(Unknown2 == null ? "[NULL]" : BitConverter.ToString(Unknown2).Replace('-', ' '))}"); builder.AppendLine($" Length: {Length} (0x{Length:X})"); - //builder.AppendLine($" Data: {BitConverter.ToString(Data ?? new byte[0]).Replace('-', ' ')}"); + //builder.AppendLine($" Data: {(Data == null ? "[NULL]" : BitConverter.ToString(Data).Replace('-', ' '))}"); builder.AppendLine(); } diff --git a/BinaryObjectScanner.Wrappers/BFPK.cs b/BinaryObjectScanner.Wrappers/BFPK.cs index 279cbb1b..47badd86 100644 --- a/BinaryObjectScanner.Wrappers/BFPK.cs +++ b/BinaryObjectScanner.Wrappers/BFPK.cs @@ -19,7 +19,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Magic => _model.Header.Magic; +#else + public string? Magic => _model.Header.Magic; +#endif /// public int Version => _model.Header.Version; @@ -35,7 +39,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.BFPK.FileEntry[] FileTable => _model.Files; #else - public SabreTools.Models.BFPK.FileEntry?[] FileTable => _model.Files; + public SabreTools.Models.BFPK.FileEntry?[]? FileTable => _model.Files; #endif #endregion @@ -72,7 +76,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// A BFPK archive wrapper on success, null on failure +#if NET48 public static BFPK Create(byte[] data, int offset) +#else + public static BFPK? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -92,7 +100,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A BFPK archive wrapper on success, null on failure +#if NET48 public static BFPK Create(Stream data) +#else + public static BFPK? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -155,6 +167,8 @@ namespace BinaryObjectScanner.Wrappers // Get the file information var file = FileTable[index]; + if (file == null) + return false; // Get the read index and length int offset = file.Offset + 4; @@ -173,11 +187,17 @@ namespace BinaryObjectScanner.Wrappers Directory.CreateDirectory(outputDirectory); // Create the output path - string filePath = Path.Combine(outputDirectory, file.Name); + string filePath = Path.Combine(outputDirectory, file.Name ?? $"file{index}"); using (FileStream fs = File.OpenWrite(filePath)) { // Read the data block +#if NET48 byte[] data = ReadFromDataSource(offset, compressedSize); +#else + byte[]? data = ReadFromDataSource(offset, compressedSize); +#endif + if (data == null) + return false; // If we have uncompressed data if (compressedSize == file.UncompressedSize) diff --git a/BinaryObjectScanner.Wrappers/BSP.cs b/BinaryObjectScanner.Wrappers/BSP.cs index ada32c92..307a2151 100644 --- a/BinaryObjectScanner.Wrappers/BSP.cs +++ b/BinaryObjectScanner.Wrappers/BSP.cs @@ -30,7 +30,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.BSP.Lump[] Lumps => _model.Lumps; #else - public SabreTools.Models.BSP.Lump?[] Lumps => _model.Lumps; + public SabreTools.Models.BSP.Lump?[]? Lumps => _model.Lumps; #endif #endregion @@ -41,7 +41,11 @@ namespace BinaryObjectScanner.Wrappers public uint TextureCount => _model.TextureHeader.TextureCount; /// +#if NET48 public uint[] Offsets => _model.TextureHeader.Offsets; +#else + public uint[]? Offsets => _model.TextureHeader.Offsets; +#endif #endregion @@ -51,7 +55,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.BSP.Texture[] Textures => _model.Textures; #else - public SabreTools.Models.BSP.Texture?[] Textures => _model.Textures; + public SabreTools.Models.BSP.Texture?[]? Textures => _model.Textures; #endif #endregion @@ -88,7 +92,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the BSP /// Offset within the array to parse /// A BSP wrapper on success, null on failure +#if NET48 public static BSP Create(byte[] data, int offset) +#else + public static BSP? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -108,7 +116,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the BSP /// An BSP wrapper on success, null on failure +#if NET48 public static BSP Create(Stream data) +#else + public static BSP? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -326,7 +338,13 @@ namespace BinaryObjectScanner.Wrappers filename = Path.Combine(outputDirectory, filename); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try @@ -403,7 +421,13 @@ namespace BinaryObjectScanner.Wrappers filename = Path.Combine(outputDirectory, filename); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try @@ -427,7 +451,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Texture object to format /// Byte array representing the texture as a bitmap +#if NET48 private static byte[] CreateTextureData(SabreTools.Models.BSP.Texture texture) +#else + private static byte[]? CreateTextureData(SabreTools.Models.BSP.Texture texture) +#endif { // If there's no texture data if (texture.TextureData == null || texture.TextureData.Length == 0) diff --git a/BinaryObjectScanner.Wrappers/CFB.cs b/BinaryObjectScanner.Wrappers/CFB.cs index 9fc494e4..048f6bab 100644 --- a/BinaryObjectScanner.Wrappers/CFB.cs +++ b/BinaryObjectScanner.Wrappers/CFB.cs @@ -40,7 +40,11 @@ namespace BinaryObjectScanner.Wrappers public ushort MiniSectorShift => _model.Header.MiniSectorShift; /// +#if NET48 public byte[] Reserved => _model.Header.Reserved; +#else + public byte[]? Reserved => _model.Header.Reserved; +#endif /// public uint NumberOfDirectorySectors => _model.Header.NumberOfDirectorySectors; @@ -73,7 +77,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.CFB.SectorNumber[] DIFAT => _model.Header.DIFAT; #else - public SabreTools.Models.CFB.SectorNumber?[] DIFAT => _model.Header.DIFAT; + public SabreTools.Models.CFB.SectorNumber?[]? DIFAT => _model.Header.DIFAT; #endif #endregion @@ -84,7 +88,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.CFB.SectorNumber[] FATSectorNumbers => _model.FATSectorNumbers; #else - public SabreTools.Models.CFB.SectorNumber?[] FATSectorNumbers => _model.FATSectorNumbers; + public SabreTools.Models.CFB.SectorNumber?[]? FATSectorNumbers => _model.FATSectorNumbers; #endif #endregion @@ -95,7 +99,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.CFB.SectorNumber[] MiniFATSectorNumbers => _model.MiniFATSectorNumbers; #else - public SabreTools.Models.CFB.SectorNumber?[] MiniFATSectorNumbers => _model.MiniFATSectorNumbers; + public SabreTools.Models.CFB.SectorNumber?[]? MiniFATSectorNumbers => _model.MiniFATSectorNumbers; #endif #endregion @@ -106,7 +110,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.CFB.SectorNumber[] DIFATSectorNumbers => _model.DIFATSectorNumbers; #else - public SabreTools.Models.CFB.SectorNumber?[] DIFATSectorNumbers => _model.DIFATSectorNumbers; + public SabreTools.Models.CFB.SectorNumber?[]? DIFATSectorNumbers => _model.DIFATSectorNumbers; #endif #endregion @@ -117,7 +121,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public SabreTools.Models.CFB.DirectoryEntry[] DirectoryEntries => _model.DirectoryEntries; #else - public SabreTools.Models.CFB.DirectoryEntry?[] DirectoryEntries => _model.DirectoryEntries; + public SabreTools.Models.CFB.DirectoryEntry?[]? DirectoryEntries => _model.DirectoryEntries; #endif #endregion @@ -168,7 +172,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// A Compound File Binary wrapper on success, null on failure +#if NET48 public static CFB Create(byte[] data, int offset) +#else + public static CFB? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -188,7 +196,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A Compound File Binary wrapper on success, null on failure +#if NET48 public static CFB Create(Stream data) +#else + public static CFB? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -220,7 +232,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public List GetFATSectorChain(SabreTools.Models.CFB.SectorNumber startingSector) #else - public List GetFATSectorChain(SabreTools.Models.CFB.SectorNumber? startingSector) + public List? GetFATSectorChain(SabreTools.Models.CFB.SectorNumber? startingSector) #endif { // If we have an invalid sector @@ -257,7 +269,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Initial FAT sector /// Ordered list of sector numbers, null on error +#if NET48 public byte[] GetFATSectorChainData(SabreTools.Models.CFB.SectorNumber startingSector) +#else + public byte[]? GetFATSectorChainData(SabreTools.Models.CFB.SectorNumber startingSector) +#endif { // Get the sector chain first var sectorChain = GetFATSectorChain(startingSector); @@ -297,7 +313,11 @@ namespace BinaryObjectScanner.Wrappers #endif { // If we have an invalid sector number +#if NET48 + if (sector > SabreTools.Models.CFB.SectorNumber.MAXREGSECT) +#else if (sector == null || sector > SabreTools.Models.CFB.SectorNumber.MAXREGSECT) +#endif return -1; // Convert based on the sector shift value @@ -316,7 +336,7 @@ namespace BinaryObjectScanner.Wrappers #if NET48 public List GetMiniFATSectorChain(SabreTools.Models.CFB.SectorNumber startingSector) #else - public List GetMiniFATSectorChain(SabreTools.Models.CFB.SectorNumber? startingSector) + public List? GetMiniFATSectorChain(SabreTools.Models.CFB.SectorNumber? startingSector) #endif { // If we have an invalid sector @@ -353,7 +373,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Initial Mini FAT sector /// Ordered list of sector numbers, null on error +#if NET48 public byte[] GetMiniFATSectorChainData(SabreTools.Models.CFB.SectorNumber startingSector) +#else + public byte[]? GetMiniFATSectorChainData(SabreTools.Models.CFB.SectorNumber startingSector) +#endif { // Get the sector chain first var sectorChain = GetMiniFATSectorChain(startingSector); @@ -393,7 +417,11 @@ namespace BinaryObjectScanner.Wrappers #endif { // If we have an invalid sector number +#if NET48 + if (sector > SabreTools.Models.CFB.SectorNumber.MAXREGSECT) +#else if (sector == null || sector > SabreTools.Models.CFB.SectorNumber.MAXREGSECT) +#endif return -1; // Convert based on the sector shift value @@ -437,7 +465,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Byte order: {ByteOrder} (0x{ByteOrder:X})"); builder.AppendLine($" Sector shift: {SectorShift} (0x{SectorShift:X}) => {SectorSize}"); builder.AppendLine($" Mini sector shift: {MiniSectorShift} (0x{MiniSectorShift:X}) => {MiniSectorSize}"); - builder.AppendLine($" Reserved: {BitConverter.ToString(Reserved).Replace('-', ' ')}"); + builder.AppendLine($" Reserved: {(Reserved == null ? "[NULL]" : BitConverter.ToString(Reserved).Replace('-', ' '))}"); builder.AppendLine($" Number of directory sectors: {NumberOfDirectorySectors} (0x{NumberOfDirectorySectors:X})"); builder.AppendLine($" Number of FAT sectors: {NumberOfFATSectors} (0x{NumberOfFATSectors:X})"); builder.AppendLine($" First directory sector location: {FirstDirectorySectorLocation} (0x{FirstDirectorySectorLocation:X})"); diff --git a/BinaryObjectScanner.Wrappers/CIA.cs b/BinaryObjectScanner.Wrappers/CIA.cs index 42786c0b..f944f5b0 100644 --- a/BinaryObjectScanner.Wrappers/CIA.cs +++ b/BinaryObjectScanner.Wrappers/CIA.cs @@ -42,7 +42,11 @@ namespace BinaryObjectScanner.Wrappers public ulong ContentSize => _model.Header.ContentSize; /// +#if NET48 public byte[] ContentIndex => _model.Header.ContentIndex; +#else + public byte[]? ContentIndex => _model.Header.ContentIndex; +#endif #endregion @@ -69,16 +73,32 @@ namespace BinaryObjectScanner.Wrappers public byte T_PaddingSize => _model.Ticket.PaddingSize; /// +#if NET48 public byte[] T_Signature => _model.Ticket.Signature; +#else + public byte[]? T_Signature => _model.Ticket.Signature; +#endif /// +#if NET48 public byte[] T_Padding => _model.Ticket.Padding; +#else + public byte[]? T_Padding => _model.Ticket.Padding; +#endif /// +#if NET48 public string T_Issuer => _model.Ticket.Issuer; +#else + public string? T_Issuer => _model.Ticket.Issuer; +#endif /// +#if NET48 public byte[] T_ECCPublicKey => _model.Ticket.ECCPublicKey; +#else + public byte[]? T_ECCPublicKey => _model.Ticket.ECCPublicKey; +#endif /// public byte T_Version => _model.Ticket.Version; @@ -90,7 +110,11 @@ namespace BinaryObjectScanner.Wrappers public byte T_SignerCrlVersion => _model.Ticket.SignerCrlVersion; /// +#if NET48 public byte[] T_TitleKey => _model.Ticket.TitleKey; +#else + public byte[]? T_TitleKey => _model.Ticket.TitleKey; +#endif /// public byte T_Reserved1 => _model.Ticket.Reserved1; @@ -105,13 +129,21 @@ namespace BinaryObjectScanner.Wrappers public ulong T_TitleID => _model.Ticket.TitleID; /// +#if NET48 public byte[] T_Reserved2 => _model.Ticket.Reserved2; +#else + public byte[]? T_Reserved2 => _model.Ticket.Reserved2; +#endif /// public ushort T_TicketTitleVersion => _model.Ticket.TicketTitleVersion; /// +#if NET48 public byte[] T_Reserved3 => _model.Ticket.Reserved3; +#else + public byte[]? T_Reserved3 => _model.Ticket.Reserved3; +#endif /// public byte T_LicenseType => _model.Ticket.LicenseType; @@ -120,7 +152,11 @@ namespace BinaryObjectScanner.Wrappers public byte T_CommonKeyYIndex => _model.Ticket.CommonKeyYIndex; /// +#if NET48 public byte[] T_Reserved4 => _model.Ticket.Reserved4; +#else + public byte[]? T_Reserved4 => _model.Ticket.Reserved4; +#endif /// public uint T_eShopAccountID => _model.Ticket.eShopAccountID; @@ -132,16 +168,28 @@ namespace BinaryObjectScanner.Wrappers public byte T_Audit => _model.Ticket.Audit; /// +#if NET48 public byte[] T_Reserved6 => _model.Ticket.Reserved6; +#else + public byte[]? T_Reserved6 => _model.Ticket.Reserved6; +#endif /// +#if NET48 public uint[] T_Limits => _model.Ticket.Limits; +#else + public uint[]? T_Limits => _model.Ticket.Limits; +#endif /// public uint T_ContentIndexSize => _model.Ticket.ContentIndexSize; /// +#if NET48 public byte[] T_ContentIndex => _model.Ticket.ContentIndex; +#else + public byte[]? T_ContentIndex => _model.Ticket.ContentIndex; +#endif /// #if NET48 @@ -164,13 +212,25 @@ namespace BinaryObjectScanner.Wrappers public byte TMD_PaddingSize => _model.TMDFileData.PaddingSize; /// +#if NET48 public byte[] TMD_Signature => _model.TMDFileData.Signature; +#else + public byte[]? TMD_Signature => _model.TMDFileData.Signature; +#endif /// +#if NET48 public byte[] TMD_Padding1 => _model.TMDFileData.Padding1; +#else + public byte[]? TMD_Padding1 => _model.TMDFileData.Padding1; +#endif /// +#if NET48 public string TMD_Issuer => _model.TMDFileData.Issuer; +#else + public string? TMD_Issuer => _model.TMDFileData.Issuer; +#endif /// public byte TMD_Version => _model.TMDFileData.Version; @@ -203,13 +263,21 @@ namespace BinaryObjectScanner.Wrappers public uint TMD_SRLPrivateSaveDataSize => _model.TMDFileData.SRLPrivateSaveDataSize; /// +#if NET48 public byte[] TMD_Reserved2 => _model.TMDFileData.Reserved2; +#else + public byte[]? TMD_Reserved2 => _model.TMDFileData.Reserved2; +#endif /// public byte TMD_SRLFlag => _model.TMDFileData.SRLFlag; /// +#if NET48 public byte[] TMD_Reserved3 => _model.TMDFileData.Reserved3; +#else + public byte[]? TMD_Reserved3 => _model.TMDFileData.Reserved3; +#endif /// public uint TMD_AccessRights => _model.TMDFileData.AccessRights; @@ -224,10 +292,18 @@ namespace BinaryObjectScanner.Wrappers public ushort TMD_BootContent => _model.TMDFileData.BootContent; /// +#if NET48 public byte[] TMD_Padding2 => _model.TMDFileData.Padding2; +#else + public byte[]? TMD_Padding2 => _model.TMDFileData.Padding2; +#endif /// +#if NET48 public byte[] TMD_SHA256HashContentInfoRecords => _model.TMDFileData.SHA256HashContentInfoRecords; +#else + public byte[]? TMD_SHA256HashContentInfoRecords => _model.TMDFileData.SHA256HashContentInfoRecords; +#endif /// #if NET48 @@ -266,19 +342,35 @@ namespace BinaryObjectScanner.Wrappers #region Meta Data /// +#if NET48 public byte[] MD_TitleIDDependencyList => _model.MetaData?.TitleIDDependencyList; +#else + public byte[]? MD_TitleIDDependencyList => _model.MetaData?.TitleIDDependencyList; +#endif /// +#if NET48 public byte[] MD_Reserved1 => _model.MetaData?.Reserved1; +#else + public byte[]? MD_Reserved1 => _model.MetaData?.Reserved1; +#endif /// public uint? MD_CoreVersion => _model.MetaData?.CoreVersion; /// +#if NET48 public byte[] MD_Reserved2 => _model.MetaData?.Reserved2; +#else + public byte[]? MD_Reserved2 => _model.MetaData?.Reserved2; +#endif /// +#if NET48 public byte[] MD_IconData => _model.MetaData?.IconData; +#else + public byte[]? MD_IconData => _model.MetaData?.IconData; +#endif #endregion @@ -314,7 +406,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// A CIA archive wrapper on success, null on failure +#if NET48 public static CIA Create(byte[] data, int offset) +#else + public static CIA? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -334,7 +430,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A CIA archive wrapper on success, null on failure +#if NET48 public static CIA Create(Stream data) +#else + public static CIA? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -393,7 +493,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" TMD file size: {TMDFileSize} (0x{TMDFileSize:X})"); builder.AppendLine($" Meta size: {MetaSize} (0x{MetaSize:X})"); builder.AppendLine($" Content size: {ContentSize} (0x{ContentSize:X})"); - builder.AppendLine($" Content index: {BitConverter.ToString(ContentIndex).Replace('-', ' ')}"); + builder.AppendLine($" Content index: {(ContentIndex == null ? "[NULL]" : BitConverter.ToString(ContentIndex).Replace('-', ' '))}"); builder.AppendLine(); } @@ -427,8 +527,8 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})"); builder.AppendLine($" Signature size: {certificate.SignatureSize} (0x{certificate.SignatureSize:X})"); builder.AppendLine($" Padding size: {certificate.PaddingSize} (0x{certificate.PaddingSize:X})"); - builder.AppendLine($" Signature: {BitConverter.ToString(certificate.Signature).Replace('-', ' ')}"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.Padding).Replace('-', ' ')}"); + builder.AppendLine($" Signature: {(certificate.Signature == null ? "[NULL]" : BitConverter.ToString(certificate.Signature).Replace('-', ' '))}"); + builder.AppendLine($" Padding: {(certificate.Padding == null ? "[NULL]" : BitConverter.ToString(certificate.Padding).Replace('-', ' '))}"); builder.AppendLine($" Issuer: {certificate.Issuer ?? "[NULL]"}"); builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})"); builder.AppendLine($" Name: {certificate.Name ?? "[NULL]"}"); @@ -437,13 +537,13 @@ namespace BinaryObjectScanner.Wrappers { case SabreTools.Models.N3DS.PublicKeyType.RSA_4096: case SabreTools.Models.N3DS.PublicKeyType.RSA_2048: - builder.AppendLine($" Modulus: {BitConverter.ToString(certificate.RSAModulus).Replace('-', ' ')}"); + builder.AppendLine($" Modulus: {(certificate.RSAModulus == null ? "[NULL]" : BitConverter.ToString(certificate.RSAModulus).Replace('-', ' '))}"); builder.AppendLine($" Public exponent: {certificate.RSAPublicExponent} (0x{certificate.RSAPublicExponent:X})"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.RSAPadding).Replace('-', ' ')}"); + builder.AppendLine($" Padding: {(certificate.RSAPadding == null ? "[NULL]" : BitConverter.ToString(certificate.RSAPadding).Replace('-', ' '))}"); break; case SabreTools.Models.N3DS.PublicKeyType.EllipticCurve: - builder.AppendLine($" Public key: {BitConverter.ToString(certificate.ECCPublicKey).Replace('-', ' ')}"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.ECCPadding).Replace('-', ' ')}"); + builder.AppendLine($" Public key: {(certificate.ECCPublicKey == null ? "[NULL]" : BitConverter.ToString(certificate.ECCPublicKey).Replace('-', ' '))}"); + builder.AppendLine($" Padding: {(certificate.ECCPadding == null ? "[NULL]" : BitConverter.ToString(certificate.ECCPadding).Replace('-', ' '))}"); break; } } @@ -462,35 +562,35 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Signature type: {T_SignatureType} (0x{T_SignatureType:X})"); builder.AppendLine($" Signature size: {T_SignatureSize} (0x{T_SignatureSize:X})"); builder.AppendLine($" Padding size: {T_PaddingSize} (0x{T_PaddingSize:X})"); - builder.AppendLine($" Signature: {BitConverter.ToString(T_Signature).Replace('-', ' ')}"); - builder.AppendLine($" Padding: {BitConverter.ToString(T_Padding).Replace('-', ' ')}"); + builder.AppendLine($" Signature: {(T_Signature == null ? "[NULL]" : BitConverter.ToString(T_Signature).Replace('-', ' '))}"); + builder.AppendLine($" Padding: {(T_Padding == null ? "[NULL]" : BitConverter.ToString(T_Padding).Replace('-', ' '))}"); builder.AppendLine($" Issuer: {T_Issuer ?? "[NULL]"}"); - builder.AppendLine($" ECC public key: {BitConverter.ToString(T_ECCPublicKey).Replace('-', ' ')}"); + builder.AppendLine($" ECC public key: {(T_ECCPublicKey == null ? "[NULL]" : BitConverter.ToString(T_ECCPublicKey).Replace('-', ' '))}"); builder.AppendLine($" Version: {T_Version} (0x{T_Version:X})"); builder.AppendLine($" CaCrlVersion: {T_CaCrlVersion} (0x{T_CaCrlVersion:X})"); builder.AppendLine($" SignerCrlVersion: {T_SignerCrlVersion} (0x{T_SignerCrlVersion:X})"); - builder.AppendLine($" Title key: {BitConverter.ToString(T_TitleKey).Replace('-', ' ')}"); + builder.AppendLine($" Title key: {(T_TitleKey == null ? "[NULL]" : BitConverter.ToString(T_TitleKey).Replace('-', ' '))}"); builder.AppendLine($" Reserved 1: {T_Reserved1} (0x{T_Reserved1:X})"); builder.AppendLine($" Ticket ID: {T_TicketID} (0x{T_TicketID:X})"); builder.AppendLine($" Console ID: {T_ConsoleID} (0x{T_ConsoleID:X})"); builder.AppendLine($" Title ID {T_TitleID} (0x{T_TitleID:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(T_Reserved2).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(T_Reserved2 == null ? "[NULL]" : BitConverter.ToString(T_Reserved2).Replace('-', ' '))}"); builder.AppendLine($" Ticket title version: {T_TicketTitleVersion} (0x{T_TicketTitleVersion:X})"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(T_Reserved3).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 3: {(T_Reserved3 == null ? "[NULL]" : BitConverter.ToString(T_Reserved3).Replace('-', ' '))}"); builder.AppendLine($" License type: {T_LicenseType} (0x{T_LicenseType:X})"); builder.AppendLine($" Common keY index: {T_CommonKeyYIndex} (0x{T_CommonKeyYIndex:X})"); - builder.AppendLine($" Reserved 4: {BitConverter.ToString(T_Reserved4).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 4: {(T_Reserved4 == null ? "[NULL]" : BitConverter.ToString(T_Reserved4).Replace('-', ' '))}"); builder.AppendLine($" eShop Account ID?: {T_eShopAccountID} (0x{T_eShopAccountID:X})"); builder.AppendLine($" Reserved 5: {T_Reserved5} (0x{T_Reserved5:X})"); builder.AppendLine($" Audit: {T_Audit} (0x{T_Audit:X})"); - builder.AppendLine($" Reserved 6: {BitConverter.ToString(T_Reserved6).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 6: {(T_Reserved6 == null ? "[NULL]" : BitConverter.ToString(T_Reserved6).Replace('-', ' '))}"); builder.AppendLine($" Limits:"); for (int i = 0; i < T_Limits.Length; i++) { builder.AppendLine($" Limit {i}: {T_Limits[i]} (0x{T_Limits[i]:X})"); } builder.AppendLine($" Content index size: {T_ContentIndexSize} (0x{T_ContentIndexSize:X})"); - builder.AppendLine($" Content index: {BitConverter.ToString(T_ContentIndex).Replace('-', ' ')}"); + builder.AppendLine($" Content index: {(T_ContentIndex == null ? "[NULL]" : BitConverter.ToString(T_ContentIndex).Replace('-', ' '))}"); builder.AppendLine(); builder.AppendLine(" Ticket Certificate Chain Information:"); @@ -516,8 +616,8 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})"); builder.AppendLine($" Signature size: {certificate.SignatureSize} (0x{certificate.SignatureSize:X})"); builder.AppendLine($" Padding size: {certificate.PaddingSize} (0x{certificate.PaddingSize:X})"); - builder.AppendLine($" Signature: {BitConverter.ToString(certificate.Signature).Replace('-', ' ')}"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.Padding).Replace('-', ' ')}"); + builder.AppendLine($" Signature: {(certificate.Signature == null ? "[NULL]" : BitConverter.ToString(certificate.Signature).Replace('-', ' '))}"); + builder.AppendLine($" Padding: {(certificate.Padding == null ? "[NULL]" : BitConverter.ToString(certificate.Padding).Replace('-', ' '))}"); builder.AppendLine($" Issuer: {certificate.Issuer ?? "[NULL]"}"); builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})"); builder.AppendLine($" Name: {certificate.Name ?? "[NULL]"}"); @@ -526,13 +626,13 @@ namespace BinaryObjectScanner.Wrappers { case SabreTools.Models.N3DS.PublicKeyType.RSA_4096: case SabreTools.Models.N3DS.PublicKeyType.RSA_2048: - builder.AppendLine($" Modulus: {BitConverter.ToString(certificate.RSAModulus).Replace('-', ' ')}"); + builder.AppendLine($" Modulus: {(certificate.RSAModulus == null ? "[NULL]" : BitConverter.ToString(certificate.RSAModulus).Replace('-', ' '))}"); builder.AppendLine($" Public exponent: {certificate.RSAPublicExponent} (0x{certificate.RSAPublicExponent:X})"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.RSAPadding).Replace('-', ' ')}"); + builder.AppendLine($" Padding: {(certificate.RSAPadding == null ? "[NULL]" : BitConverter.ToString(certificate.RSAPadding).Replace('-', ' '))}"); break; case SabreTools.Models.N3DS.PublicKeyType.EllipticCurve: - builder.AppendLine($" Public key: {BitConverter.ToString(certificate.ECCPublicKey).Replace('-', ' ')}"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.ECCPadding).Replace('-', ' ')}"); + builder.AppendLine($" Public key: {(certificate.ECCPublicKey == null ? "[NULL]" : BitConverter.ToString(certificate.ECCPublicKey).Replace('-', ' '))}"); + builder.AppendLine($" Padding: {(certificate.ECCPadding == null ? "[NULL]" : BitConverter.ToString(certificate.ECCPadding).Replace('-', ' '))}"); break; } } @@ -551,8 +651,8 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Signature type: {TMD_SignatureType} (0x{TMD_SignatureType:X})"); builder.AppendLine($" Signature size: {TMD_SignatureSize} (0x{TMD_SignatureSize:X})"); builder.AppendLine($" Padding size: {TMD_PaddingSize} (0x{TMD_PaddingSize:X})"); - builder.AppendLine($" Signature: {BitConverter.ToString(TMD_Signature).Replace('-', ' ')}"); - builder.AppendLine($" Padding 1: {BitConverter.ToString(TMD_Padding1).Replace('-', ' ')}"); + builder.AppendLine($" Signature: {(TMD_Signature == null ? "[NULL]" : BitConverter.ToString(TMD_Signature).Replace('-', ' '))}"); + builder.AppendLine($" Padding 1: {(TMD_Padding1 == null ? "[NULL]" : BitConverter.ToString(TMD_Padding1).Replace('-', ' '))}"); builder.AppendLine($" Issuer: {TMD_Issuer ?? "[NULL]"}"); builder.AppendLine($" Version: {TMD_Version} (0x{TMD_Version:X})"); builder.AppendLine($" CaCrlVersion: {TMD_CaCrlVersion} (0x{TMD_CaCrlVersion:X})"); @@ -564,15 +664,15 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Group ID: {TMD_GroupID} (0x{TMD_GroupID:X})"); builder.AppendLine($" Save data size: {TMD_SaveDataSize} (0x{TMD_SaveDataSize:X})"); builder.AppendLine($" SRL private save data size: {TMD_SRLPrivateSaveDataSize} (0x{TMD_SRLPrivateSaveDataSize:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(TMD_Reserved2).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(TMD_Reserved2 == null ? "[NULL]" : BitConverter.ToString(TMD_Reserved2).Replace('-', ' '))}"); builder.AppendLine($" SRL flag: {TMD_SRLFlag} (0x{TMD_SRLFlag:X})"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(TMD_Reserved3).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 3: {(TMD_Reserved3 == null ? "[NULL]" : BitConverter.ToString(TMD_Reserved3).Replace('-', ' '))}"); builder.AppendLine($" Access rights: {TMD_AccessRights} (0x{TMD_AccessRights:X})"); builder.AppendLine($" Title version: {TMD_TitleVersion} (0x{TMD_TitleVersion:X})"); builder.AppendLine($" Content count: {TMD_ContentCount} (0x{TMD_ContentCount:X})"); builder.AppendLine($" Boot content: {TMD_BootContent} (0x{TMD_BootContent:X})"); - builder.AppendLine($" Padding 2: {BitConverter.ToString(TMD_Padding2).Replace('-', ' ')}"); - builder.AppendLine($" SHA-256 hash of the content info records: {BitConverter.ToString(TMD_SHA256HashContentInfoRecords).Replace('-', ' ')}"); + builder.AppendLine($" Padding 2: {(TMD_Padding2 == null ? "[NULL]" : BitConverter.ToString(TMD_Padding2).Replace('-', ' '))}"); + builder.AppendLine($" SHA-256 hash of the content info records: {(TMD_SHA256HashContentInfoRecords == null ? "[NULL]" : BitConverter.ToString(TMD_SHA256HashContentInfoRecords).Replace('-', ' '))}"); builder.AppendLine(); builder.AppendLine(" Ticket Content Info Records Information:"); @@ -589,7 +689,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Content Info Record {i}"); builder.AppendLine($" Content index offset: {contentInfoRecord.ContentIndexOffset} (0x{contentInfoRecord.ContentIndexOffset:X})"); builder.AppendLine($" Content command count: {contentInfoRecord.ContentCommandCount} (0x{contentInfoRecord.ContentCommandCount:X})"); - builder.AppendLine($" SHA-256 hash of the next {contentInfoRecord.ContentCommandCount} records not hashed: {BitConverter.ToString(contentInfoRecord.UnhashedContentRecordsSHA256Hash).Replace('-', ' ')}"); + builder.AppendLine($" SHA-256 hash of the next {contentInfoRecord.ContentCommandCount} records not hashed: {(contentInfoRecord.UnhashedContentRecordsSHA256Hash == null ? "[NULL]" : BitConverter.ToString(contentInfoRecord.UnhashedContentRecordsSHA256Hash).Replace('-', ' '))}"); } } builder.AppendLine(); @@ -610,7 +710,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Content index: {contentChunkRecord.ContentIndex} (0x{contentChunkRecord.ContentIndex:X})"); builder.AppendLine($" Content type: {contentChunkRecord.ContentType} (0x{contentChunkRecord.ContentType:X})"); builder.AppendLine($" Content size: {contentChunkRecord.ContentSize} (0x{contentChunkRecord.ContentSize:X})"); - builder.AppendLine($" SHA-256 hash: {BitConverter.ToString(contentChunkRecord.SHA256Hash).Replace('-', ' ')}"); + builder.AppendLine($" SHA-256 hash: {(contentChunkRecord.SHA256Hash == null ? "[NULL]" : BitConverter.ToString(contentChunkRecord.SHA256Hash).Replace('-', ' '))}"); } } builder.AppendLine(); @@ -638,8 +738,8 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})"); builder.AppendLine($" Signature size: {certificate.SignatureSize} (0x{certificate.SignatureSize:X})"); builder.AppendLine($" Padding size: {certificate.PaddingSize} (0x{certificate.PaddingSize:X})"); - builder.AppendLine($" Signature: {BitConverter.ToString(certificate.Signature).Replace('-', ' ')}"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.Padding).Replace('-', ' ')}"); + builder.AppendLine($" Signature: {(certificate.Signature == null ? "[NULL]" : BitConverter.ToString(certificate.Signature).Replace('-', ' '))}"); + builder.AppendLine($" Padding: {(certificate.Padding == null ? "[NULL]" : BitConverter.ToString(certificate.Padding).Replace('-', ' '))}"); builder.AppendLine($" Issuer: {certificate.Issuer ?? "[NULL]"}"); builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})"); builder.AppendLine($" Name: {certificate.Name ?? "[NULL]"}"); @@ -648,13 +748,13 @@ namespace BinaryObjectScanner.Wrappers { case SabreTools.Models.N3DS.PublicKeyType.RSA_4096: case SabreTools.Models.N3DS.PublicKeyType.RSA_2048: - builder.AppendLine($" Modulus: {BitConverter.ToString(certificate.RSAModulus).Replace('-', ' ')}"); + builder.AppendLine($" Modulus: {(certificate.RSAModulus == null ? "[NULL]" : BitConverter.ToString(certificate.RSAModulus).Replace('-', ' '))}"); builder.AppendLine($" Public exponent: {certificate.RSAPublicExponent} (0x{certificate.RSAPublicExponent:X})"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.RSAPadding).Replace('-', ' ')}"); + builder.AppendLine($" Padding: {(certificate.RSAPadding == null ? "[NULL]" : BitConverter.ToString(certificate.RSAPadding).Replace('-', ' '))}"); break; case SabreTools.Models.N3DS.PublicKeyType.EllipticCurve: - builder.AppendLine($" Public key: {BitConverter.ToString(certificate.ECCPublicKey).Replace('-', ' ')}"); - builder.AppendLine($" Padding: {BitConverter.ToString(certificate.ECCPadding).Replace('-', ' ')}"); + builder.AppendLine($" Public key: {(certificate.ECCPublicKey == null ? "[NULL]" : BitConverter.ToString(certificate.ECCPublicKey).Replace('-', ' '))}"); + builder.AppendLine($" Padding: {(certificate.ECCPadding == null ? "[NULL]" : BitConverter.ToString(certificate.ECCPadding).Replace('-', ' '))}"); break; } } @@ -690,20 +790,20 @@ namespace BinaryObjectScanner.Wrappers } else { - builder.AppendLine($" RSA-2048 SHA-256 signature: {BitConverter.ToString(partitionHeader.RSA2048Signature).Replace('-', ' ')}"); + builder.AppendLine($" RSA-2048 SHA-256 signature: {(partitionHeader.RSA2048Signature == null ? "[NULL]" : BitConverter.ToString(partitionHeader.RSA2048Signature).Replace('-', ' '))}"); builder.AppendLine($" Magic ID: {partitionHeader.MagicID} (0x{partitionHeader.MagicID:X})"); builder.AppendLine($" Content size in media units: {partitionHeader.ContentSizeInMediaUnits} (0x{partitionHeader.ContentSizeInMediaUnits:X})"); builder.AppendLine($" Partition ID: {partitionHeader.PartitionId} (0x{partitionHeader.PartitionId:X})"); builder.AppendLine($" Maker code: {partitionHeader.MakerCode} (0x{partitionHeader.MakerCode:X})"); builder.AppendLine($" Version: {partitionHeader.Version} (0x{partitionHeader.Version:X})"); builder.AppendLine($" Verification hash: {partitionHeader.VerificationHash} (0x{partitionHeader.VerificationHash:X})"); - builder.AppendLine($" Program ID: {BitConverter.ToString(partitionHeader.ProgramId).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(partitionHeader.Reserved1).Replace('-', ' ')}"); - builder.AppendLine($" Logo region SHA-256 hash: {BitConverter.ToString(partitionHeader.LogoRegionHash).Replace('-', ' ')}"); + builder.AppendLine($" Program ID: {(partitionHeader.ProgramId == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ProgramId).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 1: {(partitionHeader.Reserved1 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved1).Replace('-', ' '))}"); + builder.AppendLine($" Logo region SHA-256 hash: {(partitionHeader.LogoRegionHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.LogoRegionHash).Replace('-', ' '))}"); builder.AppendLine($" Product code: {partitionHeader.ProductCode} (0x{partitionHeader.ProductCode:X})"); - builder.AppendLine($" Extended header SHA-256 hash: {BitConverter.ToString(partitionHeader.ExtendedHeaderHash).Replace('-', ' ')}"); + builder.AppendLine($" Extended header SHA-256 hash: {(partitionHeader.ExtendedHeaderHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ExtendedHeaderHash).Replace('-', ' '))}"); builder.AppendLine($" Extended header size in bytes: {partitionHeader.ExtendedHeaderSizeInBytes} (0x{partitionHeader.ExtendedHeaderSizeInBytes:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(partitionHeader.Reserved2).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(partitionHeader.Reserved2 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved2).Replace('-', ' '))}"); builder.AppendLine(" Flags:"); builder.AppendLine($" Reserved 0: {partitionHeader.Flags.Reserved0} (0x{partitionHeader.Flags.Reserved0:X})"); builder.AppendLine($" Reserved 1: {partitionHeader.Flags.Reserved1} (0x{partitionHeader.Flags.Reserved1:X})"); @@ -720,13 +820,13 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" ExeFS offset, in media units: {partitionHeader.ExeFSOffsetInMediaUnits} (0x{partitionHeader.ExeFSOffsetInMediaUnits:X})"); builder.AppendLine($" ExeFS size, in media units: {partitionHeader.ExeFSSizeInMediaUnits} (0x{partitionHeader.ExeFSSizeInMediaUnits:X})"); builder.AppendLine($" ExeFS hash region size, in media units: {partitionHeader.ExeFSHashRegionSizeInMediaUnits} (0x{partitionHeader.ExeFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(partitionHeader.Reserved3).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 3: {(partitionHeader.Reserved3 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved3).Replace('-', ' '))}"); builder.AppendLine($" RomFS offset, in media units: {partitionHeader.RomFSOffsetInMediaUnits} (0x{partitionHeader.RomFSOffsetInMediaUnits:X})"); builder.AppendLine($" RomFS size, in media units: {partitionHeader.RomFSSizeInMediaUnits} (0x{partitionHeader.RomFSSizeInMediaUnits:X})"); builder.AppendLine($" RomFS hash region size, in media units: {partitionHeader.RomFSHashRegionSizeInMediaUnits} (0x{partitionHeader.RomFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 4: {BitConverter.ToString(partitionHeader.Reserved4).Replace('-', ' ')}"); - builder.AppendLine($" ExeFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.ExeFSSuperblockHash).Replace('-', ' ')}"); - builder.AppendLine($" RomFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.RomFSSuperblockHash).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 4: {(partitionHeader.Reserved4 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved4).Replace('-', ' '))}"); + builder.AppendLine($" ExeFS superblock SHA-256 hash: {(partitionHeader.ExeFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ExeFSSuperblockHash).Replace('-', ' '))}"); + builder.AppendLine($" RomFS superblock SHA-256 hash: {(partitionHeader.RomFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.RomFSSuperblockHash).Replace('-', ' '))}"); } } } @@ -747,11 +847,11 @@ namespace BinaryObjectScanner.Wrappers } else { - builder.AppendLine(value: $" Title ID dependency list: {BitConverter.ToString(MD_TitleIDDependencyList).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(MD_Reserved1).Replace('-', ' ')}"); + builder.AppendLine(value: $" Title ID dependency list: {(MD_TitleIDDependencyList == null ? "[NULL]" : BitConverter.ToString(MD_TitleIDDependencyList).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 1: {(MD_Reserved1 == null ? "[NULL]" : BitConverter.ToString(MD_Reserved1).Replace('-', ' '))}"); builder.AppendLine($" Core version: {MD_CoreVersion} (0x{MD_CoreVersion:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(MD_Reserved2).Replace('-', ' ')}"); - builder.AppendLine($" Icon data: {BitConverter.ToString(MD_IconData).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(MD_Reserved2 == null ? "[NULL]" : BitConverter.ToString(MD_Reserved2).Replace('-', ' '))}"); + builder.AppendLine($" Icon data: {(MD_IconData == null ? "[NULL]" : BitConverter.ToString(MD_IconData).Replace('-', ' '))}"); } builder.AppendLine(); } diff --git a/BinaryObjectScanner.Wrappers/GCF.cs b/BinaryObjectScanner.Wrappers/GCF.cs index 0f0cacf1..908e0528 100644 --- a/BinaryObjectScanner.Wrappers/GCF.cs +++ b/BinaryObjectScanner.Wrappers/GCF.cs @@ -385,15 +385,19 @@ namespace BinaryObjectScanner.Wrappers Size = directoryEntry.ItemSize, Encrypted = directoryEntry.DirectoryFlags.HasFlag(SabreTools.Models.GCF.HL_GCF_FLAG.HL_GCF_FLAG_ENCRYPTED), }; - var pathParts = new List { directoryEntry.Name }; + var pathParts = new List { directoryEntry.Name ?? string.Empty }; +#if NET48 var blockEntries = new List(); +#else + var blockEntries = new List(); +#endif // Traverse the parent tree uint index = directoryEntry.ParentIndex; while (index != 0xFFFFFFFF) { var parentDirectoryEntry = DirectoryEntries[index]; - pathParts.Add(parentDirectoryEntry.Name); + pathParts.Add(parentDirectoryEntry.Name ?? string.Empty); index = parentDirectoryEntry.ParentIndex; } @@ -493,7 +497,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the GCF /// Offset within the array to parse /// An GCF wrapper on success, null on failure +#if NET48 public static GCF Create(byte[] data, int offset) +#else + public static GCF? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -513,7 +521,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the GCF /// An GCF wrapper on success, null on failure +#if NET48 public static GCF Create(Stream data) +#else + public static GCF? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -1113,10 +1125,16 @@ namespace BinaryObjectScanner.Wrappers return false; // Create the full output path - filename = Path.Combine(outputDirectory, filename); + filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try @@ -1130,7 +1148,14 @@ namespace BinaryObjectScanner.Wrappers { int readSize = (int)Math.Min(DBH_BlockSize, fileSize); +#if NET48 byte[] data = ReadFromDataSource((int)dataBlockOffsets[i], readSize); +#else + byte[]? data = ReadFromDataSource((int)dataBlockOffsets[i], readSize); +#endif + if (data == null) + return false; + fs.Write(data, 0, data.Length); } } @@ -1155,7 +1180,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Full item path /// +#if NET48 public string Path; +#else + public string? Path; +#endif /// /// File size @@ -1170,7 +1199,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Array of block entries /// +#if NET48 public SabreTools.Models.GCF.BlockEntry[] BlockEntries; +#else + public SabreTools.Models.GCF.BlockEntry?[]? BlockEntries; +#endif } #endregion diff --git a/BinaryObjectScanner.Wrappers/InstallShieldCabinet.cs b/BinaryObjectScanner.Wrappers/InstallShieldCabinet.cs index 5affb6d3..5e47614b 100644 --- a/BinaryObjectScanner.Wrappers/InstallShieldCabinet.cs +++ b/BinaryObjectScanner.Wrappers/InstallShieldCabinet.cs @@ -19,7 +19,11 @@ namespace BinaryObjectScanner.Wrappers #region Common Header /// +#if NET48 public string Signature => _model.CommonHeader.Signature; +#else + public string? Signature => _model.CommonHeader.Signature; +#endif /// public uint Version => _model.CommonHeader.Version; @@ -93,7 +97,11 @@ namespace BinaryObjectScanner.Wrappers public uint StringsOffset => _model.Descriptor.StringsOffset; /// +#if NET48 public byte[] Reserved0 => _model.Descriptor.Reserved0; +#else + public byte[]? Reserved0 => _model.Descriptor.Reserved0; +#endif /// public uint ComponentListOffset => _model.Descriptor.ComponentListOffset; @@ -102,7 +110,11 @@ namespace BinaryObjectScanner.Wrappers public uint FileTableOffset => _model.Descriptor.FileTableOffset; /// +#if NET48 public byte[] Reserved1 => _model.Descriptor.Reserved1; +#else + public byte[]? Reserved1 => _model.Descriptor.Reserved1; +#endif /// public uint FileTableSize => _model.Descriptor.FileTableSize; @@ -114,13 +126,25 @@ namespace BinaryObjectScanner.Wrappers public ushort DirectoryCount => _model.Descriptor.DirectoryCount; /// +#if NET48 public byte[] Reserved2 => _model.Descriptor.Reserved2; +#else + public byte[]? Reserved2 => _model.Descriptor.Reserved2; +#endif /// +#if NET48 public byte[] Reserved3 => _model.Descriptor.Reserved3; +#else + public byte[]? Reserved3 => _model.Descriptor.Reserved3; +#endif /// +#if NET48 public byte[] Reserved4 => _model.Descriptor.Reserved4; +#else + public byte[]? Reserved4 => _model.Descriptor.Reserved4; +#endif /// public uint FileCount => _model.Descriptor.FileCount; @@ -135,16 +159,32 @@ namespace BinaryObjectScanner.Wrappers public uint ComponentTableOffset => _model.Descriptor.ComponentTableOffset; /// +#if NET48 public byte[] Reserved5 => _model.Descriptor.Reserved5; +#else + public byte[]? Reserved5 => _model.Descriptor.Reserved5; +#endif /// +#if NET48 public byte[] Reserved6 => _model.Descriptor.Reserved6; +#else + public byte[]? Reserved6 => _model.Descriptor.Reserved6; +#endif /// +#if NET48 public uint[] D_FileGroupOffsets => _model.Descriptor.FileGroupOffsets; +#else + public uint[]? D_FileGroupOffsets => _model.Descriptor.FileGroupOffsets; +#endif /// +#if NET48 public uint[] D_ComponentOffsets => _model.Descriptor.ComponentOffsets; +#else + public uint[]? D_ComponentOffsets => _model.Descriptor.ComponentOffsets; +#endif /// public uint SetupTypesOffset => _model.Descriptor.SetupTypesOffset; @@ -153,24 +193,40 @@ namespace BinaryObjectScanner.Wrappers public uint SetupTableOffset => _model.Descriptor.SetupTableOffset; /// +#if NET48 public byte[] Reserved7 => _model.Descriptor.Reserved7; +#else + public byte[]? Reserved7 => _model.Descriptor.Reserved7; +#endif /// +#if NET48 public byte[] Reserved8 => _model.Descriptor.Reserved8; +#else + public byte[]? Reserved8 => _model.Descriptor.Reserved8; +#endif #endregion #region File Descriptor Offsets /// +#if NET48 public uint[] FileDescriptorOffsets => _model.FileDescriptorOffsets; +#else + public uint[]? FileDescriptorOffsets => _model.FileDescriptorOffsets; +#endif #endregion #region Directory Descriptors /// +#if NET48 public string[] DirectoryNames => _model.DirectoryNames; +#else + public string[]? DirectoryNames => _model.DirectoryNames; +#endif #endregion @@ -288,7 +344,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the cabinet /// Offset within the array to parse /// A cabinet wrapper on success, null on failure +#if NET48 public static InstallShieldCabinet Create(byte[] data, int offset) +#else + public static InstallShieldCabinet? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -308,7 +368,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the cabinet /// A cabinet wrapper on success, null on failure +#if NET48 public static InstallShieldCabinet Create(Stream data) +#else + public static InstallShieldCabinet? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -430,22 +494,22 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(" Descriptor Information:"); builder.AppendLine(" -------------------------"); builder.AppendLine($" Strings offset: {StringsOffset} (0x{StringsOffset:X})"); - builder.AppendLine($" Reserved 0: {BitConverter.ToString(Reserved0).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 0: {(Reserved0 == null ? "[NULL]" : BitConverter.ToString(Reserved0).Replace('-', ' '))}"); builder.AppendLine($" Component list offset: {ComponentListOffset} (0x{ComponentListOffset:X})"); builder.AppendLine($" File table offset: {FileTableOffset} (0x{FileTableOffset:X})"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(Reserved1).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 1: {(Reserved1 == null ? "[NULL]" : BitConverter.ToString(Reserved1).Replace('-', ' '))}"); builder.AppendLine($" File table size: {FileTableSize} (0x{FileTableSize:X})"); builder.AppendLine($" File table size 2: {FileTableSize2} (0x{FileTableSize2:X})"); builder.AppendLine($" Directory count: {DirectoryCount} (0x{DirectoryCount:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(Reserved2).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(Reserved3).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 4: {BitConverter.ToString(Reserved4).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(Reserved2 == null ? "[NULL]" : BitConverter.ToString(Reserved2).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 3: {(Reserved3 == null ? "[NULL]" : BitConverter.ToString(Reserved3).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 4: {(Reserved4 == null ? "[NULL]" : BitConverter.ToString(Reserved4).Replace('-', ' '))}"); builder.AppendLine($" File count: {FileCount} (0x{FileCount:X})"); builder.AppendLine($" File table offset 2: {FileTableOffset2} (0x{FileTableOffset2:X})"); builder.AppendLine($" Component table info count: {ComponentTableInfoCount} (0x{ComponentTableInfoCount:X})"); builder.AppendLine($" Component table offset: {ComponentTableOffset} (0x{ComponentTableOffset:X})"); - builder.AppendLine($" Reserved 5: {BitConverter.ToString(Reserved5).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 6: {BitConverter.ToString(Reserved6).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 5: {(Reserved5 == null ? "[NULL]" : BitConverter.ToString(Reserved5).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 6: {(Reserved6 == null ? "[NULL]" : BitConverter.ToString(Reserved6).Replace('-', ' '))}"); builder.AppendLine(); builder.AppendLine($" File group offsets:"); @@ -480,8 +544,8 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Setup types offset: {SetupTypesOffset} (0x{SetupTypesOffset:X})"); builder.AppendLine($" Setup table offset: {SetupTableOffset} (0x{SetupTableOffset:X})"); - builder.AppendLine($" Reserved 7: {BitConverter.ToString(Reserved7).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 8: {BitConverter.ToString(Reserved8).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 7: {(Reserved7 == null ? "[NULL]" : BitConverter.ToString(Reserved7).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 8: {(Reserved8 == null ? "[NULL]" : BitConverter.ToString(Reserved8).Replace('-', ' '))}"); builder.AppendLine(); } @@ -554,7 +618,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Expanded size: {fileDescriptor.ExpandedSize} (0x{fileDescriptor.ExpandedSize:X})"); builder.AppendLine($" Compressed size: {fileDescriptor.CompressedSize} (0x{fileDescriptor.CompressedSize:X})"); builder.AppendLine($" Data offset: {fileDescriptor.DataOffset} (0x{fileDescriptor.DataOffset:X})"); - builder.AppendLine($" MD5: {BitConverter.ToString(fileDescriptor.MD5 ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" MD5: {(fileDescriptor.MD5 == null ? "[NULL]" : BitConverter.ToString(fileDescriptor.MD5).Replace('-', ' '))}"); builder.AppendLine($" Volume: {fileDescriptor.Volume} (0x{fileDescriptor.Volume:X})"); builder.AppendLine($" Link previous: {fileDescriptor.LinkPrevious} (0x{fileDescriptor.LinkPrevious:X})"); builder.AppendLine($" Link next: {fileDescriptor.LinkNext} (0x{fileDescriptor.LinkNext:X})"); @@ -627,10 +691,10 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Name offset: {fileGroup.NameOffset} (0x{fileGroup.NameOffset:X})"); builder.AppendLine($" Name: {fileGroup.Name ?? "[NULL]"}"); builder.AppendLine($" Expanded size: {fileGroup.ExpandedSize} (0x{fileGroup.ExpandedSize:X})"); - builder.AppendLine($" Reserved 0: {BitConverter.ToString(fileGroup.Reserved0).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 0: {(fileGroup.Reserved0 == null ? "[NULL]" : BitConverter.ToString(fileGroup.Reserved0).Replace('-', ' '))}"); builder.AppendLine($" Compressed size: {fileGroup.CompressedSize} (0x{fileGroup.CompressedSize:X})"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(fileGroup.Reserved1).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(fileGroup.Reserved2).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 1: {(fileGroup.Reserved1 == null ? "[NULL]" : BitConverter.ToString(fileGroup.Reserved1).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 2: {(fileGroup.Reserved2 == null ? "[NULL]" : BitConverter.ToString(fileGroup.Reserved2).Replace('-', ' '))}"); builder.AppendLine($" Attribute 1: {fileGroup.Attribute1} (0x{fileGroup.Attribute1:X})"); builder.AppendLine($" Attribute 2: {fileGroup.Attribute2} (0x{fileGroup.Attribute2:X})"); builder.AppendLine($" First file: {fileGroup.FirstFile} (0x{fileGroup.FirstFile:X})"); @@ -643,11 +707,11 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Misc. offset: {fileGroup.MiscOffset} (0x{fileGroup.MiscOffset:X})"); builder.AppendLine($" Var 2 offset: {fileGroup.Var2Offset} (0x{fileGroup.Var2Offset:X})"); builder.AppendLine($" Target directory offset: {fileGroup.TargetDirectoryOffset} (0x{fileGroup.TargetDirectoryOffset:X})"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(fileGroup.Reserved3).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 4: {BitConverter.ToString(fileGroup.Reserved4).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 5: {BitConverter.ToString(fileGroup.Reserved5).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 6: {BitConverter.ToString(fileGroup.Reserved6).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 7: {BitConverter.ToString(fileGroup.Reserved7).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 3: {(fileGroup.Reserved3 == null ? "[NULL]" : BitConverter.ToString(fileGroup.Reserved3).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 4: {(fileGroup.Reserved4 == null ? "[NULL]" : BitConverter.ToString(fileGroup.Reserved4).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 5: {(fileGroup.Reserved5 == null ? "[NULL]" : BitConverter.ToString(fileGroup.Reserved5).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 6: {(fileGroup.Reserved6 == null ? "[NULL]" : BitConverter.ToString(fileGroup.Reserved6).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 7: {(fileGroup.Reserved7 == null ? "[NULL]" : BitConverter.ToString(fileGroup.Reserved7).Replace('-', ' '))}"); } builder.AppendLine(); } @@ -719,7 +783,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Descriptor offset: {component.DescriptorOffset} (0x{component.DescriptorOffset:X})"); builder.AppendLine($" Display name offset: {component.DisplayNameOffset} (0x{component.DisplayNameOffset:X})"); builder.AppendLine($" Display name: {component.DisplayName ?? "[NULL]"}"); - builder.AppendLine($" Reserved 0: {BitConverter.ToString(component.Reserved0).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 0: {(component.Reserved0 == null ? "[NULL]" : BitConverter.ToString(component.Reserved0).Replace('-', ' '))}"); builder.AppendLine($" Reserved offset 0: {component.ReservedOffset0} (0x{component.ReservedOffset0:X})"); builder.AppendLine($" Reserved offset 1: {component.ReservedOffset1} (0x{component.ReservedOffset1:X})"); builder.AppendLine($" Component index: {component.ComponentIndex} (0x{component.ComponentIndex:X})"); @@ -728,11 +792,11 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Reserved offset 2: {component.ReservedOffset2} (0x{component.ReservedOffset2:X})"); builder.AppendLine($" Reserved offset 3: {component.ReservedOffset3} (0x{component.ReservedOffset3:X})"); builder.AppendLine($" Reserved offset 4: {component.ReservedOffset4} (0x{component.ReservedOffset4:X})"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(component.Reserved1).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 1: {(component.Reserved1 == null ? "[NULL]" : BitConverter.ToString(component.Reserved1).Replace('-', ' '))}"); builder.AppendLine($" CLSID offset: {component.CLSIDOffset} (0x{component.CLSIDOffset:X})"); builder.AppendLine($" CLSID: {component.CLSID}"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(component.Reserved2).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(component.Reserved3).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(component.Reserved2 == null ? "[NULL]" : BitConverter.ToString(component.Reserved2).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 3: {(component.Reserved3 == null ? "[NULL]" : BitConverter.ToString(component.Reserved3).Replace('-', ' '))}"); builder.AppendLine($" Depends count: {component.DependsCount} (0x{component.DependsCount:X})"); builder.AppendLine($" Depends offset: {component.DependsOffset} (0x{component.DependsOffset:X})"); builder.AppendLine($" File group count: {component.FileGroupCount} (0x{component.FileGroupCount:X})"); diff --git a/BinaryObjectScanner.Wrappers/LinearExecutable.cs b/BinaryObjectScanner.Wrappers/LinearExecutable.cs index 12fbe4dd..bf1b031a 100644 --- a/BinaryObjectScanner.Wrappers/LinearExecutable.cs +++ b/BinaryObjectScanner.Wrappers/LinearExecutable.cs @@ -20,7 +20,11 @@ namespace BinaryObjectScanner.Wrappers #region Standard Fields /// +#if NET48 public string Stub_Magic => _model.Stub.Header.Magic; +#else + public string? Stub_Magic => _model.Stub.Header.Magic; +#endif /// public ushort Stub_LastPageBytes => _model.Stub.Header.LastPageBytes; @@ -66,7 +70,11 @@ namespace BinaryObjectScanner.Wrappers #region PE Extensions /// +#if NET48 public ushort[] Stub_Reserved1 => _model.Stub.Header.Reserved1; +#else + public ushort[]? Stub_Reserved1 => _model.Stub.Header.Reserved1; +#endif /// public ushort Stub_OEMIdentifier => _model.Stub.Header.OEMIdentifier; @@ -75,7 +83,11 @@ namespace BinaryObjectScanner.Wrappers public ushort Stub_OEMInformation => _model.Stub.Header.OEMInformation; /// +#if NET48 public ushort[] Stub_Reserved2 => _model.Stub.Header.Reserved2; +#else + public ushort[]? Stub_Reserved2 => _model.Stub.Header.Reserved2; +#endif /// public uint Stub_NewExeHeaderAddr => _model.Stub.Header.NewExeHeaderAddr; @@ -87,7 +99,11 @@ namespace BinaryObjectScanner.Wrappers #region Information Block /// +#if NET48 public string Signature => _model.InformationBlock.Signature; +#else + public string? Signature => _model.InformationBlock.Signature; +#endif /// public SabreTools.Models.LinearExecutable.ByteOrder ByteOrder => _model.InformationBlock.ByteOrder; @@ -324,13 +340,21 @@ namespace BinaryObjectScanner.Wrappers #region Debug Information /// +#if NET48 public string DI_Signature => _model.DebugInformation?.Signature; +#else + public string? DI_Signature => _model.DebugInformation?.Signature; +#endif /// public SabreTools.Models.LinearExecutable.DebugFormatType? DI_FormatType => _model.DebugInformation?.FormatType; /// +#if NET48 public byte[] DebuggerData => _model.DebugInformation?.DebuggerData; +#else + public byte[]? DebuggerData => _model.DebugInformation?.DebuggerData; +#endif #endregion @@ -370,7 +394,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the executable /// Offset within the array to parse /// An LE/LX executable wrapper on success, null on failure +#if NET48 public static LinearExecutable Create(byte[] data, int offset) +#else + public static LinearExecutable? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -390,7 +418,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the executable /// An LE/LX executable wrapper on success, null on failure +#if NET48 public static LinearExecutable Create(Stream data) +#else + public static LinearExecutable? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -484,10 +516,10 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" MS-DOS Stub Extended Header Information:"); builder.AppendLine(" -------------------------"); - builder.AppendLine($" Reserved words: {string.Join(", ", Stub_Reserved1)}"); + builder.AppendLine($" Reserved words: {(Stub_Reserved1 == null ? "[NULL]" : string.Join(", ", Stub_Reserved1))}"); builder.AppendLine($" OEM identifier: {Stub_OEMIdentifier} (0x{Stub_OEMIdentifier:X})"); builder.AppendLine($" OEM information: {Stub_OEMInformation} (0x{Stub_OEMInformation:X})"); - builder.AppendLine($" Reserved words: {string.Join(", ", Stub_Reserved2)}"); + builder.AppendLine($" Reserved words: {(Stub_Reserved2 == null ? "[NULL]" : string.Join(", ", Stub_Reserved2))}"); builder.AppendLine($" New EXE header address: {Stub_NewExeHeaderAddr} (0x{Stub_NewExeHeaderAddr:X})"); builder.AppendLine(); } @@ -1097,7 +1129,11 @@ namespace BinaryObjectScanner.Wrappers /// How many bytes to read, -1 means read until end /// Byte array representing the range, null on error [Obsolete] +#if NET48 public byte[] ReadArbitraryRange(int rangeStart = -1, int length = -1) +#else + public byte[]? ReadArbitraryRange(int rangeStart = -1, int length = -1) +#endif { // If we have an unset range start, read from the start of the source if (rangeStart == -1) diff --git a/BinaryObjectScanner.Wrappers/MSDOS.cs b/BinaryObjectScanner.Wrappers/MSDOS.cs index cdff2700..1163f38d 100644 --- a/BinaryObjectScanner.Wrappers/MSDOS.cs +++ b/BinaryObjectScanner.Wrappers/MSDOS.cs @@ -17,7 +17,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Magic => _model.Header.Magic; +#else + public string? Magic => _model.Header.Magic; +#endif /// public ushort LastPageBytes => _model.Header.LastPageBytes; @@ -63,7 +67,11 @@ namespace BinaryObjectScanner.Wrappers #region PE Extensions /// +#if NET48 public ushort[] Reserved1 => _model.Header.Reserved1; +#else + public ushort[]? Reserved1 => _model.Header.Reserved1; +#endif /// public ushort OEMIdentifier => _model.Header.OEMIdentifier; @@ -72,7 +80,11 @@ namespace BinaryObjectScanner.Wrappers public ushort OEMInformation => _model.Header.OEMInformation; /// +#if NET48 public ushort[] Reserved2 => _model.Header.Reserved2; +#else + public ushort[]? Reserved2 => _model.Header.Reserved2; +#endif /// public uint NewExeHeaderAddr => _model.Header.NewExeHeaderAddr; @@ -120,7 +132,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the executable /// Offset within the array to parse /// An MS-DOS executable wrapper on success, null on failure +#if NET48 public static MSDOS Create(byte[] data, int offset) +#else + public static MSDOS? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -140,7 +156,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the executable /// An MS-DOS executable wrapper on success, null on failure +#if NET48 public static MSDOS Create(Stream data) +#else + public static MSDOS? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) diff --git a/BinaryObjectScanner.Wrappers/MicrosoftCabinet.cs b/BinaryObjectScanner.Wrappers/MicrosoftCabinet.cs index 911b0e98..56f62f9d 100644 --- a/BinaryObjectScanner.Wrappers/MicrosoftCabinet.cs +++ b/BinaryObjectScanner.Wrappers/MicrosoftCabinet.cs @@ -19,7 +19,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Signature => _model.Header.Signature; +#else + public string? Signature => _model.Header.Signature; +#endif /// public uint Reserved1 => _model.Header.Reserved1; @@ -67,19 +71,39 @@ namespace BinaryObjectScanner.Wrappers public byte DataReservedSize => _model.Header.DataReservedSize; /// +#if NET48 public byte[] ReservedData => _model.Header.ReservedData; +#else + public byte[]? ReservedData => _model.Header.ReservedData; +#endif /// +#if NET48 public string CabinetPrev => _model.Header.CabinetPrev; +#else + public string? CabinetPrev => _model.Header.CabinetPrev; +#endif /// +#if NET48 public string DiskPrev => _model.Header.DiskPrev; +#else + public string? DiskPrev => _model.Header.DiskPrev; +#endif /// +#if NET48 public string CabinetNext => _model.Header.CabinetNext; +#else + public string? CabinetNext => _model.Header.CabinetNext; +#endif /// +#if NET48 public string DiskNext => _model.Header.DiskNext; +#else + public string? DiskNext => _model.Header.DiskNext; +#endif #endregion @@ -130,12 +154,16 @@ namespace BinaryObjectScanner.Wrappers { // All logic is handled by the base class }/// - /// Create a Microsoft Cabinet from a byte array and offset - /// - /// Byte array representing the cabinet - /// Offset within the array to parse - /// A cabinet wrapper on success, null on failure + /// Create a Microsoft Cabinet from a byte array and offset + /// + /// Byte array representing the cabinet + /// Offset within the array to parse + /// A cabinet wrapper on success, null on failure +#if NET48 public static MicrosoftCabinet Create(byte[] data, int offset) +#else + public static MicrosoftCabinet? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -155,7 +183,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the cabinet /// A cabinet wrapper on success, null on failure +#if NET48 public static MicrosoftCabinet Create(Stream data) +#else + public static MicrosoftCabinet? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -223,7 +255,11 @@ namespace BinaryObjectScanner.Wrappers /// Folder index to check /// Byte array representing the data, null on error /// All but uncompressed are unimplemented +#if NET48 public byte[] GetUncompressedData(int folderIndex) +#else + public byte[]? GetUncompressedData(int folderIndex) +#endif { // If we have an invalid folder index if (folderIndex < 0 || folderIndex >= Folders.Length) @@ -273,7 +309,8 @@ namespace BinaryObjectScanner.Wrappers return null; } - data.AddRange(decompressed ?? new byte[0]); + if (decompressed != null) + data.AddRange(decompressed); } return data.ToArray(); @@ -329,7 +366,7 @@ namespace BinaryObjectScanner.Wrappers return false; // Create the output filename - string fileName = Path.Combine(outputDirectory, file.Name); + string fileName = Path.Combine(outputDirectory, file.Name ?? $"file{index}"); // Get the file data, if possible byte[] fileData = GetFileData(index); @@ -390,7 +427,11 @@ namespace BinaryObjectScanner.Wrappers /// /// File index to check /// Byte array representing the data, null on error +#if NET48 public byte[] GetFileData(int fileIndex) +#else + public byte[]? GetFileData(int fileIndex) +#endif { // If we have an invalid file index if (fileIndex < 0 || fileIndex >= Files.Length) diff --git a/BinaryObjectScanner.Wrappers/N3DS.cs b/BinaryObjectScanner.Wrappers/N3DS.cs index a0135f53..3aa70518 100644 --- a/BinaryObjectScanner.Wrappers/N3DS.cs +++ b/BinaryObjectScanner.Wrappers/N3DS.cs @@ -20,22 +20,38 @@ namespace BinaryObjectScanner.Wrappers #region Common to all NCSD files /// +#if NET48 public byte[] RSA2048Signature => _model.Header.RSA2048Signature; +#else + public byte[]? RSA2048Signature => _model.Header.RSA2048Signature; +#endif /// +#if NET48 public string MagicNumber => _model.Header.MagicNumber; +#else + public string? MagicNumber => _model.Header.MagicNumber; +#endif /// public uint ImageSizeInMediaUnits => _model.Header.ImageSizeInMediaUnits; /// +#if NET48 public byte[] MediaId => _model.Header.MediaId; +#else + public byte[]? MediaId => _model.Header.MediaId; +#endif /// public SabreTools.Models.N3DS.FilesystemType PartitionsFSType => _model.Header.PartitionsFSType; /// +#if NET48 public byte[] PartitionsCryptType => _model.Header.PartitionsCryptType; +#else + public byte[]? PartitionsCryptType => _model.Header.PartitionsCryptType; +#endif /// #if NET48 @@ -49,7 +65,11 @@ namespace BinaryObjectScanner.Wrappers #region CTR Cart Image (CCI) Specific /// +#if NET48 public byte[] ExheaderHash => _model.Header.ExheaderHash; +#else + public byte[]? ExheaderHash => _model.Header.ExheaderHash; +#endif /// public uint AdditionalHeaderSize => _model.Header.AdditionalHeaderSize; @@ -58,16 +78,32 @@ namespace BinaryObjectScanner.Wrappers public uint SectorZeroOffset => _model.Header.SectorZeroOffset; /// +#if NET48 public byte[] PartitionFlags => _model.Header.PartitionFlags; +#else + public byte[]? PartitionFlags => _model.Header.PartitionFlags; +#endif /// +#if NET48 public ulong[] PartitionIdTable => _model.Header.PartitionIdTable; +#else + public ulong[]? PartitionIdTable => _model.Header.PartitionIdTable; +#endif /// +#if NET48 public byte[] Reserved1 => _model.Header.Reserved1; +#else + public byte[]? Reserved1 => _model.Header.Reserved1; +#endif /// +#if NET48 public byte[] Reserved2 => _model.Header.Reserved2; +#else + public byte[]? Reserved2 => _model.Header.Reserved2; +#endif /// public byte FirmUpdateByte1 => _model.Header.FirmUpdateByte1; @@ -80,10 +116,18 @@ namespace BinaryObjectScanner.Wrappers #region Raw NAND Format Specific /// +#if NET48 public byte[] Unknown => _model.Header.Unknown; +#else + public byte[]? Unknown => _model.Header.Unknown; +#endif /// +#if NET48 public byte[] EncryptedMBR => _model.Header.EncryptedMBR; +#else + public byte[]? EncryptedMBR => _model.Header.EncryptedMBR; +#endif #endregion @@ -98,13 +142,21 @@ namespace BinaryObjectScanner.Wrappers public uint CIH_CardInfoBitmask => _model.CardInfoHeader.CardInfoBitmask; /// +#if NET48 public byte[] CIH_Reserved1 => _model.CardInfoHeader.Reserved1; +#else + public byte[]? CIH_Reserved1 => _model.CardInfoHeader.Reserved1; +#endif /// public uint CIH_FilledSize => _model.CardInfoHeader.FilledSize; /// +#if NET48 public byte[] CIH_Reserved2 => _model.CardInfoHeader.Reserved2; +#else + public byte[]? CIH_Reserved2 => _model.CardInfoHeader.Reserved2; +#endif /// public ushort CIH_TitleVersion => _model.CardInfoHeader.TitleVersion; @@ -113,16 +165,28 @@ namespace BinaryObjectScanner.Wrappers public ushort CIH_CardRevision => _model.CardInfoHeader.CardRevision; /// +#if NET48 public byte[] CIH_Reserved3 => _model.CardInfoHeader.Reserved3; +#else + public byte[]? CIH_Reserved3 => _model.CardInfoHeader.Reserved3; +#endif /// +#if NET48 public byte[] CIH_CVerTitleID => _model.CardInfoHeader.CVerTitleID; +#else + public byte[]? CIH_CVerTitleID => _model.CardInfoHeader.CVerTitleID; +#endif /// public ushort CIH_CVerVersionNumber => _model.CardInfoHeader.CVerVersionNumber; /// +#if NET48 public byte[] CIH_Reserved4 => _model.CardInfoHeader.Reserved4; +#else + public byte[]? CIH_Reserved4 => _model.CardInfoHeader.Reserved4; +#endif #endregion @@ -131,62 +195,134 @@ namespace BinaryObjectScanner.Wrappers #region Initial Data /// +#if NET48 public byte[] DCIH_ID_CardSeedKeyY => _model.DevelopmentCardInfoHeader?.InitialData?.CardSeedKeyY; +#else + public byte[]? DCIH_ID_CardSeedKeyY => _model.DevelopmentCardInfoHeader?.InitialData?.CardSeedKeyY; +#endif /// +#if NET48 public byte[] DCIH_ID_EncryptedCardSeed => _model.DevelopmentCardInfoHeader?.InitialData?.EncryptedCardSeed; +#else + public byte[]? DCIH_ID_EncryptedCardSeed => _model.DevelopmentCardInfoHeader?.InitialData?.EncryptedCardSeed; +#endif /// +#if NET48 public byte[] DCIH_ID_CardSeedAESMAC => _model.DevelopmentCardInfoHeader?.InitialData?.CardSeedAESMAC; +#else + public byte[]? DCIH_ID_CardSeedAESMAC => _model.DevelopmentCardInfoHeader?.InitialData?.CardSeedAESMAC; +#endif /// +#if NET48 public byte[] DCIH_ID_CardSeedNonce => _model.DevelopmentCardInfoHeader?.InitialData?.CardSeedNonce; +#else + public byte[]? DCIH_ID_CardSeedNonce => _model.DevelopmentCardInfoHeader?.InitialData?.CardSeedNonce; +#endif /// +#if NET48 public byte[] DCIH_ID_Reserved => _model.DevelopmentCardInfoHeader?.InitialData?.Reserved; +#else + public byte[]? DCIH_ID_Reserved => _model.DevelopmentCardInfoHeader?.InitialData?.Reserved; +#endif /// +#if NET48 public SabreTools.Models.N3DS.NCCHHeader DCIH_ID_BackupHeader => _model.DevelopmentCardInfoHeader?.InitialData?.BackupHeader; +#else + public SabreTools.Models.N3DS.NCCHHeader? DCIH_ID_BackupHeader => _model.DevelopmentCardInfoHeader?.InitialData?.BackupHeader; +#endif #endregion /// +#if NET48 public byte[] DCIH_CardDeviceReserved1 => _model.DevelopmentCardInfoHeader?.CardDeviceReserved1; +#else + public byte[]? DCIH_CardDeviceReserved1 => _model.DevelopmentCardInfoHeader?.CardDeviceReserved1; +#endif /// +#if NET48 public byte[] DCIH_TitleKey => _model.DevelopmentCardInfoHeader?.TitleKey; +#else + public byte[]? DCIH_TitleKey => _model.DevelopmentCardInfoHeader?.TitleKey; +#endif /// +#if NET48 public byte[] DCIH_CardDeviceReserved2 => _model.DevelopmentCardInfoHeader?.CardDeviceReserved2; +#else + public byte[]? DCIH_CardDeviceReserved2 => _model.DevelopmentCardInfoHeader?.CardDeviceReserved2; +#endif #region Test Data /// +#if NET48 public byte[] DCIH_TD_Signature => _model.DevelopmentCardInfoHeader?.TestData?.Signature; +#else + public byte[]? DCIH_TD_Signature => _model.DevelopmentCardInfoHeader?.TestData?.Signature; +#endif /// +#if NET48 public byte[] DCIH_TD_AscendingByteSequence => _model.DevelopmentCardInfoHeader?.TestData?.AscendingByteSequence; +#else + public byte[]? DCIH_TD_AscendingByteSequence => _model.DevelopmentCardInfoHeader?.TestData?.AscendingByteSequence; +#endif /// +#if NET48 public byte[] DCIH_TD_DescendingByteSequence => _model.DevelopmentCardInfoHeader?.TestData?.DescendingByteSequence; +#else + public byte[]? DCIH_TD_DescendingByteSequence => _model.DevelopmentCardInfoHeader?.TestData?.DescendingByteSequence; +#endif /// +#if NET48 public byte[] DCIH_TD_Filled00 => _model.DevelopmentCardInfoHeader?.TestData?.Filled00; +#else + public byte[]? DCIH_TD_Filled00 => _model.DevelopmentCardInfoHeader?.TestData?.Filled00; +#endif /// +#if NET48 public byte[] DCIH_TD_FilledFF => _model.DevelopmentCardInfoHeader?.TestData?.FilledFF; +#else + public byte[]? DCIH_TD_FilledFF => _model.DevelopmentCardInfoHeader?.TestData?.FilledFF; +#endif /// +#if NET48 public byte[] DCIH_TD_Filled0F => _model.DevelopmentCardInfoHeader?.TestData?.Filled0F; +#else + public byte[]? DCIH_TD_Filled0F => _model.DevelopmentCardInfoHeader?.TestData?.Filled0F; +#endif /// +#if NET48 public byte[] DCIH_TD_FilledF0 => _model.DevelopmentCardInfoHeader?.TestData?.FilledF0; +#else + public byte[]? DCIH_TD_FilledF0 => _model.DevelopmentCardInfoHeader?.TestData?.FilledF0; +#endif /// +#if NET48 public byte[] DCIH_TD_Filled55 => _model.DevelopmentCardInfoHeader?.TestData?.Filled55; +#else + public byte[]? DCIH_TD_Filled55 => _model.DevelopmentCardInfoHeader?.TestData?.Filled55; +#endif /// +#if NET48 public byte[] DCIH_TD_FilledAA => _model.DevelopmentCardInfoHeader?.TestData?.FilledAA; +#else + public byte[]? DCIH_TD_FilledAA => _model.DevelopmentCardInfoHeader?.TestData?.FilledAA; +#endif /// public byte? DCIH_TD_FinalByte => _model.DevelopmentCardInfoHeader?.TestData?.FinalByte; @@ -271,7 +407,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// A 3DS cart image wrapper on success, null on failure +#if NET48 public static N3DS Create(byte[] data, int offset) +#else + public static N3DS? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -291,7 +431,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A 3DS cart image wrapper on success, null on failure +#if NET48 public static N3DS Create(Stream data) +#else + public static N3DS? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -343,12 +487,12 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" NCSD Header Information:"); builder.AppendLine(" -------------------------"); - builder.AppendLine($" RSA-2048 SHA-256 signature: {BitConverter.ToString(RSA2048Signature).Replace('-', ' ')}"); + builder.AppendLine($" RSA-2048 SHA-256 signature: {(RSA2048Signature == null ? "[NULL]" : BitConverter.ToString(RSA2048Signature).Replace('-', ' '))}"); builder.AppendLine($" Magic number: {MagicNumber} (0x{MagicNumber:X})"); builder.AppendLine($" Image size in media units: {ImageSizeInMediaUnits} (0x{ImageSizeInMediaUnits:X})"); - builder.AppendLine($" Media ID: {BitConverter.ToString(MediaId).Replace('-', ' ')}"); + builder.AppendLine($" Media ID: {(MediaId == null ? "[NULL]" : BitConverter.ToString(MediaId).Replace('-', ' '))}"); builder.AppendLine($" Partitions filesystem type: {PartitionsFSType} (0x{PartitionsFSType:X})"); - builder.AppendLine($" Partitions crypt type: {BitConverter.ToString(PartitionsCryptType).Replace('-', ' ')}"); + builder.AppendLine($" Partitions crypt type: {(PartitionsCryptType == null ? "[NULL]" : BitConverter.ToString(PartitionsCryptType).Replace('-', ' '))}"); builder.AppendLine(); builder.AppendLine($" Partition table:"); @@ -365,10 +509,10 @@ namespace BinaryObjectScanner.Wrappers // If we have a cart image if (PartitionsFSType == SabreTools.Models.N3DS.FilesystemType.Normal || PartitionsFSType == SabreTools.Models.N3DS.FilesystemType.None) { - builder.AppendLine($" Exheader SHA-256 hash: {BitConverter.ToString(ExheaderHash).Replace('-', ' ')}"); + builder.AppendLine($" Exheader SHA-256 hash: {(ExheaderHash == null ? "[NULL]" : BitConverter.ToString(ExheaderHash).Replace('-', ' '))}"); builder.AppendLine($" Additional header size: {AdditionalHeaderSize} (0x{AdditionalHeaderSize:X})"); builder.AppendLine($" Sector zero offset: {SectorZeroOffset} (0x{SectorZeroOffset:X})"); - builder.AppendLine($" Partition flags: {BitConverter.ToString(PartitionFlags).Replace('-', ' ')}"); + builder.AppendLine($" Partition flags: {(PartitionFlags == null ? "[NULL]" : BitConverter.ToString(PartitionFlags).Replace('-', ' '))}"); builder.AppendLine(); builder.AppendLine($" Partition ID table:"); @@ -379,8 +523,8 @@ namespace BinaryObjectScanner.Wrappers } builder.AppendLine(); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(Reserved1).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(Reserved2).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 1: {(Reserved1 == null ? "[NULL]" : BitConverter.ToString(Reserved1).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 2: {(Reserved2 == null ? "[NULL]" : BitConverter.ToString(Reserved2).Replace('-', ' '))}"); builder.AppendLine($" Firmware update byte 1: {FirmUpdateByte1} (0x{FirmUpdateByte1:X})"); builder.AppendLine($" Firmware update byte 2: {FirmUpdateByte2} (0x{FirmUpdateByte2:X})"); } @@ -388,8 +532,8 @@ namespace BinaryObjectScanner.Wrappers // If we have a firmware image else if (PartitionsFSType == SabreTools.Models.N3DS.FilesystemType.FIRM) { - builder.AppendLine($" Unknown: {BitConverter.ToString(Unknown).Replace('-', ' ')}"); - builder.AppendLine($" Encrypted MBR: {BitConverter.ToString(EncryptedMBR).Replace('-', ' ')}"); + builder.AppendLine($" Unknown: {(Unknown == null ? "[NULL]" : BitConverter.ToString(Unknown).Replace('-', ' '))}"); + builder.AppendLine($" Encrypted MBR: {(EncryptedMBR == null ? "[NULL]" : BitConverter.ToString(EncryptedMBR).Replace('-', ' '))}"); } builder.AppendLine(); @@ -405,15 +549,15 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(" -------------------------"); builder.AppendLine($" Writable address in media units: {CIH_WritableAddressMediaUnits} (0x{CIH_WritableAddressMediaUnits:X})"); builder.AppendLine($" Card info bitmask: {CIH_CardInfoBitmask} (0x{CIH_CardInfoBitmask:X})"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(CIH_Reserved1).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 1: {(CIH_Reserved1 == null ? "[NULL]" : BitConverter.ToString(CIH_Reserved1).Replace('-', ' '))}"); builder.AppendLine($" Filled size of cartridge: {CIH_FilledSize} (0x{CIH_FilledSize:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(CIH_Reserved2).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(CIH_Reserved2 == null ? "[NULL]" : BitConverter.ToString(CIH_Reserved2).Replace('-', ' '))}"); builder.AppendLine($" Title version: {CIH_TitleVersion} (0x{CIH_TitleVersion:X})"); builder.AppendLine($" Card revision: {CIH_CardRevision} (0x{CIH_CardRevision:X})"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(CIH_Reserved3).Replace('-', ' ')}"); - builder.AppendLine($" Title ID of CVer in included update partition: {BitConverter.ToString(CIH_CVerTitleID).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 3: {(CIH_Reserved3 == null ? "[NULL]" : BitConverter.ToString(CIH_Reserved3).Replace('-', ' '))}"); + builder.AppendLine($" Title ID of CVer in included update partition: {(CIH_CVerTitleID == null ? "[NULL]" : BitConverter.ToString(CIH_CVerTitleID).Replace('-', ' '))}"); builder.AppendLine($" Version number of CVer in included update partition: {CIH_CVerVersionNumber} (0x{CIH_CVerVersionNumber:X})"); - builder.AppendLine($" Reserved 4: {BitConverter.ToString(CIH_Reserved4).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 4: {(CIH_Reserved4 == null ? "[NULL]" : BitConverter.ToString(CIH_Reserved4).Replace('-', ' '))}"); builder.AppendLine(); } @@ -434,11 +578,11 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(); builder.AppendLine(" Initial Data:"); builder.AppendLine(" -------------------------"); - builder.AppendLine($" Card seed keyY: {BitConverter.ToString(DCIH_ID_CardSeedKeyY).Replace('-', ' ')}"); - builder.AppendLine($" Encrypted card seed: {BitConverter.ToString(DCIH_ID_EncryptedCardSeed).Replace('-', ' ')}"); - builder.AppendLine($" Card seed AES-MAC: {BitConverter.ToString(DCIH_ID_CardSeedAESMAC).Replace('-', ' ')}"); - builder.AppendLine($" Card seed nonce: {BitConverter.ToString(DCIH_ID_CardSeedNonce).Replace('-', ' ')}"); - builder.AppendLine($" Reserved: {BitConverter.ToString(DCIH_ID_Reserved).Replace('-', ' ')}"); + builder.AppendLine($" Card seed keyY: {(DCIH_ID_CardSeedKeyY == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_CardSeedKeyY).Replace('-', ' '))}"); + builder.AppendLine($" Encrypted card seed: {(DCIH_ID_EncryptedCardSeed == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_EncryptedCardSeed).Replace('-', ' '))}"); + builder.AppendLine($" Card seed AES-MAC: {(DCIH_ID_CardSeedAESMAC == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_CardSeedAESMAC).Replace('-', ' '))}"); + builder.AppendLine($" Card seed nonce: {(DCIH_ID_CardSeedNonce == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_CardSeedNonce).Replace('-', ' '))}"); + builder.AppendLine($" Reserved: {(DCIH_ID_Reserved == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_Reserved).Replace('-', ' '))}"); builder.AppendLine(); builder.AppendLine(" Backup Header:"); @@ -449,13 +593,13 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Maker code: {DCIH_ID_BackupHeader.MakerCode} (0x{DCIH_ID_BackupHeader.MakerCode:X})"); builder.AppendLine($" Version: {DCIH_ID_BackupHeader.Version} (0x{DCIH_ID_BackupHeader.Version:X})"); builder.AppendLine($" Verification hash: {DCIH_ID_BackupHeader.VerificationHash} (0x{DCIH_ID_BackupHeader.VerificationHash:X})"); - builder.AppendLine($" Program ID: {BitConverter.ToString(DCIH_ID_BackupHeader.ProgramId).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(DCIH_ID_BackupHeader.Reserved1).Replace('-', ' ')}"); - builder.AppendLine($" Logo region SHA-256 hash: {BitConverter.ToString(DCIH_ID_BackupHeader.LogoRegionHash).Replace('-', ' ')}"); + builder.AppendLine($" Program ID: {(DCIH_ID_BackupHeader.ProgramId == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.ProgramId).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 1: {(DCIH_ID_BackupHeader.Reserved1 == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.Reserved1).Replace('-', ' '))}"); + builder.AppendLine($" Logo region SHA-256 hash: {(DCIH_ID_BackupHeader.LogoRegionHash == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.LogoRegionHash).Replace('-', ' '))}"); builder.AppendLine($" Product code: {DCIH_ID_BackupHeader.ProductCode} (0x{DCIH_ID_BackupHeader.ProductCode:X})"); - builder.AppendLine($" Extended header SHA-256 hash: {BitConverter.ToString(DCIH_ID_BackupHeader.ExtendedHeaderHash).Replace('-', ' ')}"); + builder.AppendLine($" Extended header SHA-256 hash: {(DCIH_ID_BackupHeader.ExtendedHeaderHash == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.ExtendedHeaderHash).Replace('-', ' '))}"); builder.AppendLine($" Extended header size in bytes: {DCIH_ID_BackupHeader.ExtendedHeaderSizeInBytes} (0x{DCIH_ID_BackupHeader.ExtendedHeaderSizeInBytes:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(DCIH_ID_BackupHeader.Reserved2).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(DCIH_ID_BackupHeader.Reserved2 == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.Reserved2).Replace('-', ' '))}"); builder.AppendLine($" Flags: {DCIH_ID_BackupHeader.Flags} (0x{DCIH_ID_BackupHeader.Flags:X})"); builder.AppendLine($" Plain region offset, in media units: {DCIH_ID_BackupHeader.PlainRegionOffsetInMediaUnits} (0x{DCIH_ID_BackupHeader.PlainRegionOffsetInMediaUnits:X})"); builder.AppendLine($" Plain region size, in media units: {DCIH_ID_BackupHeader.PlainRegionSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.PlainRegionSizeInMediaUnits:X})"); @@ -464,31 +608,31 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" ExeFS offset, in media units: {DCIH_ID_BackupHeader.ExeFSOffsetInMediaUnits} (0x{DCIH_ID_BackupHeader.ExeFSOffsetInMediaUnits:X})"); builder.AppendLine($" ExeFS size, in media units: {DCIH_ID_BackupHeader.ExeFSSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.ExeFSSizeInMediaUnits:X})"); builder.AppendLine($" ExeFS hash region size, in media units: {DCIH_ID_BackupHeader.ExeFSHashRegionSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.ExeFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(DCIH_ID_BackupHeader.Reserved3).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 3: {(DCIH_ID_BackupHeader.Reserved3 == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.Reserved3).Replace('-', ' '))}"); builder.AppendLine($" RomFS offset, in media units: {DCIH_ID_BackupHeader.RomFSOffsetInMediaUnits} (0x{DCIH_ID_BackupHeader.RomFSOffsetInMediaUnits:X})"); builder.AppendLine($" RomFS size, in media units: {DCIH_ID_BackupHeader.RomFSSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.RomFSSizeInMediaUnits:X})"); builder.AppendLine($" RomFS hash region size, in media units: {DCIH_ID_BackupHeader.RomFSHashRegionSizeInMediaUnits} (0x{DCIH_ID_BackupHeader.RomFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 4: {BitConverter.ToString(DCIH_ID_BackupHeader.Reserved4).Replace('-', ' ')}"); - builder.AppendLine($" ExeFS superblock SHA-256 hash: {BitConverter.ToString(DCIH_ID_BackupHeader.ExeFSSuperblockHash).Replace('-', ' ')}"); - builder.AppendLine($" RomFS superblock SHA-256 hash: {BitConverter.ToString(DCIH_ID_BackupHeader.RomFSSuperblockHash).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 4: {(DCIH_ID_BackupHeader.Reserved4 == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.Reserved4).Replace('-', ' '))}"); + builder.AppendLine($" ExeFS superblock SHA-256 hash: {(DCIH_ID_BackupHeader.ExeFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.ExeFSSuperblockHash).Replace('-', ' '))}"); + builder.AppendLine($" RomFS superblock SHA-256 hash: {(DCIH_ID_BackupHeader.RomFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(DCIH_ID_BackupHeader.RomFSSuperblockHash).Replace('-', ' '))}"); builder.AppendLine(); - builder.AppendLine($" Card device reserved 1: {BitConverter.ToString(DCIH_CardDeviceReserved1).Replace('-', ' ')}"); - builder.AppendLine($" Title key: {BitConverter.ToString(DCIH_TitleKey).Replace('-', ' ')}"); - builder.AppendLine($" Card device reserved 2: {BitConverter.ToString(DCIH_CardDeviceReserved2).Replace('-', ' ')}"); + builder.AppendLine($" Card device reserved 1: {(DCIH_CardDeviceReserved1 == null ? "[NULL]" : BitConverter.ToString(DCIH_CardDeviceReserved1).Replace('-', ' '))}"); + builder.AppendLine($" Title key: {(DCIH_TitleKey == null ? "[NULL]" : BitConverter.ToString(DCIH_TitleKey).Replace('-', ' '))}"); + builder.AppendLine($" Card device reserved 2: {(DCIH_CardDeviceReserved2 == null ? "[NULL]" : BitConverter.ToString(DCIH_CardDeviceReserved2).Replace('-', ' '))}"); builder.AppendLine(); builder.AppendLine(" Test Data:"); builder.AppendLine(" -------------------------"); - builder.AppendLine($" Signature: {BitConverter.ToString(DCIH_TD_Signature).Replace('-', ' ')}"); - builder.AppendLine($" Ascending byte sequence: {BitConverter.ToString(DCIH_TD_AscendingByteSequence).Replace('-', ' ')}"); - builder.AppendLine($" Descending byte sequence: {BitConverter.ToString(DCIH_TD_DescendingByteSequence).Replace('-', ' ')}"); - builder.AppendLine($" Filled with 00: {BitConverter.ToString(DCIH_TD_Filled00).Replace('-', ' ')}"); - builder.AppendLine($" Filled with FF: {BitConverter.ToString(DCIH_TD_FilledFF).Replace('-', ' ')}"); - builder.AppendLine($" Filled with 0F: {BitConverter.ToString(DCIH_TD_Filled0F).Replace('-', ' ')}"); - builder.AppendLine($" Filled with F0: {BitConverter.ToString(DCIH_TD_FilledF0).Replace('-', ' ')}"); - builder.AppendLine($" Filled with 55: {BitConverter.ToString(DCIH_TD_Filled55).Replace('-', ' ')}"); - builder.AppendLine($" Filled with AA: {BitConverter.ToString(DCIH_TD_FilledAA).Replace('-', ' ')}"); + builder.AppendLine($" Signature: {(DCIH_TD_Signature == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_Signature).Replace('-', ' '))}"); + builder.AppendLine($" Ascending byte sequence: {(DCIH_TD_AscendingByteSequence == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_AscendingByteSequence).Replace('-', ' '))}"); + builder.AppendLine($" Descending byte sequence: {(DCIH_TD_DescendingByteSequence == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_DescendingByteSequence).Replace('-', ' '))}"); + builder.AppendLine($" Filled with 00: {(DCIH_TD_Filled00 == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_Filled00).Replace('-', ' '))}"); + builder.AppendLine($" Filled with FF: {(DCIH_TD_FilledFF == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_FilledFF).Replace('-', ' '))}"); + builder.AppendLine($" Filled with 0F: {(DCIH_TD_Filled0F == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_Filled0F).Replace('-', ' '))}"); + builder.AppendLine($" Filled with F0: {(DCIH_TD_FilledF0 == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_FilledF0).Replace('-', ' '))}"); + builder.AppendLine($" Filled with 55: {(DCIH_TD_Filled55 == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_Filled55).Replace('-', ' '))}"); + builder.AppendLine($" Filled with AA: {(DCIH_TD_FilledAA == null ? "[NULL]" : BitConverter.ToString(DCIH_TD_FilledAA).Replace('-', ' '))}"); builder.AppendLine($" Final byte: {DCIH_TD_FinalByte}"); } @@ -523,20 +667,20 @@ namespace BinaryObjectScanner.Wrappers } else { - builder.AppendLine($" RSA-2048 SHA-256 signature: {BitConverter.ToString(partitionHeader.RSA2048Signature).Replace('-', ' ')}"); + builder.AppendLine($" RSA-2048 SHA-256 signature: {(partitionHeader.RSA2048Signature == null ? "[NULL]" : BitConverter.ToString(partitionHeader.RSA2048Signature).Replace('-', ' '))}"); builder.AppendLine($" Magic ID: {partitionHeader.MagicID} (0x{partitionHeader.MagicID:X})"); builder.AppendLine($" Content size in media units: {partitionHeader.ContentSizeInMediaUnits} (0x{partitionHeader.ContentSizeInMediaUnits:X})"); builder.AppendLine($" Partition ID: {partitionHeader.PartitionId} (0x{partitionHeader.PartitionId:X})"); builder.AppendLine($" Maker code: {partitionHeader.MakerCode} (0x{partitionHeader.MakerCode:X})"); builder.AppendLine($" Version: {partitionHeader.Version} (0x{partitionHeader.Version:X})"); builder.AppendLine($" Verification hash: {partitionHeader.VerificationHash} (0x{partitionHeader.VerificationHash:X})"); - builder.AppendLine($" Program ID: {BitConverter.ToString(partitionHeader.ProgramId).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(partitionHeader.Reserved1).Replace('-', ' ')}"); - builder.AppendLine($" Logo region SHA-256 hash: {BitConverter.ToString(partitionHeader.LogoRegionHash).Replace('-', ' ')}"); + builder.AppendLine($" Program ID: {(partitionHeader.ProgramId == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ProgramId).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 1: {(partitionHeader.Reserved1 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved1).Replace('-', ' '))}"); + builder.AppendLine($" Logo region SHA-256 hash: {(partitionHeader.LogoRegionHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.LogoRegionHash).Replace('-', ' '))}"); builder.AppendLine($" Product code: {partitionHeader.ProductCode} (0x{partitionHeader.ProductCode:X})"); - builder.AppendLine($" Extended header SHA-256 hash: {BitConverter.ToString(partitionHeader.ExtendedHeaderHash).Replace('-', ' ')}"); + builder.AppendLine($" Extended header SHA-256 hash: {(partitionHeader.ExtendedHeaderHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ExtendedHeaderHash).Replace('-', ' '))}"); builder.AppendLine($" Extended header size in bytes: {partitionHeader.ExtendedHeaderSizeInBytes} (0x{partitionHeader.ExtendedHeaderSizeInBytes:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(partitionHeader.Reserved2).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(partitionHeader.Reserved2 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved2).Replace('-', ' '))}"); builder.AppendLine(" Flags:"); builder.AppendLine($" Reserved 0: {partitionHeader.Flags.Reserved0} (0x{partitionHeader.Flags.Reserved0:X})"); builder.AppendLine($" Reserved 1: {partitionHeader.Flags.Reserved1} (0x{partitionHeader.Flags.Reserved1:X})"); @@ -553,13 +697,13 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" ExeFS offset, in media units: {partitionHeader.ExeFSOffsetInMediaUnits} (0x{partitionHeader.ExeFSOffsetInMediaUnits:X})"); builder.AppendLine($" ExeFS size, in media units: {partitionHeader.ExeFSSizeInMediaUnits} (0x{partitionHeader.ExeFSSizeInMediaUnits:X})"); builder.AppendLine($" ExeFS hash region size, in media units: {partitionHeader.ExeFSHashRegionSizeInMediaUnits} (0x{partitionHeader.ExeFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 3: {BitConverter.ToString(partitionHeader.Reserved3).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 3: {(partitionHeader.Reserved3 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved3).Replace('-', ' '))}"); builder.AppendLine($" RomFS offset, in media units: {partitionHeader.RomFSOffsetInMediaUnits} (0x{partitionHeader.RomFSOffsetInMediaUnits:X})"); builder.AppendLine($" RomFS size, in media units: {partitionHeader.RomFSSizeInMediaUnits} (0x{partitionHeader.RomFSSizeInMediaUnits:X})"); builder.AppendLine($" RomFS hash region size, in media units: {partitionHeader.RomFSHashRegionSizeInMediaUnits} (0x{partitionHeader.RomFSHashRegionSizeInMediaUnits:X})"); - builder.AppendLine($" Reserved 4: {BitConverter.ToString(partitionHeader.Reserved4).Replace('-', ' ')}"); - builder.AppendLine($" ExeFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.ExeFSSuperblockHash).Replace('-', ' ')}"); - builder.AppendLine($" RomFS superblock SHA-256 hash: {BitConverter.ToString(partitionHeader.RomFSSuperblockHash).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 4: {(partitionHeader.Reserved4 == null ? "[NULL]" : BitConverter.ToString(partitionHeader.Reserved4).Replace('-', ' '))}"); + builder.AppendLine($" ExeFS superblock SHA-256 hash: {(partitionHeader.ExeFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.ExeFSSuperblockHash).Replace('-', ' '))}"); + builder.AppendLine($" RomFS superblock SHA-256 hash: {(partitionHeader.RomFSSuperblockHash == null ? "[NULL]" : BitConverter.ToString(partitionHeader.RomFSSuperblockHash).Replace('-', ' '))}"); } } } @@ -592,7 +736,7 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine($" System control info:"); builder.AppendLine($" Application title: {extendedHeader.SCI.ApplicationTitle}"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(extendedHeader.SCI.Reserved1).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 1: {(extendedHeader.SCI.Reserved1 == null ? "[NULL]" : BitConverter.ToString(extendedHeader.SCI.Reserved1).Replace('-', ' '))}"); builder.AppendLine($" Flag: {extendedHeader.SCI.Flag} (0x{extendedHeader.SCI.Flag:X})"); builder.AppendLine($" Remaster version: {extendedHeader.SCI.RemasterVersion} (0x{extendedHeader.SCI.RemasterVersion:X})"); @@ -608,7 +752,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Physical region size (in page-multiples): {extendedHeader.SCI.ReadOnlyCodeSetInfo.PhysicalRegionSizeInPages} (0x{extendedHeader.SCI.ReadOnlyCodeSetInfo.PhysicalRegionSizeInPages:X})"); builder.AppendLine($" Size (in bytes): {extendedHeader.SCI.ReadOnlyCodeSetInfo.SizeInBytes} (0x{extendedHeader.SCI.ReadOnlyCodeSetInfo.SizeInBytes:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(extendedHeader.SCI.Reserved2).Replace('-', newChar: ' ')}"); + builder.AppendLine($" Reserved 2: {(extendedHeader.SCI.Reserved2 == null ? "[NULL]" : BitConverter.ToString(extendedHeader.SCI.Reserved2).Replace('-', ' '))}"); builder.AppendLine($" Data code set info:"); builder.AppendLine($" Address: {extendedHeader.SCI.DataCodeSetInfo.Address} (0x{extendedHeader.SCI.DataCodeSetInfo.Address:X})"); @@ -616,12 +760,12 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Size (in bytes): {extendedHeader.SCI.DataCodeSetInfo.SizeInBytes} (0x{extendedHeader.SCI.DataCodeSetInfo.SizeInBytes:X})"); builder.AppendLine($" BSS size: {extendedHeader.SCI.BSSSize} (0x{extendedHeader.SCI.BSSSize:X})"); - builder.AppendLine($" Dependency module list: {string.Join(", ", extendedHeader.SCI.DependencyModuleList)}"); + builder.AppendLine($" Dependency module list: {(extendedHeader.SCI.DependencyModuleList == null ? "[NULL]" : string.Join(", ", extendedHeader.SCI.DependencyModuleList))}"); builder.AppendLine($" System info:"); builder.AppendLine($" SaveData size: {extendedHeader.SCI.SystemInfo.SaveDataSize} (0x{extendedHeader.SCI.SystemInfo.SaveDataSize:X})"); builder.AppendLine($" Jump ID: {extendedHeader.SCI.SystemInfo.JumpID} (0x{extendedHeader.SCI.SystemInfo.JumpID:X})"); - builder.AppendLine($" Reserved: {BitConverter.ToString(extendedHeader.SCI.SystemInfo.Reserved).Replace('-', newChar: ' ')}"); + builder.AppendLine($" Reserved: {(extendedHeader.SCI.SystemInfo.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.SCI.SystemInfo.Reserved).Replace('-', ' '))}"); builder.AppendLine($" Access control info:"); builder.AppendLine($" ARM11 local system capabilities:"); @@ -631,30 +775,30 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Flag 2: {extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag2} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag2:X})"); builder.AppendLine($" Flag 0: {extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag0} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.Flag0:X})"); builder.AppendLine($" Priority: {extendedHeader.ACI.ARM11LocalSystemCapabilities.Priority} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.Priority:X})"); - builder.AppendLine($" Resource limit descriptors: {string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitDescriptors)}"); + builder.AppendLine($" Resource limit descriptors: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitDescriptors == null ? "[NULL]" : string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitDescriptors))}"); builder.AppendLine($" Storage info:"); builder.AppendLine($" Extdata ID: {extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID:X})"); - builder.AppendLine($" System savedata IDs: {BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs).Replace('-', newChar: ' ')}"); - builder.AppendLine($" Storage accessible unique IDs: {BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs).Replace('-', newChar: ' ')}"); - builder.AppendLine($" File system access info: {BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo).Replace('-', newChar: ' ')}"); + builder.AppendLine($" System savedata IDs: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs).Replace('-', ' '))}"); + builder.AppendLine($" Storage accessible unique IDs: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs).Replace('-', ' '))}"); + builder.AppendLine($" File system access info: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo).Replace('-', ' '))}"); builder.AppendLine($" Other attributes: {extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes:X})"); - builder.AppendLine($" Service access control: {string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ServiceAccessControl)}"); - builder.AppendLine($" Extended service access control: {string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl)}"); - builder.AppendLine($" Reserved: {BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.Reserved).Replace('-', newChar: ' ')}"); + builder.AppendLine($" Service access control: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.ServiceAccessControl == null ? "[NULL]" : string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ServiceAccessControl))}"); + builder.AppendLine($" Extended service access control: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl == null ? "[NULL]" : string.Join(", ", extendedHeader.ACI.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl))}"); + builder.AppendLine($" Reserved: {(extendedHeader.ACI.ARM11LocalSystemCapabilities.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11LocalSystemCapabilities.Reserved).Replace('-', ' '))}"); builder.AppendLine($" Resource limit cateogry: {extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitCategory} (0x{extendedHeader.ACI.ARM11LocalSystemCapabilities.ResourceLimitCategory:X})"); builder.AppendLine($" ARM11 kernel capabilities:"); - builder.AppendLine($" Descriptors: {string.Join(", ", extendedHeader.ACI.ARM11KernelCapabilities.Descriptors)}"); - builder.AppendLine($" Reserved: {BitConverter.ToString(extendedHeader.ACI.ARM11KernelCapabilities.Reserved).Replace('-', newChar: ' ')}"); + builder.AppendLine($" Descriptors: {(extendedHeader.ACI.ARM11KernelCapabilities.Descriptors == null ? "[NULL]" : string.Join(", ", extendedHeader.ACI.ARM11KernelCapabilities.Descriptors))}"); + builder.AppendLine($" Reserved: {(extendedHeader.ACI.ARM11KernelCapabilities.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM11KernelCapabilities.Reserved).Replace('-', ' '))}"); builder.AppendLine($" ARM9 access control:"); - builder.AppendLine($" Descriptors: {BitConverter.ToString(extendedHeader.ACI.ARM9AccessControl.Descriptors).Replace('-', newChar: ' ')}"); + builder.AppendLine($" Descriptors: {(extendedHeader.ACI.ARM9AccessControl.Descriptors == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACI.ARM9AccessControl.Descriptors).Replace('-', ' '))}"); builder.AppendLine($" Descriptor version: {extendedHeader.ACI.ARM9AccessControl.DescriptorVersion} (0x{extendedHeader.ACI.ARM9AccessControl.DescriptorVersion:X})"); - builder.AppendLine($" AccessDec signature (RSA-2048-SHA256): {BitConverter.ToString(extendedHeader.AccessDescSignature).Replace('-', ' ')}"); - builder.AppendLine($" NCCH HDR RSA-2048 public key: {BitConverter.ToString(extendedHeader.NCCHHDRPublicKey).Replace('-', ' ')}"); + builder.AppendLine($" AccessDec signature (RSA-2048-SHA256): {(extendedHeader.AccessDescSignature == null ? "[NULL]" : BitConverter.ToString(extendedHeader.AccessDescSignature).Replace('-', ' '))}"); + builder.AppendLine($" NCCH HDR RSA-2048 public key: {(extendedHeader.NCCHHDRPublicKey == null ? "[NULL]" : BitConverter.ToString(extendedHeader.NCCHHDRPublicKey).Replace('-', ' '))}"); builder.AppendLine($" Access control info (for limitations of first ACI):"); @@ -665,26 +809,26 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Flag 2: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag2} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag2:X})"); builder.AppendLine($" Flag 0: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag0} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Flag0:X})"); builder.AppendLine($" Priority: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Priority} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Priority:X})"); - builder.AppendLine($" Resource limit descriptors: {string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitDescriptors)}"); + builder.AppendLine($" Resource limit descriptors: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitDescriptors == null ? "[NULL]" : string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitDescriptors))}"); builder.AppendLine($" Storage info:"); builder.AppendLine($" Extdata ID: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID:X})"); - builder.AppendLine($" System savedata IDs: {BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs).Replace('-', newChar: ' ')}"); - builder.AppendLine($" Storage accessible unique IDs: {BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs).Replace('-', newChar: ' ')}"); - builder.AppendLine($" File system access info: {BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo).Replace('-', newChar: ' ')}"); + builder.AppendLine($" System savedata IDs: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs).Replace('-', ' '))}"); + builder.AppendLine($" Storage accessible unique IDs: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs).Replace('-', ' '))}"); + builder.AppendLine($" File system access info: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo).Replace('-', ' '))}"); builder.AppendLine($" Other attributes: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes:X})"); - builder.AppendLine($" Service access control: {string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ServiceAccessControl)}"); - builder.AppendLine($" Extended service access control: {string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl)}"); - builder.AppendLine($" Reserved: {BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Reserved).Replace('-', newChar: ' ')}"); + builder.AppendLine($" Service access control: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ServiceAccessControl == null ? "[NULL]" : string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ServiceAccessControl))}"); + builder.AppendLine($" Extended service access control: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl == null ? "[NULL]" : string.Join(", ", extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl))}"); + builder.AppendLine($" Reserved: {(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.Reserved).Replace('-', ' '))}"); builder.AppendLine($" Resource limit cateogry: {extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitCategory} (0x{extendedHeader.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitCategory:X})"); builder.AppendLine($" ARM11 kernel capabilities:"); - builder.AppendLine($" Descriptors: {string.Join(", ", extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Descriptors)}"); - builder.AppendLine($" Reserved: {BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Reserved).Replace('-', newChar: ' ')}"); + builder.AppendLine($" Descriptors: {(extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Descriptors == null ? "[NULL]" : string.Join(", ", extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Descriptors))}"); + builder.AppendLine($" Reserved: {(extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Reserved == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM11KernelCapabilities.Reserved).Replace('-', ' '))}"); builder.AppendLine($" ARM9 access control:"); - builder.AppendLine($" Descriptors: {BitConverter.ToString(extendedHeader.ACIForLimitations.ARM9AccessControl.Descriptors).Replace('-', newChar: ' ')}"); + builder.AppendLine($" Descriptors: {(extendedHeader.ACIForLimitations.ARM9AccessControl.Descriptors == null ? "[NULL]" : BitConverter.ToString(extendedHeader.ACIForLimitations.ARM9AccessControl.Descriptors).Replace('-', ' '))}"); builder.AppendLine($" Descriptor version: {extendedHeader.ACIForLimitations.ARM9AccessControl.DescriptorVersion} (0x{extendedHeader.ACIForLimitations.ARM9AccessControl.DescriptorVersion:X})"); } } @@ -726,14 +870,14 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(value: $" File size: {fileHeader.FileSize} (0x{fileHeader.FileSize:X})"); } - builder.AppendLine(value: $" Reserved: {BitConverter.ToString(exeFSHeader.Reserved).Replace('-', ' ')}"); + builder.AppendLine(value: $" Reserved: {(exeFSHeader.Reserved == null ? "[NULL]" : BitConverter.ToString(exeFSHeader.Reserved).Replace('-', ' '))}"); builder.AppendLine($" File hashes:"); for (int j = 0; j < exeFSHeader.FileHashes.Length; j++) { var fileHash = exeFSHeader.FileHashes[j]; builder.AppendLine(value: $" File Hash {j}"); - builder.AppendLine(value: $" SHA-256: {BitConverter.ToString(fileHash).Replace('-', ' ')}"); + builder.AppendLine(value: $" SHA-256: {(fileHash == null ? "[NULL]" : BitConverter.ToString(fileHash).Replace('-', ' '))}"); } } } @@ -771,16 +915,16 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(value: $" Level 1 logical offset: {romFSHeader.Level1LogicalOffset} (0x{romFSHeader.Level1LogicalOffset:X})"); builder.AppendLine(value: $" Level 1 hashdata size: {romFSHeader.Level1HashdataSize} (0x{romFSHeader.Level1HashdataSize:X})"); builder.AppendLine(value: $" Level 1 block size: {romFSHeader.Level1BlockSizeLog2} (0x{romFSHeader.Level1BlockSizeLog2:X})"); - builder.AppendLine(value: $" Reserved 1: {BitConverter.ToString(romFSHeader.Reserved1).Replace('-', ' ')}"); + builder.AppendLine(value: $" Reserved 1: {(romFSHeader.Reserved1 == null ? "[NULL]" : BitConverter.ToString(romFSHeader.Reserved1).Replace('-', ' '))}"); builder.AppendLine(value: $" Level 2 logical offset: {romFSHeader.Level2LogicalOffset} (0x{romFSHeader.Level2LogicalOffset:X})"); builder.AppendLine(value: $" Level 2 hashdata size: {romFSHeader.Level2HashdataSize} (0x{romFSHeader.Level2HashdataSize:X})"); builder.AppendLine(value: $" Level 2 block size: {romFSHeader.Level2BlockSizeLog2} (0x{romFSHeader.Level2BlockSizeLog2:X})"); - builder.AppendLine(value: $" Reserved 2: {BitConverter.ToString(romFSHeader.Reserved2).Replace('-', ' ')}"); + builder.AppendLine(value: $" Reserved 2: {(romFSHeader.Reserved2 == null ? "[NULL]" : BitConverter.ToString(romFSHeader.Reserved2).Replace('-', ' '))}"); builder.AppendLine(value: $" Level 3 logical offset: {romFSHeader.Level3LogicalOffset} (0x{romFSHeader.Level3LogicalOffset:X})"); builder.AppendLine(value: $" Level 3 hashdata size: {romFSHeader.Level3HashdataSize} (0x{romFSHeader.Level3HashdataSize:X})"); builder.AppendLine(value: $" Level 3 block size: {romFSHeader.Level3BlockSizeLog2} (0x{romFSHeader.Level3BlockSizeLog2:X})"); - builder.AppendLine(value: $" Reserved 3: {BitConverter.ToString(romFSHeader.Reserved3).Replace('-', ' ')}"); - builder.AppendLine(value: $" Reserved 4: {BitConverter.ToString(romFSHeader.Reserved4).Replace('-', ' ')}"); + builder.AppendLine(value: $" Reserved 3: {(romFSHeader.Reserved3 == null ? "[NULL]" : BitConverter.ToString(romFSHeader.Reserved3).Replace('-', ' '))}"); + builder.AppendLine(value: $" Reserved 4: {(romFSHeader.Reserved4 == null ? "[NULL]" : BitConverter.ToString(romFSHeader.Reserved4).Replace('-', ' '))}"); builder.AppendLine(value: $" Optional info size: {romFSHeader.OptionalInfoSize} (0x{romFSHeader.OptionalInfoSize:X})"); } } diff --git a/BinaryObjectScanner.Wrappers/NCF.cs b/BinaryObjectScanner.Wrappers/NCF.cs index 196378d2..f350178c 100644 --- a/BinaryObjectScanner.Wrappers/NCF.cs +++ b/BinaryObjectScanner.Wrappers/NCF.cs @@ -265,7 +265,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the NCF /// Offset within the array to parse /// An NCF wrapper on success, null on failure +#if NET48 public static NCF Create(byte[] data, int offset) +#else + public static NCF? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -285,7 +289,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the NCF /// An NCF wrapper on success, null on failure +#if NET48 public static NCF Create(Stream data) +#else + public static NCF? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) diff --git a/BinaryObjectScanner.Wrappers/NewExecutable.cs b/BinaryObjectScanner.Wrappers/NewExecutable.cs index 9da627b7..b35c8f2f 100644 --- a/BinaryObjectScanner.Wrappers/NewExecutable.cs +++ b/BinaryObjectScanner.Wrappers/NewExecutable.cs @@ -22,7 +22,11 @@ namespace BinaryObjectScanner.Wrappers #region Standard Fields /// +#if NET48 public string Stub_Magic => _model.Stub.Header.Magic; +#else + public string? Stub_Magic => _model.Stub.Header.Magic; +#endif /// public ushort Stub_LastPageBytes => _model.Stub.Header.LastPageBytes; @@ -68,7 +72,11 @@ namespace BinaryObjectScanner.Wrappers #region PE Extensions /// +#if NET48 public ushort[] Stub_Reserved1 => _model.Stub.Header.Reserved1; +#else + public ushort[]? Stub_Reserved1 => _model.Stub.Header.Reserved1; +#endif /// public ushort Stub_OEMIdentifier => _model.Stub.Header.OEMIdentifier; @@ -77,7 +85,11 @@ namespace BinaryObjectScanner.Wrappers public ushort Stub_OEMInformation => _model.Stub.Header.OEMInformation; /// +#if NET48 public ushort[] Stub_Reserved2 => _model.Stub.Header.Reserved2; +#else + public ushort[]? Stub_Reserved2 => _model.Stub.Header.Reserved2; +#endif /// public uint Stub_NewExeHeaderAddr => _model.Stub.Header.NewExeHeaderAddr; @@ -89,7 +101,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Magic => _model.Header.Magic; +#else + public string? Magic => _model.Header.Magic; +#endif /// public byte LinkerVersion => _model.Header.LinkerVersion; @@ -274,7 +290,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the executable /// Offset within the array to parse /// An NE executable wrapper on success, null on failure +#if NET48 public static NewExecutable Create(byte[] data, int offset) +#else + public static NewExecutable? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -294,7 +314,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the executable /// An NE executable wrapper on success, null on failure +#if NET48 public static NewExecutable Create(Stream data) +#else + public static NewExecutable? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -379,10 +403,10 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" MS-DOS Stub Extended Header Information:"); builder.AppendLine(" -------------------------"); - builder.AppendLine($" Reserved words: {string.Join(", ", Stub_Reserved1)}"); + builder.AppendLine($" Reserved words: {(Stub_Reserved1 == null ? "[NULL]" : string.Join(", ", Stub_Reserved1))}"); builder.AppendLine($" OEM identifier: {Stub_OEMIdentifier} (0x{Stub_OEMIdentifier:X})"); builder.AppendLine($" OEM information: {Stub_OEMInformation} (0x{Stub_OEMInformation:X})"); - builder.AppendLine($" Reserved words: {string.Join(", ", Stub_Reserved2)}"); + builder.AppendLine($" Reserved words: {(Stub_Reserved2 == null ? "[NULL]" : string.Join(", ", Stub_Reserved2))}"); builder.AppendLine($" New EXE header address: {Stub_NewExeHeaderAddr} (0x{Stub_NewExeHeaderAddr:X})"); builder.AppendLine(); } @@ -674,7 +698,11 @@ namespace BinaryObjectScanner.Wrappers /// How many bytes to read, -1 means read until end /// Byte array representing the range, null on error [Obsolete] +#if NET48 public byte[] ReadArbitraryRange(int rangeStart = -1, int length = -1) +#else + public byte[]? ReadArbitraryRange(int rangeStart = -1, int length = -1) +#endif { // If we have an unset range start, read from the start of the source if (rangeStart == -1) diff --git a/BinaryObjectScanner.Wrappers/Nitro.cs b/BinaryObjectScanner.Wrappers/Nitro.cs index 0e938a22..f768c657 100644 --- a/BinaryObjectScanner.Wrappers/Nitro.cs +++ b/BinaryObjectScanner.Wrappers/Nitro.cs @@ -18,13 +18,21 @@ namespace BinaryObjectScanner.Wrappers #region Common Header /// +#if NET48 public string GameTitle => _model.CommonHeader.GameTitle; +#else + public string? GameTitle => _model.CommonHeader.GameTitle; +#endif /// public uint GameCode => _model.CommonHeader.GameCode; /// +#if NET48 public string MakerCode => _model.CommonHeader.MakerCode; +#else + public string? MakerCode => _model.CommonHeader.MakerCode; +#endif /// public SabreTools.Models.Nitro.Unitcode UnitCode => _model.CommonHeader.UnitCode; @@ -36,7 +44,11 @@ namespace BinaryObjectScanner.Wrappers public byte DeviceCapacity => _model.CommonHeader.DeviceCapacity; /// +#if NET48 public byte[] Reserved1 => _model.CommonHeader.Reserved1; +#else + public byte[]? Reserved1 => _model.CommonHeader.Reserved1; +#endif /// public ushort GameRevision => _model.CommonHeader.GameRevision; @@ -117,7 +129,11 @@ namespace BinaryObjectScanner.Wrappers public uint ARM7Autoload => _model.CommonHeader.ARM7Autoload; /// +#if NET48 public byte[] SecureDisable => _model.CommonHeader.SecureDisable; +#else + public byte[]? SecureDisable => _model.CommonHeader.SecureDisable; +#endif /// public uint NTRRegionRomSize => _model.CommonHeader.NTRRegionRomSize; @@ -126,10 +142,18 @@ namespace BinaryObjectScanner.Wrappers public uint HeaderSize => _model.CommonHeader.HeaderSize; /// +#if NET48 public byte[] Reserved2 => _model.CommonHeader.Reserved2; +#else + public byte[]? Reserved2 => _model.CommonHeader.Reserved2; +#endif /// +#if NET48 public byte[] NintendoLogo => _model.CommonHeader.NintendoLogo; +#else + public byte[]? NintendoLogo => _model.CommonHeader.NintendoLogo; +#endif /// public ushort NintendoLogoCRC => _model.CommonHeader.NintendoLogoCRC; @@ -138,20 +162,36 @@ namespace BinaryObjectScanner.Wrappers public ushort HeaderCRC => _model.CommonHeader.HeaderCRC; /// +#if NET48 public byte[] DebuggerReserved => _model.CommonHeader.DebuggerReserved; +#else + public byte[]? DebuggerReserved => _model.CommonHeader.DebuggerReserved; +#endif #endregion #region Extended DSi Header /// +#if NET48 public uint[] GlobalMBK15Settings => _model.ExtendedDSiHeader?.GlobalMBK15Settings; +#else + public uint[]? GlobalMBK15Settings => _model.ExtendedDSiHeader?.GlobalMBK15Settings; +#endif /// +#if NET48 public uint[] LocalMBK68SettingsARM9 => _model.ExtendedDSiHeader?.LocalMBK68SettingsARM9; +#else + public uint[]? LocalMBK68SettingsARM9 => _model.ExtendedDSiHeader?.LocalMBK68SettingsARM9; +#endif /// +#if NET48 public uint[] LocalMBK68SettingsARM7 => _model.ExtendedDSiHeader?.LocalMBK68SettingsARM7; +#else + public uint[]? LocalMBK68SettingsARM7 => _model.ExtendedDSiHeader?.LocalMBK68SettingsARM7; +#endif /// public uint? GlobalMBK9Setting => _model.ExtendedDSiHeader?.GlobalMBK9Setting; @@ -241,7 +281,11 @@ namespace BinaryObjectScanner.Wrappers public uint? ModcryptArea2Size => _model.ExtendedDSiHeader?.ModcryptArea2Size; /// +#if NET48 public byte[] TitleID => _model.ExtendedDSiHeader?.TitleID; +#else + public byte[]? TitleID => _model.ExtendedDSiHeader?.TitleID; +#endif /// public uint? DSiWarePublicSavSize => _model.ExtendedDSiHeader?.DSiWarePublicSavSize; @@ -250,50 +294,106 @@ namespace BinaryObjectScanner.Wrappers public uint? DSiWarePrivateSavSize => _model.ExtendedDSiHeader?.DSiWarePrivateSavSize; /// +#if NET48 public byte[] ReservedZero => _model.ExtendedDSiHeader?.ReservedZero; +#else + public byte[]? ReservedZero => _model.ExtendedDSiHeader?.ReservedZero; +#endif /// +#if NET48 public byte[] Unknown2 => _model.ExtendedDSiHeader?.Unknown2; +#else + public byte[]? Unknown2 => _model.ExtendedDSiHeader?.Unknown2; +#endif /// +#if NET48 public byte[] ARM9WithSecureAreaSHA1HMACHash => _model.ExtendedDSiHeader?.ARM9WithSecureAreaSHA1HMACHash; +#else + public byte[]? ARM9WithSecureAreaSHA1HMACHash => _model.ExtendedDSiHeader?.ARM9WithSecureAreaSHA1HMACHash; +#endif /// +#if NET48 public byte[] ARM7SHA1HMACHash => _model.ExtendedDSiHeader?.ARM7SHA1HMACHash; +#else + public byte[]? ARM7SHA1HMACHash => _model.ExtendedDSiHeader?.ARM7SHA1HMACHash; +#endif /// +#if NET48 public byte[] DigestMasterSHA1HMACHash => _model.ExtendedDSiHeader?.DigestMasterSHA1HMACHash; +#else + public byte[]? DigestMasterSHA1HMACHash => _model.ExtendedDSiHeader?.DigestMasterSHA1HMACHash; +#endif /// +#if NET48 public byte[] BannerSHA1HMACHash => _model.ExtendedDSiHeader?.BannerSHA1HMACHash; +#else + public byte[]? BannerSHA1HMACHash => _model.ExtendedDSiHeader?.BannerSHA1HMACHash; +#endif /// +#if NET48 public byte[] ARM9iDecryptedSHA1HMACHash => _model.ExtendedDSiHeader?.ARM9iDecryptedSHA1HMACHash; +#else + public byte[]? ARM9iDecryptedSHA1HMACHash => _model.ExtendedDSiHeader?.ARM9iDecryptedSHA1HMACHash; +#endif /// +#if NET48 public byte[] ARM7iDecryptedSHA1HMACHash => _model.ExtendedDSiHeader?.ARM7iDecryptedSHA1HMACHash; +#else + public byte[]? ARM7iDecryptedSHA1HMACHash => _model.ExtendedDSiHeader?.ARM7iDecryptedSHA1HMACHash; +#endif /// +#if NET48 public byte[] Reserved5 => _model.ExtendedDSiHeader?.Reserved5; +#else + public byte[]? Reserved5 => _model.ExtendedDSiHeader?.Reserved5; +#endif /// +#if NET48 public byte[] ARM9NoSecureAreaSHA1HMACHash => _model.ExtendedDSiHeader?.ARM9NoSecureAreaSHA1HMACHash; +#else + public byte[]? ARM9NoSecureAreaSHA1HMACHash => _model.ExtendedDSiHeader?.ARM9NoSecureAreaSHA1HMACHash; +#endif /// +#if NET48 public byte[] Reserved6 => _model.ExtendedDSiHeader?.Reserved6; +#else + public byte[]? Reserved6 => _model.ExtendedDSiHeader?.Reserved6; +#endif /// +#if NET48 public byte[] ReservedAndUnchecked => _model.ExtendedDSiHeader?.ReservedAndUnchecked; +#else + public byte[]? ReservedAndUnchecked => _model.ExtendedDSiHeader?.ReservedAndUnchecked; +#endif /// +#if NET48 public byte[] RSASignature => _model.ExtendedDSiHeader?.RSASignature; +#else + public byte[]? RSASignature => _model.ExtendedDSiHeader?.RSASignature; +#endif #endregion #region Secure Area /// +#if NET48 public byte[] SecureArea => _model.SecureArea; +#else + public byte[]? SecureArea => _model.SecureArea; +#endif #endregion @@ -358,7 +458,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// A NDS cart image wrapper on success, null on failure +#if NET48 public static Nitro Create(byte[] data, int offset) +#else + public static Nitro? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -378,7 +482,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A NDS cart image wrapper on success, null on failure +#if NET48 public static Nitro Create(Stream data) +#else + public static Nitro? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -434,7 +542,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Unit code: {UnitCode} (0x{UnitCode:X})"); builder.AppendLine($" Encryption seed select: {EncryptionSeedSelect} (0x{EncryptionSeedSelect:X})"); builder.AppendLine($" Device capacity: {DeviceCapacity} (0x{DeviceCapacity:X})"); - builder.AppendLine($" Reserved 1: {BitConverter.ToString(Reserved1).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 1: {(Reserved1 == null ? "[NULL]" : BitConverter.ToString(Reserved1).Replace('-', ' '))}"); builder.AppendLine($" Game revision: {GameRevision} (0x{GameRevision:X})"); builder.AppendLine($" Rom version: {RomVersion} (0x{RomVersion:X})"); builder.AppendLine($" ARM9 rom offset: {ARM9RomOffset} (0x{ARM9RomOffset:X})"); @@ -463,11 +571,11 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Secure disable: {SecureDisable} (0x{SecureDisable:X})"); builder.AppendLine($" NTR region rom size: {NTRRegionRomSize} (0x{NTRRegionRomSize:X})"); builder.AppendLine($" Header size: {HeaderSize} (0x{HeaderSize:X})"); - builder.AppendLine($" Reserved 2: {BitConverter.ToString(Reserved2).Replace('-', ' ')}"); - builder.AppendLine($" Nintendo logo: {BitConverter.ToString(NintendoLogo).Replace('-', ' ')}"); + builder.AppendLine($" Reserved 2: {(Reserved2 == null ? "[NULL]" : BitConverter.ToString(Reserved2).Replace('-', ' '))}"); + builder.AppendLine($" Nintendo logo: {(NintendoLogo == null ? "[NULL]" : BitConverter.ToString(NintendoLogo).Replace('-', ' '))}"); builder.AppendLine($" Nintendo logo CRC: {NintendoLogoCRC} (0x{NintendoLogoCRC:X})"); builder.AppendLine($" Header CRC: {HeaderCRC} (0x{HeaderCRC:X})"); - builder.AppendLine($" Debugger reserved: {BitConverter.ToString(DebuggerReserved).Replace('-', ' ')}"); + builder.AppendLine($" Debugger reserved: {(DebuggerReserved == null ? "[NULL]" : BitConverter.ToString(DebuggerReserved).Replace('-', ' '))}"); builder.AppendLine(); } @@ -485,9 +593,9 @@ namespace BinaryObjectScanner.Wrappers } else { - builder.AppendLine($" Global MBK1..MBK5 settings: {string.Join(", ", GlobalMBK15Settings)}"); - builder.AppendLine($" Local MBK6..MBK8 settings for ARM9: {string.Join(", ", LocalMBK68SettingsARM9)}"); - builder.AppendLine($" Local MBK6..MBK8 settings for ARM7: {string.Join(", ", LocalMBK68SettingsARM7)}"); + builder.AppendLine($" Global MBK1..MBK5 settings: {(GlobalMBK15Settings == null ? "[NULL]" : string.Join(", ", GlobalMBK15Settings))}"); + builder.AppendLine($" Local MBK6..MBK8 settings for ARM9: {(LocalMBK68SettingsARM9 == null ? "[NULL]" : string.Join(", ", LocalMBK68SettingsARM9))}"); + builder.AppendLine($" Local MBK6..MBK8 settings for ARM7: {(LocalMBK68SettingsARM7 == null ? "[NULL]" : string.Join(", ", LocalMBK68SettingsARM7))}"); builder.AppendLine($" Global MBK9 setting: {GlobalMBK9Setting} (0x{GlobalMBK9Setting:X})"); builder.AppendLine($" Region flags: {RegionFlags} (0x{RegionFlags:X})"); builder.AppendLine($" Access control: {AccessControl} (0x{AccessControl:X})"); @@ -517,22 +625,22 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Modcrypt area 1 size: {ModcryptArea1Size} (0x{ModcryptArea1Size:X})"); builder.AppendLine($" Modcrypt area 2 offset: {ModcryptArea2Offset} (0x{ModcryptArea2Offset:X})"); builder.AppendLine($" Modcrypt area 2 size: {ModcryptArea2Size} (0x{ModcryptArea2Size:X})"); - builder.AppendLine($" Title ID: {BitConverter.ToString(TitleID).Replace('-', ' ')}"); + builder.AppendLine($" Title ID: {(TitleID == null ? "[NULL]" : BitConverter.ToString(TitleID).Replace('-', ' '))}"); builder.AppendLine($" DSiWare 'public.sav' size: {DSiWarePublicSavSize} (0x{DSiWarePublicSavSize:X})"); builder.AppendLine($" DSiWare 'private.sav' size: {DSiWarePrivateSavSize} (0x{DSiWarePrivateSavSize:X})"); - builder.AppendLine($" Reserved (zero): {BitConverter.ToString(ReservedZero).Replace('-', ' ')}"); - builder.AppendLine($" Unknown 2: {BitConverter.ToString(Unknown2).Replace('-', ' ')}"); - builder.AppendLine($" ARM9 (with encrypted secure area) SHA1 HMAC hash: {BitConverter.ToString(ARM9WithSecureAreaSHA1HMACHash).Replace('-', ' ')}"); - builder.AppendLine($" ARM7 SHA1 HMAC hash: {BitConverter.ToString(ARM7SHA1HMACHash).Replace('-', ' ')}"); - builder.AppendLine($" Digest master SHA1 HMAC hash: {BitConverter.ToString(DigestMasterSHA1HMACHash).Replace('-', ' ')}"); - builder.AppendLine($" Banner SHA1 HMAC hash: {BitConverter.ToString(BannerSHA1HMACHash).Replace('-', ' ')}"); - builder.AppendLine($" ARM9i (decrypted) SHA1 HMAC hash: {BitConverter.ToString(ARM9iDecryptedSHA1HMACHash).Replace('-', ' ')}"); - builder.AppendLine($" ARM7i (decrypted) SHA1 HMAC hash: {BitConverter.ToString(ARM7iDecryptedSHA1HMACHash).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 5: {BitConverter.ToString(Reserved5).Replace('-', ' ')}"); - builder.AppendLine($" ARM9 (without secure area) SHA1 HMAC hash: {BitConverter.ToString(ARM9NoSecureAreaSHA1HMACHash).Replace('-', ' ')}"); - builder.AppendLine($" Reserved 6: {BitConverter.ToString(Reserved6).Replace('-', ' ')}"); - builder.AppendLine($" Reserved and unchecked region: {BitConverter.ToString(ReservedAndUnchecked).Replace('-', ' ')}"); - builder.AppendLine($" RSA signature: {BitConverter.ToString(RSASignature).Replace('-', ' ')}"); + builder.AppendLine($" Reserved (zero): {(ReservedZero == null ? "[NULL]" : BitConverter.ToString(ReservedZero).Replace('-', ' '))}"); + builder.AppendLine($" Unknown 2: {(Unknown2 == null ? "[NULL]" : BitConverter.ToString(Unknown2).Replace('-', ' '))}"); + builder.AppendLine($" ARM9 (with encrypted secure area) SHA1 HMAC hash: {(ARM9WithSecureAreaSHA1HMACHash == null ? "[NULL]" : BitConverter.ToString(ARM9WithSecureAreaSHA1HMACHash).Replace('-', ' '))}"); + builder.AppendLine($" ARM7 SHA1 HMAC hash: {(ARM7SHA1HMACHash == null ? "[NULL]" : BitConverter.ToString(ARM7SHA1HMACHash).Replace('-', ' '))}"); + builder.AppendLine($" Digest master SHA1 HMAC hash: {(DigestMasterSHA1HMACHash == null ? "[NULL]" : BitConverter.ToString(DigestMasterSHA1HMACHash).Replace('-', ' '))}"); + builder.AppendLine($" Banner SHA1 HMAC hash: {(BannerSHA1HMACHash == null ? "[NULL]" : BitConverter.ToString(BannerSHA1HMACHash).Replace('-', ' '))}"); + builder.AppendLine($" ARM9i (decrypted) SHA1 HMAC hash: {(ARM9iDecryptedSHA1HMACHash == null ? "[NULL]" : BitConverter.ToString(ARM9iDecryptedSHA1HMACHash).Replace('-', ' '))}"); + builder.AppendLine($" ARM7i (decrypted) SHA1 HMAC hash: {(ARM7iDecryptedSHA1HMACHash == null ? "[NULL]" : BitConverter.ToString(ARM7iDecryptedSHA1HMACHash).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 5: {(Reserved5 == null ? "[NULL]" : BitConverter.ToString(Reserved5).Replace('-', ' '))}"); + builder.AppendLine($" ARM9 (without secure area) SHA1 HMAC hash: {(ARM9NoSecureAreaSHA1HMACHash == null ? "[NULL]" : BitConverter.ToString(ARM9NoSecureAreaSHA1HMACHash).Replace('-', ' '))}"); + builder.AppendLine($" Reserved 6: {(Reserved6 == null ? "[NULL]" : BitConverter.ToString(Reserved6).Replace('-', ' '))}"); + builder.AppendLine($" Reserved and unchecked region: {(ReservedAndUnchecked == null ? "[NULL]" : BitConverter.ToString(ReservedAndUnchecked).Replace('-', ' '))}"); + builder.AppendLine($" RSA signature: {(RSASignature == null ? "[NULL]" : BitConverter.ToString(RSASignature).Replace('-', ' '))}"); } builder.AppendLine(); } @@ -545,7 +653,7 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" Secure Area Information:"); builder.AppendLine(" -------------------------"); - builder.AppendLine($" {BitConverter.ToString(SecureArea).Replace('-', ' ')}"); + builder.AppendLine($" {(SecureArea == null ? "[NULL]" : BitConverter.ToString(SecureArea).Replace('-', ' '))}"); builder.AppendLine(); } diff --git a/BinaryObjectScanner.Wrappers/PAK.cs b/BinaryObjectScanner.Wrappers/PAK.cs index 7a01c087..6dad1af2 100644 --- a/BinaryObjectScanner.Wrappers/PAK.cs +++ b/BinaryObjectScanner.Wrappers/PAK.cs @@ -17,7 +17,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Signature => _model.Header.Signature; +#else + public string? Signature => _model.Header.Signature; +#endif /// public uint DirectoryOffset => _model.Header.DirectoryOffset; @@ -76,7 +80,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the PAK /// Offset within the array to parse /// A PAK wrapper on success, null on failure +#if NET48 public static PAK Create(byte[] data, int offset) +#else + public static PAK? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -96,7 +104,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the PAK /// A PAK wrapper on success, null on failure +#if NET48 public static PAK Create(Stream data) +#else + public static PAK? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -229,20 +241,36 @@ namespace BinaryObjectScanner.Wrappers return false; // Read the item data +#if NET48 byte[] data = ReadFromDataSource((int)directoryItem.ItemOffset, (int)directoryItem.ItemLength); +#else + byte[] data = ReadFromDataSource((int)directoryItem.ItemOffset, (int)directoryItem.ItemLength); +#endif + if (data == null) + return false; // Create the filename +#if NET48 string filename = directoryItem.ItemName; +#else + string? filename = directoryItem.ItemName; +#endif // If we have an invalid output directory if (string.IsNullOrWhiteSpace(outputDirectory)) return false; // Create the full output path - filename = Path.Combine(outputDirectory, filename); + filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try diff --git a/BinaryObjectScanner.Wrappers/PFF.cs b/BinaryObjectScanner.Wrappers/PFF.cs index 44f23f24..af4eda5f 100644 --- a/BinaryObjectScanner.Wrappers/PFF.cs +++ b/BinaryObjectScanner.Wrappers/PFF.cs @@ -20,7 +20,11 @@ namespace BinaryObjectScanner.Wrappers public uint HeaderSize => _model.Header.HeaderSize; /// +#if NET48 public string Signature => _model.Header.Signature; +#else + public string? Signature => _model.Header.Signature; +#endif /// public uint NumberOfFiles => _model.Header.NumberOfFiles; @@ -53,7 +57,11 @@ namespace BinaryObjectScanner.Wrappers public uint Reserved => _model.Footer.Reserved; /// +#if NET48 public string KingTag => _model.Footer.KingTag; +#else + public string? KingTag => _model.Footer.KingTag; +#endif #endregion @@ -82,12 +90,16 @@ namespace BinaryObjectScanner.Wrappers { // All logic is handled by the base class }/// - /// Create a PFF archive from a byte array and offset - /// - /// Byte array representing the archive - /// Offset within the array to parse - /// A PFF archive wrapper on success, null on failure + /// Create a PFF archive from a byte array and offset + /// + /// Byte array representing the archive + /// Offset within the array to parse + /// A PFF archive wrapper on success, null on failure +#if NET48 public static PFF Create(byte[] data, int offset) +#else + public static PFF? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -107,7 +119,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A PFF archive wrapper on success, null on failure +#if NET48 public static PFF Create(Stream data) +#else + public static PFF? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -181,11 +197,17 @@ namespace BinaryObjectScanner.Wrappers Directory.CreateDirectory(outputDirectory); // Create the output path - string filePath = Path.Combine(outputDirectory, file.FileName); + string filePath = Path.Combine(outputDirectory, file.FileName ?? $"file{index}"); using (FileStream fs = File.OpenWrite(filePath)) { // Read the data block +#if NET48 byte[] data = ReadFromDataSource(offset, size); +#else + byte[]? data = ReadFromDataSource(offset, size); +#endif + if (data == null) + return false; // Write the data -- TODO: Compressed data? fs.Write(data, 0, size); diff --git a/BinaryObjectScanner.Wrappers/PlayJAudioFile.cs b/BinaryObjectScanner.Wrappers/PlayJAudioFile.cs index 312d21cb..80ee916f 100644 --- a/BinaryObjectScanner.Wrappers/PlayJAudioFile.cs +++ b/BinaryObjectScanner.Wrappers/PlayJAudioFile.cs @@ -134,43 +134,71 @@ namespace BinaryObjectScanner.Wrappers public ushort TrackLength => _model.Header.TrackLength; /// +#if NET48 public string Track => _model.Header.Track; +#else + public string? Track => _model.Header.Track; +#endif /// public ushort ArtistLength => _model.Header.ArtistLength; /// +#if NET48 public string Artist => _model.Header.Artist; +#else + public string? Artist => _model.Header.Artist; +#endif /// public ushort AlbumLength => _model.Header.AlbumLength; /// +#if NET48 public string Album => _model.Header.Album; +#else + public string? Album => _model.Header.Album; +#endif /// public ushort WriterLength => _model.Header.WriterLength; /// +#if NET48 public string Writer => _model.Header.Writer; +#else + public string? Writer => _model.Header.Writer; +#endif /// public ushort PublisherLength => _model.Header.PublisherLength; /// +#if NET48 public string Publisher => _model.Header.Publisher; +#else + public string? Publisher => _model.Header.Publisher; +#endif /// public ushort LabelLength => _model.Header.LabelLength; /// +#if NET48 public string Label => _model.Header.Label; +#else + public string? Label => _model.Header.Label; +#endif /// public ushort CommentsLength => _model.Header.CommentsLength; /// +#if NET48 public string Comments => _model.Header.Comments; +#else + public string? Comments => _model.Header.Comments; +#endif #endregion @@ -180,7 +208,11 @@ namespace BinaryObjectScanner.Wrappers public uint UB1_Length => _model.UnknownBlock1.Length; /// +#if NET48 public byte[] UB1_Data => _model.UnknownBlock1.Data; +#else + public byte[]? UB1_Data => _model.UnknownBlock1.Data; +#endif #endregion @@ -196,7 +228,11 @@ namespace BinaryObjectScanner.Wrappers #region Unknown Block 3 /// +#if NET48 public byte[] UB3_Data => _model.UnknownBlock3.Data; +#else + public byte[]? UB3_Data => _model.UnknownBlock3.Data; +#endif #endregion @@ -256,7 +292,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// A PlayJ audio file wrapper on success, null on failure +#if NET48 public static PlayJAudioFile Create(byte[] data, int offset) +#else + public static PlayJAudioFile? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -276,7 +316,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A PlayJ audio file wrapper on success, null on failure +#if NET48 public static PlayJAudioFile Create(Stream data) +#else + public static PlayJAudioFile? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -404,7 +448,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(" Unknown Block 1 Information:"); builder.AppendLine(" -------------------------"); builder.AppendLine($" Length: {UB1_Length} (0x{UB1_Length:X})"); - builder.AppendLine($" Data: {BitConverter.ToString(UB1_Data ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" Data: {(UB1_Data == null ? "[NULL]" : BitConverter.ToString(UB1_Data).Replace('-', ' '))}"); builder.AppendLine(); } @@ -428,7 +472,7 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" Unknown Block 3 Information:"); builder.AppendLine(" -------------------------"); - builder.AppendLine($" Data: {BitConverter.ToString(UB3_Data ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" Data: {(UB3_Data == null ? "[NULL]" : BitConverter.ToString(UB3_Data).Replace('-', ' '))}"); builder.AppendLine(); } @@ -450,7 +494,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" File name length: {dataFile.FileNameLength} (0x{dataFile.FileNameLength:X})"); builder.AppendLine($" File name: {dataFile.FileName ?? "[NULL]"}"); builder.AppendLine($" Data length: {dataFile.DataLength} (0x{dataFile.DataLength:X})"); - builder.AppendLine($" Data: {BitConverter.ToString(dataFile.Data ?? new byte[0]).Replace('-', ' ')}"); + builder.AppendLine($" Data: {(dataFile.Data == null ? "[NULL]" : BitConverter.ToString(dataFile.Data).Replace('-', ' '))}"); } } builder.AppendLine(); diff --git a/BinaryObjectScanner.Wrappers/PortableExecutable.cs b/BinaryObjectScanner.Wrappers/PortableExecutable.cs index b301c5fe..c104821f 100644 --- a/BinaryObjectScanner.Wrappers/PortableExecutable.cs +++ b/BinaryObjectScanner.Wrappers/PortableExecutable.cs @@ -26,7 +26,11 @@ namespace BinaryObjectScanner.Wrappers #region Standard Fields /// +#if NET48 public string Stub_Magic => _model.Stub.Header.Magic; +#else + public string? Stub_Magic => _model.Stub.Header.Magic; +#endif /// public ushort Stub_LastPageBytes => _model.Stub.Header.LastPageBytes; @@ -72,7 +76,11 @@ namespace BinaryObjectScanner.Wrappers #region PE Extensions /// +#if NET48 public ushort[] Stub_Reserved1 => _model.Stub.Header.Reserved1; +#else + public ushort[]? Stub_Reserved1 => _model.Stub.Header.Reserved1; +#endif /// public ushort Stub_OEMIdentifier => _model.Stub.Header.OEMIdentifier; @@ -81,7 +89,11 @@ namespace BinaryObjectScanner.Wrappers public ushort Stub_OEMInformation => _model.Stub.Header.OEMInformation; /// +#if NET48 public ushort[] Stub_Reserved2 => _model.Stub.Header.Reserved2; +#else + public ushort[]? Stub_Reserved2 => _model.Stub.Header.Reserved2; +#endif /// public uint Stub_NewExeHeaderAddr => _model.Stub.Header.NewExeHeaderAddr; @@ -91,7 +103,11 @@ namespace BinaryObjectScanner.Wrappers #endregion /// +#if NET48 public string Signature => _model.Signature; +#else + public string? Signature => _model.Signature; +#endif #region COFF File Header @@ -233,49 +249,105 @@ namespace BinaryObjectScanner.Wrappers #region Data Directories /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_ExportTable => _model.OptionalHeader.ExportTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_ExportTable => _model.OptionalHeader.ExportTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_ImportTable => _model.OptionalHeader.ImportTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_ImportTable => _model.OptionalHeader.ImportTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_ResourceTable => _model.OptionalHeader.ResourceTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_ResourceTable => _model.OptionalHeader.ResourceTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_ExceptionTable => _model.OptionalHeader.ExceptionTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_ExceptionTable => _model.OptionalHeader.ExceptionTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_CertificateTable => _model.OptionalHeader.CertificateTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_CertificateTable => _model.OptionalHeader.CertificateTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_BaseRelocationTable => _model.OptionalHeader.BaseRelocationTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_BaseRelocationTable => _model.OptionalHeader.BaseRelocationTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_Debug => _model.OptionalHeader.Debug; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_Debug => _model.OptionalHeader.Debug; +#endif /// public ulong OH_Architecture => _model.OptionalHeader.Architecture; /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_GlobalPtr => _model.OptionalHeader.GlobalPtr; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_GlobalPtr => _model.OptionalHeader.GlobalPtr; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_ThreadLocalStorageTable => _model.OptionalHeader.ThreadLocalStorageTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_ThreadLocalStorageTable => _model.OptionalHeader.ThreadLocalStorageTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_LoadConfigTable => _model.OptionalHeader.LoadConfigTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_LoadConfigTable => _model.OptionalHeader.LoadConfigTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_BoundImport => _model.OptionalHeader.BoundImport; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_BoundImport => _model.OptionalHeader.BoundImport; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_ImportAddressTable => _model.OptionalHeader.ImportAddressTable; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_ImportAddressTable => _model.OptionalHeader.ImportAddressTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_DelayImportDescriptor => _model.OptionalHeader.DelayImportDescriptor; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_DelayImportDescriptor => _model.OptionalHeader.DelayImportDescriptor; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DataDirectory OH_CLRRuntimeHeader => _model.OptionalHeader.CLRRuntimeHeader; +#else + public SabreTools.Models.PortableExecutable.DataDirectory? OH_CLRRuntimeHeader => _model.OptionalHeader.CLRRuntimeHeader; +#endif /// public ulong OH_Reserved => _model.OptionalHeader.Reserved; @@ -301,7 +373,11 @@ namespace BinaryObjectScanner.Wrappers #endif /// +#if NET48 public SabreTools.Models.PortableExecutable.COFFStringTable COFFStringTable => _model.COFFStringTable; +#else + public SabreTools.Models.PortableExecutable.COFFStringTable? COFFStringTable => _model.COFFStringTable; +#endif /// #if NET48 @@ -311,7 +387,11 @@ namespace BinaryObjectScanner.Wrappers #endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DelayLoadDirectoryTable DelayLoadDirectoryTable => _model.DelayLoadDirectoryTable; +#else + public SabreTools.Models.PortableExecutable.DelayLoadDirectoryTable? DelayLoadDirectoryTable => _model.DelayLoadDirectoryTable; +#endif #endregion @@ -325,16 +405,32 @@ namespace BinaryObjectScanner.Wrappers #endif /// +#if NET48 public SabreTools.Models.PortableExecutable.DebugTable DebugTable => _model.DebugTable; +#else + public SabreTools.Models.PortableExecutable.DebugTable? DebugTable => _model.DebugTable; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.ExportTable ExportTable => _model.ExportTable; +#else + public SabreTools.Models.PortableExecutable.ExportTable? ExportTable => _model.ExportTable; +#endif /// +#if NET48 public string[] ExportNameTable => _model.ExportTable?.ExportNameTable?.Strings; +#else + public string[]? ExportNameTable => _model.ExportTable?.ExportNameTable?.Strings; +#endif /// +#if NET48 public SabreTools.Models.PortableExecutable.ImportTable ImportTable => _model.ImportTable; +#else + public SabreTools.Models.PortableExecutable.ImportTable? ImportTable => _model.ImportTable; +#endif /// #if NET48 @@ -346,7 +442,11 @@ namespace BinaryObjectScanner.Wrappers : null; /// +#if NET48 public SabreTools.Models.PortableExecutable.ResourceDirectoryTable ResourceDirectoryTable => _model.ResourceDirectoryTable; +#else + public SabreTools.Models.PortableExecutable.ResourceDirectoryTable? ResourceDirectoryTable => _model.ResourceDirectoryTable; +#endif #endregion @@ -357,7 +457,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Header padding data, if it exists /// +#if NET48 public byte[] HeaderPaddingData +#else + public byte[]? HeaderPaddingData +#endif { get { @@ -369,6 +473,10 @@ namespace BinaryObjectScanner.Wrappers // TODO: Don't scan the known header data as well + // If the section table is missing + if (SectionTable == null) + return null; + // Populate the raw header padding data based on the source uint headerStartAddress = Stub_NewExeHeaderAddr; uint firstSectionAddress = SectionTable.Select(s => s.PointerToRawData).Where(s => s != 0).OrderBy(s => s).First(); @@ -384,7 +492,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Header padding strings, if they exist /// +#if NET48 public List HeaderPaddingStrings +#else + public List? HeaderPaddingStrings +#endif { get { @@ -396,6 +508,10 @@ namespace BinaryObjectScanner.Wrappers // TODO: Don't scan the known header data as well + // If the section table is missing + if (SectionTable == null) + return null; + // Populate the raw header padding data based on the source uint headerStartAddress = Stub_NewExeHeaderAddr; uint firstSectionAddress = SectionTable.Select(s => s.PointerToRawData).Where(s => s != 0).OrderBy(s => s).First(); @@ -411,12 +527,20 @@ namespace BinaryObjectScanner.Wrappers /// /// Entry point data, if it exists /// +#if NET48 public byte[] EntryPointData +#else + public byte[]? EntryPointData +#endif { get { lock (_sourceDataLock) { + // If the section table is missing + if (SectionTable == null) + return null; + // If we have no entry point int entryPointAddress = (int)OH_AddressOfEntryPoint.ConvertVirtualAddress(SectionTable); if (entryPointAddress == 0) @@ -459,11 +583,15 @@ namespace BinaryObjectScanner.Wrappers if (endOfFile == -1) return -1; + // If the section table is missing + if (SectionTable == null) + return -1; + // If we have certificate data, use that as the end if (OH_CertificateTable != null) { var certificateTable = _model.OptionalHeader.CertificateTable; - int certificateTableAddress = (int)certificateTable.VirtualAddress.ConvertVirtualAddress(_model.SectionTable); + int certificateTableAddress = (int)certificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable); if (certificateTableAddress != 0 && certificateTableAddress < endOfFile) endOfFile = certificateTableAddress; } @@ -508,7 +636,11 @@ namespace BinaryObjectScanner.Wrappers /// Overlay data, if it exists /// /// +#if NET48 public byte[] OverlayData +#else + public byte[]? OverlayData +#endif { get { @@ -523,11 +655,15 @@ namespace BinaryObjectScanner.Wrappers if (endOfFile == -1) return null; + // If the section table is missing + if (SectionTable == null) + return null; + // If we have certificate data, use that as the end if (OH_CertificateTable != null) { var certificateTable = _model.OptionalHeader.CertificateTable; - int certificateTableAddress = (int)certificateTable.VirtualAddress.ConvertVirtualAddress(_model.SectionTable); + int certificateTableAddress = (int)certificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable); if (certificateTableAddress != 0 && certificateTableAddress < endOfFile) endOfFile = certificateTableAddress; } @@ -579,7 +715,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Overlay strings, if they exist /// +#if NET48 public List OverlayStrings +#else + public List? OverlayStrings +#endif { get { @@ -594,11 +734,15 @@ namespace BinaryObjectScanner.Wrappers if (endOfFile == -1) return null; + // If the section table is missing + if (SectionTable == null) + return null; + // If we have certificate data, use that as the end if (OH_CertificateTable != null) { var certificateTable = _model.OptionalHeader.CertificateTable; - int certificateTableAddress = (int)certificateTable.VirtualAddress.ConvertVirtualAddress(_model.SectionTable); + int certificateTableAddress = (int)certificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable); if (certificateTableAddress != 0 && certificateTableAddress < endOfFile) endOfFile = certificateTableAddress; } @@ -650,7 +794,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Sanitized section names /// +#if NET48 public string[] SectionNames +#else + public string[]? SectionNames +#endif { get { @@ -667,9 +815,16 @@ namespace BinaryObjectScanner.Wrappers var section = _model.SectionTable[i]; // TODO: Handle long section names with leading `/` +#if NET48 byte[] sectionNameBytes = section.Name; - string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0'); - _sectionNames[i] = sectionNameString; +#else + byte[]? sectionNameBytes = section.Name; +#endif + if (sectionNameBytes != null) + { + string sectionNameString = Encoding.UTF8.GetString(sectionNameBytes).TrimEnd('\0'); + _sectionNames[i] = sectionNameString; + } } return _sectionNames; @@ -680,7 +835,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stub executable data, if it exists /// +#if NET48 public byte[] StubExecutableData +#else + public byte[]? StubExecutableData +#endif { get { @@ -704,7 +863,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Dictionary of debug data /// +#if NET48 public Dictionary DebugData +#else + public Dictionary? DebugData +#endif { get { @@ -729,7 +892,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Dictionary of resource data /// +#if NET48 public Dictionary ResourceData +#else + public Dictionary? ResourceData +#endif { get { @@ -756,115 +923,191 @@ namespace BinaryObjectScanner.Wrappers /// /// "Build GUID" - /// + /// +#if NET48 public string BuildGuid => GetVersionInfoString("BuildGuid"); +#else + public string? BuildGuid => GetVersionInfoString("BuildGuid"); +#endif /// /// "Build signature" - /// + /// +#if NET48 public string BuildSignature => GetVersionInfoString("BuildSignature"); +#else + public string? BuildSignature => GetVersionInfoString("BuildSignature"); +#endif /// /// Additional information that should be displayed for diagnostic purposes. - /// + /// +#if NET48 public string Comments => GetVersionInfoString("Comments"); +#else + public string? Comments => GetVersionInfoString("Comments"); +#endif /// /// Company that produced the file—for example, "Microsoft Corporation" or /// "Standard Microsystems Corporation, Inc." This string is required. - /// + /// +#if NET48 public string CompanyName => GetVersionInfoString("CompanyName"); +#else + public string? CompanyName => GetVersionInfoString("CompanyName"); +#endif /// /// "Debug version" - /// + /// +#if NET48 public string DebugVersion => GetVersionInfoString("DebugVersion"); +#else + public string? DebugVersion => GetVersionInfoString("DebugVersion"); +#endif /// /// File description to be presented to users. This string may be displayed in a /// list box when the user is choosing files to install—for example, "Keyboard /// Driver for AT-Style Keyboards". This string is required. - /// + /// +#if NET48 public string FileDescription => GetVersionInfoString("FileDescription"); +#else + public string? FileDescription => GetVersionInfoString("FileDescription"); +#endif /// /// Version number of the file—for example, "3.10" or "5.00.RC2". This string /// is required. - /// + /// +#if NET48 public string FileVersion => GetVersionInfoString("FileVersion"); +#else + public string? FileVersion => GetVersionInfoString("FileVersion"); +#endif /// /// Internal name of the file, if one exists—for example, a module name if the /// file is a dynamic-link library. If the file has no internal name, this /// string should be the original filename, without extension. This string is required. - /// + /// +#if NET48 public string InternalName => GetVersionInfoString(key: "InternalName"); +#else + public string? InternalName => GetVersionInfoString(key: "InternalName"); +#endif /// /// Copyright notices that apply to the file. This should include the full text of /// all notices, legal symbols, copyright dates, and so on. This string is optional. - /// + /// +#if NET48 public string LegalCopyright => GetVersionInfoString(key: "LegalCopyright"); +#else + public string? LegalCopyright => GetVersionInfoString(key: "LegalCopyright"); +#endif /// /// Trademarks and registered trademarks that apply to the file. This should include /// the full text of all notices, legal symbols, trademark numbers, and so on. This /// string is optional. - /// + /// +#if NET48 public string LegalTrademarks => GetVersionInfoString(key: "LegalTrademarks"); +#else + public string? LegalTrademarks => GetVersionInfoString(key: "LegalTrademarks"); +#endif /// /// Original name of the file, not including a path. This information enables an /// application to determine whether a file has been renamed by a user. The format of /// the name depends on the file system for which the file was created. This string /// is required. - /// + /// +#if NET48 public string OriginalFilename => GetVersionInfoString(key: "OriginalFilename"); +#else + public string? OriginalFilename => GetVersionInfoString(key: "OriginalFilename"); +#endif /// /// Information about a private version of the file—for example, "Built by TESTER1 on /// \TESTBED". This string should be present only if VS_FF_PRIVATEBUILD is specified in /// the fileflags parameter of the root block. - /// + /// +#if NET48 public string PrivateBuild => GetVersionInfoString(key: "PrivateBuild"); +#else + public string? PrivateBuild => GetVersionInfoString(key: "PrivateBuild"); +#endif /// /// "Product GUID" - /// + /// +#if NET48 public string ProductGuid => GetVersionInfoString("ProductGuid"); +#else + public string? ProductGuid => GetVersionInfoString("ProductGuid"); +#endif /// /// Name of the product with which the file is distributed. This string is required. - /// + /// +#if NET48 public string ProductName => GetVersionInfoString(key: "ProductName"); +#else + public string? ProductName => GetVersionInfoString(key: "ProductName"); +#endif /// /// Version of the product with which the file is distributed—for example, "3.10" or /// "5.00.RC2". This string is required. - /// + /// +#if NET48 public string ProductVersion => GetVersionInfoString(key: "ProductVersion"); +#else + public string? ProductVersion => GetVersionInfoString(key: "ProductVersion"); +#endif /// /// Text that specifies how this version of the file differs from the standard /// version—for example, "Private build for TESTER1 solving mouse problems on M250 and /// M250E computers". This string should be present only if VS_FF_SPECIALBUILD is /// specified in the fileflags parameter of the root block. - /// + /// +#if NET48 public string SpecialBuild => GetVersionInfoString(key: "SpecialBuild") ?? GetVersionInfoString(key: "Special Build"); +#else + public string? SpecialBuild => GetVersionInfoString(key: "SpecialBuild") ?? GetVersionInfoString(key: "Special Build"); +#endif /// /// "Trade name" - /// + /// +#if NET48 public string TradeName => GetVersionInfoString(key: "TradeName"); +#else + public string? TradeName => GetVersionInfoString(key: "TradeName"); +#endif /// /// Get the internal version as reported by the resources /// /// Version string, null on error /// The internal version is either the file version, product version, or assembly version, in that order +#if NET48 public string GetInternalVersion() +#else + public string? GetInternalVersion() +#endif { +#if NET48 string version = this.FileVersion; +#else + string? version = this.FileVersion; +#endif if (!string.IsNullOrWhiteSpace(version)) return version.Replace(", ", "."); @@ -886,7 +1129,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Description as derived from the assembly manifest /// +#if NET48 public string AssemblyDescription +#else + public string? AssemblyDescription +#endif { get { @@ -905,7 +1152,11 @@ namespace BinaryObjectScanner.Wrappers /// this will only retrieve the value from the first that doesn't /// have a null or empty version. /// +#if NET48 public string AssemblyVersion +#else + public string? AssemblyVersion +#endif { get { @@ -926,17 +1177,29 @@ namespace BinaryObjectScanner.Wrappers /// /// Header padding data, if it exists /// +#if NET48 private byte[] _headerPaddingData = null; +#else + private byte[]? _headerPaddingData = null; +#endif /// /// Header padding strings, if they exist /// +#if NET48 private List _headerPaddingStrings = null; +#else + private List? _headerPaddingStrings = null; +#endif /// /// Entry point data, if it exists and isn't aligned to a section /// +#if NET48 private byte[] _entryPointData = null; +#else + private byte[]? _entryPointData = null; +#endif /// /// Address of the overlay, if it exists @@ -946,42 +1209,74 @@ namespace BinaryObjectScanner.Wrappers /// /// Overlay data, if it exists /// +#if NET48 private byte[] _overlayData = null; +#else + private byte[]? _overlayData = null; +#endif /// /// Overlay strings, if they exist /// +#if NET48 private List _overlayStrings = null; +#else + private List? _overlayStrings = null; +#endif /// /// Stub executable data, if it exists /// +#if NET48 private byte[] _stubExecutableData = null; +#else + private byte[]? _stubExecutableData = null; +#endif /// /// Sanitized section names /// +#if NET48 private string[] _sectionNames = null; +#else + private string[]? _sectionNames = null; +#endif /// /// Cached raw section data /// +#if NET48 private byte[][] _sectionData = null; +#else + private byte[]?[]? _sectionData = null; +#endif /// /// Cached found string data in sections /// +#if NET48 private List[] _sectionStringData = null; +#else + private List?[]? _sectionStringData = null; +#endif /// /// Cached raw table data /// +#if NET48 private byte[][] _tableData = null; +#else + private byte[]?[]? _tableData = null; +#endif /// /// Cached found string data in tables /// +#if NET48 private List[] _tableStringData = null; +#else + private List?[]? _tableStringData = null; +#endif /// /// Cached debug data @@ -991,17 +1286,29 @@ namespace BinaryObjectScanner.Wrappers /// /// Cached resource data /// +#if NET48 private readonly Dictionary _resourceData = new Dictionary(); +#else + private readonly Dictionary _resourceData = new Dictionary(); +#endif /// /// Cached version info data /// +#if NET48 private SabreTools.Models.PortableExecutable.VersionInfo _versionInfo = null; +#else + private SabreTools.Models.PortableExecutable.VersionInfo? _versionInfo = null; +#endif /// /// Cached assembly manifest data /// +#if NET48 private SabreTools.Models.PortableExecutable.AssemblyManifest _assemblyManifest = null; +#else + private SabreTools.Models.PortableExecutable.AssemblyManifest? _assemblyManifest = null; +#endif /// /// Lock object for reading from the source @@ -1040,7 +1347,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the executable /// Offset within the array to parse /// A PE executable wrapper on success, null on failure +#if NET48 public static PortableExecutable Create(byte[] data, int offset) +#else + public static PortableExecutable? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -1060,7 +1371,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the executable /// A PE executable wrapper on success, null on failure +#if NET48 public static PortableExecutable Create(Stream data) +#else + public static PortableExecutable? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -1096,7 +1411,11 @@ namespace BinaryObjectScanner.Wrappers /// the first available value. This may not actually matter for version info, /// but it is worth mentioning. /// +#if NET48 public string GetVersionInfoString(string key) +#else + public string? GetVersionInfoString(string key) +#endif { // If we have an invalid key, we can't do anything if (string.IsNullOrEmpty(key)) @@ -1113,8 +1432,8 @@ namespace BinaryObjectScanner.Wrappers // Try to find a key that matches var match = stringTable - .SelectMany(st => st.Children) - .FirstOrDefault(sd => key.Equals(sd.Key, StringComparison.OrdinalIgnoreCase)); + .SelectMany(st => st?.Children ?? Array.Empty()) + .FirstOrDefault(sd => sd != null && key.Equals(sd.Key, StringComparison.OrdinalIgnoreCase)); // Return either the match or null return match?.Value?.TrimEnd('\0'); @@ -1124,7 +1443,11 @@ namespace BinaryObjectScanner.Wrappers /// Get the assembly manifest, if possible /// /// Assembly manifest object, null on error +#if NET48 private SabreTools.Models.PortableExecutable.AssemblyManifest GetAssemblyManifest() +#else + private SabreTools.Models.PortableExecutable.AssemblyManifest? GetAssemblyManifest() +#endif { // Use the cached data if possible if (_assemblyManifest != null) @@ -1208,10 +1531,10 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" MS-DOS Stub Extended Header Information:"); builder.AppendLine(" -------------------------"); - builder.AppendLine($" Reserved words: {string.Join(", ", Stub_Reserved1)}"); + builder.AppendLine($" Reserved words: {(Stub_Reserved1 == null ? "[NULL]" : string.Join(", ", Stub_Reserved1))}"); builder.AppendLine($" OEM identifier: {Stub_OEMIdentifier} (0x{Stub_OEMIdentifier:X})"); builder.AppendLine($" OEM information: {Stub_OEMInformation} (0x{Stub_OEMInformation:X})"); - builder.AppendLine($" Reserved words: {string.Join(", ", Stub_Reserved2)}"); + builder.AppendLine($" Reserved words: {(Stub_Reserved2 == null ? "[NULL]" : string.Join(", ", Stub_Reserved2))}"); builder.AppendLine($" New EXE header address: {Stub_NewExeHeaderAddr} (0x{Stub_NewExeHeaderAddr:X})"); builder.AppendLine(); } @@ -1286,49 +1609,49 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" Export Table (1)"); builder.AppendLine($" Virtual address: {OH_ExportTable.VirtualAddress} (0x{OH_ExportTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_ExportTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_ExportTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_ExportTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_ExportTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_ExportTable.Size} (0x{OH_ExportTable.Size:X})"); } if (OH_ImportTable != null) { builder.AppendLine(" Import Table (2)"); builder.AppendLine($" Virtual address: {OH_ImportTable.VirtualAddress} (0x{OH_ImportTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_ImportTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_ImportTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_ImportTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_ImportTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_ImportTable.Size} (0x{OH_ImportTable.Size:X})"); } if (OH_ResourceTable != null) { builder.AppendLine(" Resource Table (3)"); builder.AppendLine($" Virtual address: {OH_ResourceTable.VirtualAddress} (0x{OH_ResourceTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_ResourceTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_ResourceTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_ResourceTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_ResourceTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_ResourceTable.Size} (0x{OH_ResourceTable.Size:X})"); } if (OH_ExceptionTable != null) { builder.AppendLine(" Exception Table (4)"); builder.AppendLine($" Virtual address: {OH_ExceptionTable.VirtualAddress} (0x{OH_ExceptionTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_ExceptionTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_ExceptionTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_ExceptionTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_ExceptionTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_ExceptionTable.Size} (0x{OH_ExceptionTable.Size:X})"); } if (OH_CertificateTable != null) { builder.AppendLine(" Certificate Table (5)"); builder.AppendLine($" Virtual address: {OH_CertificateTable.VirtualAddress} (0x{OH_CertificateTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_CertificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_CertificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_CertificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_CertificateTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_CertificateTable.Size} (0x{OH_CertificateTable.Size:X})"); } if (OH_BaseRelocationTable != null) { builder.AppendLine(" Base Relocation Table (6)"); builder.AppendLine($" Virtual address: {OH_BaseRelocationTable.VirtualAddress} (0x{OH_BaseRelocationTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_BaseRelocationTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_BaseRelocationTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_BaseRelocationTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_BaseRelocationTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_BaseRelocationTable.Size} (0x{OH_BaseRelocationTable.Size:X})"); } if (OH_Debug != null) { builder.AppendLine(" Debug Table (7)"); builder.AppendLine($" Virtual address: {OH_Debug.VirtualAddress} (0x{OH_Debug.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_Debug.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_Debug.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_Debug.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_Debug.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_Debug.Size} (0x{OH_Debug.Size:X})"); } if (OH_NumberOfRvaAndSizes >= 8) @@ -1342,49 +1665,49 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" Global Pointer Register (9)"); builder.AppendLine($" Virtual address: {OH_GlobalPtr.VirtualAddress} (0x{OH_GlobalPtr.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_GlobalPtr.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_GlobalPtr.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_GlobalPtr.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_GlobalPtr.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_GlobalPtr.Size} (0x{OH_GlobalPtr.Size:X})"); } if (OH_ThreadLocalStorageTable != null) { builder.AppendLine(" Thread Local Storage (TLS) Table (10)"); builder.AppendLine($" Virtual address: {OH_ThreadLocalStorageTable.VirtualAddress} (0x{OH_ThreadLocalStorageTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_ThreadLocalStorageTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_ThreadLocalStorageTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_ThreadLocalStorageTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_ThreadLocalStorageTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_ThreadLocalStorageTable.Size} (0x{OH_ThreadLocalStorageTable.Size:X})"); } if (OH_LoadConfigTable != null) { builder.AppendLine(" Load Config Table (11)"); builder.AppendLine($" Virtual address: {OH_LoadConfigTable.VirtualAddress} (0x{OH_LoadConfigTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_LoadConfigTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_LoadConfigTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_LoadConfigTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_LoadConfigTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_LoadConfigTable.Size} (0x{OH_LoadConfigTable.Size:X})"); } if (OH_BoundImport != null) { builder.AppendLine(" Bound Import Table (12)"); builder.AppendLine($" Virtual address: {OH_BoundImport.VirtualAddress} (0x{OH_BoundImport.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_BoundImport.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_BoundImport.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_BoundImport.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_BoundImport.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_BoundImport.Size} (0x{OH_BoundImport.Size:X})"); } if (OH_ImportAddressTable != null) { builder.AppendLine(" Import Address Table (13)"); builder.AppendLine($" Virtual address: {OH_ImportAddressTable.VirtualAddress} (0x{OH_ImportAddressTable.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_ImportAddressTable.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_ImportAddressTable.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_ImportAddressTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_ImportAddressTable.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_ImportAddressTable.Size} (0x{OH_ImportAddressTable.Size:X})"); } if (OH_DelayImportDescriptor != null) { builder.AppendLine(" Delay Import Descriptior (14)"); builder.AppendLine($" Virtual address: {OH_DelayImportDescriptor.VirtualAddress} (0x{OH_DelayImportDescriptor.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_DelayImportDescriptor.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_DelayImportDescriptor.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_DelayImportDescriptor.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_DelayImportDescriptor.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_DelayImportDescriptor.Size} (0x{OH_DelayImportDescriptor.Size:X})"); } if (OH_CLRRuntimeHeader != null) { builder.AppendLine(" CLR Runtime Header (15)"); builder.AppendLine($" Virtual address: {OH_CLRRuntimeHeader.VirtualAddress} (0x{OH_CLRRuntimeHeader.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {OH_CLRRuntimeHeader.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{OH_CLRRuntimeHeader.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {OH_CLRRuntimeHeader.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{OH_CLRRuntimeHeader.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size: {OH_CLRRuntimeHeader.Size} (0x{OH_CLRRuntimeHeader.Size:X})"); } if (OH_NumberOfRvaAndSizes >= 16) @@ -1416,10 +1739,10 @@ namespace BinaryObjectScanner.Wrappers { var entry = SectionTable[i]; builder.AppendLine($" Section Table Entry {i}"); - builder.AppendLine($" Name: {Encoding.UTF8.GetString(entry.Name).TrimEnd('\0')}"); + builder.AppendLine($" Name: {(entry.Name == null ? "[NULL]" : Encoding.UTF8.GetString(entry.Name).TrimEnd('\0'))}"); builder.AppendLine($" Virtual size: {entry.VirtualSize} (0x{entry.VirtualSize:X})"); builder.AppendLine($" Virtual address: {entry.VirtualAddress} (0x{entry.VirtualAddress:X})"); - builder.AppendLine($" Physical address: {entry.VirtualAddress.ConvertVirtualAddress(SectionTable)} (0x{entry.VirtualAddress.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Physical address: {entry.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{entry.VirtualAddress.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Size of raw data: {entry.SizeOfRawData} (0x{entry.SizeOfRawData:X})"); builder.AppendLine($" Pointer to raw data: {entry.PointerToRawData} (0x{entry.PointerToRawData:X})"); builder.AppendLine($" Pointer to relocations: {entry.PointerToRelocations} (0x{entry.PointerToRelocations:X})"); @@ -1462,7 +1785,7 @@ namespace BinaryObjectScanner.Wrappers { if (entry.ShortName != null) { - builder.AppendLine($" Short name: {Encoding.UTF8.GetString(entry.ShortName).TrimEnd('\0')}"); + builder.AppendLine($" Short name: {(entry.ShortName == null ? "[NULL]" : Encoding.UTF8.GetString(entry.ShortName).TrimEnd('\0'))}"); } else { @@ -1535,12 +1858,12 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine($" Tag index: {entry.AuxFormat3TagIndex} (0x{entry.AuxFormat3TagIndex:X})"); builder.AppendLine($" Characteristics: {entry.AuxFormat3Characteristics} (0x{entry.AuxFormat3Characteristics:X})"); - builder.AppendLine($" Unused: {BitConverter.ToString(entry.AuxFormat3Unused).Replace("-", string.Empty)}"); + builder.AppendLine($" Unused: {(entry.AuxFormat3Unused == null ? "[NULL]" : BitConverter.ToString(entry.AuxFormat3Unused).Replace("-", string.Empty))}"); auxSymbolsRemaining--; } else if (currentSymbolType == 4) { - builder.AppendLine($" File name: {Encoding.ASCII.GetString(entry.AuxFormat4FileName).TrimEnd('\0')}"); + builder.AppendLine($" File name: {(entry.AuxFormat4FileName == null ? "[NULL]" : Encoding.ASCII.GetString(entry.AuxFormat4FileName).TrimEnd('\0'))}"); auxSymbolsRemaining--; } else if (currentSymbolType == 5) @@ -1551,7 +1874,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Checksum: {entry.AuxFormat5CheckSum} (0x{entry.AuxFormat5CheckSum:X})"); builder.AppendLine($" Number: {entry.AuxFormat5Number} (0x{entry.AuxFormat5Number:X})"); builder.AppendLine($" Selection: {entry.AuxFormat5Selection} (0x{entry.AuxFormat5Selection:X})"); - builder.AppendLine($" Unused: {BitConverter.ToString(entry.AuxFormat5Unused).Replace("-", string.Empty)}"); + builder.AppendLine($" Unused: {(entry.AuxFormat5Unused == null ? "[NULL]" : BitConverter.ToString(entry.AuxFormat5Unused).Replace("-", string.Empty))}"); auxSymbolsRemaining--; } else if (currentSymbolType == 6) @@ -1559,7 +1882,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Aux type: {entry.AuxFormat6AuxType} (0x{entry.AuxFormat6AuxType:X})"); builder.AppendLine($" Reserved: {entry.AuxFormat6Reserved1} (0x{entry.AuxFormat6Reserved1:X})"); builder.AppendLine($" Symbol table index: {entry.AuxFormat6SymbolTableIndex} (0x{entry.AuxFormat6SymbolTableIndex:X})"); - builder.AppendLine($" Reserved: {BitConverter.ToString(entry.AuxFormat6Reserved2).Replace("-", string.Empty)}"); + builder.AppendLine($" Reserved: {(entry.AuxFormat6Reserved2 == null ? "[NULL]" : BitConverter.ToString(entry.AuxFormat6Reserved2).Replace("-", string.Empty))}"); auxSymbolsRemaining--; } @@ -1601,6 +1924,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(" -------------------------"); if (OH_CertificateTable == null || OH_CertificateTable.VirtualAddress == 0 + || AttributeCertificateTable == null || AttributeCertificateTable.Length == 0) { builder.AppendLine(" No attribute certificate table items"); @@ -1611,6 +1935,12 @@ namespace BinaryObjectScanner.Wrappers { var entry = AttributeCertificateTable[i]; builder.AppendLine($" Attribute Certificate Table Entry {i}"); + if (entry == null) + { + builder.AppendLine($" [NULL]"); + continue; + } + builder.AppendLine($" Length: {entry.Length} (0x{entry.Length:X})"); builder.AppendLine($" Revision: {entry.Revision} (0x{entry.Revision:X})"); builder.AppendLine($" Certificate type: {entry.CertificateType} (0x{entry.CertificateType:X})"); @@ -1619,18 +1949,25 @@ namespace BinaryObjectScanner.Wrappers { builder.AppendLine(" Certificate Data [Formatted]"); builder.AppendLine(" -------------------------"); - var topLevelValues = AbstractSyntaxNotationOne.Parse(entry.Certificate, pointer: 0); - if (topLevelValues == null) + if (entry.Certificate == null) { builder.AppendLine(" INVALID DATA FOUND"); - builder.AppendLine($" {BitConverter.ToString(entry.Certificate).Replace("-", string.Empty)}"); } else { - foreach (TypeLengthValue tlv in topLevelValues) + var topLevelValues = AbstractSyntaxNotationOne.Parse(entry.Certificate, 0); + if (topLevelValues == null) { - string tlvString = tlv.Format(paddingLevel: 4); - builder.AppendLine(tlvString); + builder.AppendLine(" INVALID DATA FOUND"); + builder.AppendLine($" {(entry.Certificate == null ? "[NULL]" : BitConverter.ToString(entry.Certificate).Replace("-", string.Empty))}"); + } + else + { + foreach (TypeLengthValue tlv in topLevelValues) + { + string tlvString = tlv.Format(paddingLevel: 4); + builder.AppendLine(tlvString); + } } } } @@ -1640,7 +1977,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine(" -------------------------"); try { - builder.AppendLine($" {BitConverter.ToString(entry.Certificate).Replace("-", string.Empty)}"); + builder.AppendLine($" {(entry.Certificate == null ? "[NULL]" : BitConverter.ToString(entry.Certificate).Replace("-", string.Empty))}"); } catch { @@ -1703,7 +2040,7 @@ namespace BinaryObjectScanner.Wrappers var baseRelocationTableEntry = BaseRelocationTable[i]; builder.AppendLine($" Base Relocation Table Entry {i}"); builder.AppendLine($" Page RVA: {baseRelocationTableEntry.PageRVA} (0x{baseRelocationTableEntry.PageRVA:X})"); - builder.AppendLine($" Page physical address: {baseRelocationTableEntry.PageRVA.ConvertVirtualAddress(SectionTable)} (0x{baseRelocationTableEntry.PageRVA.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Page physical address: {baseRelocationTableEntry.PageRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{baseRelocationTableEntry.PageRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Block size: {baseRelocationTableEntry.BlockSize} (0x{baseRelocationTableEntry.BlockSize:X})"); builder.AppendLine($" Base Relocation Table {i} Type and Offset Information:"); @@ -1894,13 +2231,13 @@ namespace BinaryObjectScanner.Wrappers var importDirectoryTableEntry = ImportTable.ImportDirectoryTable[i]; builder.AppendLine($" Import Directory Table Entry {i}"); builder.AppendLine($" Import lookup table RVA: {importDirectoryTableEntry.ImportLookupTableRVA} (0x{importDirectoryTableEntry.ImportLookupTableRVA:X})"); - builder.AppendLine($" Import lookup table Physical Address: {importDirectoryTableEntry.ImportLookupTableRVA.ConvertVirtualAddress(SectionTable)} (0x{importDirectoryTableEntry.ImportLookupTableRVA.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Import lookup table Physical Address: {importDirectoryTableEntry.ImportLookupTableRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{importDirectoryTableEntry.ImportLookupTableRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); builder.AppendLine($" Time/Date stamp: {importDirectoryTableEntry.TimeDateStamp} (0x{importDirectoryTableEntry.TimeDateStamp:X})"); builder.AppendLine($" Forwarder chain: {importDirectoryTableEntry.ForwarderChain} (0x{importDirectoryTableEntry.ForwarderChain:X})"); builder.AppendLine($" Name RVA: {importDirectoryTableEntry.NameRVA} (0x{importDirectoryTableEntry.NameRVA:X})"); builder.AppendLine($" Name: {importDirectoryTableEntry.Name}"); builder.AppendLine($" Import address table RVA: {importDirectoryTableEntry.ImportAddressTableRVA} (0x{importDirectoryTableEntry.ImportAddressTableRVA:X})"); - builder.AppendLine($" Import address table Physical Address: {importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(SectionTable)} (0x{importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Import address table Physical Address: {importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{importDirectoryTableEntry.ImportAddressTableRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); } } builder.AppendLine(); @@ -1939,7 +2276,7 @@ namespace BinaryObjectScanner.Wrappers else { builder.AppendLine($" Hint/Name table RVA: {importLookupTableEntry.HintNameTableRVA} (0x{importLookupTableEntry.HintNameTableRVA:X})"); - builder.AppendLine($" Hint/Name table Physical Address: {importLookupTableEntry.HintNameTableRVA.ConvertVirtualAddress(SectionTable)} (0x{importLookupTableEntry.HintNameTableRVA.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Hint/Name table Physical Address: {importLookupTableEntry.HintNameTableRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{importLookupTableEntry.HintNameTableRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); } } } @@ -1981,7 +2318,7 @@ namespace BinaryObjectScanner.Wrappers else { builder.AppendLine($" Hint/Name table RVA: {importAddressTableEntry.HintNameTableRVA} (0x{importAddressTableEntry.HintNameTableRVA:X})"); - builder.AppendLine($" Hint/Name table Physical Address: {importAddressTableEntry.HintNameTableRVA.ConvertVirtualAddress(SectionTable)} (0x{importAddressTableEntry.HintNameTableRVA.ConvertVirtualAddress(SectionTable):X})"); + builder.AppendLine($" Hint/Name table Physical Address: {importAddressTableEntry.HintNameTableRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty())} (0x{importAddressTableEntry.HintNameTableRVA.ConvertVirtualAddress(SectionTable ?? Array.Empty()):X})"); } } } @@ -2059,9 +2396,12 @@ namespace BinaryObjectScanner.Wrappers for (int i = 0; i < table.Entries.Length; i++) { var entry = table.Entries[i]; + if (entry == null) + continue; + var newTypes = new List(types ?? new List()); - if (entry.Name != null) - newTypes.Add(Encoding.UTF8.GetString(entry.Name.UnicodeString ?? new byte[0])); + if (entry.Name?.UnicodeString != null) + newTypes.Add(Encoding.UTF8.GetString(entry.Name.UnicodeString)); else newTypes.Add(entry.IntegerID); @@ -2082,7 +2422,7 @@ namespace BinaryObjectScanner.Wrappers if (entry.NameOffset != default) { builder.AppendLine($"{padding}Name offset: {entry.NameOffset} (0x{entry.NameOffset:X})"); - builder.AppendLine($"{padding}Name ({entry.Name.Length}): {Encoding.UTF8.GetString(entry.Name.UnicodeString ?? new byte[0])}"); + builder.AppendLine($"{padding}Name ({entry.Name?.Length ?? 0}): {(entry.Name.UnicodeString == null ? "[NULL]" : Encoding.UTF8.GetString(entry.Name.UnicodeString))}"); } else { @@ -2104,7 +2444,7 @@ namespace BinaryObjectScanner.Wrappers string padding = new string(' ', (level + 1) * 2); // TODO: Use ordered list of base types to determine the shape of the data - builder.AppendLine($"{padding}Base types: {string.Join(", ", types)}"); + builder.AppendLine($"{padding}Base types: {(types == null ? "[NULL]" : string.Join(", ", types))}"); builder.AppendLine($"{padding}Entry level: {level}"); builder.AppendLine($"{padding}Data RVA: {entry.DataRVA} (0x{entry.DataRVA:X})"); @@ -2231,7 +2571,11 @@ namespace BinaryObjectScanner.Wrappers { string padding = new string(' ', (level + 1) * 2); +#if NET48 SabreTools.Models.PortableExecutable.MenuResource menu = null; +#else + SabreTools.Models.PortableExecutable.MenuResource? menu = null; +#endif try { menu = entry.AsMenu(); } catch { } if (menu == null) { @@ -2314,7 +2658,11 @@ namespace BinaryObjectScanner.Wrappers { string padding = new string(' ', (level + 1) * 2); +#if NET48 SabreTools.Models.PortableExecutable.DialogBoxResource dialogBox = null; +#else + SabreTools.Models.PortableExecutable.DialogBoxResource? dialogBox = null; +#endif try { dialogBox = entry.AsDialogBox(); } catch { } if (dialogBox == null) { @@ -2367,7 +2715,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($"{padding} Title resource ordinal: {dialogItemTemplate.TitleResourceOrdinal} (0x{dialogItemTemplate.TitleResourceOrdinal:X})"); builder.AppendLine($"{padding} Creation data size: {dialogItemTemplate.CreationDataSize} (0x{dialogItemTemplate.CreationDataSize:X})"); if (dialogItemTemplate.CreationData != null && dialogItemTemplate.CreationData.Length != 0) - builder.AppendLine($"{padding} Creation data: {BitConverter.ToString(dialogItemTemplate.CreationData).Replace("-", string.Empty)}"); + builder.AppendLine($"{padding} Creation data: {(dialogItemTemplate.CreationData == null ? "[NULL]" : BitConverter.ToString(dialogItemTemplate.CreationData).Replace("-", string.Empty))}"); else builder.AppendLine($"{padding} Creation data: [EMPTY]"); } @@ -2424,7 +2772,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($"{padding} Title resource ordinal: {dialogItemTemplate.TitleResourceOrdinal} (0x{dialogItemTemplate.TitleResourceOrdinal:X})"); builder.AppendLine($"{padding} Creation data size: {dialogItemTemplate.CreationDataSize} (0x{dialogItemTemplate.CreationDataSize:X})"); if (dialogItemTemplate.CreationData != null && dialogItemTemplate.CreationData.Length != 0) - builder.AppendLine($"{padding} Creation data: {BitConverter.ToString(dialogItemTemplate.CreationData).Replace("-", string.Empty)}"); + builder.AppendLine($"{padding} Creation data: {(dialogItemTemplate.CreationData == null ? "[NULL]" : BitConverter.ToString(dialogItemTemplate.CreationData).Replace("-", string.Empty))}"); else builder.AppendLine($"{padding} Creation data: [EMPTY]"); } @@ -2491,7 +2839,11 @@ namespace BinaryObjectScanner.Wrappers { string padding = new string(' ', (level + 1) * 2); +#if NET48 SabreTools.Models.PortableExecutable.AcceleratorTableEntry[] acceleratorTable = null; +#else + SabreTools.Models.PortableExecutable.AcceleratorTableEntry[]? acceleratorTable = null; +#endif try { acceleratorTable = entry.AsAcceleratorTableResource(); } catch { } if (acceleratorTable == null) { @@ -2539,10 +2891,10 @@ namespace BinaryObjectScanner.Wrappers } else { - builder.AppendLine($"{padding}Data: {BitConverter.ToString(magic).Replace('-', ' ')} ..."); + builder.AppendLine($"{padding}Data: {(magic == null ? "[NULL]" : BitConverter.ToString(magic).Replace('-', ' '))} ..."); //if (entry.Data != null) - // builder.AppendLine($"{padding}Value (Byte Data): {BitConverter.ToString(entry.Data).Replace('-', ' ')}"); + // builder.AppendLine($"{padding}Value (Byte Data): {(entry.Data == null ? "[NULL]" : BitConverter.ToString(entry.Data).Replace('-', ' '))}"); //if (entry.Data != null) // builder.AppendLine($"{padding}Value (ASCII): {Encoding.ASCII.GetString(entry.Data)}"); //if (entry.Data != null) @@ -2561,7 +2913,11 @@ namespace BinaryObjectScanner.Wrappers { string padding = new string(' ', (level + 1) * 2); +#if NET48 SabreTools.Models.PortableExecutable.MessageResourceData messageTable = null; +#else + SabreTools.Models.PortableExecutable.MessageResourceData? messageTable = null; +#endif try { messageTable = entry.AsMessageResourceData(); } catch { } if (messageTable == null) { @@ -2643,7 +2999,11 @@ namespace BinaryObjectScanner.Wrappers { string padding = new string(' ', (level + 1) * 2); +#if NET48 SabreTools.Models.PortableExecutable.VersionInfo versionInfo = null; +#else + SabreTools.Models.PortableExecutable.VersionInfo? versionInfo = null; +#endif try { versionInfo = entry.AsVersionInfo(); } catch { } if (versionInfo == null) { @@ -2739,7 +3099,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($"{padding} [String Table {i}] Value length: {varFileInfoChildEntry.ValueLength} (0x{varFileInfoChildEntry.ValueLength:X})"); builder.AppendLine($"{padding} [String Table {i}] ResourceType: {varFileInfoChildEntry.ResourceType} (0x{varFileInfoChildEntry.ResourceType:X})"); builder.AppendLine($"{padding} [String Table {i}] Key: {varFileInfoChildEntry.Key}"); - builder.AppendLine($"{padding} [String Table {i}] Value: {string.Join(",", varFileInfoChildEntry.Value)}"); + builder.AppendLine($"{padding} [String Table {i}] Value: {(varFileInfoChildEntry.Value == null ? "[NULL]" : string.Join(", ", varFileInfoChildEntry.Value))}"); } } } @@ -2820,7 +3180,11 @@ namespace BinaryObjectScanner.Wrappers { string padding = new string(' ', (level + 1) * 2); +#if NET48 SabreTools.Models.PortableExecutable.AssemblyManifest assemblyManifest = null; +#else + SabreTools.Models.PortableExecutable.AssemblyManifest? assemblyManifest = null; +#endif try { assemblyManifest = entry.AsAssemblyManifest(); } catch { } if (assemblyManifest == null) { @@ -3015,10 +3379,10 @@ namespace BinaryObjectScanner.Wrappers } else { - builder.AppendLine($"{padding}Data: {BitConverter.ToString(magic).Replace('-', ' ')} ..."); + builder.AppendLine($"{padding}Data: {(magic == null ? "[NULL]" : BitConverter.ToString(magic).Replace('-', ' '))} ..."); //if (entry.Data != null) - // builder.AppendLine($"{padding}Value (Byte Data): {BitConverter.ToString(entry.Data).Replace('-', ' ')}"); + // builder.AppendLine($"{padding}Value (Byte Data): {(entry.Data == null ? "[NULL]" : BitConverter.ToString(entry.Data).Replace('-', ' '))}"); //if (entry.Data != null) // builder.AppendLine($"{padding}Value (ASCII): {Encoding.ASCII.GetString(entry.Data)}"); //if (entry.Data != null) @@ -3100,7 +3464,11 @@ namespace BinaryObjectScanner.Wrappers { try { +#if NET48 string arrayAsASCII = Encoding.ASCII.GetString(b); +#else + string? arrayAsASCII = Encoding.ASCII.GetString(b!); +#endif if (arrayAsASCII.Contains(value)) return true; } @@ -3108,7 +3476,11 @@ namespace BinaryObjectScanner.Wrappers try { +#if NET48 string arrayAsUTF8 = Encoding.UTF8.GetString(b); +#else + string? arrayAsUTF8 = Encoding.UTF8.GetString(b!); +#endif if (arrayAsUTF8.Contains(value)) return true; } @@ -3116,7 +3488,11 @@ namespace BinaryObjectScanner.Wrappers try { +#if NET48 string arrayAsUnicode = Encoding.Unicode.GetString(b); +#else + string? arrayAsUnicode = Encoding.Unicode.GetString(b!); +#endif if (arrayAsUnicode.Contains(value)) return true; } @@ -3286,8 +3662,8 @@ namespace BinaryObjectScanner.Wrappers .Select(r => r as Dictionary) #endif .Where(st => st != null) - .Where(st => st.Select(kvp => kvp.Value) - .Any(s => s.Contains(entry))); + .Where(st => st?.Select(kvp => kvp.Value)? + .Any(s => s != null && s.Contains(entry)) == true); } /// @@ -3340,7 +3716,11 @@ namespace BinaryObjectScanner.Wrappers { try { +#if NET48 string arrayAsASCII = Encoding.ASCII.GetString(b); +#else + string? arrayAsASCII = Encoding.ASCII.GetString(b!); +#endif if (arrayAsASCII.Contains(value)) return true; } @@ -3348,7 +3728,11 @@ namespace BinaryObjectScanner.Wrappers try { +#if NET48 string arrayAsUTF8 = Encoding.UTF8.GetString(b); +#else + string? arrayAsUTF8 = Encoding.UTF8.GetString(b!); +#endif if (arrayAsUTF8.Contains(value)) return true; } @@ -3356,7 +3740,11 @@ namespace BinaryObjectScanner.Wrappers try { +#if NET48 string arrayAsUnicode = Encoding.Unicode.GetString(b); +#else + string? arrayAsUnicode = Encoding.Unicode.GetString(b!); +#endif if (arrayAsUnicode.Contains(value)) return true; } @@ -3381,8 +3769,8 @@ namespace BinaryObjectScanner.Wrappers var entry = table.Entries[i]; var newTypes = new List(types ?? new List()); - if (entry.Name != null) - newTypes.Add(Encoding.UTF8.GetString(entry.Name.UnicodeString ?? new byte[0])); + if (entry.Name?.UnicodeString != null) + newTypes.Add(Encoding.UTF8.GetString(entry.Name.UnicodeString)); else newTypes.Add(entry.IntegerID); @@ -3519,8 +3907,16 @@ namespace BinaryObjectScanner.Wrappers /// Name of the section to check for /// True to enable exact matching of names, false for starts-with /// True if the section is in the executable, false otherwise +#if NET48 public bool ContainsSection(string sectionName, bool exact = false) +#else + public bool ContainsSection(string? sectionName, bool exact = false) +#endif { + // If no section name is provided + if (sectionName == null) + return false; + // Get all section names first if (SectionNames == null) return false; @@ -3540,6 +3936,10 @@ namespace BinaryObjectScanner.Wrappers /// Section index on success, null on error public int FindEntryPointSectionIndex() { + // If the section table is missing + if (SectionTable == null) + return -1; + // If we don't have an entry point if (OH_AddressOfEntryPoint.ConvertVirtualAddress(SectionTable) == 0) return -1; @@ -3554,10 +3954,14 @@ namespace BinaryObjectScanner.Wrappers /// Name of the section to check for /// True to enable exact matching of names, false for starts-with /// Section data on success, null on error +#if NET48 public SabreTools.Models.PortableExecutable.SectionHeader GetFirstSection(string name, bool exact = false) +#else + public SabreTools.Models.PortableExecutable.SectionHeader? GetFirstSection(string? name, bool exact = false) +#endif { // If we have no sections - if (SectionTable == null || !SectionTable.Any()) + if (SectionNames == null || !SectionNames.Any() || SectionTable == null || !SectionTable.Any()) return null; // If the section doesn't exist @@ -3579,10 +3983,14 @@ namespace BinaryObjectScanner.Wrappers /// Name of the section to check for /// True to enable exact matching of names, false for starts-with /// Section data on success, null on error +#if NET48 public SabreTools.Models.PortableExecutable.SectionHeader GetLastSection(string name, bool exact = false) +#else + public SabreTools.Models.PortableExecutable.SectionHeader? GetLastSection(string? name, bool exact = false) +#endif { // If we have no sections - if (SectionTable == null || !SectionTable.Any()) + if (SectionNames == null || !SectionNames.Any() || SectionTable == null || !SectionTable.Any()) return null; // If the section doesn't exist @@ -3603,7 +4011,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Index of the section to check for /// Section data on success, null on error +#if NET48 public SabreTools.Models.PortableExecutable.SectionHeader GetSection(int index) +#else + public SabreTools.Models.PortableExecutable.SectionHeader? GetSection(int index) +#endif { // If we have no sections if (SectionTable == null || !SectionTable.Any()) @@ -3623,10 +4035,14 @@ namespace BinaryObjectScanner.Wrappers /// Name of the section to check for /// True to enable exact matching of names, false for starts-with /// Section data on success, null on error +#if NET48 public byte[] GetFirstSectionData(string name, bool exact = false) +#else + public byte[]? GetFirstSectionData(string? name, bool exact = false) +#endif { // If we have no sections - if (SectionTable == null || !SectionTable.Any()) + if (SectionNames == null || !SectionNames.Any() || SectionTable == null || !SectionTable.Any()) return null; // If the section doesn't exist @@ -3644,10 +4060,14 @@ namespace BinaryObjectScanner.Wrappers /// Name of the section to check for /// True to enable exact matching of names, false for starts-with /// Section data on success, null on error +#if NET48 public byte[] GetLastSectionData(string name, bool exact = false) +#else + public byte[]? GetLastSectionData(string? name, bool exact = false) +#endif { // If we have no sections - if (SectionTable == null || !SectionTable.Any()) + if (SectionNames == null || !SectionNames.Any() || SectionTable == null || !SectionTable.Any()) return null; // If the section doesn't exist @@ -3664,10 +4084,14 @@ namespace BinaryObjectScanner.Wrappers /// /// Index of the section to check for /// Section data on success, null on error +#if NET48 public byte[] GetSectionData(int index) +#else + public byte[]? GetSectionData(int index) +#endif { // If we have no sections - if (SectionTable == null || !SectionTable.Any()) + if (SectionNames == null || !SectionNames.Any() || SectionTable == null || !SectionTable.Any()) return null; // If the section doesn't exist @@ -3676,6 +4100,9 @@ namespace BinaryObjectScanner.Wrappers // Get the section data from the table var section = SectionTable[index]; + if (section == null) + return null; + uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable); if (address == 0) return null; @@ -3693,7 +4120,11 @@ namespace BinaryObjectScanner.Wrappers return _sectionData[index]; // Populate the raw section data based on the source +#if NET48 byte[] sectionData = ReadFromDataSource((int)address, (int)size); +#else + byte[]? sectionData = ReadFromDataSource((int)address, (int)size); +#endif // Cache and return the section data, even if null _sectionData[index] = sectionData; @@ -3707,10 +4138,14 @@ namespace BinaryObjectScanner.Wrappers /// Name of the section to check for /// True to enable exact matching of names, false for starts-with /// Section strings on success, null on error +#if NET48 public List GetFirstSectionStrings(string name, bool exact = false) +#else + public List? GetFirstSectionStrings(string? name, bool exact = false) +#endif { // If we have no sections - if (SectionTable == null || !SectionTable.Any()) + if (SectionNames == null || !SectionNames.Any() || SectionTable == null || !SectionTable.Any()) return null; // If the section doesn't exist @@ -3728,10 +4163,14 @@ namespace BinaryObjectScanner.Wrappers /// Name of the section to check for /// True to enable exact matching of names, false for starts-with /// Section strings on success, null on error +#if NET48 public List GetLastSectionStrings(string name, bool exact = false) +#else + public List? GetLastSectionStrings(string? name, bool exact = false) +#endif { // If we have no sections - if (SectionTable == null || !SectionTable.Any()) + if (SectionNames == null || !SectionNames.Any() || SectionTable == null || !SectionTable.Any()) return null; // If the section doesn't exist @@ -3748,10 +4187,14 @@ namespace BinaryObjectScanner.Wrappers /// /// Index of the section to check for /// Section strings on success, null on error +#if NET48 public List GetSectionStrings(int index) +#else + public List? GetSectionStrings(int index) +#endif { // If we have no sections - if (SectionTable == null || !SectionTable.Any()) + if (SectionNames == null || !SectionNames.Any() || SectionTable == null || !SectionTable.Any()) return null; // If the section doesn't exist @@ -3777,7 +4220,11 @@ namespace BinaryObjectScanner.Wrappers return _sectionStringData[index]; // Populate the section string data based on the source +#if NET48 List sectionStringData = ReadStringsFromDataSource((int)address, (int)size); +#else + List? sectionStringData = ReadStringsFromDataSource((int)address, (int)size); +#endif // Cache and return the section string data, even if null _sectionStringData[index] = sectionStringData; @@ -3794,7 +4241,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Index of the table to check for /// Table data on success, null on error +#if NET48 public byte[] GetTableData(int index) +#else + public byte[]? GetTableData(int index) +#endif { // If the table doesn't exist if (index < 0 || index > 16) @@ -3870,6 +4321,10 @@ namespace BinaryObjectScanner.Wrappers break; } + // If there is no section table + if (SectionTable == null) + return null; + // Get the physical address from the virtual one uint address = virtualAddress.ConvertVirtualAddress(SectionTable); if (address == 0 || size == 0) @@ -3886,7 +4341,11 @@ namespace BinaryObjectScanner.Wrappers return _tableData[index]; // Populate the raw table data based on the source +#if NET48 byte[] tableData = ReadFromDataSource((int)address, (int)size); +#else + byte[]? tableData = ReadFromDataSource((int)address, (int)size); +#endif // Cache and return the table data, even if null _tableData[index] = tableData; @@ -3899,7 +4358,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Index of the table to check for /// Table strings on success, null on error +#if NET48 public List GetTableStrings(int index) +#else + public List? GetTableStrings(int index) +#endif { // If the table doesn't exist if (index < 0 || index > 16) @@ -3975,6 +4438,10 @@ namespace BinaryObjectScanner.Wrappers break; } + // If there is no section table + if (SectionTable == null) + return null; + // Get the physical address from the virtual one uint address = virtualAddress.ConvertVirtualAddress(SectionTable); if (address == 0 || size == 0) @@ -3991,7 +4458,11 @@ namespace BinaryObjectScanner.Wrappers return _tableStringData[index]; // Populate the table string data based on the source +#if NET48 List tableStringData = ReadStringsFromDataSource((int)address, (int)size); +#else + List? tableStringData = ReadStringsFromDataSource((int)address, (int)size); +#endif // Cache and return the table string data, even if null _tableStringData[index] = tableStringData; diff --git a/BinaryObjectScanner.Wrappers/Quantum.cs b/BinaryObjectScanner.Wrappers/Quantum.cs index 3e3519ec..09e7043c 100644 --- a/BinaryObjectScanner.Wrappers/Quantum.cs +++ b/BinaryObjectScanner.Wrappers/Quantum.cs @@ -17,7 +17,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Signature => _model.Header.Signature; +#else + public string? Signature => _model.Header.Signature; +#endif /// public byte MajorVersion => _model.Header.MajorVersion; @@ -82,7 +86,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the archive /// Offset within the array to parse /// A Quantum archive wrapper on success, null on failure +#if NET48 public static Quantum Create(byte[] data, int offset) +#else + public static Quantum? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -102,7 +110,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the archive /// A Quantum archive wrapper on success, null on failure +#if NET48 public static Quantum Create(Stream data) +#else + public static Quantum? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) diff --git a/BinaryObjectScanner.Wrappers/SGA.cs b/BinaryObjectScanner.Wrappers/SGA.cs index b32a35dc..d1e81de7 100644 --- a/BinaryObjectScanner.Wrappers/SGA.cs +++ b/BinaryObjectScanner.Wrappers/SGA.cs @@ -21,7 +21,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Signature => _model.Header.Signature; +#else + public string? Signature => _model.Header.Signature; +#endif /// public ushort MajorVersion => _model.Header.MajorVersion; @@ -410,7 +414,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the SGA /// Offset within the array to parse /// An SGA wrapper on success, null on failure +#if NET48 public static SGA Create(byte[] data, int offset) +#else + public static SGA? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -430,7 +438,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the SGA /// An SGA wrapper on success, null on failure +#if NET48 public static SGA Create(Stream data) +#else + public static SGA? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -737,7 +749,11 @@ namespace BinaryObjectScanner.Wrappers return false; // Create the filename +#if NET48 string filename; +#else + string? filename; +#endif switch (MajorVersion) { case 4: @@ -748,16 +764,24 @@ namespace BinaryObjectScanner.Wrappers } // Loop through and get all parent directories +#if NET48 var parentNames = new List { filename }; +#else + var parentNames = new List { filename }; +#endif // Get the parent directory +#if NET48 object folder; +#else + object? folder; +#endif switch (MajorVersion) { - case 4: folder = (Folders as SabreTools.Models.SGA.Folder4[]).FirstOrDefault(f => index >= f.FileStartIndex && index <= f.FileEndIndex); break; + case 4: folder = (Folders as SabreTools.Models.SGA.Folder4[])?.FirstOrDefault(f => index >= f.FileStartIndex && index <= f.FileEndIndex); break; case 5: case 6: - case 7: folder = (Folders as SabreTools.Models.SGA.Folder5[]).FirstOrDefault(f => index >= f.FileStartIndex && index <= f.FileEndIndex); break; + case 7: folder = (Folders as SabreTools.Models.SGA.Folder5[])?.FirstOrDefault(f => index >= f.FileStartIndex && index <= f.FileEndIndex); break; default: return false; } @@ -815,7 +839,11 @@ namespace BinaryObjectScanner.Wrappers } // Read the compressed data directly +#if NET48 byte[] compressedData = ReadFromDataSource((int)fileOffset, (int)fileSize); +#else + byte[]? compressedData = ReadFromDataSource((int)fileOffset, (int)fileSize); +#endif if (compressedData == null) return false; @@ -842,7 +870,13 @@ namespace BinaryObjectScanner.Wrappers filename = Path.Combine(outputDirectory, filename); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try diff --git a/BinaryObjectScanner.Wrappers/VBSP.cs b/BinaryObjectScanner.Wrappers/VBSP.cs index 79595428..bdafba87 100644 --- a/BinaryObjectScanner.Wrappers/VBSP.cs +++ b/BinaryObjectScanner.Wrappers/VBSP.cs @@ -16,7 +16,11 @@ namespace BinaryObjectScanner.Wrappers #region Pass-Through Properties /// +#if NET48 public string Signature => _model.Header.Signature; +#else + public string? Signature => _model.Header.Signature; +#endif /// public int Version => _model.Header.Version; @@ -69,7 +73,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the VBSP /// Offset within the array to parse /// A VBSP wrapper on success, null on failure +#if NET48 public static VBSP Create(byte[] data, int offset) +#else + public static VBSP? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -89,7 +97,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the VBSP /// An VBSP wrapper on success, null on failure +#if NET48 public static VBSP Create(Stream data) +#else + public static VBSP? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -176,7 +188,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Offset: {lump.Offset} (0x{lump.Offset:X})"); builder.AppendLine($" Length: {lump.Length} (0x{lump.Length:X})"); builder.AppendLine($" Version: {lump.Version} (0x{lump.Version:X})"); - builder.AppendLine($" 4CC: {string.Join(", ", lump.FourCC)}"); + builder.AppendLine($" 4CC: {(lump.FourCC == null ? "[NULL]" : string.Join(", ", lump.FourCC))}"); } } builder.AppendLine(); @@ -236,7 +248,11 @@ namespace BinaryObjectScanner.Wrappers return false; // Read the data +#if NET48 byte[] data = ReadFromDataSource((int)lump.Offset, (int)lump.Length); +#else + byte[]? data = ReadFromDataSource((int)lump.Offset, (int)lump.Length); +#endif if (data == null) return false; @@ -260,7 +276,13 @@ namespace BinaryObjectScanner.Wrappers filename = Path.Combine(outputDirectory, filename); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try diff --git a/BinaryObjectScanner.Wrappers/VPK.cs b/BinaryObjectScanner.Wrappers/VPK.cs index 5bd516e9..87591267 100644 --- a/BinaryObjectScanner.Wrappers/VPK.cs +++ b/BinaryObjectScanner.Wrappers/VPK.cs @@ -76,7 +76,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Array of archive filenames attached to the given VPK /// +#if NET48 public string[] ArchiveFilenames +#else + public string[]? ArchiveFilenames +#endif { get { @@ -90,18 +94,28 @@ namespace BinaryObjectScanner.Wrappers // If the filename is not the right format string extension = Path.GetExtension(fs.Name).TrimStart('.'); - string fileName = Path.Combine(Path.GetDirectoryName(fs.Name), Path.GetFileNameWithoutExtension(fs.Name)); +#if NET48 + string directoryName = Path.GetDirectoryName(fs.Name); +#else + string? directoryName = Path.GetDirectoryName(fs.Name); +#endif + string fileName = directoryName == null + ? Path.GetFileNameWithoutExtension(fs.Name) + : Path.Combine(directoryName, Path.GetFileNameWithoutExtension(fs.Name)); + if (fileName.Length < 3) return null; else if (fileName.Substring(fileName.Length - 3) != "dir") return null; // Get the archive count - int archiveCount = DirectoryItems - .Select(di => di.DirectoryEntry) - .Select(de => de.ArchiveIndex) - .Where(ai => ai != HL_VPK_NO_ARCHIVE) - .Max(); + int archiveCount = DirectoryItems == null + ? 0 + : DirectoryItems + .Select(di => di.DirectoryEntry) + .Select(de => de.ArchiveIndex) + .Where(ai => ai != HL_VPK_NO_ARCHIVE) + .Max(); // Build the list of archive filenames to populate _archiveFilenames = new string[archiveCount]; @@ -160,7 +174,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the VPK /// Offset within the array to parse /// A VPK wrapper on success, null on failure +#if NET48 public static VPK Create(byte[] data, int offset) +#else + public static VPK? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -180,7 +198,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the VPK /// A VPK wrapper on success, null on failure +#if NET48 public static VPK Create(Stream data) +#else + public static VPK? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -278,7 +300,7 @@ namespace BinaryObjectScanner.Wrappers builder.AppendLine($" Archive index: {archiveHash.ArchiveIndex} (0x{archiveHash.ArchiveIndex:X})"); builder.AppendLine($" Archive offset: {archiveHash.ArchiveOffset} (0x{archiveHash.ArchiveOffset:X})"); builder.AppendLine($" Length: {archiveHash.Length} (0x{archiveHash.Length:X})"); - builder.AppendLine($" Hash: {BitConverter.ToString(archiveHash.Hash).Replace("-", string.Empty)}"); + builder.AppendLine($" Hash: {(archiveHash.Hash == null ? "[NULL]" : BitConverter.ToString(archiveHash.Hash).Replace("-", string.Empty))}"); } } builder.AppendLine(); @@ -302,11 +324,18 @@ namespace BinaryObjectScanner.Wrappers { var directoryItem = DirectoryItems[i]; builder.AppendLine($" Directory Item {i}"); - builder.AppendLine($" Extension: {directoryItem.Extension}"); - builder.AppendLine($" Path: {directoryItem.Path}"); - builder.AppendLine($" Name: {directoryItem.Name}"); - PrintDirectoryEntry(directoryItem.DirectoryEntry, builder); - // TODO: Print out preload data? + if (directoryItem == null) + { + builder.AppendLine(" [NULL]"); + } + else + { + builder.AppendLine($" Extension: {directoryItem.Extension}"); + builder.AppendLine($" Path: {directoryItem.Path}"); + builder.AppendLine($" Name: {directoryItem.Name}"); + PrintDirectoryEntry(directoryItem.DirectoryEntry, builder); + // TODO: Print out preload data? + } } } builder.AppendLine(); @@ -316,7 +345,11 @@ namespace BinaryObjectScanner.Wrappers /// Print directory entry information /// /// StringBuilder to append information to +#if NET48 private void PrintDirectoryEntry(SabreTools.Models.VPK.DirectoryEntry directoryEntry, StringBuilder builder) +#else + private void PrintDirectoryEntry(SabreTools.Models.VPK.DirectoryEntry? directoryEntry, StringBuilder builder) +#endif { if (directoryEntry == null) { @@ -387,7 +420,11 @@ namespace BinaryObjectScanner.Wrappers return false; // If we have an item with no archive +#if NET48 byte[] data; +#else + byte[]? data; +#endif if (directoryItem.DirectoryEntry.ArchiveIndex == HL_VPK_NO_ARCHIVE) { if (directoryItem.PreloadData == null) @@ -415,7 +452,11 @@ namespace BinaryObjectScanner.Wrappers return false; // Try to open the archive +#if NET48 Stream archiveStream = null; +#else + Stream? archiveStream = null; +#endif try { // Open the archive @@ -437,10 +478,14 @@ namespace BinaryObjectScanner.Wrappers } // If we have preload data, prepend it - if (directoryItem.PreloadData != null) + if (data != null && directoryItem.PreloadData != null) data = directoryItem.PreloadData.Concat(data).ToArray(); } + // If there is nothing to write out + if (data == null) + return false; + // Create the filename string filename = $"{directoryItem.Name}.{directoryItem.Extension}"; if (!string.IsNullOrWhiteSpace(directoryItem.Path)) @@ -454,7 +499,13 @@ namespace BinaryObjectScanner.Wrappers filename = Path.Combine(outputDirectory, filename); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try diff --git a/BinaryObjectScanner.Wrappers/WAD.cs b/BinaryObjectScanner.Wrappers/WAD.cs index cb89b1be..5ce143d7 100644 --- a/BinaryObjectScanner.Wrappers/WAD.cs +++ b/BinaryObjectScanner.Wrappers/WAD.cs @@ -17,7 +17,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Signature => _model.Header.Signature; +#else + public string? Signature => _model.Header.Signature; +#endif /// public uint LumpCount => _model.Header.LumpCount; @@ -87,7 +91,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the WAD /// Offset within the array to parse /// A WAD wrapper on success, null on failure +#if NET48 public static WAD Create(byte[] data, int offset) +#else + public static WAD? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -107,7 +115,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the WAD /// An WAD wrapper on success, null on failure +#if NET48 public static WAD Create(Stream data) +#else + public static WAD? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -284,7 +296,11 @@ namespace BinaryObjectScanner.Wrappers return false; // Read the data -- TODO: Handle uncompressed lumps (see BSP.ExtractTexture) +#if NET48 byte[] data = ReadFromDataSource((int)lump.Offset, (int)lump.Length); +#else + byte[]? data = ReadFromDataSource((int)lump.Offset, (int)lump.Length); +#endif if (data == null) return false; @@ -299,7 +315,13 @@ namespace BinaryObjectScanner.Wrappers filename = Path.Combine(outputDirectory, filename); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try diff --git a/BinaryObjectScanner.Wrappers/WrapperBase.cs b/BinaryObjectScanner.Wrappers/WrapperBase.cs index e2e70329..3b56844c 100644 --- a/BinaryObjectScanner.Wrappers/WrapperBase.cs +++ b/BinaryObjectScanner.Wrappers/WrapperBase.cs @@ -27,7 +27,7 @@ namespace BinaryObjectScanner.Wrappers /// Internal model /// /// TODO: Should this have a public getter? - protected T _model = default; + protected T _model; /// /// Source of the original data @@ -190,7 +190,11 @@ namespace BinaryObjectScanner.Wrappers /// Position in the source to read from /// Length of the requested data /// Byte array containing the requested data, null on error +#if NET48 protected byte[] ReadFromDataSource(int position, int length) +#else + protected byte[]? ReadFromDataSource(int position, int length) +#endif { // Validate the data source if (!DataSourceIsValid()) @@ -201,12 +205,20 @@ namespace BinaryObjectScanner.Wrappers return null; // Read and return the data +#if NET48 byte[] sectionData = null; +#else + byte[]? sectionData = null; +#endif switch (_dataSource) { case DataSource.ByteArray: sectionData = new byte[length]; +#if NET48 Array.Copy(_byteArrayData, _byteArrayOffset + position, sectionData, 0, length); +#else + Array.Copy(_byteArrayData!, _byteArrayOffset + position, sectionData, 0, length); +#endif break; case DataSource.Stream: @@ -227,7 +239,11 @@ namespace BinaryObjectScanner.Wrappers /// Length of the requested data /// Number of characters needed to be a valid string /// String list containing the requested data, null on error +#if NET48 protected List ReadStringsFromDataSource(int position, int length, int charLimit = 5) +#else + protected List? ReadStringsFromDataSource(int position, int length, int charLimit = 5) +#endif { // Read the data as a byte array first byte[] sourceData = ReadFromDataSource(position, length); diff --git a/BinaryObjectScanner.Wrappers/WrapperFactory.cs b/BinaryObjectScanner.Wrappers/WrapperFactory.cs index e77f2d20..77fe0925 100644 --- a/BinaryObjectScanner.Wrappers/WrapperFactory.cs +++ b/BinaryObjectScanner.Wrappers/WrapperFactory.cs @@ -11,7 +11,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Create an instance of a wrapper based on file type /// +#if NET48 public static IWrapper CreateWrapper(SupportedFileType fileType, Stream data) +#else + public static IWrapper? CreateWrapper(SupportedFileType fileType, Stream? data) +#endif { switch (fileType) { @@ -59,8 +63,12 @@ namespace BinaryObjectScanner.Wrappers /// Create an instance of a wrapper based on the executable type /// /// Stream data to parse - /// WrapperBase representing the executable, null on error + /// IWrapper representing the executable, null on error +#if NET48 public static IWrapper CreateExecutableWrapper(Stream stream) +#else + public static IWrapper? CreateExecutableWrapper(Stream? stream) +#endif { // Try to get an MS-DOS wrapper first IWrapper wrapper = MSDOS.Create(stream); diff --git a/BinaryObjectScanner.Wrappers/XZP.cs b/BinaryObjectScanner.Wrappers/XZP.cs index 85071e93..85bcee26 100644 --- a/BinaryObjectScanner.Wrappers/XZP.cs +++ b/BinaryObjectScanner.Wrappers/XZP.cs @@ -18,7 +18,11 @@ namespace BinaryObjectScanner.Wrappers #region Header /// +#if NET48 public string Signature => _model.Header.Signature; +#else + public string? Signature => _model.Header.Signature; +#endif /// public uint Version => _model.Header.Version; @@ -96,7 +100,11 @@ namespace BinaryObjectScanner.Wrappers public uint F_FileLength => _model.Footer.FileLength; /// +#if NET48 public string F_Signature => _model.Footer.Signature; +#else + public string? F_Signature => _model.Footer.Signature; +#endif #endregion @@ -138,7 +146,11 @@ namespace BinaryObjectScanner.Wrappers /// Byte array representing the XZP /// Offset within the array to parse /// A XZP wrapper on success, null on failure +#if NET48 public static XZP Create(byte[] data, int offset) +#else + public static XZP? Create(byte[]? data, int offset) +#endif { // If the data is invalid if (data == null) @@ -158,7 +170,11 @@ namespace BinaryObjectScanner.Wrappers /// /// Stream representing the XZP /// A XZP wrapper on success, null on failure +#if NET48 public static XZP Create(Stream data) +#else + public static XZP? Create(Stream? data) +#endif { // If the data is invalid if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead) @@ -400,20 +416,36 @@ namespace BinaryObjectScanner.Wrappers return false; // Load the item data +#if NET48 byte[] data = ReadFromDataSource((int)directoryEntry.EntryOffset, (int)directoryEntry.EntryLength); +#else + byte[]? data = ReadFromDataSource((int)directoryEntry.EntryOffset, (int)directoryEntry.EntryLength); +#endif + if (data == null) + return false; // Create the filename +#if NET48 string filename = directoryItem.Name; +#else + string? filename = directoryItem.Name; +#endif // If we have an invalid output directory if (string.IsNullOrWhiteSpace(outputDirectory)) return false; // Create the full output path - filename = Path.Combine(outputDirectory, filename); + filename = Path.Combine(outputDirectory, filename ?? $"file{index}"); // Ensure the output directory is created - Directory.CreateDirectory(Path.GetDirectoryName(filename)); +#if NET48 + string directoryName = Path.GetDirectoryName(filename); +#else + string? directoryName = Path.GetDirectoryName(filename); +#endif + if (directoryName != null) + Directory.CreateDirectory(directoryName); // Try to write the data try