Beispiel #1
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);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Beispiel #2
0
        private void CreateDirectoryEntries(DirectoryEntry parent, ref IList <DirectoryEntry> allDirectoryEntries)
        {
            if (parent.directoryEntries.Count > 0)
            {
                parent.directoryEntries.Sort();

                int middlePosition = parent.directoryEntries.Count / 2;

                DirectoryEntry middleEntry = parent.directoryEntries[middlePosition];

                if (parent.color == Color.Black)
                {
                    middleEntry.color = Color.Red;
                }
                else
                {
                    middleEntry.color = Color.Black;
                }

                middleEntry.createdTime      = DateTime.Now;
                middleEntry.lastModifiedTime = middleEntry.createdTime;

                if (middleEntry.buffer != null)
                {
                    middleEntry.size = (uint)middleEntry.buffer.Length;
                }
                else
                {
                    middleEntry.size = 0;
                }

                middleEntry.startSector = 0;

                middleEntry.leftSiblingSid  = 0xFFFFFFFF;
                middleEntry.rightSiblingSid = 0xFFFFFFFF;
                middleEntry.childSid        = 0xFFFFFFFF;

                allDirectoryEntries.Add(middleEntry);
                parent.childSid = (uint)(allDirectoryEntries.Count - 1);

                DirectoryEntry previous = middleEntry;

                for (int l = middlePosition - 1; l >= 0; l--)
                {
                    DirectoryEntry leftEntry = parent.directoryEntries[l];

                    if (parent.color == Color.Black)
                    {
                        leftEntry.color = Color.Red;
                    }
                    else
                    {
                        leftEntry.color = Color.Black;
                    }

                    leftEntry.createdTime      = DateTime.Now;
                    leftEntry.lastModifiedTime = leftEntry.createdTime;

                    if (leftEntry.buffer != null)
                    {
                        leftEntry.size = (uint)leftEntry.buffer.Length;
                    }
                    else
                    {
                        leftEntry.size = 0;
                    }

                    leftEntry.leftSiblingSid  = 0xFFFFFFFF;
                    leftEntry.rightSiblingSid = 0xFFFFFFFF;
                    leftEntry.childSid        = 0xFFFFFFFF;

                    allDirectoryEntries.Add(leftEntry);
                    previous.leftSiblingSid = (uint)(allDirectoryEntries.Count - 1);
                    previous = leftEntry;

                    if (leftEntry is Storage)
                    {
                        CreateDirectoryEntries(leftEntry, ref allDirectoryEntries);
                    }
                }

                previous = middleEntry;

                for (int r = middlePosition + 1; r < parent.directoryEntries.Count; r++)
                {
                    DirectoryEntry rightEntry = parent.directoryEntries[r];

                    if (parent.color == Color.Black)
                    {
                        rightEntry.color = Color.Red;
                    }
                    else
                    {
                        rightEntry.color = Color.Black;
                    }

                    rightEntry.createdTime      = DateTime.Now;
                    rightEntry.lastModifiedTime = rightEntry.createdTime;

                    if (rightEntry.buffer != null)
                    {
                        rightEntry.size = (uint)rightEntry.buffer.Length;
                    }
                    else
                    {
                        rightEntry.size = 0;
                    }

                    rightEntry.leftSiblingSid  = 0xFFFFFFFF;
                    rightEntry.rightSiblingSid = 0xFFFFFFFF;
                    rightEntry.childSid        = 0xFFFFFFFF;

                    allDirectoryEntries.Add(rightEntry);
                    previous.rightSiblingSid = (uint)(allDirectoryEntries.Count - 1);
                    previous = rightEntry;

                    if (rightEntry is Storage)
                    {
                        CreateDirectoryEntries(rightEntry, ref allDirectoryEntries);
                    }
                }

                if (middleEntry is Storage)
                {
                    CreateDirectoryEntries(middleEntry, ref allDirectoryEntries);
                }
            }
        }
Beispiel #3
0
        private byte[] CreateCompoundFile()
        {
            byte[] outputBuffer = null;

            IList <DirectoryEntry> allDirectoryEntries = new List <DirectoryEntry>();
            IList <uint>           fat     = new List <uint>();
            IList <uint>           miniFat = new List <uint>();

            uint firstMiniFatSector    = 0xFFFFFFFE;
            uint firstMiniStreamSector = 0xFFFFFFFE;
            uint miniFatSectorCount    = 0;

            MemoryStream compoundFileMemoryStream = new MemoryStream();

            using (compoundFileMemoryStream)
            {
                BinaryWriter compoundFileWriter = new BinaryWriter(compoundFileMemoryStream, System.Text.Encoding.Unicode);

                root.color            = Color.Red;
                root.type             = DirectoryEntryType.Root;
                root.buffer           = null;
                root.leftSiblingSid   = 0xFFFFFFFF;
                root.rightSiblingSid  = 0xFFFFFFFF;
                root.createdTime      = DateTime.MinValue;
                root.lastModifiedTime = DateTime.MinValue;
                root.size             = 0;
                root.startSector      = 0;

                allDirectoryEntries.Add(root);
                CreateDirectoryEntries(root, ref allDirectoryEntries);

                MemoryStream dataStream = new MemoryStream();
                MemoryStream miniStream = new MemoryStream();

                using (dataStream)
                {
                    using (miniStream)
                    {
                        BinaryWriter dataStreamWriter = new BinaryWriter(dataStream, System.Text.Encoding.Unicode);
                        BinaryWriter miniStreamWriter = new BinaryWriter(miniStream, System.Text.Encoding.Unicode);

                        for (int i = allDirectoryEntries.Count - 1; i >= 0; i--)
                        {
                            DirectoryEntry entry = allDirectoryEntries[i];

                            if (entry.buffer != null)
                            {
                                entry.size = (uint)entry.buffer.Length;
                            }
                            else
                            {
                                entry.size = 0;
                            }

                            //root entry
                            if (i == 0 && miniStream.Position > 0)
                            {
                                entry.buffer = new byte[miniStream.Position];
                                System.Array.Copy(miniStream.ToArray(), 0, entry.buffer, 0, (int)miniStream.Position);
                                entry.size = (uint)entry.buffer.Length;
                            }

                            if (i > 0 && entry.size > 0 && entry.size < header.MiniStreamMaxSize)
                            {
                                entry.startSector = (uint)miniFat.Count;

                                for (int offset = 0; offset < entry.buffer.Length; offset += header.MiniSectorSize)
                                {
                                    byte[] dataSector = new byte[header.MiniSectorSize];

                                    int copyLength = dataSector.Length;

                                    if (entry.buffer.Length < offset + header.MiniSectorSize)
                                    {
                                        copyLength = entry.buffer.Length - offset;
                                    }

                                    System.Array.Copy(entry.buffer, offset, dataSector, 0, copyLength);
                                    miniStreamWriter.Write(dataSector);

                                    if (offset + header.MiniSectorSize < entry.buffer.Length)
                                    {
                                        miniFat.Add((uint)miniFat.Count + 1);
                                    }
                                    else
                                    {
                                        miniFat.Add(0xFFFFFFFE);
                                    }
                                }
                            }
                            else if (i > 0 && entry.size > 0 && entry.size >= header.MiniStreamMaxSize)
                            {
                                entry.startSector = (uint)fat.Count;

                                for (int offset = 0; offset < entry.buffer.Length; offset += header.SectorSize)
                                {
                                    byte[] dataSector = new byte[header.SectorSize];

                                    int copyLength = dataSector.Length;

                                    if (entry.buffer.Length < offset + header.SectorSize)
                                    {
                                        copyLength = entry.buffer.Length - offset;
                                    }

                                    System.Array.Copy(entry.buffer, offset, dataSector, 0, copyLength);
                                    dataStreamWriter.Write(dataSector);

                                    if (offset + header.SectorSize < entry.buffer.Length)
                                    {
                                        fat.Add((uint)fat.Count + 1);
                                    }
                                    else
                                    {
                                        fat.Add(0xFFFFFFFE);
                                    }
                                }
                            }
                        }

                        int  miniSectorCountInFatSector = header.SectorSize / header.MiniSectorSize;
                        int  currentMiniSector          = 0;
                        bool lastSector = false;

                        firstMiniStreamSector = (uint)fat.Count;

                        if (miniStream.Length > 0)
                        {
                            byte[] miniBuffer = miniStream.ToArray();
                            byte[] dataSector = new byte[header.SectorSize];

                            for (int offset = 0; offset < miniBuffer.Length; offset += header.MiniSectorSize)
                            {
                                int copyLength = header.MiniSectorSize;

                                if (miniBuffer.Length < offset + header.MiniSectorSize)
                                {
                                    copyLength = (int)(miniStream.Length - offset);
                                }

                                System.Array.Copy(miniBuffer, offset, dataSector, currentMiniSector * header.MiniSectorSize, copyLength);
                                currentMiniSector++;

                                if (offset + header.MiniSectorSize >= miniBuffer.Length)
                                {
                                    lastSector = true;
                                }

                                if (lastSector || currentMiniSector == miniSectorCountInFatSector)
                                {
                                    currentMiniSector = 0;
                                    dataStreamWriter.Write(dataSector);

                                    if (!lastSector)
                                    {
                                        fat.Add((uint)fat.Count + 1);
                                    }
                                    else
                                    {
                                        fat.Add(0xFFFFFFFE);
                                    }
                                }
                            }

                            int miniFatCountInFatSector = header.SectorSize / 4;
                            firstMiniFatSector = (uint)fat.Count;

                            for (int i = 0; i < miniFat.Count; i += miniFatCountInFatSector)
                            {
                                byte[] miniFatSector = new byte[header.SectorSize];

                                for (int j = 0; j < miniFatCountInFatSector; j++)
                                {
                                    if (i + j < miniFat.Count)
                                    {
                                        uint currentMiniFat = miniFat[i + j];

                                        byte[] currentMiniFatBuffer = BitConverter.GetBytes(currentMiniFat);
                                        System.Array.Copy(currentMiniFatBuffer, 0, miniFatSector, j * 4, 4);
                                    }
                                    else
                                    {
                                        byte[] currentMiniFatBuffer = BitConverter.GetBytes(0xFFFFFFFF);
                                        System.Array.Copy(currentMiniFatBuffer, 0, miniFatSector, j * 4, 4);
                                    }
                                }

                                dataStreamWriter.Write(miniFatSector);
                                miniFatSectorCount++;

                                if (i + miniFatCountInFatSector < miniFat.Count)
                                {
                                    fat.Add((uint)fat.Count + 1);
                                }
                                else
                                {
                                    fat.Add(0xFFFFFFFE);
                                }
                            }
                        }

                        compoundFileWriter.Write(dataStream.ToArray());
                    }
                }

                //Directory
                ///////////////////////////////////////////////////////////////////////////////////

                header.FirstDirectorySector = (uint)fat.Count;

                uint directorySectorCount = 0;

                int directoryEntriesInSector = header.SectorSize / 128;

                for (int i = 0; i < allDirectoryEntries.Count; i += directoryEntriesInSector)
                {
                    if (allDirectoryEntries[i] == root)
                    {
                        if (firstMiniStreamSector != 0xFFFFFFFE)
                        {
                            root.startSector = firstMiniStreamSector;
                        }
                    }

                    byte[] directorySector = new byte[header.SectorSize];

                    for (int j = 0; j < directoryEntriesInSector; j++)
                    {
                        if (i + j < allDirectoryEntries.Count)
                        {
                            DirectoryEntry entry = allDirectoryEntries[i + j];
                            System.Array.Copy(entry.ToBytes(), 0, directorySector, j * 128, 128);
                        }
                    }

                    compoundFileWriter.Write(directorySector);
                    directorySectorCount++;

                    if (i + directoryEntriesInSector < allDirectoryEntries.Count)
                    {
                        fat.Add((uint)fat.Count + 1);
                    }
                    else
                    {
                        fat.Add(0xFFFFFFFE);
                    }
                }

                if (header.MajorVersion == 4)
                {
                    header.DirectorySectorCount = directorySectorCount;
                }

                //DIFAT and FAT
                ///////////////////////////////////////////////////////////////////////////////////

                int fatSectorsPerSector = header.SectorSize / 4;
                int fatSectorCount      = fat.Count / fatSectorsPerSector;

                if (fatSectorCount * fatSectorsPerSector < fat.Count)
                {
                    fatSectorCount = fatSectorCount + 1;
                }

                fatSectorCount = (fat.Count + fatSectorCount) / fatSectorsPerSector;

                if (fatSectorCount * fatSectorsPerSector < fat.Count + fatSectorCount)
                {
                    fatSectorCount = fatSectorCount + 1;
                }

                int difatSectorCount = (fatSectorCount - 109) / (fatSectorsPerSector - 1);

                if (difatSectorCount * fatSectorsPerSector < (fatSectorCount - 109))
                {
                    difatSectorCount = difatSectorCount + 1;
                }

                header.FatSectorCount = (uint)fatSectorCount;

                IList <uint> difatSectorList          = new List <uint>();
                IList <uint> difatAddtionalSectorList = new List <uint>();

                for (int i = 0; i < fatSectorCount; i++)
                {
                    fat.Add(0xFFFFFFFD); //fat sectors
                    int position = fat.Count - 1;

                    if (i < 109)
                    {
                        difatSectorList.Add((uint)position);
                    }
                    else
                    {
                        difatAddtionalSectorList.Add((uint)position);
                    }
                }

                for (int i = 0; i < difatSectorCount; i++)
                {
                    fat.Add(0xFFFFFFFC); //difat sectors
                }

                for (int i = 0; i < fat.Count; i += fatSectorsPerSector)
                {
                    byte[] fatSector = new byte[header.SectorSize];

                    for (int j = 0; j < fatSectorsPerSector; j++)
                    {
                        if (i + j < fat.Count)
                        {
                            uint currentFat = (uint)fat[i + j];

                            byte[] currentFatBuffer = BitConverter.GetBytes(currentFat);
                            System.Array.Copy(currentFatBuffer, 0, fatSector, j * 4, 4);
                        }
                        else
                        {
                            byte[] currentFatBuffer = BitConverter.GetBytes(0xFFFFFFFF);
                            System.Array.Copy(currentFatBuffer, 0, fatSector, j * 4, 4);
                        }
                    }

                    compoundFileWriter.Write(fatSector);
                }

                if (difatSectorCount > 0)
                {
                    header.FirstDifatSector = (uint)(compoundFileWriter.BaseStream.Position / header.SectorSize);
                }
                else
                {
                    header.FirstDifatSector = 0xFFFFFFFE;
                }

                header.DifatSectorCount = (uint)difatSectorCount;

                for (int i = 0; i < difatSectorList.Count; i++)
                {
                    header.Difat[i] = difatSectorList[i];
                }

                for (int i = difatSectorList.Count; i < 109; i++)
                {
                    header.Difat[i] = 0xFFFFFFFF;
                }

                int nextDifatSector = 1;

                for (int i = 0; i < difatAddtionalSectorList.Count; i += fatSectorsPerSector - 1)
                {
                    byte[] fatSector = new byte[header.SectorSize];

                    for (int j = 0; j < fatSectorsPerSector - 1; j++)
                    {
                        if (i + j < difatAddtionalSectorList.Count)
                        {
                            uint currentFat = difatAddtionalSectorList[i + j];

                            byte[] currentFatBuffer = BitConverter.GetBytes(currentFat);
                            System.Array.Copy(currentFatBuffer, 0, fatSector, j * 4, 4);
                        }
                        else
                        {
                            byte[] currentFatBuffer = BitConverter.GetBytes(0xFFFFFFFF);
                            System.Array.Copy(currentFatBuffer, 0, fatSector, j * 4, 4);
                        }
                    }

                    if (i + (fatSectorsPerSector - 1) < difatAddtionalSectorList.Count)
                    {
                        byte[] nextDifatSectorBuffer = BitConverter.GetBytes(header.FirstDifatSector + nextDifatSector++);
                        System.Array.Copy(nextDifatSectorBuffer, 0, fatSector, (fatSectorsPerSector - 1) * 4, 4);
                    }
                    else
                    {
                        byte[] nextDifatSectorBuffer = BitConverter.GetBytes(0xFFFFFFFE);
                        System.Array.Copy(nextDifatSectorBuffer, 0, fatSector, (fatSectorsPerSector - 1) * 4, 4);
                    }

                    compoundFileWriter.Write(fatSector);
                }

                //Header
                ///////////////////////////////////////////////////////////////////////////////////

                header.FirstMiniFatSector = firstMiniFatSector;
                header.MiniFatSectorCount = miniFatSectorCount;

                byte[] headerBuffer = header.ToBytes();

                outputBuffer = new byte[compoundFileMemoryStream.Length + headerBuffer.Length];

                System.Array.Copy(headerBuffer, 0, outputBuffer, 0, headerBuffer.Length);
                System.Array.Copy(compoundFileMemoryStream.ToArray(), 0, outputBuffer, headerBuffer.Length, outputBuffer.Length - headerBuffer.Length);
            }

            return(outputBuffer);
        }