Ejemplo n.º 1
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            byte[] buf = new byte[4];
            BinaryReader rd = new BinaryReader(strm);
            int numFiles;
            List<FileEntry> results = new List<FileEntry>();

            rd.Read(buf, 0, 4);
            if (Encoding.ASCII.GetString(buf, 0, 4) != "TGP0")
                return results;

            if (rd.ReadInt32() != 1)  // version check
                return results;

            if (rd.ReadInt32() != 0)  // should be zero
                return results;

            numFiles = rd.ReadInt32();
            buf = new byte[0x60];
            for (int i = 0; i < numFiles; i++)
            {
                FileEntry ent = new FileEntry();

                rd.Read(buf, 0, 0x60);
                ent.Filename = Encoding.ASCII.GetString(buf);
                ent.Filename = ent.Filename.Substring(0, ent.Filename.IndexOf('\0'));
                ent.Offset = rd.ReadInt64();
                ent.UncompressedSize = rd.ReadInt64();

                results.Add(ent);
            }

            return results;
        }
Ejemplo n.º 2
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            ZipEntry ze;
            ZipInputStream zstrm = new ZipInputStream(strm, true);
            List<FileEntry> results = new List<FileEntry>();
            FileEntry fe;

            SetupZIPParams();
            while (true)
            {
                ze = zstrm.GetNextEntry();
                if (ze == null)
                    break;

                if (ze.IsDirectory)
                    continue;

                fe = new FileEntry();
                fe.Filename = ze.FileName;
                fe.UncompressedSize = ze.UncompressedSize;
                fe.Timestamp = ze.LastModified;
                results.Add(fe);
            };

            return results;
        }
Ejemplo n.º 3
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            ArcEntry[] entries = GetDirectory(strm, false);
            List<FileEntry> results = new List<FileEntry>();

            for (int i = 0; i < entries.Length; i++)
            {
                FileEntry fe = new FileEntry();
                fe.Filename = NormalizeFileName(entries[i].Filename);
                fe.UncompressedSize = entries[i].UncompressedLength;
                yield return fe;
            }
        }
Ejemplo n.º 4
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            List<FileEntry> results = new List<FileEntry>();

            foreach (ArcEntry ae in GetDirectory(strm, false))
            {
                FileEntry fe = new FileEntry();
                fe.Filename = ae.Filename;
                fe.UncompressedSize = ae.Length;
                results.Add(fe);
            }

            return results;
        }
Ejemplo n.º 5
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            ArcEntry[] files = GetDirectory(strm);
            List<FileEntry> results = new List<FileEntry>();

            for (int i = 0; i < files.Length; i++)
            {
                FileEntry fe = new FileEntry();
                fe.Filename = files[i].FileName;
                fe.UncompressedSize = files[i].Length;
                results.Add(fe);
            }

            return results;
        }
Ejemplo n.º 6
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            List<FileEntry> results = new List<FileEntry>();

            if (!ReadHeader(strm))
                return null;

            foreach (System.Xml.XmlElement elt in fileList.SelectNodes("Files/File"))
            {
                FileEntry f = new FileEntry();
                f.Filename = elt.SelectNodes("@Name").Item(0).InnerText;
                f.UncompressedSize = Convert.ToInt64(elt.SelectNodes("@Size").Item(0).InnerText);
                results.Add(f);
            }

            return results;
        }
Ejemplo n.º 7
0
        public List<FileEntry> GetDirectory(Stream strm)
        {
            List<FileEntry> results = new List<FileEntry>();
            BinaryReader rd = new BinaryReader(strm);
            int numFiles;

            numFiles = rd.ReadInt32();
            // check if header is within file
            if (strm.Length < 8 * numFiles + 4)
                return null;

            // sanity check file count
            if (numFiles > 1000000)
                return null;

            for (int i = 0; i < numFiles; i++)
            {
                FileEntry ent = new FileEntry();
                ent.Offset = rd.ReadUInt32();
                ent.UncompressedSize = rd.ReadUInt32();
                ent.FileIndex = i;
                ent.Filename = String.Format("{0:000000}", i);
                results.Add(ent);
            }
            // sanity check
            for (int i = 0; i < results.Count; i++)
            {
                // check if size is within file
                if (results[i].Offset + results[i].UncompressedSize > strm.Length)
                    return null;
                // check if size is sane
                if ((results[i].Offset < 0) || (results[i].UncompressedSize < 0))
                    return null;
                if ((results[i].Offset > 2U * 1024U * 1024U * 1024U) || (results[i].UncompressedSize > 2U * 1024U * 1024U * 1024U))
                    return null;

                if (i > 0)
                {
                    // file must start after previous file
                    if (results[i].Offset < results[i - 1].Offset + results[i - 1].UncompressedSize)
                        return null;
                }
            }

            return results;
        }
Ejemplo n.º 8
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            ArchiveFile afile;

            if (!IsTankFile(strm))
                yield break;

            afile = ReadDirectory(strm);

            foreach (FileSetEntry fse in afile.FileSet.Entries)
            {
                FileEntry fe = new FileEntry();
                fe.UncompressedSize = fse.Size;
                fe.Filename = GetRelPath(afile, fse);

                yield return fe;
            }
        }
Ejemplo n.º 9
0
        List<FileEntry> GetDirectory(Stream strm)
        {
            List<FileEntry> results = new List<FileEntry>();
            BinaryReader rd = new BinaryReader(strm);
            int numFiles;

            if (rd.ReadUInt32() != 0x00534641)
                return null;

            numFiles = rd.ReadInt32();

            for (int i = 0; i < numFiles; i++)
            {
                FileEntry fe = new FileEntry();
                fe.Offset = rd.ReadInt32();
                fe.UncompressedSize = rd.ReadInt32();
                fe.Filename = String.Format("{0,8:00000000}.raw", i);

                results.Add(fe);
            }

            return results;
        }
Ejemplo n.º 10
0
        private List<FileEntry> GetDirectory(Stream strm)
        {
            byte[] buf = new byte[8];
            List<FileEntry> results;
            BinaryReader rd = new BinaryReader(strm);
            int numFiles;
            byte[] fname = new byte[32];

            strm.Read(buf, 0, 8);
            if (Encoding.ASCII.GetString(buf) != "NISPACK\0")
                return null;

            rd.ReadInt32(); // unknown, 0x10000000
            numFiles = FromBE(rd.ReadInt32());

            results = new List<FileEntry>();

            for (int i = 0; i < numFiles; i++)
            {
                FileEntry ent = new FileEntry();

                rd.Read(fname, 0, 32);
                ent.Filename = Encoding.GetEncoding("SJIS").GetString(fname);
                if (ent.Filename.Contains("\0"))
                    ent.Filename = ent.Filename.Substring(0, ent.Filename.IndexOf('\0'));
                ent.Offset = FromBE(rd.ReadInt32());
                ent.UncompressedSize = FromBE(rd.ReadInt32());
                ent.StringData["Unknown"] = String.Format("0x{0:x8}", FromBE(rd.ReadInt32()));

                results.Add(ent);
            }

            return results;
        }
Ejemplo n.º 11
0
        List<FileEntry> ReadDirectory(Stream strm, Callbacks callbacks)
        {
            List<FileEntry> results = new List<FileEntry>();
            BinaryReader rd = new BinaryReader(strm);
            Int32 numFiles;

            if (rd.ReadUInt32() != 0x5041434b)
                return null;

            numFiles = rd.ReadInt32();
            if (numFiles > 100000)
                return null;

            for (int i = 0; i < numFiles; i++)
            {
                FileEntry ent = new FileEntry();
                byte[] namebuf = new byte[24];

                ent.LongData["type"] = rd.ReadUInt32(); // 0x0, 0x1 = file, 0xcccccccc = dir?
                if ((ent.LongData["type"] != 1) && (ent.LongData["type"] != 0) && (ent.LongData["type"] != 0xcccccccc))
                    return null;

                rd.Read(namebuf, 0, 24);
                ent.Filename = Encoding.GetEncoding("SJIS").GetString(namebuf).TrimEnd('\0');
                ent.Offset = rd.ReadUInt32();
                ent.UncompressedSize = rd.ReadUInt32();
                if (ent.UncompressedSize > 1024 * 1024 * 1024)
                    return null;
                if (ent.Offset > 1024 * 1024 * 1024)
                    return null;

                results.Add(ent);
            }

            return results;
        }
Ejemplo n.º 12
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            DirEntry[] files = GetDirectory(strm, false);
            List<FileEntry> fes = new List<FileEntry>();

            for (int i = 0; i < files.Length; i++)
            {
                FileEntry fe = new FileEntry();

                fe.Filename = String.Format("{0:x8}.{1}", i, GetExtension(files[i].Flags));
                fe.UncompressedSize = files[i].Size;

                fes.Add(fe);
            }

            return fes;
        }
Ejemplo n.º 13
0
        public IEnumerable<FileEntry> ListFiles(Stream strm, Callbacks callbacks)
        {
            List<FileEntry> results = new List<FileEntry>();
            int magic;
            BinaryReader rd;
            int numFiles;
            int baseOffset;
            int totalSize;
            Stream xorStream;
            BinaryReader xrd;

            if (!IsSupported(strm, callbacks))
                return null;

            strm.Seek(2 + 4 + 4, SeekOrigin.Current);
            rd = new BinaryReader(strm);
            magic = rd.ReadInt32();
            m_XORValue = (byte)(~magic & 0xff);
            xorStream = new Shared.XORStream(strm, callbacks.TransformerRegistry, m_XORValue);
            xrd = new BinaryReader(xorStream);
            xrd.ReadInt32();
            xrd.ReadInt32();
            numFiles = xrd.ReadInt32();
            xrd.ReadInt32();
            baseOffset = xrd.ReadInt32();
            totalSize = xrd.ReadInt32();

            // read file info region
            for (int i = 0; i < numFiles; i++)
            {
                FileEntry ent = new FileEntry();
                ent.UncompressedSize = xrd.ReadInt32();
                ent.Offset = xrd.ReadInt32() + baseOffset;

                Int32 nameOffset = xrd.ReadByte();
                nameOffset |= (int)xrd.ReadByte() << 8;
                nameOffset |= (int)xrd.ReadByte() << 16;
                ent.LongData["nameoffset"] = nameOffset;
                xrd.ReadByte();
                xrd.ReadInt32();

                results.Add(ent);
            }
            // read the file name region
            byte[] fnames = new byte[baseOffset - 16 * numFiles - 0x34];
            int xbyte = fnames.Length;

            xrd.Read(fnames, 0, fnames.Length);

            for (int i = 0; i < fnames.Length; i++)
            {
                byte by = (byte)(fnames[i] ^ 0xc4);
                by += (byte)(xbyte & 0xff);
                fnames[i] = by;
                xbyte--;
            }

            // get names for every file
            foreach (FileEntry ent in results)
            {
                int nameOffset = (int)ent.LongData["nameoffset"] + 2;
                StringBuilder sb = new StringBuilder();
                while (fnames[nameOffset] != 0)
                    sb.Insert(0, (char)fnames[nameOffset++]);

                ent.Filename = sb.ToString();
            }

            return results;
        }
Ejemplo n.º 14
0
        private List<FileEntry> GetDirectory(Stream strm)
        {
            byte[] idbuf = new byte[8];
            byte[] namebuf;
            BinaryReader rd;
            UInt32 numFiles;
            UInt32 OffsetDelta;
            List<FileEntry> results = new List<FileEntry>();
            FileEntry ent;

            strm.Read(idbuf, 0, 8);
            if (Encoding.ASCII.GetString(idbuf) != "DW_PACK\0")
                return null;

            rd = new BinaryReader(strm);
            if (rd.ReadUInt32() != 0)
                return null;

            numFiles = rd.ReadUInt32();
            if ((numFiles == 0) || (numFiles > 0x100000)) // arbitrary upper limit
                return null;

            rd.ReadUInt32(); // skip 8 bytes
            rd.ReadUInt32();

            OffsetDelta = numFiles * 0x120 + 0x18; // the header size

            for (uint i = 0; i < numFiles; i++)
            {
                ent = new FileEntry();

                ent.LongData["unk1"] = rd.ReadUInt32(); // lower 16 bits contain file index, upper 16 bit = 1 for compressed??

                namebuf = new byte[0x100];
                rd.Read(namebuf, 0, 0x100);
                ent.Filename = Encoding.ASCII.GetString(namebuf).Trim('\0');
                rd.ReadUInt32();
                rd.ReadUInt32();
                ent.CompressedSize = rd.ReadUInt32();
                ent.UncompressedSize = rd.ReadUInt32();

                ent.LongData["unk2"] = rd.ReadInt32();

                ent.Offset = rd.ReadInt32() + OffsetDelta;
                ent.LongData["unk3"] = rd.ReadUInt32(); // =0 except for last file which has 0x1234

                results.Add(ent);
            }

            return results;
        }
Ejemplo n.º 15
0
        List<FileEntry> GetDirectory(Stream strm)
        {
            List<FileEntry> results = new List<FileEntry>();
            BinaryReader rd = new BinaryReader(strm);
            byte[] tocEntry = new byte[28];
            int numFiles;
            FileEntry ent;

            rd.Read(tocEntry, 0, 28);
            tocEntry = DecryptBuffer(tocEntry, "32768GLB");
            numFiles = BitConverter.ToInt32(tocEntry, 4);

            for (int i = 0; i < numFiles; i++)
            {
                rd.Read(tocEntry, 0, 28);
                tocEntry = DecryptBuffer(tocEntry, "32768GLB");

                ent = new FileEntry();
                ent.Offset = BitConverter.ToInt32(tocEntry, 4);
                ent.UncompressedSize = BitConverter.ToInt32(tocEntry, 8);
                ent.LongData["encrypted"] = BitConverter.ToInt32(tocEntry, 0);
                ent.Filename = Encoding.ASCII.GetString(tocEntry, 12, 16);
                ent.Filename = String.Format("0x{0:x8}_{1}", ent.Offset, ent.Filename.Substring(0, ent.Filename.IndexOf((char)0x00)));

                results.Add(ent);
            }

            return results;
        }
Ejemplo n.º 16
0
        List<FileEntry> GetDirectory(Stream strm, bool CheckOnly)
        {
            byte[] buf = new byte[8];
            byte[] namebuf = new byte[16];
            BinaryReader rd = new BinaryReader(strm);
            int numFiles;
            List<FileEntry> results = new List<FileEntry>();

            // read ID string
            rd.Read(buf, 0, 8);
            // ID string must be zero terminated
            if (rd.ReadByte() != 0)
                return null;
            // sanity check for number of files
            numFiles = rd.ReadInt32();
            if (numFiles < 0 || numFiles > 100000)
                return null;
            if (Encoding.ASCII.GetString(buf) != "PAC_FILE")
                return null;

            if (CheckOnly)
                return results; // anything that is not-null will suffice here...

            for (int i = 0; i < numFiles; i++)
            {
                FileEntry ent = new FileEntry();

                // read filename and size
                rd.Read(namebuf, 0, 16);
                // TODO: check if the file name encoding is correct! it's only a guess since it is definitely NOT US-ASCII
                ent.Filename = Encoding.GetEncoding("shift_jis").GetString(namebuf).TrimEnd('\0');
                ent.Offset = rd.ReadInt32() + 4;
                if (i > 0)
                {
                    results[i - 1].UncompressedSize = ent.Offset - results[i - 1].Offset;
                }
                results.Add(ent);
            }
            // calculate the length of the final file
            results[numFiles - 1].UncompressedSize = (int)(strm.Length - results[numFiles - 1].Offset);

            return results;
        }
Ejemplo n.º 17
0
        private List<FileEntry> GetDirectory(Stream strm)
        {
            List<FileEntry> results = new List<FileEntry>();
            byte[] buf;
            string subdir;
            UInt32 DirectoryStart = 0, DirectoryLength = 0, NumFiles = 0;

            // check for "LOD\0" signature
            buf = new byte[4];
            strm.Read(buf, 0, 4);
            if (Encoding.ASCII.GetString(buf, 0, 3) != "LOD" || buf[3] != 0)
                return null;

            // check if the 'game name' is ASCII
            buf = new byte[12];
            strm.Read(buf, 0, 12);
            string name = Encoding.ASCII.GetString(buf).TrimEnd('\0');
            foreach (char c in name)
            {
                if (c < 32 || c > 127)
                    return null;
            }

            // skip some unknown bytes
            strm.Seek(256-16, SeekOrigin.Current);

            // get the subdirectory name and trim it
            buf = new byte[16];
            strm.Read(buf, 0, 16);
            subdir = Encoding.ASCII.GetString(buf);
            if (subdir.Contains("\0"))
                subdir = subdir.Substring(0, subdir.IndexOf('\0'));

            if (!ReadUInt32(strm, ref DirectoryStart))
                return null;

            if (!ReadUInt32(strm, ref DirectoryLength))
                return null;

            strm.Seek(4, SeekOrigin.Current);

            if (!ReadUInt32(strm, ref NumFiles))
                return null;

            strm.Seek(DirectoryStart, SeekOrigin.Begin);

            // read the file directory
            for (int i = 0; i < NumFiles; i++)
            {
                FileEntry ent = new FileEntry();
                UInt32 tmp = 0;

                buf = new byte[16];
                strm.Read(buf, 0, 16);
                string fname = Encoding.ASCII.GetString(buf);
                if (fname.Contains("\0"))
                    fname = fname.Substring(0, fname.IndexOf('\0'));
                ent.Filename = String.Format("{0}/{1}", subdir, fname);
                // read the start offset
                if (!ReadUInt32(strm, ref tmp))
                    return null;
                ent.Offset = DirectoryStart + tmp; // make sure the offset is relative to the file

                // read the size
                if (!ReadUInt32(strm, ref tmp))
                    return null;
                ent.UncompressedSize = tmp;

                // skip the next 8 bytes
                strm.Seek(8, SeekOrigin.Current);

                results.Add(ent);
            }

            return results;
        }
Ejemplo n.º 18
0
        public static List<FileEntry> Load(byte[] buffer, int xorkey)
        {
            List<FileEntry> results = new List<FileEntry>();
            Stack<Object> stack = new Stack<object>();
            Stack<int> marks = new Stack<int>();
            int pos = 2;
            byte opcode;
            bool stop = false;

            // we only support the binary Python Pickle Protocol 2
            if ((buffer[0] != 0x80) || (buffer[1] != 0x02))
                return results;

            while (pos < buffer.Length && !stop)
            {
                opcode = buffer[pos++];
                switch (opcode)
                {
                    case 0x7d: // '}'  EMPTY_DICT
                        stack.Push(new Dictionary<string, object>());
                        break;
                    case 0x71: // 'q'  BINPUT
                        // skip 1 additional byte
                        pos++;
                        break;
                    case 0x72: // 'r'  LONG_BINPUT
                        // skip 4 bytes
                        pos += 4;
                        break;
                    case 0x28: // '('  MARK
                        // skip
                        marks.Push(stack.Count);
                        break;
                    case 0x58: // 'X'  BINUNICODE
                        Int32 strlen = (Int32)buffer[pos] + 256 * (Int32)buffer[pos + 1] + 256 * 256 * (Int32)buffer[pos + 2] + 256 * 256 * 256 * (Int32)buffer[pos + 3];
                        string s;

                        s = Encoding.UTF8.GetString(buffer, pos + 4, strlen);
                        stack.Push(s);
                        pos += 4 + strlen;

                        break;
                    case 0x5d: // ']'  EMPTY_LIST
                        stack.Push(new List<object>());
                        break;
                    case 0x4a: // 'J'  BININT
                        Int32 value = (Int32)buffer[pos] + 256 * (Int32)buffer[pos + 1] + 256 * 256 * (Int32)buffer[pos + 2] + 256 * 256 * 256 * (Int32)buffer[pos + 3];

                        stack.Push(value);
                        pos += 4;

                        break;
                    case 0x55: // 'U'  SHORT_BINSTRING
                        byte datalen = buffer[pos++];
                        byte[] data = new byte[datalen];

                        for (int i = 0; i < datalen; i++)
                            data[i] = buffer[pos++];
                        stack.Push(data);

                        break;
                    case 0x87: // '.'  BUILD_TUPLE3
                        object obj3 = stack.Pop();
                        object obj2 = stack.Pop();
                        object obj1 = stack.Pop();
                        Tuple<object, object, object> tuple = new Tuple<object,object,object>(obj1, obj2, obj3);

                        stack.Push(tuple);

                        break;
                    case 0x61: // 'a'  APPEND
                        object toAppend  = stack.Pop();
                        object theList = stack.Peek();
                        if (theList is List<object>)
                            (theList as List<object>).Add(toAppend);

                        break;
                    case 0x75: // 'u'  SETITEMS
                        int numItems = stack.Count - marks.Pop();
                        List<object> itemsToSet = new List<object>();
                        for (int i = 0; i < numItems; i++)
                            itemsToSet.Add(stack.Pop());

                        itemsToSet.Reverse();

                        // check item on stack
                        if (stack.Peek() is Dictionary<string, object>)
                        {
                            Dictionary<string, object> thedict = stack.Peek() as Dictionary<string, object>;

                            for (int i = 0; i < numItems; i += 2)
                            {
                                string key = itemsToSet[i].ToString();
                                object val = itemsToSet[i + 1];

                                thedict.Add(key, val);
                            }
                        }
                        // TODO: handle other SETITEMs (for lists etc)...

                        break;
                    case 0x8a: // '.' Make BigInt with <2048 bits
                        byte count = buffer[pos++];
                        if (count > 8)
                            throw new InvalidOperationException("Unsupported BIGINT with >64bit");
                        long res = 0;

                        for (int i = 0; i < count; i++)
                        {
                            res |= ((long)(buffer[pos++]) << (8*i));
                        }
                        if (count <= 4)
                        {
                            Int32 val = (int)res;
                            stack.Push(val);
                        }
                        else
                        {
                            Int64 val = res;
                            stack.Push(res);
                        }
                        break;
                    case 0x2e: // '.'  STOP
                        stop = true;
                        break;
                    default:
                        if (System.Diagnostics.Debugger.IsAttached)
                            System.Diagnostics.Debugger.Break();
                        throw new NotSupportedException(String.Format("Invalid Pickle opcode 0x{0:02x}", opcode));
                }
            }
            // stack contains one dictionary (at least we hope so)
            Dictionary<string, object> dict = stack.Pop() as Dictionary<string, object>;

            if (dict == null)
                return null;

            foreach (string s in dict.Keys)
            {
                FileEntry ent = new FileEntry();
                List<object> ldata = dict[s] as List<object>;
                Tuple<object, object, object> data3;

                if (ldata == null)
                {
                    System.Diagnostics.Debugger.Break();
                }
                data3 = ldata[0] as Tuple<object, object, object>;
                if (data3 == null)
                {
                    // TODO: handle 2-tuples (as soon as I find a game which uses them)
                    return null;
                }

                ent.Filename = s;
                ent.Offset = ((int)data3.Item1) ^ xorkey;
                ent.UncompressedSize = ((int)data3.Item2) ^ xorkey;
                if ((data3.Item3 as byte[]).Length > 0)
                    ent.ObjectData["prefix"] = data3.Item3;

                results.Add(ent);
            }

            return results;
        }
Ejemplo n.º 19
0
        private List<FileEntry> GetDirectory(Stream strm)
        {
            List<FileEntry> results = new List<FileEntry>();
            BinaryReader rd = new BinaryReader(strm);
            ArchiveHeader ahdr;
            FileHeader fhdr;
            int i = 0;

            ahdr = ReadArchiveHeader(rd);
            if (ahdr == null)
                return null;

            fhdr = ReadFileHeader(rd);
            while (fhdr != null)
            {
                FileEntry ent = new FileEntry();
                ent.FileIndex = i++;
                ent.Filename = fhdr.Filename;
                ent.CompressedSize = fhdr.CompressedSize;
                ent.UncompressedSize = fhdr.OriginalSize;
                ent.Timestamp = fhdr.FileModified;
                ent.ObjectData["FileHeader"] = fhdr;
                rd.BaseStream.Seek(fhdr.CompressedSize, SeekOrigin.Current);

                results.Add(ent);

                // read next header
                fhdr = ReadFileHeader(rd);
            }

            return results;
        }