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// File: DataBlob.h
6//
7
8//
9// Class code:MetaData::DataBlob provides secure access to a block of memory from MetaData (i.e. with fixed
10// endianess).
11//
12// ======================================================================================
13
14#pragma once
15
16#include "external.h"
17
18namespace MetaData
19{
20
21// --------------------------------------------------------------------------------------
22//
23// This class provides secure access to a block of memory.
24//
25class DataBlob
26{
27private:
28 //
29 // Private data
30 //
31
32 // The memory block of size code:m_cbSize. Can be non-NULL even if code:m_cbSize is 0.
33 __field_bcount(m_cbSize)
34 BYTE *m_pbData;
35 // Size of the memory block starting at code:m_pbData. If it is 0, then value of code:m_pbData can be
36 // anything (incl. NULL).
37 UINT32 m_cbSize;
38
39public:
40 //
41 // Initialization
42 //
43
44 // Creates empty memory block.
45 inline DataBlob();
46 // Creates memory block (pbData, of size cbSize).
47 inline DataBlob(
48 __in_bcount_opt(cbSize) BYTE *pbData,
49 UINT32 cbSize);
50 // Creates memory block copy.
51 inline DataBlob(
52 const DataBlob &source);
53 // Initializes memory block to empty data. The object could be already initialzied.
54 inline void Clear();
55 // Initializes memory block to data (pbData, of size cbSize). The object should be empty before.
56 inline void Init(
57 __in_bcount_opt(cbSize) BYTE *pbData,
58 UINT32 cbSize);
59
60 //
61 // Getters
62 //
63
64 //#PeekUx_Functions
65 // Reads the U1/U2/U4/U8 from the data blob without skipping the read data.
66 // Returns FALSE if there's not enough data in the blob, doesn't initialize the value '*pnValue' then.
67 // Returns TRUE otherwise, fills *pnValue, but doesn't move the memory block (doesn't skip the read
68 // data).
69 __checkReturn __success(return) inline BOOL PeekU1(__out BYTE *pnValue) const;
70 __checkReturn __success(return) inline BOOL PeekU2(__out UINT16 *pnValue) const;
71 __checkReturn __success(return) inline BOOL PeekU4(__out UINT32 *pnValue) const;
72 __checkReturn __success(return) inline BOOL PeekU8(__out UINT64 *pnValue) const;
73
74 //#GetUx_Functions
75 // Reads the U1/U2/U4/U8 from the data blob and skips the read data.
76 // Returns FALSE if there's not enough data in the blob, doesn't initialize the value '*pnValue' then.
77 // Returns TRUE otherwise, fills *pnValue and moves the memory block behind the read data.
78 __checkReturn __success(return) inline BOOL GetU1(__out BYTE *pnValue);
79 __checkReturn __success(return) inline BOOL GetU2(__out UINT16 *pnValue);
80 __checkReturn __success(return) inline BOOL GetU4(__out UINT32 *pnValue);
81 __checkReturn __success(return) inline BOOL GetU8(__out UINT64 *pnValue);
82
83 // Reads compressed integer (1, 2 or 4 bytes of format code:CompressedInteger#Format - returns the size
84 // in *pcbCompressedValueSize) from the data blob without skipping the read data.
85 // Returns FALSE if there's not enough data in the blob or the compression is invalid (starts with byte
86 // 111? ????), doesn't initialize the value *pnValue nor the size of the compressed value
87 // *pcbCompressedValueSize then.
88 // Returns TRUE otherwise, fills *pnValue and *pcbCompressedValueSize (with number 1,2 or 4), but
89 // doesn't move the memory block (doesn't skip the read data).
90 __checkReturn
91 __success(return)
92 inline BOOL PeekCompressedU(
93 __out UINT32 *pnValue,
94 __out UINT32 *pcbCompressedValueSize);
95 // Reads compressed integer (1, 2 or 4 bytes of format code:CompressedInteger#Format) from the data blob
96 // and skips the read data.
97 // Returns FALSE if there's not enough data in the blob or the compression is invalid (starts with byte
98 // 111? ????), doesn't initialize the value *pnValue then.
99 // Returns TRUE otherwise, fills *pnValue and moves the memory block behind the read data.
100 __checkReturn
101 __success(return)
102 inline BOOL GetCompressedU(__out UINT32 *pnValue);
103 // Reads compressed integer (1, 2 or 4 bytes of format code:CompressedInteger#Format - returns the size
104 // in *pcbCompressedValueSize) from the data blob and skips the read data.
105 // Returns FALSE if there's not enough data in the blob or the compression is invalid (starts with byte
106 // 111? ????), doesn't initialize the value *pnValue nor the size of the compressed value
107 // *pcbCompressedValueSize then.
108 // Returns TRUE otherwise, fills *pnValue and *pcbCompressedValueSize (with number 1,2 or 4) and moves
109 // the memory block behind the read data.
110 __checkReturn
111 __success(return)
112 inline BOOL GetCompressedU(
113 __out UINT32 *pnValue,
114 __out UINT32 *pcbCompressedValueSize);
115
116 // Reads data of size cbDataSize and skips the data (instead of reading the bytes, returns the data as
117 // *pData).
118 // Returns FALSE if there's not enough data in the blob, clears *pData then.
119 // Returns TRUE otherwise, fills *pData with the "read" data and moves the memory block behind the
120 // "read" data.
121 __checkReturn
122 __success(return)
123 inline BOOL GetDataOfSize(
124 UINT32 cbDataSize,
125 __out DataBlob *pData);
126
127 // Checks if there's at least cbDataSize bytes in the represented memory block.
128 // Returns TRUE if there's >= cbDataSize bytes. Returns FALSE otherwise.
129 inline BOOL ContainsData(UINT32 cbDataSize) const
130 { return cbDataSize <= m_cbSize; }
131/*
132 // Checks if there's at least cbDataSize1 + cbDataSize2 bytes in the represented memory block (and that
133 // the sum doesn't overflow).
134 // Returns TRUE if there's >= cbDataSize1 + cbDataSize2 bytes.
135 // Returns FALSE otherwise and if cbDataSize1 + cbDataSize2 overflows.
136 inline BOOL ContainsData_2Parts(
137 UINT32 cbDataSize1,
138 UINT32 cbDataSize2) const;
139 // Checks if there's valid compressed integer (1, 2 or 4 bytes of format
140 // code:DataBlob#CompressedIntegerFormat) in the data blob.
141 // Returns:
142 // * 0 ... if there's valid compressed integer.
143 // * 1 ... if there's not enough data in the data blob, but the encoding is correct.
144 // * 2 ... if the integer encoding is invalid (starts with byte 111x xxxx byte), but there are at least
145 // 4 bytes in the data blob left.
146 // * 3 ... if there's not enough data in the data blob and the integer encoding is invalid (starts with
147 // 111x xxx byte).
148 inline int ValidateCompressedU() const;
149*/
150
151 // Returns TRUE if the represented memory is empty.
152 inline BOOL IsEmpty() const
153 { return (m_cbSize == 0); }
154 // Gets pointer to the represented data buffer (can be random pointer if size of the data is 0).
155 // Note: Should be used exceptionally. Try to use other operations instead.
156 inline BYTE *GetDataPointer()
157 { return m_pbData; }
158 // Gets pointer to the represented data buffer (can be random pointer if size of the data is 0).
159 // Note: Should be used exceptionally. Try to use other operations instead.
160 inline const BYTE *GetDataPointer() const
161 { return m_pbData; }
162 // Gets pointer right behind the represented data buffer (can be random pointer if size of the data is
163 // 0).
164 inline const BYTE *GetDataPointerBehind() const
165 { return ((m_cbSize == 0) ? NULL : (m_pbData + m_cbSize)); }
166 // Gets the size of represented memory.
167 inline UINT32 GetSize() const
168 { return m_cbSize; }
169 //BOOL SkipBytes(UINT32 cbSize);
170
171public:
172 //
173 // Operations
174 //
175
176 // Truncates the buffer to exact size (cbSize).
177 // Returns FALSE if there's less than cbSize data represented.
178 // Returns TRUE otherwise and truncates the represented data size to cbSize.
179 __checkReturn
180 __success(return)
181 inline BOOL TruncateToExactSize(UINT32 cbSize);
182 // Truncates the buffer by size (cbSize).
183 // Returns FALSE if there's less than cbSize data represented.
184 // Returns TRUE otherwise and truncates the represented data size by cbSize.
185 __checkReturn
186 __success(return)
187 inline BOOL TruncateBySize(UINT32 cbSize);
188
189#ifdef _DEBUG
190 // Returns U1 value at offset (nOffset). Fires an assert if the offset is behind the end of represented
191 // data.
192 inline BYTE Debug_GetByteAtOffset(UINT32 nOffset) const;
193#endif //_DEBUG
194
195public:
196 //
197 // Setters
198 //
199
200 // Writes compressed integer (1, 2 or 4 bytes of format code:CompressedInteger#Format) to the data blob
201 // and skips the written data.
202 // Returns FALSE if there's not enough data in the blob or the value cannot be encoded as compressed
203 // integer (bigger than code:CompressedInteger::const_Max).
204 // Returns TRUE on success and moves the memory block behind the written data.
205 __checkReturn
206 __success(return)
207 inline BOOL StoreCompressedU(UINT32 nValue);
208
209 // Writes data from *pSource to the data blob and skips the written data.
210 // Returns FALSE if there's not enough data in the blob.
211 // Returns TRUE on success and moves memory block behind the written data.
212 __checkReturn
213 __success(return)
214 inline BOOL StoreData(__in const DataBlob *pSource);
215
216private:
217 //
218 // Helpers
219 //
220
221 // Skips cbSize bytes in the represented memory block. The caller is responsible for making sure that
222 // the represented memory block contains at least cbSize bytes, otherwise there will be a security
223 // issue.
224 // Should be used only internally, never call it from outside of this class.
225 inline void SkipBytes_InternalInsecure(UINT32 cbSize);
226
227}; // class DataBlob
228
229}; // namespace MetaData
230
231#include "datablob.inl"
232