Coverage Report

Created: 2025-06-24 07:14

/src/libfwsi/libfwsi/libfwsi_file_entry_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * File entry (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_debug.h"
28
#include "libfwsi_definitions.h"
29
#include "libfwsi_file_attributes.h"
30
#include "libfwsi_file_entry_values.h"
31
#include "libfwsi_libcerror.h"
32
#include "libfwsi_libcnotify.h"
33
#include "libfwsi_libfdatetime.h"
34
#include "libfwsi_libfguid.h"
35
#include "libfwsi_libuna.h"
36
#include "libfwsi_shell_folder_identifier.h"
37
#include "libfwsi_unused.h"
38
39
/* Creates file entry values
40
 * Make sure the value file_entry_values is referencing, is set to NULL
41
 * Returns 1 if successful or -1 on error
42
 */
43
int libfwsi_file_entry_values_initialize(
44
     libfwsi_file_entry_values_t **file_entry_values,
45
     libcerror_error_t **error )
46
0
{
47
0
  static char *function = "libfwsi_file_entry_values_initialize";
48
49
0
  if( file_entry_values == NULL )
50
0
  {
51
0
    libcerror_error_set(
52
0
     error,
53
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
54
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
55
0
     "%s: invalid file entry values.",
56
0
     function );
57
58
0
    return( -1 );
59
0
  }
60
0
  if( *file_entry_values != NULL )
61
0
  {
62
0
    libcerror_error_set(
63
0
     error,
64
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
65
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
66
0
     "%s: invalid file entry values value already set.",
67
0
     function );
68
69
0
    return( -1 );
70
0
  }
71
0
  *file_entry_values = memory_allocate_structure(
72
0
                        libfwsi_file_entry_values_t );
73
74
0
  if( *file_entry_values == NULL )
75
0
  {
76
0
    libcerror_error_set(
77
0
     error,
78
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
79
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
80
0
     "%s: unable to create file entry values.",
81
0
     function );
82
83
0
    goto on_error;
84
0
  }
85
0
  if( memory_set(
86
0
       *file_entry_values,
87
0
       0,
88
0
       sizeof( libfwsi_file_entry_values_t ) ) == NULL )
89
0
  {
90
0
    libcerror_error_set(
91
0
     error,
92
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
93
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
94
0
     "%s: unable to clear file entry values.",
95
0
     function );
96
97
0
    goto on_error;
98
0
  }
99
0
  return( 1 );
100
101
0
on_error:
102
0
  if( *file_entry_values != NULL )
103
0
  {
104
0
    memory_free(
105
0
     *file_entry_values );
106
107
0
    *file_entry_values = NULL;
108
0
  }
109
0
  return( -1 );
110
0
}
111
112
/* Frees file entry values
113
 * Returns 1 if successful or -1 on error
114
 */
115
int libfwsi_file_entry_values_free(
116
     libfwsi_file_entry_values_t **file_entry_values,
117
     libcerror_error_t **error )
118
0
{
119
0
  static char *function = "libfwsi_file_entry_values_free";
120
121
0
  if( file_entry_values == NULL )
122
0
  {
123
0
    libcerror_error_set(
124
0
     error,
125
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
126
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
127
0
     "%s: invalid file entry values.",
128
0
     function );
129
130
0
    return( -1 );
131
0
  }
132
0
  if( *file_entry_values != NULL )
133
0
  {
134
0
    if( ( *file_entry_values )->name != NULL )
135
0
    {
136
0
      memory_free(
137
0
       ( *file_entry_values )->name );
138
0
    }
139
0
    memory_free(
140
0
     *file_entry_values );
141
142
0
    *file_entry_values = NULL;
143
0
  }
144
0
  return( 1 );
145
0
}
146
147
/* Reads the file entry values
148
 * Returns 1 if successful, 0 if not supported or -1 on error
149
 */
150
int libfwsi_file_entry_values_read_data(
151
     libfwsi_file_entry_values_t *file_entry_values,
152
     const uint8_t *data,
153
     size_t data_size,
154
     int ascii_codepage,
155
     libcerror_error_t **error )
156
0
{
157
0
  static char *function          = "libfwsi_file_entry_values_read_data";
158
0
  size_t data_offset             = 0;
159
0
  size_t string_alignment_offset = 0;
160
0
  size_t string_alignment_size   = 0;
161
0
  size_t string_size             = 0;
162
0
  uint16_t extension_size        = 0;
163
0
  uint8_t class_type_indicator   = 0;
164
0
  int has_swn1                   = 0;
165
166
#if defined( HAVE_DEBUG_OUTPUT )
167
  uint64_t value_64bit           = 0;
168
  uint32_t value_32bit           = 0;
169
  uint16_t value_16bit           = 0;
170
#endif
171
172
0
  if( file_entry_values == NULL )
173
0
  {
174
0
    libcerror_error_set(
175
0
     error,
176
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
177
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
178
0
     "%s: invalid file entry values.",
179
0
     function );
180
181
0
    return( -1 );
182
0
  }
183
0
  if( data == NULL )
184
0
  {
185
0
    libcerror_error_set(
186
0
     error,
187
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
188
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
189
0
     "%s: invalid data.",
190
0
     function );
191
192
0
    return( -1 );
193
0
  }
194
0
  if( data_size > (size_t) SSIZE_MAX )
195
0
  {
196
0
    libcerror_error_set(
197
0
     error,
198
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
199
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
200
0
     "%s: data size exceeds maximum.",
201
0
     function );
202
203
0
    return( -1 );
204
0
  }
205
  /* Do not try to parse unsupported data sizes
206
   */
207
0
  if( data_size < 14 )
208
0
  {
209
0
    return( 0 );
210
0
  }
211
  /* Do not try to parse unsupported data
212
   */
213
0
  if( ( data[ 2 ] != 0x30 )
214
0
   && ( data[ 2 ] != 0x31 )
215
0
   && ( data[ 2 ] != 0x32 )
216
0
   && ( data[ 2 ] != 0x35 )
217
0
   && ( data[ 2 ] != 0x36 )
218
0
   && ( data[ 2 ] != 0xb1 ) )
219
0
  {
220
0
    return( 0 );
221
0
  }
222
0
  class_type_indicator = data[ 2 ];
223
224
0
  byte_stream_copy_to_uint32_little_endian(
225
0
   &( data[ 4 ] ),
226
0
   file_entry_values->file_size );
227
228
0
  byte_stream_copy_to_uint32_little_endian(
229
0
   &( data[ 8 ] ),
230
0
   file_entry_values->modification_time );
231
232
0
  byte_stream_copy_to_uint16_little_endian(
233
0
   &( data[ 12 ] ),
234
0
   file_entry_values->file_attribute_flags );
235
236
#if defined( HAVE_DEBUG_OUTPUT )
237
  if( libcnotify_verbose != 0 )
238
  {
239
    libcnotify_printf(
240
     "%s: unknown1\t\t\t\t: 0x%02" PRIx8 "\n",
241
     function,
242
     data[ 3 ] );
243
244
    libcnotify_printf(
245
     "%s: file size\t\t\t\t: %" PRIu32 "\n",
246
     function,
247
     file_entry_values->file_size );
248
249
    if( libfwsi_debug_print_fat_date_time_value(
250
         function,
251
         "modification time\t\t\t",
252
         &( data[ 8 ] ),
253
         4,
254
         LIBFDATETIME_ENDIAN_LITTLE,
255
         LIBFDATETIME_STRING_FORMAT_TYPE_CTIME | LIBFDATETIME_STRING_FORMAT_FLAG_DATE_TIME,
256
         error ) != 1 )
257
    {
258
      libcerror_error_set(
259
       error,
260
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
261
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
262
       "%s: unable to print FAT date time value.",
263
       function );
264
265
      goto on_error;
266
    }
267
    libcnotify_printf(
268
     "%s: file attribute flags\t\t: 0x%04" PRIx16 "\n",
269
     function,
270
     file_entry_values->file_attribute_flags );
271
    libfwsi_file_attributes_print(
272
     file_entry_values->file_attribute_flags );
273
    libcnotify_printf(
274
     "\n" );
275
  }
276
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
277
278
0
  data_offset = 14;
279
280
  /* Check for "S.W.N.1" signature at offset -30
281
   */
282
0
  if( ( data_size > 30 )
283
0
   && ( memory_compare(
284
0
         &( data[ data_size - 30 ] ),
285
0
         "S.W.N.1",
286
0
         7 ) == 0 ) )
287
0
  {
288
0
    has_swn1 = 1;
289
0
  }
290
0
  if( ( has_swn1 != 0 )
291
0
   || ( ( class_type_indicator & LIBFWSI_FILE_ENTRY_FLAG_IS_UNICODE ) != 0 ) )
292
0
  {
293
0
    file_entry_values->is_unicode = 1;
294
0
  }
295
0
  else
296
0
  {
297
0
    file_entry_values->is_unicode = 0;
298
0
  }
299
0
  string_size = data_offset;
300
301
  /* Determine the size of the primary name
302
   */
303
0
  if( file_entry_values->is_unicode != 0 )
304
0
  {
305
0
    while( ( string_size + 1 ) < data_size )
306
0
    {
307
0
      if( ( data[ string_size ] == 0 )
308
0
       && ( data[ string_size + 1 ] == 0 ) )
309
0
      {
310
0
        string_size += 2;
311
312
0
        break;
313
0
      }
314
0
      string_size += 2;
315
0
    }
316
0
    string_size          -= data_offset;
317
0
    string_alignment_size = 0;
318
0
  }
319
0
  else
320
0
  {
321
0
    while( string_size < data_size )
322
0
    {
323
0
      if( data[ string_size ] == 0 )
324
0
      {
325
0
        string_size++;
326
327
0
        break;
328
0
      }
329
0
      string_size++;
330
0
    }
331
0
    string_size          -= data_offset;
332
0
    string_alignment_size = string_size % 2;
333
0
  }
334
0
  if( ( string_size == 0 )
335
0
   || ( string_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
336
0
  {
337
0
    libcerror_error_set(
338
0
     error,
339
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
340
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
341
0
     "%s: invalid name string size value out of bounds.",
342
0
     function );
343
344
0
    goto on_error;
345
0
  }
346
0
  file_entry_values->name = (uint8_t *) memory_allocate(
347
0
                                         sizeof( uint8_t ) * string_size );
348
349
0
  if( file_entry_values->name == NULL )
350
0
  {
351
0
    libcerror_error_set(
352
0
     error,
353
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
354
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
355
0
     "%s: unable to create name.",
356
0
     function );
357
358
0
    goto on_error;
359
0
  }
360
0
  if( memory_copy(
361
0
       file_entry_values->name,
362
0
       &( data[ data_offset ] ),
363
0
       string_size ) == NULL )
364
0
  {
365
0
    libcerror_error_set(
366
0
     error,
367
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
368
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
369
0
     "%s: unable to copy name.",
370
0
     function );
371
372
0
    goto on_error;
373
0
  }
374
0
  file_entry_values->name_size = string_size;
375
376
#if defined( HAVE_DEBUG_OUTPUT )
377
  if( libcnotify_verbose != 0 )
378
  {
379
    if( file_entry_values->is_unicode != 0 )
380
    {
381
      if( libfwsi_debug_print_utf16_string_value(
382
           function,
383
           "primary name\t\t\t",
384
           file_entry_values->name,
385
           file_entry_values->name_size,
386
           LIBUNA_ENDIAN_LITTLE,
387
           error ) != 1 )
388
      {
389
        libcerror_error_set(
390
         error,
391
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
392
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
393
         "%s: unable to print UTF-16 string value.",
394
         function );
395
396
        goto on_error;
397
      }
398
    }
399
    else
400
    {
401
      if( libfwsi_debug_print_string_value(
402
           function,
403
           "primary name\t\t\t",
404
           file_entry_values->name,
405
           file_entry_values->name_size,
406
           ascii_codepage,
407
           error ) != 1 )
408
      {
409
        libcerror_error_set(
410
         error,
411
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
412
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
413
         "%s: unable to print string value.",
414
         function );
415
416
        goto on_error;
417
      }
418
    }
419
  }
420
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
421
422
0
  data_offset            += string_size;
423
0
  string_alignment_offset = data_offset + string_alignment_size;
424
425
0
  if( ( string_alignment_offset < data_size )
426
0
   && ( ( data_size - string_alignment_offset ) >= 2 ) )
427
0
  {
428
    /* Look ahead if the extension size makes sense
429
     * if not we're dealing with a Windows 2000 or earlier entry
430
     * otherwise a Windows XP or later
431
     */
432
0
    byte_stream_copy_to_uint16_little_endian(
433
0
     &( data[ string_alignment_offset ] ),
434
0
     extension_size );
435
0
  }
436
0
  if( ( has_swn1 == 0 )
437
0
   && ( data_offset < data_size )
438
0
   && ( ( ( data_size - string_alignment_offset ) < 2 )
439
0
    ||  ( extension_size > data_size ) ) )
440
0
  {
441
0
    file_entry_values->in_pre_xp_format = 1;
442
443
0
    string_size = data_offset;
444
445
    /* Determine the size of the secondary name
446
     */
447
0
    if( file_entry_values->is_unicode != 0 )
448
0
    {
449
0
      while( ( string_size + 1 ) < data_size )
450
0
      {
451
0
        if( ( data[ string_size ] == 0 )
452
0
         && ( data[ string_size + 1 ] == 0 ) )
453
0
        {
454
0
          string_size += 2;
455
456
0
          break;
457
0
        }
458
0
        string_size += 2;
459
0
      }
460
0
    }
461
0
    else
462
0
    {
463
0
      while( string_size < data_size )
464
0
      {
465
0
        if( data[ string_size ] == 0 )
466
0
        {
467
0
          string_size++;
468
469
0
          break;
470
0
        }
471
0
        string_size++;
472
0
      }
473
0
    }
474
0
    string_size -= data_offset;
475
476
#if defined( HAVE_DEBUG_OUTPUT )
477
    if( libcnotify_verbose != 0 )
478
    {
479
      if( file_entry_values->is_unicode != 0 )
480
      {
481
        if( libfwsi_debug_print_utf16_string_value(
482
             function,
483
             "secondary name\t\t\t",
484
             &( data[ data_offset ] ),
485
             string_size,
486
             LIBUNA_ENDIAN_LITTLE,
487
             error ) != 1 )
488
        {
489
          libcerror_error_set(
490
           error,
491
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
492
           LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
493
           "%s: unable to print UTF-16 string value.",
494
           function );
495
496
          goto on_error;
497
        }
498
      }
499
      else
500
      {
501
        if( libfwsi_debug_print_string_value(
502
             function,
503
             "secondary name\t\t\t",
504
             &( data[ data_offset ] ),
505
             string_size,
506
             ascii_codepage,
507
             error ) != 1 )
508
        {
509
          libcerror_error_set(
510
           error,
511
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
512
           LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
513
           "%s: unable to print string value.",
514
           function );
515
516
          goto on_error;
517
        }
518
      }
519
    }
520
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
521
522
0
    data_offset += string_size;
523
0
  }
524
0
  else
525
0
  {
526
0
    data_offset += string_alignment_size;
527
0
  }
528
0
  if( has_swn1 != 0 )
529
0
  {
530
#if defined( HAVE_DEBUG_OUTPUT )
531
    if( libcnotify_verbose != 0 )
532
    {
533
      byte_stream_copy_to_uint16_little_endian(
534
       &( data[ data_offset ] ),
535
       value_16bit );
536
      libcnotify_printf(
537
       "%s: extension block size\t\t\t: %" PRIu16 "\n",
538
       function,
539
       value_16bit );
540
    }
541
#endif
542
0
    data_offset += 2;
543
544
#if defined( HAVE_DEBUG_OUTPUT )
545
    if( libcnotify_verbose != 0 )
546
    {
547
      libcnotify_printf(
548
       "%s: signature\t\t\t\t: %c%c%c%c%c%c%c\\x%02" PRIx8 "\n",
549
       function,
550
       data[ data_offset ],
551
       data[ data_offset + 1 ],
552
       data[ data_offset + 2 ],
553
       data[ data_offset + 3 ],
554
       data[ data_offset + 4 ],
555
       data[ data_offset + 5 ],
556
       data[ data_offset + 6 ],
557
       data[ data_offset + 7 ] );
558
    }
559
#endif
560
0
    data_offset += 8;
561
562
#if defined( HAVE_DEBUG_OUTPUT )
563
    if( libcnotify_verbose != 0 )
564
    {
565
      byte_stream_copy_to_uint32_little_endian(
566
       &( data[ data_offset ] ),
567
       value_32bit );
568
      libcnotify_printf(
569
       "%s: unknown1\t\t\t\t: 0x%08" PRIx32 "\n",
570
       function,
571
       value_32bit );
572
    }
573
#endif
574
0
    data_offset += 4;
575
576
#if defined( HAVE_DEBUG_OUTPUT )
577
    if( libcnotify_verbose != 0 )
578
    {
579
      byte_stream_copy_to_uint32_little_endian(
580
       &( data[ data_offset ] ),
581
       value_32bit );
582
      libcnotify_printf(
583
       "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n",
584
       function,
585
       value_32bit );
586
    }
587
#endif
588
0
    data_offset += 4;
589
590
#if defined( HAVE_DEBUG_OUTPUT )
591
    if( libcnotify_verbose != 0 )
592
    {
593
      byte_stream_copy_to_uint64_little_endian(
594
       &( data[ data_offset ] ),
595
       value_64bit );
596
      libcnotify_printf(
597
       "%s: unknown3\t\t\t\t: 0x%08" PRIx64 "\n",
598
       function,
599
       value_64bit );
600
    }
601
#endif
602
0
    data_offset += 8;
603
604
#if defined( HAVE_DEBUG_OUTPUT )
605
    if( libcnotify_verbose != 0 )
606
    {
607
      libcnotify_printf(
608
       "%s: unknown4:\n",
609
       function );
610
      libcnotify_print_data(
611
       &( data[ data_offset ] ),
612
       6,
613
       0 );
614
    }
615
#endif
616
0
    data_offset += 6;
617
0
  }
618
0
  if( ( file_entry_values->in_pre_xp_format != 0 )
619
0
   && ( ( class_type_indicator & 0x80 ) != 0 )
620
0
   && ( data_offset <= ( data_size - 16 ) ) )
621
0
  {
622
#if defined( HAVE_DEBUG_OUTPUT )
623
    if( libcnotify_verbose != 0 )
624
    {
625
      if( libfwsi_debug_print_guid_value(
626
           function,
627
           "shell folder identifier\t\t\t",
628
           &( data[ data_offset ] ),
629
           16,
630
           LIBFGUID_ENDIAN_LITTLE,
631
           LIBFGUID_STRING_FORMAT_FLAG_USE_UPPER_CASE | LIBFGUID_STRING_FORMAT_FLAG_USE_SURROUNDING_BRACES,
632
           error ) != 1 )
633
      {
634
        libcerror_error_set(
635
         error,
636
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
637
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
638
         "%s: unable to print GUID value.",
639
         function );
640
641
        goto on_error;
642
      }
643
      libcnotify_printf(
644
       "%s: shell folder name\t\t\t: %s\n",
645
       function,
646
       libfwsi_shell_folder_identifier_get_name(
647
        &( data[ data_offset ] ) ) );
648
    }
649
#endif
650
0
    data_offset += 16;
651
0
  }
652
#if defined( HAVE_DEBUG_OUTPUT )
653
  if( libcnotify_verbose != 0 )
654
  {
655
    libcnotify_printf(
656
     "\n" );
657
  }
658
#endif
659
0
  return( 1 );
660
661
0
on_error:
662
0
  if( file_entry_values->name != NULL )
663
0
  {
664
0
    memory_free(
665
0
     file_entry_values->name );
666
667
0
    file_entry_values->name = NULL;
668
0
  }
669
0
  file_entry_values->name_size = 0;
670
671
0
  return( -1 );
672
0
}
673
674
/* Retrieves the size of the UTF-8 formatted name
675
 * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode
676
 * The size includes the end of string character
677
 * Returns 1 if successful or -1 on error
678
 */
679
int libfwsi_file_entry_values_get_utf8_name_size(
680
     libfwsi_file_entry_values_t *file_entry_values,
681
     size_t *utf8_string_size,
682
     int ascii_codepage,
683
     libcerror_error_t **error )
684
0
{
685
0
  static char *function = "libfwsi_file_entry_values_get_utf8_name_size";
686
0
  int result            = 0;
687
688
0
  if( file_entry_values == NULL )
689
0
  {
690
0
    libcerror_error_set(
691
0
     error,
692
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
693
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
694
0
     "%s: invalid file entry values.",
695
0
     function );
696
697
0
    return( -1 );
698
0
  }
699
0
  if( file_entry_values->is_unicode != 0 )
700
0
  {
701
0
    result = libuna_utf8_string_size_from_utf16_stream(
702
0
        file_entry_values->name,
703
0
        file_entry_values->name_size,
704
0
        LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
705
0
        utf8_string_size,
706
0
        error );
707
0
  }
708
0
  else
709
0
  {
710
0
    result = libuna_utf8_string_size_from_byte_stream(
711
0
        file_entry_values->name,
712
0
        file_entry_values->name_size,
713
0
              ascii_codepage,
714
0
        utf8_string_size,
715
0
        error );
716
0
  }
717
0
  if( result != 1 )
718
0
  {
719
0
    libcerror_error_set(
720
0
     error,
721
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
722
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
723
0
     "%s: unable to determine size of UTF-8 string.",
724
0
     function );
725
726
0
    return( -1 );
727
0
  }
728
0
  return( 1 );
729
0
}
730
731
/* Retrieves the UTF-8 formatted name
732
 * This function uses UTF-8 RFC 2279 (or 6-byte UTF-8) to support characters outside Unicode
733
 * The size should include the end of string character
734
 * Returns 1 if successful or -1 on error
735
 */
736
int libfwsi_file_entry_values_get_utf8_name(
737
     libfwsi_file_entry_values_t *file_entry_values,
738
     uint8_t *utf8_string,
739
     size_t utf8_string_size,
740
     int ascii_codepage,
741
     libcerror_error_t **error )
742
0
{
743
0
  static char *function = "libfwsi_file_entry_values_get_utf8_name";
744
0
  int result            = 0;
745
746
0
  if( file_entry_values == NULL )
747
0
  {
748
0
    libcerror_error_set(
749
0
     error,
750
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
751
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
752
0
     "%s: invalid file entry values.",
753
0
     function );
754
755
0
    return( -1 );
756
0
  }
757
0
  if( file_entry_values->is_unicode != 0 )
758
0
  {
759
0
    result = libuna_utf8_string_copy_from_utf16_stream(
760
0
              utf8_string,
761
0
              utf8_string_size,
762
0
        file_entry_values->name,
763
0
        file_entry_values->name_size,
764
0
        LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
765
0
        error );
766
0
  }
767
0
  else
768
0
  {
769
0
    result = libuna_utf8_string_copy_from_byte_stream(
770
0
              utf8_string,
771
0
              utf8_string_size,
772
0
        file_entry_values->name,
773
0
        file_entry_values->name_size,
774
0
              ascii_codepage,
775
0
        error );
776
0
  }
777
0
  if( result != 1 )
778
0
  {
779
0
    libcerror_error_set(
780
0
     error,
781
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
782
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
783
0
     "%s: unable to set UTF-8 string.",
784
0
     function );
785
786
0
    return( -1 );
787
0
  }
788
0
  return( 1 );
789
0
}
790
791
/* Retrieves the size of the UTF-16 formatted name
792
 * This function uses UCS-2 (with surrogates) to support characters outside Unicode
793
 * The size includes the end of string character
794
 * Returns 1 if successful or -1 on error
795
 */
796
int libfwsi_file_entry_values_get_utf16_name_size(
797
     libfwsi_file_entry_values_t *file_entry_values,
798
     size_t *utf16_string_size,
799
     int ascii_codepage,
800
     libcerror_error_t **error )
801
0
{
802
0
  static char *function = "libfwsi_file_entry_values_get_utf16_name_size";
803
0
  int result            = 0;
804
805
0
  if( file_entry_values == NULL )
806
0
  {
807
0
    libcerror_error_set(
808
0
     error,
809
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
810
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
811
0
     "%s: invalid file entry values.",
812
0
     function );
813
814
0
    return( -1 );
815
0
  }
816
0
  if( file_entry_values->is_unicode != 0 )
817
0
  {
818
0
    result = libuna_utf16_string_size_from_utf16_stream(
819
0
        file_entry_values->name,
820
0
        file_entry_values->name_size,
821
0
        LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
822
0
        utf16_string_size,
823
0
        error );
824
0
  }
825
0
  else
826
0
  {
827
0
    result = libuna_utf16_string_size_from_byte_stream(
828
0
        file_entry_values->name,
829
0
        file_entry_values->name_size,
830
0
              ascii_codepage,
831
0
        utf16_string_size,
832
0
        error );
833
0
  }
834
0
  if( result != 1 )
835
0
  {
836
0
    libcerror_error_set(
837
0
     error,
838
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
839
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
840
0
     "%s: unable to determine size of UTF-16 string.",
841
0
     function );
842
843
0
    return( -1 );
844
0
  }
845
0
  return( 1 );
846
0
}
847
848
/* Retrieves the UTF-16 formatted name
849
 * This function uses UCS-2 (with surrogates) to support characters outside Unicode
850
 * The size should include the end of string character
851
 * Returns 1 if successful or -1 on error
852
 */
853
int libfwsi_file_entry_values_get_utf16_name(
854
     libfwsi_file_entry_values_t *file_entry_values,
855
     uint16_t *utf16_string,
856
     size_t utf16_string_size,
857
     int ascii_codepage,
858
     libcerror_error_t **error )
859
0
{
860
0
  static char *function = "libfwsi_file_entry_values_get_utf16_name";
861
0
  int result            = 0;
862
863
0
  if( file_entry_values == NULL )
864
0
  {
865
0
    libcerror_error_set(
866
0
     error,
867
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
868
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
869
0
     "%s: invalid file entry values.",
870
0
     function );
871
872
0
    return( -1 );
873
0
  }
874
0
  if( file_entry_values->is_unicode != 0 )
875
0
  {
876
0
    result = libuna_utf16_string_copy_from_utf16_stream(
877
0
              utf16_string,
878
0
              utf16_string_size,
879
0
        file_entry_values->name,
880
0
        file_entry_values->name_size,
881
0
        LIBUNA_ENDIAN_LITTLE | LIBUNA_UTF16_STREAM_ALLOW_UNPAIRED_SURROGATE,
882
0
        error );
883
0
  }
884
0
  else
885
0
  {
886
0
    result = libuna_utf16_string_copy_from_byte_stream(
887
0
              utf16_string,
888
0
              utf16_string_size,
889
0
        file_entry_values->name,
890
0
        file_entry_values->name_size,
891
0
              ascii_codepage,
892
0
        error );
893
0
  }
894
0
  if( result != 1 )
895
0
  {
896
0
    libcerror_error_set(
897
0
     error,
898
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
899
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
900
0
     "%s: unable to set UTF-16 string.",
901
0
     function );
902
903
0
    return( -1 );
904
0
  }
905
0
  return( 1 );
906
0
}
907