Exemple #1
0
 public _x02(BinaryReader reader, long chunkOffset, LogRoot root, INode parent)
 {
     this.Position = reader.BaseStream.Position;
     this.LogRoot = root;
     this.SelfEnclosed = true;
     root.TagState = 0;
 }
Exemple #2
0
        public _x05(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            this.Type     = log.ReadByte();
            short length = log.ReadInt16();

            this.SelfEnclosed = true;

            this.LogRoot = root;

            this.TagState = root.TagState;

            IType type = null;

            switch (this.Type)
            {
            case 0x01:
                type = new Type0x01(log, length, false);
                break;

            default:
                throw new Exception("Don't know type: " + this.Type);
            }

            this.String = type.String;
            this.Length = ((length) * 2) + 4;
        }
        public Template(BinaryReader log, long chunkOffset, LogRoot root)
        {
            this.Position            = log.BaseStream.Position;
            this.LogRoot             = root;
            this.ChunkOffset         = chunkOffset;
            log.BaseStream.Position += 1;
            int templateID = log.ReadInt32();
            int ptr        = log.ReadInt32();

            log.BaseStream.Position = this.ChunkOffset + ptr;

            int nextTemplate = log.ReadInt32();
            int templateID2  = log.ReadInt32();

            log.BaseStream.Position -= 4;

            byte[] g            = log.ReadBytes(16);
            Guid   templateGuid = new Guid(g);

            this.Length = log.ReadInt32();
            long i = this.Length;

            this.ChildNodes = new List <INode>();
            while (i >= 0 && !root.ReachedEOS)
            {
                Console.WriteLine("Current length: " + i);
                INode node = LogNode.NewNode(log, this, chunkOffset, root);
                this.ChildNodes.Add(node);
                i -= node.Length;
                if (node is _x00)
                {
                    root.ReachedEOS = true;
                }
            }
        }
Exemple #4
0
        public _x06(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position     = log.BaseStream.Position;
            this.ChunkOffset  = chunkOffset;
            this.SelfEnclosed = true;
            int ptr = log.ReadInt32();

            this.LogRoot = root;
            this.Length  = 5;            //tag length

            if (!root.ParentLog.Strings.ContainsKey(this.ChunkOffset + ptr))
            {
                log.BaseStream.Position = this.ChunkOffset + ptr;

                int next    = log.ReadInt32();
                int hash    = log.ReadInt16();
                int length2 = log.ReadInt16();

                _str = log.ReadBytes((int)(length2 * 2));
                log.BaseStream.Position += 2;

                this.String  = root.ParentLog.Strings[this.ChunkOffset + ptr] = System.Text.Encoding.Unicode.GetString(_str);
                this.Length += (length2 + 1) * 2;
            }
            else
            {
                this.String = root.ParentLog.Strings[this.ChunkOffset + ptr];
            }

            this.Length += 8;
        }
Exemple #5
0
 public _x02(BinaryReader reader, long chunkOffset, LogRoot root, INode parent)
 {
     this.Position     = reader.BaseStream.Position;
     this.LogRoot      = root;
     this.SelfEnclosed = true;
     root.TagState     = 0;
 }
Exemple #6
0
        public _x06(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            this.ChunkOffset = chunkOffset;
            this.SelfEnclosed = true;
            int ptr = log.ReadInt32();

            this.LogRoot = root;
            this.Length = 5; //tag length

            if (!root.ParentLog.Strings.ContainsKey(this.ChunkOffset + ptr))
            {
                log.BaseStream.Position  = this.ChunkOffset + ptr;

                int next = log.ReadInt32();
                int hash = log.ReadInt16();
                int length2 = log.ReadInt16();

                _str = log.ReadBytes((int)(length2*2));
                log.BaseStream.Position +=2;

                this.String = root.ParentLog.Strings[this.ChunkOffset + ptr] = System.Text.Encoding.Unicode.GetString(_str);
                this.Length +=(length2+1)*2;
            }
            else
                this.String = root.ParentLog.Strings[this.ChunkOffset + ptr];

            this.Length += 8;
        }
        public SubstitutionArray(BinaryReader reader, long chunkOffset, LogRoot root)
        {
            this.ElementCount = reader.ReadInt32();
            this.ChunkOffset = chunkOffset;
            this.Length = 2;

            if (this.ElementCount != 0)
            {
                short[][] sizetype = new short[this.ElementCount][];

                for (int i = 0; i < this.ElementCount; i++)
                {
                    sizetype[i] = new short[2];

                    short size = reader.ReadInt16();
                    byte type = reader.ReadByte();
                    reader.BaseStream.Position++; //unknown

                    sizetype[i][0] = size;
                    sizetype[i][1] = type;
                }

                this.Types = new List<IType>();

                for (int i = 0; i < this.ElementCount; i++)
                    this.Types.Add(LogType.NewType(reader, sizetype[i], this.ChunkOffset, root, true));
            }
        }
        public SubstitutionArray(BinaryReader reader, long chunkOffset, LogRoot root)
        {
            this.ElementCount = reader.ReadInt32();
            this.ChunkOffset  = chunkOffset;
            this.Length       = 2;

            if (this.ElementCount != 0)
            {
                short[][] sizetype = new short[this.ElementCount][];

                for (int i = 0; i < this.ElementCount; i++)
                {
                    sizetype[i] = new short[2];

                    short size = reader.ReadInt16();
                    byte  type = reader.ReadByte();
                    reader.BaseStream.Position++;                     //unknown

                    sizetype[i][0] = size;
                    sizetype[i][1] = type;
                }

                this.Types = new List <IType>();

                for (int i = 0; i < this.ElementCount; i++)
                {
                    this.Types.Add(LogType.NewType(reader, sizetype[i], this.ChunkOffset, root, true));
                }
            }
        }
Exemple #9
0
        public _x07(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            short length = log.ReadInt16();
            this.SelfEnclosed = true;

            this.LogRoot = root;
        }
Exemple #10
0
 public _x0D(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
 {
     this.Position = log.BaseStream.Position;
     short index = log.ReadInt16();
     byte type = log.ReadByte();
     this.LogRoot = root;
     this.SelfEnclosed = true;
 }
Exemple #11
0
        public _x07(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            short length = log.ReadInt16();

            this.SelfEnclosed = true;

            this.LogRoot = root;
        }
Exemple #12
0
        public _x0D(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            short index = log.ReadInt16();
            byte  type  = log.ReadByte();

            this.LogRoot      = root;
            this.SelfEnclosed = true;
        }
Exemple #13
0
 public _x0C(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
 {
     this.Position = log.BaseStream.Position;
     this.LogRoot = root;
     this.ChunkOffset = chunkOffset;
     this.Length = 10;
     this.SelfEnclosed = true;
     this.Template = new Template(log, chunkOffset, root) { Parent = this };
     this.Length += this.Template.Length;
 }
Exemple #14
0
        public _x0E(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            this.Index    = log.ReadInt16();
            this.Type     = log.ReadByte();

            this.SelfEnclosed = true;
            this.LogRoot      = root;
            this.TagState     = root.TagState;
        }
Exemple #15
0
        public _x0B(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position     = log.BaseStream.Position;
            this.SelfEnclosed = true;
            short length = log.ReadInt16();

            _str         = log.ReadBytes(length * 2);
            this.String  = System.Text.Encoding.Unicode.GetString(_str);
            this.LogRoot = root;
            this.Length  = (length * 2) + 2;
        }
Exemple #16
0
        public _x01(BinaryReader log, long chunkOffset, int flags, LogRoot root, INode parent)
        {
            this.Position         = log.BaseStream.Position;
            this.LogRoot          = root;
            this.SelfEnclosed     = false;
            this.LogRoot.TagState = 1;
            this.ChunkOffset      = chunkOffset;
            _addFour = ((flags & 4) == 0) ? false : true;

            log.BaseStream.Position += 2;             //short unk1
            _length = log.ReadInt32();
            _ptr    = log.ReadInt32();
            long i = 0;

            if (!root.ParentLog.Strings.ContainsKey((long)(this.ChunkOffset + _ptr)))
            {
                log.BaseStream.Position = this.ChunkOffset + _ptr;

                _next    = log.ReadInt32();
                _hash    = log.ReadInt16();
                _length2 = log.ReadInt16();

                _posdiff    = 2;
                this.Length = _length + 6;                 //6?

                _str = log.ReadBytes((int)(_length2 * 2));
                log.BaseStream.Position += _posdiff + (_addFour ? 4 : 0);
                this.String              = root.ParentLog.Strings[this.ChunkOffset + _ptr] = System.Text.Encoding.Unicode.GetString(_str);
                i = this.Length - (11 + (_length2 + 1) * 2 + (_addFour ? 4 : 0));
            }
            else
            {
                this.String              = root.ParentLog.Strings[this.ChunkOffset + _ptr];
                _length2                 = 0;
                log.BaseStream.Position += (_addFour ? 4 : 0);
                i = this.Length - (11 + (_addFour ? 4 : 0));
            }

            this.ChildNodes = new List <INode>();
            i -= 8;
            while (i >= 0 && !root.ReachedEOS)
            {
                Console.WriteLine("Current length: " + i);
                INode node = LogNode.NewNode(log, this, chunkOffset, this.LogRoot);
                this.ChildNodes.Add(node);
                i -= node.Length;

                if (node is _x00)
                {
                    root.ReachedEOS = true;
                }
            }
        }
Exemple #17
0
 public _x0C(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
 {
     this.Position     = log.BaseStream.Position;
     this.LogRoot      = root;
     this.ChunkOffset  = chunkOffset;
     this.Length       = 10;
     this.SelfEnclosed = true;
     this.Template     = new Template(log, chunkOffset, root)
     {
         Parent = this
     };
     this.Length += this.Template.Length;
 }
Exemple #18
0
        public _x0F(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            this.LogRoot  = root;
            char  oth1 = log.ReadChar();
            short oth2 = log.ReadInt16();

            this.SelfEnclosed = true;

            if (oth1 != 1 && oth2 != 1)
            {
                throw new Exception("Bad 0x0f node -- oth1: " + oth1 + " :: oth2: " + oth2);
            }
        }
Exemple #19
0
        public _x01(BinaryReader log, long chunkOffset, int flags, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            this.LogRoot = root;
            this.SelfEnclosed = false;
            this.LogRoot.TagState = 1;
            this.ChunkOffset = chunkOffset;
            _addFour = ((flags & 4) == 0) ? false : true;

            log.BaseStream.Position += 2; //short unk1
            _length = log.ReadInt32 ();
            _ptr = log.ReadInt32 ();
            long i = 0;
            if (!root.ParentLog.Strings.ContainsKey((long)(this.ChunkOffset + _ptr)))
            {
                log.BaseStream.Position = this.ChunkOffset + _ptr;

                _next = log.ReadInt32 ();
                _hash = log.ReadInt16 ();
                _length2 = log.ReadInt16 ();

                _posdiff = 2;
                this.Length = _length + 6; //6?

                _str = log.ReadBytes ((int)(_length2 * 2));
                log.BaseStream.Position += _posdiff + (_addFour ? 4 : 0);
                this.String = root.ParentLog.Strings[this.ChunkOffset + _ptr] = System.Text.Encoding.Unicode.GetString (_str);
                i = this.Length - (11 + (_length2+1)*2 + (_addFour ? 4 : 0));
            }
            else
            {
                this.String = root.ParentLog.Strings[this.ChunkOffset + _ptr];
                _length2 = 0;
                log.BaseStream.Position += (_addFour ? 4 : 0);
                i = this.Length - (11 + (_addFour ? 4 : 0));
            }

            this.ChildNodes = new List<INode>();
            i -= 8;
            while(i >= 0 && !root.ReachedEOS)
            {
                Console.WriteLine("Current length: " + i);
                INode node = LogNode.NewNode(log, this, chunkOffset, this.LogRoot);
                this.ChildNodes.Add(node);
                i -= node.Length;

                if (node is _x00)
                    root.ReachedEOS = true;
            }
        }
Exemple #20
0
        public _x05(BinaryReader log, long chunkOffset, LogRoot root, INode parent)
        {
            this.Position = log.BaseStream.Position;
            this.Type  = log.ReadByte();
            short length = log.ReadInt16();
            this.SelfEnclosed = true;

            this.LogRoot = root;

            this.TagState = root.TagState;

            IType type = null;
            switch(this.Type)
            {
            case 0x01:
                type = new Type0x01(log, length, false);
                break;
            default:
                throw new Exception("Don't know type: " + this.Type);
            }

            this.String = type.String;
            this.Length =  ((length)*2) + 4;
        }
        public static IType NewType(BinaryReader log, short[] sizetype, long chunkOffset, LogRoot root, bool isSubstArray)
        {
            short size = sizetype[0];
            short type = sizetype[1];

            Console.WriteLine("New type " + type + " at offset: " + (log.BaseStream.Position - chunkOffset));

            if (type == 0x00)
            {
                return(new Type0x00(log, size));
            }
            else if (type == 0x01)
            {
                return(new Type0x01(log, size, isSubstArray));
            }
            else if (type == 0x02)
            {
                return(new Type0x02(log, size));
            }
            else if (type == 0x03)
            {
                return(new Type0x03(log, size));
            }
            else if (type == 0x04)
            {
                return(new Type0x04(log, size));
            }
            else if (type == 0x05)
            {
                return(new Type0x05(log, size));
            }
            else if (type == 0x06)
            {
                return(new Type0x06(log, size));
            }
            else if (type == 0x08)
            {
                return(new Type0x08(log, size));
            }
            else if (type == 0x09)
            {
                return(new Type0x09(log, size));
            }
            else if (type == 0x0A)
            {
                return(new Type0x0A(log, size));
            }
            else if (type == 0x0B)
            {
                return(new Type0x0B(log, size));
            }
            else if (type == 0x0C)
            {
                return(new Type0x0C(log, size));
            }
            else if (type == 0x0D)
            {
                return(new Type0x0D(log, size));
            }
            else if (type == 0x0E)
            {
                return(new Type0x0E(log, size));
            }
            else if (type == 0x0F)
            {
                return(new Type0x0F(log, size));
            }
            else if (type == 0x10)
            {
                return(new Type0x10(log, size));
            }
            else if (type == 0x11)
            {
                return(new Type0x11(log, size));
            }
            else if (type == 0x12)
            {
                return(new Type0x12(log, size));
            }
            else if (type == 0x13)
            {
                return(new Type0x13(log, size));
            }
            else if (type == 0x14)
            {
                return(new Type0x14(log, size));
            }
            else if (type == 0x15)
            {
                return(new Type0x15(log, size));
            }
            else if (type == 0x21)
            {
                return(new Type0x21(log, size, chunkOffset, root));
            }
            else if (type == 0x81)
            {
                return(new Type0x81(log, size));
            }
            else if (type == 0x83)
            {
                return(new Type0x83(log, size));
            }
            else if (type == 0x84)
            {
                return(new Type0x84(log, size));
            }
            else if (type == 0x85)
            {
                return(new Type0x85(log, size));
            }
            else if (type == 0x86)
            {
                return(new Type0x86(log, size));
            }
            else if (type == 0x87)
            {
                return(new Type0x87(log, size));
            }
            else if (type == 0x88)
            {
                return(new Type0x88(log, size));
            }
            else if (type == 0x89)
            {
                return(new Type0x89(log, size));
            }
            else if (type == 0x8A)
            {
                return(new Type0x8A(log, size));
            }
            else if (type == 0x8B)
            {
                return(new Type0x8B(log, size));
            }
            else if (type == 0x8C)
            {
                return(new Type0x8C(log, size));
            }
            else if (type == 0x8F)
            {
                return(new Type0x8F(log, size));
            }
            else if (type == 0x91)
            {
                return(new Type0x91(log, size));
            }
            else if (type == 0x92)
            {
                return(new Type0x92(log, size));
            }
            else if (type == 0x94)
            {
                return(new Type0x94(log, size));
            }
            else if (type == 0x95)
            {
                return(new Type0x95(log, size));
            }
            else
            {
                throw new Exception("Don't know type: " + type + " at offset: " + (log.BaseStream.Position - 1));
            }
        }
        public EventLog(string filename)
        {
            this.Strings = new Dictionary <long, string>();

            using (FileStream stream = File.OpenRead(filename))
            {
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    byte[] h = reader.ReadBytes(8);

                    if (!(h[0] == 'E' && h[1] == 'l' && h[2] == 'f' && h[3] == 'F' && h[4] == 'i' && h[5] == 'l' && h[6] == 'e'))
                    {
                        throw new Exception("Unsupported file type");
                    }

                    int numOldLow, numOldHigh;
                    int numCurLow, numCurHigh;
                    int nextRecLow, nextRecHigh;

                    numOldLow   = reader.ReadInt32();
                    numOldHigh  = reader.ReadInt32();
                    numCurLow   = reader.ReadInt32();
                    numCurHigh  = reader.ReadInt32();
                    nextRecLow  = reader.ReadInt32();
                    nextRecHigh = reader.ReadInt32();

                    int numOld  = (numOldHigh << 32) ^ numOldLow;
                    int numCur  = (numCurHigh << 32) ^ numCurLow;
                    int nextRec = (nextRecHigh << 32) ^ nextRecLow;

                    byte[] headerPart, versionMinor, versionMajor, headerLen, chunkCount;

                    headerPart   = reader.ReadBytes(4);
                    versionMinor = reader.ReadBytes(2);
                    versionMajor = reader.ReadBytes(2);
                    headerLen    = reader.ReadBytes(2);
                    chunkCount   = reader.ReadBytes(2);

                    if (!BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(headerLen);
                        Array.Reverse(headerPart);
                        Array.Reverse(versionMajor);
                        Array.Reverse(versionMinor);
                        Array.Reverse(chunkCount);
                    }

                    int chunkc = BitConverter.ToInt16(chunkCount, 0);


                    long chunkOffset = 0x1000;
                    reader.BaseStream.Position = chunkOffset;

                    int n = 1;
                    for (int k = 0; k < chunkc; k++)
                    {
                        h = reader.ReadBytes(8);

                        if (!(h[0] == 'E' && h[1] == 'l' && h[2] == 'f' && h[3] == 'C' && h[4] == 'h' && h[5] == 'n' && h[6] == 'k'))
                        {
                            throw new Exception("Bad chunk at offset: " + reader.BaseStream.Position);
                        }

                        ulong first     = reader.ReadUInt64();
                        ulong last      = reader.ReadUInt64();
                        ulong rfirst    = reader.ReadUInt64();                     //redundant first
                        ulong rlast     = reader.ReadUInt64();                     //redundant last
                        uint  unk1      = reader.ReadUInt32();
                        uint  unk2      = reader.ReadUInt32();
                        uint  offset    = reader.ReadUInt32();
                        uint  crcData   = reader.ReadUInt32();
                        uint  crcHeader = reader.ReadUInt32();

                        if (crcData == 0)
                        {
                            continue;                                          //empty chunk
                        }
                        uint nextOffset = 0x200;                               //first event in a chunk
                        reader.BaseStream.Position = chunkOffset + nextOffset; //(512+4096)

                        this.Roots = new List <LogRoot>();
                        for (ulong i = first; i <= last; i++)
                        {
                            long pos = reader.BaseStream.Position;

                            h = reader.ReadBytes(2);

                            if (h[0] != '*' || h[1] != '*')
                            {
                                Console.WriteLine("Bad event at position: " + reader.BaseStream.Position);
                                continue;
                            }

                            reader.BaseStream.Position += 2;

                            uint  el  = reader.ReadUInt32() - 28;
                            long  rid = reader.ReadInt64();
                            ulong ts  = reader.ReadUInt64();

                            ts /= 1000;
                            ts -= 116444736000000;

                            int      secs      = (int)(ts / 10000);
                            DateTime timestamp = GetTime(secs);

                            LogRoot root = new LogRoot(reader, chunkOffset, el, this)
                            {
                                Offset = pos
                            };

                            Console.WriteLine(root.ToXML());

                            this.Roots.Add(root);
                            reader.BaseStream.Position = (el + pos);
                        }

                        reader.BaseStream.Position = chunkOffset = (n++ *0x10000) + 0x1000;
                    }
                }
            }

            string xml = "<Events>";

            foreach (LogRoot root in this.Roots)
            {
                xml += root.ToXML();
            }

            Console.WriteLine(xml);
            xml += "</Events>";

            this.XmlDocument = new XmlDocument();
            this.XmlDocument.LoadXml(xml);
        }
Exemple #23
0
        public Type0x21(BinaryReader log, int size, long chunkOffset, LogRoot root)
        {
            LogRoot newRoot = new LogRoot(log, chunkOffset, (uint)size, root.ParentLog);

            this.String = newRoot.ToXML();
        }
        public static IType NewType(BinaryReader log, short[] sizetype, long chunkOffset, LogRoot root, bool isSubstArray)
        {
            short size = sizetype[0];
            short type = sizetype[1];

            Console.WriteLine("New type " + type + " at offset: " + (log.BaseStream.Position-chunkOffset));

            if (type == 0x00)
                return new Type0x00(log, size);
            else if (type == 0x01)
                return new Type0x01(log, size, isSubstArray);
            else if (type == 0x02)
                return new Type0x02(log, size);
            else if (type == 0x03)
                return new Type0x03(log, size);
            else if (type == 0x04)
                return new Type0x04(log, size);
            else if (type == 0x05)
                return new Type0x05(log, size);
            else if (type == 0x06)
                return new Type0x06(log, size);
            else if (type == 0x08)
                return new Type0x08(log, size);
            else if (type == 0x09)
                return new Type0x09(log, size);
            else if (type == 0x0A)
                return new Type0x0A(log, size);
            else if (type == 0x0B)
                return new Type0x0B(log, size);
            else if (type == 0x0C)
                return new Type0x0C(log, size);
            else if (type == 0x0D)
                return new Type0x0D(log, size);
            else if (type == 0x0E)
                return new Type0x0E(log, size);
            else if (type == 0x0F)
                return new Type0x0F(log, size);
            else if (type == 0x10)
                return new Type0x10(log, size);
            else if (type == 0x11)
                return new Type0x11(log, size);
            else if (type == 0x12)
                return new Type0x12(log, size);
            else if (type == 0x13)
                return new Type0x13(log, size);
            else if (type == 0x14)
                return new Type0x14(log, size);
            else if (type == 0x15)
                return new Type0x15(log, size);
            else if (type == 0x21)
                return new Type0x21(log, size, chunkOffset, root);
            else if (type == 0x81)
                return new Type0x81(log, size);
            else if (type == 0x83)
                return new Type0x83(log, size);
            else if (type == 0x84)
                return new Type0x84(log, size);
            else if (type == 0x85)
                return new Type0x85(log, size);
            else if (type == 0x86)
                return new Type0x86(log, size);
            else if (type == 0x87)
                return new Type0x87(log, size);
            else if (type == 0x88)
                return new Type0x88(log, size);
            else if (type == 0x89)
                return new Type0x89(log, size);
            else if (type == 0x8A)
                return new Type0x8A(log, size);
            else if (type == 0x8B)
                return new Type0x8B(log, size);
            else if (type == 0x8C)
                return new Type0x8C(log, size);
            else if (type == 0x8F)
                return new Type0x8F(log, size);
            else if (type == 0x91)
                return new Type0x91(log, size);
            else if (type == 0x92)
                return new Type0x92(log, size);
            else if (type == 0x94)
                return new Type0x94(log, size);
            else if (type == 0x95)
                return new Type0x95(log, size);
            else
                throw new Exception("Don't know type: " + type + " at offset: " + (log.BaseStream.Position - 1));
        }
        public static INode NewNode(BinaryReader log, INode parent, long chunkOffset, LogRoot root)
        {
            long pos   = log.BaseStream.Position;
            byte op    = log.ReadByte();
            int  flags = op >> 4;

            //This is important, you will come across bytes in the hex editor
            //that start a node with BA, BC, etc and this is what will "fix" them
            op = (byte)(op & 0x0f);

            Console.WriteLine("New subnode of type " + op + " at offset: " + ((log.BaseStream.Position - chunkOffset) - 1));

            INode node = null;

            if (op == 0x0f)
            {
                node = new _x0F(log, chunkOffset, root, parent);
            }
            else if (op == 0x0c)
            {
                node = new _x0C(log, chunkOffset, root, parent);
            }
            else if (op == 0x01)
            {
                node = new _x01(log, chunkOffset, flags, root, parent);
            }
            else if (op == 0x02)
            {
                node = new _x02(log, chunkOffset, root, parent);
            }
            else if (op == 0x03)
            {
                node = new _x03(log, chunkOffset, root, parent);
            }
            else if (op == 0x04)
            {
                node = new _x04(log, chunkOffset, root, parent);
            }
            else if (op == 0x07)
            {
                node = new _x07(log, chunkOffset, root, parent);
            }
            else if (op == 0x06)
            {
                node = new _x06(log, chunkOffset, root, parent);
            }
            else if (op == 0x05)
            {
                node = new _x05(log, chunkOffset, root, parent);
            }
            else if (op == 0x0b)
            {
                node = new _x0B(log, chunkOffset, root, parent);
            }
            else if (op == 0x0d)
            {
                node = new _x0D(log, chunkOffset, root, parent);
            }
            else if (op == 0x0e)
            {
                node = new _x0E(log, chunkOffset, root, parent);
            }
            else if (op == 0x00)
            {
                node = new _x00(log, chunkOffset, root, parent);
            }
            else
            {
                throw new Exception(String.Format("Don't know op: 0x{0:x2} at position {1}", op, log.BaseStream.Position - 1));
            }

            return(node);
        }
        public Type0x21(BinaryReader log, int size, long chunkOffset, LogRoot root)
        {
            LogRoot newRoot = new LogRoot(log, chunkOffset, (uint)size, root.ParentLog);

            this.String = newRoot.ToXML();
        }