603 lines
12 KiB
C++
603 lines
12 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991-2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
ntfsbit.hxx
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains the declarations for NTFS_BITMAP,
|
|||
|
which models the bitmaps on an NTFS volume. There are three
|
|||
|
kinds of bitmaps on an NTFS volume:
|
|||
|
|
|||
|
(1) The Volume Bitmap, which is stored as the nameless $DATA
|
|||
|
attribute of the bitmap file. This bitmap has one bit for
|
|||
|
each cluster on the disk, and is of fixed size. It is unique.
|
|||
|
|
|||
|
(2) The MFT Bitmap, which is stored as the value of the nameless
|
|||
|
$BITMAP attribute of the Master File Table File. It has one
|
|||
|
bit per File Record Segment in the Master File Table, and grows
|
|||
|
with the Master File Table. It is unique.
|
|||
|
|
|||
|
(3) Index Allocation bitmaps. An index allocation bitmap is stored
|
|||
|
as the value of a $BITMAP attribute in a File Record Segment
|
|||
|
that has an $INDEX_ALLOCATION attribute. The name of the $BITMAP
|
|||
|
attribute agrees with the associated $INDEX_ALLOCATION attribute.
|
|||
|
This bitmap has one bit for each index allocation buffer in the
|
|||
|
associated $INDEX_ALLOCATION attribute, and grows with that
|
|||
|
attribute.
|
|||
|
|
|||
|
In every case, a set bit indicates that the associated allocation
|
|||
|
unit (cluster, File Record Segment, or Index Allocation Buffer) is
|
|||
|
allocated; a reset bit indicates that it is free.
|
|||
|
|
|||
|
The size of a bitmap (in bytes) is always quad-word aligned; bytes
|
|||
|
are added at the end of the bitmap to pad it to the correct size.
|
|||
|
If the bitmap is of fixed size, then all bits in the padding are
|
|||
|
set (allocated); if it is growable, the bits of the padding are
|
|||
|
reset (free).
|
|||
|
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Bill McJohn (billmc) 17-June-91
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
ULIB, User Mode
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#if !defined( _NTFS_BITMAP_DEFN_ )
|
|||
|
|
|||
|
#define _NTFS_BITMAP_DEFN_
|
|||
|
|
|||
|
#include "bitvect.hxx"
|
|||
|
#include "attrib.hxx"
|
|||
|
|
|||
|
DECLARE_CLASS( NTFS_ATTRIBUTE );
|
|||
|
DECLARE_CLASS( NTFS_BITMAP );
|
|||
|
DECLARE_CLASS( NTFS_MASTER_FILE_TABLE );
|
|||
|
|
|||
|
class NTFS_BITMAP : public OBJECT {
|
|||
|
|
|||
|
public:
|
|||
|
|
|||
|
UNTFS_EXPORT
|
|||
|
DECLARE_CONSTRUCTOR( NTFS_BITMAP );
|
|||
|
|
|||
|
VIRTUAL
|
|||
|
UNTFS_EXPORT
|
|||
|
~NTFS_BITMAP(
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
UNTFS_EXPORT
|
|||
|
BOOLEAN
|
|||
|
Initialize(
|
|||
|
IN BIG_INT NumberOfClusters,
|
|||
|
IN BOOLEAN IsGrowable,
|
|||
|
IN PLOG_IO_DP_DRIVE Drive DEFAULT NULL,
|
|||
|
IN ULONG ClusterFactor DEFAULT 0
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
Create(
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BIG_INT
|
|||
|
QuerySize(
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
SetFree(
|
|||
|
IN LCN Lcn,
|
|||
|
IN BIG_INT NumberOfClusters
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
SetAllocated(
|
|||
|
IN LCN Lcn,
|
|||
|
IN BIG_INT NumberOfClusters
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
SetNextAlloc(
|
|||
|
IN LCN Lcn
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BIG_INT
|
|||
|
QueryFreeClusters(
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BIG_INT
|
|||
|
QueryFreeBlockSize(
|
|||
|
IN LCN Lcn
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
UNTFS_EXPORT
|
|||
|
BOOLEAN
|
|||
|
IsFree(
|
|||
|
IN LCN Lcn,
|
|||
|
IN BIG_INT RunLength
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
UNTFS_EXPORT
|
|||
|
BOOLEAN
|
|||
|
IsAllocated(
|
|||
|
IN LCN Lcn,
|
|||
|
IN BIG_INT RunLength
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
IsInRange(
|
|||
|
IN LCN Lcn,
|
|||
|
IN BIG_INT RunLength
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
AllocateClusters(
|
|||
|
IN LCN NearHere OPTIONAL,
|
|||
|
IN BIG_INT NumberOfClusters,
|
|||
|
OUT PLCN FirstAllocatedLcn,
|
|||
|
IN ULONG AlignmentFactor DEFAULT 1
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
Read(
|
|||
|
IN OUT PNTFS_ATTRIBUTE BitmapAttribute
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
UNTFS_EXPORT
|
|||
|
BOOLEAN
|
|||
|
Write(
|
|||
|
IN OUT PNTFS_ATTRIBUTE BitmapAttribute,
|
|||
|
IN OUT PNTFS_BITMAP VolumeBitmap OPTIONAL
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
CheckAttributeSize(
|
|||
|
IN OUT PNTFS_ATTRIBUTE BitmapAttribute,
|
|||
|
IN OUT PNTFS_BITMAP VolumeBitmap
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
BOOLEAN
|
|||
|
Resize(
|
|||
|
IN BIG_INT NumberOfClusters
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
PCVOID
|
|||
|
GetBitmapData(
|
|||
|
OUT PULONG SizeInBytes
|
|||
|
) CONST;
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
SetMftPointer(
|
|||
|
IN PNTFS_MASTER_FILE_TABLE Mft
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
SetGrowable(
|
|||
|
IN BOOLEAN Growable
|
|||
|
);
|
|||
|
|
|||
|
private:
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
Construct (
|
|||
|
);
|
|||
|
|
|||
|
NONVIRTUAL
|
|||
|
VOID
|
|||
|
Destroy(
|
|||
|
);
|
|||
|
|
|||
|
BIG_INT _NumberOfClusters;
|
|||
|
BOOLEAN _IsGrowable;
|
|||
|
|
|||
|
ULONG _BitmapSize;
|
|||
|
PVOID _BitmapData;
|
|||
|
BIG_INT _NextAlloc;
|
|||
|
BITVECTOR _Bitmap;
|
|||
|
|
|||
|
//
|
|||
|
// This is to support testing newly-allocated clusters in the
|
|||
|
// volume bitmap to ensure they can support IO.
|
|||
|
//
|
|||
|
|
|||
|
PLOG_IO_DP_DRIVE _Drive;
|
|||
|
ULONG _ClusterFactor;
|
|||
|
PNTFS_MASTER_FILE_TABLE _Mft;
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
BIG_INT
|
|||
|
NTFS_BITMAP::QuerySize(
|
|||
|
) CONST
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method returns the number of clusters covered by this bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The number of clusters covered by this bitmap.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return _NumberOfClusters;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
NTFS_BITMAP::SetFree(
|
|||
|
IN LCN Lcn,
|
|||
|
IN BIG_INT RunLength
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method marks a run of clusters as free in the bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Lcn -- supplies the LCN of the first cluster in the run
|
|||
|
RunLength -- supplies the length of the run
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
This method performs range checking.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
// Since the high part of _NumberOfClusters is zero, if
|
|||
|
// Lcn and RunLength pass the range-checking, their high
|
|||
|
// parts must also be zero.
|
|||
|
|
|||
|
if( !(Lcn < 0) &&
|
|||
|
!(RunLength < 0 ) &&
|
|||
|
!(Lcn + RunLength > _NumberOfClusters) ) {
|
|||
|
|
|||
|
_Bitmap.ResetBit( Lcn.GetLowPart(), RunLength.GetLowPart() ) ;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
NTFS_BITMAP::SetAllocated(
|
|||
|
IN LCN Lcn,
|
|||
|
IN BIG_INT RunLength
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method marks a run of clusters as used in the bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Lcn -- supplies the LCN of the first cluster in the run
|
|||
|
RunLength -- supplies the length of the run
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
This method performs range checking.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
// Since the high part of _NumberOfClusters is zero, if
|
|||
|
// Lcn and RunLength pass the range-checking, their high
|
|||
|
// parts must also be zero.
|
|||
|
|
|||
|
if( !(Lcn < 0) &&
|
|||
|
!(Lcn + RunLength > _NumberOfClusters) ) {
|
|||
|
|
|||
|
_Bitmap.SetBit( Lcn.GetLowPart(), RunLength.GetLowPart() );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
NTFS_BITMAP::SetNextAlloc(
|
|||
|
IN LCN Lcn
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method sets the next allocation location from the bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Lcn -- supplies the LCN of the first cluster to allocate
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
This method performs range checking.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if( !(Lcn < 0) &&
|
|||
|
!(Lcn > _NumberOfClusters) ) {
|
|||
|
|
|||
|
_NextAlloc = Lcn;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
BIG_INT
|
|||
|
NTFS_BITMAP::QueryFreeClusters(
|
|||
|
) CONST
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method returns the number of free clusters in the bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The number of free clusters in the bitmap.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BIG_INT result;
|
|||
|
|
|||
|
if( _IsGrowable ) {
|
|||
|
|
|||
|
// The bits in the padding are marked as free (ie. are
|
|||
|
// not set). Thus, we can just count the number of set
|
|||
|
// bits and subtract that from the number of clusters.
|
|||
|
//
|
|||
|
result = _NumberOfClusters - ((PNTFS_BITMAP) this)->_Bitmap.QueryCountSet();
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
// The bits in the padding are marked as in-use (ie.
|
|||
|
// are set), so we need to compensate for them when
|
|||
|
// we count the number of bits that are set.
|
|||
|
//
|
|||
|
result = _BitmapSize*8 - ((PNTFS_BITMAP) this)->_Bitmap.QueryCountSet();
|
|||
|
}
|
|||
|
|
|||
|
return result;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
NTFS_BITMAP::Create(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method sets up an NTFS_BITMAP object in memory. Note that
|
|||
|
it does not write the bitmap to disk.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE upon successful completion.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
The newly-created bitmap begins with all clusters marked as FREE.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
SetFree( 0, _NumberOfClusters );
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
NTFS_BITMAP::IsInRange(
|
|||
|
IN LCN Lcn,
|
|||
|
IN BIG_INT RunLength
|
|||
|
) CONST
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine computes whether or not the given range of clusters is
|
|||
|
in the range allowed by this bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Lcn - Supplies the first cluster in the range.
|
|||
|
RunLength - Supplies the number of clusters in the range.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
FALSE - The specified range of clusters is not within the range of
|
|||
|
the bitmap.
|
|||
|
TRUE - The specified range of clusters is within the range of
|
|||
|
the bitmap.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return (BOOLEAN) ((Lcn >= 0) &&
|
|||
|
(RunLength >= 0 ) &&
|
|||
|
(Lcn + RunLength <= _NumberOfClusters));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
NTFS_BITMAP::Read(
|
|||
|
PNTFS_ATTRIBUTE BitmapAttribute
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method reads the bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BitmapAttribute -- supplies the attribute which describes the
|
|||
|
bitmap's location on disk.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE upon successful completion.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG BytesRead;
|
|||
|
|
|||
|
DebugPtrAssert( _BitmapData );
|
|||
|
|
|||
|
return( BitmapAttribute->Read( _BitmapData,
|
|||
|
0,
|
|||
|
_BitmapSize,
|
|||
|
&BytesRead ) &&
|
|||
|
|
|||
|
BytesRead == _BitmapSize );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
BOOLEAN
|
|||
|
NTFS_BITMAP::CheckAttributeSize(
|
|||
|
IN OUT PNTFS_ATTRIBUTE BitmapAttribute,
|
|||
|
IN OUT PNTFS_BITMAP VolumeBitmap
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This method ensures that the allocated size of the attribute is
|
|||
|
big enough to hold the bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BitmapAttribute -- Supplies the attribute which describes the
|
|||
|
bitmap's location on disk.
|
|||
|
VolumeBitmap -- Supplies the volume bitmap.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE upon successful completion.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DebugAssert( BitmapAttribute != NULL );
|
|||
|
|
|||
|
return( BitmapAttribute->QueryValueLength() == _BitmapSize ||
|
|||
|
BitmapAttribute->Resize( _BitmapSize, VolumeBitmap ) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
INLINE
|
|||
|
PCVOID
|
|||
|
NTFS_BITMAP::GetBitmapData(
|
|||
|
OUT PULONG SizeInBytes
|
|||
|
) CONST
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine returns a pointer to the in memory bitmap contained by
|
|||
|
this class. It also return the size in bytes of the bitmap.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
SizeInBytes - Returns the size of the bitmap.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
The bitmap contained by this class.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
*SizeInBytes = _BitmapSize;
|
|||
|
return _BitmapData;
|
|||
|
}
|
|||
|
|
|||
|
INLINE
|
|||
|
VOID
|
|||
|
NTFS_BITMAP::SetMftPointer(
|
|||
|
IN PNTFS_MASTER_FILE_TABLE Mft
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine set the _Mft member in the NTFS_BITMAP so that
|
|||
|
subsequent calls to AllocateClusters will be able to add any
|
|||
|
bad clusters found to the bad cluster file.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Mft - pointer to the volume's mft.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
_Mft = Mft;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#endif // _NTFS_BITMAP_DEFN_
|