/*
         * private static void InvalidatePMap(PSTFile file)
         * {
         *  file.BaseStream.Seek(PMapPage.FirstPageOffset, SeekOrigin.Begin);
         *  PMapPage pmap = PMapPage.GetFilledPMapPage();
         *  byte[] buffer = pmap.GetBytes(PMapPage.FirstPageOffset);
         *  file.BaseStream.Write(buffer, 0, buffer.Length);
         * }
         *
         * private static void InvalidateDList(PSTFile file)
         * {
         *  file.BaseStream.Seek(DensityListPage.FirstPageOffset, SeekOrigin.Begin);
         *  byte[] buffer = new byte[Page.Length];
         *  file.BaseStream.Write(buffer, 0, buffer.Length);
         * }*/

        private static AllocationMapPage GrowPST(PSTFile file, int newPageIndex)
        {
            // The PST file MUST grow at integer multiples of the number of bytes mapped by an AMap
            ulong oldLength = (ulong)file.BaseStream.Length;
            ulong newLength = oldLength + AllocationMapPage.MapppedLength;

            file.BaseStream.Seek(0, SeekOrigin.End);
            AllocationMapPage amap = new AllocationMapPage();
            int freeSpaceInAMap    = AllocationMapPage.MapppedLength - 512;

            byte[] buffer = new byte[AllocationMapPage.MapppedLength];
            if (newPageIndex % 8 == 0)
            {
                // We need to write a PMap for backward compatibility
                PMapPage pmap       = PMapPage.GetFilledPMapPage();
                ulong    pmapOffset = PMapPage.FirstPageOffset + (ulong)(newPageIndex / 8) * PMapPage.MapppedLength;
                Array.Copy(pmap.GetBytes(pmapOffset), 0, buffer, 512, Page.Length);

                // Allocate the PMap out of the AMap
                amap.AllocateSpace(512, 512);
                freeSpaceInAMap -= 512;

                if (newPageIndex >= 128 && FreeMapPage.GetFreeMapEntryIndex(newPageIndex) == 0)
                {
                    // We need to write an FMap for backward compatibility
                    FreeMapPage fmap = new FreeMapPage();
                    fmap.rgbFMapBits[0] = 255;
                    int   fmapPageIndex = FreeMapPage.GetFreeMapPageIndex(newPageIndex);
                    ulong fmapOffset    = FreeMapPage.FirstPageOffset + (ulong)fmapPageIndex * FreeMapPage.MapppedLength;
                    Array.Copy(fmap.GetBytes(fmapOffset), 0, buffer, 1024, Page.Length);

                    // Allocate the FMap out of the AMap
                    amap.AllocateSpace(1024, 512);
                    freeSpaceInAMap -= 512;
                }

                // FPMap page will always follow an FMap page
                if (newPageIndex >= (128 * 64) && FPMapPage.GetFPMapEntryIndex(newPageIndex) == 0)
                {
                    // We need to write a FPMap for backward compatibility
                    FPMapPage fpmap          = new FPMapPage();
                    int       fpmapPageIndex = FPMapPage.GetFPMapPageIndex(newPageIndex);
                    ulong     fpmapOffset    = FPMapPage.FirstPageOffset + (ulong)fpmapPageIndex * FPMapPage.MapppedLength;
                    Array.Copy(fpmap.GetBytes(fpmapOffset), 0, buffer, 1536, Page.Length);

                    // Allocate the FPMap out of the AMap
                    amap.AllocateSpace(1536, 512);
                    freeSpaceInAMap -= 512;
                }
            }
            Array.Copy(amap.GetBytes(oldLength), 0, buffer, 0, AllocationMapPage.Length);
            file.BaseStream.Write(buffer, 0, buffer.Length);
            file.Header.root.ibFileEOF   = newLength;
            file.Header.root.ibAMapLast  = oldLength;
            file.Header.root.cbAMapFree += (ulong)freeSpaceInAMap;
            file.Header.WriteToStream(file.BaseStream, file.WriterCompatibilityMode);

            return(amap);
        }
        private static void UpdateFMap(PSTFile file, AllocationMapPage targetPage, int targetPageIndex)
        {
            byte fMax               = (byte)Math.Min(255, targetPage.GetMaxContiguousSpace() / 64);
            int  fmapPageIndex      = FreeMapPage.GetFreeMapPageIndex(targetPageIndex);
            int  fmapPageEntryIndex = FreeMapPage.GetFreeMapEntryIndex(targetPageIndex);

            if (fmapPageIndex >= 0)
            {
                FreeMapPage fmap = FreeMapPage.ReadFreeMapPage(file, fmapPageIndex);
                fmap.rgbFMapBits[fmapPageEntryIndex] = fMax;
                fmap.WriteFreeMapPage(file, fmapPageIndex);
            }
            else
            {
                file.Header.rgbFM[fmapPageEntryIndex] = fMax;
            }
        }