Пример #1
0
        internal static DirectoryEntry Parse(BinaryReader reader)
        {
            byte[] nameValue  = reader.ReadBytes(64);
            ushort nameLength = reader.ReadUInt16();

            string name = null;

            if (nameLength > 1)
            {
                name = System.Text.Encoding.Unicode.GetString(nameValue, 0, nameLength - 2);
            }

            byte typeValue          = reader.ReadByte();
            DirectoryEntryType type = EnumUtil.ParseDirectoryEntryType(typeValue);

            byte  colorValue = reader.ReadByte();
            Color color      = EnumUtil.ParseColor(colorValue);

            uint leftSiblingSid  = reader.ReadUInt32();
            uint rightSiblingSid = reader.ReadUInt32();
            uint childSid        = reader.ReadUInt32();

            byte[] classId   = reader.ReadBytes(16);
            uint   userFlags = reader.ReadUInt32();

            uint createdTimeLow  = reader.ReadUInt32();
            long createdTimeHigh = reader.ReadUInt32();

            DateTime createdTime = new DateTime();

            if (createdTimeHigh > 0)
            {
                long ticks = createdTimeLow + (createdTimeHigh << 32);

                DateTime year1601 = new DateTime(1601, 1, 1);

                try
                {
                    createdTime = year1601.AddTicks(ticks).ToLocalTime();
                }
                catch (Exception) //ignore wrong dates
                {
                }
            }

            uint lastModifiedTimeLow  = reader.ReadUInt32();
            long lastModifiedTimeHigh = reader.ReadUInt32();

            DateTime lastModifiedTime = new DateTime();

            if (lastModifiedTimeHigh > 0)
            {
                long ticks = lastModifiedTimeLow + (lastModifiedTimeHigh << 32);

                DateTime year1601 = new DateTime(1601, 1, 1);

                try
                {
                    lastModifiedTime = year1601.AddTicks(ticks).ToLocalTime();
                }
                catch (Exception) //ignore wrong dates
                {
                }
            }

            uint startSector = reader.ReadUInt32();
            uint size        = reader.ReadUInt32();

            if (type == DirectoryEntryType.Root)
            {
                RootDirectoryEntry entry = new RootDirectoryEntry();
                entry.type             = DirectoryEntryType.Root;
                entry.name             = name;
                entry.color            = color;
                entry.leftSiblingSid   = leftSiblingSid;
                entry.rightSiblingSid  = rightSiblingSid;
                entry.childSid         = childSid;
                entry.classId          = classId;
                entry.userFlags        = userFlags;
                entry.createdTime      = createdTime;
                entry.lastModifiedTime = lastModifiedTime;
                entry.startSector      = startSector;
                entry.size             = size;

                return(entry);
            }
            else if (type == DirectoryEntryType.Stream)
            {
                Stream entry = new Stream();
                entry.type             = DirectoryEntryType.Stream;
                entry.name             = name;
                entry.color            = color;
                entry.leftSiblingSid   = leftSiblingSid;
                entry.rightSiblingSid  = rightSiblingSid;
                entry.childSid         = childSid;
                entry.classId          = classId;
                entry.userFlags        = userFlags;
                entry.createdTime      = createdTime;
                entry.lastModifiedTime = lastModifiedTime;
                entry.startSector      = startSector;
                entry.size             = size;

                return(entry);
            }
            else if (type == DirectoryEntryType.Storage)
            {
                Storage entry = new Storage();
                entry.type             = DirectoryEntryType.Storage;
                entry.name             = name;
                entry.color            = color;
                entry.leftSiblingSid   = leftSiblingSid;
                entry.rightSiblingSid  = rightSiblingSid;
                entry.childSid         = childSid;
                entry.classId          = classId;
                entry.userFlags        = userFlags;
                entry.createdTime      = createdTime;
                entry.lastModifiedTime = lastModifiedTime;
                entry.startSector      = startSector;
                entry.size             = size;

                return(entry);
            }
            else
            {
                Storage entry = new Storage();
                entry.type             = DirectoryEntryType.Invalid;
                entry.name             = name;
                entry.color            = color;
                entry.leftSiblingSid   = leftSiblingSid;
                entry.rightSiblingSid  = rightSiblingSid;
                entry.childSid         = childSid;
                entry.classId          = classId;
                entry.userFlags        = userFlags;
                entry.createdTime      = createdTime;
                entry.lastModifiedTime = lastModifiedTime;
                entry.startSector      = startSector;
                entry.size             = size;

                return(entry);
            }
        }
Пример #2
0
        private void OpenImplementation(System.IO.Stream stream)
        {
            if (stream.Length < 512)
            {
                throw new InvalidFileFormatException("Invalid file format.");
            }

            BinaryReader reader = new BinaryReader(stream, System.Text.Encoding.Unicode);

            reader.BaseStream.Position = 0;

            header = new Header(reader);

            uint[] difat   = ParseDifat(reader);
            uint[] fat     = ParseFat(reader, difat);
            uint[] miniFat = null;

            if (header.FirstMiniFatSector != 0xFFFFFFFE)
            {
                miniFat = ParseMiniFat(reader, fat);
            }

            IList <uint> directoryChain = new List <uint>();

            uint directorySector = header.FirstDirectorySector;

            directoryChain.Add(directorySector);

            while (true)
            {
                directorySector = fat[directorySector];

                if (directorySector != 0xFFFFFFFE)
                {
                    directoryChain.Add(directorySector);
                }
                else
                {
                    break;
                }
            }

            MemoryStream directoryMemoryStream = new MemoryStream();

            using (directoryMemoryStream)
            {
                BinaryReader directoryReader = new BinaryReader(directoryMemoryStream, System.Text.Encoding.Unicode);

                for (int i = 0; i < directoryChain.Count; i++)
                {
                    uint currentDirectoryChain = directoryChain[i];
                    reader.BaseStream.Position = currentDirectoryChain * header.SectorSize + header.SectorSize;

                    byte[] currentSector = reader.ReadBytes(header.SectorSize);
                    directoryMemoryStream.Write(currentSector, 0, currentSector.Length);
                }

                directoryReader.BaseStream.Position = 0;

                root = (RootDirectoryEntry)DirectoryEntry.Parse(directoryReader);

                IDictionary <uint, DirectoryEntry> directoryEntries = new Dictionary <uint, DirectoryEntry>();

                //read directory entries
                ////////////////////////////////////////////////
                directoryEntries.Add(0, root);

                if (root.childSid != 0xFFFFFFFF)
                {
                    directoryReader.BaseStream.Position = root.childSid * 128;
                    DirectoryEntry newEntry = DirectoryEntry.Parse(directoryReader);

                    directoryEntries.Add(root.childSid, newEntry);

                    root.directoryEntries.Add(newEntry);
                    newEntry.parent = root;

                    Stack <DirectoryEntry> leftStack  = new Stack <DirectoryEntry>();
                    Stack <DirectoryEntry> rightStack = new Stack <DirectoryEntry>();
                    Stack <DirectoryEntry> childStack = new Stack <DirectoryEntry>();

                    leftStack.Push(newEntry);
                    rightStack.Push(newEntry);
                    childStack.Push(newEntry);

                    while (leftStack.Count > 0 || rightStack.Count > 0 || childStack.Count > 0)
                    {
                        if (leftStack.Count > 0)
                        {
                            DirectoryEntry currentEntry = (DirectoryEntry)leftStack.Pop();

                            if (currentEntry.leftSiblingSid != 0xFFFFFFFF && !directoryEntries.ContainsKey(currentEntry.leftSiblingSid))
                            {
                                directoryReader.BaseStream.Position = currentEntry.leftSiblingSid * 128;
                                newEntry = DirectoryEntry.Parse(directoryReader);

                                directoryEntries.Add(currentEntry.leftSiblingSid, newEntry);

                                currentEntry.parent.directoryEntries.Add(newEntry);
                                newEntry.parent = currentEntry.parent;

                                leftStack.Push(newEntry);
                                rightStack.Push(newEntry);
                                childStack.Push(newEntry);

                                continue;
                            }
                        }

                        if (rightStack.Count > 0)
                        {
                            DirectoryEntry currentEntry = (DirectoryEntry)rightStack.Pop();

                            if (currentEntry.rightSiblingSid != 0xFFFFFFFF && !directoryEntries.ContainsKey(currentEntry.rightSiblingSid))
                            {
                                directoryReader.BaseStream.Position = currentEntry.rightSiblingSid * 128;
                                newEntry = DirectoryEntry.Parse(directoryReader);

                                directoryEntries.Add(currentEntry.rightSiblingSid, newEntry);

                                currentEntry.parent.directoryEntries.Add(newEntry);
                                newEntry.parent = currentEntry.parent;

                                leftStack.Push(newEntry);
                                rightStack.Push(newEntry);
                                childStack.Push(newEntry);

                                continue;
                            }
                        }

                        if (childStack.Count > 0)
                        {
                            DirectoryEntry currentEntry = (DirectoryEntry)childStack.Pop();

                            if (currentEntry.childSid != 0xFFFFFFFF && !directoryEntries.ContainsKey(currentEntry.childSid))
                            {
                                directoryReader.BaseStream.Position = currentEntry.childSid * 128;
                                newEntry = DirectoryEntry.Parse(directoryReader);

                                directoryEntries.Add(currentEntry.childSid, newEntry);

                                currentEntry.directoryEntries.Add(newEntry);
                                newEntry.parent = currentEntry;

                                leftStack.Push(newEntry);
                                rightStack.Push(newEntry);
                                childStack.Push(newEntry);
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////

                IList <DirectoryEntry> directoryEntriesList = new List <DirectoryEntry>();

                foreach (DirectoryEntry entry in directoryEntries.Values)
                {
                    if (entry == root)
                    {
                        directoryEntriesList.Insert(0, entry);
                    }
                    else
                    {
                        directoryEntriesList.Add(entry);
                    }
                }

                MemoryStream miniStream = new MemoryStream();

                using (miniStream)
                {
                    BinaryReader miniStreamReader = new BinaryReader(miniStream);

                    for (int i = 0; i < directoryEntriesList.Count; i++)
                    {
                        DirectoryEntry entry = directoryEntriesList[i];

                        if (entry.type != DirectoryEntryType.Storage)
                        {
                            if (entry.type != DirectoryEntryType.Root && entry.Size > 0 && entry.Size < header.MiniStreamMaxSize)
                            {
                                IList <uint> streamChain = new List <uint>();

                                uint streamSector = entry.startSector;
                                streamChain.Add(streamSector);

                                while (true)
                                {
                                    streamSector = miniFat[streamSector];

                                    if (streamSector != 0xFFFFFFFC && streamSector != 0xFFFFFFFD && streamSector != 0xFFFFFFFE && streamSector != 0xFFFFFFFF && streamSector != miniFat[streamSector])
                                    {
                                        streamChain.Add(streamSector);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                MemoryStream entryBufferMemoryStream = new MemoryStream();

                                using (entryBufferMemoryStream)
                                {
                                    for (int j = 0; j < streamChain.Count; j++)
                                    {
                                        uint currentStreamChain = streamChain[j];
                                        miniStreamReader.BaseStream.Position = currentStreamChain * 64;

                                        byte[] currentSector = miniStreamReader.ReadBytes(64);
                                        entryBufferMemoryStream.Write(currentSector, 0, currentSector.Length);
                                    }

                                    entry.buffer = new byte[entry.size];

                                    if (entryBufferMemoryStream.Length < entry.buffer.Length)
                                    {
                                        entry.buffer = new byte[entryBufferMemoryStream.Length];
                                    }

                                    System.Array.Copy(entryBufferMemoryStream.ToArray(), 0, entry.buffer, 0, entry.buffer.Length);
                                }
                            }
                            else if (entry.Size > 0)
                            {
                                IList <uint> streamChain = new List <uint>();

                                uint streamSector = entry.startSector;
                                streamChain.Add(streamSector);

                                while (true)
                                {
                                    streamSector = fat[streamSector];

                                    if (streamSector != 0xFFFFFFFC && streamSector != 0xFFFFFFFD && streamSector != 0xFFFFFFFE && streamSector != 0xFFFFFFFF && streamSector != fat[streamSector])
                                    {
                                        streamChain.Add(streamSector);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                MemoryStream entryBufferMemoryStream = new MemoryStream();

                                using (entryBufferMemoryStream)
                                {
                                    for (int j = 0; j < streamChain.Count; j++)
                                    {
                                        uint currentStreamChain = streamChain[j];
                                        reader.BaseStream.Position = currentStreamChain * header.SectorSize + header.SectorSize;

                                        byte[] currentSector = reader.ReadBytes(header.SectorSize);
                                        entryBufferMemoryStream.Write(currentSector, 0, currentSector.Length);
                                    }

                                    entry.buffer = new byte[entry.Size];

                                    if (entryBufferMemoryStream.Length < entry.buffer.Length)
                                    {
                                        entry.buffer = new byte[entryBufferMemoryStream.Length];
                                    }

                                    System.Array.Copy(entryBufferMemoryStream.ToArray(), 0, entry.buffer, 0, entry.buffer.Length);
                                }

                                if (entry == root)
                                {
                                    if (root.buffer != null)
                                    {
                                        miniStream.Write(root.buffer, 0, root.buffer.Length);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }