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//*****************************************************************************
30struct 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
125class StgPoolReadOnly;
126
127//*****************************************************************************
128// This hash class will handle strings inside of a chunk of the pool.
129//*****************************************************************************
130struct STRINGHASH : HASHLINK
131{
132 ULONG iOffset; // Offset of this item.
133};
134
135class CStringPoolHash : public CChainedHash<STRINGHASH>
136{
137 friend class VerifyLayoutsMD;
138public:
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
164private:
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//*****************************************************************************
173typedef STRINGHASH BLOBHASH;
174
175class CBlobPoolHash : public CChainedHash<STRINGHASH>
176{
177 friend class VerifyLayoutsMD;
178public:
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
210private:
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//*****************************************************************************
217struct GUIDHASH : HASHLINK
218{
219 ULONG iIndex; // Index of this item.
220};
221
222class CGuidPoolHash : public CChainedHash<GUIDHASH>
223{
224 friend class VerifyLayoutsMD;
225public:
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
251private:
252 StgPoolReadOnly *m_Pool; // The GUID pool which this hashes.
253};
254
255
256#endif // __StgPooli_h__
257