/*++

Copyright (c) 1990 Microsoft Corporation

Module Name:

    rfatsa.hxx

Abstract:

Author:

    Mark Shavlik (marks) 27-Mar-90
    Norbert Kusters (norbertk) 15-Jan-91
    Matthew Bradburn (mattbr) 01-Oct-93

--*/

#ifndef REAL_FAT_SA_DEFN
#define REAL_FAT_SA_DEFN

#include "hmem.hxx"
#include "message.hxx"
#include "fatsa.hxx"
#include "bpb.hxx"

#if defined ( _AUTOCHECK_ )
#define UFAT_EXPORT
#elif defined ( _UFAT_MEMBER_ )
#define UFAT_EXPORT    __declspec(dllexport)
#else
#define UFAT_EXPORT    __declspec(dllimport)
#endif

//
//    Forward references
//

DECLARE_CLASS( ARRAY );
DECLARE_CLASS( BITVECTOR );
DECLARE_CLASS( EA_HEADER );
DECLARE_CLASS( FAT );
DECLARE_CLASS( FAT_SA );
DECLARE_CLASS( FAT_DIRENT );
DECLARE_CLASS( FATDIR );
DECLARE_CLASS( GENERIC_STRING );
DECLARE_CLASS( INTSTACK );
DECLARE_CLASS( NUMBER_SET );
DECLARE_CLASS( LOG_IO_DP_DRIVE );
DECLARE_CLASS( MESSAGE );
DECLARE_CLASS( ROOTDIR );
DECLARE_CLASS( SORTED_LIST );
DECLARE_CLASS( TIMEINFO );
DECLARE_CLASS( WSTRING );
DEFINE_POINTER_TYPES( PFATDIR );

class REAL_FAT_SA : public FAT_SA {

    public:

        UFAT_EXPORT
        DECLARE_CONSTRUCTOR(REAL_FAT_SA);

        VIRTUAL
        UFAT_EXPORT
        ~REAL_FAT_SA(
            );

        NONVIRTUAL
        UFAT_EXPORT
        BOOLEAN
        Initialize(
            IN OUT  PLOG_IO_DP_DRIVE    Drive,
            IN OUT  PMESSAGE            Message,
            IN      BOOLEAN             Formatted DEFAULT TRUE
            );

        NONVIRTUAL
        BOOLEAN
        Create(
            IN      PCNUMBER_SET    BadSectors,
            IN OUT  PMESSAGE        Message,
            IN      PCWSTRING       Label       DEFAULT NULL,
            IN      ULONG           ClusterSize DEFAULT 0,
            IN      ULONG           VirtualSize DEFAULT 0
            );

        NONVIRTUAL
        BOOLEAN
        RecoverFile(
            IN      PCWSTRING   FullPathFileName,
            IN OUT  PMESSAGE    Message
            );

        NONVIRTUAL
        UFAT_EXPORT
        BOOLEAN
        Read(
            IN OUT  PMESSAGE    Message
            );

        NONVIRTUAL
        BOOLEAN
        Write(
            IN OUT  PMESSAGE    Message
            );

        NONVIRTUAL
        VOID
        QueryGeometry(
            OUT PUSHORT SectorSize,
            OUT PUSHORT SectorsPerTrack,
            OUT PUSHORT Heads,
            OUT PULONG  HiddenSectors
            );

        NONVIRTUAL
        USHORT
        QuerySectorsPerCluster(
            ) CONST;

        NONVIRTUAL
        USHORT
        QuerySectorsPerFat(
            ) CONST;

        NONVIRTUAL
        USHORT
        QueryReservedSectors(
            ) CONST;

        NONVIRTUAL
        USHORT
        QueryFats(
            ) CONST;

        NONVIRTUAL
        USHORT
        QueryRootEntries(
            ) CONST;

        NONVIRTUAL
        PARTITION_SYSTEM_ID
        QuerySystemId(
            ) CONST;

        NONVIRTUAL
        LBN
        QueryStartDataLbn(
            ) CONST;

        NONVIRTUAL
        USHORT
        QueryClusterCount(
            ) CONST;

        NONVIRTUAL
        UFAT_EXPORT
        SECTORCOUNT
        QueryFreeSectors(
            ) CONST;

        NONVIRTUAL
        FATTYPE
        QueryFatType(
            ) CONST;

        NONVIRTUAL
        BYTE
        QueryVolumeFlags(
            ) CONST;

        NONVIRTUAL
        VOID
        SetVolumeFlags(
            BYTE Flags,
            BOOLEAN ResetFlags
            );

        NONVIRTUAL
        BOOLEAN
        RecoverChain(
            IN OUT  PUSHORT     StartingCluster,
            OUT     PBOOLEAN    ChangesMade,
            IN      USHORT      EndingCluster   DEFAULT 0,
            IN      BOOLEAN     Replace         DEFAULT FALSE
            );

        STATIC
        USHORT
        ComputeSecClus(
            IN  SECTORCOUNT Sectors,
            IN  FATTYPE     FatType,
            IN  MEDIA_TYPE  MediaType
            );

        NONVIRTUAL
        BOOLEAN
        IsCompressed(
            ) CONST;

        NONVIRTUAL
        BOOLEAN
        ReadSectorZero(
            );

        NONVIRTUAL
        PBIOS_PARAMETER_BLOCK
        GetBpb(
            );

    private:

        HMEM                _mem;           // memory for SECRUN

        // _fat inherited from FAT_SA
        // _fattype inherited from FAT_SA
        // _dir inherited from FAT_SA

        LBN                 _StartDataLbn;  // LBN of files, or data area
        USHORT              _ClusterCount;  // number of clusters in Super Area
        PARTITION_SYSTEM_ID _sysid;         // system id
        ULONG               _sec_per_boot;  // sectors for boot code.
        EXTENDED_BIOS_PARAMETER_BLOCK
                            _sector_zero;
        PUCHAR              _sector_sig;    // sector signature

        NONVIRTUAL
        VOID
        Construct(
            );

        NONVIRTUAL
        VOID
        Destroy(
            );

        NONVIRTUAL
        BOOLEAN
        SetBpb(
            IN  ULONG   ClusterSize
            );

        NONVIRTUAL
        BOOLEAN
        SetBpb(
            );

        NONVIRTUAL
        BOOLEAN
        DupFats(
            );

        NONVIRTUAL
        LBN
        ComputeStartDataLbn(
            ) CONST;

        NONVIRTUAL
        USHORT
        ComputeRootEntries(
            ) CONST;

        NONVIRTUAL
        BOOLEAN
        ValidateDirent(
            IN OUT  PFAT_DIRENT Dirent,
            IN      PCWSTRING   FilePath,
            IN      FIX_LEVEL   FixLevel,
            IN      BOOLEAN     RecoverAlloc,
            IN OUT  PMESSAGE    Message,
            IN OUT  PBOOLEAN    NeedErrorsMessage,
            IN OUT  PBITVECTOR  FatBitMap,
            OUT     PBOOLEAN    CrossLinkDetected,
            OUT     PUSHORT     CrossLinkPreviousCluster
            );

        NONVIRTUAL
        BOOLEAN
        CopyClusters(
            IN      USHORT      SourceChain,
            OUT     PUSHORT     DestChain,
            IN OUT  PBITVECTOR  FatBitMap,
            IN      FIX_LEVEL   FixLevel,
            IN OUT  PMESSAGE    Message
            );

        NONVIRTUAL
        BOOLEAN
        InitRelocationList(
            IN OUT  PINTSTACK       RelocationStack,
            IN OUT  PUSHORT         RelocatedChain,
            IN OUT  PSORTED_LIST    ClustersToRelocate,
            OUT     PBOOLEAN        Relocated
            );

        NONVIRTUAL
        BOOLEAN
        RelocateFirstCluster(
            IN OUT  PFAT_DIRENT     Dirent
            );

        NONVIRTUAL
        USHORT
        RelocateOneCluster(
            IN  USHORT  Cluster,
            IN  USHORT  Previous
            );

        NONVIRTUAL
        BOOLEAN
        DoDirectoryCensusAndRelocation(
            IN OUT  PFATDIR         Directory,
            IN OUT  PCENSUS_REPORT  CensusReport,
            IN OUT  PSORTED_LIST    ClustersToRelocate,
            IN OUT  PUSHORT         RelocatedChain,
            OUT     PBOOLEAN        Relocated
            );

        NONVIRTUAL
        BOOLEAN
        DoVolumeCensusAndRelocation(
            IN OUT  PCENSUS_REPORT  CensusReport,
            IN OUT  PSORTED_LIST    ClustersToRelocate,
            IN OUT  PUSHORT         RelocatedChain,
            OUT     PBOOLEAN        Relocated
            );

        NONVIRTUAL
        ULONG
        SecPerBoot(
            );

        NONVIRTUAL
        VOLID
        QueryVolId(
            ) CONST;

        NONVIRTUAL
        VOLID
        SetVolId(
            IN VOLID VolId
            );

        NONVIRTUAL
        UCHAR
        QueryMediaByte(
            ) CONST;

        VIRTUAL
        VOID
        SetMediaByte(
            UCHAR   MediaByte
            );

        NONVIRTUAL
        BOOLEAN
        VerifyBootSector(
            );

        NONVIRTUAL
        SECTORCOUNT
        QueryVirtualSectors(
            ) CONST;

        NONVIRTUAL
        BOOLEAN
        CreateBootSector(
            IN  ULONG   ClusterSize
            );

        BOOLEAN
        REAL_FAT_SA::SetBootCode(
            );

        NONVIRTUAL
        BOOLEAN
        SetPhysicalDriveType(
            IN  PHYSTYPE    PhysType
            );

        NONVIRTUAL
        BOOLEAN
        SetOemData(
            );

        NONVIRTUAL
        BOOLEAN
        SetSignature(
            );

        NONVIRTUAL
        BOOLEAN
        SetBootSignature(
            IN  UCHAR   Signature DEFAULT sigBOOTSTRAP
            );

        BOOLEAN
        DosSaInit(
            IN OUT PMEM         Mem,
            IN OUT PLOG_IO_DP_DRIVE Drive,
            IN     SECTORCOUNT     NumberOfSectors,
            IN OUT PMESSAGE        Message
            );

        BOOLEAN
        DosSaSetBpb(
            );

        BOOLEAN
        RecoverOrphans(
            IN OUT  PBITVECTOR  FatBitMap,
            IN      FIX_LEVEL   FixLevel,
            IN OUT  PMESSAGE    Message,
            IN OUT  PBOOLEAN    NeedErrorsMessage
            );

        NONVIRTUAL
        ULONG
        QuerySectorFromCluster(
            IN      ULONG       Cluster,
            OUT     PUCHAR      NumSectors        DEFAULT NULL
            );

        NONVIRTUAL
        BOOLEAN
        IsClusterCompressed(
            IN      ULONG       Cluster
            ) CONST;

        NONVIRTUAL
        VOID
        SetClusterCompressed(
            IN      ULONG       Cluster,
            IN      BOOLEAN     fCompressed
            );

        NONVIRTUAL
        UCHAR
        QuerySectorsRequiredForPlainData(
            IN      ULONG       Cluster
            );

        NONVIRTUAL
        BOOLEAN
        VerifyFatExtensions(
            IN      FIX_LEVEL   FixLevel,
            IN      PMESSAGE    Message,
            IN      PBOOLEAN    pfNeedMsg
            );

        NONVIRTUAL
        BOOLEAN
        CheckSectorHeapAllocation(
            IN      FIX_LEVEL   FixLevel,
            IN      PMESSAGE    Message,
            IN      PBOOLEAN    pfNeedMsg
            );

        NONVIRTUAL
        BOOLEAN
        FreeClusterData(
            ULONG Cluster
            );

        NONVIRTUAL
        BOOLEAN
        AllocateClusterData(
            ULONG Cluster,
            UCHAR NumSectors,
            BOOLEAN bCompressed,
            UCHAR PlainSize
            );


};

INLINE
USHORT
REAL_FAT_SA::QuerySectorsPerCluster(
    ) CONST
/*++

Routine Description:

    This routine computes the number of sectors per cluster for
    the volume.

Arguments:

    None.

Return Value:

    The number of sectors per cluster for the volume.

--*/
{
    return _sector_zero.Bpb.SectorsPerCluster ?
           _sector_zero.Bpb.SectorsPerCluster : 256;
}


INLINE
USHORT
REAL_FAT_SA::QuerySectorsPerFat(
    ) CONST
/*++

Routine Description:

    This routine computes the number of sectors per FAT for the volume.

Arguments:

    None.

Return Value:

    The number of sectors per FAT for the volume.

--*/
{
    return _sector_zero.Bpb.SectorsPerFat;
}


INLINE
USHORT
REAL_FAT_SA::QueryReservedSectors(
    ) CONST
/*++

Routine Description:

    This routine computes the volume's number of Reserved Sectors,
    i.e. the number of sectors before the first FAT.

Arguments:

    None.

Return Value:

    The number of Reserved Sectors.

--*/
{
    return _sector_zero.Bpb.ReservedSectors;
}

INLINE
USHORT
REAL_FAT_SA::QueryFats(
    ) CONST
/*++

Routine Description:

    This routine computes the number of FATs on the volume.

Arguments:

    None.

Return Value:

    The number of FATs on the volume.

--*/
{
    return _sector_zero.Bpb.Fats;
}

INLINE
USHORT
REAL_FAT_SA::QueryRootEntries(
    ) CONST
/*++

Routine Description:

    This routine returns the number of entries in the root
    directory.

Arguments:

    None.

Return Value:

    The number of root directory entries.

--*/
{
    return _sector_zero.Bpb.RootEntries;
}


INLINE
PARTITION_SYSTEM_ID
REAL_FAT_SA::QuerySystemId(
    ) CONST
/*++

Routine Description:

    This routine computes the system ID for the volume.

Arguments:

    None.

Return Value:

    The system ID for the volume.

--*/
{
    return _sysid;
}


INLINE
LBN
REAL_FAT_SA::QueryStartDataLbn(
    ) CONST
/*++

Routine Description:

    This routine computes the LBN of the first logical cluster of the
    volume.

Arguments:

    None.

Return Value:

    The LBN of the first logical cluster of the volume.

--*/
{
    return _StartDataLbn;
}


INLINE
USHORT
REAL_FAT_SA::QueryClusterCount(
    ) CONST
/*++

Routine Description:

    This routine computes the total number of clusters for the volume.
    That is to say that the largest addressable cluster on the disk
    is cluster number 'QueryClusterCount() - 1'.  Note that the
    smallest addressable cluster on the disk is 2.

Arguments:

    None.

Return Value:

    The total number of clusters for the volume.

--*/
{
    return _ClusterCount;
}

INLINE BOOLEAN
REAL_FAT_SA::IsCompressed(
    ) CONST
/*++

Routine Description:

    This routine tells whether this volume is doublespaced or not.
    Since the class is REAL_FAT_SA, we know it's not.

Arguments:

Return Value:

    TRUE  -   Compressed.
    FALSE -   Not compressed.

--*/
{
    return FALSE;
}

INLINE BOOLEAN
REAL_FAT_SA::ReadSectorZero(
    )
/*++

Routine Description:

    This routine used to be DOS_SUPERAREA::Read().

Arguments:

Return Value:

    TRUE  -   Success.
    FALSE -   Failure.

--*/
{
    BOOLEAN b;
    PEXTENDED_BIOS_PARAMETER_BLOCK Pbios;

    b = SECRUN::Read();
    if (!b)
        return FALSE;

    Pbios = (PEXTENDED_BIOS_PARAMETER_BLOCK)SECRUN::GetBuf();
    UnpackExtendedBios(&_sector_zero, Pbios);

    return TRUE;
}

INLINE
PBIOS_PARAMETER_BLOCK
REAL_FAT_SA::GetBpb(
    )
{
    return &(_sector_zero.Bpb);
}



INLINE
UCHAR
REAL_FAT_SA::QueryMediaByte(
    ) CONST
/*++

Routine Description:

    This routine fetches the media byte from the super area's data.

Arguments:

    None.

Return Value:

    The media byte residing in the super area.

--*/
{
       return _sector_zero.Bpb.Media;
}

INLINE
VOID
REAL_FAT_SA::SetMediaByte(
    UCHAR   MediaByte
    )
/*++

Routine Description:

    This routine sets the media byte in the super area's data.

Arguments:

    MediaByte   --  Supplies the new media byte.

Return Value:

    None.

--*/
{
       _sector_zero.Bpb.Media = MediaByte;
}

INLINE
SECTORCOUNT
REAL_FAT_SA::QueryVirtualSectors(
    ) CONST
/*++

Routine Description:

    This routine computes the number of sectors on the volume according
    to the file system.

Arguments:

    None.

Return Value:

    The number of sectors on the volume according to the file system.

--*/
{
    return _sector_zero.Bpb.Sectors ? _sector_zero.Bpb.Sectors :
           _sector_zero.Bpb.LargeSectors;
}

INLINE
VOLID
REAL_FAT_SA::QueryVolId(
    ) CONST
/*++

Routine Description:

    This routine fetches the volume ID from the super area's data.
    This routine will return 0 if volume serial numbers are not
    supported by the partition.

Arguments:

    None.

Return Value:

    The volume ID residing in the super area.

--*/
{
       return (_sector_zero.Signature == 0x28 || _sector_zero.Signature == 0x29) ?
           _sector_zero.SerialNumber : 0;
}

INLINE
VOLID
REAL_FAT_SA::SetVolId(
    IN  VOLID   VolId
    )
/*++

Routine Description:

    This routine puts the volume ID into the super area's data.

Arguments:

    VolId   - The new volume ID.

Return Value:

    The volume ID that was put.

--*/
{
       return _sector_zero.SerialNumber = VolId;
}

INLINE
BOOLEAN
REAL_FAT_SA::SetBootSignature(
    IN  UCHAR   Signature
    )
/*++

Routine Description:

    This routine sets the boot signature in the super area.

Arguments:

    Signature   - Supplies the character to set the signature to.

Return Value:

    FALSE   - Failure.
    TRUE    - Success.

--*/
{
     _sector_zero.Signature = Signature;
    return TRUE;
}

INLINE
VOID
REAL_FAT_SA::QueryGeometry(
    OUT PUSHORT SectorSize,
    OUT PUSHORT SectorsPerTrack,
    OUT PUSHORT Heads,
    OUT PULONG  HiddenSectors
    )
/*++

Routine Description:

    This method returns the geometry information stored in
    the Bios Parameter Block.

Arguments:

    SectorSize      --  Receives the recorded sector size.
    SectorsPerTrack --  Receives the recorded sectors per track.
    Heads           --  Receives the recorded number of heads.
    HiddenSectors   --  Receives the recorded number of hidden sectors.

Return Value:

    None.

--*/
{
    *SectorSize = _sector_zero.Bpb.BytesPerSector;
    *SectorsPerTrack = _sector_zero.Bpb.SectorsPerTrack;
    *Heads = _sector_zero.Bpb.Heads;
    *HiddenSectors = _sector_zero.Bpb.HiddenSectors;
}

INLINE
BYTE
REAL_FAT_SA::QueryVolumeFlags(
    ) CONST
/*++

Routine Description:

    This routine returns the volume flags byte from the bpb.

Arguments:

    None.

Return Value:

    The flags.

--*/
{
    return _sector_zero.CurrentHead;
}

INLINE
VOID
REAL_FAT_SA::SetVolumeFlags(
    BYTE Flags,
    BOOLEAN ResetFlags
    )
/*++

Routine Description:

    This routine sets the volume flags in the bpb.

Arguments:

    Flags       -- flags to set or clear
    ResetFlags  -- if true, Flags are cleared instead of set

Return Value:

    None.

--*/
{
    if (ResetFlags) {
        _sector_zero.CurrentHead &= ~Flags;
    } else {
        _sector_zero.CurrentHead |= Flags;
    }
}

INLINE
BOOLEAN
AllocateClusterData(
    ULONG Cluster,
    UCHAR NumSectors,
    BOOLEAN bCompressed,
    UCHAR PlainSize
    )
{
    DebugAbort("Didn't expect REAL_FAT_SA::AllocateClusterData() to be called");
    return FALSE;
}

#endif // REAL_FAT_SA_DEFN