aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/buffutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dutil/buffutil.cpp')
-rw-r--r--src/dutil/buffutil.cpp419
1 files changed, 419 insertions, 0 deletions
diff --git a/src/dutil/buffutil.cpp b/src/dutil/buffutil.cpp
new file mode 100644
index 00000000..0cc67dcb
--- /dev/null
+++ b/src/dutil/buffutil.cpp
@@ -0,0 +1,419 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5
6// constants
7
8#define BUFFER_INCREMENT 128
9
10
11// helper function declarations
12
13static HRESULT EnsureBufferSize(
14 __deref_out_bcount(cbSize) BYTE** ppbBuffer,
15 __in SIZE_T cbSize
16 );
17
18
19// functions
20
21extern "C" HRESULT BuffReadNumber(
22 __in_bcount(cbBuffer) const BYTE* pbBuffer,
23 __in SIZE_T cbBuffer,
24 __inout SIZE_T* piBuffer,
25 __out DWORD* pdw
26 )
27{
28 Assert(pbBuffer);
29 Assert(piBuffer);
30 Assert(pdw);
31
32 HRESULT hr = S_OK;
33 SIZE_T cbAvailable = 0;
34
35 // get availiable data size
36 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
37 ExitOnRootFailure(hr, "Failed to calculate available data size.");
38
39 // verify buffer size
40 if (sizeof(DWORD) > cbAvailable)
41 {
42 hr = E_INVALIDARG;
43 ExitOnRootFailure(hr, "Buffer too small.");
44 }
45
46 *pdw = *(const DWORD*)(pbBuffer + *piBuffer);
47 *piBuffer += sizeof(DWORD);
48
49LExit:
50 return hr;
51}
52
53extern "C" HRESULT BuffReadNumber64(
54 __in_bcount(cbBuffer) const BYTE* pbBuffer,
55 __in SIZE_T cbBuffer,
56 __inout SIZE_T* piBuffer,
57 __out DWORD64* pdw64
58 )
59{
60 Assert(pbBuffer);
61 Assert(piBuffer);
62 Assert(pdw64);
63
64 HRESULT hr = S_OK;
65 SIZE_T cbAvailable = 0;
66
67 // get availiable data size
68 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
69 ExitOnRootFailure(hr, "Failed to calculate available data size.");
70
71 // verify buffer size
72 if (sizeof(DWORD64) > cbAvailable)
73 {
74 hr = E_INVALIDARG;
75 ExitOnRootFailure(hr, "Buffer too small.");
76 }
77
78 *pdw64 = *(const DWORD64*)(pbBuffer + *piBuffer);
79 *piBuffer += sizeof(DWORD64);
80
81LExit:
82 return hr;
83}
84
85extern "C" HRESULT BuffReadString(
86 __in_bcount(cbBuffer) const BYTE* pbBuffer,
87 __in SIZE_T cbBuffer,
88 __inout SIZE_T* piBuffer,
89 __deref_out_z LPWSTR* pscz
90 )
91{
92 Assert(pbBuffer);
93 Assert(piBuffer);
94 Assert(pscz);
95
96 HRESULT hr = S_OK;
97 DWORD cch = 0;
98 DWORD cb = 0;
99 SIZE_T cbAvailable = 0;
100
101 // get availiable data size
102 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
103 ExitOnRootFailure(hr, "Failed to calculate available data size for character count.");
104
105 // verify buffer size
106 if (sizeof(DWORD) > cbAvailable)
107 {
108 hr = E_INVALIDARG;
109 ExitOnRootFailure(hr, "Buffer too small.");
110 }
111
112 // read character count
113 cch = *(const DWORD*)(pbBuffer + *piBuffer);
114
115 hr = ::DWordMult(cch, static_cast<DWORD>(sizeof(WCHAR)), &cb);
116 ExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size");
117
118 hr = ::SIZETAdd(*piBuffer, sizeof(DWORD), piBuffer);
119 ExitOnRootFailure(hr, "Overflow while adding to calculate buffer size");
120
121 // get availiable data size
122 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
123 ExitOnRootFailure(hr, "Failed to calculate available data size for character buffer.");
124
125 // verify buffer size
126 if (cb > cbAvailable)
127 {
128 hr = E_INVALIDARG;
129 ExitOnRootFailure(hr, "Buffer too small to hold character data.");
130 }
131
132 // copy character data
133 hr = StrAllocString(pscz, cch ? (LPCWSTR)(pbBuffer + *piBuffer) : L"", cch);
134 ExitOnFailure(hr, "Failed to copy character data.");
135
136 *piBuffer += cb;
137
138LExit:
139 return hr;
140}
141
142extern "C" HRESULT BuffReadStringAnsi(
143 __in_bcount(cbBuffer) const BYTE* pbBuffer,
144 __in SIZE_T cbBuffer,
145 __inout SIZE_T* piBuffer,
146 __deref_out_z LPSTR* pscz
147 )
148{
149 Assert(pbBuffer);
150 Assert(piBuffer);
151 Assert(pscz);
152
153 HRESULT hr = S_OK;
154 DWORD cch = 0;
155 DWORD cb = 0;
156 SIZE_T cbAvailable = 0;
157
158 // get availiable data size
159 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
160 ExitOnRootFailure(hr, "Failed to calculate available data size for character count.");
161
162 // verify buffer size
163 if (sizeof(DWORD) > cbAvailable)
164 {
165 hr = E_INVALIDARG;
166 ExitOnRootFailure(hr, "Buffer too small.");
167 }
168
169 // read character count
170 cch = *(const DWORD*)(pbBuffer + *piBuffer);
171
172 hr = ::DWordMult(cch, static_cast<DWORD>(sizeof(CHAR)), &cb);
173 ExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size");
174
175 hr = ::SIZETAdd(*piBuffer, sizeof(DWORD), piBuffer);
176 ExitOnRootFailure(hr, "Overflow while adding to calculate buffer size");
177
178 // get availiable data size
179 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
180 ExitOnRootFailure(hr, "Failed to calculate available data size for character buffer.");
181
182 // verify buffer size
183 if (cb > cbAvailable)
184 {
185 hr = E_INVALIDARG;
186 ExitOnRootFailure(hr, "Buffer too small to hold character count.");
187 }
188
189 // copy character data
190 hr = StrAnsiAllocStringAnsi(pscz, cch ? (LPCSTR)(pbBuffer + *piBuffer) : "", cch);
191 ExitOnFailure(hr, "Failed to copy character data.");
192
193 *piBuffer += cb;
194
195LExit:
196 return hr;
197}
198
199extern "C" HRESULT BuffReadStream(
200 __in_bcount(cbBuffer) const BYTE* pbBuffer,
201 __in SIZE_T cbBuffer,
202 __inout SIZE_T* piBuffer,
203 __deref_out_bcount(*pcbStream) BYTE** ppbStream,
204 __out SIZE_T* pcbStream
205 )
206{
207 Assert(pbBuffer);
208 Assert(piBuffer);
209 Assert(ppbStream);
210 Assert(pcbStream);
211
212 HRESULT hr = S_OK;
213 DWORD64 cb = 0;
214 SIZE_T cbAvailable = 0;
215
216 // get availiable data size
217 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
218 ExitOnRootFailure(hr, "Failed to calculate available data size for stream size.");
219
220 // verify buffer size
221 if (sizeof(DWORD64) > cbAvailable)
222 {
223 hr = E_INVALIDARG;
224 ExitOnRootFailure(hr, "Buffer too small.");
225 }
226
227 // read stream size
228 cb = *(const DWORD64*)(pbBuffer + *piBuffer);
229 *piBuffer += sizeof(DWORD64);
230
231 // get availiable data size
232 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
233 ExitOnRootFailure(hr, "Failed to calculate available data size for stream buffer.");
234
235 // verify buffer size
236 if (cb > cbAvailable)
237 {
238 hr = E_INVALIDARG;
239 ExitOnRootFailure(hr, "Buffer too small to hold byte count.");
240 }
241
242 // allocate buffer
243 *ppbStream = (BYTE*)MemAlloc((SIZE_T)cb, TRUE);
244 ExitOnNull(*ppbStream, hr, E_OUTOFMEMORY, "Failed to allocate stream.");
245
246 // read stream data
247 memcpy_s(*ppbStream, cbBuffer - *piBuffer, pbBuffer + *piBuffer, (SIZE_T)cb);
248 *piBuffer += (SIZE_T)cb;
249
250 // return stream size
251 *pcbStream = (SIZE_T)cb;
252
253LExit:
254 return hr;
255}
256
257extern "C" HRESULT BuffWriteNumber(
258 __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,
259 __inout SIZE_T* piBuffer,
260 __in DWORD dw
261 )
262{
263 Assert(ppbBuffer);
264 Assert(piBuffer);
265
266 HRESULT hr = S_OK;
267
268 // make sure we have a buffer with sufficient space
269 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD));
270 ExitOnFailure(hr, "Failed to ensure buffer size.");
271
272 // copy data to buffer
273 *(DWORD*)(*ppbBuffer + *piBuffer) = dw;
274 *piBuffer += sizeof(DWORD);
275
276LExit:
277 return hr;
278}
279
280extern "C" HRESULT BuffWriteNumber64(
281 __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,
282 __inout SIZE_T* piBuffer,
283 __in DWORD64 dw64
284 )
285{
286 Assert(ppbBuffer);
287 Assert(piBuffer);
288
289 HRESULT hr = S_OK;
290
291 // make sure we have a buffer with sufficient space
292 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD64));
293 ExitOnFailure(hr, "Failed to ensure buffer size.");
294
295 // copy data to buffer
296 *(DWORD64*)(*ppbBuffer + *piBuffer) = dw64;
297 *piBuffer += sizeof(DWORD64);
298
299LExit:
300 return hr;
301}
302
303extern "C" HRESULT BuffWriteString(
304 __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,
305 __inout SIZE_T* piBuffer,
306 __in_z_opt LPCWSTR scz
307 )
308{
309 Assert(ppbBuffer);
310 Assert(piBuffer);
311
312 HRESULT hr = S_OK;
313 DWORD cch = (DWORD)lstrlenW(scz);
314 SIZE_T cb = cch * sizeof(WCHAR);
315
316 // make sure we have a buffer with sufficient space
317 hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(DWORD) + cb));
318 ExitOnFailure(hr, "Failed to ensure buffer size.");
319
320 // copy character count to buffer
321 *(DWORD*)(*ppbBuffer + *piBuffer) = cch;
322 *piBuffer += sizeof(DWORD);
323
324 // copy data to buffer
325 memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb);
326 *piBuffer += cb;
327
328LExit:
329 return hr;
330}
331
332extern "C" HRESULT BuffWriteStringAnsi(
333 __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,
334 __inout SIZE_T* piBuffer,
335 __in_z_opt LPCSTR scz
336 )
337{
338 Assert(ppbBuffer);
339 Assert(piBuffer);
340
341 HRESULT hr = S_OK;
342 DWORD cch = (DWORD)lstrlenA(scz);
343 SIZE_T cb = cch * sizeof(CHAR);
344
345 // make sure we have a buffer with sufficient space
346 hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(DWORD) + cb));
347 ExitOnFailure(hr, "Failed to ensure buffer size.");
348
349 // copy character count to buffer
350 *(DWORD*)(*ppbBuffer + *piBuffer) = cch;
351 *piBuffer += sizeof(DWORD);
352
353 // copy data to buffer
354 memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb);
355 *piBuffer += cb;
356
357LExit:
358 return hr;
359}
360
361extern "C" HRESULT BuffWriteStream(
362 __deref_out_bcount(*piBuffer) BYTE** ppbBuffer,
363 __inout SIZE_T* piBuffer,
364 __in_bcount(cbStream) const BYTE* pbStream,
365 __in SIZE_T cbStream
366 )
367{
368 Assert(ppbBuffer);
369 Assert(piBuffer);
370 Assert(pbStream);
371
372 HRESULT hr = S_OK;
373 DWORD64 cb = cbStream;
374
375 // make sure we have a buffer with sufficient space
376 hr = EnsureBufferSize(ppbBuffer, *piBuffer + cbStream + sizeof(DWORD64));
377 ExitOnFailure(hr, "Failed to ensure buffer size.");
378
379 // copy byte count to buffer
380 *(DWORD64*)(*ppbBuffer + *piBuffer) = cb;
381 *piBuffer += sizeof(DWORD64);
382
383 // copy data to buffer
384 memcpy_s(*ppbBuffer + *piBuffer, cbStream, pbStream, cbStream);
385 *piBuffer += cbStream;
386
387LExit:
388 return hr;
389}
390
391
392// helper functions
393
394static HRESULT EnsureBufferSize(
395 __deref_out_bcount(cbSize) BYTE** ppbBuffer,
396 __in SIZE_T cbSize
397 )
398{
399 HRESULT hr = S_OK;
400 SIZE_T cbTarget = ((cbSize / BUFFER_INCREMENT) + 1) * BUFFER_INCREMENT;
401
402 if (*ppbBuffer)
403 {
404 if (MemSize(*ppbBuffer) < cbTarget)
405 {
406 LPVOID pv = MemReAlloc(*ppbBuffer, cbTarget, TRUE);
407 ExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to reallocate buffer.");
408 *ppbBuffer = (BYTE*)pv;
409 }
410 }
411 else
412 {
413 *ppbBuffer = (BYTE*)MemAlloc(cbTarget, TRUE);
414 ExitOnNull(*ppbBuffer, hr, E_OUTOFMEMORY, "Failed to allocate buffer.");
415 }
416
417LExit:
418 return hr;
419}