FreeRDP
Loading...
Searching...
No Matches
encoded_types.c
1
21#include <freerdp/config.h>
22
23#include <freerdp/channels/log.h>
24#include <freerdp/utils/encoded_types.h>
25#include <math.h>
26
27#define TAG CHANNELS_TAG("encoded_types")
28
29typedef enum
30{
31 ONE_BYTE_VAL,
32 TWO_BYTE_VAL,
33 THREE_BYTE_VAL,
34 FOUR_BYTE_VAL,
35 FIVE_BYTE_VAL,
36 SIX_BYTE_VAL,
37 SEVEN_BYTE_VAL,
38 EIGHT_BYTE_VAL,
39} EncodedTypeByteCount;
40
41typedef enum
42{
43 POSITIVE_VAL,
44 NEGATIVE_VAL,
45} EncodedTypeSign;
46
47typedef struct
48{
49 EncodedTypeByteCount c;
50 EncodedTypeSign s;
51 BYTE val1;
52 BYTE val2;
53 BYTE val3;
54 BYTE val4;
55} FOUR_BYTE_SIGNED_INTEGER;
56
57typedef struct
58{
59 EncodedTypeByteCount c;
60 EncodedTypeSign s;
61 BYTE e;
62 BYTE val1;
63 BYTE val2;
64 BYTE val3;
65 BYTE val4;
66} FOUR_BYTE_FLOAT;
67
68BOOL freerdp_read_four_byte_signed_integer(wStream* s, INT32* value)
69{
70 FOUR_BYTE_SIGNED_INTEGER si = { 0 };
71 BYTE byte = 0;
72
73 WINPR_ASSERT(s);
74 WINPR_ASSERT(value);
75
76 *value = 0;
77
78 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
79 return FALSE;
80
81 Stream_Read_UINT8(s, byte);
82
83 si.c = (byte & 0xC0) >> 6;
84 si.s = (byte & 0x20) >> 5;
85 si.val1 = (byte & 0x1F);
86
87 if (!Stream_CheckAndLogRequiredLength(TAG, s, si.c))
88 return FALSE;
89
90 switch (si.c)
91 {
92 case ONE_BYTE_VAL:
93 *value = si.val1;
94 break;
95 case TWO_BYTE_VAL:
96 Stream_Read_UINT8(s, si.val2);
97 *value = (((INT32)si.val1) << 8) | ((INT32)si.val2);
98 break;
99 case THREE_BYTE_VAL:
100 Stream_Read_UINT8(s, si.val2);
101 Stream_Read_UINT8(s, si.val3);
102 *value = (((INT32)si.val1) << 16) | (((INT32)si.val2) << 8) | ((INT32)si.val3);
103 break;
104 case FOUR_BYTE_VAL:
105 Stream_Read_UINT8(s, si.val2);
106 Stream_Read_UINT8(s, si.val3);
107 Stream_Read_UINT8(s, si.val4);
108 *value = (((INT32)si.val1) << 24) | (((INT32)si.val2) << 16) | (((INT32)si.val3) << 8) |
109 ((INT32)si.val4);
110 break;
111 case FIVE_BYTE_VAL:
112 case SIX_BYTE_VAL:
113 case SEVEN_BYTE_VAL:
114 case EIGHT_BYTE_VAL:
115 default:
116 WLog_ERR(TAG, "Invalid byte count value in si.c: %u", si.c);
117 return FALSE;
118 }
119
120 if (si.s == NEGATIVE_VAL)
121 *value *= -1;
122
123 return TRUE;
124}
125
126BOOL freerdp_write_four_byte_signed_integer(wStream* s, INT32 value)
127{
128 FOUR_BYTE_SIGNED_INTEGER si = { 0 };
129
130 WINPR_ASSERT(s);
131 if (value > FREERDP_FOUR_BYTE_SIGNED_INT_MAX)
132 return FALSE;
133 if (value < FREERDP_FOUR_BYTE_SIGNED_INT_MIN)
134 return FALSE;
135
136 if (value < 0)
137 {
138 si.s = NEGATIVE_VAL;
139 value = -value;
140 }
141
142 if (value <= 0x1F)
143 {
144 si.c = ONE_BYTE_VAL;
145 si.val1 = value & 0x1f;
146 }
147 else if (value <= 0x1FFF)
148 {
149 si.c = TWO_BYTE_VAL;
150 si.val1 = (value >> 8) & 0x1f;
151 si.val2 = value & 0xff;
152 }
153 else if (value <= 0x1FFFFF)
154 {
155 si.c = THREE_BYTE_VAL;
156 si.val1 = (value >> 16) & 0x1f;
157 si.val2 = (value >> 8) & 0xff;
158 si.val3 = value & 0xff;
159 }
160 else if (value <= 0x1FFFFFFF)
161 {
162 si.c = FOUR_BYTE_VAL;
163 si.val1 = (value >> 24) & 0x1f;
164 si.val2 = (value >> 16) & 0xff;
165 si.val3 = (value >> 8) & 0xff;
166 si.val4 = value & 0xff;
167 }
168 else
169 {
170 WLog_ERR(TAG, "Invalid byte count for value %" PRId32, value);
171 return FALSE;
172 }
173
174 if (!Stream_EnsureRemainingCapacity(s, si.c + 1))
175 return FALSE;
176
177 const BYTE byte = ((si.c << 6) & 0xC0) | ((si.s << 5) & 0x20) | (si.val1 & 0x1F);
178 Stream_Write_UINT8(s, byte);
179
180 switch (si.c)
181 {
182 case ONE_BYTE_VAL:
183 break;
184 case TWO_BYTE_VAL:
185 Stream_Write_UINT8(s, si.val2);
186 break;
187 case THREE_BYTE_VAL:
188 Stream_Write_UINT8(s, si.val2);
189 Stream_Write_UINT8(s, si.val3);
190 break;
191 case FOUR_BYTE_VAL:
192 Stream_Write_UINT8(s, si.val2);
193 Stream_Write_UINT8(s, si.val3);
194 Stream_Write_UINT8(s, si.val4);
195 break;
196 case FIVE_BYTE_VAL:
197 case SIX_BYTE_VAL:
198 case SEVEN_BYTE_VAL:
199 case EIGHT_BYTE_VAL:
200 default:
201 WLog_ERR(TAG, "Invalid byte count value in si.c: %u", si.c);
202 return FALSE;
203 }
204
205 return TRUE;
206}
207
208BOOL freerdp_read_four_byte_float(wStream* s, double* value)
209{
210 return freerdp_read_four_byte_float_exp(s, value, NULL);
211}
212
213BOOL freerdp_read_four_byte_float_exp(wStream* s, double* value, BYTE* exp)
214{
215 FOUR_BYTE_FLOAT f = { 0 };
216 UINT32 base = 0;
217 BYTE byte = 0;
218
219 WINPR_ASSERT(s);
220 WINPR_ASSERT(value);
221
222 *value = 0.0;
223
224 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
225 return FALSE;
226
227 Stream_Read_UINT8(s, byte);
228
229 f.c = (byte & 0xC0) >> 6;
230 f.s = (byte & 0x20) >> 5;
231 f.e = (byte & 0x1C) >> 2;
232 f.val1 = (byte & 0x03);
233
234 if (!Stream_CheckAndLogRequiredLength(TAG, s, f.c))
235 return FALSE;
236
237 switch (f.c)
238 {
239 case ONE_BYTE_VAL:
240 base = f.val1;
241 break;
242 case TWO_BYTE_VAL:
243 Stream_Read_UINT8(s, f.val2);
244 base = (((UINT32)f.val1) << 8) | ((UINT32)f.val2);
245 break;
246 case THREE_BYTE_VAL:
247 Stream_Read_UINT8(s, f.val2);
248 Stream_Read_UINT8(s, f.val3);
249 base = (((UINT32)f.val1) << 16) | (((UINT32)f.val2) << 8) | ((UINT32)f.val3);
250 break;
251 case FOUR_BYTE_VAL:
252 Stream_Read_UINT8(s, f.val2);
253 Stream_Read_UINT8(s, f.val3);
254 Stream_Read_UINT8(s, f.val4);
255 base = (((UINT32)f.val1) << 24) | (((UINT32)f.val2) << 16) | (((UINT32)f.val3) << 8) |
256 ((UINT32)f.val4);
257 break;
258 case FIVE_BYTE_VAL:
259 case SIX_BYTE_VAL:
260 case SEVEN_BYTE_VAL:
261 case EIGHT_BYTE_VAL:
262 default:
263 WLog_ERR(TAG, "Invalid byte count value in f.c: %u", f.c);
264 return FALSE;
265 }
266
267 *value = base;
268 *value /= pow(10, f.e);
269
270 if (f.s == NEGATIVE_VAL)
271 *value *= -1.0;
272
273 if (exp)
274 *exp = f.e;
275
276 return TRUE;
277}
278
279BOOL freerdp_write_four_byte_float(wStream* s, double value)
280{
281 FOUR_BYTE_FLOAT si = { 0 };
282
283 WINPR_ASSERT(s);
284
285 if (value > FREERDP_FOUR_BYTE_FLOAT_MAX)
286 return FALSE;
287 if (value < FREERDP_FOUR_BYTE_FLOAT_MIN)
288 return FALSE;
289
290 if (value < 0)
291 {
292 si.s = NEGATIVE_VAL;
293 value = -value;
294 }
295
296 int exp = 0;
297 double ival = FP_NAN;
298 const double aval = fabs(value);
299 const double frac = modf(aval, &ival);
300 if (frac != 0.0)
301 {
302 const double maxfrac = frac * 10000000.0;
303 if (maxfrac <= 1.0)
304 exp = 0;
305 else if (maxfrac <= 10.0)
306 exp = 1;
307 else if (maxfrac <= 100.0)
308 exp = 2;
309 else if (maxfrac <= 1000.0)
310 exp = 3;
311 else if (maxfrac <= 10000.0)
312 exp = 4;
313 else if (maxfrac <= 100000.0)
314 exp = 5;
315 else if (maxfrac <= 1000000.0)
316 exp = 6;
317 else
318 exp = 7;
319 }
320
321 UINT64 base = (UINT64)llround(aval);
322 while (exp >= 0)
323 {
324 const double div = pow(10.0, exp);
325 const double dval = (aval * div);
326 base = (UINT64)dval;
327 if (base <= 0x03ffffff)
328 break;
329 exp--;
330 }
331
332 if (exp < 0)
333 return FALSE;
334
335 si.e = (BYTE)exp;
336 if (base <= 0x03)
337 {
338 si.c = ONE_BYTE_VAL;
339 si.val1 = base & 0x03;
340 }
341 else if (base <= 0x03ff)
342 {
343 si.c = TWO_BYTE_VAL;
344 si.val1 = (base >> 8) & 0x03;
345 si.val2 = base & 0xff;
346 }
347 else if (base <= 0x03ffff)
348 {
349 si.c = THREE_BYTE_VAL;
350 si.val1 = (base >> 16) & 0x03;
351 si.val2 = (base >> 8) & 0xff;
352 si.val3 = base & 0xff;
353 }
354 else if (base <= 0x03ffffff)
355 {
356 si.c = FOUR_BYTE_VAL;
357 si.val1 = (base >> 24) & 0x03;
358 si.val2 = (base >> 16) & 0xff;
359 si.val3 = (base >> 8) & 0xff;
360 si.val4 = base & 0xff;
361 }
362 else
363 {
364 WLog_ERR(TAG, "Invalid byte count for value %ld", value);
365 return FALSE;
366 }
367
368 if (!Stream_EnsureRemainingCapacity(s, si.c + 1))
369 return FALSE;
370
371 const BYTE byte =
372 ((si.c << 6) & 0xC0) | ((si.s << 5) & 0x20) | ((si.e << 2) & 0x1c) | (si.val1 & 0x03);
373 Stream_Write_UINT8(s, byte);
374
375 switch (si.c)
376 {
377 case ONE_BYTE_VAL:
378 break;
379 case TWO_BYTE_VAL:
380 Stream_Write_UINT8(s, si.val2);
381 break;
382 case THREE_BYTE_VAL:
383 Stream_Write_UINT8(s, si.val2);
384 Stream_Write_UINT8(s, si.val3);
385 break;
386 case FOUR_BYTE_VAL:
387 Stream_Write_UINT8(s, si.val2);
388 Stream_Write_UINT8(s, si.val3);
389 Stream_Write_UINT8(s, si.val4);
390 break;
391 case FIVE_BYTE_VAL:
392 case SIX_BYTE_VAL:
393 case SEVEN_BYTE_VAL:
394 case EIGHT_BYTE_VAL:
395 default:
396 WLog_ERR(TAG, "Invalid byte count value in si.c: %u", si.c);
397 return FALSE;
398 }
399
400 return TRUE;
401}