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: DataBuffer.h
6//
7
8//
9// Class code:DataBuffer provides secure access to a block of memory.
10//
11// ======================================================================================
12
13#pragma once
14
15#include "external.h"
16
17// --------------------------------------------------------------------------------------
18//
19// This class provides secure access to a block of memory.
20//
21class DataBuffer
22{
23private:
24 //
25 // Private data
26 //
27
28 // The memory block of size code:m_cbSize. Can be non-NULL even if code:m_cbSize is 0.
29 __field_bcount(m_cbSize)
30 BYTE *m_pbData;
31 // Size of the memory block starting at code:m_pbData. If it is 0, then value of code:m_pbData can be
32 // anything (incl. NULL).
33 UINT32 m_cbSize;
34
35public:
36 //
37 // Initialization
38 //
39
40 // Creates empty memory block.
41 inline DataBuffer();
42 // Creates memory block (pbData, of size cbSize).
43 inline DataBuffer(
44 __in_bcount(cbSize) BYTE *pbData,
45 UINT32 cbSize);
46 // Creates memory block copy.
47 inline DataBuffer(
48 const DataBuffer &source);
49 // Initializes memory block to empty data. The object could be already initialzied.
50 inline void Clear();
51 // Initializes memory block to data (pbData, of size cbSize). The object should be empty before.
52 inline void Init(
53 __in_bcount(cbSize) BYTE *pbData,
54 UINT32 cbSize);
55
56 //
57 // Getters
58 //
59
60 // Reads data of type T without skipping the read data (returns pointer to the type in *ppTypeData).
61 // Returns FALSE if there's not enough data (of size T) in the blob, doesn't initialize the pointer
62 // *ppTypeData then.
63 // Returns TRUE otherwise, fills *ppTypeData with the "read" type start, but doesn't move the memory
64 // block (doesn't skip the "read" data).
65 template<class T>
66 __checkReturn
67 inline BOOL PeekData(
68 __deref_out T **ppTypeData);
69 // Reads data of type T at offset nOffset without skipping the read data (returns pointer to the type in
70 // *ppTypeData).
71 // Returns FALSE if there's not enough data (of size T) at offset nOffset in the buffer, doesn't
72 // initialize the pointer *ppTypeData then.
73 // Returns TRUE otherwise, fills *ppTypeData with the type start, but doesn't move the memory block
74 // (doesn't skip any "read" data).
75 template<class T>
76 __checkReturn
77 inline BOOL PeekDataAt(
78 UINT32 nOffset,
79 __deref_out T **ppTypeData);
80 // Reads data of type T and skips the data (instead of reading the bytes, returns pointer to the type in
81 // *ppTypeData).
82 // Returns FALSE if there's not enough data (of size T) in the blob, doesn't initialize the pointer
83 // *ppTypeData then.
84 // Returns TRUE otherwise, fills *ppTypeData with the "read" type start and moves the memory block
85 // behind the "read" type.
86 template<class T>
87 __checkReturn
88 inline BOOL GetData(
89 __deref_out T **ppTypeData);
90 // Reads data of size cbDataSize and skips the data (instead of reading the bytes, returns pointer to
91 // the bytes in *ppbDataPointer).
92 // Returns FALSE if there's not enough data in the blob, doesn't initialize the pointer *ppbDataPointer
93 // then.
94 // Returns TRUE otherwise, fills *ppbDataPointer with the "read" data start and moves the memory block
95 // behind the "read" data.
96 __checkReturn
97 inline BOOL GetDataOfSize(
98 UINT32 cbDataSize,
99 __out_bcount(cbDataSize) BYTE **ppbDataPointer);
100
101 // Returns TRUE if the represented memory is empty.
102 inline BOOL IsEmpty() const
103 { return (m_cbSize == 0); }
104 // Gets pointer to the represented data buffer (can be random pointer if size of the data is 0).
105 // Note: Should be used exceptionally. Try to use other operations instead.
106 inline BYTE *GetDataPointer()
107 { return m_pbData; }
108 // Gets pointer to the represented data buffer (can be random pointer if size of the data is 0).
109 // Note: Should be used exceptionally. Try to use other operations instead.
110 inline const BYTE *GetDataPointer() const
111 { return m_pbData; }
112 // Gets pointer right behind the represented data buffer (can be random pointer if size of the data is
113 // 0).
114 inline const BYTE *GetDataPointerBehind() const
115 { return m_pbData + m_cbSize; }
116 // Gets the size of represented memory.
117 inline UINT32 GetSize() const
118 { return m_cbSize; }
119 //BOOL SkipBytes(UINT32 cbSize);
120
121public:
122 //
123 // Operations
124 //
125
126 // Truncates the buffer to exact size (cbSize).
127 // Returns FALSE if there's less than cbSize data represented.
128 // Returns TRUE otherwise and truncates the represented data size to cbSize.
129 __checkReturn
130 inline BOOL TruncateToExactSize(UINT32 cbSize);
131 // Truncates the buffer by size (cbSize).
132 // Returns FALSE if there's less than cbSize data represented.
133 // Returns TRUE otherwise and truncates the represented data size by cbSize.
134 __checkReturn
135 inline BOOL TruncateBySize(UINT32 cbSize);
136
137 // Skips the buffer to exact size (cbSize).
138 // Returns FALSE if there's less than cbSize data represented.
139 // Returns TRUE otherwise and skips data at the beggining, so that the result has size cbSize.
140 __checkReturn
141 inline BOOL SkipToExactSize(UINT32 cbSize);
142
143private:
144 //
145 // Helpers
146 //
147
148 // Skips 'cbSize' bytes in the represented memory block. The caller is responsible for making sure that
149 // the represented memory block contains at least 'cbSize' bytes, otherwise there will be a security
150 // issue.
151 // Should be used only internally, never call it from outside of this class.
152 inline void SkipBytes_InternalInsecure(UINT32 cbSize);
153
154}; // class DataBuffer
155
156#include "databuffer.inl"
157