Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

904 lines
16 KiB

/*++
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 FirstDiskCluster = 2;
CONST MaxNumClusForSmallFat = 4085;
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 USHORT NumberOfEntries,
IN USHORT NumSectors DEFAULT 0
);
NONVIRTUAL
USHORT
QueryEntry(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
VOID
SetEntry(
IN USHORT ClusterNumber,
IN USHORT Value
);
NONVIRTUAL
BOOLEAN
IsInRange(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
BOOLEAN
IsClusterFree(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
VOID
SetClusterFree(
IN USHORT ClusterNumber
);
NONVIRTUAL
BOOLEAN
IsEndOfChain(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
VOID
SetEndOfChain(
IN USHORT ClusterNumber
);
NONVIRTUAL
BOOLEAN
IsClusterBad(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
VOID
SetClusterBad(
IN USHORT ClusterNumber
);
NONVIRTUAL
BOOLEAN
IsClusterReserved(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
VOID
SetClusterReserved(
IN USHORT ClusterNumber
);
NONVIRTUAL
VOID
SetEarlyEntries(
IN UCHAR MediaByte
);
NONVIRTUAL
UCHAR
QueryMediaByte(
) CONST;
NONVIRTUAL
USHORT
QueryFreeClusters(
) CONST;
NONVIRTUAL
USHORT
QueryBadClusters(
) CONST;
NONVIRTUAL
USHORT
QueryReservedClusters(
) CONST;
NONVIRTUAL
UFAT_EXPORT
USHORT
QueryAllocatedClusters(
) CONST;
NONVIRTUAL
UFAT_EXPORT
USHORT
QueryNthCluster(
IN USHORT StartingCluster,
IN USHORT Index
) CONST;
NONVIRTUAL
UFAT_EXPORT
USHORT
QueryLengthOfChain(
IN USHORT StartingCluster,
OUT PUSHORT LastCluster DEFAULT NULL
) CONST;
NONVIRTUAL
USHORT
QueryLengthOfChain(
IN USHORT StartingCluster,
IN USHORT EndingCluster
) CONST;
NONVIRTUAL
USHORT
QueryPrevious(
IN USHORT Cluster
) CONST;
NONVIRTUAL
VOID
Scrub(
OUT PBOOLEAN ChangesMade DEFAULT NULL
);
NONVIRTUAL
VOID
ScrubChain(
IN USHORT StartingCluster,
OUT PBOOLEAN ChangesMade
);
NONVIRTUAL
VOID
ScrubChain(
IN USHORT StartingCluster,
OUT PBITVECTOR UsedClusters,
OUT PBOOLEAN ChangesMade,
OUT PBOOLEAN CrossLinkDetected,
OUT PUSHORT CrossLinkPreviousCluster
);
NONVIRTUAL
BOOLEAN
IsValidChain(
IN USHORT StartingCluster
) CONST;
NONVIRTUAL
UFAT_EXPORT
USHORT
AllocChain(
IN USHORT Length,
OUT PUSHORT LastCluster DEFAULT NULL
);
NONVIRTUAL
USHORT
ReAllocChain(
IN USHORT StartOfChain,
IN USHORT NewLength,
OUT PUSHORT LastCluster DEFAULT NULL
);
NONVIRTUAL
UFAT_EXPORT
VOID
FreeChain(
IN USHORT StartOfChain
);
NONVIRTUAL
USHORT
RemoveChain(
IN USHORT PreceedingCluster,
IN USHORT LastCluster
);
NONVIRTUAL
VOID
InsertChain(
IN USHORT StartOfChain,
IN USHORT EndOfChain,
IN USHORT PreceedingCluster
);
NONVIRTUAL
USHORT
InsertChain(
IN USHORT StartOfChain,
IN USHORT Cluster
);
private:
NONVIRTUAL
VOID
Construct(
);
NONVIRTUAL
VOID
Destroy(
);
NONVIRTUAL
USHORT
Index(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
UFAT_EXPORT
USHORT
Index12(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
USHORT
Index16(
IN USHORT ClusterNumber
) CONST;
NONVIRTUAL
VOID
Set(
IN USHORT ClusterNumber,
IN USHORT Value
);
NONVIRTUAL
UFAT_EXPORT
VOID
Set12(
IN USHORT ClusterNumber,
IN USHORT Value
);
NONVIRTUAL
VOID
Set16(
IN USHORT ClusterNumber,
IN USHORT Value
);
PVOID _fat;
USHORT _num_entries;
BOOLEAN _is_big;
USHORT _low_end_of_chain; // 0xFFF8 or 0x0FF8
USHORT _end_of_chain; // 0xFFFF or 0x0FFF
USHORT _bad_cluster; // 0xFFF7 or 0x0FF7
USHORT _low_reserved; // 0xFFF0 or 0x0FF0
USHORT _high_reserved; // 0xFFF6 or 0x0FF6
};
INLINE
BOOLEAN
FAT::IsInRange(
IN USHORT 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
USHORT
FAT::Index16(
IN USHORT 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 ((PUSHORT) _fat)[ClusterNumber];
}
INLINE
USHORT
FAT::Index(
IN USHORT 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.
--*/
{
return _is_big ? Index16(ClusterNumber) : Index12(ClusterNumber);
}
INLINE
VOID
FAT::Set16(
IN USHORT ClusterNumber,
IN USHORT 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] = Value;
}
INLINE
VOID
FAT::Set(
IN USHORT ClusterNumber,
IN USHORT 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.
--*/
{
_is_big ? Set16(ClusterNumber, Value) : Set12(ClusterNumber, Value);
}
INLINE
USHORT
FAT::QueryEntry(
IN USHORT 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
VOID
FAT::SetEntry(
IN USHORT ClusterNumber,
IN USHORT 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 USHORT 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 USHORT 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 USHORT 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 USHORT 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 USHORT 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 USHORT 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 USHORT 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 USHORT 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 &&
(_is_big ? p[3] == 0xFF : 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 (_is_big) {
p[3] = 0xFF;
}
}
INLINE
USHORT
FAT::RemoveChain(
IN USHORT PreceedingCluster,
IN USHORT 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.
--*/
{
USHORT r;
r = QueryEntry(PreceedingCluster);
SetEntry(PreceedingCluster, QueryEntry(LastCluster));
SetEndOfChain(LastCluster);
return r;
}
INLINE
VOID
FAT::InsertChain(
IN USHORT StartOfChain,
IN USHORT EndOfChain,
IN USHORT 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
USHORT
FAT::InsertChain(
IN USHORT StartOfChain,
IN USHORT 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:
USHORT - The new head of the chain (i.e. Cluster )
--*/
{
if ( StartOfChain ) {
SetEntry( Cluster, StartOfChain );
} else {
SetEndOfChain( Cluster );
}
return Cluster;
}
#endif // FAT_DEFN