main
cpp 714 lines 18.8 KB
Raw
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
28 static HRESULT EnsureBufferSize(
29 __deref_inout_bcount(cbSize) BYTE** ppbBuffer,
30 __in SIZE_T cbSize
31 );
32
33
34 // functions
35
36 // Buffer read functions
37
38 extern "C" HRESULT BuffReadNumber(
39 __in_bcount(cbBuffer) const BYTE* pbBuffer,
40 __in SIZE_T cbBuffer,
41 __inout SIZE_T* piBuffer,
42 __out DWORD* pdw
43 )
44 {
45 Assert(pbBuffer);
46 Assert(piBuffer);
47 Assert(pdw);
48
49 HRESULT hr = S_OK;
50 SIZE_T cbAvailable = 0;
51
52 // get availiable data size
53 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
54 BuffExitOnRootFailure(hr, "Failed to calculate available data size.");
55
56 // verify buffer size
57 if (sizeof(DWORD) > cbAvailable)
58 {
59 hr = E_INVALIDARG;
60 BuffExitOnRootFailure(hr, "Buffer too small to read number. cbAvailable: %u", cbAvailable);
61 }
62
63 *pdw = *(const DWORD*)(pbBuffer + *piBuffer);
64 *piBuffer += sizeof(DWORD);
65
66 LExit:
67 return hr;
68 }
69
70 extern "C" HRESULT BuffReadNumber64(
71 __in_bcount(cbBuffer) const BYTE * pbBuffer,
72 __in SIZE_T cbBuffer,
73 __inout SIZE_T* piBuffer,
74 __out DWORD64* pdw64
75 )
76 {
77 Assert(pbBuffer);
78 Assert(piBuffer);
79 Assert(pdw64);
80
81 HRESULT hr = S_OK;
82 SIZE_T cbAvailable = 0;
83
84 // get availiable data size
85 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
86 BuffExitOnRootFailure(hr, "Failed to calculate available data size.");
87
88 // verify buffer size
89 if (sizeof(DWORD64) > cbAvailable)
90 {
91 hr = E_INVALIDARG;
92 BuffExitOnRootFailure(hr, "Buffer too small to read 64-bit number. cbAvailable: %u", cbAvailable);
93 }
94
95 *pdw64 = *(const DWORD64*)(pbBuffer + *piBuffer);
96 *piBuffer += sizeof(DWORD64);
97
98 LExit:
99 return hr;
100 }
101
102 extern "C" HRESULT BuffReadPointer(
103 __in_bcount(cbBuffer) const BYTE* pbBuffer,
104 __in SIZE_T cbBuffer,
105 __inout SIZE_T* piBuffer,
106 __out DWORD_PTR* pdw64
107 )
108 {
109 Assert(pbBuffer);
110 Assert(piBuffer);
111 Assert(pdw64);
112
113 HRESULT hr = S_OK;
114 SIZE_T cbAvailable = 0;
115
116 // get availiable data size
117 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
118 BuffExitOnRootFailure(hr, "Failed to calculate available data size.");
119
120 // verify buffer size
121 if (sizeof(DWORD_PTR) > cbAvailable)
122 {
123 hr = E_INVALIDARG;
124 BuffExitOnRootFailure(hr, "Buffer too small to read pointer. cbAvailable: %u", cbAvailable);
125 }
126
127 *pdw64 = *(const DWORD_PTR*)(pbBuffer + *piBuffer);
128 *piBuffer += sizeof(DWORD_PTR);
129
130 LExit:
131 return hr;
132 }
133
134 extern "C" HRESULT BuffReadString(
135 __in_bcount(cbBuffer) const BYTE* pbBuffer,
136 __in SIZE_T cbBuffer,
137 __inout SIZE_T* piBuffer,
138 __deref_out_z LPWSTR* pscz
139 )
140 {
141 Assert(pbBuffer);
142 Assert(piBuffer);
143 Assert(pscz);
144
145 HRESULT hr = S_OK;
146 DWORD cch = 0;
147 SIZE_T cb = 0;
148 SIZE_T cbAvailable = 0;
149
150 // get availiable data size
151 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
152 BuffExitOnRootFailure(hr, "Failed to calculate available data size for character count.");
153
154 // verify buffer size
155 if (sizeof(DWORD) > cbAvailable)
156 {
157 hr = E_INVALIDARG;
158 BuffExitOnRootFailure(hr, "Buffer too small to read size of string. cbAvailable: %u", cbAvailable);
159 }
160
161 // read character count
162 cch = *(const DWORD*)(pbBuffer + *piBuffer);
163
164 hr = ::SIZETMult(cch, sizeof(WCHAR), &cb);
165 BuffExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size");
166
167 hr = ::SIZETAdd(*piBuffer, sizeof(cch), piBuffer);
168 BuffExitOnRootFailure(hr, "Overflow while adding to calculate buffer size");
169
170 // get availiable data size
171 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
172 BuffExitOnRootFailure(hr, "Failed to calculate available data size for character buffer.");
173
174 // verify buffer size
175 if (cb > cbAvailable)
176 {
177 hr = E_INVALIDARG;
178 BuffExitOnRootFailure(hr, "Buffer too small to read string data. cbAvailable: %u, cb: %u", cbAvailable, cb);
179 }
180
181 // copy character data
182 hr = StrAllocString(pscz, cch ? (LPCWSTR)(pbBuffer + *piBuffer) : L"", cch);
183 BuffExitOnFailure(hr, "Failed to copy character data.");
184
185 *piBuffer += cb;
186
187 LExit:
188 return hr;
189 }
190
191 extern "C" HRESULT BuffReadStringAnsi(
192 __in_bcount(cbBuffer) const BYTE* pbBuffer,
193 __in SIZE_T cbBuffer,
194 __inout SIZE_T* piBuffer,
195 __deref_out_z LPSTR* pscz
196 )
197 {
198 Assert(pbBuffer);
199 Assert(piBuffer);
200 Assert(pscz);
201
202 HRESULT hr = S_OK;
203 DWORD cch = 0;
204 SIZE_T cb = 0;
205 SIZE_T cbAvailable = 0;
206
207 // get availiable data size
208 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
209 BuffExitOnRootFailure(hr, "Failed to calculate available data size for character count.");
210
211 // verify buffer size
212 if (sizeof(DWORD) > cbAvailable)
213 {
214 hr = E_INVALIDARG;
215 BuffExitOnRootFailure(hr, "Buffer too small to read size of ANSI string. cbAvailable: %u", cbAvailable);
216 }
217
218 // read character count
219 cch = *(const DWORD*)(pbBuffer + *piBuffer);
220
221 hr = ::SIZETMult(cch, sizeof(CHAR), &cb);
222 BuffExitOnRootFailure(hr, "Overflow while multiplying to calculate buffer size");
223
224 hr = ::SIZETAdd(*piBuffer, sizeof(cch), piBuffer);
225 BuffExitOnRootFailure(hr, "Overflow while adding to calculate buffer size");
226
227 // get availiable data size
228 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
229 BuffExitOnRootFailure(hr, "Failed to calculate available data size for character buffer.");
230
231 // verify buffer size
232 if (cb > cbAvailable)
233 {
234 hr = E_INVALIDARG;
235 BuffExitOnRootFailure(hr, "Buffer too small to read ANSI string data. cbAvailable: %u, cb: %u", cbAvailable, cb);
236 }
237
238 // copy character data
239 hr = StrAnsiAllocStringAnsi(pscz, cch ? (LPCSTR)(pbBuffer + *piBuffer) : "", cch);
240 BuffExitOnFailure(hr, "Failed to copy character data.");
241
242 *piBuffer += cb;
243
244 LExit:
245 return hr;
246 }
247
248 extern "C" HRESULT BuffReadStream(
249 __in_bcount(cbBuffer) const BYTE* pbBuffer,
250 __in SIZE_T cbBuffer,
251 __inout SIZE_T* piBuffer,
252 __deref_inout_bcount(*pcbStream) BYTE** ppbStream,
253 __out SIZE_T* pcbStream
254 )
255 {
256 Assert(pbBuffer);
257 Assert(piBuffer);
258 Assert(ppbStream);
259 Assert(pcbStream);
260
261 HRESULT hr = S_OK;
262 SIZE_T cb = 0;
263 SIZE_T cbAvailable = 0;
264 errno_t err = 0;
265
266 // get availiable data size
267 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
268 BuffExitOnRootFailure(hr, "Failed to calculate available data size for stream size.");
269
270 // verify buffer size
271 if (sizeof(DWORD) > cbAvailable)
272 {
273 hr = E_INVALIDARG;
274 BuffExitOnRootFailure(hr, "Buffer too small to read size of stream. cbAvailable: %u, cb: %u", cbAvailable, cb);
275 }
276
277 // read stream size
278 cb = *(const DWORD*)(pbBuffer + *piBuffer);
279 *piBuffer += sizeof(DWORD);
280
281 // get availiable data size
282 hr = ::SIZETSub(cbBuffer, *piBuffer, &cbAvailable);
283 BuffExitOnRootFailure(hr, "Failed to calculate available data size for stream buffer.");
284
285 // verify buffer size
286 if (cb > cbAvailable)
287 {
288 hr = E_INVALIDARG;
289 BuffExitOnRootFailure(hr, "Buffer too small to read stream data. cbAvailable: %u, cb: %u", cbAvailable, cb);
290 }
291
292 // allocate buffer
293 *ppbStream = (BYTE*)MemAlloc(cb, TRUE);
294 BuffExitOnNull(*ppbStream, hr, E_OUTOFMEMORY, "Failed to allocate stream.");
295
296 // read stream data
297 err = memcpy_s(*ppbStream, cbBuffer - *piBuffer, pbBuffer + *piBuffer, cb);
298 if (err)
299 {
300 BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to read stream from buffer, error: %d", err);
301 }
302
303 *piBuffer += cb;
304
305 // return stream size
306 *pcbStream = cb;
307
308 LExit:
309 return hr;
310 }
311
312
313 // Buffer Reader read functions
314
315 extern "C" HRESULT BuffReaderReadNumber(
316 __in BUFF_READER* pReader,
317 __out DWORD* pdw
318 )
319 {
320 return BuffReadNumber(pReader->pbData, pReader->cbData, &pReader->iBuffer, pdw);
321 }
322
323 extern "C" HRESULT BuffReaderReadNumber64(
324 __in BUFF_READER* pReader,
325 __out DWORD64* pdw64
326 )
327 {
328 return BuffReadNumber64(pReader->pbData, pReader->cbData, &pReader->iBuffer, pdw64);
329 }
330
331 extern "C" HRESULT BuffReaderReadPointer(
332 __in BUFF_READER* pReader,
333 __out DWORD_PTR* pdw
334 )
335 {
336 return BuffReadPointer(pReader->pbData, pReader->cbData, &pReader->iBuffer, pdw);
337 }
338
339 extern "C" HRESULT BuffReaderReadString(
340 __in BUFF_READER* pReader,
341 __deref_out_z LPWSTR* pscz
342 )
343 {
344 return BuffReadString(pReader->pbData, pReader->cbData, &pReader->iBuffer, pscz);
345 }
346
347 extern "C" HRESULT BuffReaderReadStringAnsi(
348 __in BUFF_READER* pReader,
349 __deref_out_z LPSTR* pscz
350 )
351 {
352 return BuffReadStringAnsi(pReader->pbData, pReader->cbData, &pReader->iBuffer, pscz);
353 }
354
355
356 // Buffer write functions
357
358 extern "C" HRESULT BuffWriteNumber(
359 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
360 __inout SIZE_T* piBuffer,
361 __in DWORD dw
362 )
363 {
364 Assert(ppbBuffer);
365 Assert(piBuffer);
366
367 HRESULT hr = S_OK;
368
369 // make sure we have a buffer with sufficient space
370 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD));
371 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
372
373 // copy data to buffer
374 *reinterpret_cast<DWORD*>(*ppbBuffer + *piBuffer) = dw;
375 *piBuffer += sizeof(DWORD);
376
377 LExit:
378 return hr;
379 }
380
381 extern "C" HRESULT BuffWriteNumber64(
382 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
383 __inout SIZE_T* piBuffer,
384 __in DWORD64 dw64
385 )
386 {
387 Assert(ppbBuffer);
388 Assert(piBuffer);
389
390 HRESULT hr = S_OK;
391
392 // make sure we have a buffer with sufficient space
393 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD64));
394 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
395
396 // copy data to buffer
397 *(DWORD64*)(*ppbBuffer + *piBuffer) = dw64;
398 *piBuffer += sizeof(DWORD64);
399
400 LExit:
401 return hr;
402 }
403
404 extern "C" HRESULT BuffWritePointer(
405 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
406 __inout SIZE_T* piBuffer,
407 __in DWORD_PTR dw
408 )
409 {
410 Assert(ppbBuffer);
411 Assert(piBuffer);
412
413 HRESULT hr = S_OK;
414
415 // make sure we have a buffer with sufficient space
416 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD_PTR));
417 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
418
419 // copy data to buffer
420 *(DWORD_PTR*)(*ppbBuffer + *piBuffer) = dw;
421 *piBuffer += sizeof(DWORD_PTR);
422
423 LExit:
424 return hr;
425 }
426
427 extern "C" HRESULT BuffWriteString(
428 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
429 __inout SIZE_T* piBuffer,
430 __in_z_opt LPCWSTR scz
431 )
432 {
433 Assert(ppbBuffer);
434 Assert(piBuffer);
435
436 HRESULT hr = S_OK;
437 DWORD cch = 0; // This value *MUST* be treated as a DWORD to be marshalled over the pipe between 32-bit and 64-bit process the same.
438 SIZE_T cb = 0;
439 errno_t err = 0;
440
441 if (scz)
442 {
443 size_t size = 0;
444
445 hr = ::StringCchLengthW(scz, STRSAFE_MAX_CCH, &size);
446 BuffExitOnRootFailure(hr, "Failed to get string size.");
447
448 if (size > DWORD_MAX)
449 {
450 hr = E_INVALIDARG;
451 BuffExitOnRootFailure(hr, "String too long to write to buffer.");
452 }
453
454 cch = static_cast<DWORD>(size);
455 }
456
457 cb = cch * sizeof(WCHAR);
458
459 // make sure we have a buffer with sufficient space for the length plus the string without terminator.
460 hr = EnsureBufferSize(ppbBuffer, *piBuffer + sizeof(DWORD) + cb);
461 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
462
463 // copy the character count to buffer as a DWORD
464 *reinterpret_cast<DWORD*>(*ppbBuffer + *piBuffer) = cch;
465 *piBuffer += sizeof(DWORD);
466
467 // copy data to buffer
468 err = memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb);
469 if (err)
470 {
471 BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write string to buffer: '%ls', error: %d", scz, err);
472 }
473
474 *piBuffer += cb;
475
476 LExit:
477 return hr;
478 }
479
480 extern "C" HRESULT BuffWriteStringAnsi(
481 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
482 __inout SIZE_T* piBuffer,
483 __in_z_opt LPCSTR scz
484 )
485 {
486 Assert(ppbBuffer);
487 Assert(piBuffer);
488
489 HRESULT hr = S_OK;
490 DWORD cch = 0; // This value *MUST* be treated as a DWORD to be marshalled over the pipe between 32-bit and 64-bit process the same.
491 SIZE_T cb = 0;
492 errno_t err = 0;
493
494 if (scz)
495 {
496 size_t size = 0;
497
498 hr = ::StringCchLengthA(scz, STRSAFE_MAX_CCH, &size);
499 BuffExitOnRootFailure(hr, "Failed to get ANSI string size.")
500
501 if (size > DWORD_MAX)
502 {
503 hr = E_INVALIDARG;
504 BuffExitOnRootFailure(hr, "ANSI string too long to write to buffer.");
505 }
506
507 cch = static_cast<DWORD>(size);
508 }
509
510 cb = cch * sizeof(CHAR);
511
512 // make sure we have a buffer with sufficient space
513 hr = EnsureBufferSize(ppbBuffer, *piBuffer + (sizeof(DWORD) + cb));
514 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
515
516 // copy character count to buffer
517 *reinterpret_cast<DWORD*>(*ppbBuffer + *piBuffer) = cch;
518 *piBuffer += sizeof(DWORD);
519
520 // copy data to buffer
521 err = memcpy_s(*ppbBuffer + *piBuffer, cb, scz, cb);
522 if (err)
523 {
524 BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write string to buffer: '%hs', error: %d", scz, err);
525 }
526
527 *piBuffer += cb;
528
529 LExit:
530 return hr;
531 }
532
533 extern "C" HRESULT BuffWriteStream(
534 __deref_inout_bcount(*piBuffer) BYTE** ppbBuffer,
535 __inout SIZE_T* piBuffer,
536 __in_bcount(cbStream) const BYTE* pbStream,
537 __in SIZE_T cbStream
538 )
539 {
540 Assert(ppbBuffer);
541 Assert(piBuffer);
542 Assert(pbStream);
543
544 HRESULT hr = S_OK;
545 DWORD cb = 0;
546 errno_t err = 0;
547
548 if (cbStream > DWORD_MAX)
549 {
550 hr = E_INVALIDARG;
551 BuffExitOnRootFailure(hr, "Stream too large to write to buffer.");
552 }
553
554 cb = static_cast<DWORD>(cbStream);
555
556 // make sure we have a buffer with sufficient space
557 hr = EnsureBufferSize(ppbBuffer, *piBuffer + cbStream + sizeof(DWORD));
558 BuffExitOnFailure(hr, "Failed to ensure buffer size.");
559
560 // copy byte count to buffer
561 *reinterpret_cast<DWORD*>(*ppbBuffer + *piBuffer) = cb;
562 *piBuffer += sizeof(DWORD);
563
564 if (cbStream)
565 {
566 // copy data to buffer
567 err = memcpy_s(*ppbBuffer + *piBuffer, cbStream, pbStream, cbStream);
568 if (err)
569 {
570 BuffExitOnRootFailure(hr = E_INVALIDARG, "Failed to write stream to buffer, error: %d", err);
571 }
572
573 *piBuffer += cbStream;
574 }
575
576 LExit:
577 return hr;
578 }
579
580 // Buffer-based write functions
581
582 extern "C" HRESULT BuffWriteNumberToBuffer(
583 __in BUFF_BUFFER* pBuffer,
584 __out DWORD dw
585 )
586 {
587 return BuffWriteNumber(&pBuffer->pbData, &pBuffer->cbData, dw);
588 }
589
590 extern "C" HRESULT BuffWriteNumber64ToBuffer(
591 __in BUFF_BUFFER* pBuffer,
592 __out DWORD64 dw64
593 )
594 {
595 return BuffWriteNumber64(&pBuffer->pbData, &pBuffer->cbData, dw64);
596 }
597
598 extern "C" HRESULT BuffWritePointerToBuffer(
599 __in BUFF_BUFFER* pBuffer,
600 __out DWORD_PTR dw
601 )
602 {
603 return BuffWritePointer(&pBuffer->pbData, &pBuffer->cbData, dw);
604 }
605
606 extern "C" HRESULT BuffWriteStringToBuffer(
607 __in BUFF_BUFFER* pBuffer,
608 __in_z_opt LPCWSTR scz
609 )
610 {
611 return BuffWriteString(&pBuffer->pbData, &pBuffer->cbData, scz);
612 }
613
614 extern "C" HRESULT BuffWriteStringAnsiToBuffer(
615 __in BUFF_BUFFER* pBuffer,
616 __in_z_opt LPCSTR scz
617 )
618 {
619 return BuffWriteStringAnsi(&pBuffer->pbData, &pBuffer->cbData, scz);
620 }
621
622 extern "C" HRESULT BuffWriteStreamToBuffer(
623 __in BUFF_BUFFER* pBuffer,
624 __in_bcount(cbStream) const BYTE* pbStream,
625 __in SIZE_T cbStream
626 )
627 {
628 return BuffWriteStream(&pBuffer->pbData, &pBuffer->cbData, pbStream, cbStream);
629 }
630
631 // Buffer Writer write functions
632
633 extern "C" HRESULT BuffWriterWriteNumber(
634 __in BUFF_WRITER* pWriter,
635 __out DWORD dw
636 )
637 {
638 return BuffWriteNumber(pWriter->ppbData, pWriter->pcbData, dw);
639 }
640
641 extern "C" HRESULT BuffWriterWriteNumber64(
642 __in BUFF_WRITER* pWriter,
643 __out DWORD64 dw64
644 )
645 {
646 return BuffWriteNumber64(pWriter->ppbData, pWriter->pcbData, dw64);
647 }
648
649 extern "C" HRESULT BuffWriterWritePointer(
650 __in BUFF_WRITER* pWriter,
651 __out DWORD_PTR dw
652 )
653 {
654 return BuffWritePointer(pWriter->ppbData, pWriter->pcbData, dw);
655 }
656
657 extern "C" HRESULT BuffWriterWriteString(
658 __in BUFF_WRITER* pWriter,
659 __in_z_opt LPCWSTR scz
660 )
661 {
662 return BuffWriteString(pWriter->ppbData, pWriter->pcbData, scz);
663 }
664
665 extern "C" HRESULT BuffWriterWriteStringAnsi(
666 __in BUFF_WRITER* pWriter,
667 __in_z_opt LPCSTR scz
668 )
669 {
670 return BuffWriteStringAnsi(pWriter->ppbData, pWriter->pcbData, scz);
671 }
672
673 extern "C" HRESULT BuffWriterWriteStream(
674 __in BUFF_WRITER* pWriter,
675 __in_bcount(cbStream) const BYTE* pbStream,
676 __in SIZE_T cbStream
677 )
678 {
679 return BuffWriteStream(pWriter->ppbData, pWriter->pcbData, pbStream, cbStream);
680 }
681
682
683 // helper functions
684
685 static HRESULT EnsureBufferSize(
686 __deref_inout_bcount(cbSize) BYTE** ppbBuffer,
687 __in SIZE_T cbSize
688 )
689 {
690 HRESULT hr = S_OK;
691 SIZE_T cbTarget = ((cbSize / BUFFER_INCREMENT) + 1) * BUFFER_INCREMENT;
692 SIZE_T cbCurrent = 0;
693
694 if (*ppbBuffer)
695 {
696 hr = MemSizeChecked(*ppbBuffer, &cbCurrent);
697 BuffExitOnFailure(hr, "Failed to get current buffer size.");
698
699 if (cbCurrent < cbTarget)
700 {
701 LPVOID pv = MemReAlloc(*ppbBuffer, cbTarget, TRUE);
702 BuffExitOnNull(pv, hr, E_OUTOFMEMORY, "Failed to reallocate buffer.");
703 *ppbBuffer = (BYTE*)pv;
704 }
705 }
706 else
707 {
708 *ppbBuffer = (BYTE*)MemAlloc(cbTarget, TRUE);
709 BuffExitOnNull(*ppbBuffer, hr, E_OUTOFMEMORY, "Failed to allocate buffer.");
710 }
711
712 LExit:
713 return hr;
714 }