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 #include <winpr/cast.h>
32 #include <winpr/wlog.h>
33 
34 #ifdef __cplusplus
35 extern "C"
36 {
37 #endif
38 
39  typedef struct s_wStreamPool wStreamPool;
40 
41  typedef struct
42  {
43  BYTE* buffer;
44  BYTE* pointer;
45  size_t length;
46  size_t capacity;
47 
48  DWORD count;
49  wStreamPool* pool;
50  BOOL isAllocatedStream;
51  BOOL isOwner;
52  } wStream;
53 
54  static INLINE size_t Stream_Capacity(const wStream* _s);
55  WINPR_API size_t Stream_GetRemainingCapacity(const wStream* _s);
56  WINPR_API size_t Stream_GetRemainingLength(const wStream* _s);
57 
58  WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size);
59  WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size);
60 
61 #define WINPR_STREAM_CAST(t, val) WINPR_CXX_COMPAT_CAST(t, val)
62 
63 #define Stream_CheckAndLogRequiredCapacityOfSize(tag, s, nmemb, size) \
64  Stream_CheckAndLogRequiredCapacityEx(tag, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
65  __func__, __FILE__, (size_t)__LINE__)
66 #define Stream_CheckAndLogRequiredCapacity(tag, s, len) \
67  Stream_CheckAndLogRequiredCapacityOfSize((tag), (s), (len), 1)
68 
69  WINPR_API BOOL Stream_CheckAndLogRequiredCapacityEx(const char* tag, DWORD level, wStream* s,
70  size_t nmemb, size_t size, const char* fmt,
71  ...);
72  WINPR_API BOOL Stream_CheckAndLogRequiredCapacityExVa(const char* tag, DWORD level, wStream* s,
73  size_t nmemb, size_t size,
74  const char* fmt, va_list args);
75 
76 #define Stream_CheckAndLogRequiredCapacityOfSizeWLog(log, s, nmemb, size) \
77  Stream_CheckAndLogRequiredCapacityWLogEx(log, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
78  __func__, __FILE__, (size_t)__LINE__)
79 
80 #define Stream_CheckAndLogRequiredCapacityWLog(log, s, len) \
81  Stream_CheckAndLogRequiredCapacityOfSizeWLog((log), (s), (len), 1)
82 
83  WINPR_API BOOL Stream_CheckAndLogRequiredCapacityWLogEx(wLog* log, DWORD level, wStream* s,
84  size_t nmemb, size_t size,
85  const char* fmt, ...);
86  WINPR_API BOOL Stream_CheckAndLogRequiredCapacityWLogExVa(wLog* log, DWORD level, wStream* s,
87  size_t nmemb, size_t size,
88  const char* fmt, va_list args);
89 
90  WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
91 
92  WINPR_ATTR_MALLOC(Stream_Free, 1)
93  WINPR_API wStream* Stream_New(BYTE* buffer, size_t size);
94  WINPR_API wStream* Stream_StaticConstInit(wStream* s, const BYTE* buffer, size_t size);
95  WINPR_API wStream* Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
96 
97 #define Stream_CheckAndLogRequiredLengthOfSize(tag, s, nmemb, size) \
98  Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
99  __func__, __FILE__, (size_t)__LINE__)
100 #define Stream_CheckAndLogRequiredLength(tag, s, len) \
101  Stream_CheckAndLogRequiredLengthOfSize(tag, s, len, 1)
102 
103  WINPR_API BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s,
104  size_t nmemb, size_t size, const char* fmt,
105  ...);
106  WINPR_API BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s,
107  size_t nmemb, size_t size, const char* fmt,
108  va_list args);
109 
110 #define Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, nmemb, size) \
111  Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
112  __func__, __FILE__, (size_t)__LINE__)
113 #define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \
114  Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, len, 1)
115 
116  WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s,
117  size_t nmemb, size_t size,
118  const char* fmt, ...);
119  WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s,
120  size_t nmemb, size_t size,
121  const char* fmt, va_list args);
122 
123  static INLINE void Stream_Seek(wStream* s, size_t _offset)
124  {
125  WINPR_ASSERT(s);
126  WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= _offset);
127  s->pointer += (_offset);
128  }
129 
130  static INLINE void Stream_Rewind(wStream* s, size_t _offset)
131  {
132  size_t cur = 0;
133  WINPR_ASSERT(s);
134  WINPR_ASSERT(s->buffer <= s->pointer);
135  cur = WINPR_STREAM_CAST(size_t, s->pointer - s->buffer);
136  WINPR_ASSERT(cur >= _offset);
137  if (cur >= _offset)
138  s->pointer -= (_offset);
139  else
140  s->pointer = s->buffer;
141  }
142 
143  static INLINE UINT8 stream_read_u8(wStream* _s, BOOL seek)
144  {
145  WINPR_ASSERT(_s);
146  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= sizeof(UINT8));
147 
148  const UINT8 v = winpr_Data_Get_UINT8(_s->pointer);
149  if (seek)
150  Stream_Seek(_s, sizeof(UINT8));
151  return v;
152  }
153 
154  static INLINE INT8 stream_read_i8(wStream* _s, BOOL seek)
155  {
156  const INT8 v = winpr_Data_Get_INT8(_s->pointer);
157  if (seek)
158  Stream_Seek(_s, sizeof(INT8));
159  return 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  const UINT16 v = winpr_Data_Get_UINT16(_s->pointer);
169  if (seek)
170  Stream_Seek(_s, typesize);
171  return v;
172  }
173 
174  static INLINE UINT16 stream_read_u16_be(wStream* _s, BOOL seek)
175  {
176  const size_t typesize = sizeof(UINT16);
177  WINPR_ASSERT(_s);
178  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
179 
180  const UINT16 v = winpr_Data_Get_UINT16_BE(_s->pointer);
181  if (seek)
182  Stream_Seek(_s, typesize);
183  return v;
184  }
185 
186  static INLINE INT16 stream_read_i16_le(wStream* _s, BOOL seek)
187  {
188  const size_t typesize = sizeof(INT16);
189  WINPR_ASSERT(_s);
190  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
191 
192  const INT16 v = winpr_Data_Get_INT16(_s->pointer);
193  if (seek)
194  Stream_Seek(_s, typesize);
195  return v;
196  }
197 
198  static INLINE INT16 stream_read_i16_be(wStream* _s, BOOL seek)
199  {
200  const size_t typesize = sizeof(INT16);
201  WINPR_ASSERT(_s);
202  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
203 
204  const INT16 v = winpr_Data_Get_INT16_BE(_s->pointer);
205  if (seek)
206  Stream_Seek(_s, typesize);
207  return v;
208  }
209 
210  static INLINE UINT32 stream_read_u32_le(wStream* _s, BOOL seek)
211  {
212  const size_t typesize = sizeof(UINT32);
213  WINPR_ASSERT(_s);
214  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
215 
216  const UINT32 v = winpr_Data_Get_UINT32(_s->pointer);
217  if (seek)
218  Stream_Seek(_s, typesize);
219  return v;
220  }
221 
222  static INLINE UINT32 stream_read_u32_be(wStream* _s, BOOL seek)
223  {
224  const size_t typesize = sizeof(UINT32);
225  WINPR_ASSERT(_s);
226  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
227 
228  const UINT32 v = winpr_Data_Get_UINT32_BE(_s->pointer);
229  if (seek)
230  Stream_Seek(_s, typesize);
231  return v;
232  }
233 
234  static INLINE INT32 stream_read_i32_le(wStream* _s, BOOL seek)
235  {
236  const size_t typesize = sizeof(INT32);
237  WINPR_ASSERT(_s);
238  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
239 
240  const INT32 v = winpr_Data_Get_INT32(_s->pointer);
241  if (seek)
242  Stream_Seek(_s, typesize);
243  return v;
244  }
245 
246  static INLINE INT32 stream_read_i32_be(wStream* _s, BOOL seek)
247  {
248  const size_t typesize = sizeof(INT32);
249  WINPR_ASSERT(_s);
250  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
251 
252  const INT32 v = winpr_Data_Get_INT32_BE(_s->pointer);
253  if (seek)
254  Stream_Seek(_s, typesize);
255  return v;
256  }
257 
258  static INLINE UINT64 stream_read_u64_le(wStream* _s, BOOL seek)
259  {
260  const size_t typesize = sizeof(UINT64);
261  WINPR_ASSERT(_s);
262  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
263 
264  const UINT64 v = winpr_Data_Get_UINT64(_s->pointer);
265  if (seek)
266  Stream_Seek(_s, typesize);
267  return v;
268  }
269 
270  static INLINE UINT64 stream_read_u64_be(wStream* _s, BOOL seek)
271  {
272  const size_t typesize = sizeof(UINT64);
273  WINPR_ASSERT(_s);
274  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
275 
276  const UINT64 v = winpr_Data_Get_UINT64_BE(_s->pointer);
277  if (seek)
278  Stream_Seek(_s, typesize);
279  return v;
280  }
281 
282  static INLINE INT64 stream_read_i64_le(wStream* _s, BOOL seek)
283  {
284  const size_t typesize = sizeof(INT64);
285  WINPR_ASSERT(_s);
286  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
287 
288  const INT64 v = winpr_Data_Get_INT64(_s->pointer);
289  if (seek)
290  Stream_Seek(_s, typesize);
291  return v;
292  }
293 
294  static INLINE INT64 stream_read_i64_be(wStream* _s, BOOL seek)
295  {
296  const size_t typesize = sizeof(INT64);
297  WINPR_ASSERT(_s);
298  WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
299 
300  const INT64 v = winpr_Data_Get_INT64_BE(_s->pointer);
301  if (seek)
302  Stream_Seek(_s, typesize);
303  return v;
304  }
305 
312  static INLINE UINT8 Stream_Get_UINT8(wStream* _s)
313  {
314  return stream_read_u8(_s, TRUE);
315  }
316 
323  static INLINE INT8 Stream_Get_INT8(wStream* _s)
324  {
325  return stream_read_i8(_s, TRUE);
326  }
327 
334  static INLINE UINT16 Stream_Get_UINT16(wStream* _s)
335  {
336  return stream_read_u16_le(_s, TRUE);
337  }
338 
345  static INLINE INT16 Stream_Get_INT16(wStream* _s)
346  {
347  return stream_read_i16_le(_s, TRUE);
348  }
349 
356  static INLINE UINT16 Stream_Get_UINT16_BE(wStream* _s)
357  {
358  return stream_read_u16_be(_s, TRUE);
359  }
360 
367  static INLINE INT16 Stream_Get_INT16_BE(wStream* _s)
368  {
369  return stream_read_i16_be(_s, TRUE);
370  }
371 
378  static INLINE UINT32 Stream_Get_UINT32(wStream* _s)
379  {
380  return stream_read_u32_le(_s, TRUE);
381  }
382 
389  static INLINE INT32 Stream_Get_INT32(wStream* _s)
390  {
391  return stream_read_i32_le(_s, TRUE);
392  }
393 
400  static INLINE UINT32 Stream_Get_UINT32_BE(wStream* _s)
401  {
402  return stream_read_u32_be(_s, TRUE);
403  }
404 
411  static INLINE INT32 Stream_Get_INT32_BE(wStream* _s)
412  {
413  return stream_read_i32_be(_s, TRUE);
414  }
415 
422  static INLINE UINT64 Stream_Get_UINT64(wStream* _s)
423  {
424  return stream_read_u64_le(_s, TRUE);
425  }
426 
433  static INLINE INT64 Stream_Get_INT64(wStream* _s)
434  {
435  return stream_read_i64_le(_s, TRUE);
436  }
437 
444  static INLINE UINT64 Stream_Get_UINT64_BE(wStream* _s)
445  {
446  return stream_read_u64_be(_s, TRUE);
447  }
448 
455  static INLINE INT64 Stream_Get_INT64_BE(wStream* _s)
456  {
457  return stream_read_i64_be(_s, TRUE);
458  }
459 
466  static INLINE UINT8 Stream_Peek_Get_UINT8(wStream* _s)
467  {
468  return stream_read_u8(_s, FALSE);
469  }
470 
477  static INLINE INT8 Stream_Peek_Get_INT8(wStream* _s)
478  {
479  return stream_read_i8(_s, FALSE);
480  }
481 
488  static INLINE UINT16 Stream_Peek_Get_UINT16(wStream* _s)
489  {
490  return stream_read_u16_le(_s, FALSE);
491  }
492 
499  static INLINE INT16 Stream_Peek_Get_INT16(wStream* _s)
500  {
501  return stream_read_i16_le(_s, FALSE);
502  }
503 
510  static INLINE UINT16 Stream_Peek_Get_UINT16_BE(wStream* _s)
511  {
512  return stream_read_u16_be(_s, FALSE);
513  }
514 
521  static INLINE INT16 Stream_Peek_Get_INT16_BE(wStream* _s)
522  {
523  return stream_read_i16_be(_s, FALSE);
524  }
525 
532  static INLINE UINT32 Stream_Peek_Get_UINT32(wStream* _s)
533  {
534  return stream_read_u32_le(_s, FALSE);
535  }
536 
543  static INLINE INT32 Stream_Peek_Get_INT32(wStream* _s)
544  {
545  return stream_read_i32_le(_s, FALSE);
546  }
547 
554  static INLINE UINT32 Stream_Peek_Get_UINT32_BE(wStream* _s)
555  {
556  return stream_read_u32_be(_s, FALSE);
557  }
558 
565  static INLINE INT32 Stream_Peek_Get_INT32_BE(wStream* _s)
566  {
567  return stream_read_i32_be(_s, FALSE);
568  }
569 
576  static INLINE UINT64 Stream_Peek_Get_UINT64(wStream* _s)
577  {
578  return stream_read_u64_le(_s, FALSE);
579  }
580 
587  static INLINE INT64 Stream_Peek_Get_INT64(wStream* _s)
588  {
589  return stream_read_i64_le(_s, FALSE);
590  }
591 
598  static INLINE UINT64 Stream_Peek_Get_UINT64_BE(wStream* _s)
599  {
600  return stream_read_u64_be(_s, FALSE);
601  }
602 
609  static INLINE INT64 Stream_Peek_Get_INT64_BE(wStream* _s)
610  {
611  return stream_read_i64_be(_s, FALSE);
612  }
613 
614 #define Stream_Read_UINT8(_s, _v) \
615  do \
616  { \
617  _v = stream_read_u8(_s, TRUE); \
618  } while (0)
619 
620 #define Stream_Read_INT8(_s, _v) \
621  do \
622  { \
623  _v = stream_read_i8(_s, TRUE); \
624  } while (0)
625 
626 #define Stream_Read_UINT16(_s, _v) \
627  do \
628  { \
629  _v = stream_read_u16_le(_s, TRUE); \
630  } while (0)
631 
632 #define Stream_Read_INT16(_s, _v) \
633  do \
634  { \
635  _v = stream_read_i16_le(_s, TRUE); \
636  } while (0)
637 
638 #define Stream_Read_UINT16_BE(_s, _v) \
639  do \
640  { \
641  _v = stream_read_u16_be(_s, TRUE); \
642  } while (0)
643 
644 #define Stream_Read_INT16_BE(_s, _v) \
645  do \
646  { \
647  _v = stream_read_i16_be(_s, TRUE); \
648  } while (0)
649 
650 #define Stream_Read_UINT32(_s, _v) \
651  do \
652  { \
653  _v = stream_read_u32_le(_s, TRUE); \
654  } while (0)
655 
656 #define Stream_Read_INT32(_s, _v) \
657  do \
658  { \
659  _v = stream_read_i32_le(_s, TRUE); \
660  } while (0)
661 
662 #define Stream_Read_UINT32_BE(_s, _v) \
663  do \
664  { \
665  _v = stream_read_u32_be(_s, TRUE); \
666  } while (0)
667 
668 #define Stream_Read_INT32_BE(_s, _v) \
669  do \
670  { \
671  _v = stream_read_i32_be(_s, TRUE); \
672  } while (0)
673 
674 #define Stream_Read_UINT64(_s, _v) \
675  do \
676  { \
677  _v = stream_read_u64_le(_s, TRUE); \
678  } while (0)
679 
680 #define Stream_Read_INT64(_s, _v) \
681  do \
682  { \
683  _v = stream_read_i64_le(_s, TRUE); \
684  } while (0)
685 
686 #define Stream_Read_UINT64_BE(_s, _v) \
687  do \
688  { \
689  _v = stream_read_u64_be(_s, TRUE); \
690  } while (0)
691 
692 #define Stream_Read_INT64_BE(_s, _v) \
693  do \
694  { \
695  _v = stream_read_i64_be(_s, TRUE); \
696  } while (0)
697 
698  static INLINE void Stream_Read(wStream* _s, void* _b, size_t _n)
699  {
700  WINPR_ASSERT(_s);
701  WINPR_ASSERT(_b || (_n == 0));
702  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
703  memcpy(_b, (_s->pointer), (_n));
704  Stream_Seek(_s, _n);
705  }
706 
707 #define Stream_Peek_UINT8(_s, _v) \
708  do \
709  { \
710  _v = stream_read_u8(_s, FALSE); \
711  } while (0)
712 
713 #define Stream_Peek_INT8(_s, _v) \
714  do \
715  { \
716  _v = stream_read_i8(_s, FALSE); \
717  } while (0)
718 
719 #define Stream_Peek_UINT16(_s, _v) \
720  do \
721  { \
722  _v = stream_read_u16_le(_s, FALSE); \
723  } while (0)
724 
725 #define Stream_Peek_INT16(_s, _v) \
726  do \
727  { \
728  _v = stream_read_i16_le(_s, FALSE); \
729  } while (0)
730 
731 #define Stream_Peek_UINT16_BE(_s, _v) \
732  do \
733  { \
734  _v = stream_read_u16_be(_s, FALSE); \
735  } while (0)
736 
737 #define Stream_Peek_INT16_BE(_s, _v) \
738  do \
739  { \
740  _v = stream_read_i16_be(_s, FALSE); \
741  } while (0)
742 
743 #define Stream_Peek_UINT32(_s, _v) \
744  do \
745  { \
746  _v = stream_read_u32_le(_s, FALSE); \
747  } while (0)
748 
749 #define Stream_Peek_INT32(_s, _v) \
750  do \
751  { \
752  _v = stream_read_i32_le(_s, FALSE); \
753  } while (0)
754 
755 #define Stream_Peek_UINT32_BE(_s, _v) \
756  do \
757  { \
758  _v = stream_read_u32_be(_s, FALSE); \
759  } while (0)
760 
761 #define Stream_Peek_INT32_BE(_s, _v) \
762  do \
763  { \
764  _v = stream_read_i32_be(_s, FALSE); \
765  } while (0)
766 
767 #define Stream_Peek_UINT64(_s, _v) \
768  do \
769  { \
770  _v = stream_read_u64_le(_s, FALSE); \
771  } while (0)
772 
773 #define Stream_Peek_INT64(_s, _v) \
774  do \
775  { \
776  _v = stream_read_i64_le(_s, FALSE); \
777  } while (0)
778 
779 #define Stream_Peek_UINT64_BE(_s, _v) \
780  do \
781  { \
782  _v = stream_read_u64_be(_s, FALSE); \
783  } while (0)
784 
785 #define Stream_Peek_INT64_BE(_s, _v) \
786  do \
787  { \
788  _v = stream_read_i64_be(_s, FALSE); \
789  } while (0)
790 
791  static INLINE void Stream_Peek(const wStream* _s, void* _b, size_t _n)
792  {
793  WINPR_ASSERT(_s);
794  WINPR_ASSERT(_b || (_n == 0));
795  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
796  memcpy(_b, (_s->pointer), (_n));
797  }
798 
799 #define Stream_Write_INT8(s, v) \
800  do \
801  { \
802  WINPR_ASSERT((v) <= INT8_MAX); \
803  WINPR_ASSERT((v) >= INT8_MIN); \
804  Stream_Write_INT8_unchecked((s), (v)); \
805  } while (0)
806 
814  static INLINE void Stream_Write_INT8_unchecked(wStream* _s, INT8 _v)
815  {
816  WINPR_ASSERT(_s);
817  WINPR_ASSERT(_s->pointer);
818  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 1);
819 
820  winpr_Data_Write_INT8(_s->pointer, _v);
821  _s->pointer += 1;
822  }
823 
824 #define Stream_Write_UINT8(s, v) \
825  do \
826  { \
827  WINPR_ASSERT((v) <= UINT8_MAX); \
828  WINPR_ASSERT((v) >= 0); \
829  Stream_Write_UINT8_unchecked((s), (v)); \
830  } while (0)
831 
839  static INLINE void Stream_Write_UINT8_unchecked(wStream* _s, UINT8 _v)
840  {
841  WINPR_ASSERT(_s);
842  WINPR_ASSERT(_s->pointer);
843  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 1);
844 
845  winpr_Data_Write_UINT8(_s->pointer, _v);
846  _s->pointer += 1;
847  }
848 
849 #define Stream_Write_INT16(s, v) \
850  do \
851  { \
852  WINPR_ASSERT((v) >= INT16_MIN); \
853  WINPR_ASSERT((v) <= INT16_MAX); \
854  Stream_Write_INT16_unchecked((s), (v)); \
855  } while (0)
856 
865  static INLINE void Stream_Write_INT16_unchecked(wStream* _s, INT16 _v)
866  {
867  WINPR_ASSERT(_s);
868  WINPR_ASSERT(_s->pointer);
869  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
870 
871  winpr_Data_Write_INT16(_s->pointer, _v);
872  _s->pointer += 2;
873  }
874 
875 #define Stream_Write_UINT16(s, v) \
876  do \
877  { \
878  WINPR_ASSERT((v) <= UINT16_MAX); \
879  WINPR_ASSERT((v) >= 0); \
880  Stream_Write_UINT16_unchecked((s), (v)); \
881  } while (0)
882 
891  static INLINE void Stream_Write_UINT16_unchecked(wStream* _s, UINT16 _v)
892  {
893  WINPR_ASSERT(_s);
894  WINPR_ASSERT(_s->pointer);
895  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
896 
897  winpr_Data_Write_UINT16(_s->pointer, _v);
898  _s->pointer += 2;
899  }
900 
901 #define Stream_Write_UINT16_BE(s, v) \
902  do \
903  { \
904  WINPR_ASSERT((v) <= UINT16_MAX); \
905  WINPR_ASSERT((v) >= 0); \
906  Stream_Write_UINT16_BE_unchecked((s), (v)); \
907  } while (0)
908 
917  static INLINE void Stream_Write_UINT16_BE_unchecked(wStream* _s, UINT16 _v)
918  {
919  WINPR_ASSERT(_s);
920  WINPR_ASSERT(_s->pointer);
921  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
922 
923  winpr_Data_Write_UINT16_BE(_s->pointer, _v);
924  _s->pointer += 2;
925  }
926 
927 #define Stream_Write_INT16_BE(s, v) \
928  do \
929  { \
930  WINPR_ASSERT((v) <= INT16_MAX); \
931  WINPR_ASSERT((v) >= INT16_MIN); \
932  Stream_Write_INT16_BE_unchecked((s), (v)); \
933  } while (0)
934 
945  static INLINE void Stream_Write_INT16_BE_unchecked(wStream* _s, INT16 _v)
946  {
947  WINPR_ASSERT(_s);
948  WINPR_ASSERT(_s->pointer);
949  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
950 
951  winpr_Data_Write_INT16_BE(_s->pointer, _v);
952  _s->pointer += 2;
953  }
954 
955 #define Stream_Write_UINT24_BE(s, v) \
956  do \
957  { \
958  WINPR_ASSERT((v) <= 0xFFFFFF); \
959  WINPR_ASSERT((v) >= 0); \
960  Stream_Write_UINT24_BE_unchecked((s), (v)); \
961  } while (0)
962 
971  static INLINE void Stream_Write_UINT24_BE_unchecked(wStream* _s, UINT32 _v)
972  {
973  WINPR_ASSERT(_s);
974  WINPR_ASSERT(_s->pointer);
975  WINPR_ASSERT(_v <= 0x00FFFFFF);
976  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 3);
977 
978  *_s->pointer++ = ((_v) >> 16) & 0xFF;
979  *_s->pointer++ = ((_v) >> 8) & 0xFF;
980  *_s->pointer++ = (_v) & 0xFF;
981  }
982 
983 #define Stream_Write_INT32(s, v) \
984  do \
985  { \
986  WINPR_ASSERT((v) <= INT32_MAX); \
987  WINPR_ASSERT((v) >= INT32_MIN); \
988  Stream_Write_INT32_unchecked((s), (v)); \
989  } while (0)
990 
999  static INLINE void Stream_Write_INT32_unchecked(wStream* _s, INT32 _v)
1000  {
1001  WINPR_ASSERT(_s);
1002  WINPR_ASSERT(_s->pointer);
1003  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1004 
1005  winpr_Data_Write_INT32(_s->pointer, _v);
1006  _s->pointer += 4;
1007  }
1008 
1009 #define Stream_Write_INT32_BE(s, v) \
1010  do \
1011  { \
1012  WINPR_ASSERT((v) <= INT32_MAX); \
1013  WINPR_ASSERT((v) >= INT32_MIN); \
1014  Stream_Write_INT32_BE_unchecked((s), (v)); \
1015  } while (0)
1016 
1027  static INLINE void Stream_Write_INT32_BE_unchecked(wStream* _s, INT32 _v)
1028  {
1029  WINPR_ASSERT(_s);
1030  WINPR_ASSERT(_s->pointer);
1031  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1032 
1033  winpr_Data_Write_INT32_BE(_s->pointer, _v);
1034  _s->pointer += 4;
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  winpr_Data_Write_UINT32(_s->pointer, _v);
1060  _s->pointer += 4;
1061  }
1062 
1063 #define Stream_Write_UINT32_BE(s, v) \
1064  do \
1065  { \
1066  WINPR_ASSERT((v) <= UINT32_MAX); \
1067  WINPR_ASSERT((v) >= 0); \
1068  Stream_Write_UINT32_BE_unchecked((s), (v)); \
1069  } while (0)
1070 
1079  static INLINE void Stream_Write_UINT32_BE_unchecked(wStream* _s, UINT32 _v)
1080  {
1081  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1082 
1083  winpr_Data_Write_UINT32_BE(_s->pointer, _v);
1084  _s->pointer += 4;
1085  }
1086 
1093  static INLINE void Stream_Write_UINT64(wStream* _s, UINT64 _v)
1094  {
1095  WINPR_ASSERT(_s);
1096  WINPR_ASSERT(_s->pointer);
1097  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1098 
1099  winpr_Data_Write_UINT64(_s->pointer, _v);
1100  _s->pointer += 8;
1101  }
1102 
1109  static INLINE void Stream_Write_UINT64_BE(wStream* _s, UINT64 _v)
1110  {
1111  WINPR_ASSERT(_s);
1112  WINPR_ASSERT(_s->pointer);
1113  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1114 
1115  winpr_Data_Write_UINT64_BE(_s->pointer, _v);
1116  _s->pointer += 8;
1117  }
1118 
1126  static INLINE void Stream_Write_INT64(wStream* _s, INT64 _v)
1127  {
1128  WINPR_ASSERT(_s);
1129  WINPR_ASSERT(_s->pointer);
1130  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1131 
1132  winpr_Data_Write_INT64(_s->pointer, _v);
1133  _s->pointer += 8;
1134  }
1135 
1143  static INLINE void Stream_Write_INT64_BE(wStream* _s, INT64 _v)
1144  {
1145  WINPR_ASSERT(_s);
1146  WINPR_ASSERT(_s->pointer);
1147  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1148 
1149  winpr_Data_Write_INT64_BE(_s->pointer, _v);
1150  _s->pointer += 8;
1151  }
1152 
1153  static INLINE void Stream_Write(wStream* _s, const void* _b, size_t _n)
1154  {
1155  if (_n > 0)
1156  {
1157  WINPR_ASSERT(_s);
1158  WINPR_ASSERT(_b);
1159  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
1160  memcpy(_s->pointer, (_b), (_n));
1161  Stream_Seek(_s, _n);
1162  }
1163  }
1164 
1165  static INLINE void Stream_Seek_UINT8(wStream* _s)
1166  {
1167  Stream_Seek(_s, sizeof(UINT8));
1168  }
1169  static INLINE void Stream_Seek_UINT16(wStream* _s)
1170  {
1171  Stream_Seek(_s, sizeof(UINT16));
1172  }
1173  static INLINE void Stream_Seek_UINT32(wStream* _s)
1174  {
1175  Stream_Seek(_s, sizeof(UINT32));
1176  }
1177  static INLINE void Stream_Seek_UINT64(wStream* _s)
1178  {
1179  Stream_Seek(_s, sizeof(UINT64));
1180  }
1181 
1182  static INLINE void Stream_Rewind_UINT8(wStream* _s)
1183  {
1184  Stream_Rewind(_s, sizeof(UINT8));
1185  }
1186  static INLINE void Stream_Rewind_UINT16(wStream* _s)
1187  {
1188  Stream_Rewind(_s, sizeof(UINT16));
1189  }
1190  static INLINE void Stream_Rewind_UINT32(wStream* _s)
1191  {
1192  Stream_Rewind(_s, sizeof(UINT32));
1193  }
1194  static INLINE void Stream_Rewind_UINT64(wStream* _s)
1195  {
1196  Stream_Rewind(_s, sizeof(UINT64));
1197  }
1198 
1199  static INLINE void Stream_Fill(wStream* _s, int _v, size_t _n)
1200  {
1201  WINPR_ASSERT(_s);
1202  WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= (_n));
1203  memset(_s->pointer, _v, (_n));
1204  Stream_Seek(_s, _n);
1205  }
1206 
1207  static INLINE void Stream_Zero(wStream* _s, size_t _n)
1208  {
1209  Stream_Fill(_s, '\0', _n);
1210  }
1211 
1212  static INLINE void Stream_Copy(wStream* _src, wStream* _dst, size_t _n)
1213  {
1214  WINPR_ASSERT(_src);
1215  WINPR_ASSERT(_dst);
1216  WINPR_ASSERT(Stream_GetRemainingCapacity(_src) >= (_n));
1217  WINPR_ASSERT(Stream_GetRemainingCapacity(_dst) >= (_n));
1218 
1219  memcpy(_dst->pointer, _src->pointer, _n);
1220  Stream_Seek(_dst, _n);
1221  Stream_Seek(_src, _n);
1222  }
1223 
1228 #define Stream_BufferAs(s, type) WINPR_STREAM_CAST(type*, Stream_Buffer(s))
1229 
1230  static INLINE BYTE* Stream_Buffer(wStream* _s)
1231  {
1232  WINPR_ASSERT(_s);
1233  return _s->buffer;
1234  }
1235 
1240 #define Stream_ConstBufferAs(s, type) WINPR_STREAM_CAST(type*, Stream_ConstBuffer(s))
1241  static INLINE const BYTE* Stream_ConstBuffer(const wStream* _s)
1242  {
1243  WINPR_ASSERT(_s);
1244  return _s->buffer;
1245  }
1246 
1247 #define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s)
1248 
1253 #define Stream_GetBufferAs(_s, _b) _b = Stream_BufferAs(_s, __typeof(_b))
1254 
1255 #define Stream_PointerAs(s, type) WINPR_STREAM_CAST(type*, Stream_Pointer(s))
1256 
1257  static INLINE void* Stream_Pointer(wStream* _s)
1258  {
1259  WINPR_ASSERT(_s);
1260  return _s->pointer;
1261  }
1262 
1263  static INLINE const void* Stream_ConstPointer(const wStream* _s)
1264  {
1265  WINPR_ASSERT(_s);
1266  return _s->pointer;
1267  }
1268 
1269 #define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s)
1270 
1275 #define Stream_GetPointerAs(_s, _p) _p = Stream_PointerAs(_s, __typeof(_p))
1276 
1277 #if defined(WITH_WINPR_DEPRECATED)
1278  WINPR_API WINPR_DEPRECATED_VAR("Use Stream_SetPosition instead",
1279  BOOL Stream_SetPointer(wStream* _s, BYTE* _p));
1280  WINPR_API WINPR_DEPRECATED_VAR("Use Stream_New(buffer, capacity) instead",
1281  BOOL Stream_SetBuffer(wStream* _s, BYTE* _b));
1282  WINPR_API WINPR_DEPRECATED_VAR("Use Stream_New(buffer, capacity) instead",
1283  void Stream_SetCapacity(wStream* _s, size_t capacity));
1284 #endif
1285 
1286  static INLINE size_t Stream_Length(const wStream* _s)
1287  {
1288  WINPR_ASSERT(_s);
1289  return _s->length;
1290  }
1291 
1292 #define Stream_GetLength(_s, _l) _l = Stream_Length(_s)
1293  WINPR_API BOOL Stream_SetLength(wStream* _s, size_t _l);
1294 
1295  static INLINE size_t Stream_Capacity(const wStream* _s)
1296  {
1297  WINPR_ASSERT(_s);
1298  return _s->capacity;
1299  }
1300 
1301 #define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s);
1302 
1303  static INLINE size_t Stream_GetPosition(const wStream* _s)
1304  {
1305  WINPR_ASSERT(_s);
1306  WINPR_ASSERT(_s->buffer <= _s->pointer);
1307  return WINPR_STREAM_CAST(size_t, (_s->pointer - _s->buffer));
1308  }
1309 
1310  WINPR_API BOOL Stream_SetPosition(wStream* _s, size_t _p);
1311 
1312  WINPR_API void Stream_SealLength(wStream* _s);
1313 
1314  static INLINE void Stream_Clear(wStream* _s)
1315  {
1316  WINPR_ASSERT(_s);
1317  memset(_s->buffer, 0, _s->capacity);
1318  }
1319 
1320 #define Stream_SafeSeek(s, size) Stream_SafeSeekEx(s, size, __FILE__, __LINE__, __func__)
1321  WINPR_API BOOL Stream_SafeSeekEx(wStream* s, size_t size, const char* file, size_t line,
1322  const char* fkt);
1323 
1324  WINPR_API BOOL Stream_Read_UTF16_String(wStream* s, WCHAR* dst, size_t charLength);
1325  WINPR_API BOOL Stream_Write_UTF16_String(wStream* s, const WCHAR* src, size_t charLength);
1326 
1336  WINPR_API char* Stream_Read_UTF16_String_As_UTF8(wStream* s, size_t wcharLength,
1337  size_t* pUtfCharLength);
1338 
1348  WINPR_API SSIZE_T Stream_Read_UTF16_String_As_UTF8_Buffer(wStream* s, size_t wcharLength,
1349  char* utfBuffer,
1350  size_t utfBufferCharLength);
1351 
1363  WINPR_API SSIZE_T Stream_Write_UTF16_String_From_UTF8(wStream* s, size_t wcharLength,
1364  const char* src, size_t length,
1365  BOOL fill);
1366 
1367  /* StreamPool */
1368 
1369  WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s);
1370 
1371  WINPR_API void Stream_AddRef(wStream* s);
1372  WINPR_API void Stream_Release(wStream* s);
1373 
1374  WINPR_ATTR_MALLOC(Stream_Release, 1)
1375  WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size);
1376 
1377  WINPR_API wStream* StreamPool_Find(wStreamPool* pool, const BYTE* ptr);
1378 
1387  WINPR_API size_t StreamPool_UsedCount(wStreamPool* pool);
1388 
1399  WINPR_API BOOL StreamPool_WaitForReturn(wStreamPool* pool, UINT32 timeoutMS);
1400 
1401  WINPR_API void StreamPool_Clear(wStreamPool* pool);
1402 
1403  WINPR_API void StreamPool_Free(wStreamPool* pool);
1404 
1405  WINPR_ATTR_MALLOC(StreamPool_Free, 1)
1406  WINPR_API wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize);
1407 
1408  WINPR_API char* StreamPool_GetStatistics(wStreamPool* pool, char* buffer, size_t size);
1409 
1410 #ifdef __cplusplus
1411 }
1412 #endif
1413 
1414 #endif /* WINPR_UTILS_STREAM_H */