public SdbFile(byte[] rawBytes, string sourceFile) { RawBytes = rawBytes; SourceFile = Path.GetFullPath(sourceFile); MajorVersion = BitConverter.ToInt32(rawBytes, 0); MinorVersion = BitConverter.ToInt32(rawBytes, 4); var logger = LogManager.GetCurrentClassLogger(); logger.Debug($"Major: {MajorVersion}, Minor: {MinorVersion}"); var index = 0xc; StringTableEntries.Clear(); Metrics.Clear(); Children = new List <ISdbEntry>(); while (index < rawBytes.Length) { var id = (TagValue)BitConverter.ToUInt16(rawBytes, index); index += 2; var tagType = (int)id & 0xF000; if (tagType == 0x7000) { //lists look like: //tag //length //data ('length' bytes long) var size = BitConverter.ToInt32(rawBytes, index); index += 4; var buff = new byte[size]; Buffer.BlockCopy(rawBytes, index, buff, 0, size); var c = new Chunk(id, buff, index - 2 - 4); var l = new SdbEntryList(id, buff, index - 2 - 4); foreach (var sdbEntry in c.Children) { if (!(sdbEntry is SdbEntryList)) { sdbEntry.Offset += 4; } l.Children.Add(sdbEntry); } Children.Add(l); index += size; } else { throw new Exception( $"Unexpected Tag type '0x{tagType:X4}'! Please send this sdb file to [email protected] so suppoprt can be added!"); } } }
internal Chunk(SdbFile file, SdbFile.TagValue typeId, byte[] bytes, int baseOffset) { TypeId = typeId; Bytes = bytes; var logger = LogManager.GetCurrentClassLogger(); logger.Debug($"Chunk ID: {typeId} ({typeId:X}) bytes length: 0x{Bytes.Length:X}"); var index = 0x0; Children = new List <ISdbEntry>(); //bytes contains whatever the payload for this chunk is while (index < bytes.Length) { if (bytes.Length - index < 2) { break; } var id1 = (SdbFile.TagValue)BitConverter.ToUInt16(bytes, index); var tagTypeInt = (int)id1 & 0xF000; logger.Debug($"While loop TagType {tagTypeInt:X}, Id: {id1} (0x{id1:X})"); index += 2; //handle some special cases switch ((int)id1) { case 0x53db: index -= 1; continue; } //end handle some special cases int size; byte[] buff; var tagType = (SdbFile.TagType)tagTypeInt; UpdateMetrics(file, id1); switch (tagType) { case SdbFile.TagType.TAG_TYPE_NULL: buff = new byte[0]; var n = new SdbEntryNull(id1, buff, baseOffset + index); Children.Add(n); break; case SdbFile.TagType.TAG_TYPE_BYTE: throw new Exception("Send this file to [email protected] so BYTE support can be added"); // buff = new byte[1]; // Buffer.BlockCopy(bytes, index, buff, 0, 1); // var b = new SdbEntryByte(id1, buff, baseOffset + index); // // Children.Add(b); // break; case SdbFile.TagType.TAG_TYPE_WORD: buff = new byte[2]; Buffer.BlockCopy(bytes, index, buff, 0, 2); var w = new SdbEntryWord(id1, buff, baseOffset + index); Children.Add(w); index += 2; break; case SdbFile.TagType.TAG_TYPE_DWORD: buff = new byte[4]; Buffer.BlockCopy(bytes, index, buff, 0, 4); var d = new SdbEntryDWord(id1, buff, baseOffset + index); Children.Add(d); index += 4; break; case SdbFile.TagType.TAG_TYPE_QWORD: buff = new byte[8]; Buffer.BlockCopy(bytes, index, buff, 0, 8); var q = new SdbEntryQWord(id1, buff, baseOffset + index); Children.Add(q); index += 8; break; case SdbFile.TagType.TAG_TYPE_STRINGREF: buff = new byte[4]; Buffer.BlockCopy(bytes, index, buff, 0, 4); var sr = new SdbEntryStringRef(file, id1, buff, baseOffset + index); Children.Add(sr); index += 4; break; case SdbFile.TagType.TAG_TYPE_LIST: size = BitConverter.ToInt32(bytes, index); index += 4; buff = new byte[size]; Buffer.BlockCopy(bytes, index, buff, 0, size); var c = new Chunk(file, id1, buff, baseOffset + index); var l = new SdbEntryList(id1, buff, baseOffset + index); foreach (var sdbEntry in c.Children) { if (!(sdbEntry is SdbEntryList)) { sdbEntry.Offset += 4; } l.Children.Add(sdbEntry); } Children.Add(l); index += size; break; case SdbFile.TagType.TAG_TYPE_STRING: size = BitConverter.ToInt32(bytes, index); index += 4; buff = new byte[size]; Buffer.BlockCopy(bytes, index, buff, 0, size); //this provides a means to do easy string lookups based on relative offset var sti = new StringTableEntry(index, Encoding.Unicode.GetString(buff, 0, size).Trim('\0')); file.StringTableEntries.Add(sti.Offset, sti); //this is the structure itself that defines the strings found in the database var st = new SdbEntryStringTableItem(id1, buff, baseOffset + index - 4); Children.Add(st); index += size; break; case SdbFile.TagType.TAG_TYPE_BINARY: size = BitConverter.ToInt32(bytes, index); index += 4; buff = new byte[size]; Buffer.BlockCopy(bytes, index, buff, 0, size); var bin = new SdbEntryBinary(id1, buff, baseOffset + index - 4); Children.Add(bin); index += size; break; default: throw new Exception($"Unknown tag type: {tagType}, index: 0x{index:X}"); } } }