* PROJECT: ReactOS system libraries
* LICENSE: GNU GPL - See COPYING in the top level directory
* BSD - See COPYING.ARM in the top level directory
* FILE: lib/rtl/bitmap.c
* PURPOSE: Bitmap functions
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
#include <rtl.h>
#define NDEBUG
#include <debug.h>
#undef ASSERT
#define ASSERT(...)
#ifdef USE_RTL_BITMAP64
#define _BITCOUNT 64
#define MAXINDEX 0xFFFFFFFFFFFFFFFF
typedef ULONG64 BITMAP_INDEX, *PBITMAP_INDEX;
typedef ULONG64 BITMAP_BUFFER, *PBITMAP_BUFFER;
#define RTL_BITMAP RTL_BITMAP64
#define PRTL_BITMAP PRTL_BITMAP64
#define RTL_BITMAP_RUN RTL_BITMAP_RUN64
#define PRTL_BITMAP_RUN PRTL_BITMAP_RUN64
#undef BitScanForward
#define BitScanForward(Index, Mask) \
do { unsigned long tmp; BitScanForward64(&tmp, Mask); *Index = tmp; } while (0)
#undef BitScanReverse
#define BitScanReverse(Index, Mask) \
do { unsigned long tmp; BitScanReverse64(&tmp, Mask); *Index = tmp; } while (0)
#define RtlFillMemoryUlong RtlFillMemoryUlonglong
#define RtlInitializeBitMap RtlInitializeBitMap64
#define RtlClearAllBits RtlClearAllBits64
#define RtlSetAllBits RtlSetAllBits64
#define RtlClearBit RtlClearBit64
#define RtlSetBit RtlSetBit64
#define RtlClearBits RtlClearBits64
#define RtlSetBits RtlSetBits64
#define RtlTestBit RtlTestBit64
#define RtlAreBitsClear RtlAreBitsClear64
#define RtlAreBitsSet RtlAreBitsSet64
#define RtlNumberOfSetBits RtlNumberOfSetBits64
#define RtlNumberOfClearBits RtlNumberOfClearBits64
#define RtlFindClearBits RtlFindClearBits64
#define RtlFindSetBits RtlFindSetBits64
#define RtlFindClearBitsAndSet RtlFindClearBitsAndSet64
#define RtlFindSetBitsAndClear RtlFindSetBitsAndClear64
#define RtlFindNextForwardRunClear RtlFindNextForwardRunClear64
#define RtlFindNextForwardRunSet RtlFindNextForwardRunSet64
#define RtlFindFirstRunClear RtlFindFirstRunClear64
#define RtlFindLastBackwardRunClear RtlFindLastBackwardRunClear64
#define RtlFindClearRuns RtlFindClearRuns64
#define RtlFindLongestRunClear RtlFindLongestRunClear64
#define RtlFindLongestRunSet RtlFindLongestRunSet64
#else
#define _BITCOUNT 32
#define MAXINDEX 0xFFFFFFFF
typedef ULONG BITMAP_INDEX, *PBITMAP_INDEX;
typedef ULONG BITMAP_BUFFER, *PBITMAP_BUFFER;
#endif
static const
UCHAR
BitCountTable[256] =
{
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};
static __inline
BITMAP_INDEX
RtlpGetLengthOfRunClear(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX StartingIndex,
_In_ BITMAP_INDEX MaxLength)
{
BITMAP_INDEX Value, BitPos, Length;
PBITMAP_BUFFER Buffer, MaxBuffer;
ASSERT(StartingIndex <= BitMapHeader->SizeOfBitMap);
if (StartingIndex >= BitMapHeader->SizeOfBitMap)
return 0;
Buffer = BitMapHeader->Buffer + StartingIndex / _BITCOUNT;
BitPos = StartingIndex & (_BITCOUNT - 1);
MaxLength = min(MaxLength, BitMapHeader->SizeOfBitMap - StartingIndex);
MaxBuffer = Buffer + (BitPos + MaxLength + _BITCOUNT - 1) / _BITCOUNT;
Value = *Buffer++ >> BitPos << BitPos;
while (Value == 0 && Buffer < MaxBuffer)
{
Value = *Buffer++;
}
if (Value == 0)
{
return MaxLength;
}
BitScanForward(&BitPos, Value);
Length = (BITMAP_INDEX)(Buffer - BitMapHeader->Buffer) * _BITCOUNT - StartingIndex;
Length += BitPos - _BITCOUNT;
if (Length > BitMapHeader->SizeOfBitMap - StartingIndex)
Length = BitMapHeader->SizeOfBitMap - StartingIndex;
return Length;
}
static __inline
BITMAP_INDEX
RtlpGetLengthOfRunSet(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX StartingIndex,
_In_ BITMAP_INDEX MaxLength)
{
BITMAP_INDEX InvValue, BitPos, Length;
PBITMAP_BUFFER Buffer, MaxBuffer;
ASSERT(StartingIndex <= BitMapHeader->SizeOfBitMap);
if (StartingIndex >= BitMapHeader->SizeOfBitMap)
return 0;
Buffer = BitMapHeader->Buffer + StartingIndex / _BITCOUNT;
BitPos = StartingIndex & (_BITCOUNT - 1);
MaxLength = min(MaxLength, BitMapHeader->SizeOfBitMap - StartingIndex);
MaxBuffer = Buffer + (BitPos + MaxLength + _BITCOUNT - 1) / _BITCOUNT;
InvValue = ~(*Buffer++) >> BitPos << BitPos;
while (InvValue == 0 && Buffer < MaxBuffer)
{
InvValue = ~(*Buffer++);
}
if (InvValue == 0)
{
return MaxLength;
}
BitScanForward(&BitPos, InvValue);
Length = (ULONG)(Buffer - BitMapHeader->Buffer) * _BITCOUNT - StartingIndex;
Length += BitPos - _BITCOUNT;
if (Length > BitMapHeader->SizeOfBitMap - StartingIndex)
Length = BitMapHeader->SizeOfBitMap - StartingIndex;
return Length;
}
#ifndef USE_RTL_BITMAP64
CCHAR
NTAPI
RtlFindMostSignificantBit(ULONGLONG Value)
{
ULONG Position;
#ifdef _M_AMD64
if (BitScanReverse64(&Position, Value))
{
return (CCHAR)Position;
}
#else
if (BitScanReverse(&Position, Value >> _BITCOUNT))
{
return (CCHAR)(Position + _BITCOUNT);
}
else if (BitScanReverse(&Position, (ULONG)Value))
{
return (CCHAR)Position;
}
#endif
return -1;
}
CCHAR
NTAPI
RtlFindLeastSignificantBit(ULONGLONG Value)
{
ULONG Position;
#ifdef _M_AMD64
if (BitScanForward64(&Position, Value))
{
return (CCHAR)Position;
}
#else
if (BitScanForward(&Position, (ULONG)Value))
{
return (CCHAR)Position;
}
else if (BitScanForward(&Position, Value >> _BITCOUNT))
{
return (CCHAR)(Position + _BITCOUNT);
}
#endif
return -1;
}
#endif
VOID
NTAPI
RtlInitializeBitMap(
_Out_ PRTL_BITMAP BitMapHeader,
_In_opt_ __drv_aliasesMem PBITMAP_BUFFER BitMapBuffer,
_In_opt_ ULONG SizeOfBitMap)
{
BitMapHeader->SizeOfBitMap = SizeOfBitMap;
BitMapHeader->Buffer = BitMapBuffer;
}
VOID
NTAPI
RtlClearAllBits(
_In_ PRTL_BITMAP BitMapHeader)
{
BITMAP_INDEX LengthInUlongs;
LengthInUlongs = (BitMapHeader->SizeOfBitMap + _BITCOUNT - 1) / _BITCOUNT;
RtlFillMemoryUlong(BitMapHeader->Buffer, LengthInUlongs * sizeof(BITMAP_INDEX), 0);
}
VOID
NTAPI
RtlSetAllBits(
_In_ PRTL_BITMAP BitMapHeader)
{
BITMAP_INDEX LengthInUlongs;
LengthInUlongs = (BitMapHeader->SizeOfBitMap + _BITCOUNT - 1) / _BITCOUNT;
RtlFillMemoryUlong(BitMapHeader->Buffer, LengthInUlongs * sizeof(BITMAP_INDEX), ~0);
}
VOID
NTAPI
RtlClearBit(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX BitNumber)
{
ASSERT(BitNumber <= BitMapHeader->SizeOfBitMap);
BitMapHeader->Buffer[BitNumber / _BITCOUNT] &= ~(1 << (BitNumber & (_BITCOUNT - 1)));
}
VOID
NTAPI
RtlSetBit(
_In_ PRTL_BITMAP BitMapHeader,
_In_range_(<, BitMapHeader->SizeOfBitMap) BITMAP_INDEX BitNumber)
{
ASSERT(BitNumber <= BitMapHeader->SizeOfBitMap);
BitMapHeader->Buffer[BitNumber / _BITCOUNT] |= ((BITMAP_INDEX)1 << (BitNumber & (_BITCOUNT - 1)));
}
VOID
NTAPI
RtlClearBits(
_In_ PRTL_BITMAP BitMapHeader,
_In_range_(0, BitMapHeader->SizeOfBitMap - NumberToClear) BITMAP_INDEX StartingIndex,
_In_range_(0, BitMapHeader->SizeOfBitMap - StartingIndex) BITMAP_INDEX NumberToClear)
{
BITMAP_INDEX Bits, Mask;
PBITMAP_BUFFER Buffer;
ASSERT(StartingIndex + NumberToClear <= BitMapHeader->SizeOfBitMap);
Buffer = &BitMapHeader->Buffer[StartingIndex / _BITCOUNT];
Bits = StartingIndex & (_BITCOUNT - 1);
if (Bits)
{
Mask = MAXINDEX << Bits;
Bits = _BITCOUNT - Bits;
if (NumberToClear < Bits)
{
Bits -= NumberToClear;
Mask = Mask << Bits >> Bits;
*Buffer &= ~Mask;
return;
}
*Buffer &= ~Mask;
Buffer++;
NumberToClear -= Bits;
}
RtlFillMemoryUlong(Buffer, NumberToClear >> 3, 0);
Buffer += NumberToClear / _BITCOUNT;
NumberToClear &= (_BITCOUNT - 1);
if (NumberToClear != 0)
{
Mask = MAXINDEX << NumberToClear;
*Buffer &= Mask;
}
}
VOID
NTAPI
RtlSetBits(
_In_ PRTL_BITMAP BitMapHeader,
_In_range_(0, BitMapHeader->SizeOfBitMap - NumberToSet) BITMAP_INDEX StartingIndex,
_In_range_(0, BitMapHeader->SizeOfBitMap - StartingIndex) BITMAP_INDEX NumberToSet)
{
BITMAP_INDEX Bits, Mask;
PBITMAP_BUFFER Buffer;
ASSERT(StartingIndex + NumberToSet <= BitMapHeader->SizeOfBitMap);
Buffer = &BitMapHeader->Buffer[StartingIndex / _BITCOUNT];
Bits = StartingIndex & (_BITCOUNT - 1);
if (Bits)
{
Mask = MAXINDEX << Bits;
Bits = _BITCOUNT - Bits;
if (NumberToSet < Bits)
{
Bits -= NumberToSet;
Mask = Mask << Bits >> Bits;
*Buffer |= Mask;
return;
}
*Buffer |= Mask;
Buffer++;
NumberToSet -= Bits;
}
RtlFillMemoryUlong(Buffer, NumberToSet >> 3, MAXINDEX);
Buffer += NumberToSet / _BITCOUNT;
NumberToSet &= (_BITCOUNT - 1);
if (NumberToSet != 0)
{
Mask = MAXINDEX << NumberToSet;
*Buffer |= ~Mask;
}
}
BOOLEAN
NTAPI
RtlTestBit(
_In_ PRTL_BITMAP BitMapHeader,
_In_range_(<, BitMapHeader->SizeOfBitMap) BITMAP_INDEX BitNumber)
{
ASSERT(BitNumber < BitMapHeader->SizeOfBitMap);
return (BitMapHeader->Buffer[BitNumber / _BITCOUNT] >> (BitNumber & (_BITCOUNT - 1))) & 1;
}
BOOLEAN
NTAPI
RtlAreBitsClear(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX StartingIndex,
_In_ BITMAP_INDEX Length)
{
if ((StartingIndex + Length > BitMapHeader->SizeOfBitMap) ||
(StartingIndex + Length <= StartingIndex))
return FALSE;
return RtlpGetLengthOfRunClear(BitMapHeader, StartingIndex, Length) >= Length;
}
BOOLEAN
NTAPI
RtlAreBitsSet(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX StartingIndex,
_In_ BITMAP_INDEX Length)
{
if ((StartingIndex + Length > BitMapHeader->SizeOfBitMap) ||
(StartingIndex + Length <= StartingIndex))
return FALSE;
return RtlpGetLengthOfRunSet(BitMapHeader, StartingIndex, Length) >= Length;
}
BITMAP_INDEX
NTAPI
RtlNumberOfSetBits(
_In_ PRTL_BITMAP BitMapHeader)
{
PUCHAR Byte, MaxByte;
BITMAP_INDEX BitCount = 0;
ULONG Shift;
Byte = (PUCHAR)BitMapHeader->Buffer;
MaxByte = Byte + BitMapHeader->SizeOfBitMap / 8;
while (Byte < MaxByte)
{
BitCount += BitCountTable[*Byte++];
}
if (BitMapHeader->SizeOfBitMap & 7)
{
Shift = 8 - (BitMapHeader->SizeOfBitMap & 7);
BitCount += BitCountTable[((*Byte) << Shift) & 0xFF];
}
return BitCount;
}
BITMAP_INDEX
NTAPI
RtlNumberOfClearBits(
_In_ PRTL_BITMAP BitMapHeader)
{
return BitMapHeader->SizeOfBitMap - RtlNumberOfSetBits(BitMapHeader);
}
BITMAP_INDEX
NTAPI
RtlFindClearBits(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX NumberToFind,
_In_ BITMAP_INDEX HintIndex)
{
BITMAP_INDEX CurrentBit, Margin, CurrentLength;
if (!BitMapHeader || NumberToFind > BitMapHeader->SizeOfBitMap)
{
return MAXINDEX;
}
if (HintIndex >= BitMapHeader->SizeOfBitMap) HintIndex = 0;
if (NumberToFind == 0)
{
return HintIndex & ~7;
}
Margin = BitMapHeader->SizeOfBitMap;
retry:
CurrentBit = HintIndex;
while (CurrentBit + NumberToFind < Margin)
{
CurrentBit += RtlpGetLengthOfRunSet(BitMapHeader,
CurrentBit,
MAXINDEX);
CurrentLength = RtlpGetLengthOfRunClear(BitMapHeader,
CurrentBit,
NumberToFind);
if (CurrentLength >= NumberToFind)
{
return CurrentBit;
}
CurrentBit += CurrentLength;
}
if (HintIndex)
{
Margin = min(HintIndex + NumberToFind, BitMapHeader->SizeOfBitMap);
HintIndex = 0;
goto retry;
}
return MAXINDEX;
}
BITMAP_INDEX
NTAPI
RtlFindSetBits(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX NumberToFind,
_In_ BITMAP_INDEX HintIndex)
{
BITMAP_INDEX CurrentBit, Margin, CurrentLength;
if (!BitMapHeader || NumberToFind > BitMapHeader->SizeOfBitMap)
{
return MAXINDEX;
}
if (HintIndex >= BitMapHeader->SizeOfBitMap) HintIndex = 0;
if (NumberToFind == 0)
{
return HintIndex & ~7;
}
Margin = BitMapHeader->SizeOfBitMap;
retry:
CurrentBit = HintIndex;
while (CurrentBit + NumberToFind <= Margin)
{
CurrentBit += RtlpGetLengthOfRunClear(BitMapHeader,
CurrentBit,
MAXINDEX);
CurrentLength = RtlpGetLengthOfRunSet(BitMapHeader,
CurrentBit,
NumberToFind);
if (CurrentLength >= NumberToFind)
{
return CurrentBit;
}
CurrentBit += CurrentLength;
}
if (HintIndex)
{
Margin = min(HintIndex + NumberToFind, BitMapHeader->SizeOfBitMap);
HintIndex = 0;
goto retry;
}
return MAXINDEX;
}
BITMAP_INDEX
NTAPI
RtlFindClearBitsAndSet(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX NumberToFind,
_In_ BITMAP_INDEX HintIndex)
{
BITMAP_INDEX Position;
Position = RtlFindClearBits(BitMapHeader, NumberToFind, HintIndex);
if (Position != MAXINDEX)
{
RtlSetBits(BitMapHeader, Position, NumberToFind);
}
return Position;
}
BITMAP_INDEX
NTAPI
RtlFindSetBitsAndClear(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX NumberToFind,
_In_ BITMAP_INDEX HintIndex)
{
BITMAP_INDEX Position;
Position = RtlFindSetBits(BitMapHeader, NumberToFind, HintIndex);
if (Position != MAXINDEX)
{
RtlClearBits(BitMapHeader, Position, NumberToFind);
}
return Position;
}
BITMAP_INDEX
NTAPI
RtlFindNextForwardRunClear(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX FromIndex,
_Out_ PBITMAP_INDEX StartingRunIndex)
{
BITMAP_INDEX Length;
if (FromIndex >= BitMapHeader->SizeOfBitMap)
{
*StartingRunIndex = FromIndex;
return 0;
}
Length = RtlpGetLengthOfRunSet(BitMapHeader, FromIndex, MAXINDEX);
*StartingRunIndex = FromIndex + Length;
return RtlpGetLengthOfRunClear(BitMapHeader, FromIndex + Length, MAXINDEX);
}
BITMAP_INDEX
NTAPI
RtlFindNextForwardRunSet(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX FromIndex,
_Out_ PBITMAP_INDEX StartingRunIndex)
{
BITMAP_INDEX Length;
if (FromIndex >= BitMapHeader->SizeOfBitMap)
{
*StartingRunIndex = FromIndex;
return 0;
}
Length = RtlpGetLengthOfRunClear(BitMapHeader, FromIndex, MAXINDEX);
*StartingRunIndex = FromIndex + Length;
return RtlpGetLengthOfRunSet(BitMapHeader, FromIndex + Length, MAXINDEX);
}
BITMAP_INDEX
NTAPI
RtlFindFirstRunClear(
_In_ PRTL_BITMAP BitMapHeader,
_Out_ PBITMAP_INDEX StartingIndex)
{
return RtlFindNextForwardRunClear(BitMapHeader, 0, StartingIndex);
}
BITMAP_INDEX
NTAPI
RtlFindLastBackwardRunClear(
_In_ PRTL_BITMAP BitMapHeader,
_In_ BITMAP_INDEX FromIndex,
_Out_ PBITMAP_INDEX StartingRunIndex)
{
BITMAP_INDEX Value, InvValue, BitPos;
PBITMAP_BUFFER Buffer;
FromIndex = min(FromIndex, BitMapHeader->SizeOfBitMap - 1);
Buffer = BitMapHeader->Buffer + FromIndex / _BITCOUNT;
BitPos = (_BITCOUNT - 1) - (FromIndex & (_BITCOUNT - 1));
InvValue = ~(*Buffer--) << BitPos >> BitPos;
while (InvValue == 0)
{
if (Buffer < BitMapHeader->Buffer)
{
return 0;
}
InvValue = ~(*Buffer--);
}
BitScanReverse(&BitPos, InvValue);
FromIndex = (BITMAP_INDEX)((Buffer + 1 - BitMapHeader->Buffer) * _BITCOUNT + BitPos);
Value = ~InvValue << ((_BITCOUNT - 1) - BitPos) >> ((_BITCOUNT - 1) - BitPos);
while (Value == 0 && Buffer >= BitMapHeader->Buffer)
{
Value = *Buffer--;
}
if (Value != 0)
{
BitScanReverse(&BitPos, Value);
*StartingRunIndex = (BITMAP_INDEX)((Buffer + 1 - BitMapHeader->Buffer) * _BITCOUNT + BitPos + 1);
}
else
{
*StartingRunIndex = 0;
}
return (FromIndex - *StartingRunIndex);
}
ULONG
NTAPI
RtlFindClearRuns(
_In_ PRTL_BITMAP BitMapHeader,
_In_ PRTL_BITMAP_RUN RunArray,
_In_ ULONG SizeOfRunArray,
_In_ BOOLEAN LocateLongestRuns)
{
BITMAP_INDEX StartingIndex, NumberOfBits, FromIndex = 0, SmallestRun = 0;
ULONG Run;
for (Run = 0; Run < SizeOfRunArray; Run++)
{
NumberOfBits = RtlFindNextForwardRunClear(BitMapHeader,
FromIndex,
&StartingIndex);
if (NumberOfBits == 0) break;
RunArray[Run].StartingIndex = StartingIndex;
RunArray[Run].NumberOfBits = NumberOfBits;
if (NumberOfBits < RunArray[SmallestRun].NumberOfBits)
{
SmallestRun = Run;
}
FromIndex = StartingIndex + NumberOfBits;
}
if (Run < SizeOfRunArray || !LocateLongestRuns)
{
return Run;
}
while (1)
{
NumberOfBits = RtlFindNextForwardRunClear(BitMapHeader,
FromIndex,
&StartingIndex);
if (NumberOfBits == 0) break;
if (NumberOfBits > RunArray[SmallestRun].NumberOfBits)
{
RunArray[SmallestRun].StartingIndex = StartingIndex;
RunArray[SmallestRun].NumberOfBits = NumberOfBits;
for (Run = 0; Run < SizeOfRunArray; Run++)
{
if (NumberOfBits < RunArray[SmallestRun].NumberOfBits)
{
SmallestRun = Run;
}
}
}
FromIndex += NumberOfBits;
}
return Run;
}
BITMAP_INDEX
NTAPI
RtlFindLongestRunClear(
IN PRTL_BITMAP BitMapHeader,
IN PBITMAP_INDEX StartingIndex)
{
BITMAP_INDEX NumberOfBits, Index, MaxNumberOfBits = 0, FromIndex = 0;
while (1)
{
NumberOfBits = RtlFindNextForwardRunClear(BitMapHeader,
FromIndex,
&Index);
if (NumberOfBits == 0) break;
if (NumberOfBits > MaxNumberOfBits)
{
MaxNumberOfBits = NumberOfBits;
*StartingIndex = Index;
}
FromIndex += NumberOfBits;
}
return MaxNumberOfBits;
}
BITMAP_INDEX
NTAPI
RtlFindLongestRunSet(
IN PRTL_BITMAP BitMapHeader,
IN PBITMAP_INDEX StartingIndex)
{
BITMAP_INDEX NumberOfBits, Index, MaxNumberOfBits = 0, FromIndex = 0;
while (1)
{
NumberOfBits = RtlFindNextForwardRunSet(BitMapHeader,
FromIndex,
&Index);
if (NumberOfBits == 0) break;
if (NumberOfBits > MaxNumberOfBits)
{
MaxNumberOfBits = NumberOfBits;
*StartingIndex = Index;
}
FromIndex += NumberOfBits;
}
return MaxNumberOfBits;
}