FreeRDP
include/winpr/stream.h
1 /*
2  * WinPR: Windows Portable Runtime
3  * Stream Utils
4  *
5  * Copyright 2011 Vic Lee
6  * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
7  * Copyright 2017 Armin Novak <armin.novak@thincast.com>
8  * Copyright 2017 Thincast Technologies GmbH
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 
23 #ifndef WINPR_UTILS_STREAM_H
24 #define WINPR_UTILS_STREAM_H
25 
26 #include <winpr/winpr.h>
27 #include <winpr/wtypes.h>
28 #include <winpr/endian.h>
29 #include <winpr/synch.h>
30 #include <winpr/assert.h>
31 
32 #ifdef __cplusplus
33 extern "C"
34 {
35 #endif
36 
37  typedef struct s_wStreamPool wStreamPool;
38 
39  typedef struct
40  {
41  BYTE* buffer;
42  BYTE* pointer;
43  size_t length;
44  size_t capacity;
45 
46  DWORD count;
47  wStreamPool* pool;
48  BOOL isAllocatedStream;
49  BOOL isOwner;
50  } wStream;
51 
52  static INLINE size_t Stream_Capacity(const wStream* _s);
53  WINPR_API size_t Stream_GetRemainingCapacity(const wStream* _s);
54  WINPR_API size_t Stream_GetRemainingLength(const wStream* _s);
55 
56  WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size);
57  WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size);
58 
59 #ifdef __cplusplus
60 #define WINPR_STREAM_CAST(t, val) static_cast<t>(val)
61 #else
62 #define WINPR_STREAM_CAST(t, val) (t)(val)
63 #endif
64 
65 #define Stream_CheckAndLogRequiredCapacityOfSize(tag, s, nmemb, size) \
66  Stream_CheckAndLogRequiredCapacityEx(tag, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
67  __func__, __FILE__, (size_t)__LINE__)
68 #define Stream_CheckAndLogRequiredCapacity(tag, s, len) \
69  Stream_CheckAndLogRequiredCapacityOfSize((tag), (s), (len), 1)
70 
71  WINPR_API BOOL Stream_CheckAndLogRequiredCapacityEx(const char* tag, DWORD level, wStream* s,
72  size_t nmemb, size_t size, const char* fmt,
73  ...);
74  WINPR_API BOOL Stream_CheckAndLogRequiredCapacityExVa(const char* tag, DWORD level, wStream* s,
75  size_t nmemb, size_t size,
76  const char* fmt, va_list args);
77 
78 #define Stream_CheckAndLogRequiredCapacityOfSizeWLog(log, s, nmemb, size) \
79  Stream_CheckAndLogRequiredCapacityWLogEx(log, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
80  __func__, __FILE__, (size_t)__LINE__)
81 
82 #define Stream_CheckAndLogRequiredCapacityWLog(log, s, len) \
83  Stream_CheckAndLogRequiredCapacityOfSizeWLog((log), (s), (len), 1)
84 
85  WINPR_API BOOL Stream_CheckAndLogRequiredCapacityWLogEx(wLog* log, DWORD level, wStream* s,
86  size_t nmemb, size_t size,
87  const char* fmt, ...);
88  WINPR_API BOOL Stream_CheckAndLogRequiredCapacityWLogExVa(wLog* log, DWORD level, wStream* s,
89  size_t nmemb, size_t size,
90  const char* fmt, va_list args);
91 
92  WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
93 
94  WINPR_ATTR_MALLOC(Stream_Free, 1)
95  WINPR_API wStream* Stream_New(BYTE* buffer, size_t size);
96  WINPR_API wStream* Stream_StaticConstInit(wStream* s, const BYTE* buffer, size_t size);
97  WINPR_API wStream* Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
98 
99 #define Stream_CheckAndLogRequiredLengthOfSize(tag, s, nmemb, size) \
100  Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
101  __func__, __FILE__, (size_t)__LINE__)
102 #define Stream_CheckAndLogRequiredLength(tag, s, len) \
103  Stream_CheckAndLogRequiredLengthOfSize(tag, s, len, 1)
104 
105  WINPR_API BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s,
106  size_t nmemb, size_t size, const char* fmt,
107  ...);
108  WINPR_API BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s,
109  size_t nmemb, size_t size, const char* fmt,
110  va_list args);
111 
112 #define Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, nmemb, size) \
113  Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
114  __func__, __FILE__, (size_t)__LINE__)
115 #define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \
116  Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, len, 1)
117 
118  WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s,
119  size_t nmemb, size_t size,
120  const char* fmt, ...);
121  WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s,
122  size_t nmemb, size_t size,
123  const char* fmt, va_list args);
124 
125  static INLINE void Stream_Seek(wStream* s, size_t _offset)
126  {
127  WINPR_ASSERT(s);
128  WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= _offset);
129  s->pointer += (_offset);
130  }
131 
132  static INLINE void Stream_Rewind(wStream* s, size_t _offset)
133  {
134  size_t cur = 0;
135  WINPR_ASSERT(s);
136  WINPR_ASSERT(s->buffer <= s->pointer);
137  cur = WINPR_STREAM_CAST(size_t, s->pointer - s->buffer);
138  WINPR_ASSERT(cur >= _offset);
139  if (cur >= _offset)
140  s->pointer -= (_offset);
141  else
142  s->pointer = s->buffer;
143  }
144 
145  static INLINE UINT8 stream_read_u8(wStream* _s, BOOL seek)
146  {
147  WINPR_ASSERT(_s);
148  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= sizeof(UINT8));
149 
150  const UINT8 v = *(_s)->pointer;
151  if (seek)
152  Stream_Seek(_s, sizeof(UINT8));
153  return v;
154  }
155 
156  static INLINE INT8 stream_read_i8(wStream* _s, BOOL seek)
157  {
158  const UINT8 v = stream_read_u8(_s, seek);
159  return WINPR_STREAM_CAST(INT8, v);
160  }
161 
162  static INLINE UINT16 stream_read_u16_le(wStream* _s, BOOL seek)
163  {
164  const size_t typesize = sizeof(UINT16);
165  WINPR_ASSERT(_s);
166  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
167 
168  UINT16 v = 0;
169  for (size_t x = 0; x < typesize; x++)
170  {
171  v <<= 8;
172  v |= (_s)->pointer[typesize - x - 1];
173  }
174  if (seek)
175  Stream_Seek(_s, typesize);
176  return v;
177  }
178 
179  static INLINE UINT16 stream_read_u16_be(wStream* _s, BOOL seek)
180  {
181  const size_t typesize = sizeof(UINT16);
182  WINPR_ASSERT(_s);
183  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
184 
185  UINT16 v = 0;
186  for (size_t x = 0; x < typesize; x++)
187  {
188  v <<= 8;
189  v |= (_s)->pointer[x];
190  }
191  if (seek)
192  Stream_Seek(_s, typesize);
193  return v;
194  }
195 
196  static INLINE INT16 stream_read_i16_le(wStream* _s, BOOL seek)
197  {
198  const UINT16 v = stream_read_u16_le(_s, seek);
199  return WINPR_STREAM_CAST(INT16, v);
200  }
201 
202  static INLINE INT16 stream_read_i16_be(wStream* _s, BOOL seek)
203  {
204  const UINT16 v = stream_read_u16_be(_s, seek);
205  return WINPR_STREAM_CAST(INT16, v);
206  }
207 
208  static INLINE UINT32 stream_read_u32_le(wStream* _s, BOOL seek)
209  {
210  const size_t typesize = sizeof(UINT32);
211  WINPR_ASSERT(_s);
212  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
213 
214  UINT32 v = 0;
215  for (size_t x = 0; x < typesize; x++)
216  {
217  v <<= 8;
218  v |= (_s)->pointer[typesize - x - 1];
219  }
220  if (seek)
221  Stream_Seek(_s, typesize);
222  return v;
223  }
224 
225  static INLINE UINT32 stream_read_u32_be(wStream* _s, BOOL seek)
226  {
227  const size_t typesize = sizeof(UINT32);
228  WINPR_ASSERT(_s);
229  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
230 
231  UINT32 v = 0;
232  for (size_t x = 0; x < typesize; x++)
233  {
234  v <<= 8;
235  v |= (_s)->pointer[x];
236  }
237  if (seek)
238  Stream_Seek(_s, typesize);
239  return v;
240  }
241 
242  static INLINE INT32 stream_read_i32_le(wStream* _s, BOOL seek)
243  {
244  const UINT32 v = stream_read_u32_le(_s, seek);
245  return WINPR_STREAM_CAST(INT32, v);
246  }
247 
248  static INLINE INT32 stream_read_i32_be(wStream* _s, BOOL seek)
249  {
250  const UINT32 v = stream_read_u32_be(_s, seek);
251  return WINPR_STREAM_CAST(INT32, v);
252  }
253 
254  static INLINE UINT64 stream_read_u64_le(wStream* _s, BOOL seek)
255  {
256  const size_t typesize = sizeof(UINT64);
257  WINPR_ASSERT(_s);
258  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
259 
260  UINT64 v = 0;
261  for (size_t x = 0; x < typesize; x++)
262  {
263  v <<= 8;
264  v |= (_s)->pointer[typesize - x - 1];
265  }
266  if (seek)
267  Stream_Seek(_s, typesize);
268  return v;
269  }
270 
271  static INLINE UINT64 stream_read_u64_be(wStream* _s, BOOL seek)
272  {
273  const size_t typesize = sizeof(UINT64);
274  WINPR_ASSERT(_s);
275  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
276 
277  UINT64 v = 0;
278  for (size_t x = 0; x < typesize; x++)
279  {
280  v <<= 8;
281  v |= (_s)->pointer[x];
282  }
283  if (seek)
284  Stream_Seek(_s, typesize);
285  return v;
286  }
287 
288  static INLINE INT64 stream_read_i64_le(wStream* _s, BOOL seek)
289  {
290  const UINT64 v = stream_read_u64_le(_s, seek);
291  return WINPR_STREAM_CAST(INT64, v);
292  }
293 
294  static INLINE INT64 stream_read_i64_be(wStream* _s, BOOL seek)
295  {
296  const UINT64 v = stream_read_u64_be(_s, seek);
297  return WINPR_STREAM_CAST(INT64, v);
298  }
299 
306  static INLINE UINT8 Stream_Get_UINT8(wStream* _s)
307  {
308  return stream_read_u8(_s, TRUE);
309  }
310 
317  static INLINE INT8 Stream_Get_INT8(wStream* _s)
318  {
319  return stream_read_i8(_s, TRUE);
320  }
321 
328  static INLINE UINT16 Stream_Get_UINT16(wStream* _s)
329  {
330  return stream_read_u16_le(_s, TRUE);
331  }
332 
339  static INLINE INT16 Stream_Get_INT16(wStream* _s)
340  {
341  return stream_read_i16_le(_s, TRUE);
342  }
343 
350  static INLINE UINT16 Stream_Get_UINT16_BE(wStream* _s)
351  {
352  return stream_read_u16_be(_s, TRUE);
353  }
354 
361  static INLINE INT16 Stream_Get_INT16_BE(wStream* _s)
362  {
363  return stream_read_i16_be(_s, TRUE);
364  }
365 
372  static INLINE UINT32 Stream_Get_UINT32(wStream* _s)
373  {
374  return stream_read_u32_le(_s, TRUE);
375  }
376 
383  static INLINE INT32 Stream_Get_INT32(wStream* _s)
384  {
385  return stream_read_i32_le(_s, TRUE);
386  }
387 
394  static INLINE UINT32 Stream_Get_UINT32_BE(wStream* _s)
395  {
396  return stream_read_u32_be(_s, TRUE);
397  }
398 
405  static INLINE INT32 Stream_Get_INT32_BE(wStream* _s)
406  {
407  return stream_read_i32_be(_s, TRUE);
408  }
409 
416  static INLINE UINT64 Stream_Get_UINT64(wStream* _s)
417  {
418  return stream_read_u64_le(_s, TRUE);
419  }
420 
427  static INLINE INT64 Stream_Get_INT64(wStream* _s)
428  {
429  return stream_read_i64_le(_s, TRUE);
430  }
431 
438  static INLINE UINT64 Stream_Get_UINT64_BE(wStream* _s)
439  {
440  return stream_read_u64_be(_s, TRUE);
441  }
442 
449  static INLINE INT64 Stream_Get_INT64_BE(wStream* _s)
450  {
451  return stream_read_i64_be(_s, TRUE);
452  }
453 
460  static INLINE UINT8 Stream_Peek_Get_UINT8(wStream* _s)
461  {
462  return stream_read_u8(_s, FALSE);
463  }
464 
471  static INLINE INT8 Stream_Peek_Get_INT8(wStream* _s)
472  {
473  return stream_read_i8(_s, FALSE);
474  }
475 
482  static INLINE UINT16 Stream_Peek_Get_UINT16(wStream* _s)
483  {
484  return stream_read_u16_le(_s, FALSE);
485  }
486 
493  static INLINE INT16 Stream_Peek_Get_INT16(wStream* _s)
494  {
495  return stream_read_i16_le(_s, FALSE);
496  }
497 
504  static INLINE UINT16 Stream_Peek_Get_UINT16_BE(wStream* _s)
505  {
506  return stream_read_u16_be(_s, FALSE);
507  }
508 
515  static INLINE INT16 Stream_Peek_Get_INT16_BE(wStream* _s)
516  {
517  return stream_read_i16_be(_s, FALSE);
518  }
519 
526  static INLINE UINT32 Stream_Peek_Get_UINT32(wStream* _s)
527  {
528  return stream_read_u32_le(_s, FALSE);
529  }
530 
537  static INLINE INT32 Stream_Peek_Get_INT32(wStream* _s)
538  {
539  return stream_read_i32_le(_s, FALSE);
540  }
541 
548  static INLINE UINT32 Stream_Peek_Get_UINT32_BE(wStream* _s)
549  {
550  return stream_read_u32_be(_s, FALSE);
551  }
552 
559  static INLINE INT32 Stream_Peek_Get_INT32_BE(wStream* _s)
560  {
561  return stream_read_i32_be(_s, FALSE);
562  }
563 
570  static INLINE UINT64 Stream_Peek_Get_UINT64(wStream* _s)
571  {
572  return stream_read_u64_le(_s, FALSE);
573  }
574 
581  static INLINE INT64 Stream_Peek_Get_INT64(wStream* _s)
582  {
583  return stream_read_i64_le(_s, FALSE);
584  }
585 
592  static INLINE UINT64 Stream_Peek_Get_UINT64_BE(wStream* _s)
593  {
594  return stream_read_u64_be(_s, FALSE);
595  }
596 
603  static INLINE INT64 Stream_Peek_Get_INT64_BE(wStream* _s)
604  {
605  return stream_read_i64_be(_s, FALSE);
606  }
607 
608 #define Stream_Read_UINT8(_s, _v) \
609  do \
610  { \
611  _v = stream_read_u8(_s, TRUE); \
612  } while (0)
613 
614 #define Stream_Read_INT8(_s, _v) \
615  do \
616  { \
617  _v = stream_read_i8(_s, TRUE); \
618  } while (0)
619 
620 #define Stream_Read_UINT16(_s, _v) \
621  do \
622  { \
623  _v = stream_read_u16_le(_s, TRUE); \
624  } while (0)
625 
626 #define Stream_Read_INT16(_s, _v) \
627  do \
628  { \
629  _v = stream_read_i16_le(_s, TRUE); \
630  } while (0)
631 
632 #define Stream_Read_UINT16_BE(_s, _v) \
633  do \
634  { \
635  _v = stream_read_u16_be(_s, TRUE); \
636  } while (0)
637 
638 #define Stream_Read_INT16_BE(_s, _v) \
639  do \
640  { \
641  _v = stream_read_i16_be(_s, TRUE); \
642  } while (0)
643 
644 #define Stream_Read_UINT32(_s, _v) \
645  do \
646  { \
647  _v = stream_read_u32_le(_s, TRUE); \
648  } while (0)
649 
650 #define Stream_Read_INT32(_s, _v) \
651  do \
652  { \
653  _v = stream_read_i32_le(_s, TRUE); \
654  } while (0)
655 
656 #define Stream_Read_UINT32_BE(_s, _v) \
657  do \
658  { \
659  _v = stream_read_u32_be(_s, TRUE); \
660  } while (0)
661 
662 #define Stream_Read_INT32_BE(_s, _v) \
663  do \
664  { \
665  _v = stream_read_i32_be(_s, TRUE); \
666  } while (0)
667 
668 #define Stream_Read_UINT64(_s, _v) \
669  do \
670  { \
671  _v = stream_read_u64_le(_s, TRUE); \
672  } while (0)
673 
674 #define Stream_Read_INT64(_s, _v) \
675  do \
676  { \
677  _v = stream_read_i64_le(_s, TRUE); \
678  } while (0)
679 
680 #define Stream_Read_UINT64_BE(_s, _v) \
681  do \
682  { \
683  _v = stream_read_u64_be(_s, TRUE); \
684  } while (0)
685 
686 #define Stream_Read_INT64_BE(_s, _v) \
687  do \
688  { \
689  _v = stream_read_i64_be(_s, TRUE); \
690  } while (0)
691 
692  static INLINE void Stream_Read(wStream* _s, void* _b, size_t _n)
693  {
694  WINPR_ASSERT(_s);
695  WINPR_ASSERT(_b || (_n == 0));
696  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
697  memcpy(_b, (_s->pointer), (_n));
698  Stream_Seek(_s, _n);
699  }
700 
701 #define Stream_Peek_UINT8(_s, _v) \
702  do \
703  { \
704  _v = stream_read_u8(_s, FALSE); \
705  } while (0)
706 
707 #define Stream_Peek_INT8(_s, _v) \
708  do \
709  { \
710  _v = stream_read_i8(_s, FALSE); \
711  } while (0)
712 
713 #define Stream_Peek_UINT16(_s, _v) \
714  do \
715  { \
716  _v = stream_read_u16_le(_s, FALSE); \
717  } while (0)
718 
719 #define Stream_Peek_INT16(_s, _v) \
720  do \
721  { \
722  _v = stream_read_i16_le(_s, FALSE); \
723  } while (0)
724 
725 #define Stream_Peek_UINT16_BE(_s, _v) \
726  do \
727  { \
728  _v = stream_read_u16_be(_s, FALSE); \
729  } while (0)
730 
731 #define Stream_Peek_INT16_BE(_s, _v) \
732  do \
733  { \
734  _v = stream_read_i16_be(_s, FALSE); \
735  } while (0)
736 
737 #define Stream_Peek_UINT32(_s, _v) \
738  do \
739  { \
740  _v = stream_read_u32_le(_s, FALSE); \
741  } while (0)
742 
743 #define Stream_Peek_INT32(_s, _v) \
744  do \
745  { \
746  _v = stream_read_i32_le(_s, FALSE); \
747  } while (0)
748 
749 #define Stream_Peek_UINT32_BE(_s, _v) \
750  do \
751  { \
752  _v = stream_read_u32_be(_s, FALSE); \
753  } while (0)
754 
755 #define Stream_Peek_INT32_BE(_s, _v) \
756  do \
757  { \
758  _v = stream_read_i32_be(_s, FALSE); \
759  } while (0)
760 
761 #define Stream_Peek_UINT64(_s, _v) \
762  do \
763  { \
764  _v = stream_read_u64_le(_s, FALSE); \
765  } while (0)
766 
767 #define Stream_Peek_INT64(_s, _v) \
768  do \
769  { \
770  _v = stream_read_i64_le(_s, FALSE); \
771  } while (0)
772 
773 #define Stream_Peek_UINT64_BE(_s, _v) \
774  do \
775  { \
776  _v = stream_read_u64_be(_s, FALSE); \
777  } while (0)
778 
779 #define Stream_Peek_INT64_BE(_s, _v) \
780  do \
781  { \
782  _v = stream_read_i64_be(_s, FALSE); \
783  } while (0)
784 
785  static INLINE void Stream_Peek(const wStream* _s, void* _b, size_t _n)
786  {
787  WINPR_ASSERT(_s);
788  WINPR_ASSERT(_b || (_n == 0));
789  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
790  memcpy(_b, (_s->pointer), (_n));
791  }
792 
793 #define Stream_Write_INT8(s, v) \
794  do \
795  { \
796  WINPR_ASSERT((v) <= INT8_MAX); \
797  WINPR_ASSERT((v) >= INT8_MIN); \
798  Stream_Write_INT8_unchecked((s), (v)); \
799  } while (0)
800 
808  static INLINE void Stream_Write_INT8_unchecked(wStream* _s, INT8 _v)
809  {
810  WINPR_ASSERT(_s);
811  WINPR_ASSERT(_s->pointer);
812  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 1);
813 
814  *_s->pointer++ = WINPR_STREAM_CAST(BYTE, _v);
815  }
816 
817 #define Stream_Write_UINT8(s, v) \
818  do \
819  { \
820  WINPR_ASSERT((v) <= UINT8_MAX); \
821  WINPR_ASSERT((v) >= 0); \
822  Stream_Write_UINT8_unchecked((s), (v)); \
823  } while (0)
824 
832  static INLINE void Stream_Write_UINT8_unchecked(wStream* _s, UINT8 _v)
833  {
834  WINPR_ASSERT(_s);
835  WINPR_ASSERT(_s->pointer);
836  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 1);
837 
838  *_s->pointer++ = WINPR_STREAM_CAST(BYTE, _v);
839  }
840 
841 #define Stream_Write_INT16(s, v) \
842  do \
843  { \
844  WINPR_ASSERT((v) >= INT16_MIN); \
845  WINPR_ASSERT((v) <= INT16_MAX); \
846  Stream_Write_INT16_unchecked((s), (v)); \
847  } while (0)
848 
857  static INLINE void Stream_Write_INT16_unchecked(wStream* _s, INT16 _v)
858  {
859  WINPR_ASSERT(_s);
860  WINPR_ASSERT(_s->pointer);
861  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
862 
863  *_s->pointer++ = (_v) & 0xFF;
864  *_s->pointer++ = ((_v) >> 8) & 0xFF;
865  }
866 
867 #define Stream_Write_UINT16(s, v) \
868  do \
869  { \
870  WINPR_ASSERT((v) <= UINT16_MAX); \
871  WINPR_ASSERT((v) >= 0); \
872  Stream_Write_UINT16_unchecked((s), (v)); \
873  } while (0)
874 
883  static INLINE void Stream_Write_UINT16_unchecked(wStream* _s, UINT16 _v)
884  {
885  WINPR_ASSERT(_s);
886  WINPR_ASSERT(_s->pointer);
887  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
888 
889  *_s->pointer++ = (_v) & 0xFF;
890  *_s->pointer++ = ((_v) >> 8) & 0xFF;
891  }
892 
893 #define Stream_Write_UINT16_BE(s, v) \
894  do \
895  { \
896  WINPR_ASSERT((v) <= UINT16_MAX); \
897  WINPR_ASSERT((v) >= 0); \
898  Stream_Write_UINT16_BE_unchecked((s), (v)); \
899  } while (0)
900 
909  static INLINE void Stream_Write_UINT16_BE_unchecked(wStream* _s, UINT16 _v)
910  {
911  WINPR_ASSERT(_s);
912  WINPR_ASSERT(_s->pointer);
913  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
914 
915  *_s->pointer++ = ((_v) >> 8) & 0xFF;
916  *_s->pointer++ = (_v) & 0xFF;
917  }
918 
919 #define Stream_Write_INT16_BE(s, v) \
920  do \
921  { \
922  WINPR_ASSERT((v) <= INT16_MAX); \
923  WINPR_ASSERT((v) >= INT16_MIN); \
924  Stream_Write_INT16_BE_unchecked((s), (v)); \
925  } while (0)
926 
937  static INLINE void Stream_Write_INT16_BE_unchecked(wStream* _s, INT16 _v)
938  {
939  WINPR_ASSERT(_s);
940  WINPR_ASSERT(_s->pointer);
941  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
942 
943  *_s->pointer++ = ((_v) >> 8) & 0xFF;
944  *_s->pointer++ = (_v) & 0xFF;
945  }
946 
947 #define Stream_Write_UINT24_BE(s, v) \
948  do \
949  { \
950  WINPR_ASSERT((v) <= 0xFFFFFF); \
951  WINPR_ASSERT((v) >= 0); \
952  Stream_Write_UINT24_BE_unchecked((s), (v)); \
953  } while (0)
954 
963  static INLINE void Stream_Write_UINT24_BE_unchecked(wStream* _s, UINT32 _v)
964  {
965  WINPR_ASSERT(_s);
966  WINPR_ASSERT(_s->pointer);
967  WINPR_ASSERT(_v <= 0x00FFFFFF);
968  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 3);
969 
970  *_s->pointer++ = ((_v) >> 16) & 0xFF;
971  *_s->pointer++ = ((_v) >> 8) & 0xFF;
972  *_s->pointer++ = (_v) & 0xFF;
973  }
974 
975 #define Stream_Write_INT32(s, v) \
976  do \
977  { \
978  WINPR_ASSERT((v) <= INT32_MAX); \
979  WINPR_ASSERT((v) >= INT32_MIN); \
980  Stream_Write_INT32_unchecked((s), (v)); \
981  } while (0)
982 
991  static INLINE void Stream_Write_INT32_unchecked(wStream* _s, INT32 _v)
992  {
993  WINPR_ASSERT(_s);
994  WINPR_ASSERT(_s->pointer);
995  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
996 
997  *_s->pointer++ = (_v) & 0xFF;
998  *_s->pointer++ = ((_v) >> 8) & 0xFF;
999  *_s->pointer++ = ((_v) >> 16) & 0xFF;
1000  *_s->pointer++ = ((_v) >> 24) & 0xFF;
1001  }
1002 
1003 #define Stream_Write_INT32_BE(s, v) \
1004  do \
1005  { \
1006  WINPR_ASSERT((v) <= INT32_MAX); \
1007  WINPR_ASSERT((v) >= INT32_MIN); \
1008  Stream_Write_INT32_BE_unchecked((s), (v)); \
1009  } while (0)
1010 
1021  static INLINE void Stream_Write_INT32_BE_unchecked(wStream* _s, INT32 _v)
1022  {
1023  WINPR_ASSERT(_s);
1024  WINPR_ASSERT(_s->pointer);
1025  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1026 
1027  *_s->pointer++ = (_v) & 0xFF;
1028  *_s->pointer++ = ((_v) >> 8) & 0xFF;
1029  *_s->pointer++ = ((_v) >> 16) & 0xFF;
1030  *_s->pointer++ = ((_v) >> 24) & 0xFF;
1031  *_s->pointer++ = (_v) & 0xFF;
1032  *_s->pointer++ = ((_v) >> 8) & 0xFF;
1033  *_s->pointer++ = ((_v) >> 16) & 0xFF;
1034  *_s->pointer++ = ((_v) >> 24) & 0xFF;
1035  }
1036 
1037 #define Stream_Write_UINT32(s, v) \
1038  do \
1039  { \
1040  WINPR_ASSERT((v) <= UINT32_MAX); \
1041  WINPR_ASSERT((v) >= 0); \
1042  Stream_Write_UINT32_unchecked((s), (v)); \
1043  } while (0)
1044 
1053  static INLINE void Stream_Write_UINT32_unchecked(wStream* _s, UINT32 _v)
1054  {
1055  WINPR_ASSERT(_s);
1056  WINPR_ASSERT(_s->pointer);
1057  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1058 
1059  *_s->pointer++ = (_v) & 0xFF;
1060  *_s->pointer++ = ((_v) >> 8) & 0xFF;
1061  *_s->pointer++ = ((_v) >> 16) & 0xFF;
1062  *_s->pointer++ = ((_v) >> 24) & 0xFF;
1063  }
1064 
1065 #define Stream_Write_UINT32_BE(s, v) \
1066  do \
1067  { \
1068  WINPR_ASSERT((v) <= UINT32_MAX); \
1069  WINPR_ASSERT((v) >= 0); \
1070  Stream_Write_UINT32_BE_unchecked((s), (v)); \
1071  } while (0)
1072 
1081  static INLINE void Stream_Write_UINT32_BE_unchecked(wStream* _s, UINT32 _v)
1082  {
1083  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1084 
1085  Stream_Write_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF));
1086  Stream_Write_UINT16_BE(_s, ((_v) & 0xFFFF));
1087  }
1088 
1095  static INLINE void Stream_Write_UINT64(wStream* _s, UINT64 _v)
1096  {
1097  WINPR_ASSERT(_s);
1098  WINPR_ASSERT(_s->pointer);
1099  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1100 
1101  Stream_Write_UINT32(_s, ((_v) & 0xFFFFFFFFUL));
1102  Stream_Write_UINT32(_s, ((_v) >> 16 & 0xFFFFFFFFUL));
1103  }
1104 
1111  static INLINE void Stream_Write_UINT64_BE(wStream* _s, UINT64 _v)
1112  {
1113  WINPR_ASSERT(_s);
1114  WINPR_ASSERT(_s->pointer);
1115  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1116 
1117  Stream_Write_UINT32_BE(_s, ((_v) >> 16 & 0xFFFFFFFFUL));
1118  Stream_Write_UINT32_BE(_s, ((_v) & 0xFFFFFFFFUL));
1119  }
1120 
1121  static INLINE void Stream_Write(wStream* _s, const void* _b, size_t _n)
1122  {
1123  if (_n > 0)
1124  {
1125  WINPR_ASSERT(_s);
1126  WINPR_ASSERT(_b);
1127  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
1128  memcpy(_s->pointer, (_b), (_n));
1129  Stream_Seek(_s, _n);
1130  }
1131  }
1132 
1133  static INLINE void Stream_Seek_UINT8(wStream* _s)
1134  {
1135  Stream_Seek(_s, sizeof(UINT8));
1136  }
1137  static INLINE void Stream_Seek_UINT16(wStream* _s)
1138  {
1139  Stream_Seek(_s, sizeof(UINT16));
1140  }
1141  static INLINE void Stream_Seek_UINT32(wStream* _s)
1142  {
1143  Stream_Seek(_s, sizeof(UINT32));
1144  }
1145  static INLINE void Stream_Seek_UINT64(wStream* _s)
1146  {
1147  Stream_Seek(_s, sizeof(UINT64));
1148  }
1149 
1150  static INLINE void Stream_Rewind_UINT8(wStream* _s)
1151  {
1152  Stream_Rewind(_s, sizeof(UINT8));
1153  }
1154  static INLINE void Stream_Rewind_UINT16(wStream* _s)
1155  {
1156  Stream_Rewind(_s, sizeof(UINT16));
1157  }
1158  static INLINE void Stream_Rewind_UINT32(wStream* _s)
1159  {
1160  Stream_Rewind(_s, sizeof(UINT32));
1161  }
1162  static INLINE void Stream_Rewind_UINT64(wStream* _s)
1163  {
1164  Stream_Rewind(_s, sizeof(UINT64));
1165  }
1166 
1167  static INLINE void Stream_Fill(wStream* _s, int _v, size_t _n)
1168  {
1169  WINPR_ASSERT(_s);
1170  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= (_n));
1171  memset(_s->pointer, _v, (_n));
1172  Stream_Seek(_s, _n);
1173  }
1174 
1175  static INLINE void Stream_Zero(wStream* _s, size_t _n)
1176  {
1177  Stream_Fill(_s, '\0', _n);
1178  }
1179 
1180  static INLINE void Stream_Copy(wStream* _src, wStream* _dst, size_t _n)
1181  {
1182  WINPR_ASSERT(_src);
1183  WINPR_ASSERT(_dst);
1184  WINPR_ASSERT(Stream_GetRemainingCapacity(_src) >= (_n));
1185  WINPR_ASSERT(Stream_GetRemainingCapacity(_dst) >= (_n));
1186 
1187  memcpy(_dst->pointer, _src->pointer, _n);
1188  Stream_Seek(_dst, _n);
1189  Stream_Seek(_src, _n);
1190  }
1191 
1196 #define Stream_BufferAs(s, type) WINPR_STREAM_CAST(type*, Stream_Buffer(s))
1197 
1198  static INLINE BYTE* Stream_Buffer(wStream* _s)
1199  {
1200  WINPR_ASSERT(_s);
1201  return _s->buffer;
1202  }
1203 
1208 #define Stream_ConstBufferAs(s, type) WINPR_STREAM_CAST(type*, Stream_ConstBuffer(s))
1209  static INLINE const BYTE* Stream_ConstBuffer(const wStream* _s)
1210  {
1211  WINPR_ASSERT(_s);
1212  return _s->buffer;
1213  }
1214 
1215 #define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s)
1216 
1221 #define Stream_GetBufferAs(_s, _b) _b = Stream_BufferAs(_s, typeof(_b))
1222 
1223 #define Stream_PointerAs(s, type) WINPR_STREAM_CAST(type*, Stream_Pointer(s))
1224 
1225  static INLINE void* Stream_Pointer(wStream* _s)
1226  {
1227  WINPR_ASSERT(_s);
1228  return _s->pointer;
1229  }
1230 
1231  static INLINE const void* Stream_ConstPointer(const wStream* _s)
1232  {
1233  WINPR_ASSERT(_s);
1234  return _s->pointer;
1235  }
1236 
1237 #define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s)
1238 
1243 #define Stream_GetPointerAs(_s, _p) _p = Stream_PointerAs(_s, typeof(_p))
1244 
1245 #if defined(WITH_WINPR_DEPRECATED)
1246  WINPR_API WINPR_DEPRECATED_VAR("Use Stream_SetPosition instead",
1247  BOOL Stream_SetPointer(wStream* _s, BYTE* _p));
1248  WINPR_API WINPR_DEPRECATED_VAR("Use Stream_New(buffer, capacity) instead",
1249  BOOL Stream_SetBuffer(wStream* _s, BYTE* _b));
1250  WINPR_API WINPR_DEPRECATED_VAR("Use Stream_New(buffer, capacity) instead",
1251  void Stream_SetCapacity(wStream* _s, size_t capacity));
1252 #endif
1253 
1254  static INLINE size_t Stream_Length(const wStream* _s)
1255  {
1256  WINPR_ASSERT(_s);
1257  return _s->length;
1258  }
1259 
1260 #define Stream_GetLength(_s, _l) _l = Stream_Length(_s)
1261  WINPR_API BOOL Stream_SetLength(wStream* _s, size_t _l);
1262 
1263  static INLINE size_t Stream_Capacity(const wStream* _s)
1264  {
1265  WINPR_ASSERT(_s);
1266  return _s->capacity;
1267  }
1268 
1269 #define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s);
1270 
1271  static INLINE size_t Stream_GetPosition(const wStream* _s)
1272  {
1273  WINPR_ASSERT(_s);
1274  WINPR_ASSERT(_s->buffer <= _s->pointer);
1275  return WINPR_STREAM_CAST(size_t, (_s->pointer - _s->buffer));
1276  }
1277 
1278  WINPR_API BOOL Stream_SetPosition(wStream* _s, size_t _p);
1279 
1280  WINPR_API void Stream_SealLength(wStream* _s);
1281 
1282  static INLINE void Stream_Clear(wStream* _s)
1283  {
1284  WINPR_ASSERT(_s);
1285  memset(_s->buffer, 0, _s->capacity);
1286  }
1287 
1288 #define Stream_SafeSeek(s, size) Stream_SafeSeekEx(s, size, __FILE__, __LINE__, __func__)
1289  WINPR_API BOOL Stream_SafeSeekEx(wStream* s, size_t size, const char* file, size_t line,
1290  const char* fkt);
1291 
1292  WINPR_API BOOL Stream_Read_UTF16_String(wStream* s, WCHAR* dst, size_t charLength);
1293  WINPR_API BOOL Stream_Write_UTF16_String(wStream* s, const WCHAR* src, size_t charLength);
1294 
1304  WINPR_API char* Stream_Read_UTF16_String_As_UTF8(wStream* s, size_t wcharLength,
1305  size_t* pUtfCharLength);
1306 
1316  WINPR_API SSIZE_T Stream_Read_UTF16_String_As_UTF8_Buffer(wStream* s, size_t wcharLength,
1317  char* utfBuffer,
1318  size_t utfBufferCharLength);
1319 
1331  WINPR_API SSIZE_T Stream_Write_UTF16_String_From_UTF8(wStream* s, size_t wcharLength,
1332  const char* src, size_t length,
1333  BOOL fill);
1334 
1335  /* StreamPool */
1336 
1337  WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s);
1338 
1339  WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size);
1340 
1341  WINPR_API void Stream_AddRef(wStream* s);
1342  WINPR_API void Stream_Release(wStream* s);
1343 
1344  WINPR_API wStream* StreamPool_Find(wStreamPool* pool, const BYTE* ptr);
1345 
1346  WINPR_API void StreamPool_Clear(wStreamPool* pool);
1347 
1348  WINPR_API void StreamPool_Free(wStreamPool* pool);
1349 
1350  WINPR_ATTR_MALLOC(StreamPool_Free, 1)
1351  WINPR_API wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize);
1352 
1353  WINPR_API char* StreamPool_GetStatistics(wStreamPool* pool, char* buffer, size_t size);
1354 
1355 #ifdef __cplusplus
1356 }
1357 #endif
1358 
1359 #endif /* WINPR_UTILS_STREAM_H */