Esempio n. 1
0
        private static void Explore(CASCFolder folder, string findFile, SearchType type, List <CASCFile> found)
        {
            foreach (KeyValuePair <string, ICASCEntry> node in folder.Entries)
            {
                ICASCEntry entry = node.Value;

                if (entry is CASCFolder)
                {
                    Explore((CASCFolder)entry, findFile, type, found);
                }
                else if (entry is CASCFile)
                {
                    CASCFile file     = (CASCFile)entry;
                    string   fileName = file.FullName.ToLower();

                    if (type == SearchType.COMPLETE && fileName.Equals(fileName))
                    {
                        found.Add(file);
                        break;
                    }

                    if (type == SearchType.STARTS_WITH && fileName.StartsWith(findFile))
                    {
                        found.Add(file);
                        continue;
                    }

                    if (type == SearchType.ENDS_WITH && fileName.EndsWith(findFile))
                    {
                        found.Add(file);
                        continue;
                    }
                }
            }
        }
Esempio n. 2
0
        private static void CreateSubTree(CASCFolder root, ulong filehash, string file)
        {
            string[] parts = file.Split('\\');

            CASCFolder folder = root;

            for (int i = 0; i < parts.Length; ++i)
            {
                bool isFile = (i == parts.Length - 1);

                ulong hash = isFile ? filehash : Hasher.ComputeHash(parts[i]);

                ICASCEntry entry = folder.GetEntry(hash);

                if (entry == null)
                {
                    if (isFile)
                    {
                        entry = new CASCFile(hash);
                        CASCFile.FileNames[hash] = file;
                    }
                    else
                    {
                        entry = new CASCFolder(hash);
                        CASCFolder.FolderNames[hash] = parts[i];
                    }

                    folder.SubEntries[hash] = entry;
                }

                folder = entry as CASCFolder;
            }
        }
Esempio n. 3
0
        private void Explore(CASCFolder folder)
        {
            foreach (KeyValuePair <string, ICASCEntry> node in folder.Entries)
            {
                ICASCEntry entry = node.Value;

                if (entry is CASCFolder)
                {
                    Explore((CASCFolder)entry);
                }
                else if (entry is CASCFile)
                {
                    CASCFile file = (CASCFile)entry;

                    // Check we have a valid extension.
                    if (!IsValidExtension(file))
                    {
                        continue;
                    }

                    // Ensure the file matches the filter.
                    if (!MatchesFilter(file.FullName))
                    {
                        continue;
                    }

                    EventManager.Trigger_FileExploreHit(id, file);
                }

                Thread.Sleep(2);
            }
        }
Esempio n. 4
0
        protected void CreateSubTree(CASCFolder root, ulong filehash, string file)
        {
            string[] parts = file.Split(PathDelimiters);

            CASCFolder folder = root;

            for (int i = 0; i < parts.Length; ++i)
            {
                bool isFile = (i == parts.Length - 1);

                string entryName = parts[i];

                ICASCEntry entry = folder.GetEntry(entryName);

                if (entry == null)
                {
                    if (isFile)
                    {
                        entry = new CASCFile(filehash);
                        CASCFile.FileNames[filehash] = file;
                    }
                    else
                    {
                        entry = new CASCFolder(entryName);
                    }

                    folder.Entries[entryName] = entry;
                }

                folder = entry as CASCFolder;
            }
        }
Esempio n. 5
0
        public int CompareTo(ICASCEntry other, int col, CASCEngine casc)
        {
            int result = 0;

            if (other is CASCFolder)
            {
                return(1);
            }

            switch (col)
            {
            case 0:
                result = Name.CompareTo(other.Name);
                break;

            case 1:
                result = Path.GetExtension(Name).CompareTo(Path.GetExtension(other.Name));
                break;

            case 2:
            {
                var e1 = casc.RootHandler.GetEntries(Hash);
                var e2 = casc.RootHandler.GetEntries(other.Hash);

                var flags1 = e1.Any() ? e1.First().LocaleFlags : LocaleFlags.None;
                var flags2 = e2.Any() ? e2.First().LocaleFlags : LocaleFlags.None;

                result = flags1.CompareTo(flags2);
            }
            break;

            case 3:
            {
                var e1 = casc.RootHandler.GetEntries(Hash);
                var e2 = casc.RootHandler.GetEntries(other.Hash);

                var flags1 = e1.Any() ? e1.First().ContentFlags : ContentFlags.None;
                var flags2 = e2.Any() ? e2.First().ContentFlags : ContentFlags.None;

                result = flags1.CompareTo(flags2);
            }
            break;

            case 4:
                var size1 = GetSize(casc);
                var size2 = (other as CASCFile).GetSize(casc);

                if (size1 == size2)
                {
                    result = 0;
                }
                else
                {
                    result = size1 < size2 ? -1 : 1;
                }
                break;
            }

            return(result);
        }
Esempio n. 6
0
        public int CompareTo(ICASCEntry other, int col, CASCEngine casc)
        {
            int result = 0;

            if (other is CASCFolder)
                return 1;

            switch (col)
            {
                case 0:
                    result = Name.CompareTo(other.Name);
                    break;
                case 1:
                    result = Path.GetExtension(Name).CompareTo(Path.GetExtension(other.Name));
                    break;
                case 2:
                    {
                        var e1 = casc.RootHandler.GetEntries(Hash);
                        var e2 = casc.RootHandler.GetEntries(other.Hash);

                        var flags1 = e1.Any() ? e1.First().LocaleFlags : LocaleFlags.None;
                        var flags2 = e2.Any() ? e2.First().LocaleFlags : LocaleFlags.None;

                        result = flags1.CompareTo(flags2);
                    }
                    break;
                case 3:
                    {
                        var e1 = casc.RootHandler.GetEntries(Hash);
                        var e2 = casc.RootHandler.GetEntries(other.Hash);

                        var flags1 = e1.Any() ? e1.First().ContentFlags : ContentFlags.None;
                        var flags2 = e2.Any() ? e2.First().ContentFlags : ContentFlags.None;

                        result = flags1.CompareTo(flags2);
                    }
                    break;
                case 4:
                    var size1 = GetSize(casc);
                    var size2 = (other as CASCFile).GetSize(casc);

                    if (size1 == size2)
                        result = 0;
                    else
                        result = size1 < size2 ? -1 : 1;
                    break;
            }

            return result;
        }
Esempio n. 7
0
        protected override void LoadHeroesMapMods()
        {
            CASCFolder currentFolder = CASCFolderData.GetDirectory(HeroesMapModsDirectoryPath);

            // loop through each mapmods folder
            foreach (KeyValuePair <string, ICASCEntry> mapFolder in currentFolder.Entries)
            {
                ICASCEntry baseStormDataFolder = ((CASCFolder)mapFolder.Value).GetEntry(BaseStormDataDirectoryName);
                ICASCEntry gameDataFolder      = ((CASCFolder)baseStormDataFolder).GetEntry(GameDataStringName);

                if (LoadXmlFilesEnabled)
                {
                    foreach (KeyValuePair <string, ICASCEntry> dataFiles in ((CASCFolder)gameDataFolder).Entries)
                    {
                        if (Path.GetExtension(dataFiles.Key) == ".xml")
                        {
                            string filePath = ((CASCFile)dataFiles.Value).FullName;

                            if (!CASCHandlerData.FileExists(filePath))
                            {
                                throw new FileNotFoundException(filePath);
                            }

                            using (Stream data = CASCHandlerData.OpenFile(filePath))
                            {
                                LoadXmlFile(mapFolder.Value.Name, data, filePath);
                            }
                        }
                    }
                }

                if (LoadTextFilesOnlyEnabled)
                {
                    string filePath = Path.Combine(HeroesMapModsDirectoryPath, mapFolder.Value.Name, GameStringLocalization, LocalizedDataName, GameStringFile);

                    if (CASCHandlerData.FileExists(filePath))
                    {
                        LoadTextFile(mapFolder.Value.Name, CASCHandlerData.OpenFile(filePath), filePath);
                    }
                }
            }
        }
Esempio n. 8
0
        public int CompareTo(ICASCEntry other, int col, CASCEngine casc)
        {
            int result = 0;

            if (other is CASCFile)
                return -1;

            switch (col)
            {
                case 0:
                case 1:
                case 2:
                case 3:
                    result = Name.CompareTo(other.Name);
                    break;
                case 4:
                    break;
            }

            return result;
        }
Esempio n. 9
0
        private void Explore(CASCFolder folder)
        {
            foreach (KeyValuePair <string, ICASCEntry> node in folder.Entries)
            {
                ICASCEntry entry = node.Value;

                if (entry is CASCFolder)
                {
                    Explore((CASCFolder)entry);
                }
                else if (entry is CASCFile)
                {
                    CASCFile file = (CASCFile)entry;
                    if (file.Name.ToLower().Contains("illidan2"))
                    {
                        new RunnerExtractItem(file).Begin();
                        return;
                    }
                }
            }
        }
Esempio n. 10
0
 private void ExecPlugin(IPreview plugin, ICASCEntry file)
 {
     try
     {
         using (var stream = _casc.OpenFile(file.Hash))
         {
             // todo: use Task
             var control = plugin.Show(stream, file.Name);
             if (m_currentControl != control)
             {
                 ViewPanel.Controls.Clear();
                 ViewPanel.Controls.Add(control);
                 control.Dock     = DockStyle.Fill;
                 m_currentControl = control;
             }
         }
     }
     catch (Exception ex)
     {
         MessageBox.Show(ex.Message, "Plugin Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
     }
 }
Esempio n. 11
0
        private void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            CASCFolder folder = fileList.Tag as CASCFolder;

            if (folder == null)
            {
                return;
            }

            if (e.ItemIndex < 0 || e.ItemIndex >= folder.SubEntries.Count)
            {
                return;
            }

            ICASCEntry entry = folder.SubEntries.ElementAt(e.ItemIndex).Value;

            var flags = LocaleFlags.None;

            if (entry is CASCFile)
            {
                var rootInfos = cascHandler.GetRootInfo(entry.Hash);

                if (rootInfos == null)
                {
                    throw new Exception("root entry missing!");
                }

                foreach (var rootInfo in rootInfos)
                {
                    flags |= rootInfo.Block.Flags;
                }
            }

            var item = new ListViewItem(new string[] { entry.Name, entry is CASCFolder ? "Folder" : "File", flags.ToString() });

            item.ImageIndex = entry is CASCFolder ? 0 : 2;
            e.Item          = item;
        }
Esempio n. 12
0
        public override void Work()
        {
            Thread.Sleep(500);

            if (rootFolders != null && rootFolders.Length > 0)
            {
                foreach (KeyValuePair <string, ICASCEntry> node in Program.Root.Entries)
                {
                    ICASCEntry entry = node.Value;
                    string     name  = entry.Name.ToLower();

                    if (entry is CASCFolder && rootFolders.Any(n => n.ToLower().Equals(name)))
                    {
                        Explore((CASCFolder)entry);
                    }
                }
            }
            else
            {
                Explore(Program.Root);
            }

            EventManager.Trigger_FileExploreDone(id);
        }
Esempio n. 13
0
        public int CompareTo(ICASCEntry other, int col, CASCEngine casc)
        {
            int result = 0;

            if (other is CASCFile)
            {
                return(-1);
            }

            switch (col)
            {
            case 0:
            case 1:
            case 2:
            case 3:
                result = Name.CompareTo(other.Name);
                break;

            case 4:
                break;
            }

            return(result);
        }
Esempio n. 14
0
        public void CreateListViewItem(RetrieveVirtualItemEventArgs e)
        {
            if (_currentFolder == null)
            {
                return;
            }

            if (e.ItemIndex < 0 || e.ItemIndex >= _displayedEntries.Count)
            {
                return;
            }

            ICASCEntry entry = _displayedEntries[e.ItemIndex];

            var localeFlags  = LocaleFlags.None;
            var contentFlags = ContentFlags.None;
            var size         = "<DIR>";

            if (entry is CASCFile)
            {
                var rootInfosLocale = _casc.Root.GetEntries(entry.Hash);

                if (rootInfosLocale.Any())
                {
                    if (_casc.Encoding.GetEntry(rootInfosLocale.First().MD5, out EncodingEntry enc))
                    {
                        size = enc.Size.ToString("N", sizeNumberFmt) ?? "0";
                    }
                    else
                    {
                        size = "NYI";

                        if (_casc.Root is OwRootHandler owRoot)
                        {
                            if (owRoot.GetEntry(entry.Hash, out OWRootEntry rootEntry))
                            {
                                size = rootEntry.pkgIndexRec.Size.ToString("N", sizeNumberFmt) ?? "0";
                            }
                        }
                    }

                    foreach (var rootInfo in rootInfosLocale)
                    {
                        localeFlags  |= rootInfo.LocaleFlags;
                        contentFlags |= rootInfo.ContentFlags;
                    }
                }
                else
                {
                    var installInfos = _casc.Install.GetEntries(entry.Hash);

                    if (installInfos.Any())
                    {
                        if (_casc.Encoding.GetEntry(installInfos.First().MD5, out EncodingEntry enc))
                        {
                            size = enc.Size.ToString("N", sizeNumberFmt) ?? "0";

                            //foreach (var rootInfo in rootInfosLocale)
                            //{
                            //    if (rootInfo.Block != null)
                            //    {
                            //        localeFlags |= rootInfo.Block.LocaleFlags;
                            //        contentFlags |= rootInfo.Block.ContentFlags;
                            //    }
                            //}
                        }
                    }
                }
            }

            e.Item = new ListViewItem(new string[]
            {
                entry.Name,
                entry is CASCFolder ? "Folder" : Path.GetExtension(entry.Name),
                localeFlags.ToString(),
                contentFlags.ToString(),
                size
            })
            {
                ImageIndex = entry is CASCFolder ? 0 : 2
            };
        }
Esempio n. 15
0
 public int CompareTo(ICASCEntry other)
 {
     throw new NotImplementedException();
 }
Esempio n. 16
0
        private static CASCFolder LoadListFile(CASCHandler cascHandler, string path, BackgroundWorker worker)
        {
            if (!File.Exists(path))
            {
                throw new FileNotFoundException("list file missing!");
            }

            var rootHash = CASCHandler.Hasher.ComputeHash("root");

            var root = new CASCFolder(rootHash);

            CASCHandler.FolderNames[rootHash] = "root";

            using (var sr = new StreamReader(path))
            {
                string file;
                int    filesCount = 0;

                CASCFolder folder = root;

                while ((file = sr.ReadLine()) != null)
                {
                    filesCount++;

                    string[] parts = file.Split('\\');

                    for (int i = 0; i < parts.Length; ++i)
                    {
                        bool isFile = (i == parts.Length - 1);

                        ulong hash = isFile ? CASCHandler.Hasher.ComputeHash(file) : CASCHandler.Hasher.ComputeHash(parts[i]);

                        // skip invalid names
                        if (isFile && !cascHandler.RootData.ContainsKey(hash))
                        {
                            break;
                        }

                        ICASCEntry entry = folder.GetEntry(hash);

                        if (entry == null)
                        {
                            if (isFile)
                            {
                                entry = new CASCFile(hash);
                                CASCHandler.FileNames[hash] = file;
                            }
                            else
                            {
                                entry = new CASCFolder(hash);
                                CASCHandler.FolderNames[hash] = parts[i];
                            }

                            folder.SubEntries[hash] = entry;

                            if (isFile)
                            {
                                folder = root;
                                break;
                            }
                        }

                        folder = entry as CASCFolder;
                    }
                }
                Logger.WriteLine("CASCHandler: loaded {0} file names", CASCHandler.FileNames.Count);
            }
            return(root);
        }
Esempio n. 17
0
 public int CompareTo(ICASCEntry other)
 {
     throw new NotImplementedException();
 }
Esempio n. 18
0
        public CASCHandler(CASCFolder root, BackgroundWorker worker)
        {
            if (!OnlineMode)
            {
                var idxFiles = GetIdxFiles(Properties.Settings.Default.WowPath);

                if (idxFiles.Count == 0)
                {
                    throw new FileNotFoundException("idx files missing!");
                }

                worker.ReportProgress(0);

                int idxIndex = 0;

                foreach (var idx in idxFiles)
                {
                    using (var fs = new FileStream(idx, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                        using (var br = new BinaryReader(fs))
                        {
                            int    h2Len   = br.ReadInt32();
                            int    h2Check = br.ReadInt32();
                            byte[] h2      = br.ReadBytes(h2Len);

                            long padPos = (8 + h2Len + 0x0F) & 0xFFFFFFF0;
                            fs.Position = padPos;

                            int dataLen   = br.ReadInt32();
                            int dataCheck = br.ReadInt32();

                            int numBlocks = dataLen / 18;

                            for (int i = 0; i < numBlocks; i++)
                            {
                                IndexEntry info      = new IndexEntry();
                                byte[]     key       = br.ReadBytes(9);
                                int        indexHigh = br.ReadByte();
                                int        indexLow  = br.ReadInt32BE();

                                info.Index  = (int)((byte)(indexHigh << 2) | ((indexLow & 0xC0000000) >> 30));
                                info.Offset = (indexLow & 0x3FFFFFFF);
                                info.Size   = br.ReadInt32();

                                // duplicate keys wtf...
                                //IndexData[key] = info; // use last key
                                if (!LocalIndexData.ContainsKey(key)) // use first key
                                {
                                    LocalIndexData.Add(key, info);
                                }
                            }

                            padPos      = (dataLen + 0x0FFF) & 0xFFFFF000;
                            fs.Position = padPos;

                            fs.Position += numBlocks * 18;
                            //for (int i = 0; i < numBlocks; i++)
                            //{
                            //    var bytes = br.ReadBytes(18); // unknown data
                            //}

                            if (fs.Position != fs.Position)
                            {
                                throw new Exception("idx file under read");
                            }
                        }

                    worker.ReportProgress((int)((float)++idxIndex / (float)idxFiles.Count * 100));
                }

                Logger.WriteLine("CASCHandler: loaded {0} indexes", LocalIndexData.Count);
            }

            worker.ReportProgress(0);

            using (var fs = OpenEncodingFile())
                using (var br = new BinaryReader(fs))
                {
                    br.ReadBytes(2); // EN
                    byte   b1         = br.ReadByte();
                    byte   b2         = br.ReadByte();
                    byte   b3         = br.ReadByte();
                    ushort s1         = br.ReadUInt16();
                    ushort s2         = br.ReadUInt16();
                    int    numEntries = br.ReadInt32BE();
                    int    i1         = br.ReadInt32BE();
                    byte   b4         = br.ReadByte();
                    int    entriesOfs = br.ReadInt32BE();

                    fs.Position += entriesOfs; // skip strings

                    fs.Position += numEntries * 32;
                    //for (int i = 0; i < numEntries; ++i)
                    //{
                    //    br.ReadBytes(16);
                    //    br.ReadBytes(16);
                    //}

                    for (int i = 0; i < numEntries; ++i)
                    {
                        ushort keysCount;

                        while ((keysCount = br.ReadUInt16()) != 0)
                        {
                            int    fileSize = br.ReadInt32BE();
                            byte[] md5      = br.ReadBytes(16);

                            var entry = new EncodingEntry();
                            entry.Size = fileSize;

                            for (int ki = 0; ki < keysCount; ++ki)
                            {
                                byte[] key = br.ReadBytes(16);

                                entry.Keys.Add(key);
                            }

                            //Encodings[md5] = entry;
                            EncodingData.Add(md5, entry);
                        }

                        //br.ReadBytes(28);
                        while (br.PeekChar() == 0)
                        {
                            fs.Position++;
                        }

                        worker.ReportProgress((int)((float)fs.Position / (float)fs.Length * 100));
                    }
                    //var pos = br.BaseStream.Position;
                    //for (int i = 0; i < i1; ++i)
                    //{
                    //    br.ReadBytes(16);
                    //    br.ReadBytes(16);
                    //}
                    Logger.WriteLine("CASCHandler: loaded {0} encoding data", EncodingData.Count);
                }

            worker.ReportProgress(0);

            using (var fs = OpenRootFile())
                using (var br = new BinaryReader(fs))
                {
                    while (fs.Position < fs.Length)
                    {
                        int count = br.ReadInt32();

                        RootBlock block = new RootBlock();
                        block.Unk1  = br.ReadUInt32();
                        block.Flags = (LocaleFlags)br.ReadUInt32();

                        if (block.Flags == LocaleFlags.None)
                        {
                            throw new Exception("block.Flags == LocaleFlags.None");
                        }

                        RootEntry[] entries = new RootEntry[count];

                        for (var i = 0; i < count; ++i)
                        {
                            entries[i]       = new RootEntry();
                            entries[i].Block = block;
                            entries[i].Unk1  = br.ReadInt32();
                        }

                        for (var i = 0; i < count; ++i)
                        {
                            entries[i].MD5 = br.ReadBytes(16);

                            ulong hash = br.ReadUInt64();
                            entries[i].Hash = hash;

                            // don't load other locales
                            //if (block.Flags != LocaleFlags.All && (block.Flags & LocaleFlags.enUS) == 0)
                            //    continue;

                            if (!RootData.ContainsKey(hash))
                            {
                                RootData[hash] = new List <RootEntry>();
                                RootData[hash].Add(entries[i]);
                            }
                            else
                            {
                                RootData[hash].Add(entries[i]);
                            }
                        }

                        worker.ReportProgress((int)((float)fs.Position / (float)fs.Length * 100));
                    }

                    Logger.WriteLine("CASCHandler: loaded {0} root data", RootData.Count);
                }

            worker.ReportProgress(0);

            if (File.Exists(listFile))
            {
                FolderNames[Hasher.ComputeHash("root")] = "root";

                using (StreamReader sr = new StreamReader(listFile))
                {
                    string file;
                    int    filesCount = 0;

                    CASCFolder folder = root;

                    while ((file = sr.ReadLine()) != null)
                    {
                        ulong fileHash = Hasher.ComputeHash(file);

                        // skip invalid names
                        if (!RootData.ContainsKey(fileHash))
                        {
                            Logger.WriteLine("Invalid file name: {0}", file);
                            continue;
                        }

                        filesCount++;

                        string[] parts = file.Split('\\');

                        for (int i = 0; i < parts.Length; ++i)
                        {
                            bool isFile = (i == parts.Length - 1);

                            ulong hash = isFile ? fileHash : Hasher.ComputeHash(parts[i]);

                            ICASCEntry entry = folder.GetEntry(hash);

                            if (entry == null)
                            {
                                if (isFile)
                                {
                                    entry           = new CASCFile(hash);
                                    FileNames[hash] = file;
                                }
                                else
                                {
                                    entry             = new CASCFolder(hash);
                                    FolderNames[hash] = parts[i];
                                }

                                folder.SubEntries[hash] = entry;

                                if (isFile)
                                {
                                    folder = root;
                                    break;
                                }
                            }

                            folder = entry as CASCFolder;
                        }

                        if ((filesCount % 1000) == 0)
                        {
                            worker.ReportProgress((int)((float)sr.BaseStream.Position / (float)sr.BaseStream.Length * 100));
                        }
                    }

                    Logger.WriteLine("CASCHandler: loaded {0} file names", FileNames.Count);
                }
            }
            else
            {
                throw new FileNotFoundException("list file missing!");
            }
        }
Esempio n. 19
0
        public CASCFolder LoadListFile(List <string> list)
        {
            var rootHash = Hasher.ComputeHash("root");

            var root = new CASCFolder(rootHash);

            CASCFolder.FolderNames[rootHash] = "root";

            foreach (var file in list)
            {
                CASCFolder folder = root;

                {
                    ulong fileHash = Hasher.ComputeHash(file);

                    // skip invalid names
                    if (!RootData.ContainsKey(fileHash))
                    {
                        Logger.WriteLine("Invalid file name: {0}", file);
                        continue;
                    }

                    string[] parts = file.Split('\\');

                    for (int i = 0; i < parts.Length; ++i)
                    {
                        bool isFile = (i == parts.Length - 1);

                        ulong hash = isFile ? fileHash : Hasher.ComputeHash(parts[i]);

                        ICASCEntry entry = folder.GetEntry(hash);

                        if (entry == null)
                        {
                            if (isFile)
                            {
                                entry = new CASCFile(hash);
                                CASCFile.FileNames[hash] = file;
                            }
                            else
                            {
                                entry = new CASCFolder(hash);
                                CASCFolder.FolderNames[hash] = parts[i];
                            }

                            folder.SubEntries[hash] = entry;

                            if (isFile)
                            {
                                folder = root;
                                break;
                            }
                        }

                        folder = entry as CASCFolder;
                    }
                }


                Logger.WriteLine("Found {0} ClientDB files.", CASCFile.FileNames.Count);
            }
            return(root);
        }
Esempio n. 20
0
        public void CreateListViewItem(RetrieveVirtualItemEventArgs e, CASCFolder folder)
        {
            if (folder == null)
            {
                return;
            }

            if (e.ItemIndex < 0 || e.ItemIndex >= folder.Entries.Count)
            {
                return;
            }

            ICASCEntry entry = folder.Entries.ElementAt(e.ItemIndex).Value;

            var localeFlags  = LocaleFlags.None;
            var contentFlags = ContentFlags.None;
            var size         = "<DIR>";

            if (entry is CASCFile)
            {
                var rootInfosLocale = _casc.Root.GetEntries(entry.Hash);

                if (rootInfosLocale.Any())
                {
                    var enc = _casc.Encoding.GetEntry(rootInfosLocale.First().MD5);

                    if (enc != null)
                    {
                        size = enc.Size.ToString("N", sizeNumberFmt);
                    }
                    else
                    {
                        size = "0";
                    }

                    foreach (var rootInfo in rootInfosLocale)
                    {
                        if (rootInfo.Block != null)
                        {
                            localeFlags  |= rootInfo.Block.LocaleFlags;
                            contentFlags |= rootInfo.Block.ContentFlags;
                        }
                    }
                }
                else
                {
                    var installInfos = _casc.Install.GetEntries(entry.Hash);

                    if (installInfos.Any())
                    {
                        var enc = _casc.Encoding.GetEntry(installInfos.First().MD5);

                        if (enc != null)
                        {
                            size = enc.Size.ToString("N", sizeNumberFmt);
                        }
                        else
                        {
                            size = "0";
                        }

                        //foreach (var rootInfo in rootInfosLocale)
                        //{
                        //    if (rootInfo.Block != null)
                        //    {
                        //        localeFlags |= rootInfo.Block.LocaleFlags;
                        //        contentFlags |= rootInfo.Block.ContentFlags;
                        //    }
                        //}
                    }
                }
            }

            e.Item = new ListViewItem(new string[]
            {
                entry.Name,
                entry is CASCFolder ? "Folder" : Path.GetExtension(entry.Name),
                localeFlags.ToString(),
                contentFlags.ToString(),
                size
            })
            {
                ImageIndex = entry is CASCFolder ? 0 : 2
            };
        }