Coverage Report

Created: 2024-02-25 07:20

/src/libfwsi/libfwsi/libfwsi_compressed_folder_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Compressed folder (shell item) values functions
3
 *
4
 * Copyright (C) 2010-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libfwsi_compressed_folder_values.h"
28
#include "libfwsi_debug.h"
29
#include "libfwsi_definitions.h"
30
#include "libfwsi_libcerror.h"
31
#include "libfwsi_libcnotify.h"
32
#include "libfwsi_libfdatetime.h"
33
#include "libfwsi_libuna.h"
34
#include "libfwsi_unused.h"
35
36
/* Creates compressed folder values
37
 * Make sure the value compressed_folder_values is referencing, is set to NULL
38
 * Returns 1 if successful or -1 on error
39
 */
40
int libfwsi_compressed_folder_values_initialize(
41
     libfwsi_compressed_folder_values_t **compressed_folder_values,
42
     libcerror_error_t **error )
43
0
{
44
0
  static char *function = "libfwsi_compressed_folder_values_initialize";
45
46
0
  if( compressed_folder_values == NULL )
47
0
  {
48
0
    libcerror_error_set(
49
0
     error,
50
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
51
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
52
0
     "%s: invalid compressed folder values.",
53
0
     function );
54
55
0
    return( -1 );
56
0
  }
57
0
  if( *compressed_folder_values != NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
62
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
63
0
     "%s: invalid compressed folder values value already set.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
0
  *compressed_folder_values = memory_allocate_structure(
69
0
                               libfwsi_compressed_folder_values_t );
70
71
0
  if( *compressed_folder_values == NULL )
72
0
  {
73
0
    libcerror_error_set(
74
0
     error,
75
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
76
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
77
0
     "%s: unable to create compressed folder values.",
78
0
     function );
79
80
0
    goto on_error;
81
0
  }
82
0
  if( memory_set(
83
0
       *compressed_folder_values,
84
0
       0,
85
0
       sizeof( libfwsi_compressed_folder_values_t ) ) == NULL )
86
0
  {
87
0
    libcerror_error_set(
88
0
     error,
89
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
90
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
91
0
     "%s: unable to clear compressed folder values.",
92
0
     function );
93
94
0
    goto on_error;
95
0
  }
96
0
  return( 1 );
97
98
0
on_error:
99
0
  if( *compressed_folder_values != NULL )
100
0
  {
101
0
    memory_free(
102
0
     *compressed_folder_values );
103
104
0
    *compressed_folder_values = NULL;
105
0
  }
106
0
  return( -1 );
107
0
}
108
109
/* Frees compressed folder values
110
 * Returns 1 if successful or -1 on error
111
 */
112
int libfwsi_compressed_folder_values_free(
113
     libfwsi_compressed_folder_values_t **compressed_folder_values,
114
     libcerror_error_t **error )
115
0
{
116
0
  static char *function = "libfwsi_compressed_folder_values_free";
117
118
0
  if( compressed_folder_values == NULL )
119
0
  {
120
0
    libcerror_error_set(
121
0
     error,
122
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
123
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
124
0
     "%s: invalid compressed folder values.",
125
0
     function );
126
127
0
    return( -1 );
128
0
  }
129
0
  if( *compressed_folder_values != NULL )
130
0
  {
131
0
    memory_free(
132
0
     *compressed_folder_values );
133
134
0
    *compressed_folder_values = NULL;
135
0
  }
136
0
  return( 1 );
137
0
}
138
139
/* Reads the compressed folder values
140
 * Returns 1 if successful, 0 if not supported or -1 on error
141
 */
142
int libfwsi_compressed_folder_values_read_data(
143
     libfwsi_compressed_folder_values_t *compressed_folder_values,
144
     const uint8_t *data,
145
     size_t data_size,
146
     libcerror_error_t **error )
147
0
{
148
0
  static char *function = "libfwsi_compressed_folder_values_read_data";
149
0
  size_t data_offset    = 0;
150
0
  uint32_t string_size  = 0;
151
152
#if defined( HAVE_DEBUG_OUTPUT )
153
  uint64_t value_64bit  = 0;
154
  uint32_t value_32bit  = 0;
155
  uint16_t value_16bit  = 0;
156
#endif
157
158
0
  if( compressed_folder_values == NULL )
159
0
  {
160
0
    libcerror_error_set(
161
0
     error,
162
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
163
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
164
0
     "%s: invalid compressed folder values.",
165
0
     function );
166
167
0
    return( -1 );
168
0
  }
169
0
  if( data == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
175
0
     "%s: invalid data.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
0
  if( data_size > (size_t) SSIZE_MAX )
181
0
  {
182
0
    libcerror_error_set(
183
0
     error,
184
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
185
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
186
0
     "%s: data size exceeds maximum.",
187
0
     function );
188
189
0
    return( -1 );
190
0
  }
191
  /* Do not try to parse unsupported data sizes
192
   */
193
0
  if( data_size < 6 )
194
0
  {
195
0
    return( 0 );
196
0
  }
197
  /* Do not try to parse unknown class type indicators
198
   */
199
0
  if( data[ 2 ] != 0x52 )
200
0
  {
201
0
    return( 0 );
202
0
  }
203
/* TODO: other variants not supported yet */
204
0
  if( ( data[ 3 ] != 0x67 )
205
0
   || ( data[ 4 ] != 0xb1 )
206
0
   || ( data[ 5 ] != 0xac ) )
207
0
  {
208
0
    return( 0 );
209
0
  }
210
0
  if( ( data[ 3 ] == 0x67 )
211
0
   && ( data[ 4 ] == 0xb1 )
212
0
   && ( data[ 5 ] == 0xac ) )
213
0
  {
214
0
    if( data_size < 50 )
215
0
    {
216
0
      return( 0 );
217
0
    }
218
#if defined( HAVE_DEBUG_OUTPUT )
219
    if( libcnotify_verbose != 0 )
220
    {
221
      libcnotify_printf(
222
       "%s: unknown1\t\t\t\t: 0x%02" PRIx8 "\n",
223
       function,
224
       data[ 3 ] );
225
226
      byte_stream_copy_to_uint16_little_endian(
227
       &( data[ 4 ] ),
228
       value_16bit );
229
      libcnotify_printf(
230
       "%s: unknown2\t\t\t\t: 0x%04" PRIx16 "\n",
231
       function,
232
       value_16bit );
233
234
      byte_stream_copy_to_uint32_little_endian(
235
       &( data[ 6 ] ),
236
       value_32bit );
237
      libcnotify_printf(
238
       "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n",
239
       function,
240
       value_32bit );
241
242
      byte_stream_copy_to_uint64_little_endian(
243
       &( data[ 10 ] ),
244
       value_64bit );
245
      libcnotify_printf(
246
       "%s: unknown4\t\t\t\t: 0x%08" PRIx64 "\n",
247
       function,
248
       value_64bit );
249
250
      byte_stream_copy_to_uint32_little_endian(
251
       &( data[ 18 ] ),
252
       value_32bit );
253
      libcnotify_printf(
254
       "%s: unknown5\t\t\t\t: 0x%08" PRIx32 "\n",
255
       function,
256
       value_32bit );
257
258
      byte_stream_copy_to_uint32_little_endian(
259
       &( data[ 22 ] ),
260
       value_32bit );
261
      libcnotify_printf(
262
       "%s: unknown6\t\t\t\t: 0x%08" PRIx32 "\n",
263
       function,
264
       value_32bit );
265
266
      if( libfwsi_debug_print_fat_date_time_value(
267
           function,
268
           "unknown time1\t\t\t",
269
           &( data[ 26 ] ),
270
           4,
271
           LIBFDATETIME_ENDIAN_LITTLE,
272
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
273
           error ) != 1 )
274
      {
275
        libcerror_error_set(
276
         error,
277
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
278
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
279
         "%s: unable to print FAT date time value.",
280
         function );
281
282
        return( -1 );
283
      }
284
      byte_stream_copy_to_uint32_little_endian(
285
       &( data[ 30 ] ),
286
       value_32bit );
287
      libcnotify_printf(
288
       "%s: unknown7\t\t\t\t: 0x%08" PRIx32 "\n",
289
       function,
290
       value_32bit );
291
292
      if( libfwsi_debug_print_fat_date_time_value(
293
           function,
294
           "unknown time2\t\t\t",
295
           &( data[ 34 ] ),
296
           4,
297
           LIBFDATETIME_ENDIAN_LITTLE,
298
           LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
299
           error ) != 1 )
300
      {
301
        libcerror_error_set(
302
         error,
303
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
304
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
305
         "%s: unable to print FAT date time value.",
306
         function );
307
308
        return( -1 );
309
      }
310
      byte_stream_copy_to_uint64_little_endian(
311
       &( data[ 38 ] ),
312
       value_64bit );
313
      libcnotify_printf(
314
       "%s: unknown8\t\t\t\t: 0x%08" PRIx64 "\n",
315
       function,
316
       value_64bit );
317
    }
318
#endif
319
0
    data_offset = 46;
320
0
  }
321
0
  byte_stream_copy_to_uint32_little_endian(
322
0
   &( data[ data_offset ] ),
323
0
   string_size );
324
325
#if defined( HAVE_DEBUG_OUTPUT )
326
  if( libcnotify_verbose != 0 )
327
  {
328
    libcnotify_printf(
329
     "%s: string size\t\t\t: %" PRIu32 "\n",
330
     function,
331
     string_size );
332
  }
333
#endif
334
0
  data_offset += 4;
335
336
0
  string_size *= 2;
337
338
0
  if( ( string_size > 0 )
339
0
         && ( string_size <= data_size )
340
0
   && ( data_offset <= ( data_size - string_size ) ) )
341
0
  {
342
#if defined( HAVE_DEBUG_OUTPUT )
343
    if( libcnotify_verbose != 0 )
344
    {
345
      if( libfwsi_debug_print_utf16_string_value(
346
           function,
347
           "string\t\t\t\t",
348
           &( data[ data_offset ] ),
349
           string_size,
350
           LIBUNA_ENDIAN_LITTLE,
351
           error ) != 1 )
352
      {
353
        libcerror_error_set(
354
         error,
355
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
356
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
357
         "%s: unable to print UTF-16 string value.",
358
         function );
359
360
        return( -1 );
361
      }
362
    }
363
#endif
364
0
    data_offset += string_size;
365
0
  }
366
0
  byte_stream_copy_to_uint32_little_endian(
367
0
   &( data[ data_offset ] ),
368
0
   string_size );
369
370
#if defined( HAVE_DEBUG_OUTPUT )
371
  if( libcnotify_verbose != 0 )
372
  {
373
    libcnotify_printf(
374
     "%s: string size\t\t\t: %" PRIu32 "\n",
375
     function,
376
     string_size );
377
  }
378
#endif
379
0
  data_offset += 4;
380
381
0
  string_size *= 2;
382
383
0
  if( ( string_size > 0 )
384
0
         && ( string_size <= data_size )
385
0
   && ( data_offset <= ( data_size - string_size ) ) )
386
0
  {
387
#if defined( HAVE_DEBUG_OUTPUT )
388
    if( libcnotify_verbose != 0 )
389
    {
390
      if( libfwsi_debug_print_utf16_string_value(
391
           function,
392
           "string\t\t\t\t",
393
           &( data[ data_offset ] ),
394
           string_size,
395
           LIBUNA_ENDIAN_LITTLE,
396
           error ) != 1 )
397
      {
398
        libcerror_error_set(
399
         error,
400
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
401
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
402
         "%s: unable to print UTF-16 string value.",
403
         function );
404
405
        return( -1 );
406
      }
407
    }
408
#endif
409
0
    data_offset += string_size;
410
0
  }
411
0
  byte_stream_copy_to_uint32_little_endian(
412
0
   &( data[ data_offset ] ),
413
0
   string_size );
414
415
#if defined( HAVE_DEBUG_OUTPUT )
416
  if( libcnotify_verbose != 0 )
417
  {
418
    libcnotify_printf(
419
     "%s: string size\t\t\t: %" PRIu32 "\n",
420
     function,
421
     string_size );
422
  }
423
#endif
424
0
  data_offset += 4;
425
426
0
  string_size *= 2;
427
428
0
  if( ( string_size > 0 )
429
0
         && ( string_size <= data_size )
430
0
   && ( data_offset <= ( data_size - string_size ) ) )
431
0
  {
432
#if defined( HAVE_DEBUG_OUTPUT )
433
    if( libcnotify_verbose != 0 )
434
    {
435
      if( libfwsi_debug_print_utf16_string_value(
436
           function,
437
           "string\t\t\t\t",
438
           &( data[ data_offset ] ),
439
           string_size,
440
           LIBUNA_ENDIAN_LITTLE,
441
           error ) != 1 )
442
      {
443
        libcerror_error_set(
444
         error,
445
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
446
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
447
         "%s: unable to print UTF-16 string value.",
448
         function );
449
450
        return( -1 );
451
      }
452
    }
453
#endif
454
0
    data_offset += string_size;
455
0
  }
456
0
  byte_stream_copy_to_uint32_little_endian(
457
0
   &( data[ data_offset ] ),
458
0
   string_size );
459
460
#if defined( HAVE_DEBUG_OUTPUT )
461
  if( libcnotify_verbose != 0 )
462
  {
463
    libcnotify_printf(
464
     "%s: string size\t\t\t: %" PRIu32 "\n",
465
     function,
466
     string_size );
467
  }
468
#endif
469
0
  data_offset += 4;
470
471
0
  string_size *= 2;
472
473
0
  if( ( string_size > 0 )
474
0
         && ( string_size <= data_size )
475
0
   && ( data_offset <= ( data_size - string_size ) ) )
476
0
  {
477
#if defined( HAVE_DEBUG_OUTPUT )
478
    if( libcnotify_verbose != 0 )
479
    {
480
      if( libfwsi_debug_print_utf16_string_value(
481
           function,
482
           "string\t\t\t\t",
483
           &( data[ data_offset ] ),
484
           string_size,
485
           LIBUNA_ENDIAN_LITTLE,
486
           error ) != 1 )
487
      {
488
        libcerror_error_set(
489
         error,
490
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
491
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
492
         "%s: unable to print UTF-16 string value.",
493
         function );
494
495
        return( -1 );
496
      }
497
    }
498
#endif
499
0
  }
500
#if defined( HAVE_DEBUG_OUTPUT )
501
  if( libcnotify_verbose != 0 )
502
  {
503
    libcnotify_printf(
504
     "\n" );
505
  }
506
#endif
507
0
  return( 1 );
508
0
}
509