summaryrefslogtreecommitdiff
path: root/src/inc/stgpooli.h
blob: a29fa01e7533d090d376a6dc8356cfacaea052bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//*****************************************************************************
// StgPooli.h
// 

// 
// This is helper code for the string and blob pools.  It is here because it is
// secondary to the pooling interface and reduces clutter in the main file.
//
//*****************************************************************************

#ifndef __StgPooli_h__
#define __StgPooli_h__

#include "utilcode.h"                   // Base hashing code.



//
//
// CPackedLen
//
//

//*****************************************************************************
// Helper class to pack and unpack lengths.
//*****************************************************************************
struct CPackedLen
{
    enum {MAX_LEN = 0x1fffffff};
    static int Size(ULONG len)
    {
                LIMITED_METHOD_CONTRACT;
        // Smallest.
        if (len <= 0x7F)
            return 1;
        // Medium.
        if (len <= 0x3FFF)
            return 2;
        // Large (too large?).
        _ASSERTE(len <= MAX_LEN);
        return 4;
    }

    // Get a pointer to the data, and store the length.
    static void const *GetData(void const *pData, ULONG *pLength);

    // Get the length value encoded at *pData.  Update ppData to point past data.
    static ULONG GetLength(void const *pData, void const **ppData=0);

    // Get the length value encoded at *pData, and the size of that encoded value.
    static ULONG GetLength(void const *pData, int *pSizeOfLength);

    // Pack a length at *pData; return a pointer to the next byte.
    static void* PutLength(void *pData, ULONG len);

    // This is used for just getting an encoded length, and verifies that
    // there is no buffer or integer overflow.
    static HRESULT SafeGetLength(       // S_OK, or error
        void const  *pDataSource,       // First byte of length.
        void const  *pDataSourceEnd,    // End of valid source data memory
        ULONG       *pLength,           // Encoded value
        void const **ppDataNext);       // Pointer immediately following encoded length

    static HRESULT SafeGetLength(       // S_OK, or error
        BYTE const  *pDataSource,       // First byte of length.
        BYTE const  *pDataSourceEnd,    // End of valid source data memory
        ULONG       *pLength,           // Encoded value
        BYTE const **ppDataNext)        // Pointer immediately following encoded length
    {
        return SafeGetLength(
            reinterpret_cast<void const *>(pDataSource),
            reinterpret_cast<void const *>(pDataSourceEnd),
            pLength,
            reinterpret_cast<void const **>(ppDataNext));
    }

    // This performs the same tasks as GetLength above in addition to checking
    // that the value in *pcbData does not extend *ppData beyond pDataSourceEnd
    // and does not cause an integer overflow.
    static HRESULT SafeGetData(
        void const  *pDataSource,       // First byte of length.
        void const  *pDataSourceEnd,    // End of valid source data memory
        ULONG       *pcbData,           // Length of data
        void const **ppData);           // Start of data

    static HRESULT SafeGetData(
        BYTE const  *pDataSource,       // First byte of length.
        BYTE const  *pDataSourceEnd,    // End of valid source data memory
        ULONG       *pcbData,           // Length of data
        BYTE const **ppData)            // Start of data
    {
        return SafeGetData(
            reinterpret_cast<void const *>(pDataSource),
            reinterpret_cast<void const *>(pDataSourceEnd),
            pcbData,
            reinterpret_cast<void const **>(ppData));
    }

    // This is the same as GetData above except it takes a byte count instead
    // of pointer to determine the source data length.
    static HRESULT SafeGetData(         // S_OK, or error
        void const  *pDataSource,       // First byte of data
        ULONG        cbDataSource,      // Count of valid bytes in data source
        ULONG       *pcbData,           // Length of data
        void const **ppData);           // Start of data

    static HRESULT SafeGetData(
        BYTE const  *pDataSource,       // First byte of length.
        ULONG        cbDataSource,      // Count of valid bytes in data source
        ULONG       *pcbData,           // Length of data
        BYTE const **ppData)            // Start of data
    {
        return SafeGetData(
            reinterpret_cast<void const *>(pDataSource),
            cbDataSource,
            pcbData,
            reinterpret_cast<void const **>(ppData));
    }
};


class StgPoolReadOnly;

//*****************************************************************************
// This hash class will handle strings inside of a chunk of the pool.
//*****************************************************************************
struct STRINGHASH : HASHLINK
{
    ULONG       iOffset;                // Offset of this item.
};

class CStringPoolHash : public CChainedHash<STRINGHASH>
{
    friend class VerifyLayoutsMD;
public:
    CStringPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) 
    {
        LIMITED_METHOD_CONTRACT;
    }

    virtual bool InUse(STRINGHASH *pItem)
    { 
        LIMITED_METHOD_CONTRACT;
        return (pItem->iOffset != 0xffffffff); 
    }

    virtual void SetFree(STRINGHASH *pItem)
    { 
        LIMITED_METHOD_CONTRACT;
        pItem->iOffset = 0xffffffff; 
    }

    virtual ULONG Hash(const void *pData)
    { 
        WRAPPER_NO_CONTRACT;
        return (HashStringA(reinterpret_cast<LPCSTR>(pData))); 
    }

    virtual int Cmp(const void *pData, void *pItem);

private:
    StgPoolReadOnly *m_Pool;                // String pool which this hashes.
};


//*****************************************************************************
// This version is for byte streams with a 2 byte WORD giving the length of
// the data.
//*****************************************************************************
typedef STRINGHASH BLOBHASH;

class CBlobPoolHash : public CChainedHash<STRINGHASH>
{
    friend class VerifyLayoutsMD;
public:
    CBlobPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) 
    {
        LIMITED_METHOD_CONTRACT;
    }

    virtual bool InUse(BLOBHASH *pItem)
    { 
        LIMITED_METHOD_CONTRACT;
        return (pItem->iOffset != 0xffffffff); 
    }

    virtual void SetFree(BLOBHASH *pItem)
    { 
        LIMITED_METHOD_CONTRACT;
        pItem->iOffset = 0xffffffff; 
    }

    virtual ULONG Hash(const void *pData)
    {
        STATIC_CONTRACT_NOTHROW;
        STATIC_CONTRACT_GC_NOTRIGGER;
        STATIC_CONTRACT_FORBID_FAULT;

        ULONG       ulSize;
        ulSize = CPackedLen::GetLength(pData);
        ulSize += CPackedLen::Size(ulSize);
        return (HashBytes(reinterpret_cast<BYTE const *>(pData), ulSize));
    }

    virtual int Cmp(const void *pData, void *pItem);

private:
    StgPoolReadOnly *m_Pool;                // Blob pool which this hashes.
};

//*****************************************************************************
// This hash class will handle guids inside of a chunk of the pool.
//*****************************************************************************
struct GUIDHASH : HASHLINK
{
    ULONG       iIndex;                 // Index of this item.
};

class CGuidPoolHash : public CChainedHash<GUIDHASH>
{
    friend class VerifyLayoutsMD;
public:
    CGuidPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) 
    { 
        LIMITED_METHOD_CONTRACT; 
    }

    virtual bool InUse(GUIDHASH *pItem)
    {
        LIMITED_METHOD_CONTRACT;  
        return (pItem->iIndex != 0xffffffff); 
    }

    virtual void SetFree(GUIDHASH *pItem)
    {
        LIMITED_METHOD_CONTRACT;  
        pItem->iIndex = 0xffffffff; 
    }

    virtual ULONG Hash(const void *pData)
    { 
        WRAPPER_NO_CONTRACT;
        return (HashBytes(reinterpret_cast<BYTE const *>(pData), sizeof(GUID))); 
    }

    virtual int Cmp(const void *pData, void *pItem);

private:
    StgPoolReadOnly *m_Pool;                // The GUID pool which this hashes.
};


#endif // __StgPooli_h__