Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1128 lines
22 KiB

/*++
Copyright (c) 1990-2001 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 );
//
// Sony Memory Stick thresholds
//
#define SMS_VOLSIZE_SMALL (70*1024*1024) // Maximum volume size to be formatted as FAT12
// Internal data types
// Possible return status after validating a given cluster size
typedef enum _VALIDATION_STATUS
{
VALID,
TOO_SMALL,
TOO_BIG
} VALIDATION_STATUS;
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
UFAT_EXPORT
BOOLEAN
InitFATChkDirty(
IN OUT PLOG_IO_DP_DRIVE Drive,
IN OUT PMESSAGE Message
);
NONVIRTUAL
BOOLEAN
Create(
IN PCNUMBER_SET BadSectors,
IN OUT PMESSAGE Message,
IN PCWSTRING Label DEFAULT NULL,
IN ULONG Flags DEFAULT FORMAT_BACKWARD_COMPATIBLE,
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
ULONG
QuerySectorsPerFat(
) CONST;
NONVIRTUAL
USHORT
QueryReservedSectors(
) CONST;
NONVIRTUAL
USHORT
QueryFats(
) CONST;
NONVIRTUAL
ULONG
QueryRootEntries(
) CONST;
NONVIRTUAL
PARTITION_SYSTEM_ID
QuerySystemId(
) CONST;
NONVIRTUAL
LBN
QueryStartDataLbn(
) CONST;
NONVIRTUAL
ULONG
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 PULONG StartingCluster,
OUT PBOOLEAN ChangesMade,
IN ULONG EndingCluster DEFAULT 0,
IN BOOLEAN Replace DEFAULT FALSE,
IN PBITVECTOR FatBitMap DEFAULT NULL
);
STATIC
USHORT
ComputeSecClus(
IN SECTORCOUNT Sectors,
IN FATTYPE FatType,
#if defined(FE_SB) && defined(_X86_)
IN MEDIA_TYPE MediaType,
IN ULONG SectorSize = 512
#else
IN MEDIA_TYPE MediaType
#endif
);
NONVIRTUAL
BOOLEAN
IsFileContiguous(
IN ULONG StartingCluster
) CONST;
NONVIRTUAL
BOOLEAN
IsCompressed(
) CONST;
NONVIRTUAL
BOOLEAN
IsVolumeDataAligned(
) CONST;
NONVIRTUAL
BOOLEAN
ReadSectorZero(
);
NONVIRTUAL
PBIOS_PARAMETER_BLOCK
GetBpb(
);
NONVIRTUAL
SECTORCOUNT
QueryVirtualSectors(
) CONST;
NONVIRTUAL
VOID
PrintFormatReport (
IN OUT PMESSAGE Message,
IN PFILE_FS_SIZE_INFORMATION FsSizeInfo,
IN PFILE_FS_VOLUME_INFORMATION FsVolInfo
);
private:
HMEM _mem; // memory for SECRUN
// _fat inherited from FAT_SA
// _fattype inherited from FAT_SA
// _dir inherited from FAT_SA
HMEM _mem2; // memory for SECRUN2
SECRUN _secrun2; // secrun to hold one sector FAT sector
LBN _StartDataLbn; // LBN of files, or data area
ULONG _ClusterCount; // number of clusters in Super Area
// It actually means the number of
// fat entries.
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
BOOLEAN _data_aligned; // TRUE if data clusters are aligned to
// FAT_FIRST_DATA_CLUSTER_ALIGNMENT boundary
ULONG _AdditionalReservedSectors; // padding to be added for data alignment
NONVIRTUAL
VOID
Construct(
);
NONVIRTUAL
VOID
Destroy(
);
NONVIRTUAL
VALIDATION_STATUS
ValidateClusterSize(
IN ULONG ClusterSize,
IN ULONG Sectors,
IN ULONG SectorSize,
IN ULONG Fats,
IN OUT FATTYPE *FatType,
OUT PULONG FatSize,
OUT PULONG ClusterCount
);
NONVIRTUAL
ULONG
ComputeDefaultClusterSize(
IN ULONG Sectors,
IN ULONG SectorSize,
IN ULONG ReservedSectors,
IN ULONG Fats,
IN MEDIA_TYPE MediaType,
IN FATTYPE FatType,
OUT PULONG FatSize,
OUT PULONG ClusterCount
);
NONVIRTUAL
ULONG
DetermineClusterCountAndFatType (
IN OUT PULONG StartingDataLbn,
IN OUT FATTYPE *Fattype
);
NONVIRTUAL
BOOLEAN
InitializeRootDirectory (
IN PMESSAGE Message
);
NONVIRTUAL
BOOLEAN
SetBpb(
IN ULONG ClusterSize,
IN ULONG Flags,
IN PMESSAGE Message
);
NONVIRTUAL
BOOLEAN
SetBpb(
);
NONVIRTUAL
BOOLEAN
DupFats(
);
NONVIRTUAL
LBN
ComputeStartDataLbn(
) CONST;
NONVIRTUAL
ULONG
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 PULONG CrossLinkPreviousCluster
);
NONVIRTUAL
BOOLEAN
CopyClusters(
IN ULONG SourceChain,
OUT PULONG DestChain,
IN OUT PBITVECTOR FatBitMap,
IN FIX_LEVEL FixLevel,
IN OUT PMESSAGE Message
);
NONVIRTUAL
BOOLEAN
InitRelocationList(
IN OUT PINTSTACK RelocationStack,
IN OUT PULONG RelocatedChain,
IN OUT PSORTED_LIST ClustersToRelocate,
OUT PBOOLEAN Relocated
);
NONVIRTUAL
BOOLEAN
RelocateFirstCluster(
IN OUT PFAT_DIRENT Dirent
);
NONVIRTUAL
ULONG
RelocateOneCluster(
IN ULONG Cluster,
IN ULONG Previous
);
NONVIRTUAL
BOOLEAN
DoDirectoryCensusAndRelocation(
IN OUT PFATDIR Directory,
IN OUT PCENSUS_REPORT CensusReport,
IN OUT PSORTED_LIST ClustersToRelocate,
IN OUT PULONG RelocatedChain,
OUT PBOOLEAN Relocated
);
NONVIRTUAL
BOOLEAN
DoVolumeCensusAndRelocation(
IN OUT PCENSUS_REPORT CensusReport,
IN OUT PSORTED_LIST ClustersToRelocate,
IN OUT PULONG 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
BOOLEAN
CreateBootSector(
IN ULONG ClusterSize,
IN ULONG Flags,
IN PMESSAGE Message
);
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,
IN OUT PFATCHK_REPORT Report,
OUT PBOOLEAN Changes
);
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
VOID
SetFat32RootDirStartingCluster(
IN ULONG RootCluster
);
NONVIRTUAL
ULONG
QueryFat32RootDirStartingCluster(
);
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
);
//
// The following routines are defined for the new lightweight
// format.
//
NONVIRTUAL
BOOLEAN
DiskIsUsable (
IN PCNUMBER_SET BadSectors,
IN PMESSAGE Message
);
NONVIRTUAL
BOOLEAN
WriteNewFats (
IN PCNUMBER_SET BadSectors,
IN OUT PULONG BadClusters,
IN PMESSAGE Message
);
NONVIRTUAL
BOOLEAN
WriteNewRootDirAndVolumeLabel (
IN PCWSTRING Label,
IN PMESSAGE Message
);
NONVIRTUAL
BOOLEAN
WriteNewBootArea (
IN PMESSAGE Message
);
NONVIRTUAL
VOID
PrintFormatReport (
IN ULONG BadClusters,
IN PMESSAGE Message
);
};
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
ULONG
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.
--*/
{
if ( 0 == _sector_zero.Bpb.SectorsPerFat ) {
return _sector_zero.Bpb.BigSectorsPerFat;
} else {
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
ULONG
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
ULONG
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::IsVolumeDataAligned(
) CONST
/*++
Routine Description:
This routine tells whether the data clusters of this volume is
aligned to FAT_FIRST_DATA_CLUSTER_ALIGNMENT boundary.
Arguments:
Return Value:
TRUE - Aligned.
FALSE - Not aligned.
--*/
{
return _data_aligned;
}
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
BOOLEAN
AllocateClusterData(
ULONG Cluster,
UCHAR NumSectors,
BOOLEAN bCompressed,
UCHAR PlainSize
)
{
DebugAbort("Didn't expect REAL_FAT_SA::AllocateClusterData() to be called");
return FALSE;
}
//
// Defines for the volume flags in the BPB current head field.
//
#define FAT_BPB_RESERVED_DIRTY 0x01
#define FAT_BPB_RESERVED_TEST_SURFACE 0x02
//
// Defines for the volume flags in FAT[1].
//
#define CLUS1CLNSHUTDWNFAT16 0x00008000
#define CLUS1NOHRDERRFAT16 0x00004000
#define CLUS1CLNSHUTDWNFAT32 0x08000000
#define CLUS1NOHRDERRFAT32 0x04000000
#endif // REAL_FAT_SA_DEFN