aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/buffutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/buffutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/buffutil.cpp529
1 files changed, 529 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/buffutil.cpp b/src/libs/dutil/WixToolset.DUtil/buffutil.cpp
new file mode 100644
index 00000000..b6d58cc0
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/buffutil.cpp
@@ -0,0 +1,529 @@
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// Exit macros
7#define BuffExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_BUFFUTIL, x, s, __VA_ARGS__)
8#define BuffExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_BUFFUTIL, x, s, __VA_ARGS__)
9#define BuffExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_BUFFUTIL, x, s, __VA_ARGS__)
10#define BuffExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_BUFFUTIL, x, s, __VA_ARGS__)
11#define BuffExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_BUFFUTIL, x, s, __VA_ARGS__)
12#define BuffExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_BUFFUTIL, x, s, __VA_ARGS__)
13#define BuffExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_BUFFUTIL, p, x, e, s, __VA_ARGS__)
14#define BuffExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_BUFFUTIL, p, x, s, __VA_ARGS__)
15#define BuffExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_BUFFUTIL, p, x, e, s, __VA_ARGS__)
16#define BuffExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_BUFFUTIL, p, x, s, __VA_ARGS__)
17#define BuffExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_BUFFUTIL, e, x, s, __VA_ARGS__)
18#define BuffExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_BUFFUTIL, g, x, s, __VA_ARGS__)
19
20
21// constants
22
23#define BUFFER_INCREMENT 128
24
25
26// helper function declarations
27
28static HRESULT EnsureBufferSize(
29 __deref_inout_bcount(cbSize) BYTE** ppbBuffer,
30 __in SIZE_T cbSize
31 );
32
33
34// functions
35
36extern "C" HRESULT BuffReadNumber(
37 __in_bcount(cbBuffer) const BYTE* pbBuffer,
38 __in SIZE_T cbBuffer,
39 __inout SIZE_T* piBuffer,
40 __out DWORD* pdw
41 )
42{
43 Assert(pbBuffer);
44 Assert(piBuffer);
45 Assert(pdw);
46
47 HRESULT hr = S_OK;
48 SIZE_T cbAvailable = 0;
49
50 // get availiable data size
51 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
52 BuffExitOnRootFailure(hr, "Failed to calculate available data size.");
53
54 // verify buffer size
55 if (sizeof(DWORD) > cbAvailable)
56 {
57 hr = E_INVALIDARG;
58 BuffExitOnRootFailure(hr, "Buffer too small.");
59 }
60
61 *pdw = *(const DWORD*)(pbBuffer + *piBuffer);
62 *piBuffer += sizeof(DWORD);
63
64LExit:
65 return hr;
66}
67
68extern "C" HRESULT BuffReadNumber64(
69 __in_bcount(cbBuffer) const BYTE * pbBuffer,
70 __in SIZE_T cbBuffer,
71 __inout SIZE_T* piBuffer,
72 __out DWORD64* pdw64
73 )
74{
75 Assert(pbBuffer);
76 Assert(piBuffer);
77 Assert(pdw64);
78
79 HRESULT hr = S_OK;
80 SIZE_T cbAvailable = 0;
81
82 // get availiable data size
83 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
84 BuffExitOnRootFailure(hr, "Failed to calculate available data size.");
85
86 // verify buffer size
87 if (sizeof(DWORD64) > cbAvailable)
88 {
89 hr = E_INVALIDARG;
90 BuffExitOnRootFailure(hr, "Buffer too small.");
91 }
92
93 *pdw64 = *(const DWORD64*)(pbBuffer + *piBuffer);
94 *piBuffer += sizeof(DWORD64);
95
96LExit:
97 return hr;
98}
99
100extern "C" HRESULT BuffReadPointer(
101 __in_bcount(cbBuffer) const BYTE* pbBuffer,
102 __in SIZE_T cbBuffer,
103 __inout SIZE_T* piBuffer,
104 __out DWORD_PTR* pdw64
105 )
106{
107 Assert(pbBuffer);
108 Assert(piBuffer);
109 Assert(pdw64);
110
111 HRESULT hr = S_OK;
112 SIZE_T cbAvailable = 0;
113
114 // get availiable data size
115 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
116 BuffExitOnRootFailure(hr, "Failed to calculate available data size.");
117
118 // verify buffer size
119 if (sizeof(DWORD_PTR) > cbAvailable)
120 {
121 hr = E_INVALIDARG;
122 BuffExitOnRootFailure(hr, "Buffer too small.");
123 }
124
125 *pdw64 = *(const DWORD_PTR*)(pbBuffer + *piBuffer);
126 *piBuffer += sizeof(DWORD_PTR);
127
128LExit:
129 return hr;
130}
131
132extern "C" HRESULT BuffReadString(
133 __in_bcount(cbBuffer) const BYTE* pbBuffer,
134 __in SIZE_T cbBuffer,
135 __inout SIZE_T* piBuffer,
136 __deref_out_z LPWSTR* pscz
137 )
138{
139 Assert(pbBuffer);
140 Assert(piBuffer);
141 Assert(pscz);
142
143 HRESULT hr = S_OK;
144 SIZE_T cch = 0;
145 SIZE_T cb = 0;
146 SIZE_T cbAvailable = 0;
147
148 // get availiable data size
149 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
150 BuffExitOnRootFailure(hr, "Failed to calculate available data size for character count.");
151
152 // verify buffer size
153 if (sizeof(SIZE_T) > cbAvailable)
154 {
155 hr = E_INVALIDARG;
156 BuffExitOnRootFailure(hr, "Buffer too small.");
157 }
158
159 // read character count
160 cch = *(const SIZE_T*)(pbBuffer + *piBuffer);
161
162 hr = ::SIZETMult(cch, sizeof(WCHAR), &cb);
163 BuffExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size");
164
165 hr = ::SIZETAdd(*piBuffer, sizeof(SIZE_T), piBuffer);
166 BuffExitOnRootFailure(hr, "Overflow while adding to calculate buffer size");
167
168 // get availiable data size
169 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
170 BuffExitOnRootFailure(hr, "Failed to calculate available data size for character buffer.");
171
172 // verify buffer size
173 if (cb > cbAvailable)
174 {
175 hr = E_INVALIDARG;
176 BuffExitOnRootFailure(hr, "Buffer too small to hold character data.");
177 }
178
179 // copy character data
180 hr = StrAllocString(pscz, cch ? (LPCWSTR)(pbBuffer + *piBuffer) : L"", cch);
181 BuffExitOnFailure(hr, "Failed to copy character data.");
182
183 *piBuffer += cb;
184
185LExit:
186 return hr;
187}
188
189extern "C" HRESULT BuffReadStringAnsi(
190 __in_bcount(cbBuffer) const BYTE* pbBuffer,
191 __in SIZE_T cbBuffer,
192 __inout SIZE_T* piBuffer,
193 __deref_out_z LPSTR* pscz
194 )
195{
196 Assert(pbBuffer);
197 Assert(piBuffer);
198 Assert(pscz);
199
200 HRESULT hr = S_OK;
201 SIZE_T cch = 0;
202 SIZE_T cb = 0;
203 SIZE_T cbAvailable = 0;
204
205 // get availiable data size
206 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
207 BuffExitOnRootFailure(hr, "Failed to calculate available data size for character count.");
208
209 // verify buffer size
210 if (sizeof(SIZE_T) > cbAvailable)
211 {
212 hr = E_INVALIDARG;
213 BuffExitOnRootFailure(hr, "Buffer too small.");
214 }
215
216 // read character count
217 cch = *(const SIZE_T*)(pbBuffer + *piBuffer);
218
219 hr = ::SIZETMult(cch, sizeof(CHAR), &cb);
220 BuffExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size");
221
222 hr = ::SIZETAdd(*piBuffer, sizeof(SIZE_T), piBuffer);
223 BuffExitOnRootFailure(hr, "Overflow while adding to calculate buffer size");
224
225 // get availiable data size
226 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
227 BuffExitOnRootFailure(hr, "Failed to calculate available data size for character buffer.");
228
229 // verify buffer size
230 if (cb > cbAvailable)
231 {
232 hr = E_INVALIDARG;
233 BuffExitOnRootFailure(hr, "Buffer too small to hold character count.");
234 }
235
236 // copy character data
237 hr = StrAnsiAllocStringAnsi(pscz, cch ? (LPCSTR)(pbBuffer + *piBuffer) : "", cch);
238 BuffExitOnFailure(hr, "Failed to copy character data.");
239
240 *piBuffer += cb;
241
242LExit:
243 return hr;
244}
245
246extern "C" HRESULT BuffReadStream(
247 __in_bcount(cbBuffer) const BYTE* pbBuffer,
248 __in SIZE_T cbBuffer,
249 __inout SIZE_T* piBuffer,
250 __deref_inout_bcount(*pcbStream) BYTE** ppbStream,
251 __out SIZE_T* pcbStream
252 )
253{
254 Assert(pbBuffer);
255 Assert(piBuffer);
256 Assert(ppbStream);
257 Assert(pcbStream);
258
259 HRESULT hr = S_OK;
260 SIZE_T cb = 0;
261 SIZE_T cbAvailable = 0;
262 errno_t err = 0;
263
264 // get availiable data size
265 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
266 BuffExitOnRootFailure(hr, "Failed to calculate available data size for stream size.");
267
268 // verify buffer size
269 if (sizeof(SIZE_T) > cbAvailable)
270 {
271 hr = E_INVALIDARG;
272 BuffExitOnRootFailure(hr, "Buffer too small.");
273 }
274
275 // read stream size
276 cb = *(const SIZE_T*)(pbBuffer + *piBuffer);
277 *piBuffer += sizeof(SIZE_T);
278
279 // get availiable data size
280 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
281 BuffExitOnRootFailure(hr, "Failed to calculate available data size for stream buffer.");
282
283 // verify buffer size
284 if (cb > cbAvailable)
285 {
286 hr = E_INVALIDARG;
287 BuffExitOnRootFailure(hr, "Buffer too small to hold byte count.");
288 }
289
290 // allocate buffer
291 *ppbStream = (BYTE*)MemAlloc(cb, TRUE);
292 BuffExitOnNull(*ppbStream, hr, E_OUTOFMEMORY, "Failed to allocate stream.");
293
294 // read stream data
295 err = memcpy_s(*ppbStream, cbBuffer - *piBuffer, pbBuffer + *piBuffer, cb);
296 if (err)
297 {
298 BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to read stream from buffer, error: %d", err);
299 }
300
301 *piBuffer += cb;
302
303 // return stream size
304 *pcbStream = cb;
305
306LExit:
307 return hr;
308}
309
310extern "C" HRESULT BuffWriteNumber(
311 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
312 __inout SIZE_T* piBuffer,
313 __in DWORD dw
314 )
315{
316 Assert(ppbBuffer);
317 Assert(piBuffer);
318
319 HRESULT hr = S_OK;
320
321 // make sure we have a buffer with sufficient space
322 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD));
323 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
324
325 // copy data to buffer
326 *(DWORD*)(*ppbBuffer + *piBuffer) = dw;
327 *piBuffer += sizeof(DWORD);
328
329LExit:
330 return hr;
331}
332
333extern "C" HRESULT BuffWriteNumber64(
334 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
335 __inout SIZE_T* piBuffer,
336 __in DWORD64 dw64
337 )
338{
339 Assert(ppbBuffer);
340 Assert(piBuffer);
341
342 HRESULT hr = S_OK;
343
344 // make sure we have a buffer with sufficient space
345 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD64));
346 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
347
348 // copy data to buffer
349 *(DWORD64*)(*ppbBuffer + *piBuffer) = dw64;
350 *piBuffer += sizeof(DWORD64);
351
352LExit:
353 return hr;
354}
355
356extern "C" HRESULT BuffWritePointer(
357 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
358 __inout SIZE_T* piBuffer,
359 __in DWORD_PTR dw
360 )
361{
362 Assert(ppbBuffer);
363 Assert(piBuffer);
364
365 HRESULT hr = S_OK;
366
367 // make sure we have a buffer with sufficient space
368 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD_PTR));
369 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
370
371 // copy data to buffer
372 *(DWORD_PTR*)(*ppbBuffer + *piBuffer) = dw;
373 *piBuffer += sizeof(DWORD_PTR);
374
375LExit:
376 return hr;
377}
378
379extern "C" HRESULT BuffWriteString(
380 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
381 __inout SIZE_T* piBuffer,
382 __in_z_opt LPCWSTR scz
383 )
384{
385 Assert(ppbBuffer);
386 Assert(piBuffer);
387
388 HRESULT hr = S_OK;
389 SIZE_T cch = 0;
390 SIZE_T cb = 0;
391 errno_t err = 0;
392
393 if (scz)
394 {
395 hr = ::StringCchLengthW(scz, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cch));
396 BuffExitOnRootFailure(hr, "Failed to get string size.")
397 }
398
399 cb = cch * sizeof(WCHAR);
400
401 // make sure we have a buffer with sufficient space
402 hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(SIZE_T) + cb));
403 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
404
405 // copy character count to buffer
406 *(SIZE_T*)(*ppbBuffer + *piBuffer) = cch;
407 *piBuffer += sizeof(SIZE_T);
408
409 // copy data to buffer
410 err = memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb);
411 if (err)
412 {
413 BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write string to buffer: '%ls', error: %d", scz, err);
414 }
415
416 *piBuffer += cb;
417
418LExit:
419 return hr;
420}
421
422extern "C" HRESULT BuffWriteStringAnsi(
423 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
424 __inout SIZE_T* piBuffer,
425 __in_z_opt LPCSTR scz
426 )
427{
428 Assert(ppbBuffer);
429 Assert(piBuffer);
430
431 HRESULT hr = S_OK;
432 SIZE_T cch = 0;
433 SIZE_T cb = 0;
434 errno_t err = 0;
435
436 if (scz)
437 {
438 hr = ::StringCchLengthA(scz, STRSAFE_MAX_CCH, reinterpret_cast<size_t*>(&cch));
439 BuffExitOnRootFailure(hr, "Failed to get string size.")
440 }
441
442 cb = cch * sizeof(CHAR);
443
444 // make sure we have a buffer with sufficient space
445 hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(SIZE_T) + cb));
446 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
447
448 // copy character count to buffer
449 *(SIZE_T*)(*ppbBuffer + *piBuffer) = cch;
450 *piBuffer += sizeof(SIZE_T);
451
452 // copy data to buffer
453 err = memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb);
454 if (err)
455 {
456 BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write string to buffer: '%hs', error: %d", scz, err);
457 }
458
459 *piBuffer += cb;
460
461LExit:
462 return hr;
463}
464
465extern "C" HRESULT BuffWriteStream(
466 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
467 __inout SIZE_T* piBuffer,
468 __in_bcount(cbStream) const BYTE* pbStream,
469 __in SIZE_T cbStream
470 )
471{
472 Assert(ppbBuffer);
473 Assert(piBuffer);
474 Assert(pbStream);
475
476 HRESULT hr = S_OK;
477 SIZE_T cb = cbStream;
478 errno_t err = 0;
479
480 // make sure we have a buffer with sufficient space
481 hr = EnsureBufferSize(ppbBuffer, *piBuffer + cbStream + sizeof(SIZE_T));
482 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
483
484 // copy byte count to buffer
485 *(SIZE_T*)(*ppbBuffer + *piBuffer) = cb;
486 *piBuffer += sizeof(SIZE_T);
487
488 // copy data to buffer
489 err = memcpy_s(*ppbBuffer + *piBuffer, cbStream, pbStream, cbStream);
490 if (err)
491 {
492 BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write stream to buffer, error: %d", err);
493 }
494
495 *piBuffer += cbStream;
496
497LExit:
498 return hr;
499}
500
501
502// helper functions
503
504static HRESULT EnsureBufferSize(
505 __deref_inout_bcount(cbSize) BYTE** ppbBuffer,
506 __in SIZE_T cbSize
507 )
508{
509 HRESULT hr = S_OK;
510 SIZE_T cbTarget = ((cbSize / BUFFER_INCREMENT) + 1) * BUFFER_INCREMENT;
511
512 if (*ppbBuffer)
513 {
514 if (MemSize(*ppbBuffer) < cbTarget)
515 {
516 LPVOID pv = MemReAlloc(*ppbBuffer, cbTarget, TRUE);
517 BuffExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to reallocate buffer.");
518 *ppbBuffer = (BYTE*)pv;
519 }
520 }
521 else
522 {
523 *ppbBuffer = (BYTE*)MemAlloc(cbTarget, TRUE);
524 BuffExitOnNull(*ppbBuffer, hr, E_OUTOFMEMORY, "Failed to allocate buffer.");
525 }
526
527LExit:
528 return hr;
529}