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 
31 #ifdef __cplusplus
32 extern "C"
33 {
34 #endif
35 
36 	typedef struct _wStreamPool wStreamPool;
37 
38 	struct _wStream
39 	{
40 		BYTE* buffer;
41 		BYTE* pointer;
42 		size_t length;
43 		size_t capacity;
44 
45 		DWORD count;
46 		wStreamPool* pool;
47 		BOOL isAllocatedStream;
48 		BOOL isOwner;
49 	};
50 	typedef struct _wStream wStream;
51 
52 	WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size);
53 	WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size);
54 
55 	WINPR_API wStream* Stream_New(BYTE* buffer, size_t size);
56 	WINPR_API void Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
57 	WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
58 
Stream_Seek(wStream * s,size_t _offset)59 	static INLINE void Stream_Seek(wStream* s, size_t _offset)
60 	{
61 		s->pointer += (_offset);
62 	}
63 
Stream_Rewind(wStream * s,size_t _offset)64 	static INLINE void Stream_Rewind(wStream* s, size_t _offset)
65 	{
66 		s->pointer -= (_offset);
67 	}
68 
69 #define _stream_read_n8(_t, _s, _v, _p)  \
70 	do                                   \
71 	{                                    \
72 		(_v) = (_t)(*(_s)->pointer);     \
73 		if (_p)                          \
74 			Stream_Seek(_s, sizeof(_t)); \
75 	} while (0)
76 
77 #define _stream_read_n16_le(_t, _s, _v, _p)                                      \
78 	do                                                                           \
79 	{                                                                            \
80 		(_v) = (_t)((*(_s)->pointer) + (((UINT16)(*((_s)->pointer + 1))) << 8)); \
81 		if (_p)                                                                  \
82 			Stream_Seek(_s, sizeof(_t));                                         \
83 	} while (0)
84 
85 #define _stream_read_n16_be(_t, _s, _v, _p)                                              \
86 	do                                                                                   \
87 	{                                                                                    \
88 		(_v) = (_t)((((UINT16)(*(_s)->pointer)) << 8) + (UINT16)(*((_s)->pointer + 1))); \
89 		if (_p)                                                                          \
90 			Stream_Seek(_s, sizeof(_t));                                                 \
91 	} while (0)
92 
93 #define _stream_read_n32_le(_t, _s, _v, _p)                                              \
94 	do                                                                                   \
95 	{                                                                                    \
96 		(_v) = (_t)((UINT32)(*(_s)->pointer) + (((UINT32)(*((_s)->pointer + 1))) << 8) + \
97 		            (((UINT32)(*((_s)->pointer + 2))) << 16) +                           \
98 		            ((((UINT32) * ((_s)->pointer + 3))) << 24));                         \
99 		if (_p)                                                                          \
100 			Stream_Seek(_s, sizeof(_t));                                                 \
101 	} while (0)
102 
103 #define _stream_read_n32_be(_t, _s, _v, _p)                                                        \
104 	do                                                                                             \
105 	{                                                                                              \
106 		(_v) = (_t)(((((UINT32) * ((_s)->pointer))) << 24) +                                       \
107 		            (((UINT32)(*((_s)->pointer + 1))) << 16) +                                     \
108 		            (((UINT32)(*((_s)->pointer + 2))) << 8) + (((UINT32)(*((_s)->pointer + 3))))); \
109 		if (_p)                                                                                    \
110 			Stream_Seek(_s, sizeof(_t));                                                           \
111 	} while (0)
112 
113 #define _stream_read_n64_le(_t, _s, _v, _p)                                                       \
114 	do                                                                                            \
115 	{                                                                                             \
116 		(_v) = (_t)(                                                                              \
117 		    (UINT64)(*(_s)->pointer) + (((UINT64)(*((_s)->pointer + 1))) << 8) +                  \
118 		    (((UINT64)(*((_s)->pointer + 2))) << 16) + (((UINT64)(*((_s)->pointer + 3))) << 24) + \
119 		    (((UINT64)(*((_s)->pointer + 4))) << 32) + (((UINT64)(*((_s)->pointer + 5))) << 40) + \
120 		    (((UINT64)(*((_s)->pointer + 6))) << 48) + (((UINT64)(*((_s)->pointer + 7))) << 56)); \
121 		if (_p)                                                                                   \
122 			Stream_Seek(_s, sizeof(_t));                                                          \
123 	} while (0)
124 
125 #define _stream_read_n64_be(_t, _s, _v, _p)                                                       \
126 	do                                                                                            \
127 	{                                                                                             \
128 		(_v) = (_t)(                                                                              \
129 		    (((UINT64)(*((_s)->pointer))) << 56) + (((UINT64)(*((_s)->pointer + 1))) << 48) +     \
130 		    (((UINT64)(*((_s)->pointer + 2))) << 40) + (((UINT64)(*((_s)->pointer + 3))) << 32) + \
131 		    (((UINT64)(*((_s)->pointer + 4))) << 24) + (((UINT64)(*((_s)->pointer + 5))) << 16) + \
132 		    (((UINT64)(*((_s)->pointer + 6))) << 8) + (((UINT64)(*((_s)->pointer + 7)))));        \
133 		if (_p)                                                                                   \
134 			Stream_Seek(_s, sizeof(_t));                                                          \
135 	} while (0)
136 
137 #define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, TRUE)
138 #define Stream_Read_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, TRUE)
139 
140 #define Stream_Read_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, TRUE)
141 #define Stream_Read_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, TRUE)
142 
143 #define Stream_Read_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, TRUE)
144 #define Stream_Read_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, TRUE)
145 
146 #define Stream_Read_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, TRUE)
147 #define Stream_Read_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, TRUE)
148 
149 #define Stream_Read_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, TRUE)
150 #define Stream_Read_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, TRUE)
151 
152 #define Stream_Read_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, TRUE)
153 #define Stream_Read_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, TRUE)
154 
155 #define Stream_Read_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, TRUE)
156 #define Stream_Read_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, TRUE)
157 
Stream_Read(wStream * _s,void * _b,size_t _n)158 	static INLINE void Stream_Read(wStream* _s, void* _b, size_t _n)
159 	{
160 		memcpy(_b, (_s->pointer), (_n));
161 		Stream_Seek(_s, _n);
162 	}
163 
164 #define Stream_Peek_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, FALSE)
165 #define Stream_Peek_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, FALSE)
166 
167 #define Stream_Peek_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, FALSE)
168 #define Stream_Peek_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, FALSE)
169 
170 #define Stream_Peek_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, FALSE)
171 #define Stream_Peek_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, FALSE)
172 
173 #define Stream_Peek_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, FALSE)
174 #define Stream_Peek_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, FALSE)
175 
176 #define Stream_Peek_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, FALSE)
177 #define Stream_Peek_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, FALSE)
178 
179 #define Stream_Peek_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, FALSE)
180 #define Stream_Peek_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, FALSE)
181 
182 #define Stream_Peek_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, FALSE)
183 #define Stream_Peek_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, FALSE)
184 
Stream_Peek(wStream * _s,void * _b,size_t _n)185 	static INLINE void Stream_Peek(wStream* _s, void* _b, size_t _n)
186 	{
187 		memcpy(_b, (_s->pointer), (_n));
188 	}
189 
Stream_Write_UINT8(wStream * _s,UINT8 _v)190 	static INLINE void Stream_Write_UINT8(wStream* _s, UINT8 _v)
191 	{
192 		*_s->pointer++ = (UINT8)(_v);
193 	}
194 
Stream_Write_INT16(wStream * _s,INT16 _v)195 	static INLINE void Stream_Write_INT16(wStream* _s, INT16 _v)
196 	{
197 		*_s->pointer++ = (_v)&0xFF;
198 		*_s->pointer++ = ((_v) >> 8) & 0xFF;
199 	}
200 
Stream_Write_UINT16(wStream * _s,UINT16 _v)201 	static INLINE void Stream_Write_UINT16(wStream* _s, UINT16 _v)
202 	{
203 		*_s->pointer++ = (_v)&0xFF;
204 		*_s->pointer++ = ((_v) >> 8) & 0xFF;
205 	}
206 
Stream_Write_UINT16_BE(wStream * _s,UINT16 _v)207 	static INLINE void Stream_Write_UINT16_BE(wStream* _s, UINT16 _v)
208 	{
209 		*_s->pointer++ = ((_v) >> 8) & 0xFF;
210 		*_s->pointer++ = (_v)&0xFF;
211 	}
212 
Stream_Write_INT32(wStream * _s,INT32 _v)213 	static INLINE void Stream_Write_INT32(wStream* _s, INT32 _v)
214 	{
215 		*_s->pointer++ = (_v)&0xFF;
216 		*_s->pointer++ = ((_v) >> 8) & 0xFF;
217 		*_s->pointer++ = ((_v) >> 16) & 0xFF;
218 		*_s->pointer++ = ((_v) >> 24) & 0xFF;
219 	}
220 
Stream_Write_UINT32(wStream * _s,UINT32 _v)221 	static INLINE void Stream_Write_UINT32(wStream* _s, UINT32 _v)
222 	{
223 		*_s->pointer++ = (_v)&0xFF;
224 		*_s->pointer++ = ((_v) >> 8) & 0xFF;
225 		*_s->pointer++ = ((_v) >> 16) & 0xFF;
226 		*_s->pointer++ = ((_v) >> 24) & 0xFF;
227 	}
228 
Stream_Write_UINT32_BE(wStream * _s,UINT32 _v)229 	static INLINE void Stream_Write_UINT32_BE(wStream* _s, UINT32 _v)
230 	{
231 		Stream_Write_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF));
232 		Stream_Write_UINT16_BE(_s, ((_v)&0xFFFF));
233 	}
234 
Stream_Write_UINT64(wStream * _s,UINT64 _v)235 	static INLINE void Stream_Write_UINT64(wStream* _s, UINT64 _v)
236 	{
237 		*_s->pointer++ = (UINT64)(_v)&0xFF;
238 		*_s->pointer++ = ((UINT64)(_v) >> 8) & 0xFF;
239 		*_s->pointer++ = ((UINT64)(_v) >> 16) & 0xFF;
240 		*_s->pointer++ = ((UINT64)(_v) >> 24) & 0xFF;
241 		*_s->pointer++ = ((UINT64)(_v) >> 32) & 0xFF;
242 		*_s->pointer++ = ((UINT64)(_v) >> 40) & 0xFF;
243 		*_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF;
244 		*_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF;
245 	}
Stream_Write(wStream * _s,const void * _b,size_t _n)246 	static INLINE void Stream_Write(wStream* _s, const void* _b, size_t _n)
247 	{
248 		if (_n > 0)
249 		{
250 			memcpy(_s->pointer, (_b), (_n));
251 			Stream_Seek(_s, _n);
252 		}
253 	}
254 
255 #define Stream_Seek_UINT8(_s) Stream_Seek(_s, 1)
256 #define Stream_Seek_UINT16(_s) Stream_Seek(_s, 2)
257 #define Stream_Seek_UINT32(_s) Stream_Seek(_s, 4)
258 #define Stream_Seek_UINT64(_s) Stream_Seek(_s, 8)
259 
260 #define Stream_Rewind_UINT8(_s) Stream_Rewind(_s, 1)
261 #define Stream_Rewind_UINT16(_s) Stream_Rewind(_s, 2)
262 #define Stream_Rewind_UINT32(_s) Stream_Rewind(_s, 4)
263 #define Stream_Rewind_UINT64(_s) Stream_Rewind(_s, 8)
264 
Stream_Zero(wStream * _s,size_t _n)265 	static INLINE void Stream_Zero(wStream* _s, size_t _n)
266 	{
267 		memset(_s->pointer, '\0', (_n));
268 		Stream_Seek(_s, _n);
269 	}
270 
Stream_Fill(wStream * _s,int _v,size_t _n)271 	static INLINE void Stream_Fill(wStream* _s, int _v, size_t _n)
272 	{
273 		memset(_s->pointer, _v, (_n));
274 		Stream_Seek(_s, _n);
275 	}
276 
Stream_Copy(wStream * _src,wStream * _dst,size_t _n)277 	static INLINE void Stream_Copy(wStream* _src, wStream* _dst, size_t _n)
278 	{
279 		memcpy(_dst->pointer, _src->pointer, _n);
280 		Stream_Seek(_dst, _n);
281 		Stream_Seek(_src, _n);
282 	}
283 
Stream_Buffer(wStream * _s)284 	static INLINE BYTE* Stream_Buffer(wStream* _s)
285 	{
286 		return _s->buffer;
287 	}
288 
289 #define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s)
Stream_SetBuffer(wStream * _s,BYTE * _b)290 	static INLINE void Stream_SetBuffer(wStream* _s, BYTE* _b)
291 	{
292 		_s->buffer = _b;
293 	}
294 
Stream_Pointer(wStream * _s)295 	static INLINE BYTE* Stream_Pointer(wStream* _s)
296 	{
297 		return _s->pointer;
298 	}
299 
300 #define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s)
Stream_SetPointer(wStream * _s,BYTE * _p)301 	static INLINE void Stream_SetPointer(wStream* _s, BYTE* _p)
302 	{
303 		_s->pointer = _p;
304 	}
305 
Stream_Length(wStream * _s)306 	static INLINE size_t Stream_Length(wStream* _s)
307 	{
308 		return _s->length;
309 	}
310 
311 #define Stream_GetLength(_s, _l) _l = Stream_Length(_s)
Stream_SetLength(wStream * _s,size_t _l)312 	static INLINE void Stream_SetLength(wStream* _s, size_t _l)
313 	{
314 		_s->length = _l;
315 	}
316 
Stream_Capacity(wStream * _s)317 	static INLINE size_t Stream_Capacity(wStream* _s)
318 	{
319 		return _s->capacity;
320 	}
321 
322 #define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s);
Stream_SetCapacity(wStream * _s,size_t _c)323 	static INLINE void Stream_SetCapacity(wStream* _s, size_t _c)
324 	{
325 		_s->capacity = _c;
326 	}
327 
Stream_GetPosition(wStream * _s)328 	static INLINE size_t Stream_GetPosition(wStream* _s)
329 	{
330 		return (_s->pointer - _s->buffer);
331 	}
332 
Stream_SetPosition(wStream * _s,size_t _p)333 	static INLINE void Stream_SetPosition(wStream* _s, size_t _p)
334 	{
335 		_s->pointer = _s->buffer + (_p);
336 	}
337 
Stream_SealLength(wStream * _s)338 	static INLINE void Stream_SealLength(wStream* _s)
339 	{
340 		_s->length = (_s->pointer - _s->buffer);
341 	}
342 
Stream_GetRemainingCapacity(wStream * _s)343 	static INLINE size_t Stream_GetRemainingCapacity(wStream* _s)
344 	{
345 		return (_s->capacity - (_s->pointer - _s->buffer));
346 	}
347 
Stream_GetRemainingLength(wStream * _s)348 	static INLINE size_t Stream_GetRemainingLength(wStream* _s)
349 	{
350 		return (_s->length - (_s->pointer - _s->buffer));
351 	}
352 
Stream_Clear(wStream * _s)353 	static INLINE void Stream_Clear(wStream* _s)
354 	{
355 		memset(_s->buffer, 0, _s->capacity);
356 	}
357 
Stream_SafeSeek(wStream * s,size_t size)358 	static INLINE BOOL Stream_SafeSeek(wStream* s, size_t size)
359 	{
360 		if (Stream_GetRemainingLength(s) < size)
361 			return FALSE;
362 
363 		Stream_Seek(s, size);
364 		return TRUE;
365 	}
366 
Stream_Read_UTF16_String(wStream * s,WCHAR * dst,size_t length)367 	static INLINE BOOL Stream_Read_UTF16_String(wStream* s, WCHAR* dst, size_t length)
368 	{
369 		size_t x;
370 
371 		if (!s || !dst)
372 			return FALSE;
373 
374 		if (Stream_GetRemainingLength(s) / sizeof(WCHAR) < length)
375 			return FALSE;
376 
377 		for (x = 0; x < length; x++)
378 			Stream_Read_UINT16(s, dst[x]);
379 
380 		return TRUE;
381 	}
382 
Stream_Write_UTF16_String(wStream * s,const WCHAR * src,size_t length)383 	static INLINE BOOL Stream_Write_UTF16_String(wStream* s, const WCHAR* src, size_t length)
384 	{
385 		size_t x;
386 
387 		if (!s || !src)
388 			return FALSE;
389 
390 		if (Stream_GetRemainingCapacity(s) / sizeof(WCHAR) < length)
391 			return FALSE;
392 
393 		for (x = 0; x < length; x++)
394 			Stream_Write_UINT16(s, src[x]);
395 
396 		return TRUE;
397 	}
398 
399 	/* StreamPool */
400 
401 	struct _wStreamPool
402 	{
403 		int aSize;
404 		int aCapacity;
405 		wStream** aArray;
406 
407 		int uSize;
408 		int uCapacity;
409 		wStream** uArray;
410 
411 		CRITICAL_SECTION lock;
412 		BOOL synchronized;
413 		size_t defaultSize;
414 	};
415 
416 	WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size);
417 	WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s);
418 
419 	WINPR_API void Stream_AddRef(wStream* s);
420 	WINPR_API void Stream_Release(wStream* s);
421 
422 	WINPR_API wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr);
423 	WINPR_API void StreamPool_AddRef(wStreamPool* pool, BYTE* ptr);
424 	WINPR_API void StreamPool_Release(wStreamPool* pool, BYTE* ptr);
425 
426 	WINPR_API void StreamPool_Clear(wStreamPool* pool);
427 
428 	WINPR_API wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize);
429 	WINPR_API void StreamPool_Free(wStreamPool* pool);
430 
431 #ifdef __cplusplus
432 }
433 #endif
434 
435 #endif /* WINPR_UTILS_STREAM_H */
436