1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | //***************************************************************************** |
5 | // StgPooli.h |
6 | // |
7 | |
8 | // |
9 | // This is helper code for the string and blob pools. It is here because it is |
10 | // secondary to the pooling interface and reduces clutter in the main file. |
11 | // |
12 | //***************************************************************************** |
13 | |
14 | #ifndef __StgPooli_h__ |
15 | #define __StgPooli_h__ |
16 | |
17 | #include "utilcode.h" // Base hashing code. |
18 | |
19 | |
20 | |
21 | // |
22 | // |
23 | // CPackedLen |
24 | // |
25 | // |
26 | |
27 | //***************************************************************************** |
28 | // Helper class to pack and unpack lengths. |
29 | //***************************************************************************** |
30 | struct CPackedLen |
31 | { |
32 | enum {MAX_LEN = 0x1fffffff}; |
33 | static int Size(ULONG len) |
34 | { |
35 | LIMITED_METHOD_CONTRACT; |
36 | // Smallest. |
37 | if (len <= 0x7F) |
38 | return 1; |
39 | // Medium. |
40 | if (len <= 0x3FFF) |
41 | return 2; |
42 | // Large (too large?). |
43 | _ASSERTE(len <= MAX_LEN); |
44 | return 4; |
45 | } |
46 | |
47 | // Get a pointer to the data, and store the length. |
48 | static void const *GetData(void const *pData, ULONG *pLength); |
49 | |
50 | // Get the length value encoded at *pData. Update ppData to point past data. |
51 | static ULONG GetLength(void const *pData, void const **ppData=0); |
52 | |
53 | // Get the length value encoded at *pData, and the size of that encoded value. |
54 | static ULONG GetLength(void const *pData, int *pSizeOfLength); |
55 | |
56 | // Pack a length at *pData; return a pointer to the next byte. |
57 | static void* PutLength(void *pData, ULONG len); |
58 | |
59 | // This is used for just getting an encoded length, and verifies that |
60 | // there is no buffer or integer overflow. |
61 | static HRESULT SafeGetLength( // S_OK, or error |
62 | void const *pDataSource, // First byte of length. |
63 | void const *pDataSourceEnd, // End of valid source data memory |
64 | ULONG *pLength, // Encoded value |
65 | void const **ppDataNext); // Pointer immediately following encoded length |
66 | |
67 | static HRESULT SafeGetLength( // S_OK, or error |
68 | BYTE const *pDataSource, // First byte of length. |
69 | BYTE const *pDataSourceEnd, // End of valid source data memory |
70 | ULONG *pLength, // Encoded value |
71 | BYTE const **ppDataNext) // Pointer immediately following encoded length |
72 | { |
73 | return SafeGetLength( |
74 | reinterpret_cast<void const *>(pDataSource), |
75 | reinterpret_cast<void const *>(pDataSourceEnd), |
76 | pLength, |
77 | reinterpret_cast<void const **>(ppDataNext)); |
78 | } |
79 | |
80 | // This performs the same tasks as GetLength above in addition to checking |
81 | // that the value in *pcbData does not extend *ppData beyond pDataSourceEnd |
82 | // and does not cause an integer overflow. |
83 | static HRESULT SafeGetData( |
84 | void const *pDataSource, // First byte of length. |
85 | void const *pDataSourceEnd, // End of valid source data memory |
86 | ULONG *pcbData, // Length of data |
87 | void const **ppData); // Start of data |
88 | |
89 | static HRESULT SafeGetData( |
90 | BYTE const *pDataSource, // First byte of length. |
91 | BYTE const *pDataSourceEnd, // End of valid source data memory |
92 | ULONG *pcbData, // Length of data |
93 | BYTE const **ppData) // Start of data |
94 | { |
95 | return SafeGetData( |
96 | reinterpret_cast<void const *>(pDataSource), |
97 | reinterpret_cast<void const *>(pDataSourceEnd), |
98 | pcbData, |
99 | reinterpret_cast<void const **>(ppData)); |
100 | } |
101 | |
102 | // This is the same as GetData above except it takes a byte count instead |
103 | // of pointer to determine the source data length. |
104 | static HRESULT SafeGetData( // S_OK, or error |
105 | void const *pDataSource, // First byte of data |
106 | ULONG cbDataSource, // Count of valid bytes in data source |
107 | ULONG *pcbData, // Length of data |
108 | void const **ppData); // Start of data |
109 | |
110 | static HRESULT SafeGetData( |
111 | BYTE const *pDataSource, // First byte of length. |
112 | ULONG cbDataSource, // Count of valid bytes in data source |
113 | ULONG *pcbData, // Length of data |
114 | BYTE const **ppData) // Start of data |
115 | { |
116 | return SafeGetData( |
117 | reinterpret_cast<void const *>(pDataSource), |
118 | cbDataSource, |
119 | pcbData, |
120 | reinterpret_cast<void const **>(ppData)); |
121 | } |
122 | }; |
123 | |
124 | |
125 | class StgPoolReadOnly; |
126 | |
127 | //***************************************************************************** |
128 | // This hash class will handle strings inside of a chunk of the pool. |
129 | //***************************************************************************** |
130 | struct STRINGHASH : HASHLINK |
131 | { |
132 | ULONG iOffset; // Offset of this item. |
133 | }; |
134 | |
135 | class CStringPoolHash : public CChainedHash<STRINGHASH> |
136 | { |
137 | friend class VerifyLayoutsMD; |
138 | public: |
139 | CStringPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) |
140 | { |
141 | LIMITED_METHOD_CONTRACT; |
142 | } |
143 | |
144 | virtual bool InUse(STRINGHASH *pItem) |
145 | { |
146 | LIMITED_METHOD_CONTRACT; |
147 | return (pItem->iOffset != 0xffffffff); |
148 | } |
149 | |
150 | virtual void SetFree(STRINGHASH *pItem) |
151 | { |
152 | LIMITED_METHOD_CONTRACT; |
153 | pItem->iOffset = 0xffffffff; |
154 | } |
155 | |
156 | virtual ULONG Hash(const void *pData) |
157 | { |
158 | WRAPPER_NO_CONTRACT; |
159 | return (HashStringA(reinterpret_cast<LPCSTR>(pData))); |
160 | } |
161 | |
162 | virtual int Cmp(const void *pData, void *pItem); |
163 | |
164 | private: |
165 | StgPoolReadOnly *m_Pool; // String pool which this hashes. |
166 | }; |
167 | |
168 | |
169 | //***************************************************************************** |
170 | // This version is for byte streams with a 2 byte WORD giving the length of |
171 | // the data. |
172 | //***************************************************************************** |
173 | typedef STRINGHASH BLOBHASH; |
174 | |
175 | class CBlobPoolHash : public CChainedHash<STRINGHASH> |
176 | { |
177 | friend class VerifyLayoutsMD; |
178 | public: |
179 | CBlobPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) |
180 | { |
181 | LIMITED_METHOD_CONTRACT; |
182 | } |
183 | |
184 | virtual bool InUse(BLOBHASH *pItem) |
185 | { |
186 | LIMITED_METHOD_CONTRACT; |
187 | return (pItem->iOffset != 0xffffffff); |
188 | } |
189 | |
190 | virtual void SetFree(BLOBHASH *pItem) |
191 | { |
192 | LIMITED_METHOD_CONTRACT; |
193 | pItem->iOffset = 0xffffffff; |
194 | } |
195 | |
196 | virtual ULONG Hash(const void *pData) |
197 | { |
198 | STATIC_CONTRACT_NOTHROW; |
199 | STATIC_CONTRACT_GC_NOTRIGGER; |
200 | STATIC_CONTRACT_FORBID_FAULT; |
201 | |
202 | ULONG ulSize; |
203 | ulSize = CPackedLen::GetLength(pData); |
204 | ulSize += CPackedLen::Size(ulSize); |
205 | return (HashBytes(reinterpret_cast<BYTE const *>(pData), ulSize)); |
206 | } |
207 | |
208 | virtual int Cmp(const void *pData, void *pItem); |
209 | |
210 | private: |
211 | StgPoolReadOnly *m_Pool; // Blob pool which this hashes. |
212 | }; |
213 | |
214 | //***************************************************************************** |
215 | // This hash class will handle guids inside of a chunk of the pool. |
216 | //***************************************************************************** |
217 | struct GUIDHASH : HASHLINK |
218 | { |
219 | ULONG iIndex; // Index of this item. |
220 | }; |
221 | |
222 | class CGuidPoolHash : public CChainedHash<GUIDHASH> |
223 | { |
224 | friend class VerifyLayoutsMD; |
225 | public: |
226 | CGuidPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) |
227 | { |
228 | LIMITED_METHOD_CONTRACT; |
229 | } |
230 | |
231 | virtual bool InUse(GUIDHASH *pItem) |
232 | { |
233 | LIMITED_METHOD_CONTRACT; |
234 | return (pItem->iIndex != 0xffffffff); |
235 | } |
236 | |
237 | virtual void SetFree(GUIDHASH *pItem) |
238 | { |
239 | LIMITED_METHOD_CONTRACT; |
240 | pItem->iIndex = 0xffffffff; |
241 | } |
242 | |
243 | virtual ULONG Hash(const void *pData) |
244 | { |
245 | WRAPPER_NO_CONTRACT; |
246 | return (HashBytes(reinterpret_cast<BYTE const *>(pData), sizeof(GUID))); |
247 | } |
248 | |
249 | virtual int Cmp(const void *pData, void *pItem); |
250 | |
251 | private: |
252 | StgPoolReadOnly *m_Pool; // The GUID pool which this hashes. |
253 | }; |
254 | |
255 | |
256 | #endif // __StgPooli_h__ |
257 | |