Coverage Report

Created: 2025-06-13 07:22

/src/libfsntfs/libfsntfs/libfsntfs_reparse_point_values.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Reparse point attribute ($REPARSE_POINT) 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 <narrow_string.h>
26
#include <system_string.h>
27
#include <types.h>
28
#include <wide_string.h>
29
30
#include "libfsntfs_debug.h"
31
#include "libfsntfs_definitions.h"
32
#include "libfsntfs_libcerror.h"
33
#include "libfsntfs_libcnotify.h"
34
#include "libfsntfs_libuna.h"
35
#include "libfsntfs_mft_attribute.h"
36
#include "libfsntfs_reparse_point_values.h"
37
38
#include "fsntfs_reparse_point.h"
39
40
/* Creates reparse point values
41
 * Make sure the value reparse_point_values is referencing, is set to NULL
42
 * Returns 1 if successful or -1 on error
43
 */
44
int libfsntfs_reparse_point_values_initialize(
45
     libfsntfs_reparse_point_values_t **reparse_point_values,
46
     libcerror_error_t **error )
47
0
{
48
0
  static char *function = "libfsntfs_reparse_point_values_initialize";
49
50
0
  if( reparse_point_values == NULL )
51
0
  {
52
0
    libcerror_error_set(
53
0
     error,
54
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
55
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
56
0
     "%s: invalid reparse point values.",
57
0
     function );
58
59
0
    return( -1 );
60
0
  }
61
0
  if( *reparse_point_values != NULL )
62
0
  {
63
0
    libcerror_error_set(
64
0
     error,
65
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
66
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
67
0
     "%s: invalid reparse point values value already set.",
68
0
     function );
69
70
0
    return( -1 );
71
0
  }
72
0
  *reparse_point_values = memory_allocate_structure(
73
0
                           libfsntfs_reparse_point_values_t );
74
75
0
  if( *reparse_point_values == NULL )
76
0
  {
77
0
    libcerror_error_set(
78
0
     error,
79
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
80
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
81
0
     "%s: unable to create reparse point values.",
82
0
     function );
83
84
0
    goto on_error;
85
0
  }
86
0
  if( memory_set(
87
0
       *reparse_point_values,
88
0
       0,
89
0
       sizeof( libfsntfs_reparse_point_values_t ) ) == NULL )
90
0
  {
91
0
    libcerror_error_set(
92
0
     error,
93
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
94
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
95
0
     "%s: unable to clear reparse point values.",
96
0
     function );
97
98
0
    goto on_error;
99
0
  }
100
0
  return( 1 );
101
102
0
on_error:
103
0
  if( *reparse_point_values != NULL )
104
0
  {
105
0
    memory_free(
106
0
     *reparse_point_values );
107
108
0
    *reparse_point_values = NULL;
109
0
  }
110
0
  return( -1 );
111
0
}
112
113
/* Frees reparse point values
114
 * Returns 1 if successful or -1 on error
115
 */
116
int libfsntfs_reparse_point_values_free(
117
     libfsntfs_reparse_point_values_t **reparse_point_values,
118
     libcerror_error_t **error )
119
0
{
120
0
  static char *function = "libfsntfs_reparse_point_values_free";
121
122
0
  if( reparse_point_values == NULL )
123
0
  {
124
0
    libcerror_error_set(
125
0
     error,
126
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
127
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
128
0
     "%s: invalid reparse point values.",
129
0
     function );
130
131
0
    return( -1 );
132
0
  }
133
0
  if( *reparse_point_values != NULL )
134
0
  {
135
0
    if( ( *reparse_point_values )->reparse_data != NULL )
136
0
    {
137
0
      memory_free(
138
0
       ( *reparse_point_values )->reparse_data );
139
0
    }
140
0
    memory_free(
141
0
     *reparse_point_values );
142
143
0
    *reparse_point_values = NULL;
144
0
  }
145
0
  return( 1 );
146
0
}
147
148
/* Reads the reparse point values
149
 * Returns 1 if successful or -1 on error
150
 */
151
int libfsntfs_reparse_point_values_read_data(
152
     libfsntfs_reparse_point_values_t *reparse_point_values,
153
     const uint8_t *data,
154
     size_t data_size,
155
     libcerror_error_t **error )
156
0
{
157
0
  static char *function            = "libfsntfs_reparse_point_values_read_data";
158
0
  uint32_t flags                   = 0;
159
160
#if defined( HAVE_DEBUG_OUTPUT )
161
  system_character_t *value_string = NULL;
162
  size_t value_string_size         = 0;
163
  uint32_t value_32bit             = 0;
164
  int result                       = 0;
165
#endif
166
167
0
  if( reparse_point_values == NULL )
168
0
  {
169
0
    libcerror_error_set(
170
0
     error,
171
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
172
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
173
0
     "%s: invalid reparse point values.",
174
0
     function );
175
176
0
    return( -1 );
177
0
  }
178
0
  if( data == NULL )
179
0
  {
180
0
    libcerror_error_set(
181
0
     error,
182
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
183
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
184
0
     "%s: invalid data.",
185
0
     function );
186
187
0
    return( -1 );
188
0
  }
189
0
  if( data_size > (size_t) SSIZE_MAX )
190
0
  {
191
0
    libcerror_error_set(
192
0
     error,
193
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
194
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
195
0
     "%s: invalid data size value out of bounds.",
196
0
     function );
197
198
0
    return( -1 );
199
0
  }
200
#if defined( HAVE_DEBUG_OUTPUT )
201
  if( libcnotify_verbose != 0 )
202
  {
203
    libcnotify_printf(
204
     "%s: reparse point data:\n",
205
     function );
206
    libcnotify_print_data(
207
     data,
208
     data_size,
209
     0 );
210
  }
211
#endif
212
0
  byte_stream_copy_to_uint32_little_endian(
213
0
   ( (fsntfs_reparse_point_t *) data )->tag,
214
0
   reparse_point_values->tag );
215
216
0
  byte_stream_copy_to_uint16_little_endian(
217
0
   ( (fsntfs_reparse_point_t *) data )->reparse_data_size,
218
0
   reparse_point_values->reparse_data_size );
219
220
#if defined( HAVE_DEBUG_OUTPUT )
221
  if( libcnotify_verbose != 0 )
222
  {
223
    libcnotify_printf(
224
     "%s: tag\t\t\t\t: 0x%08" PRIx32 "\n",
225
     function,
226
     reparse_point_values->tag );
227
    libfsntfs_debug_print_reparse_point_tag(
228
     reparse_point_values->tag );
229
    libcnotify_printf(
230
     "\n" );
231
232
    libcnotify_printf(
233
     "%s: reparse data size\t\t: %" PRIu16 "\n",
234
     function,
235
     reparse_point_values->reparse_data_size );
236
237
    libcnotify_printf(
238
     "\n" );
239
  }
240
#endif
241
0
  if( reparse_point_values->reparse_data_size > 0 )
242
0
  {
243
0
    if( ( sizeof( fsntfs_reparse_point_t ) > data_size )
244
0
     || ( (size_t) reparse_point_values->reparse_data_size > ( data_size - sizeof( fsntfs_reparse_point_t ) ) )
245
0
     || ( (size_t) reparse_point_values->reparse_data_size > MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
246
0
    {
247
0
      libcerror_error_set(
248
0
       error,
249
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
250
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
251
0
       "%s: invalid reparse data size value out of bounds.",
252
0
       function );
253
254
0
      goto on_error;
255
0
    }
256
0
    reparse_point_values->reparse_data = (uint8_t *) memory_allocate(
257
0
                                                      sizeof( uint8_t ) * reparse_point_values->reparse_data_size );
258
259
0
    if( reparse_point_values->reparse_data == NULL )
260
0
    {
261
0
      libcerror_error_set(
262
0
       error,
263
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
264
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
265
0
       "%s: unable to create reparse data.",
266
0
       function );
267
268
0
      goto on_error;
269
0
    }
270
0
    if( memory_copy(
271
0
         reparse_point_values->reparse_data,
272
0
         &( data[ sizeof( fsntfs_reparse_point_t ) ] ),
273
0
         (size_t) reparse_point_values->reparse_data_size ) == NULL )
274
0
    {
275
0
      libcerror_error_set(
276
0
       error,
277
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
278
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
279
0
       "%s: unable to copy reparse data.",
280
0
       function );
281
282
0
      goto on_error;
283
0
    }
284
0
  }
285
0
  if( reparse_point_values->tag == 0x80000017 )
286
0
  {
287
0
    byte_stream_copy_to_uint32_little_endian(
288
0
     &( reparse_point_values->reparse_data[ 12 ] ),
289
0
     reparse_point_values->compression_method );
290
291
#if defined( HAVE_DEBUG_OUTPUT )
292
    if( libcnotify_verbose != 0 )
293
    {
294
      byte_stream_copy_to_uint32_little_endian(
295
       &( reparse_point_values->reparse_data[ 0 ] ),
296
       value_32bit );
297
      libcnotify_printf(
298
       "%s: external version\t\t: %" PRIu32 "\n",
299
       function,
300
       value_32bit );
301
302
      byte_stream_copy_to_uint32_little_endian(
303
       &( reparse_point_values->reparse_data[ 4 ] ),
304
       value_32bit );
305
      libcnotify_printf(
306
       "%s: external provider\t\t: %" PRIu32 "\n",
307
       function,
308
       value_32bit );
309
310
      byte_stream_copy_to_uint32_little_endian(
311
       &( reparse_point_values->reparse_data[ 8 ] ),
312
       value_32bit );
313
      libcnotify_printf(
314
       "%s: internal version\t\t: %" PRIu32 "\n",
315
       function,
316
       value_32bit );
317
318
      libcnotify_printf(
319
       "%s: compression method\t\t: %" PRIu32 " (%s)\n",
320
       function,
321
       reparse_point_values->compression_method,
322
       libfsntfs_debug_print_compression_method(
323
        reparse_point_values->compression_method ) );
324
    }
325
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
326
0
  }
327
0
  else if( ( reparse_point_values->tag == 0xa0000003 )
328
0
        || ( reparse_point_values->tag == 0xa000000c ) )
329
0
  {
330
0
    byte_stream_copy_to_uint16_little_endian(
331
0
     ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->substitute_name_offset,
332
0
     reparse_point_values->substitute_name_offset );
333
334
0
    byte_stream_copy_to_uint16_little_endian(
335
0
     ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->substitute_name_size,
336
0
     reparse_point_values->substitute_name_size );
337
338
0
    byte_stream_copy_to_uint16_little_endian(
339
0
     ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->print_name_offset,
340
0
     reparse_point_values->print_name_offset );
341
342
0
    byte_stream_copy_to_uint16_little_endian(
343
0
     ( (fsntfs_mount_point_reparse_data_t *) reparse_point_values->reparse_data )->print_name_size,
344
0
     reparse_point_values->print_name_size );
345
346
#if defined( HAVE_DEBUG_OUTPUT )
347
    if( libcnotify_verbose != 0 )
348
    {
349
      libcnotify_printf(
350
       "%s: substitute name offset\t: 0x%04" PRIx16 "\n",
351
       function,
352
       reparse_point_values->substitute_name_offset );
353
354
      libcnotify_printf(
355
       "%s: substitute name size\t\t: %" PRIu16 "\n",
356
       function,
357
       reparse_point_values->substitute_name_size );
358
359
      libcnotify_printf(
360
       "%s: print name offset\t\t: 0x%04" PRIx16 "\n",
361
       function,
362
       reparse_point_values->print_name_offset );
363
364
      libcnotify_printf(
365
       "%s: print name size\t\t: %" PRIu16 "\n",
366
       function,
367
       reparse_point_values->print_name_size );
368
    }
369
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
370
0
  }
371
0
  if( reparse_point_values->tag == 0xa0000003 )
372
0
  {
373
0
    reparse_point_values->substitute_name_offset += sizeof( fsntfs_mount_point_reparse_data_t );
374
0
    reparse_point_values->print_name_offset      += sizeof( fsntfs_mount_point_reparse_data_t );
375
0
  }
376
0
  else if( reparse_point_values->tag == 0xa000000c )
377
0
  {
378
0
    byte_stream_copy_to_uint32_little_endian(
379
0
     ( (fsntfs_symbolic_link_reparse_data_t *) reparse_point_values->reparse_data )->flags,
380
0
     flags );
381
382
#if defined( HAVE_DEBUG_OUTPUT )
383
    if( libcnotify_verbose != 0 )
384
    {
385
      libcnotify_printf(
386
       "%s: flags\t\t\t\t: 0x%08" PRIx32 "\n",
387
       function,
388
       flags );
389
    }
390
#endif
391
0
    reparse_point_values->substitute_name_offset += sizeof( fsntfs_symbolic_link_reparse_data_t );
392
0
    reparse_point_values->print_name_offset      += sizeof( fsntfs_symbolic_link_reparse_data_t );
393
0
  }
394
#if defined( HAVE_DEBUG_OUTPUT )
395
  if( libcnotify_verbose != 0 )
396
  {
397
    if( ( reparse_point_values->tag != 0x80000017 )
398
     && ( reparse_point_values->tag != 0xa0000003 )
399
     && ( reparse_point_values->tag != 0xa000000c ) )
400
    {
401
      libcnotify_printf(
402
       "%s: unusupported reparse point tag: 0x%08" PRIx32 "\n",
403
       function,
404
       reparse_point_values->tag );
405
    }
406
  }
407
#endif
408
0
  if( reparse_point_values->substitute_name_size > 0 )
409
0
  {
410
0
    if( reparse_point_values->substitute_name_offset >= reparse_point_values->reparse_data_size )
411
0
    {
412
0
      libcerror_error_set(
413
0
       error,
414
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
415
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
416
0
       "%s: invalid substitute name offset value out of bounds.",
417
0
       function );
418
419
0
      goto on_error;
420
0
    }
421
0
    if( reparse_point_values->substitute_name_size > ( reparse_point_values->reparse_data_size - reparse_point_values->substitute_name_offset ) )
422
0
    {
423
0
      libcerror_error_set(
424
0
       error,
425
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
426
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
427
0
       "%s: invalid substitute name size value out of bounds.",
428
0
       function );
429
430
0
      goto on_error;
431
0
    }
432
#if defined( HAVE_DEBUG_OUTPUT )
433
    if( libcnotify_verbose != 0 )
434
    {
435
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
436
      result = libuna_utf16_string_size_from_utf16_stream(
437
                &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
438
                (size_t) reparse_point_values->substitute_name_size,
439
                LIBUNA_ENDIAN_LITTLE,
440
                &value_string_size,
441
                error );
442
#else
443
      result = libuna_utf8_string_size_from_utf16_stream(
444
                &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
445
                (size_t) reparse_point_values->substitute_name_size,
446
                LIBUNA_ENDIAN_LITTLE,
447
                &value_string_size,
448
                error );
449
#endif
450
      if( result != 1 )
451
      {
452
        libcerror_error_set(
453
         error,
454
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
455
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
456
         "%s: unable to determine size of substitute name string.",
457
         function );
458
459
        goto on_error;
460
      }
461
      value_string = system_string_allocate(
462
                      value_string_size );
463
464
      if( value_string == NULL )
465
      {
466
        libcerror_error_set(
467
         error,
468
         LIBCERROR_ERROR_DOMAIN_MEMORY,
469
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
470
         "%s: unable to create substitute name string.",
471
         function );
472
473
        goto on_error;
474
      }
475
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
476
      result = libuna_utf16_string_copy_from_utf16_stream(
477
                (libuna_utf16_character_t *) value_string,
478
                value_string_size,
479
                &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
480
                (size_t) reparse_point_values->substitute_name_size,
481
                LIBUNA_ENDIAN_LITTLE,
482
                error );
483
#else
484
      result = libuna_utf8_string_copy_from_utf16_stream(
485
                (libuna_utf8_character_t *) value_string,
486
                value_string_size,
487
                &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
488
                (size_t) reparse_point_values->substitute_name_size,
489
                LIBUNA_ENDIAN_LITTLE,
490
                error );
491
#endif
492
      if( result != 1 )
493
      {
494
        libcerror_error_set(
495
         error,
496
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
497
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
498
         "%s: unable to set substitute name string.",
499
         function );
500
501
        goto on_error;
502
      }
503
      libcnotify_printf(
504
       "%s: substitute name\t\t: %" PRIs_SYSTEM "\n",
505
       function,
506
       value_string );
507
508
      memory_free(
509
       value_string );
510
511
      value_string = NULL;
512
    }
513
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
514
0
  }
515
0
  if( reparse_point_values->print_name_size > 0 )
516
0
  {
517
0
    if( reparse_point_values->print_name_offset >= reparse_point_values->reparse_data_size )
518
0
    {
519
0
      libcerror_error_set(
520
0
       error,
521
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
522
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
523
0
       "%s: invalid print name offset value out of bounds.",
524
0
       function );
525
526
0
      goto on_error;
527
0
    }
528
0
    if( reparse_point_values->print_name_size > ( reparse_point_values->reparse_data_size - reparse_point_values->print_name_offset ) )
529
0
    {
530
0
      libcerror_error_set(
531
0
       error,
532
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
533
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
534
0
       "%s: invalid print name size value out of bounds.",
535
0
       function );
536
537
0
      goto on_error;
538
0
    }
539
#if defined( HAVE_DEBUG_OUTPUT )
540
    if( libcnotify_verbose != 0 )
541
    {
542
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
543
      result = libuna_utf16_string_size_from_utf16_stream(
544
                &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
545
                (size_t) reparse_point_values->print_name_size,
546
                LIBUNA_ENDIAN_LITTLE,
547
                &value_string_size,
548
                error );
549
#else
550
      result = libuna_utf8_string_size_from_utf16_stream(
551
                &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
552
                (size_t) reparse_point_values->print_name_size,
553
                LIBUNA_ENDIAN_LITTLE,
554
                &value_string_size,
555
                error );
556
#endif
557
      if( result != 1 )
558
      {
559
        libcerror_error_set(
560
         error,
561
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
562
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
563
         "%s: unable to determine size of print name string.",
564
         function );
565
566
        goto on_error;
567
      }
568
      value_string = system_string_allocate(
569
                      value_string_size );
570
571
      if( value_string == NULL )
572
      {
573
        libcerror_error_set(
574
         error,
575
         LIBCERROR_ERROR_DOMAIN_MEMORY,
576
         LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
577
         "%s: unable to create print name string.",
578
         function );
579
580
        goto on_error;
581
      }
582
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
583
      result = libuna_utf16_string_copy_from_utf16_stream(
584
                (libuna_utf16_character_t *) value_string,
585
                value_string_size,
586
                &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
587
                (size_t) reparse_point_values->print_name_size,
588
                LIBUNA_ENDIAN_LITTLE,
589
                error );
590
#else
591
      result = libuna_utf8_string_copy_from_utf16_stream(
592
                (libuna_utf8_character_t *) value_string,
593
                value_string_size,
594
                &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
595
                (size_t) reparse_point_values->print_name_size,
596
                LIBUNA_ENDIAN_LITTLE,
597
                error );
598
#endif
599
      if( result != 1 )
600
      {
601
        libcerror_error_set(
602
         error,
603
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
604
         LIBCERROR_RUNTIME_ERROR_SET_FAILED,
605
         "%s: unable to set print name string.",
606
         function );
607
608
        goto on_error;
609
      }
610
      libcnotify_printf(
611
       "%s: print name\t\t\t: %" PRIs_SYSTEM "\n",
612
       function,
613
       value_string );
614
615
      memory_free(
616
       value_string );
617
618
      value_string = NULL;
619
    }
620
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
621
0
  }
622
#if defined( HAVE_DEBUG_OUTPUT )
623
  if( libcnotify_verbose != 0 )
624
  {
625
    libcnotify_printf(
626
     "\n" );
627
  }
628
#endif
629
0
  return( 1 );
630
631
0
on_error:
632
#if defined( HAVE_DEBUG_OUTPUT )
633
  if( value_string != NULL )
634
  {
635
    memory_free(
636
     value_string );
637
  }
638
#endif
639
0
  if( reparse_point_values->reparse_data != NULL )
640
0
  {
641
0
    memory_free(
642
0
     reparse_point_values->reparse_data );
643
644
0
    reparse_point_values->reparse_data = NULL;
645
0
  }
646
0
  reparse_point_values->reparse_data_size = 0;
647
648
0
  return( -1 );
649
0
}
650
651
/* Reads the reparse point values from an MFT attribute
652
 * Returns 1 if successful or -1 on error
653
 */
654
int libfsntfs_reparse_point_values_read_from_mft_attribute(
655
     libfsntfs_reparse_point_values_t *reparse_point_values,
656
     libfsntfs_mft_attribute_t *mft_attribute,
657
     libcerror_error_t **error )
658
0
{
659
0
  uint8_t *data           = NULL;
660
0
  static char *function   = "libfsntfs_reparse_point_values_read_from_mft_attribute";
661
0
  size_t data_size        = 0;
662
0
  uint32_t attribute_type = 0;
663
0
  int result              = 0;
664
665
0
  if( reparse_point_values == NULL )
666
0
  {
667
0
    libcerror_error_set(
668
0
     error,
669
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
670
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
671
0
     "%s: invalid reparse point values.",
672
0
     function );
673
674
0
    return( -1 );
675
0
  }
676
0
  if( libfsntfs_mft_attribute_get_type(
677
0
       mft_attribute,
678
0
       &attribute_type,
679
0
       error ) != 1 )
680
0
  {
681
0
    libcerror_error_set(
682
0
     error,
683
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
684
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
685
0
     "%s: unable to retrieve type from attribute.",
686
0
     function );
687
688
0
    return( -1 );
689
0
  }
690
0
  if( attribute_type != LIBFSNTFS_ATTRIBUTE_TYPE_REPARSE_POINT )
691
0
  {
692
0
    libcerror_error_set(
693
0
     error,
694
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
695
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
696
0
     "%s: unsupported attribute type.",
697
0
     function );
698
699
0
    return( -1 );
700
0
  }
701
0
  result = libfsntfs_mft_attribute_data_is_resident(
702
0
            mft_attribute,
703
0
            error );
704
705
0
  if( result == -1 )
706
0
  {
707
0
    libcerror_error_set(
708
0
     error,
709
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
710
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
711
0
     "%s: unable to determine if attribute data is resident.",
712
0
     function );
713
714
0
    return( -1 );
715
0
  }
716
0
  else if( result == 0 )
717
0
  {
718
0
    libcerror_error_set(
719
0
     error,
720
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
721
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
722
0
     "%s: unsupported non-resident attribute.",
723
0
     function );
724
725
0
    return( 1 );
726
0
  }
727
0
  if( libfsntfs_mft_attribute_get_resident_data(
728
0
       mft_attribute,
729
0
       &data,
730
0
       &data_size,
731
0
       error ) != 1 )
732
0
  {
733
0
    libcerror_error_set(
734
0
     error,
735
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
736
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
737
0
     "%s: unable to retrieve resident data from attribute.",
738
0
     function );
739
740
0
    return( -1 );
741
0
  }
742
0
  if( libfsntfs_reparse_point_values_read_data(
743
0
       reparse_point_values,
744
0
       data,
745
0
       data_size,
746
0
       error ) != 1 )
747
0
  {
748
0
    libcerror_error_set(
749
0
     error,
750
0
     LIBCERROR_ERROR_DOMAIN_IO,
751
0
     LIBCERROR_IO_ERROR_READ_FAILED,
752
0
     "%s: unable to read reparse point values.",
753
0
     function );
754
755
0
    return( -1 );
756
0
  }
757
0
  return( 1 );
758
0
}
759
760
/* Retrieves the tag
761
 * The tag is a combination of the type and flags
762
 * Returns 1 if successful or -1 on error
763
 */
764
int libfsntfs_reparse_point_values_get_tag(
765
     libfsntfs_reparse_point_values_t *reparse_point_values,
766
     uint32_t *tag,
767
     libcerror_error_t **error )
768
0
{
769
0
  static char *function = "libfsntfs_reparse_point_values_get_tag";
770
771
0
  if( reparse_point_values == NULL )
772
0
  {
773
0
    libcerror_error_set(
774
0
     error,
775
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
776
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
777
0
     "%s: invalid reparse point values.",
778
0
     function );
779
780
0
    return( -1 );
781
0
  }
782
0
  if( tag == NULL )
783
0
  {
784
0
    libcerror_error_set(
785
0
     error,
786
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
787
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
788
0
     "%s: invalid tag.",
789
0
     function );
790
791
0
    return( -1 );
792
0
  }
793
0
  *tag = reparse_point_values->tag;
794
795
0
  return( 1 );
796
0
}
797
798
/* Retrieves the Windows Overlay Filter (WOF) compression method
799
 * Returns 1 if successful, 0 if not available or -1 on error
800
 */
801
int libfsntfs_reparse_point_values_get_compression_method(
802
     libfsntfs_reparse_point_values_t *reparse_point_values,
803
     uint32_t *compression_method,
804
     libcerror_error_t **error )
805
0
{
806
0
  static char *function = "libfsntfs_reparse_point_values_get_compression_method";
807
808
0
  if( reparse_point_values == NULL )
809
0
  {
810
0
    libcerror_error_set(
811
0
     error,
812
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
813
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
814
0
     "%s: invalid reparse point values.",
815
0
     function );
816
817
0
    return( -1 );
818
0
  }
819
0
  if( compression_method == NULL )
820
0
  {
821
0
    libcerror_error_set(
822
0
     error,
823
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
824
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
825
0
     "%s: invalid compression method.",
826
0
     function );
827
828
0
    return( -1 );
829
0
  }
830
0
  if( reparse_point_values->tag == 0x80000017 )
831
0
  {
832
0
    *compression_method = reparse_point_values->compression_method;
833
834
0
    return( 1 );
835
0
  }
836
0
  return( 0 );
837
0
}
838
839
/* Retrieves the size of the UTF-8 encoded substitute name
840
 * The returned size includes the end of string character
841
 * Returns 1 if successful, 0 if not available or -1 on error
842
 */
843
int libfsntfs_reparse_point_values_get_utf8_substitute_name_size(
844
     libfsntfs_reparse_point_values_t *reparse_point_values,
845
     size_t *utf8_string_size,
846
     libcerror_error_t **error )
847
0
{
848
0
  static char *function = "libfsntfs_reparse_point_values_get_utf8_substitute_name_size";
849
850
0
  if( reparse_point_values == NULL )
851
0
  {
852
0
    libcerror_error_set(
853
0
     error,
854
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
855
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
856
0
     "%s: invalid reparse point values.",
857
0
     function );
858
859
0
    return( -1 );
860
0
  }
861
0
  if( reparse_point_values->substitute_name_size == 0 )
862
0
  {
863
0
    return( 0 );
864
0
  }
865
0
  if( libuna_utf8_string_size_from_utf16_stream(
866
0
       &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
867
0
       (size_t) reparse_point_values->substitute_name_size,
868
0
       LIBUNA_ENDIAN_LITTLE,
869
0
       utf8_string_size,
870
0
       error ) != 1 )
871
0
  {
872
0
    libcerror_error_set(
873
0
     error,
874
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
875
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
876
0
     "%s: unable to retrieve UTF-8 string size.",
877
0
     function );
878
879
0
    return( -1 );
880
0
  }
881
0
  return( 1 );
882
0
}
883
884
/* Retrieves the UTF-8 encoded substitute name
885
 * The size should include the end of string character
886
 * Returns 1 if successful, 0 if not available or -1 on error
887
 */
888
int libfsntfs_reparse_point_values_get_utf8_substitute_name(
889
     libfsntfs_reparse_point_values_t *reparse_point_values,
890
     uint8_t *utf8_string,
891
     size_t utf8_string_size,
892
     libcerror_error_t **error )
893
0
{
894
0
  static char *function = "libfsntfs_reparse_point_values_get_utf8_substitute_name";
895
896
0
  if( reparse_point_values == NULL )
897
0
  {
898
0
    libcerror_error_set(
899
0
     error,
900
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
901
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
902
0
     "%s: invalid reparse point values.",
903
0
     function );
904
905
0
    return( -1 );
906
0
  }
907
0
  if( reparse_point_values->substitute_name_size == 0 )
908
0
  {
909
0
    return( 0 );
910
0
  }
911
0
  if( libuna_utf8_string_copy_from_utf16_stream(
912
0
       utf8_string,
913
0
       utf8_string_size,
914
0
       &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
915
0
       (size_t) reparse_point_values->substitute_name_size,
916
0
       LIBUNA_ENDIAN_LITTLE,
917
0
       error ) != 1 )
918
0
  {
919
0
    libcerror_error_set(
920
0
     error,
921
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
922
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
923
0
     "%s: unable to retrieve UTF-8 string.",
924
0
     function );
925
926
0
    return( -1 );
927
0
  }
928
0
  return( 1 );
929
0
}
930
931
/* Retrieves the size of the UTF-16 encoded substitute name
932
 * The returned size includes the end of string character
933
 * Returns 1 if successful, 0 if not available or -1 on error
934
 */
935
int libfsntfs_reparse_point_values_get_utf16_substitute_name_size(
936
     libfsntfs_reparse_point_values_t *reparse_point_values,
937
     size_t *utf16_string_size,
938
     libcerror_error_t **error )
939
0
{
940
0
  static char *function = "libfsntfs_reparse_point_values_get_utf16_substitute_name_size";
941
942
0
  if( reparse_point_values == NULL )
943
0
  {
944
0
    libcerror_error_set(
945
0
     error,
946
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
947
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
948
0
     "%s: invalid reparse point values.",
949
0
     function );
950
951
0
    return( -1 );
952
0
  }
953
0
  if( reparse_point_values->substitute_name_size == 0 )
954
0
  {
955
0
    return( 0 );
956
0
  }
957
0
  if( libuna_utf16_string_size_from_utf16_stream(
958
0
       &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
959
0
       (size_t) reparse_point_values->substitute_name_size,
960
0
       LIBUNA_ENDIAN_LITTLE,
961
0
       utf16_string_size,
962
0
       error ) != 1 )
963
0
  {
964
0
    libcerror_error_set(
965
0
     error,
966
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
967
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
968
0
     "%s: unable to retrieve UTF-16 string size.",
969
0
     function );
970
971
0
    return( -1 );
972
0
  }
973
0
  return( 1 );
974
0
}
975
976
/* Retrieves the UTF-16 encoded substitute name
977
 * The size should include the end of string character
978
 * Returns 1 if successful, 0 if not available or -1 on error
979
 */
980
int libfsntfs_reparse_point_values_get_utf16_substitute_name(
981
     libfsntfs_reparse_point_values_t *reparse_point_values,
982
     uint16_t *utf16_string,
983
     size_t utf16_string_size,
984
     libcerror_error_t **error )
985
0
{
986
0
  static char *function = "libfsntfs_reparse_point_values_get_utf16_substitute_name";
987
988
0
  if( reparse_point_values == NULL )
989
0
  {
990
0
    libcerror_error_set(
991
0
     error,
992
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
993
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
994
0
     "%s: invalid reparse point values.",
995
0
     function );
996
997
0
    return( -1 );
998
0
  }
999
0
  if( reparse_point_values->substitute_name_size == 0 )
1000
0
  {
1001
0
    return( 0 );
1002
0
  }
1003
0
  if( libuna_utf16_string_copy_from_utf16_stream(
1004
0
       utf16_string,
1005
0
       utf16_string_size,
1006
0
       &( reparse_point_values->reparse_data[ reparse_point_values->substitute_name_offset ] ),
1007
0
       (size_t) reparse_point_values->substitute_name_size,
1008
0
       LIBUNA_ENDIAN_LITTLE,
1009
0
       error ) != 1 )
1010
0
  {
1011
0
    libcerror_error_set(
1012
0
     error,
1013
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1014
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1015
0
     "%s: unable to retrieve UTF-16 string.",
1016
0
     function );
1017
1018
0
    return( -1 );
1019
0
  }
1020
0
  return( 1 );
1021
0
}
1022
1023
/* Retrieves the size of the UTF-8 encoded print name
1024
 * The returned size includes the end of string character
1025
 * Returns 1 if successful, 0 if not available or -1 on error
1026
 */
1027
int libfsntfs_reparse_point_values_get_utf8_print_name_size(
1028
     libfsntfs_reparse_point_values_t *reparse_point_values,
1029
     size_t *utf8_string_size,
1030
     libcerror_error_t **error )
1031
0
{
1032
0
  static char *function = "libfsntfs_reparse_point_values_get_utf8_print_name_size";
1033
1034
0
  if( reparse_point_values == NULL )
1035
0
  {
1036
0
    libcerror_error_set(
1037
0
     error,
1038
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1039
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1040
0
     "%s: invalid reparse point values.",
1041
0
     function );
1042
1043
0
    return( -1 );
1044
0
  }
1045
0
  if( reparse_point_values->print_name_size == 0 )
1046
0
  {
1047
0
    return( 0 );
1048
0
  }
1049
0
  if( libuna_utf8_string_size_from_utf16_stream(
1050
0
       &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
1051
0
       (size_t) reparse_point_values->print_name_size,
1052
0
       LIBUNA_ENDIAN_LITTLE,
1053
0
       utf8_string_size,
1054
0
       error ) != 1 )
1055
0
  {
1056
0
    libcerror_error_set(
1057
0
     error,
1058
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1059
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1060
0
     "%s: unable to retrieve UTF-8 string size.",
1061
0
     function );
1062
1063
0
    return( -1 );
1064
0
  }
1065
0
  return( 1 );
1066
0
}
1067
1068
/* Retrieves the UTF-8 encoded print name
1069
 * The size should include the end of string character
1070
 * Returns 1 if successful, 0 if not available or -1 on error
1071
 */
1072
int libfsntfs_reparse_point_values_get_utf8_print_name(
1073
     libfsntfs_reparse_point_values_t *reparse_point_values,
1074
     uint8_t *utf8_string,
1075
     size_t utf8_string_size,
1076
     libcerror_error_t **error )
1077
0
{
1078
0
  static char *function = "libfsntfs_reparse_point_values_get_utf8_print_name";
1079
1080
0
  if( reparse_point_values == NULL )
1081
0
  {
1082
0
    libcerror_error_set(
1083
0
     error,
1084
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1085
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1086
0
     "%s: invalid reparse point values.",
1087
0
     function );
1088
1089
0
    return( -1 );
1090
0
  }
1091
0
  if( reparse_point_values->print_name_size == 0 )
1092
0
  {
1093
0
    return( 0 );
1094
0
  }
1095
0
  if( libuna_utf8_string_copy_from_utf16_stream(
1096
0
       utf8_string,
1097
0
       utf8_string_size,
1098
0
       &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
1099
0
       (size_t) reparse_point_values->print_name_size,
1100
0
       LIBUNA_ENDIAN_LITTLE,
1101
0
       error ) != 1 )
1102
0
  {
1103
0
    libcerror_error_set(
1104
0
     error,
1105
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1106
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1107
0
     "%s: unable to retrieve UTF-8 string.",
1108
0
     function );
1109
1110
0
    return( -1 );
1111
0
  }
1112
0
  return( 1 );
1113
0
}
1114
1115
/* Retrieves the size of the UTF-16 encoded print name
1116
 * The returned size includes the end of string character
1117
 * Returns 1 if successful, 0 if not available or -1 on error
1118
 */
1119
int libfsntfs_reparse_point_values_get_utf16_print_name_size(
1120
     libfsntfs_reparse_point_values_t *reparse_point_values,
1121
     size_t *utf16_string_size,
1122
     libcerror_error_t **error )
1123
0
{
1124
0
  static char *function = "libfsntfs_reparse_point_values_get_utf16_print_name_size";
1125
1126
0
  if( reparse_point_values == NULL )
1127
0
  {
1128
0
    libcerror_error_set(
1129
0
     error,
1130
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1131
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1132
0
     "%s: invalid reparse point values.",
1133
0
     function );
1134
1135
0
    return( -1 );
1136
0
  }
1137
0
  if( reparse_point_values->print_name_size == 0 )
1138
0
  {
1139
0
    return( 0 );
1140
0
  }
1141
0
  if( libuna_utf16_string_size_from_utf16_stream(
1142
0
       &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
1143
0
       (size_t) reparse_point_values->print_name_size,
1144
0
       LIBUNA_ENDIAN_LITTLE,
1145
0
       utf16_string_size,
1146
0
       error ) != 1 )
1147
0
  {
1148
0
    libcerror_error_set(
1149
0
     error,
1150
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1151
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1152
0
     "%s: unable to retrieve UTF-16 string size.",
1153
0
     function );
1154
1155
0
    return( -1 );
1156
0
  }
1157
0
  return( 1 );
1158
0
}
1159
1160
/* Retrieves the UTF-16 encoded print name
1161
 * The size should include the end of string character
1162
 * Returns 1 if successful, 0 if not available or -1 on error
1163
 */
1164
int libfsntfs_reparse_point_values_get_utf16_print_name(
1165
     libfsntfs_reparse_point_values_t *reparse_point_values,
1166
     uint16_t *utf16_string,
1167
     size_t utf16_string_size,
1168
     libcerror_error_t **error )
1169
0
{
1170
0
  static char *function = "libfsntfs_reparse_point_values_get_utf16_print_name";
1171
1172
0
  if( reparse_point_values == NULL )
1173
0
  {
1174
0
    libcerror_error_set(
1175
0
     error,
1176
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1177
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1178
0
     "%s: invalid reparse point values.",
1179
0
     function );
1180
1181
0
    return( -1 );
1182
0
  }
1183
0
  if( reparse_point_values->print_name_size == 0 )
1184
0
  {
1185
0
    return( 0 );
1186
0
  }
1187
0
  if( libuna_utf16_string_copy_from_utf16_stream(
1188
0
       utf16_string,
1189
0
       utf16_string_size,
1190
0
       &( reparse_point_values->reparse_data[ reparse_point_values->print_name_offset ] ),
1191
0
       (size_t) reparse_point_values->print_name_size,
1192
0
       LIBUNA_ENDIAN_LITTLE,
1193
0
       error ) != 1 )
1194
0
  {
1195
0
    libcerror_error_set(
1196
0
     error,
1197
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1198
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1199
0
     "%s: unable to retrieve UTF-16 string.",
1200
0
     function );
1201
1202
0
    return( -1 );
1203
0
  }
1204
0
  return( 1 );
1205
0
}
1206