FreeRDP
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 
29 typedef 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 
41 typedef enum
42 {
43  POSITIVE_VAL,
44  NEGATIVE_VAL,
45 } EncodedTypeSign;
46 
47 typedef 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 
57 typedef 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 
68 BOOL 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 
126 BOOL 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 
208 BOOL freerdp_read_four_byte_float(wStream* s, double* value)
209 {
210  return freerdp_read_four_byte_float_exp(s, value, NULL);
211 }
212 
213 BOOL 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 
279 BOOL 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 }