1090 lines
19 KiB
C++
1090 lines
19 KiB
C++
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
fat.hxx
|
|
|
|
Abstract:
|
|
|
|
This class models a file allocation table. The composition is of
|
|
virtual functions because there are two different kinds of file
|
|
allocation tables. A user of this class will be able to manipulate
|
|
the FAT regardless of the implementation.
|
|
|
|
Author:
|
|
|
|
Norbert P. Kusters (norbertk) 6-Dec-90
|
|
|
|
--*/
|
|
|
|
#if !defined(FAT_DEFN)
|
|
|
|
#define FAT_DEFN
|
|
|
|
#include "secrun.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( FAT );
|
|
DECLARE_CLASS( BITVECTOR );
|
|
|
|
CONST ULONG FirstDiskCluster = 2;
|
|
CONST ULONG MaxNumClusForSmallFat = 4086;
|
|
|
|
// - flags to denote three state FAT type
|
|
CONST ULONG MinNumClusForFat32 = 65526; // Min # Fat32 clusters is 65525
|
|
// The largest FAT16 entry goes
|
|
// up to 65527
|
|
CONST fFat12 = 12;
|
|
CONST fFat16 = 16;
|
|
CONST fFat32 = 32;
|
|
|
|
class FAT : public SECRUN {
|
|
|
|
public:
|
|
|
|
DECLARE_CONSTRUCTOR(FAT);
|
|
|
|
VIRTUAL
|
|
~FAT(
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
Initialize(
|
|
IN OUT PMEM Mem,
|
|
IN OUT PLOG_IO_DP_DRIVE Drive,
|
|
IN LBN StartSector,
|
|
IN ULONG NumOfEntries,
|
|
IN ULONG NumSectors DEFAULT 0
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
Initialize(
|
|
IN OUT PSECRUN Srun,
|
|
IN OUT PMEM Mem,
|
|
IN OUT PLOG_IO_DP_DRIVE Drive,
|
|
IN LBN StartSector,
|
|
IN ULONG NumOfEntries,
|
|
IN ULONG NumSectors DEFAULT 0
|
|
);
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
QueryEntry(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
SetEntry(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
IsInRange(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
IsClusterFree(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
SetClusterFree(
|
|
IN ULONG ClusterNumber
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
IsEndOfChain(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
SetEndOfChain(
|
|
IN ULONG ClusterNumber
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
IsClusterBad(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
SetClusterBad(
|
|
IN ULONG ClusterNumber
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
IsClusterReserved(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
SetClusterReserved(
|
|
IN ULONG ClusterNumber
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
SetEarlyEntries(
|
|
IN UCHAR MediaByte
|
|
);
|
|
|
|
NONVIRTUAL
|
|
UCHAR
|
|
QueryMediaByte(
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
QueryFreeClusters(
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
QueryBadClusters(
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
QueryReservedClusters(
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
UFAT_EXPORT
|
|
ULONG
|
|
QueryAllocatedClusters(
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
UFAT_EXPORT
|
|
ULONG
|
|
QueryNthCluster(
|
|
IN ULONG StartingCluster,
|
|
IN ULONG Index
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
UFAT_EXPORT
|
|
ULONG
|
|
QueryLengthOfChain(
|
|
IN ULONG StartingCluster,
|
|
OUT PULONG LastCluster DEFAULT NULL
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
QueryLengthOfChain(
|
|
IN ULONG StartingCluster,
|
|
IN ULONG EndingCluster
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
QueryPrevious(
|
|
IN ULONG Cluster
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Scrub(
|
|
OUT PBOOLEAN ChangesMade DEFAULT NULL
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
ScrubChain(
|
|
IN ULONG StartingCluster,
|
|
OUT PBOOLEAN ChangesMade
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
ScrubChain(
|
|
IN ULONG StartingCluster,
|
|
OUT PBITVECTOR UsedClusters,
|
|
OUT PBOOLEAN ChangesMade,
|
|
OUT PBOOLEAN CrossLinkDetected,
|
|
OUT PULONG CrossLinkPreviousCluster
|
|
);
|
|
|
|
NONVIRTUAL
|
|
BOOLEAN
|
|
IsValidChain(
|
|
IN ULONG StartingCluster
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
UFAT_EXPORT
|
|
ULONG
|
|
AllocChain(
|
|
IN ULONG Length,
|
|
OUT PULONG LastCluster DEFAULT NULL
|
|
);
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
ReAllocChain(
|
|
IN ULONG StartOfChain,
|
|
IN ULONG NewLength,
|
|
OUT PULONG LastCluster DEFAULT NULL
|
|
);
|
|
|
|
NONVIRTUAL
|
|
UFAT_EXPORT
|
|
VOID
|
|
FreeChain(
|
|
IN ULONG StartOfChain
|
|
);
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
RemoveChain(
|
|
IN ULONG PreceedingCluster,
|
|
IN ULONG LastCluster
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
InsertChain(
|
|
IN ULONG StartOfChain,
|
|
IN ULONG EndOfChain,
|
|
IN ULONG PreceedingCluster
|
|
);
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
InsertChain(
|
|
IN ULONG StartOfChain,
|
|
IN ULONG Cluster
|
|
);
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
QueryAllocatedClusterCount(
|
|
VOID
|
|
) ;
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
InvalidateAllocatedClusterCount(
|
|
VOID
|
|
) ;
|
|
|
|
|
|
private:
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Construct(
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Destroy(
|
|
);
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
Index(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
UFAT_EXPORT
|
|
ULONG
|
|
Index12(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
Index16(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
ULONG
|
|
Index32(
|
|
IN ULONG ClusterNumber
|
|
) CONST;
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Set(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
);
|
|
|
|
NONVIRTUAL
|
|
UFAT_EXPORT
|
|
VOID
|
|
Set12(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Set16(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
);
|
|
|
|
NONVIRTUAL
|
|
VOID
|
|
Set32(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
);
|
|
|
|
PVOID _fat;
|
|
ULONG _num_entries;
|
|
ULONG _low_end_of_chain; // 0xFFF8 or 0x0FF8
|
|
ULONG _end_of_chain; // 0xFFFF or 0x0FFF
|
|
ULONG _bad_cluster; // 0xFFF7 or 0x0FF7
|
|
ULONG _low_reserved; // 0xFFF0 or 0x0FF0
|
|
ULONG _high_reserved; // 0xFFF6 or 0x0FF6
|
|
UCHAR _fat_bits; // Replacing _is_big with count of bits in FAT entry
|
|
// BOOLEAN _is_big; // Boolean TRUE for FAT16, FALSE for FAT12
|
|
ULONG _AllocatedClusters; // Count of allocated clusters
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
INLINE
|
|
BOOLEAN
|
|
FAT::IsInRange(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine computes whether or not ClusterNumber is a cluster on
|
|
the disk.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the cluster to be checked.
|
|
|
|
Return Value:
|
|
|
|
FALSE - The cluster is not on the disk.
|
|
TRUE - The cluster is on the disk.
|
|
|
|
--*/
|
|
{
|
|
return (FirstDiskCluster <= ClusterNumber && ClusterNumber < _num_entries);
|
|
}
|
|
|
|
|
|
INLINE
|
|
ULONG
|
|
FAT::Index16(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine indexes the FAT as 16 bit little endian entries.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the FAT entry desired.
|
|
|
|
Return Value:
|
|
|
|
The value of the FAT entry at ClusterNumber.
|
|
|
|
--*/
|
|
{
|
|
//DebugAssert(IsInRange(ClusterNumber));
|
|
|
|
return (ULONG )(((PUSHORT) _fat)[ClusterNumber]);
|
|
}
|
|
|
|
|
|
INLINE
|
|
ULONG
|
|
FAT::Index32(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine indexes the FAT as 32 bit little endian entries.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the FAT entry desired.
|
|
|
|
Return Value:
|
|
|
|
The value of the 32 (actually 28) bit FAT entry at ClusterNumber.
|
|
|
|
--*/
|
|
{
|
|
//DebugAssert(IsInRange(ClusterNumber));
|
|
|
|
return (((PULONG) _fat)[ClusterNumber]) & 0x0FFFFFFF;
|
|
}
|
|
|
|
INLINE
|
|
ULONG
|
|
FAT::Index(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine indexes the FAT as 16 bit or 12 bit little endian entries.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the FAT entry desired.
|
|
|
|
Return Value:
|
|
|
|
The value of the FAT entry at ClusterNumber.
|
|
|
|
--*/
|
|
{
|
|
if (fFat12 == _fat_bits)
|
|
return Index12(ClusterNumber);
|
|
else if (fFat16 == _fat_bits)
|
|
return Index16(ClusterNumber);
|
|
else
|
|
return Index32(ClusterNumber);
|
|
}
|
|
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::Set16(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the ClusterNumber'th 16 bit FAT entry to Value.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the FAT entry to set.
|
|
Value - Supplies the value to set the FAT entry to.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//DebugAssert(IsInRange(ClusterNumber));
|
|
((PUSHORT) _fat)[ClusterNumber] = (USHORT)Value;
|
|
_AllocatedClusters = 0xFFFFFFFF;
|
|
}
|
|
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::Set32(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the ClusterNumber'th 32 (actually 28) bit FAT entry to Value.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the FAT entry to set.
|
|
Value - Supplies the value to set the FAT entry to.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
//DebugAssert(IsInRange(ClusterNumber));
|
|
((PULONG) _fat)[ClusterNumber] &= 0xF0000000;
|
|
((PULONG) _fat)[ClusterNumber] |= (Value & 0x0FFFFFFF);
|
|
_AllocatedClusters = 0xFFFFFFFF;
|
|
}
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::Set(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the ClusterNumber'th 12 bit or 16 bit FAT entry to Value.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the FAT entry to set.
|
|
Value - Supplies the value to set the FAT entry to.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if (fFat12 == _fat_bits)
|
|
Set12(ClusterNumber, Value);
|
|
else if (fFat16 == _fat_bits)
|
|
Set16(ClusterNumber, Value);
|
|
else
|
|
Set32(ClusterNumber, Value);
|
|
}
|
|
|
|
|
|
INLINE
|
|
ULONG
|
|
FAT::QueryEntry(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the FAT value for ClusterNumber.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies an index into the FAT.
|
|
|
|
Return Value:
|
|
|
|
The FAT table entry at offset ClusterNumber.
|
|
|
|
--*/
|
|
{
|
|
return Index(ClusterNumber);
|
|
}
|
|
|
|
INLINE
|
|
ULONG
|
|
FAT::QueryAllocatedClusterCount(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine computes the total number of clusters for the volume.
|
|
which are allocated.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The total number of allocated clusters for the volume.
|
|
|
|
--*/
|
|
{
|
|
if(_AllocatedClusters == 0xFFFFFFFF)
|
|
{
|
|
if(_fat == NULL) {
|
|
return(0);
|
|
}
|
|
_AllocatedClusters = FAT::QueryAllocatedClusters();
|
|
}
|
|
return _AllocatedClusters;
|
|
}
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::InvalidateAllocatedClusterCount(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine invalidates trhe cached allocated clusters count so that the next
|
|
call to QueryAllocatedClusterCount will re-compute it.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
_AllocatedClusters = 0xFFFFFFFF;
|
|
return;
|
|
}
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::SetEntry(
|
|
IN ULONG ClusterNumber,
|
|
IN ULONG Value
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the FAT entry at ClusterNumber to Value.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the position in the FAT to update.
|
|
Value - Supplies the new value for that position.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
Set(ClusterNumber, Value);
|
|
}
|
|
|
|
|
|
INLINE
|
|
BOOLEAN
|
|
FAT::IsClusterFree(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine computes whether of not ClusterNumber is a free cluster.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the cluster to be checked.
|
|
|
|
Return Value:
|
|
|
|
FALSE - The cluster is not free.
|
|
TRUE - The cluster is free.
|
|
|
|
--*/
|
|
{
|
|
return Index(ClusterNumber) == 0;
|
|
}
|
|
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::SetClusterFree(
|
|
IN ULONG ClusterNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine marks the cluster ClusterNumber as free on the FAT.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the number of the cluster to mark free.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
Set(ClusterNumber, 0);
|
|
}
|
|
|
|
|
|
INLINE
|
|
BOOLEAN
|
|
FAT::IsEndOfChain(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine computes whether or not the cluster ClusterNumber is the
|
|
end of its cluster chain.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the cluster to be checked.
|
|
|
|
Return Value:
|
|
|
|
FALSE - The cluster is not the end of a chain.
|
|
TRUE - The cluster is the end of a chain.
|
|
|
|
--*/
|
|
{
|
|
return Index(ClusterNumber) >= _low_end_of_chain;
|
|
}
|
|
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::SetEndOfChain(
|
|
IN ULONG ClusterNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the cluster ClusterNumber to the end of its cluster
|
|
chain.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the cluster to be set to end of chain.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
Set(ClusterNumber, _end_of_chain);
|
|
}
|
|
|
|
|
|
INLINE
|
|
BOOLEAN
|
|
FAT::IsClusterBad(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine computes whether or not cluster ClusterNumber is bad.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the number of the cluster to be checked.
|
|
|
|
Return Value:
|
|
|
|
FALSE - The cluster is good.
|
|
TRUE - The cluster is bad.
|
|
|
|
--*/
|
|
{
|
|
return Index(ClusterNumber) == _bad_cluster;
|
|
}
|
|
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::SetClusterBad(
|
|
IN ULONG ClusterNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the cluster ClusterNumber to bad on the FAT.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the cluster number to mark bad.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
Set(ClusterNumber, _bad_cluster);
|
|
}
|
|
|
|
|
|
INLINE
|
|
BOOLEAN
|
|
FAT::IsClusterReserved(
|
|
IN ULONG ClusterNumber
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine computes whether or not the cluster ClusterNumber is
|
|
a reserved cluster.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the cluster to check.
|
|
|
|
Return Value:
|
|
|
|
FALSE - The cluster is not reserved.
|
|
TRUE - The cluster is reserved.
|
|
|
|
--*/
|
|
{
|
|
return Index(ClusterNumber) >= _low_reserved &&
|
|
Index(ClusterNumber) <= _high_reserved;
|
|
}
|
|
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::SetClusterReserved(
|
|
IN ULONG ClusterNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine marks the cluster ClusterNumber as reserved in the FAT.
|
|
|
|
Arguments:
|
|
|
|
ClusterNumber - Supplies the cluster to mark reserved.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
Set(ClusterNumber, _low_reserved);
|
|
}
|
|
|
|
|
|
INLINE
|
|
UCHAR
|
|
FAT::QueryMediaByte(
|
|
) CONST
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The media byte for the partition is stored in the first character of the
|
|
FAT. This routine will return its value provided that the two following
|
|
bytes are 0xFF.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The media byte for the partition.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR p;
|
|
|
|
p = (PUCHAR) _fat;
|
|
|
|
DebugAssert(p);
|
|
|
|
return (p[2] == 0xFF && p[1] == 0xFF && ((fFat12 != _fat_bits) ? (0x0F == (p[3] & 0x0F)) : TRUE)) ? p[0] : 0;
|
|
}
|
|
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::SetEarlyEntries(
|
|
IN UCHAR MediaByte
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the first two FAT entries as required by the
|
|
FAT file system. The first byte gets set to the media descriptor.
|
|
The remaining bytes gets set to FF.
|
|
|
|
Arguments:
|
|
|
|
MediaByte - Supplies the media byte for the volume.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR p;
|
|
|
|
p = (PUCHAR) _fat;
|
|
|
|
DebugAssert(p);
|
|
|
|
p[0] = MediaByte;
|
|
p[1] = p[2] = 0xFF;
|
|
|
|
if (fFat32 == _fat_bits) {
|
|
|
|
p[3] = 0x0F;
|
|
p[4] = 0xFF;
|
|
p[5] = 0xFF;
|
|
p[6] = 0xFF;
|
|
p[7] = 0x0F;
|
|
|
|
#if 0
|
|
// allocate cluster 2 for the root (set 2=end of chain)
|
|
p[8] = 0xFF;
|
|
p[9] = 0xFF;
|
|
p[10] = 0xFF;
|
|
p[11] = 0x0F;
|
|
#endif
|
|
} else if (fFat16 == _fat_bits) {
|
|
p[3] = 0xFF;
|
|
}
|
|
_AllocatedClusters = 0xFFFFFFFF;
|
|
}
|
|
|
|
|
|
INLINE
|
|
ULONG
|
|
FAT::RemoveChain(
|
|
IN ULONG PreceedingCluster,
|
|
IN ULONG LastCluster
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine removes a subchain of length 'Length' from a containing
|
|
chain. This routine cannot remove subchains beginning at the head
|
|
of the containing chain. To do this use the routine named
|
|
'SplitChain'.
|
|
|
|
This routine returns the number of the first cluster of the
|
|
removed subchain. The FAT is edited so that the removed subchain
|
|
is promoted to a full chain.
|
|
|
|
Arguments:
|
|
|
|
PreceedingCluster - Supplies the cluster which preceeds the one to be
|
|
removed in the chain.
|
|
LastCluster - Supplies the last cluster of the chain to remove.
|
|
|
|
Return Value:
|
|
|
|
The cluster number for the head of the chain removed.
|
|
|
|
--*/
|
|
{
|
|
ULONG r;
|
|
|
|
r = QueryEntry(PreceedingCluster);
|
|
SetEntry(PreceedingCluster, QueryEntry(LastCluster));
|
|
SetEndOfChain(LastCluster);
|
|
return r;
|
|
}
|
|
|
|
|
|
INLINE
|
|
VOID
|
|
FAT::InsertChain(
|
|
IN ULONG StartOfChain,
|
|
IN ULONG EndOfChain,
|
|
IN ULONG PreceedingCluster
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine inserts one chain into another chain. This routine
|
|
cannot insert a chain at the head of another chain. To do this
|
|
use the routine named 'JoinChains'.
|
|
|
|
Arguments:
|
|
|
|
StartOfChain - Supplies the first cluster of the chain to insert.
|
|
EndOfChain - Supplies the last cluster of the chain to insert.
|
|
PreceedingCluster - Supplies the cluster immediately preceeding the
|
|
position where the chain is to be inserted.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
SetEntry(EndOfChain, QueryEntry(PreceedingCluster));
|
|
SetEntry(PreceedingCluster, StartOfChain);
|
|
}
|
|
|
|
|
|
INLINE
|
|
ULONG
|
|
FAT::InsertChain(
|
|
IN ULONG StartOfChain,
|
|
IN ULONG Cluster
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine inserts one cluster at the head of a chain.
|
|
|
|
Arguments:
|
|
|
|
StartOfChain - Supplies the first cluster of the chain to insert.
|
|
Cluster - Supplies the cluster to be inserted
|
|
|
|
Return Value:
|
|
|
|
ULONG - The new head of the chain (i.e. Cluster )
|
|
|
|
--*/
|
|
{
|
|
if ( StartOfChain ) {
|
|
SetEntry( Cluster, StartOfChain );
|
|
} else {
|
|
SetEndOfChain( Cluster );
|
|
}
|
|
|
|
return Cluster;
|
|
}
|
|
|
|
|
|
#endif // FAT_DEFN
|