Skip to content

Commit 083f255

Browse files
SerhiiMalyiSergiusTheBest
authored andcommitted
Add a wrapper for RTL_BITMAP
1 parent 9a5dffe commit 083f255

File tree

2 files changed

+169
-0
lines changed

2 files changed

+169
-0
lines changed

include/kf/Bitmap.h

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#pragma once
2+
#include "BitmapIterator.h"
3+
4+
namespace kf
5+
{
6+
template<POOL_TYPE poolType>
7+
class Bitmap
8+
{
9+
public:
10+
Bitmap()
11+
{
12+
}
13+
14+
~Bitmap()
15+
{
16+
free();
17+
}
18+
19+
Bitmap(const Bitmap&) = delete;
20+
Bitmap& operator=(const Bitmap&) = delete;
21+
22+
// IRQL <= APC_LEVEL for PagedPool and on Windows 7 and earlier
23+
NTSTATUS init(ULONG size)
24+
{
25+
if (this->size())
26+
{
27+
free();
28+
}
29+
30+
// Buffer must be an integer multiple of sizeof(ULONG) bytes
31+
const ULONG bufferSize = size % sizeof(ULONG) ? (size / sizeof(ULONG) + 1) * sizeof(ULONG) : size;
32+
auto buffer = ::ExAllocatePoolWithTag(poolType, bufferSize, PoolTag);
33+
if (!buffer)
34+
{
35+
return STATUS_INSUFFICIENT_RESOURCES;
36+
}
37+
RtlZeroMemory(buffer, bufferSize);
38+
39+
m_header = reinterpret_cast<PRTL_BITMAP>(::ExAllocatePoolWithTag(poolType, sizeof(RTL_BITMAP), PoolTag));
40+
if (!m_header)
41+
{
42+
::ExFreePoolWithTag(buffer, PoolTag);
43+
return STATUS_INSUFFICIENT_RESOURCES;
44+
}
45+
RtlZeroMemory(m_header, sizeof(RTL_BITMAP));
46+
47+
m_buffer = buffer;
48+
m_size = size;
49+
50+
RtlInitializeBitMap(m_header, static_cast<PULONG>(m_buffer), m_size);
51+
return STATUS_SUCCESS;
52+
}
53+
54+
ULONG size() const
55+
{
56+
return m_size;
57+
}
58+
59+
void setBits(ULONG startingIndex, ULONG numberToSet)
60+
{
61+
RtlSetBits(m_header, startingIndex, numberToSet);
62+
}
63+
64+
void clearBits(ULONG startingIndex, ULONG numberToSet)
65+
{
66+
RtlClearBits(m_header, startingIndex, numberToSet);
67+
}
68+
69+
void setAll()
70+
{
71+
RtlSetAllBits(m_header);
72+
}
73+
74+
void clearAll()
75+
{
76+
RtlClearAllBits(m_header);
77+
}
78+
79+
bool areBitsSet(ULONG startingIndex, ULONG size)
80+
{
81+
return RtlAreBitsSet(m_header, startingIndex, size);
82+
}
83+
84+
bool areBitsClear(ULONG startingIndex, ULONG size)
85+
{
86+
return RtlAreBitsClear(m_header, startingIndex, size);
87+
}
88+
89+
ULONG numberOfSetBits()
90+
{
91+
return RtlNumberOfSetBits(m_header);
92+
}
93+
94+
ULONG numberOfClearBits()
95+
{
96+
return RtlNumberOfClearBits(m_header);
97+
}
98+
99+
BitmapRangeIterator rangeIterator(ULONG startingIndex = 0)
100+
{
101+
return BitmapRangeIterator(m_header, startingIndex);
102+
}
103+
104+
private:
105+
void free()
106+
{
107+
if (m_buffer)
108+
{
109+
::ExFreePoolWithTag(m_buffer, PoolTag);
110+
m_buffer = nullptr;
111+
m_size = 0;
112+
}
113+
114+
if (m_header)
115+
{
116+
ExFreePoolWithTag(m_header, PoolTag);
117+
m_header = nullptr;
118+
}
119+
}
120+
121+
private:
122+
enum { PoolTag = '++MB' };
123+
124+
private:
125+
void* m_buffer = nullptr;
126+
ULONG m_size = 0;
127+
PRTL_BITMAP m_header = nullptr;
128+
};
129+
}

include/kf/BitmapIterator.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#pragma once
2+
3+
namespace kf
4+
{
5+
class BitmapRangeIterator
6+
{
7+
public:
8+
BitmapRangeIterator(PRTL_BITMAP header, ULONG startingIndex = 0)
9+
: m_index(startingIndex)
10+
, m_header(header)
11+
{
12+
}
13+
14+
struct Range
15+
{
16+
ULONG startingIndex;
17+
ULONG size;
18+
};
19+
20+
Range next()
21+
{
22+
ULONG startingIndex = RtlFindSetBits(m_header, 1, m_index);
23+
// For the case if Bitmap doesn't contain set bits after m_index, but contains some set bits ranges,
24+
// it can return the starting index of the first set range in the bitmap that will be lower than m_index
25+
if (ULONG_MAX == startingIndex || m_index > startingIndex)
26+
{
27+
return {};
28+
}
29+
30+
ULONG clearBitsStart = RtlFindClearBits(m_header, 1, startingIndex);
31+
32+
m_index = clearBitsStart;
33+
return { startingIndex, clearBitsStart - startingIndex };
34+
}
35+
36+
private:
37+
ULONG m_index = 0;
38+
PRTL_BITMAP m_header;
39+
};
40+
}

0 commit comments

Comments
 (0)